1 |
|
2 |
|
3 | import { DocumentWidget } from '@jupyterlab/docregistry';
|
4 | import { nullTranslator } from '@jupyterlab/translation';
|
5 | import { classes, DockPanelSvg, LabIcon, TabPanelSvg } from '@jupyterlab/ui-components';
|
6 | import { ArrayExt, find, iter, toArray } from '@lumino/algorithm';
|
7 | import { PromiseDelegate, Token } from '@lumino/coreutils';
|
8 | import { MessageLoop } from '@lumino/messaging';
|
9 | import { Debouncer } from '@lumino/polling';
|
10 | import { Signal } from '@lumino/signaling';
|
11 | import { BoxLayout, BoxPanel, FocusTracker, Panel, SplitPanel, StackedPanel, TabBar, Widget } from '@lumino/widgets';
|
12 |
|
13 |
|
14 |
|
15 | const APPLICATION_SHELL_CLASS = 'jp-LabShell';
|
16 |
|
17 |
|
18 |
|
19 | const SIDEBAR_CLASS = 'jp-SideBar';
|
20 |
|
21 |
|
22 |
|
23 | const CURRENT_CLASS = 'jp-mod-current';
|
24 |
|
25 |
|
26 |
|
27 | const ACTIVE_CLASS = 'jp-mod-active';
|
28 |
|
29 |
|
30 |
|
31 | const DEFAULT_RANK = 900;
|
32 | const ACTIVITY_CLASS = 'jp-Activity';
|
33 |
|
34 |
|
35 |
|
36 | export const ILabShell = new Token('@jupyterlab/application:ILabShell');
|
37 |
|
38 |
|
39 |
|
40 | export class LabShell extends Widget {
|
41 | |
42 |
|
43 |
|
44 | constructor(options) {
|
45 | super();
|
46 | |
47 |
|
48 |
|
49 | this._dockChildHook = (handler, msg) => {
|
50 | switch (msg.type) {
|
51 | case 'child-added':
|
52 | msg.child.addClass(ACTIVITY_CLASS);
|
53 | this._tracker.add(msg.child);
|
54 | break;
|
55 | case 'child-removed':
|
56 | msg.child.removeClass(ACTIVITY_CLASS);
|
57 | this._tracker.remove(msg.child);
|
58 | break;
|
59 | default:
|
60 | break;
|
61 | }
|
62 | return true;
|
63 | };
|
64 | this._activeChanged = new Signal(this);
|
65 | this._cachedLayout = null;
|
66 | this._currentChanged = new Signal(this);
|
67 | this._currentPath = '';
|
68 | this._currentPathChanged = new Signal(this);
|
69 | this._modeChanged = new Signal(this);
|
70 | this._isRestored = false;
|
71 | this._layoutModified = new Signal(this);
|
72 | this._layoutDebouncer = new Debouncer(() => {
|
73 | this._layoutModified.emit(undefined);
|
74 | }, 0);
|
75 | this._restored = new PromiseDelegate();
|
76 | this._tracker = new FocusTracker();
|
77 | this._mainOptionsCache = new Map();
|
78 | this._sideOptionsCache = new Map();
|
79 | this.addClass(APPLICATION_SHELL_CLASS);
|
80 | this.id = 'main';
|
81 | const trans = ((options && options.translator) || nullTranslator).load('jupyterlab');
|
82 | const headerPanel = (this._headerPanel = new BoxPanel());
|
83 | const menuHandler = (this._menuHandler = new Private.PanelHandler());
|
84 | menuHandler.panel.node.setAttribute('role', 'navigation');
|
85 | menuHandler.panel.node.setAttribute('aria-label', trans.__('main'));
|
86 | const topHandler = (this._topHandler = new Private.PanelHandler());
|
87 | topHandler.panel.node.setAttribute('role', 'banner');
|
88 | const bottomPanel = (this._bottomPanel = new BoxPanel());
|
89 | bottomPanel.node.setAttribute('role', 'contentinfo');
|
90 | const hboxPanel = new BoxPanel();
|
91 | const vsplitPanel = (this._vsplitPanel = new Private.RestorableSplitPanel());
|
92 | const dockPanel = (this._dockPanel = new DockPanelSvg({
|
93 | hiddenMode: Widget.HiddenMode.Scale,
|
94 | translator: options === null || options === void 0 ? void 0 : options.translator
|
95 | }));
|
96 | MessageLoop.installMessageHook(dockPanel, this._dockChildHook);
|
97 | const hsplitPanel = (this._hsplitPanel = new Private.RestorableSplitPanel());
|
98 | const downPanel = (this._downPanel = new TabPanelSvg({
|
99 | tabsMovable: true
|
100 | }));
|
101 | const leftHandler = (this._leftHandler = new Private.SideBarHandler());
|
102 | const rightHandler = (this._rightHandler = new Private.SideBarHandler());
|
103 | const rootLayout = new BoxLayout();
|
104 | headerPanel.id = 'jp-header-panel';
|
105 | menuHandler.panel.id = 'jp-menu-panel';
|
106 | topHandler.panel.id = 'jp-top-panel';
|
107 | bottomPanel.id = 'jp-bottom-panel';
|
108 | hboxPanel.id = 'jp-main-content-panel';
|
109 | vsplitPanel.id = 'jp-main-vsplit-panel';
|
110 | dockPanel.id = 'jp-main-dock-panel';
|
111 | hsplitPanel.id = 'jp-main-split-panel';
|
112 | downPanel.id = 'jp-down-stack';
|
113 | leftHandler.sideBar.addClass(SIDEBAR_CLASS);
|
114 | leftHandler.sideBar.addClass('jp-mod-left');
|
115 | leftHandler.sideBar.node.setAttribute('aria-label', trans.__('main sidebar'));
|
116 | leftHandler.sideBar.contentNode.setAttribute('aria-label', trans.__('main sidebar'));
|
117 | leftHandler.sideBar.node.setAttribute('role', 'complementary');
|
118 | leftHandler.stackedPanel.id = 'jp-left-stack';
|
119 | rightHandler.sideBar.addClass(SIDEBAR_CLASS);
|
120 | rightHandler.sideBar.addClass('jp-mod-right');
|
121 | rightHandler.sideBar.node.setAttribute('aria-label', trans.__('alternate sidebar'));
|
122 | rightHandler.sideBar.contentNode.setAttribute('aria-label', trans.__('alternate sidebar'));
|
123 | rightHandler.sideBar.node.setAttribute('role', 'complementary');
|
124 | rightHandler.stackedPanel.id = 'jp-right-stack';
|
125 | dockPanel.node.setAttribute('role', 'main');
|
126 | hboxPanel.spacing = 0;
|
127 | vsplitPanel.spacing = 1;
|
128 | dockPanel.spacing = 5;
|
129 | hsplitPanel.spacing = 1;
|
130 | headerPanel.direction = 'top-to-bottom';
|
131 | vsplitPanel.orientation = 'vertical';
|
132 | hboxPanel.direction = 'left-to-right';
|
133 | hsplitPanel.orientation = 'horizontal';
|
134 | bottomPanel.direction = 'bottom-to-top';
|
135 | SplitPanel.setStretch(leftHandler.stackedPanel, 0);
|
136 | SplitPanel.setStretch(downPanel, 0);
|
137 | SplitPanel.setStretch(dockPanel, 1);
|
138 | SplitPanel.setStretch(rightHandler.stackedPanel, 0);
|
139 | BoxPanel.setStretch(leftHandler.sideBar, 0);
|
140 | BoxPanel.setStretch(hsplitPanel, 1);
|
141 | BoxPanel.setStretch(rightHandler.sideBar, 0);
|
142 | SplitPanel.setStretch(vsplitPanel, 1);
|
143 | hsplitPanel.addWidget(leftHandler.stackedPanel);
|
144 | hsplitPanel.addWidget(dockPanel);
|
145 | hsplitPanel.addWidget(rightHandler.stackedPanel);
|
146 | vsplitPanel.addWidget(hsplitPanel);
|
147 | vsplitPanel.addWidget(downPanel);
|
148 | hboxPanel.addWidget(leftHandler.sideBar);
|
149 | hboxPanel.addWidget(vsplitPanel);
|
150 | hboxPanel.addWidget(rightHandler.sideBar);
|
151 | rootLayout.direction = 'top-to-bottom';
|
152 | rootLayout.spacing = 0;
|
153 |
|
154 |
|
155 |
|
156 | vsplitPanel.setRelativeSizes([3, 1]);
|
157 | hsplitPanel.setRelativeSizes([1, 2.5, 1]);
|
158 | BoxLayout.setStretch(headerPanel, 0);
|
159 | BoxLayout.setStretch(menuHandler.panel, 0);
|
160 | BoxLayout.setStretch(topHandler.panel, 0);
|
161 | BoxLayout.setStretch(hboxPanel, 1);
|
162 | BoxLayout.setStretch(bottomPanel, 0);
|
163 | rootLayout.addWidget(headerPanel);
|
164 | rootLayout.addWidget(topHandler.panel);
|
165 | rootLayout.addWidget(hboxPanel);
|
166 | rootLayout.addWidget(bottomPanel);
|
167 |
|
168 | this._headerPanel.hide();
|
169 | this._bottomPanel.hide();
|
170 | this._downPanel.hide();
|
171 | this.layout = rootLayout;
|
172 |
|
173 | this._tracker.currentChanged.connect(this._onCurrentChanged, this);
|
174 | this._tracker.activeChanged.connect(this._onActiveChanged, this);
|
175 |
|
176 | this._dockPanel.layoutModified.connect(this._onLayoutModified, this);
|
177 |
|
178 | this._vsplitPanel.updated.connect(this._onLayoutModified, this);
|
179 |
|
180 | this._downPanel.currentChanged.connect(this._onLayoutModified, this);
|
181 | this._downPanel.tabBar.tabMoved.connect(this._onTabPanelChanged, this);
|
182 | this._downPanel.stackedPanel.widgetRemoved.connect(this._onTabPanelChanged, this);
|
183 |
|
184 | this._leftHandler.sideBar.currentChanged.connect(this._onLayoutModified, this);
|
185 | this._rightHandler.sideBar.currentChanged.connect(this._onLayoutModified, this);
|
186 |
|
187 | this._hsplitPanel.updated.connect(this._onLayoutModified, this);
|
188 |
|
189 | const titleHandler = (this._titleHandler = new Private.TitleHandler(this));
|
190 | this.add(titleHandler, 'top', { rank: 100 });
|
191 | if (this._dockPanel.mode === 'multiple-document') {
|
192 | this._topHandler.addWidget(this._menuHandler.panel, 100);
|
193 | titleHandler.hide();
|
194 | }
|
195 | else {
|
196 | rootLayout.insertWidget(2, this._menuHandler.panel);
|
197 | }
|
198 |
|
199 | const skipLinkWidget = (this._skipLinkWidget = new Private.SkipLinkWidget(this));
|
200 | this.add(skipLinkWidget, 'top', { rank: 0 });
|
201 | this._skipLinkWidget.show();
|
202 |
|
203 |
|
204 | this.currentChanged.connect((sender, args) => {
|
205 | let newValue = args.newValue;
|
206 | let oldValue = args.oldValue;
|
207 |
|
208 | if (oldValue) {
|
209 | oldValue.title.changed.disconnect(this._updateTitlePanelTitle, this);
|
210 | }
|
211 |
|
212 | if (newValue) {
|
213 | newValue.title.changed.connect(this._updateTitlePanelTitle, this);
|
214 | this._updateTitlePanelTitle();
|
215 | }
|
216 | if (newValue && newValue instanceof DocumentWidget) {
|
217 | newValue.context.pathChanged.connect(this._updateCurrentPath, this);
|
218 | }
|
219 | this._updateCurrentPath();
|
220 | });
|
221 | }
|
222 | |
223 |
|
224 |
|
225 | get activeChanged() {
|
226 | return this._activeChanged;
|
227 | }
|
228 | |
229 |
|
230 |
|
231 | get activeWidget() {
|
232 | return this._tracker.activeWidget;
|
233 | }
|
234 | |
235 |
|
236 |
|
237 | get currentChanged() {
|
238 | return this._currentChanged;
|
239 | }
|
240 | |
241 |
|
242 |
|
243 | get modeChanged() {
|
244 | return this._modeChanged;
|
245 | }
|
246 | |
247 |
|
248 |
|
249 |
|
250 |
|
251 | get currentPathChanged() {
|
252 | return this._currentPathChanged;
|
253 | }
|
254 | |
255 |
|
256 |
|
257 | get currentWidget() {
|
258 | return this._tracker.currentWidget;
|
259 | }
|
260 | |
261 |
|
262 |
|
263 | get layoutModified() {
|
264 | return this._layoutModified;
|
265 | }
|
266 | |
267 |
|
268 |
|
269 | get leftCollapsed() {
|
270 | return !this._leftHandler.sideBar.currentTitle;
|
271 | }
|
272 | |
273 |
|
274 |
|
275 | get rightCollapsed() {
|
276 | return !this._rightHandler.sideBar.currentTitle;
|
277 | }
|
278 | |
279 |
|
280 |
|
281 |
|
282 | get presentationMode() {
|
283 | return this.hasClass('jp-mod-presentationMode');
|
284 | }
|
285 | |
286 |
|
287 |
|
288 |
|
289 | set presentationMode(value) {
|
290 | this.toggleClass('jp-mod-presentationMode', value);
|
291 | }
|
292 | |
293 |
|
294 |
|
295 | get mode() {
|
296 | return this._dockPanel.mode;
|
297 | }
|
298 | set mode(mode) {
|
299 | const dock = this._dockPanel;
|
300 | if (mode === dock.mode) {
|
301 | return;
|
302 | }
|
303 | const applicationCurrentWidget = this.currentWidget;
|
304 | if (mode === 'single-document') {
|
305 |
|
306 | this._cachedLayout = dock.saveLayout();
|
307 | dock.mode = mode;
|
308 |
|
309 |
|
310 | if (this.currentWidget) {
|
311 | dock.activateWidget(this.currentWidget);
|
312 | }
|
313 |
|
314 | this.layout.insertWidget(2, this._menuHandler.panel);
|
315 | this._titleHandler.show();
|
316 | this._updateTitlePanelTitle();
|
317 | }
|
318 | else {
|
319 |
|
320 |
|
321 | const widgets = toArray(dock.widgets());
|
322 | dock.mode = mode;
|
323 |
|
324 | if (this._cachedLayout) {
|
325 |
|
326 | Private.normalizeAreaConfig(dock, this._cachedLayout.main);
|
327 | dock.restoreLayout(this._cachedLayout);
|
328 | this._cachedLayout = null;
|
329 | }
|
330 |
|
331 |
|
332 |
|
333 |
|
334 |
|
335 | widgets.forEach(widget => {
|
336 | if (!widget.parent) {
|
337 | this._addToMainArea(widget, Object.assign(Object.assign({}, this._mainOptionsCache.get(widget)), { activate: false }));
|
338 | }
|
339 | });
|
340 | this._mainOptionsCache.clear();
|
341 |
|
342 |
|
343 | if (applicationCurrentWidget) {
|
344 | dock.activateWidget(applicationCurrentWidget);
|
345 | }
|
346 |
|
347 | this.add(this._menuHandler.panel, 'top', { rank: 100 });
|
348 |
|
349 | this._titleHandler.hide();
|
350 | }
|
351 |
|
352 | this.node.dataset.shellMode = mode;
|
353 | this._downPanel.fit();
|
354 |
|
355 | this._modeChanged.emit(mode);
|
356 | }
|
357 | |
358 |
|
359 |
|
360 |
|
361 | get restored() {
|
362 | return this._restored.promise;
|
363 | }
|
364 | |
365 |
|
366 |
|
367 | activateById(id) {
|
368 | if (this._leftHandler.has(id)) {
|
369 | this._leftHandler.activate(id);
|
370 | return;
|
371 | }
|
372 | if (this._rightHandler.has(id)) {
|
373 | this._rightHandler.activate(id);
|
374 | return;
|
375 | }
|
376 | const tabIndex = this._downPanel.tabBar.titles.findIndex(title => title.owner.id === id);
|
377 | if (tabIndex >= 0) {
|
378 | this._downPanel.currentIndex = tabIndex;
|
379 | return;
|
380 | }
|
381 | const dock = this._dockPanel;
|
382 | const widget = find(dock.widgets(), value => value.id === id);
|
383 | if (widget) {
|
384 | dock.activateWidget(widget);
|
385 | }
|
386 | }
|
387 | |
388 |
|
389 |
|
390 | activateNextTab() {
|
391 | const current = this._currentTabBar();
|
392 | if (!current) {
|
393 | return;
|
394 | }
|
395 | const ci = current.currentIndex;
|
396 | if (ci === -1) {
|
397 | return;
|
398 | }
|
399 | if (ci < current.titles.length - 1) {
|
400 | current.currentIndex += 1;
|
401 | if (current.currentTitle) {
|
402 | current.currentTitle.owner.activate();
|
403 | }
|
404 | return;
|
405 | }
|
406 | if (ci === current.titles.length - 1) {
|
407 | const nextBar = this._adjacentBar('next');
|
408 | if (nextBar) {
|
409 | nextBar.currentIndex = 0;
|
410 | if (nextBar.currentTitle) {
|
411 | nextBar.currentTitle.owner.activate();
|
412 | }
|
413 | }
|
414 | }
|
415 | }
|
416 | |
417 |
|
418 |
|
419 | get addButtonEnabled() {
|
420 | return this._dockPanel.addButtonEnabled;
|
421 | }
|
422 | set addButtonEnabled(value) {
|
423 | this._dockPanel.addButtonEnabled = value;
|
424 | }
|
425 | |
426 |
|
427 |
|
428 | get addRequested() {
|
429 | return this._dockPanel.addRequested;
|
430 | }
|
431 | |
432 |
|
433 |
|
434 | activatePreviousTab() {
|
435 | const current = this._currentTabBar();
|
436 | if (!current) {
|
437 | return;
|
438 | }
|
439 | const ci = current.currentIndex;
|
440 | if (ci === -1) {
|
441 | return;
|
442 | }
|
443 | if (ci > 0) {
|
444 | current.currentIndex -= 1;
|
445 | if (current.currentTitle) {
|
446 | current.currentTitle.owner.activate();
|
447 | }
|
448 | return;
|
449 | }
|
450 | if (ci === 0) {
|
451 | const prevBar = this._adjacentBar('previous');
|
452 | if (prevBar) {
|
453 | const len = prevBar.titles.length;
|
454 | prevBar.currentIndex = len - 1;
|
455 | if (prevBar.currentTitle) {
|
456 | prevBar.currentTitle.owner.activate();
|
457 | }
|
458 | }
|
459 | }
|
460 | }
|
461 | |
462 |
|
463 |
|
464 | activateNextTabBar() {
|
465 | const nextBar = this._adjacentBar('next');
|
466 | if (nextBar) {
|
467 | if (nextBar.currentTitle) {
|
468 | nextBar.currentTitle.owner.activate();
|
469 | }
|
470 | }
|
471 | }
|
472 | |
473 |
|
474 |
|
475 | activatePreviousTabBar() {
|
476 | const nextBar = this._adjacentBar('previous');
|
477 | if (nextBar) {
|
478 | if (nextBar.currentTitle) {
|
479 | nextBar.currentTitle.owner.activate();
|
480 | }
|
481 | }
|
482 | }
|
483 | add(widget, area = 'main', options) {
|
484 | switch (area || 'main') {
|
485 | case 'bottom':
|
486 | return this._addToBottomArea(widget, options);
|
487 | case 'down':
|
488 | return this._addToDownArea(widget, options);
|
489 | case 'header':
|
490 | return this._addToHeaderArea(widget, options);
|
491 | case 'left':
|
492 | return this._addToLeftArea(widget, options);
|
493 | case 'main':
|
494 | return this._addToMainArea(widget, options);
|
495 | case 'menu':
|
496 | return this._addToMenuArea(widget, options);
|
497 | case 'right':
|
498 | return this._addToRightArea(widget, options);
|
499 | case 'top':
|
500 | return this._addToTopArea(widget, options);
|
501 | default:
|
502 | throw new Error(`Invalid area: ${area}`);
|
503 | }
|
504 | }
|
505 | |
506 |
|
507 |
|
508 | collapseLeft() {
|
509 | this._leftHandler.collapse();
|
510 | this._onLayoutModified();
|
511 | }
|
512 | |
513 |
|
514 |
|
515 | collapseRight() {
|
516 | this._rightHandler.collapse();
|
517 | this._onLayoutModified();
|
518 | }
|
519 | |
520 |
|
521 |
|
522 | dispose() {
|
523 | if (this.isDisposed) {
|
524 | return;
|
525 | }
|
526 | this._layoutDebouncer.dispose();
|
527 | super.dispose();
|
528 | }
|
529 | |
530 |
|
531 |
|
532 |
|
533 |
|
534 |
|
535 |
|
536 | expandLeft() {
|
537 | this._leftHandler.expand();
|
538 | this._onLayoutModified();
|
539 | }
|
540 | |
541 |
|
542 |
|
543 |
|
544 |
|
545 |
|
546 |
|
547 | expandRight() {
|
548 | this._rightHandler.expand();
|
549 | this._onLayoutModified();
|
550 | }
|
551 | |
552 |
|
553 |
|
554 | closeAll() {
|
555 |
|
556 |
|
557 |
|
558 | toArray(this._dockPanel.widgets()).forEach(widget => widget.close());
|
559 | this._downPanel.stackedPanel.widgets.forEach(widget => widget.close());
|
560 | }
|
561 | |
562 |
|
563 |
|
564 | isEmpty(area) {
|
565 | switch (area) {
|
566 | case 'bottom':
|
567 | return this._bottomPanel.widgets.length === 0;
|
568 | case 'down':
|
569 | return this._downPanel.stackedPanel.widgets.length === 0;
|
570 | case 'header':
|
571 | return this._headerPanel.widgets.length === 0;
|
572 | case 'left':
|
573 | return this._leftHandler.stackedPanel.widgets.length === 0;
|
574 | case 'main':
|
575 | return this._dockPanel.isEmpty;
|
576 | case 'menu':
|
577 | return this._menuHandler.panel.widgets.length === 0;
|
578 | case 'right':
|
579 | return this._rightHandler.stackedPanel.widgets.length === 0;
|
580 | case 'top':
|
581 | return this._topHandler.panel.widgets.length === 0;
|
582 | default:
|
583 | return true;
|
584 | }
|
585 | }
|
586 | |
587 |
|
588 |
|
589 | restoreLayout(mode, layout) {
|
590 | var _a, _b;
|
591 | const { mainArea, downArea, leftArea, rightArea, relativeSizes } = layout;
|
592 |
|
593 | if (mainArea) {
|
594 | const { currentWidget, dock } = mainArea;
|
595 | if (dock) {
|
596 | this._dockPanel.restoreLayout(dock);
|
597 | }
|
598 | if (mode) {
|
599 | this.mode = mode;
|
600 | }
|
601 | if (currentWidget) {
|
602 | this.activateById(currentWidget.id);
|
603 | }
|
604 | }
|
605 | else {
|
606 |
|
607 | if (mode) {
|
608 | this.mode = mode;
|
609 | }
|
610 | }
|
611 |
|
612 | if (downArea) {
|
613 | const { currentWidget, widgets, size } = downArea;
|
614 | const widgetIds = (_a = widgets === null || widgets === void 0 ? void 0 : widgets.map(widget => widget.id)) !== null && _a !== void 0 ? _a : [];
|
615 |
|
616 | this._downPanel.tabBar.titles
|
617 | .filter(title => !widgetIds.includes(title.owner.id))
|
618 | .map(title => title.owner.close());
|
619 |
|
620 | const titleIds = this._downPanel.tabBar.titles.map(title => title.owner.id);
|
621 | widgets === null || widgets === void 0 ? void 0 : widgets.filter(widget => !titleIds.includes(widget.id)).map(widget => this._downPanel.addWidget(widget));
|
622 |
|
623 | while (!ArrayExt.shallowEqual(widgetIds, this._downPanel.tabBar.titles.map(title => title.owner.id))) {
|
624 | this._downPanel.tabBar.titles.forEach((title, index) => {
|
625 | const position = widgetIds.findIndex(id => title.owner.id == id);
|
626 | if (position >= 0 && position != index) {
|
627 | this._downPanel.tabBar.insertTab(position, title);
|
628 | }
|
629 | });
|
630 | }
|
631 | if (currentWidget) {
|
632 | const index = this._downPanel.stackedPanel.widgets.findIndex(widget => widget.id === currentWidget.id);
|
633 | if (index) {
|
634 | this._downPanel.currentIndex = index;
|
635 | (_b = this._downPanel.currentWidget) === null || _b === void 0 ? void 0 : _b.activate();
|
636 | }
|
637 | }
|
638 | if (size && size > 0.0) {
|
639 | this._vsplitPanel.setRelativeSizes([1.0 - size, size]);
|
640 | }
|
641 | else {
|
642 |
|
643 | this._downPanel.stackedPanel.widgets.forEach(widget => widget.close());
|
644 | this._downPanel.hide();
|
645 | }
|
646 | }
|
647 |
|
648 | if (leftArea) {
|
649 | this._leftHandler.rehydrate(leftArea);
|
650 | }
|
651 | else {
|
652 | if (mode === 'single-document') {
|
653 | this.collapseLeft();
|
654 | }
|
655 | }
|
656 |
|
657 | if (rightArea) {
|
658 | this._rightHandler.rehydrate(rightArea);
|
659 | }
|
660 | else {
|
661 | if (mode === 'single-document') {
|
662 | this.collapseRight();
|
663 | }
|
664 | }
|
665 |
|
666 | if (relativeSizes) {
|
667 | this._hsplitPanel.setRelativeSizes(relativeSizes);
|
668 | }
|
669 | if (!this._isRestored) {
|
670 |
|
671 |
|
672 |
|
673 | MessageLoop.flush();
|
674 | this._restored.resolve(layout);
|
675 | }
|
676 | }
|
677 | |
678 |
|
679 |
|
680 | saveLayout() {
|
681 |
|
682 |
|
683 | const layout = {
|
684 | mainArea: {
|
685 | currentWidget: this._tracker.currentWidget,
|
686 | dock: this.mode === 'single-document'
|
687 | ? this._cachedLayout || this._dockPanel.saveLayout()
|
688 | : this._dockPanel.saveLayout()
|
689 | },
|
690 | downArea: {
|
691 | currentWidget: this._downPanel.currentWidget,
|
692 | widgets: toArray(this._downPanel.stackedPanel.widgets),
|
693 | size: this._vsplitPanel.relativeSizes()[1]
|
694 | },
|
695 | leftArea: this._leftHandler.dehydrate(),
|
696 | rightArea: this._rightHandler.dehydrate(),
|
697 | relativeSizes: this._hsplitPanel.relativeSizes()
|
698 | };
|
699 | return layout;
|
700 | }
|
701 | |
702 |
|
703 |
|
704 |
|
705 |
|
706 | updateConfig(config) {
|
707 | if (config.hiddenMode) {
|
708 | this._dockPanel.hiddenMode =
|
709 | config.hiddenMode === 'display'
|
710 | ? Widget.HiddenMode.Display
|
711 | : Widget.HiddenMode.Scale;
|
712 | }
|
713 | }
|
714 | |
715 |
|
716 |
|
717 | widgets(area) {
|
718 | switch (area !== null && area !== void 0 ? area : 'main') {
|
719 | case 'main':
|
720 | return this._dockPanel.widgets();
|
721 | case 'left':
|
722 | return iter(this._leftHandler.sideBar.titles.map(t => t.owner));
|
723 | case 'right':
|
724 | return iter(this._rightHandler.sideBar.titles.map(t => t.owner));
|
725 | case 'header':
|
726 | return this._headerPanel.children();
|
727 | case 'top':
|
728 | return this._topHandler.panel.children();
|
729 | case 'menu':
|
730 | return this._menuHandler.panel.children();
|
731 | case 'bottom':
|
732 | return this._bottomPanel.children();
|
733 | default:
|
734 | throw new Error(`Invalid area: ${area}`);
|
735 | }
|
736 | }
|
737 | |
738 |
|
739 |
|
740 | onAfterAttach(msg) {
|
741 | this.node.dataset.shellMode = this.mode;
|
742 | }
|
743 | |
744 |
|
745 |
|
746 | _updateTitlePanelTitle() {
|
747 | let current = this.currentWidget;
|
748 | const inputElement = this._titleHandler.inputElement;
|
749 | inputElement.value = current ? current.title.label : '';
|
750 | inputElement.title = current ? current.title.caption : '';
|
751 | }
|
752 | |
753 |
|
754 |
|
755 | _updateCurrentPath() {
|
756 | let current = this.currentWidget;
|
757 | let newValue = '';
|
758 | if (current && current instanceof DocumentWidget) {
|
759 | newValue = current.context.path;
|
760 | }
|
761 | this._currentPathChanged.emit({
|
762 | newValue: newValue,
|
763 | oldValue: this._currentPath
|
764 | });
|
765 | this._currentPath = newValue;
|
766 | }
|
767 | |
768 |
|
769 |
|
770 |
|
771 |
|
772 |
|
773 | _addToLeftArea(widget, options) {
|
774 | if (!widget.id) {
|
775 | console.error('Widgets added to app shell must have unique id property.');
|
776 | return;
|
777 | }
|
778 | options = options || this._sideOptionsCache.get(widget) || {};
|
779 | this._sideOptionsCache.set(widget, options);
|
780 | const rank = 'rank' in options ? options.rank : DEFAULT_RANK;
|
781 | this._leftHandler.addWidget(widget, rank);
|
782 | this._onLayoutModified();
|
783 | }
|
784 | |
785 |
|
786 |
|
787 |
|
788 |
|
789 |
|
790 |
|
791 |
|
792 |
|
793 |
|
794 |
|
795 | _addToMainArea(widget, options) {
|
796 | if (!widget.id) {
|
797 | console.error('Widgets added to app shell must have unique id property.');
|
798 | return;
|
799 | }
|
800 | options = options || {};
|
801 | const dock = this._dockPanel;
|
802 | const mode = options.mode || 'tab-after';
|
803 | let ref = this.currentWidget;
|
804 | if (options.ref) {
|
805 | ref = find(dock.widgets(), value => value.id === options.ref) || null;
|
806 | }
|
807 | const { title } = widget;
|
808 |
|
809 |
|
810 | title.dataset = Object.assign(Object.assign({}, title.dataset), { id: widget.id });
|
811 | if (title.icon instanceof LabIcon) {
|
812 |
|
813 | title.icon = title.icon.bindprops({
|
814 | stylesheet: 'mainAreaTab'
|
815 | });
|
816 | }
|
817 | else if (typeof title.icon === 'string' || !title.icon) {
|
818 |
|
819 | title.iconClass = classes(title.iconClass, 'jp-Icon');
|
820 | }
|
821 | dock.addWidget(widget, { mode, ref });
|
822 |
|
823 |
|
824 |
|
825 |
|
826 | if (dock.mode === 'single-document') {
|
827 | this._mainOptionsCache.set(widget, options);
|
828 | }
|
829 | if (options.activate !== false) {
|
830 | dock.activateWidget(widget);
|
831 | }
|
832 | }
|
833 | |
834 |
|
835 |
|
836 |
|
837 |
|
838 |
|
839 | _addToRightArea(widget, options) {
|
840 | if (!widget.id) {
|
841 | console.error('Widgets added to app shell must have unique id property.');
|
842 | return;
|
843 | }
|
844 | options = options || this._sideOptionsCache.get(widget) || {};
|
845 | const rank = 'rank' in options ? options.rank : DEFAULT_RANK;
|
846 | this._sideOptionsCache.set(widget, options);
|
847 | this._rightHandler.addWidget(widget, rank);
|
848 | this._onLayoutModified();
|
849 | }
|
850 | |
851 |
|
852 |
|
853 |
|
854 |
|
855 |
|
856 | _addToTopArea(widget, options) {
|
857 | var _a;
|
858 | if (!widget.id) {
|
859 | console.error('Widgets added to app shell must have unique id property.');
|
860 | return;
|
861 | }
|
862 | options = options || {};
|
863 | const rank = (_a = options.rank) !== null && _a !== void 0 ? _a : DEFAULT_RANK;
|
864 | this._topHandler.addWidget(widget, rank);
|
865 | this._onLayoutModified();
|
866 | if (this._topHandler.panel.isHidden) {
|
867 | this._topHandler.panel.show();
|
868 | }
|
869 | }
|
870 | |
871 |
|
872 |
|
873 |
|
874 |
|
875 |
|
876 | _addToMenuArea(widget, options) {
|
877 | var _a;
|
878 | if (!widget.id) {
|
879 | console.error('Widgets added to app shell must have unique id property.');
|
880 | return;
|
881 | }
|
882 | options = options || {};
|
883 | const rank = (_a = options.rank) !== null && _a !== void 0 ? _a : DEFAULT_RANK;
|
884 | this._menuHandler.addWidget(widget, rank);
|
885 | this._onLayoutModified();
|
886 | if (this._menuHandler.panel.isHidden) {
|
887 | this._menuHandler.panel.show();
|
888 | }
|
889 | }
|
890 | |
891 |
|
892 |
|
893 |
|
894 |
|
895 |
|
896 | _addToHeaderArea(widget, options) {
|
897 | if (!widget.id) {
|
898 | console.error('Widgets added to app shell must have unique id property.');
|
899 | return;
|
900 | }
|
901 |
|
902 | this._headerPanel.addWidget(widget);
|
903 | this._onLayoutModified();
|
904 | if (this._headerPanel.isHidden) {
|
905 | this._headerPanel.show();
|
906 | }
|
907 | }
|
908 | |
909 |
|
910 |
|
911 |
|
912 |
|
913 |
|
914 | _addToBottomArea(widget, options) {
|
915 | if (!widget.id) {
|
916 | console.error('Widgets added to app shell must have unique id property.');
|
917 | return;
|
918 | }
|
919 |
|
920 | this._bottomPanel.addWidget(widget);
|
921 | this._onLayoutModified();
|
922 | if (this._bottomPanel.isHidden) {
|
923 | this._bottomPanel.show();
|
924 | }
|
925 | }
|
926 | _addToDownArea(widget, options) {
|
927 | if (!widget.id) {
|
928 | console.error('Widgets added to app shell must have unique id property.');
|
929 | return;
|
930 | }
|
931 | options = options || {};
|
932 | const { title } = widget;
|
933 |
|
934 |
|
935 | title.dataset = Object.assign(Object.assign({}, title.dataset), { id: widget.id });
|
936 | if (title.icon instanceof LabIcon) {
|
937 |
|
938 | title.icon = title.icon.bindprops({
|
939 | stylesheet: 'mainAreaTab'
|
940 | });
|
941 | }
|
942 | else if (typeof title.icon === 'string' || !title.icon) {
|
943 |
|
944 | title.iconClass = classes(title.iconClass, 'jp-Icon');
|
945 | }
|
946 | this._downPanel.addWidget(widget);
|
947 | this._onLayoutModified();
|
948 | if (this._downPanel.isHidden) {
|
949 | this._downPanel.show();
|
950 | }
|
951 | }
|
952 | |
953 |
|
954 |
|
955 | _adjacentBar(direction) {
|
956 | const current = this._currentTabBar();
|
957 | if (!current) {
|
958 | return null;
|
959 | }
|
960 | const bars = toArray(this._dockPanel.tabBars());
|
961 | const len = bars.length;
|
962 | const index = bars.indexOf(current);
|
963 | if (direction === 'previous') {
|
964 | return index > 0 ? bars[index - 1] : index === 0 ? bars[len - 1] : null;
|
965 | }
|
966 |
|
967 | return index < len - 1
|
968 | ? bars[index + 1]
|
969 | : index === len - 1
|
970 | ? bars[0]
|
971 | : null;
|
972 | }
|
973 | |
974 |
|
975 |
|
976 | _currentTabBar() {
|
977 | const current = this._tracker.currentWidget;
|
978 | if (!current) {
|
979 | return null;
|
980 | }
|
981 | const title = current.title;
|
982 | const bars = this._dockPanel.tabBars();
|
983 | return find(bars, bar => bar.titles.indexOf(title) > -1) || null;
|
984 | }
|
985 | |
986 |
|
987 |
|
988 | _onActiveChanged(sender, args) {
|
989 | if (args.newValue) {
|
990 | args.newValue.title.className += ` ${ACTIVE_CLASS}`;
|
991 | }
|
992 | if (args.oldValue) {
|
993 | args.oldValue.title.className = args.oldValue.title.className.replace(ACTIVE_CLASS, '');
|
994 | }
|
995 | this._activeChanged.emit(args);
|
996 | }
|
997 | |
998 |
|
999 |
|
1000 | _onCurrentChanged(sender, args) {
|
1001 | if (args.newValue) {
|
1002 | args.newValue.title.className += ` ${CURRENT_CLASS}`;
|
1003 | }
|
1004 | if (args.oldValue) {
|
1005 | args.oldValue.title.className = args.oldValue.title.className.replace(CURRENT_CLASS, '');
|
1006 | }
|
1007 | this._currentChanged.emit(args);
|
1008 | this._onLayoutModified();
|
1009 | }
|
1010 | |
1011 |
|
1012 |
|
1013 | _onTabPanelChanged() {
|
1014 | if (this._downPanel.stackedPanel.widgets.length === 0) {
|
1015 | this._downPanel.hide();
|
1016 | }
|
1017 | this._onLayoutModified();
|
1018 | }
|
1019 | |
1020 |
|
1021 |
|
1022 | _onLayoutModified() {
|
1023 | void this._layoutDebouncer.invoke();
|
1024 | }
|
1025 | }
|
1026 | var Private;
|
1027 | (function (Private) {
|
1028 | |
1029 |
|
1030 |
|
1031 | function itemCmp(first, second) {
|
1032 | return first.rank - second.rank;
|
1033 | }
|
1034 | Private.itemCmp = itemCmp;
|
1035 | |
1036 |
|
1037 |
|
1038 | function normalizeAreaConfig(parent, area) {
|
1039 | if (!area) {
|
1040 | return;
|
1041 | }
|
1042 | if (area.type === 'tab-area') {
|
1043 | area.widgets = area.widgets.filter(widget => !widget.isDisposed && widget.parent === parent);
|
1044 | return;
|
1045 | }
|
1046 | area.children.forEach(child => {
|
1047 | normalizeAreaConfig(parent, child);
|
1048 | });
|
1049 | }
|
1050 | Private.normalizeAreaConfig = normalizeAreaConfig;
|
1051 | |
1052 |
|
1053 |
|
1054 | class PanelHandler {
|
1055 | constructor() {
|
1056 | |
1057 |
|
1058 |
|
1059 | this._panelChildHook = (handler, msg) => {
|
1060 | switch (msg.type) {
|
1061 | case 'child-added':
|
1062 | {
|
1063 | const widget = msg.child;
|
1064 |
|
1065 | if (this._items.find(v => v.widget === widget)) {
|
1066 | break;
|
1067 | }
|
1068 |
|
1069 | const rank = this._items[this._items.length - 1].rank;
|
1070 | this._items.push({ widget, rank });
|
1071 | }
|
1072 | break;
|
1073 | case 'child-removed':
|
1074 | {
|
1075 | const widget = msg.child;
|
1076 | ArrayExt.removeFirstWhere(this._items, v => v.widget === widget);
|
1077 | }
|
1078 | break;
|
1079 | default:
|
1080 | break;
|
1081 | }
|
1082 | return true;
|
1083 | };
|
1084 | this._items = new Array();
|
1085 | this._panel = new Panel();
|
1086 | MessageLoop.installMessageHook(this._panel, this._panelChildHook);
|
1087 | }
|
1088 | |
1089 |
|
1090 |
|
1091 | get panel() {
|
1092 | return this._panel;
|
1093 | }
|
1094 | |
1095 |
|
1096 |
|
1097 |
|
1098 |
|
1099 | addWidget(widget, rank) {
|
1100 | widget.parent = null;
|
1101 | const item = { widget, rank };
|
1102 | const index = ArrayExt.upperBound(this._items, item, Private.itemCmp);
|
1103 | ArrayExt.insert(this._items, index, item);
|
1104 | this._panel.insertWidget(index, widget);
|
1105 | }
|
1106 | }
|
1107 | Private.PanelHandler = PanelHandler;
|
1108 | |
1109 |
|
1110 |
|
1111 | class SideBarHandler {
|
1112 | |
1113 |
|
1114 |
|
1115 | constructor() {
|
1116 | this._items = new Array();
|
1117 | this._sideBar = new TabBar({
|
1118 | insertBehavior: 'none',
|
1119 | removeBehavior: 'none',
|
1120 | allowDeselect: true,
|
1121 | orientation: 'vertical'
|
1122 | });
|
1123 | this._stackedPanel = new StackedPanel();
|
1124 | this._sideBar.hide();
|
1125 | this._stackedPanel.hide();
|
1126 | this._lastCurrent = null;
|
1127 | this._sideBar.currentChanged.connect(this._onCurrentChanged, this);
|
1128 | this._sideBar.tabActivateRequested.connect(this._onTabActivateRequested, this);
|
1129 | this._stackedPanel.widgetRemoved.connect(this._onWidgetRemoved, this);
|
1130 | }
|
1131 | |
1132 |
|
1133 |
|
1134 | get sideBar() {
|
1135 | return this._sideBar;
|
1136 | }
|
1137 | |
1138 |
|
1139 |
|
1140 | get stackedPanel() {
|
1141 | return this._stackedPanel;
|
1142 | }
|
1143 | |
1144 |
|
1145 |
|
1146 |
|
1147 |
|
1148 |
|
1149 |
|
1150 | expand() {
|
1151 | const previous = this._lastCurrent || (this._items.length > 0 && this._items[0].widget);
|
1152 | if (previous) {
|
1153 | this.activate(previous.id);
|
1154 | }
|
1155 | }
|
1156 | |
1157 |
|
1158 |
|
1159 |
|
1160 |
|
1161 | activate(id) {
|
1162 | const widget = this._findWidgetByID(id);
|
1163 | if (widget) {
|
1164 | this._sideBar.currentTitle = widget.title;
|
1165 | widget.activate();
|
1166 | }
|
1167 | }
|
1168 | |
1169 |
|
1170 |
|
1171 | has(id) {
|
1172 | return this._findWidgetByID(id) !== null;
|
1173 | }
|
1174 | |
1175 |
|
1176 |
|
1177 | collapse() {
|
1178 | this._sideBar.currentTitle = null;
|
1179 | }
|
1180 | |
1181 |
|
1182 |
|
1183 |
|
1184 |
|
1185 | addWidget(widget, rank) {
|
1186 | widget.parent = null;
|
1187 | widget.hide();
|
1188 | const item = { widget, rank };
|
1189 | const index = this._findInsertIndex(item);
|
1190 | ArrayExt.insert(this._items, index, item);
|
1191 | this._stackedPanel.insertWidget(index, widget);
|
1192 | const title = this._sideBar.insertTab(index, widget.title);
|
1193 |
|
1194 |
|
1195 | title.dataset = { id: widget.id };
|
1196 | if (title.icon instanceof LabIcon) {
|
1197 |
|
1198 | title.icon = title.icon.bindprops({
|
1199 | stylesheet: 'sideBar'
|
1200 | });
|
1201 | }
|
1202 | else if (typeof title.icon === 'string' || !title.icon) {
|
1203 |
|
1204 | title.iconClass = classes(title.iconClass, 'jp-Icon', 'jp-Icon-20');
|
1205 | }
|
1206 | this._refreshVisibility();
|
1207 | }
|
1208 | |
1209 |
|
1210 |
|
1211 | dehydrate() {
|
1212 | const collapsed = this._sideBar.currentTitle === null;
|
1213 | const widgets = toArray(this._stackedPanel.widgets);
|
1214 | const currentWidget = widgets[this._sideBar.currentIndex];
|
1215 | return { collapsed, currentWidget, widgets };
|
1216 | }
|
1217 | |
1218 |
|
1219 |
|
1220 | rehydrate(data) {
|
1221 | if (data.currentWidget) {
|
1222 | this.activate(data.currentWidget.id);
|
1223 | }
|
1224 | if (data.collapsed) {
|
1225 | this.collapse();
|
1226 | }
|
1227 | }
|
1228 | |
1229 |
|
1230 |
|
1231 | _findInsertIndex(item) {
|
1232 | return ArrayExt.upperBound(this._items, item, Private.itemCmp);
|
1233 | }
|
1234 | |
1235 |
|
1236 |
|
1237 | _findWidgetIndex(widget) {
|
1238 | return ArrayExt.findFirstIndex(this._items, i => i.widget === widget);
|
1239 | }
|
1240 | |
1241 |
|
1242 |
|
1243 | _findWidgetByTitle(title) {
|
1244 | const item = find(this._items, value => value.widget.title === title);
|
1245 | return item ? item.widget : null;
|
1246 | }
|
1247 | |
1248 |
|
1249 |
|
1250 | _findWidgetByID(id) {
|
1251 | const item = find(this._items, value => value.widget.id === id);
|
1252 | return item ? item.widget : null;
|
1253 | }
|
1254 | |
1255 |
|
1256 |
|
1257 | _refreshVisibility() {
|
1258 | this._sideBar.setHidden(this._sideBar.titles.length === 0);
|
1259 | this._stackedPanel.setHidden(this._sideBar.currentTitle === null);
|
1260 | }
|
1261 | |
1262 |
|
1263 |
|
1264 | _onCurrentChanged(sender, args) {
|
1265 | const oldWidget = args.previousTitle
|
1266 | ? this._findWidgetByTitle(args.previousTitle)
|
1267 | : null;
|
1268 | const newWidget = args.currentTitle
|
1269 | ? this._findWidgetByTitle(args.currentTitle)
|
1270 | : null;
|
1271 | if (oldWidget) {
|
1272 | oldWidget.hide();
|
1273 | }
|
1274 | if (newWidget) {
|
1275 | newWidget.show();
|
1276 | }
|
1277 | this._lastCurrent = newWidget || oldWidget;
|
1278 | this._refreshVisibility();
|
1279 | }
|
1280 | |
1281 |
|
1282 |
|
1283 | _onTabActivateRequested(sender, args) {
|
1284 | args.title.owner.activate();
|
1285 | }
|
1286 | |
1287 |
|
1288 |
|
1289 | _onWidgetRemoved(sender, widget) {
|
1290 | if (widget === this._lastCurrent) {
|
1291 | this._lastCurrent = null;
|
1292 | }
|
1293 | ArrayExt.removeAt(this._items, this._findWidgetIndex(widget));
|
1294 | this._sideBar.removeTab(widget.title);
|
1295 | this._refreshVisibility();
|
1296 | }
|
1297 | }
|
1298 | Private.SideBarHandler = SideBarHandler;
|
1299 | class SkipLinkWidget extends Widget {
|
1300 | |
1301 |
|
1302 |
|
1303 | constructor(shell) {
|
1304 | super();
|
1305 | this.addClass('jp-skiplink');
|
1306 | this.id = 'jp-skiplink';
|
1307 | this._shell = shell;
|
1308 | this._createSkipLink('Skip to left side bar');
|
1309 | }
|
1310 | handleEvent(event) {
|
1311 | switch (event.type) {
|
1312 | case 'click':
|
1313 | this._focusLeftSideBar();
|
1314 | break;
|
1315 | }
|
1316 | }
|
1317 | |
1318 |
|
1319 |
|
1320 | onAfterAttach(msg) {
|
1321 | super.onAfterAttach(msg);
|
1322 | this.node.addEventListener('click', this);
|
1323 | }
|
1324 | |
1325 |
|
1326 |
|
1327 |
|
1328 | onBeforeDetach(msg) {
|
1329 | this.node.removeEventListener('click', this);
|
1330 | super.onBeforeDetach(msg);
|
1331 | }
|
1332 | _focusLeftSideBar() {
|
1333 | this._shell.expandLeft();
|
1334 | }
|
1335 | _createSkipLink(skipLinkText) {
|
1336 | const skipLink = document.createElement('a');
|
1337 | skipLink.href = '#';
|
1338 | skipLink.tabIndex = 1;
|
1339 | skipLink.text = skipLinkText;
|
1340 | skipLink.className = 'skip-link';
|
1341 | this.node.appendChild(skipLink);
|
1342 | }
|
1343 | }
|
1344 | Private.SkipLinkWidget = SkipLinkWidget;
|
1345 | class TitleHandler extends Widget {
|
1346 | |
1347 |
|
1348 |
|
1349 | constructor(shell) {
|
1350 | super();
|
1351 | this._selected = false;
|
1352 | const inputElement = document.createElement('input');
|
1353 | inputElement.type = 'text';
|
1354 | this.node.appendChild(inputElement);
|
1355 | this._shell = shell;
|
1356 | this.id = 'jp-title-panel-title';
|
1357 | }
|
1358 | |
1359 |
|
1360 |
|
1361 | onAfterAttach(msg) {
|
1362 | super.onAfterAttach(msg);
|
1363 | this.inputElement.addEventListener('keyup', this);
|
1364 | this.inputElement.addEventListener('click', this);
|
1365 | this.inputElement.addEventListener('blur', this);
|
1366 | }
|
1367 | |
1368 |
|
1369 |
|
1370 | onBeforeDetach(msg) {
|
1371 | super.onBeforeDetach(msg);
|
1372 | this.inputElement.removeEventListener('keyup', this);
|
1373 | this.inputElement.removeEventListener('click', this);
|
1374 | this.inputElement.removeEventListener('blur', this);
|
1375 | }
|
1376 | handleEvent(event) {
|
1377 | switch (event.type) {
|
1378 | case 'keyup':
|
1379 | void this._evtKeyUp(event);
|
1380 | break;
|
1381 | case 'click':
|
1382 | this._evtClick(event);
|
1383 | break;
|
1384 | case 'blur':
|
1385 | this._selected = false;
|
1386 | break;
|
1387 | }
|
1388 | }
|
1389 | |
1390 |
|
1391 |
|
1392 | async _evtKeyUp(event) {
|
1393 | if (event.key == 'Enter') {
|
1394 | const widget = this._shell.currentWidget;
|
1395 | if (widget == null) {
|
1396 | return;
|
1397 | }
|
1398 | const oldName = widget.title.label;
|
1399 | const inputElement = this.inputElement;
|
1400 | const newName = inputElement.value;
|
1401 | inputElement.blur();
|
1402 | if (newName !== oldName) {
|
1403 | widget.title.label = newName;
|
1404 | }
|
1405 | else {
|
1406 | inputElement.value = oldName;
|
1407 | }
|
1408 | }
|
1409 | }
|
1410 | |
1411 |
|
1412 |
|
1413 | _evtClick(event) {
|
1414 |
|
1415 | if (event.button !== 0 || this._selected) {
|
1416 | return;
|
1417 | }
|
1418 | const inputElement = this.inputElement;
|
1419 | event.preventDefault();
|
1420 | event.stopPropagation();
|
1421 | this._selected = true;
|
1422 | const selectEnd = inputElement.value.indexOf('.');
|
1423 | if (selectEnd === -1) {
|
1424 | inputElement.select();
|
1425 | }
|
1426 | else {
|
1427 | inputElement.setSelectionRange(0, selectEnd);
|
1428 | }
|
1429 | }
|
1430 | |
1431 |
|
1432 |
|
1433 | get inputElement() {
|
1434 | return this.node.children[0];
|
1435 | }
|
1436 | }
|
1437 | Private.TitleHandler = TitleHandler;
|
1438 | class RestorableSplitPanel extends SplitPanel {
|
1439 | constructor(options = {}) {
|
1440 | super(options);
|
1441 | this.updated = new Signal(this);
|
1442 | }
|
1443 | |
1444 |
|
1445 |
|
1446 | onUpdateRequest(msg) {
|
1447 | super.onUpdateRequest(msg);
|
1448 | this.updated.emit();
|
1449 | }
|
1450 | }
|
1451 | Private.RestorableSplitPanel = RestorableSplitPanel;
|
1452 | })(Private || (Private = {}));
|
1453 |
|
\ | No newline at end of file |