UNPKG

5.05 kBTypeScriptView Raw
1// Copyright (c) Jupyter Development Team.
2// Distributed under the terms of the Modified BSD License.
3
4import { PathExt } from '@jupyterlab/coreutils';
5import { DocumentRegistry } from '@jupyterlab/docregistry';
6import { TextItem } from '@jupyterlab/statusbar';
7import { VDomModel, VDomRenderer } from '@jupyterlab/ui-components';
8import { Title, Widget } from '@lumino/widgets';
9import React from 'react';
10import { IDocumentManager } from './tokens';
11
12/**
13 * A namespace for PathStatusComponent statics.
14 */
15namespace PathStatusComponent {
16 /**
17 * The props for rendering a PathStatusComponent.
18 */
19 export interface IProps {
20 /**
21 * The full path for a document.
22 */
23 fullPath: string;
24
25 /**
26 * The shorter name for a document or activity.
27 */
28 name: string;
29 }
30}
31
32/**
33 * A pure component for rendering a file path (or activity name).
34 *
35 * @param props - the props for the component.
36 *
37 * @returns a tsx component for a file path.
38 */
39function PathStatusComponent(
40 props: PathStatusComponent.IProps
41): React.ReactElement<PathStatusComponent.IProps> {
42 return <TextItem source={props.name} title={props.fullPath} />;
43}
44
45/**
46 * A status bar item for the current file path (or activity name).
47 */
48export class PathStatus extends VDomRenderer<PathStatus.Model> {
49 /**
50 * Construct a new PathStatus status item.
51 */
52 constructor(opts: PathStatus.IOptions) {
53 super(new PathStatus.Model(opts.docManager));
54 this.node.title = this.model.path;
55 }
56
57 /**
58 * Render the status item.
59 */
60 render(): JSX.Element {
61 return (
62 <PathStatusComponent
63 fullPath={this.model!.path}
64 name={this.model!.name!}
65 />
66 );
67 }
68}
69
70/**
71 * A namespace for PathStatus statics.
72 */
73export namespace PathStatus {
74 /**
75 * A VDomModel for rendering the PathStatus status item.
76 */
77 export class Model extends VDomModel {
78 /**
79 * Construct a new model.
80 *
81 * @param docManager the application document manager. Used to check
82 * whether the current widget is a document.
83 */
84 constructor(docManager: IDocumentManager) {
85 super();
86 this._docManager = docManager;
87 }
88
89 /**
90 * The current path for the application.
91 */
92 get path(): string {
93 return this._path;
94 }
95
96 /**
97 * The name of the current activity.
98 */
99 get name(): string {
100 return this._name;
101 }
102
103 /**
104 * The current widget for the application.
105 */
106 get widget(): Widget | null {
107 return this._widget;
108 }
109 set widget(widget: Widget | null) {
110 const oldWidget = this._widget;
111 if (oldWidget !== null) {
112 const oldContext = this._docManager.contextForWidget(oldWidget);
113 if (oldContext) {
114 oldContext.pathChanged.disconnect(this._onPathChange);
115 } else {
116 oldWidget.title.changed.disconnect(this._onTitleChange);
117 }
118 }
119
120 const oldState = this._getAllState();
121 this._widget = widget;
122 if (this._widget === null) {
123 this._path = '';
124 this._name = '';
125 } else {
126 const widgetContext = this._docManager.contextForWidget(this._widget);
127 if (widgetContext) {
128 this._path = widgetContext.path;
129 this._name = PathExt.basename(widgetContext.path);
130
131 widgetContext.pathChanged.connect(this._onPathChange);
132 } else {
133 this._path = '';
134 this._name = this._widget.title.label;
135
136 this._widget.title.changed.connect(this._onTitleChange);
137 }
138 }
139
140 this._triggerChange(oldState, this._getAllState());
141 }
142
143 /**
144 * React to a title change for the current widget.
145 */
146 private _onTitleChange = (title: Title<Widget>) => {
147 const oldState = this._getAllState();
148 this._name = title.label;
149 this._triggerChange(oldState, this._getAllState());
150 };
151
152 /**
153 * React to a path change for the current document.
154 */
155 private _onPathChange = (
156 _documentModel: DocumentRegistry.IContext<DocumentRegistry.IModel>,
157 newPath: string
158 ) => {
159 const oldState = this._getAllState();
160 this._path = newPath;
161 this._name = PathExt.basename(newPath);
162
163 this._triggerChange(oldState, this._getAllState());
164 };
165
166 /**
167 * Get the current state of the model.
168 */
169 private _getAllState(): [string, string] {
170 return [this._path, this._name];
171 }
172
173 /**
174 * Trigger a state change to rerender.
175 */
176 private _triggerChange(
177 oldState: [string, string],
178 newState: [string, string]
179 ) {
180 if (oldState[0] !== newState[0] || oldState[1] !== newState[1]) {
181 this.stateChanged.emit(void 0);
182 }
183 }
184
185 private _path: string = '';
186 private _name: string = '';
187 private _widget: Widget | null = null;
188 private _docManager: IDocumentManager;
189 }
190
191 /**
192 * Options for creating the PathStatus widget.
193 */
194 export interface IOptions {
195 /**
196 * The application document manager.
197 */
198 docManager: IDocumentManager;
199 }
200}