Browse Source

WIP converting code to use IDocumentWidget

Jason Grout 7 years ago
parent
commit
0ff19f6366

+ 2 - 1
packages/csvviewer-extension/package.json

@@ -31,7 +31,8 @@
   "dependencies": {
     "@jupyterlab/application": "^0.16.2",
     "@jupyterlab/apputils": "^0.16.3",
-    "@jupyterlab/csvviewer": "^0.16.2"
+    "@jupyterlab/csvviewer": "^0.16.2",
+    "@jupyterlab/docregistry": "^0.16.2"
   },
   "devDependencies": {
     "rimraf": "~2.6.2",

+ 4 - 1
packages/csvviewer-extension/src/index.ts

@@ -13,6 +13,9 @@ import {
   CSVViewer, CSVViewerFactory
 } from '@jupyterlab/csvviewer';
 
+import {
+  IDocumentWidget
+} from '@jupyterlab/docregistry';
 
 /**
  * The name of the factory that creates CSV widgets.
@@ -47,7 +50,7 @@ function activate(app: JupyterLab, restorer: ILayoutRestorer): void {
     defaultFor: ['csv'],
     readOnly: true
   });
-  const tracker = new InstanceTracker<CSVViewer>({ namespace: 'csvviewer' });
+  const tracker = new InstanceTracker<IDocumentWidget<CSVViewer>>({ namespace: 'csvviewer' });
 
   // Handle state restoration.
   restorer.restore(tracker, {

+ 7 - 5
packages/csvviewer/src/widget.ts

@@ -6,7 +6,7 @@ import {
 } from '@jupyterlab/coreutils';
 
 import {
-  ABCWidgetFactory, DocumentRegistry
+  ABCWidgetFactory, DocumentRegistry, IDocumentWidget, DocumentWidget
 } from '@jupyterlab/docregistry';
 
 import {
@@ -58,7 +58,7 @@ const RENDER_TIMEOUT = 1000;
  * A viewer for CSV tables.
  */
 export
-class CSVViewer extends Widget implements DocumentRegistry.IReadyWidget {
+class CSVViewer extends Widget {
   /**
    * Construct a new CSV viewer.
    */
@@ -186,11 +186,13 @@ namespace CSVViewer {
  * A widget factory for CSV widgets.
  */
 export
-class CSVViewerFactory extends ABCWidgetFactory<CSVViewer, DocumentRegistry.IModel> {
+class CSVViewerFactory extends ABCWidgetFactory<IDocumentWidget<CSVViewer>, DocumentRegistry.IModel> {
   /**
    * Create a new widget given a context.
    */
-  protected createNewWidget(context: DocumentRegistry.Context): CSVViewer {
-    return new CSVViewer({ context });
+  protected createNewWidget(context: DocumentRegistry.Context): IDocumentWidget<CSVViewer> {
+    const content = new CSVViewer({ context });
+    const widget = new DocumentWidget({ content, context });
+    return widget;
   }
 }

+ 9 - 9
packages/docmanager/src/manager.ts

@@ -11,7 +11,7 @@ import {
 } from '@jupyterlab/coreutils';
 
 import {
-  DocumentRegistry, Context
+  DocumentRegistry, Context, IDocumentWidget
 } from '@jupyterlab/docregistry';
 
 import {
@@ -19,7 +19,7 @@ import {
 } from '@jupyterlab/services';
 
 import {
-  ArrayExt, find, filter
+  ArrayExt, find
 } from '@phosphor/algorithm';
 
 import {
@@ -171,7 +171,7 @@ class DocumentManager implements IDisposable {
    *  Uses the same widget factory and context as the source, or returns
    *  `undefined` if the source widget is not managed by this manager.
    */
-  cloneWidget(widget: Widget): DocumentRegistry.IReadyWidget | undefined {
+  cloneWidget(widget: Widget): IDocumentWidget | undefined {
     return this._widgetManager.cloneWidget(widget);
   }
 
@@ -275,7 +275,7 @@ class DocumentManager implements IDisposable {
    * This can be used to find an existing widget instead of opening
    * a new widget.
    */
-  findWidget(path: string, widgetName='default'): DocumentRegistry.IReadyWidget | undefined {
+  findWidget(path: string, widgetName='default'): IDocumentWidget | undefined {
     if (widgetName === 'default') {
       let factory = this.registry.defaultWidgetFactory(path);
       if (!factory) {
@@ -320,7 +320,7 @@ class DocumentManager implements IDisposable {
    * This function will return `undefined` if a valid widget factory
    * cannot be found.
    */
-  open(path: string, widgetName='default', kernel?: Partial<Kernel.IModel>, options?: DocumentRegistry.IOpenOptions ): DocumentRegistry.IReadyWidget | undefined {
+  open(path: string, widgetName='default', kernel?: Partial<Kernel.IModel>, options?: DocumentRegistry.IOpenOptions ): IDocumentWidget | undefined {
     return this._createOrOpenDocument('open', path, widgetName, kernel, options);
   }
 
@@ -340,7 +340,7 @@ class DocumentManager implements IDisposable {
    * This function will return `undefined` if a valid widget factory
    * cannot be found.
    */
-  openOrReveal(path: string, widgetName='default', kernel?: Partial<Kernel.IModel>, options?: DocumentRegistry.IOpenOptions ): DocumentRegistry.IReadyWidget | undefined {
+  openOrReveal(path: string, widgetName='default', kernel?: Partial<Kernel.IModel>, options?: DocumentRegistry.IOpenOptions ): IDocumentWidget | undefined {
     let widget = this.findWidget(path, widgetName);
     if (widget) {
       this._opener.open(widget, options || {});
@@ -418,7 +418,7 @@ class DocumentManager implements IDisposable {
     // widgets that have different models.
 
     // Allow options to be passed when adding a sibling.
-    let adopter = (widget: DocumentRegistry.IReadyWidget, options?: DocumentRegistry.IOpenOptions) => {
+    let adopter = (widget: IDocumentWidget, options?: DocumentRegistry.IOpenOptions) => {
       this._widgetManager.adoptWidget(context, widget);
       this._opener.open(widget, options);
     };
@@ -474,7 +474,7 @@ class DocumentManager implements IDisposable {
    * The two cases differ in how the document context is handled, but the creation
    * of the widget and launching of the kernel are identical.
    */
-  private _createOrOpenDocument(which: 'open'|'create', path: string, widgetName='default', kernel?: Partial<Kernel.IModel>, options?: DocumentRegistry.IOpenOptions): DocumentRegistry.IReadyWidget | undefined {
+  private _createOrOpenDocument(which: 'open'|'create', path: string, widgetName='default', kernel?: Partial<Kernel.IModel>, options?: DocumentRegistry.IOpenOptions): IDocumentWidget | undefined {
     let widgetFactory = this._widgetFactoryFor(path, widgetName);
     if (!widgetFactory) {
       return undefined;
@@ -574,7 +574,7 @@ namespace DocumentManager {
     /**
      * Open the given widget.
      */
-    open(widget: DocumentRegistry.IReadyWidget, options?: DocumentRegistry.IOpenOptions): void;
+    open(widget: IDocumentWidget, options?: DocumentRegistry.IOpenOptions): void;
   }
 }
 

+ 6 - 6
packages/docmanager/src/widgetmanager.ts

@@ -34,7 +34,7 @@ import {
 } from '@jupyterlab/apputils';
 
 import {
-  DocumentRegistry
+  DocumentRegistry, IDocumentWidget
 } from '@jupyterlab/docregistry';
 
 import {
@@ -96,7 +96,7 @@ class DocumentWidgetManager implements IDisposable {
    *
    * @throws If the factory is not registered.
    */
-  createWidget(factory: DocumentRegistry.WidgetFactory, context: DocumentRegistry.Context): DocumentRegistry.IReadyWidget {
+  createWidget(factory: DocumentRegistry.WidgetFactory, context: DocumentRegistry.Context): IDocumentWidget {
     let widget = factory.createNew(context);
     Private.factoryProperty.set(widget, factory);
 
@@ -125,7 +125,7 @@ class DocumentWidgetManager implements IDisposable {
    *
    * @param widget - The widget to adopt.
    */
-  adoptWidget(context: DocumentRegistry.Context, widget: DocumentRegistry.IReadyWidget): void {
+  adoptWidget(context: DocumentRegistry.Context, widget: IDocumentWidget): void {
     let widgets = Private.widgetsProperty.get(context);
     widgets.push(widget);
     MessageLoop.installMessageHook(widget, this);
@@ -146,7 +146,7 @@ class DocumentWidgetManager implements IDisposable {
    * This can be used to use an existing widget instead of opening
    * a new widget.
    */
-  findWidget(context: DocumentRegistry.Context, widgetName: string): DocumentRegistry.IReadyWidget | undefined {
+  findWidget(context: DocumentRegistry.Context, widgetName: string): IDocumentWidget | undefined {
     let widgets = Private.widgetsProperty.get(context);
     if (!widgets) {
       return undefined;
@@ -182,7 +182,7 @@ class DocumentWidgetManager implements IDisposable {
    *  Uses the same widget factory and context as the source, or throws
    *  if the source widget is not managed by this manager.
    */
-  cloneWidget(widget: Widget): DocumentRegistry.IReadyWidget | undefined {
+  cloneWidget(widget: Widget): IDocumentWidget | undefined {
     let context = Private.contextProperty.get(widget);
     if (!context) {
       return undefined;
@@ -448,7 +448,7 @@ namespace Private {
    * A private attached property for the widgets associated with a context.
    */
   export
-  const widgetsProperty = new AttachedProperty<DocumentRegistry.Context, DocumentRegistry.IReadyWidget[]>({
+  const widgetsProperty = new AttachedProperty<DocumentRegistry.Context, IDocumentWidget[]>({
     name: 'widgets',
     create: () => []
   });

+ 1 - 1
packages/docregistry/src/default.ts

@@ -22,7 +22,7 @@ import {
 } from '@phosphor/widgets';
 
 import {
-  Toolbar, MainAreaWidget
+  MainAreaWidget
 } from '@jupyterlab/apputils';
 
 import {

+ 10 - 8
packages/docregistry/src/mimedocument.ts

@@ -2,11 +2,11 @@
 // Distributed under the terms of the Modified BSD License.
 
 import {
-  showErrorMessage, MainAreaWidget
+  showErrorMessage
 } from '@jupyterlab/apputils';
 
 import {
-  ActivityMonitor, PathExt
+  ActivityMonitor
 } from '@jupyterlab/coreutils';
 
 import {
@@ -22,7 +22,7 @@ import {
 } from '@phosphor/messaging';
 
 import {
-  SingletonLayout, Widget
+  PanelLayout, Widget
 } from '@phosphor/widgets';
 
 import {
@@ -50,8 +50,10 @@ class MimeContent extends Widget {
     this._context = options.context;
     this._renderer = options.renderer;
 
-    const layout = new SingletonLayout();
-    layout.widget = this._renderer;
+    // TODO: Use SingletonLayout when a new version of phosphor is released. See
+    // https://github.com/phosphorjs/phosphor/issues/337
+    const layout = new PanelLayout();
+    layout.addWidget(this._renderer);
     this.layout = layout;
 
     this._context.ready.then(() => {
@@ -186,7 +188,7 @@ namespace MimeContent {
    * The options used to initialize a MimeDocument.
    */
   export
-  interface IOptions extends DocumentWidget.IOptions<IRenderMime.IRenderer> {
+  interface IOptions {
     /**
      * Context
      */
@@ -234,7 +236,7 @@ class MimeDocumentFactory extends ABCWidgetFactory<IDocumentWidget<MimeContent>,
   /**
    * Create a new widget given a context.
    */
-  protected createNewWidget(context: DocumentRegistry.Context): MainAreaWidget {
+  protected createNewWidget(context: DocumentRegistry.Context): IDocumentWidget<MimeContent> {
     const ft = this._fileType;
     const mimeType = ft.mimeTypes.length ? ft.mimeTypes[0] : 'text/plain';
 
@@ -254,7 +256,7 @@ class MimeDocumentFactory extends ABCWidgetFactory<IDocumentWidget<MimeContent>,
     content.title.iconClass = ft.iconClass;
     content.title.iconLabel = ft.iconLabel;
 
-    const widget = new DocumentWidget({content});
+    const widget = new DocumentWidget({ content, context });
 
     return widget;
   }

+ 1 - 1
packages/docregistry/src/registry.ts

@@ -1188,7 +1188,7 @@ namespace DocumentRegistry {
 export
 interface IDocumentWidget<T extends Widget = Widget, U extends DocumentRegistry.IModel = DocumentRegistry.IModel> extends Widget {
   readonly content: T;
-  readonly populated: Promise<void>;
+  readonly ready: Promise<void>;
   readonly context: DocumentRegistry.IContext<U>;
   readonly toolbar: Toolbar<Widget>;
 }

+ 1 - 0
packages/fileeditor-extension/package.json

@@ -35,6 +35,7 @@
     "@jupyterlab/codeeditor": "^0.16.1",
     "@jupyterlab/console": "^0.16.2",
     "@jupyterlab/coreutils": "^1.1.2",
+    "@jupyterlab/docregistry": "^0.16.2",
     "@jupyterlab/filebrowser": "^0.16.2",
     "@jupyterlab/fileeditor": "^0.16.2",
     "@jupyterlab/launcher": "^0.16.2",

+ 24 - 20
packages/fileeditor-extension/src/index.ts

@@ -21,6 +21,10 @@ import {
   ISettingRegistry, MarkdownCodeBlocks, PathExt
 } from '@jupyterlab/coreutils';
 
+import {
+  IDocumentWidget
+} from '@jupyterlab/docregistry';
+
 import {
   IFileBrowserFactory
 } from '@jupyterlab/filebrowser';
@@ -119,7 +123,7 @@ function activate(app: JupyterLab, consoleTracker: IConsoleTracker, editorServic
     factoryOptions: { name: FACTORY, fileTypes: ['*'], defaultFor: ['*'] }
   });
   const { commands, restored } = app;
-  const tracker = new InstanceTracker<FileEditor>({ namespace });
+  const tracker = new InstanceTracker<IDocumentWidget<FileEditor>>({ namespace });
   const isEnabled = () => tracker.currentWidget !== null &&
                           tracker.currentWidget === app.shell.currentWidget;
 
@@ -148,7 +152,7 @@ function activate(app: JupyterLab, consoleTracker: IConsoleTracker, editorServic
    * Update the settings of the current tracker instances.
    */
   function updateTracker(): void {
-    tracker.forEach(widget => { updateWidget(widget); });
+    tracker.forEach(widget => { updateWidget(widget.content); });
   }
 
   /**
@@ -180,13 +184,13 @@ function activate(app: JupyterLab, consoleTracker: IConsoleTracker, editorServic
     // Notify the instance tracker if restore data needs to update.
     widget.context.pathChanged.connect(() => { tracker.save(widget); });
     tracker.add(widget);
-    updateWidget(widget);
+    updateWidget(widget.content);
   });
   app.docRegistry.addWidgetFactory(factory);
 
   // Handle the settings of new widgets.
   tracker.widgetAdded.connect((sender, widget) => {
-    updateWidget(widget);
+    updateWidget(widget.content);
   });
 
   commands.addCommand(CommandIDs.lineNumbers, {
@@ -282,7 +286,7 @@ function activate(app: JupyterLab, consoleTracker: IConsoleTracker, editorServic
   commands.addCommand(CommandIDs.runCode, {
     execute: () => {
       // Run the appropriate code, taking into account a ```fenced``` code block.
-      const widget = tracker.currentWidget;
+      const widget = tracker.currentWidget.content;
 
       if (!widget) {
         return;
@@ -428,29 +432,29 @@ function activate(app: JupyterLab, consoleTracker: IConsoleTracker, editorServic
     // Add undo/redo hooks to the edit menu.
     menu.editMenu.undoers.add({
       tracker,
-      undo: widget => { widget.editor.undo(); },
-      redo: widget => { widget.editor.redo(); }
-    } as IEditMenu.IUndoer<FileEditor>);
+      undo: widget => { widget.content.editor.undo(); },
+      redo: widget => { widget.content.editor.redo(); }
+    } as IEditMenu.IUndoer<IDocumentWidget<FileEditor>>);
 
     // Add editor view options.
     menu.viewMenu.editorViewers.add({
       tracker,
       toggleLineNumbers: widget => {
-        const lineNumbers = !widget.editor.getOption('lineNumbers');
-        widget.editor.setOption('lineNumbers', lineNumbers);
+        const lineNumbers = !widget.content.editor.getOption('lineNumbers');
+        widget.content.editor.setOption('lineNumbers', lineNumbers);
       },
       toggleWordWrap: widget => {
-        const wordWrap = !widget.editor.getOption('lineWrap');
-        widget.editor.setOption('lineWrap', wordWrap);
+        const wordWrap = !widget.content.editor.getOption('lineWrap');
+        widget.content.editor.setOption('lineWrap', wordWrap);
       },
       toggleMatchBrackets: widget => {
-        const matchBrackets = !widget.editor.getOption('matchBrackets');
-        widget.editor.setOption('matchBrackets', matchBrackets);
+        const matchBrackets = !widget.content.editor.getOption('matchBrackets');
+        widget.content.editor.setOption('matchBrackets', matchBrackets);
       },
-      lineNumbersToggled: widget => widget.editor.getOption('lineNumbers'),
-      wordWrapToggled: widget => widget.editor.getOption('lineWrap'),
-      matchBracketsToggled: widget => widget.editor.getOption('matchBrackets')
-    } as IViewMenu.IEditorViewer<FileEditor>);
+      lineNumbersToggled: widget => widget.content.editor.getOption('lineNumbers'),
+      wordWrapToggled: widget => widget.content.editor.getOption('lineWrap'),
+      matchBracketsToggled: widget => widget.content.editor.getOption('matchBrackets')
+    } as IViewMenu.IEditorViewer<IDocumentWidget<FileEditor>>);
 
     // Add a console creator the the Kernel menu.
     menu.fileMenu.consoleCreators.add({
@@ -463,7 +467,7 @@ function activate(app: JupyterLab, consoleTracker: IConsoleTracker, editorServic
         };
         return commands.execute('console:create', options);
       }
-    } as IFileMenu.IConsoleCreator<FileEditor>);
+    } as IFileMenu.IConsoleCreator<IDocumentWidget<FileEditor>>);
 
     // Add a code runner to the Run menu.
     menu.runMenu.codeRunners.add({
@@ -479,7 +483,7 @@ function activate(app: JupyterLab, consoleTracker: IConsoleTracker, editorServic
         return found;
       },
       run: () => commands.execute(CommandIDs.runCode)
-    } as IRunMenu.ICodeRunner<FileEditor>);
+    } as IRunMenu.ICodeRunner<IDocumentWidget<FileEditor>>);
   }
 
   app.contextMenu.addItem({

+ 5 - 4
packages/fileeditor/src/widget.ts

@@ -10,7 +10,7 @@ import {
 } from '@jupyterlab/coreutils';
 
 import {
-  ABCWidgetFactory, DocumentRegistry
+  ABCWidgetFactory, DocumentRegistry, DocumentWidget, IDocumentWidget
 } from '@jupyterlab/docregistry';
 
 import {
@@ -343,7 +343,7 @@ namespace FileEditor {
  * A widget factory for editors.
  */
 export
-class FileEditorFactory extends ABCWidgetFactory<FileEditor, DocumentRegistry.ICodeModel> {
+class FileEditorFactory extends ABCWidgetFactory<IDocumentWidget<FileEditor>, DocumentRegistry.ICodeModel> {
   /**
    * Construct a new editor widget factory.
    */
@@ -355,16 +355,17 @@ class FileEditorFactory extends ABCWidgetFactory<FileEditor, DocumentRegistry.IC
   /**
    * Create a new widget given a context.
    */
-  protected createNewWidget(context: DocumentRegistry.CodeContext): FileEditor {
+  protected createNewWidget(context: DocumentRegistry.CodeContext): IDocumentWidget<FileEditor> {
     let func = this._services.factoryService.newDocumentEditor;
     let factory: CodeEditor.Factory = options => {
       return func(options);
     };
-    return new FileEditor({
+    const content = new FileEditor({
       factory,
       context,
       mimeTypeService: this._services.mimeTypeService
     });
+    const widget = new DocumentWidget({ content, context })
   }
 
   private _services: IEditorServices;