@@ -2,10 +2,14 @@ import { NotebookPanel } from '@jupyterlab/notebook';
22
33import { CodeCell , MarkdownCell , Cell } from '@jupyterlab/cells' ;
44
5+ import * as React from 'react' ;
6+
57import {
68 WidgetTracker ,
79 CommandToolbarButton ,
810 IWidgetTracker ,
11+ Toolbar ,
12+ ReactWidget ,
913} from '@jupyterlab/apputils' ;
1014
1115import { CommandRegistry } from '@lumino/commands' ;
@@ -37,12 +41,20 @@ import { IDashboardModel, DashboardModel } from './model';
3741
3842import { CommandIDs } from './commands' ;
3943
44+ import { HTMLSelect } from '@jupyterlab/ui-components' ;
45+
4046// HTML element classes
4147
4248const DASHBOARD_CLASS = 'pr-JupyterDashboard' ;
4349
4450const DROP_TARGET_CLASS = 'pr-DropTarget' ;
4551
52+ const TOOLBAR_MODE_SWITCHER_CLASS = 'pr-ToolbarModeSwitcher' ;
53+
54+ const TOOLBAR_SELECT_CLASS = 'pr-ToolbarSelector' ;
55+
56+ const TOOLBAR_CLASS = 'pr-DashboardToolbar' ;
57+
4658export const IDashboardTracker = new Token < IDashboardTracker > (
4759 'jupyterlab-interactive-dashboard-editor'
4860) ;
@@ -387,6 +399,63 @@ export namespace Dashboard {
387399 }
388400}
389401
402+ export class DashboardDocument extends DocumentWidget < Dashboard > {
403+ constructor ( options : DashboardDocument . IOptions ) {
404+ let { content, reveal } = options ;
405+ const { context, commandRegistry } = options ;
406+ const model = context . model as DashboardModel ;
407+ content = content || new Dashboard ( { ...options , model, context } ) ;
408+ reveal = Promise . all ( [ reveal , context . ready ] ) ;
409+ super ( {
410+ ...options ,
411+ content : content as Dashboard ,
412+ reveal,
413+ } ) ;
414+
415+ // Build the toolbar
416+
417+ this . toolbar . addClass ( TOOLBAR_CLASS ) ;
418+
419+ const commands = commandRegistry ;
420+ const { save, undo, redo, cut, copy, paste, runOutput } = CommandIDs ;
421+
422+ const args = { toolbar : true , dashboardId : content . id } ;
423+
424+ const makeToolbarButton = (
425+ id : string ,
426+ tooltip : string
427+ ) : CommandToolbarButton => {
428+ const button = new CommandToolbarButton ( { args, commands, id } ) ;
429+ button . node . title = tooltip ;
430+ return button ;
431+ } ;
432+
433+ const saveButton = makeToolbarButton ( save , 'Save' ) ;
434+ const undoButton = makeToolbarButton ( undo , 'Undo' ) ;
435+ const redoButton = makeToolbarButton ( redo , 'Redo' ) ;
436+ const cutButton = makeToolbarButton ( cut , 'Cut the selected outputs' ) ;
437+ const copyButton = makeToolbarButton ( copy , 'Copy the selected outputs' ) ;
438+ const pasteButton = makeToolbarButton (
439+ paste ,
440+ 'Paste outputs from the clipboard'
441+ ) ;
442+ const runButton = makeToolbarButton ( runOutput , 'Run the selected outputs' ) ;
443+
444+ this . toolbar . addItem ( save , saveButton ) ;
445+ this . toolbar . addItem ( undo , undoButton ) ;
446+ this . toolbar . addItem ( redo , redoButton ) ;
447+ this . toolbar . addItem ( cut , cutButton ) ;
448+ this . toolbar . addItem ( copy , copyButton ) ;
449+ this . toolbar . addItem ( paste , pasteButton ) ;
450+ this . toolbar . addItem ( runOutput , runButton ) ;
451+ this . toolbar . addItem ( 'spacer' , Toolbar . createSpacerItem ( ) ) ;
452+ this . toolbar . addItem (
453+ 'switchMode' ,
454+ new DashboardDocument . DashboardModeSwitcher ( content as Dashboard )
455+ ) ;
456+ }
457+ }
458+
390459export namespace DashboardDocument {
391460 export interface IOptions extends DocumentWidget . IOptionsOptionalContent {
392461 /**
@@ -419,83 +488,53 @@ export namespace DashboardDocument {
419488 */
420489 dashboardHeight ?: number ;
421490 }
422- }
423491
424- export class DashboardDocument extends DocumentWidget < Dashboard > {
425- constructor ( options : DashboardDocument . IOptions ) {
426- let { content, reveal } = options ;
427- const { context, commandRegistry } = options ;
428- const model = context . model as DashboardModel ;
429- content = content || new Dashboard ( { ...options , model, context } ) ;
430- reveal = Promise . all ( [ reveal , context . ready ] ) ;
431- super ( {
432- ...options ,
433- content : content as Dashboard ,
434- reveal,
435- } ) ;
436-
437- // Build the toolbar
438-
439- const commands = commandRegistry ;
440- const {
441- save,
442- undo,
443- redo,
444- cut,
445- copy,
446- paste,
447- runOutput,
448- startFullscreen,
449- toggleMode,
450- } = CommandIDs ;
451-
452- const args = { toolbar : true , dashboardId : content . id } ;
492+ export class DashboardModeSwitcher extends ReactWidget {
493+ constructor ( dashboard : Dashboard ) {
494+ super ( ) ;
495+ this . addClass ( TOOLBAR_MODE_SWITCHER_CLASS ) ;
496+ this . _dashboard = dashboard ;
453497
454- this . toolbar . addItem (
455- 'save' ,
456- new CommandToolbarButton ( { args, commands, id : save } )
457- ) ;
458- this . toolbar . addItem (
459- 'undo' ,
460- new CommandToolbarButton ( { args, commands, id : undo } )
461- ) ;
462- this . toolbar . addItem (
463- 'redo' ,
464- new CommandToolbarButton ( { args, commands, id : redo } )
465- ) ;
466- this . toolbar . addItem (
467- 'cut' ,
468- new CommandToolbarButton ( { args, commands, id : cut } )
469- ) ;
470- this . toolbar . addItem (
471- 'copy' ,
472- new CommandToolbarButton ( { args, commands, id : copy } )
473- ) ;
474- this . toolbar . addItem (
475- 'paste' ,
476- new CommandToolbarButton ( { args, commands, id : paste } )
477- ) ;
478- this . toolbar . addItem (
479- 'runOutput' ,
480- new CommandToolbarButton ( { args, commands, id : runOutput } )
481- ) ;
482- this . toolbar . addItem (
483- 'startFullscreen' ,
484- new CommandToolbarButton ( { args, commands, id : startFullscreen } )
485- ) ;
486- this . toolbar . addItem (
487- 'toggleMode' ,
488- new CommandToolbarButton ( { args, commands, id : toggleMode } )
489- ) ;
498+ if ( dashboard . model ) {
499+ this . update ( ) ;
500+ }
490501
491- // Listen to toggle the icon on the mode switch button.
492- context . ready . then ( ( ) => {
493- model . stateChanged . connect ( ( _sender , change ) => {
502+ dashboard . model . stateChanged . connect ( ( _sender , change ) => {
494503 if ( change . name === 'mode' ) {
495- commandRegistry . notifyCommandChanged ( toggleMode ) ;
504+ this . update ( ) ;
496505 }
497506 } , this ) ;
498- } ) ;
507+ }
508+
509+ private _handleChange (
510+ that : DashboardModeSwitcher
511+ ) : ( event : React . ChangeEvent < HTMLSelectElement > ) => void {
512+ return ( event : React . ChangeEvent < HTMLSelectElement > ) : void => {
513+ that . dashboard . model . mode = event . target . value as Dashboard . Mode ;
514+ } ;
515+ }
516+
517+ render ( ) : JSX . Element {
518+ const value = this . _dashboard . model . mode ;
519+ return (
520+ < HTMLSelect
521+ className = { TOOLBAR_SELECT_CLASS }
522+ onChange = { this . _handleChange ( this ) }
523+ value = { value }
524+ aria-label = { 'Mode' }
525+ >
526+ < option value = "present" > Present</ option >
527+ < option value = "edit" > Free Layout</ option >
528+ < option value = "grid" > Tile Layout</ option >
529+ </ HTMLSelect >
530+ ) ;
531+ }
532+
533+ get dashboard ( ) : Dashboard {
534+ return this . _dashboard ;
535+ }
536+
537+ private _dashboard : Dashboard ;
499538 }
500539}
501540
0 commit comments