1 |
|
2 |
|
3 | import { nullTranslator } from '@jupyterlab/translation';
|
4 | import { Button, circleEmptyIcon, circleIcon, classes, ellipsesIcon, LabIcon, offlineBoltIcon, refreshIcon, stopIcon } from '@jupyterlab/ui-components';
|
5 | import { find, map, some } from '@lumino/algorithm';
|
6 | import { CommandRegistry } from '@lumino/commands';
|
7 | import { MessageLoop } from '@lumino/messaging';
|
8 | import { AttachedProperty } from '@lumino/properties';
|
9 | import { PanelLayout, Widget } from '@lumino/widgets';
|
10 | import * as React from 'react';
|
11 | import { sessionContextDialogs } from '../sessioncontext';
|
12 | import { translateKernelStatuses } from '../kernelstatuses';
|
13 | import { ReactWidget, UseSignal } from '../vdom';
|
14 | import { Throttler } from '@lumino/polling';
|
15 |
|
16 |
|
17 |
|
18 | const TOOLBAR_CLASS = 'jp-Toolbar';
|
19 |
|
20 |
|
21 |
|
22 | const TOOLBAR_OPENER_NAME = 'toolbar-popup-opener';
|
23 |
|
24 |
|
25 |
|
26 | const TOOLBAR_ITEM_CLASS = 'jp-Toolbar-item';
|
27 |
|
28 |
|
29 |
|
30 | const TOOLBAR_KERNEL_NAME_CLASS = 'jp-Toolbar-kernelName';
|
31 |
|
32 |
|
33 |
|
34 | const TOOLBAR_SPACER_CLASS = 'jp-Toolbar-spacer';
|
35 |
|
36 |
|
37 |
|
38 | const TOOLBAR_KERNEL_STATUS_CLASS = 'jp-Toolbar-kernelStatus';
|
39 |
|
40 |
|
41 |
|
42 |
|
43 |
|
44 |
|
45 |
|
46 |
|
47 | class ToolbarLayout extends PanelLayout {
|
48 | constructor() {
|
49 | super(...arguments);
|
50 | this._dirty = false;
|
51 | }
|
52 | |
53 |
|
54 |
|
55 |
|
56 |
|
57 |
|
58 | onFitRequest(msg) {
|
59 | super.onFitRequest(msg);
|
60 | if (this.parent.isAttached) {
|
61 |
|
62 |
|
63 | if (some(this.widgets, w => !w.isHidden)) {
|
64 | this.parent.node.style.minHeight = 'var(--jp-private-toolbar-height)';
|
65 | this.parent.removeClass('jp-Toolbar-micro');
|
66 | }
|
67 | else {
|
68 | this.parent.node.style.minHeight = '';
|
69 | this.parent.addClass('jp-Toolbar-micro');
|
70 | }
|
71 | }
|
72 |
|
73 | this._dirty = true;
|
74 |
|
75 |
|
76 | if (this.parent.parent) {
|
77 | MessageLoop.sendMessage(this.parent.parent, Widget.Msg.FitRequest);
|
78 | }
|
79 |
|
80 |
|
81 | if (this._dirty) {
|
82 | MessageLoop.sendMessage(this.parent, Widget.Msg.UpdateRequest);
|
83 | }
|
84 | }
|
85 | |
86 |
|
87 |
|
88 | onUpdateRequest(msg) {
|
89 | super.onUpdateRequest(msg);
|
90 | if (this.parent.isVisible) {
|
91 | this._dirty = false;
|
92 | }
|
93 | }
|
94 | |
95 |
|
96 |
|
97 | onChildShown(msg) {
|
98 | super.onChildShown(msg);
|
99 |
|
100 | this.parent.fit();
|
101 | }
|
102 | |
103 |
|
104 |
|
105 | onChildHidden(msg) {
|
106 | super.onChildHidden(msg);
|
107 |
|
108 | this.parent.fit();
|
109 | }
|
110 | |
111 |
|
112 |
|
113 | onBeforeAttach(msg) {
|
114 | super.onBeforeAttach(msg);
|
115 |
|
116 | this.parent.fit();
|
117 | }
|
118 | |
119 |
|
120 |
|
121 |
|
122 |
|
123 |
|
124 |
|
125 |
|
126 |
|
127 |
|
128 | attachWidget(index, widget) {
|
129 | super.attachWidget(index, widget);
|
130 |
|
131 | this.parent.fit();
|
132 | }
|
133 | |
134 |
|
135 |
|
136 |
|
137 |
|
138 |
|
139 |
|
140 |
|
141 |
|
142 |
|
143 | detachWidget(index, widget) {
|
144 | super.detachWidget(index, widget);
|
145 |
|
146 | this.parent.fit();
|
147 | }
|
148 | }
|
149 |
|
150 |
|
151 |
|
152 | export class Toolbar extends Widget {
|
153 | |
154 |
|
155 |
|
156 | constructor(options = {}) {
|
157 | var _a;
|
158 | super();
|
159 | this.addClass(TOOLBAR_CLASS);
|
160 | this.layout = (_a = options.layout) !== null && _a !== void 0 ? _a : new ToolbarLayout();
|
161 | }
|
162 | |
163 |
|
164 |
|
165 |
|
166 |
|
167 | names() {
|
168 | const layout = this.layout;
|
169 | return map(layout.widgets, widget => {
|
170 | return Private.nameProperty.get(widget);
|
171 | });
|
172 | }
|
173 | |
174 |
|
175 |
|
176 |
|
177 |
|
178 |
|
179 |
|
180 |
|
181 |
|
182 |
|
183 |
|
184 |
|
185 |
|
186 |
|
187 |
|
188 | addItem(name, widget) {
|
189 | const layout = this.layout;
|
190 | return this.insertItem(layout.widgets.length, name, widget);
|
191 | }
|
192 | |
193 |
|
194 |
|
195 |
|
196 |
|
197 |
|
198 |
|
199 |
|
200 |
|
201 |
|
202 |
|
203 |
|
204 |
|
205 |
|
206 |
|
207 |
|
208 | insertItem(index, name, widget) {
|
209 | const existing = find(this.names(), value => value === name);
|
210 | if (existing) {
|
211 | return false;
|
212 | }
|
213 | widget.addClass(TOOLBAR_ITEM_CLASS);
|
214 | const layout = this.layout;
|
215 | const j = Math.max(0, Math.min(index, layout.widgets.length));
|
216 | layout.insertWidget(j, widget);
|
217 | Private.nameProperty.set(widget, name);
|
218 | return true;
|
219 | }
|
220 | |
221 |
|
222 |
|
223 |
|
224 |
|
225 |
|
226 |
|
227 |
|
228 |
|
229 |
|
230 |
|
231 |
|
232 |
|
233 |
|
234 |
|
235 |
|
236 | insertAfter(at, name, widget) {
|
237 | return this._insertRelative(at, 1, name, widget);
|
238 | }
|
239 | |
240 |
|
241 |
|
242 |
|
243 |
|
244 |
|
245 |
|
246 |
|
247 |
|
248 |
|
249 |
|
250 |
|
251 |
|
252 |
|
253 |
|
254 |
|
255 | insertBefore(at, name, widget) {
|
256 | return this._insertRelative(at, 0, name, widget);
|
257 | }
|
258 | _insertRelative(at, offset, name, widget) {
|
259 | const nameWithIndex = map(this.names(), (name, i) => {
|
260 | return { name: name, index: i };
|
261 | });
|
262 | const target = find(nameWithIndex, x => x.name === at);
|
263 | if (target) {
|
264 | return this.insertItem(target.index + offset, name, widget);
|
265 | }
|
266 | return false;
|
267 | }
|
268 | |
269 |
|
270 |
|
271 |
|
272 |
|
273 |
|
274 |
|
275 |
|
276 |
|
277 |
|
278 | handleEvent(event) {
|
279 | switch (event.type) {
|
280 | case 'click':
|
281 | this.handleClick(event);
|
282 | break;
|
283 | default:
|
284 | break;
|
285 | }
|
286 | }
|
287 | |
288 |
|
289 |
|
290 | handleClick(event) {
|
291 |
|
292 | event.stopPropagation();
|
293 |
|
294 |
|
295 | if (event.target instanceof HTMLLabelElement) {
|
296 | const forId = event.target.getAttribute('for');
|
297 | if (forId && this.node.querySelector(`#${forId}`)) {
|
298 | return;
|
299 | }
|
300 | }
|
301 |
|
302 | if (this.node.contains(document.activeElement)) {
|
303 | return;
|
304 | }
|
305 |
|
306 | if (this.parent) {
|
307 | this.parent.activate();
|
308 | }
|
309 | }
|
310 | |
311 |
|
312 |
|
313 | onAfterAttach(msg) {
|
314 | this.node.addEventListener('click', this);
|
315 | }
|
316 | |
317 |
|
318 |
|
319 | onBeforeDetach(msg) {
|
320 | this.node.removeEventListener('click', this);
|
321 | }
|
322 | }
|
323 |
|
324 |
|
325 |
|
326 | export class ReactiveToolbar extends Toolbar {
|
327 | |
328 |
|
329 |
|
330 | constructor() {
|
331 | super();
|
332 | this.popupOpener = new ToolbarPopupOpener();
|
333 | this._widgetWidths = {};
|
334 | this.insertItem(0, TOOLBAR_OPENER_NAME, this.popupOpener);
|
335 | this.popupOpener.hide();
|
336 | this._resizer = new Throttler(this._onResize.bind(this), 500);
|
337 | }
|
338 | |
339 |
|
340 |
|
341 | dispose() {
|
342 | if (this.isDisposed) {
|
343 | return;
|
344 | }
|
345 | if (this._resizer) {
|
346 | this._resizer.dispose();
|
347 | }
|
348 | super.dispose();
|
349 | }
|
350 | |
351 |
|
352 |
|
353 |
|
354 |
|
355 |
|
356 |
|
357 |
|
358 |
|
359 |
|
360 |
|
361 |
|
362 |
|
363 |
|
364 |
|
365 |
|
366 |
|
367 | insertAfter(at, name, widget) {
|
368 | if (at === TOOLBAR_OPENER_NAME) {
|
369 | return false;
|
370 | }
|
371 | return super.insertAfter(at, name, widget);
|
372 | }
|
373 | |
374 |
|
375 |
|
376 |
|
377 |
|
378 |
|
379 |
|
380 |
|
381 |
|
382 |
|
383 |
|
384 |
|
385 |
|
386 |
|
387 |
|
388 |
|
389 | insertItem(index, name, widget) {
|
390 | if (widget instanceof ToolbarPopupOpener) {
|
391 | return super.insertItem(index, name, widget);
|
392 | }
|
393 | else {
|
394 | const j = Math.max(0, Math.min(index, this.layout.widgets.length - 1));
|
395 | return super.insertItem(j, name, widget);
|
396 | }
|
397 | }
|
398 | |
399 |
|
400 |
|
401 |
|
402 |
|
403 | onBeforeHide(msg) {
|
404 | this.popupOpener.hidePopup();
|
405 | super.onBeforeHide(msg);
|
406 | }
|
407 | onResize(msg) {
|
408 | super.onResize(msg);
|
409 | if (msg.width > 0 && this._resizer) {
|
410 | void this._resizer.invoke();
|
411 | }
|
412 | }
|
413 | _onResize() {
|
414 | if (this.parent && this.parent.isAttached) {
|
415 | const toolbarWidth = this.node.clientWidth;
|
416 | const opener = this.popupOpener;
|
417 | const openerWidth = 30;
|
418 | const toolbarPadding = 2;
|
419 | const layout = this.layout;
|
420 | let width = opener.isHidden
|
421 | ? toolbarPadding
|
422 | : toolbarPadding + openerWidth;
|
423 | let index = 0;
|
424 | const widgetsToRemove = [];
|
425 | const toIndex = layout.widgets.length - 1;
|
426 | while (index < toIndex) {
|
427 | const widget = layout.widgets[index];
|
428 | this._saveWidgetWidth(widget);
|
429 | width += this._getWidgetWidth(widget);
|
430 | if (widgetsToRemove.length === 0 &&
|
431 | opener.isHidden &&
|
432 | width + openerWidth > toolbarWidth) {
|
433 | width += openerWidth;
|
434 | }
|
435 | if (width > toolbarWidth) {
|
436 | widgetsToRemove.push(widget);
|
437 | }
|
438 | index++;
|
439 | }
|
440 | while (widgetsToRemove.length > 0) {
|
441 | const widget = widgetsToRemove.pop();
|
442 | width -= this._getWidgetWidth(widget);
|
443 | opener.addWidget(widget);
|
444 | }
|
445 | if (opener.widgetCount() > 0) {
|
446 | const widgetsToAdd = [];
|
447 | let index = 0;
|
448 | let widget = opener.widgetAt(index);
|
449 | const widgetCount = opener.widgetCount();
|
450 | width += this._getWidgetWidth(widget);
|
451 | if (widgetCount === 1 && width - openerWidth <= toolbarWidth) {
|
452 | width -= openerWidth;
|
453 | }
|
454 | while (width < toolbarWidth && index < widgetCount) {
|
455 | widgetsToAdd.push(widget);
|
456 | index++;
|
457 | widget = opener.widgetAt(index);
|
458 | if (widget) {
|
459 | width += this._getWidgetWidth(widget);
|
460 | }
|
461 | else {
|
462 | break;
|
463 | }
|
464 | }
|
465 | while (widgetsToAdd.length > 0) {
|
466 | const widget = widgetsToAdd.shift();
|
467 | this.addItem(Private.nameProperty.get(widget), widget);
|
468 | }
|
469 | }
|
470 | if (opener.widgetCount() > 0) {
|
471 | opener.updatePopup();
|
472 | opener.show();
|
473 | }
|
474 | else {
|
475 | opener.hide();
|
476 | }
|
477 | }
|
478 | }
|
479 | _saveWidgetWidth(widget) {
|
480 | const widgetName = Private.nameProperty.get(widget);
|
481 | this._widgetWidths[widgetName] = widget.hasClass(TOOLBAR_SPACER_CLASS)
|
482 | ? 2
|
483 | : widget.node.clientWidth;
|
484 | }
|
485 | _getWidgetWidth(widget) {
|
486 | const widgetName = Private.nameProperty.get(widget);
|
487 | return this._widgetWidths[widgetName];
|
488 | }
|
489 | }
|
490 |
|
491 |
|
492 |
|
493 | (function (Toolbar) {
|
494 | |
495 |
|
496 |
|
497 |
|
498 |
|
499 |
|
500 | function createInterruptButton(sessionContext, translator) {
|
501 | translator = translator || nullTranslator;
|
502 | const trans = translator.load('jupyterlab');
|
503 | return new ToolbarButton({
|
504 | icon: stopIcon,
|
505 | onClick: () => {
|
506 | var _a, _b;
|
507 | void ((_b = (_a = sessionContext.session) === null || _a === void 0 ? void 0 : _a.kernel) === null || _b === void 0 ? void 0 : _b.interrupt());
|
508 | },
|
509 | tooltip: trans.__('Interrupt the kernel')
|
510 | });
|
511 | }
|
512 | Toolbar.createInterruptButton = createInterruptButton;
|
513 | |
514 |
|
515 |
|
516 |
|
517 |
|
518 |
|
519 | function createRestartButton(sessionContext, dialogs, translator) {
|
520 | translator = translator || nullTranslator;
|
521 | const trans = translator.load('jupyterlab');
|
522 | return new ToolbarButton({
|
523 | icon: refreshIcon,
|
524 | onClick: () => {
|
525 | void (dialogs !== null && dialogs !== void 0 ? dialogs : sessionContextDialogs).restart(sessionContext, translator);
|
526 | },
|
527 | tooltip: trans.__('Restart the kernel')
|
528 | });
|
529 | }
|
530 | Toolbar.createRestartButton = createRestartButton;
|
531 | |
532 |
|
533 |
|
534 |
|
535 |
|
536 |
|
537 |
|
538 | function createSpacerItem() {
|
539 | return new Private.Spacer();
|
540 | }
|
541 | Toolbar.createSpacerItem = createSpacerItem;
|
542 | |
543 |
|
544 |
|
545 |
|
546 |
|
547 |
|
548 |
|
549 | function createKernelNameItem(sessionContext, dialogs, translator) {
|
550 | const el = ReactWidget.create(React.createElement(Private.KernelNameComponent, { sessionContext: sessionContext, dialogs: dialogs !== null && dialogs !== void 0 ? dialogs : sessionContextDialogs, translator: translator }));
|
551 | el.addClass('jp-KernelName');
|
552 | return el;
|
553 | }
|
554 | Toolbar.createKernelNameItem = createKernelNameItem;
|
555 | |
556 |
|
557 |
|
558 |
|
559 |
|
560 |
|
561 |
|
562 |
|
563 | function createKernelStatusItem(sessionContext, translator) {
|
564 | return new Private.KernelStatus(sessionContext, translator);
|
565 | }
|
566 | Toolbar.createKernelStatusItem = createKernelStatusItem;
|
567 | })(Toolbar || (Toolbar = {}));
|
568 |
|
569 |
|
570 |
|
571 |
|
572 |
|
573 | export function ToolbarButtonComponent(props) {
|
574 | var _a, _b;
|
575 |
|
576 |
|
577 |
|
578 |
|
579 | const handleMouseDown = (event) => {
|
580 | var _a;
|
581 |
|
582 | if (event.button === 0) {
|
583 | event.preventDefault();
|
584 | (_a = props.onClick) === null || _a === void 0 ? void 0 : _a.call(props);
|
585 | }
|
586 | };
|
587 | const handleKeyDown = (event) => {
|
588 | var _a;
|
589 | const { key } = event;
|
590 | if (key === 'Enter' || key === ' ') {
|
591 | (_a = props.onClick) === null || _a === void 0 ? void 0 : _a.call(props);
|
592 | }
|
593 | };
|
594 | const handleClick = (event) => {
|
595 | var _a;
|
596 | if (event.button === 0) {
|
597 | (_a = props.onClick) === null || _a === void 0 ? void 0 : _a.call(props);
|
598 | }
|
599 | };
|
600 | const getTooltip = () => {
|
601 | if (props.enabled === false && props.disabledTooltip) {
|
602 | return props.disabledTooltip;
|
603 | }
|
604 | else if (props.pressed && props.pressedTooltip) {
|
605 | return props.pressedTooltip;
|
606 | }
|
607 | else {
|
608 | return props.tooltip || props.iconLabel;
|
609 | }
|
610 | };
|
611 | return (React.createElement(Button, Object.assign({ className: props.className
|
612 | ? props.className + ' jp-ToolbarButtonComponent'
|
613 | : 'jp-ToolbarButtonComponent', "aria-pressed": props.pressed, "aria-disabled": props.enabled === false }, props.dataset, { disabled: props.enabled === false, onClick: ((_a = props.actualOnClick) !== null && _a !== void 0 ? _a : false) ? handleClick : undefined, onMouseDown: !((_b = props.actualOnClick) !== null && _b !== void 0 ? _b : false) ? handleMouseDown : undefined, onKeyDown: handleKeyDown, title: getTooltip(), minimal: true }),
|
614 | (props.icon || props.iconClass) && (React.createElement(LabIcon.resolveReact, { icon: props.pressed ? props.pressedIcon : props.icon, iconClass:
|
615 |
|
616 | classes(props.iconClass, 'jp-Icon'), className: "jp-ToolbarButtonComponent-icon", tag: "span", stylesheet: "toolbarButton" })),
|
617 | props.label && (React.createElement("span", { className: "jp-ToolbarButtonComponent-label" }, props.label))));
|
618 | }
|
619 |
|
620 |
|
621 |
|
622 |
|
623 | export function addToolbarButtonClass(w) {
|
624 | w.addClass('jp-ToolbarButton');
|
625 | return w;
|
626 | }
|
627 |
|
628 |
|
629 |
|
630 | export class ToolbarButton extends ReactWidget {
|
631 | |
632 |
|
633 |
|
634 |
|
635 | constructor(props = {}) {
|
636 | var _a, _b;
|
637 | super();
|
638 | this.props = props;
|
639 | addToolbarButtonClass(this);
|
640 | this._enabled = (_a = props.enabled) !== null && _a !== void 0 ? _a : true;
|
641 | this._pressed = this._enabled && ((_b = props.pressed) !== null && _b !== void 0 ? _b : false);
|
642 | this._onClick = props.onClick;
|
643 | }
|
644 | |
645 |
|
646 |
|
647 |
|
648 | set pressed(value) {
|
649 | if (this.enabled && value !== this._pressed) {
|
650 | this._pressed = value;
|
651 | this.update();
|
652 | }
|
653 | }
|
654 | |
655 |
|
656 |
|
657 | get pressed() {
|
658 | return this._pressed;
|
659 | }
|
660 | |
661 |
|
662 |
|
663 |
|
664 | set enabled(value) {
|
665 | if (value != this._enabled) {
|
666 | this._enabled = value;
|
667 | if (!this._enabled) {
|
668 | this._pressed = false;
|
669 | }
|
670 | this.update();
|
671 | }
|
672 | }
|
673 | |
674 |
|
675 |
|
676 | get enabled() {
|
677 | return this._enabled;
|
678 | }
|
679 | |
680 |
|
681 |
|
682 |
|
683 | set onClick(value) {
|
684 | if (value !== this._onClick) {
|
685 | this._onClick = value;
|
686 | this.update();
|
687 | }
|
688 | }
|
689 | |
690 |
|
691 |
|
692 | get onClick() {
|
693 | return this._onClick;
|
694 | }
|
695 | render() {
|
696 | return (React.createElement(ToolbarButtonComponent, Object.assign({}, this.props, { pressed: this.pressed, enabled: this.enabled, onClick: this.onClick })));
|
697 | }
|
698 | }
|
699 |
|
700 |
|
701 |
|
702 |
|
703 |
|
704 |
|
705 | export function CommandToolbarButtonComponent(props) {
|
706 | return (React.createElement(UseSignal, { signal: props.commands.commandChanged, shouldUpdate: (sender, args) => (args.id === props.id && args.type === 'changed') ||
|
707 | args.type === 'many-changed' }, () => React.createElement(ToolbarButtonComponent, Object.assign({}, Private.propsFromCommand(props)))));
|
708 | }
|
709 |
|
710 |
|
711 |
|
712 |
|
713 | export function addCommandToolbarButtonClass(w) {
|
714 | w.addClass('jp-CommandToolbarButton');
|
715 | return w;
|
716 | }
|
717 |
|
718 |
|
719 |
|
720 | export class CommandToolbarButton extends ReactWidget {
|
721 | |
722 |
|
723 |
|
724 |
|
725 | constructor(props) {
|
726 | super();
|
727 | this.props = props;
|
728 | addCommandToolbarButtonClass(this);
|
729 | }
|
730 | render() {
|
731 | return React.createElement(CommandToolbarButtonComponent, Object.assign({}, this.props));
|
732 | }
|
733 | }
|
734 |
|
735 |
|
736 |
|
737 |
|
738 |
|
739 | class ToolbarPopup extends Widget {
|
740 | |
741 |
|
742 |
|
743 | constructor() {
|
744 | super();
|
745 | this.width = 0;
|
746 | this.addClass('jp-Toolbar-responsive-popup');
|
747 | this.layout = new PanelLayout();
|
748 | Widget.attach(this, document.body);
|
749 | this.hide();
|
750 | }
|
751 | |
752 |
|
753 |
|
754 |
|
755 |
|
756 |
|
757 |
|
758 | updateWidth(width) {
|
759 | if (width > 0) {
|
760 | this.width = width;
|
761 | this.node.style.width = `${width}px`;
|
762 | }
|
763 | }
|
764 | |
765 |
|
766 |
|
767 |
|
768 |
|
769 |
|
770 | alignTo(widget) {
|
771 | const { height: widgetHeight, width: widgetWidth, x: widgetX, y: widgetY } = widget.node.getBoundingClientRect();
|
772 | const width = this.width;
|
773 | this.node.style.left = `${widgetX + widgetWidth - width + 1}px`;
|
774 | this.node.style.top = `${widgetY + widgetHeight + 1}px`;
|
775 | }
|
776 | |
777 |
|
778 |
|
779 |
|
780 |
|
781 | insertWidget(index, widget) {
|
782 | this.layout.insertWidget(0, widget);
|
783 | }
|
784 | |
785 |
|
786 |
|
787 | widgetCount() {
|
788 | return this.layout.widgets.length;
|
789 | }
|
790 | |
791 |
|
792 |
|
793 |
|
794 | widgetAt(index) {
|
795 | return this.layout.widgets[index];
|
796 | }
|
797 | }
|
798 |
|
799 |
|
800 |
|
801 |
|
802 |
|
803 | class ToolbarPopupOpener extends ToolbarButton {
|
804 | |
805 |
|
806 |
|
807 | constructor() {
|
808 | super({
|
809 | icon: ellipsesIcon,
|
810 | onClick: () => {
|
811 | this.handleClick();
|
812 | }
|
813 | });
|
814 | this.addClass('jp-Toolbar-responsive-opener');
|
815 | this.popup = new ToolbarPopup();
|
816 | }
|
817 | |
818 |
|
819 |
|
820 |
|
821 | addWidget(widget) {
|
822 | this.popup.insertWidget(0, widget);
|
823 | }
|
824 | |
825 |
|
826 |
|
827 |
|
828 |
|
829 |
|
830 |
|
831 |
|
832 | dispose() {
|
833 | if (this.isDisposed) {
|
834 | return;
|
835 | }
|
836 | this.popup.dispose();
|
837 | super.dispose();
|
838 | }
|
839 | |
840 |
|
841 |
|
842 | hide() {
|
843 | super.hide();
|
844 | this.hidePopup();
|
845 | }
|
846 | |
847 |
|
848 |
|
849 | hidePopup() {
|
850 | this.popup.hide();
|
851 | }
|
852 | |
853 |
|
854 |
|
855 |
|
856 | updatePopup() {
|
857 | this.popup.updateWidth(this.parent.node.clientWidth);
|
858 | this.popup.alignTo(this.parent);
|
859 | }
|
860 | |
861 |
|
862 |
|
863 |
|
864 | widgetAt(index) {
|
865 | return this.popup.widgetAt(index);
|
866 | }
|
867 | |
868 |
|
869 |
|
870 |
|
871 |
|
872 | widgetCount() {
|
873 | return this.popup.widgetCount();
|
874 | }
|
875 | handleClick() {
|
876 | this.updatePopup();
|
877 | this.popup.setHidden(!this.popup.isHidden);
|
878 | }
|
879 | }
|
880 |
|
881 |
|
882 |
|
883 | var Private;
|
884 | (function (Private) {
|
885 | function propsFromCommand(options) {
|
886 | var _a, _b;
|
887 | const { commands, id, args } = options;
|
888 | const iconClass = commands.iconClass(id, args);
|
889 | const iconLabel = commands.iconLabel(id, args);
|
890 |
|
891 |
|
892 | const _icon = (_a = options.icon) !== null && _a !== void 0 ? _a : commands.icon(id, args);
|
893 | const icon = _icon === iconClass ? undefined : _icon;
|
894 | const label = commands.label(id, args);
|
895 | let className = commands.className(id, args);
|
896 |
|
897 | if (commands.isToggled(id, args)) {
|
898 | className += ' lm-mod-toggled';
|
899 | }
|
900 | if (!commands.isVisible(id, args)) {
|
901 | className += ' lm-mod-hidden';
|
902 | }
|
903 | let tooltip = commands.caption(id, args) || options.label || label || iconLabel;
|
904 |
|
905 | const binding = commands.keyBindings.find(b => b.command === id);
|
906 | if (binding) {
|
907 | const ks = CommandRegistry.formatKeystroke(binding.keys.join(' '));
|
908 | tooltip = `${tooltip} (${ks})`;
|
909 | }
|
910 | const onClick = () => {
|
911 | void commands.execute(id, args);
|
912 | };
|
913 | const enabled = commands.isEnabled(id, args);
|
914 | return {
|
915 | className,
|
916 | dataset: { 'data-command': options.id },
|
917 | icon,
|
918 | iconClass,
|
919 | tooltip,
|
920 | onClick,
|
921 | enabled,
|
922 | label: (_b = options.label) !== null && _b !== void 0 ? _b : label
|
923 | };
|
924 | }
|
925 | Private.propsFromCommand = propsFromCommand;
|
926 | |
927 |
|
928 |
|
929 | Private.nameProperty = new AttachedProperty({
|
930 | name: 'name',
|
931 | create: () => ''
|
932 | });
|
933 | |
934 |
|
935 |
|
936 | function noOp() {
|
937 |
|
938 | }
|
939 | Private.noOp = noOp;
|
940 | |
941 |
|
942 |
|
943 | class Spacer extends Widget {
|
944 | |
945 |
|
946 |
|
947 | constructor() {
|
948 | super();
|
949 | this.addClass(TOOLBAR_SPACER_CLASS);
|
950 | }
|
951 | }
|
952 | Private.Spacer = Spacer;
|
953 | |
954 |
|
955 |
|
956 |
|
957 |
|
958 |
|
959 | function KernelNameComponent(props) {
|
960 | const translator = props.translator || nullTranslator;
|
961 | const trans = translator.load('jupyterlab');
|
962 | const callback = () => {
|
963 | void props.dialogs.selectKernel(props.sessionContext, translator);
|
964 | };
|
965 | return (React.createElement(UseSignal, { signal: props.sessionContext.kernelChanged, initialSender: props.sessionContext }, sessionContext => (React.createElement(ToolbarButtonComponent, { className: TOOLBAR_KERNEL_NAME_CLASS, onClick: callback, tooltip: trans.__('Switch kernel'), label: sessionContext === null || sessionContext === void 0 ? void 0 : sessionContext.kernelDisplayName }))));
|
966 | }
|
967 | Private.KernelNameComponent = KernelNameComponent;
|
968 | |
969 |
|
970 |
|
971 | class KernelStatus extends Widget {
|
972 | |
973 |
|
974 |
|
975 | constructor(sessionContext, translator) {
|
976 | super();
|
977 | this.translator = translator || nullTranslator;
|
978 | this._trans = this.translator.load('jupyterlab');
|
979 | this.addClass(TOOLBAR_KERNEL_STATUS_CLASS);
|
980 | this._statusNames = translateKernelStatuses(this.translator);
|
981 | this._onStatusChanged(sessionContext);
|
982 | sessionContext.statusChanged.connect(this._onStatusChanged, this);
|
983 | sessionContext.connectionStatusChanged.connect(this._onStatusChanged, this);
|
984 | }
|
985 | |
986 |
|
987 |
|
988 | _onStatusChanged(sessionContext) {
|
989 | if (this.isDisposed) {
|
990 | return;
|
991 | }
|
992 | const status = sessionContext.kernelDisplayStatus;
|
993 | const circleIconProps = {
|
994 | container: this.node,
|
995 | title: this._trans.__('Kernel %1', this._statusNames[status] || status),
|
996 | stylesheet: 'toolbarButton',
|
997 | alignSelf: 'normal',
|
998 | height: '24px'
|
999 | };
|
1000 |
|
1001 | LabIcon.remove(this.node);
|
1002 | if (status === 'busy' ||
|
1003 | status === 'starting' ||
|
1004 | status === 'terminating' ||
|
1005 | status === 'restarting' ||
|
1006 | status === 'initializing') {
|
1007 | circleIcon.element(circleIconProps);
|
1008 | }
|
1009 | else if (status === 'connecting' ||
|
1010 | status === 'disconnected' ||
|
1011 | status === 'unknown') {
|
1012 | offlineBoltIcon.element(circleIconProps);
|
1013 | }
|
1014 | else {
|
1015 | circleEmptyIcon.element(circleIconProps);
|
1016 | }
|
1017 | }
|
1018 | }
|
1019 | Private.KernelStatus = KernelStatus;
|
1020 | })(Private || (Private = {}));
|
1021 |
|
\ | No newline at end of file |