瀏覽代碼

Implement a codemodel for the document registry

Steven Silvester 8 年之前
父節點
當前提交
f3337a73b6
共有 4 個文件被更改,包括 70 次插入49 次删除
  1. 27 29
      src/docregistry/default.ts
  2. 23 0
      src/docregistry/registry.ts
  3. 5 5
      src/editorwidget/plugin.ts
  4. 15 15
      src/editorwidget/widget.ts

+ 27 - 29
src/docregistry/default.ts

@@ -18,10 +18,18 @@ import {
   Widget
 } from 'phosphor/lib/ui/widget';
 
+import {
+  CodeEditor
+} from '../codeeditor';
+
 import {
   IChangedArgs
 } from '../common/interfaces';
 
+import {
+  IObservableString, ObservableString
+} from '../common/observablestring';
+
 import {
   DocumentRegistry
 } from './index';
@@ -31,30 +39,25 @@ import {
  * The default implementation of a document model.
  */
 export
-class DocumentModel implements DocumentRegistry.IModel {
+class DocumentModel extends CodeEditor.Model implements DocumentRegistry.ICodeModel  {
   /**
    * Construct a new document model.
    */
   constructor(languagePreference?: string) {
+    super();
     this._defaultLang = languagePreference || '';
+    this.value.changed.connect(this._onValueChanged, this);
   }
 
   /**
    * A signal emitted when the document content changes.
    */
-  contentChanged: ISignal<DocumentRegistry.IModel, void>;
+  contentChanged: ISignal<this, void>;
 
   /**
    * A signal emitted when the document state changes.
    */
-  stateChanged: ISignal<DocumentRegistry.IModel, IChangedArgs<any>>;
-
-  /**
-   * Get whether the model factory has been disposed.
-   */
-  get isDisposed(): boolean {
-    return this._isDisposed;
-  }
+  stateChanged: ISignal<this, IChangedArgs<any>>;
 
   /**
    * The dirty state of the document.
@@ -106,18 +109,11 @@ class DocumentModel implements DocumentRegistry.IModel {
     return this._defaultLang;
   }
 
-  /**
-   * Dispose of the resources held by the document manager.
-   */
-  dispose(): void {
-    this._isDisposed = true;
-  }
-
   /**
    * Serialize the model to a string.
    */
   toString(): string {
-    return this._text;
+    return this.value.text;
   }
 
   /**
@@ -127,19 +123,14 @@ class DocumentModel implements DocumentRegistry.IModel {
    * Should emit a [contentChanged] signal.
    */
   fromString(value: string): void {
-    if (this._text === value) {
-      return;
-    }
-    this._text = value;
-    this.contentChanged.emit(void 0);
-    this.dirty = true;
+    this.value.text = value;
   }
 
   /**
    * Serialize the model to JSON.
    */
   toJSON(): any {
-    return JSON.stringify(this._text);
+    return JSON.stringify(this.value.text);
   }
 
   /**
@@ -152,13 +143,20 @@ class DocumentModel implements DocumentRegistry.IModel {
     this.fromString(JSON.parse(value));
   }
 
-  private _text = '';
+  /**
+   * Handle a change to the observable value.
+   */
+  private _onValueChanged(sender: IObservableString, args: ObservableString.IChangedArgs): void {
+    this.contentChanged.emit(void 0);
+    this.dirty = true;
+  }
+
   private _defaultLang = '';
   private _dirty = false;
   private _readOnly = false;
-  private _isDisposed = false;
 }
 
+
 // Define the signals for the `DocumentModel` class.
 defineSignal(DocumentModel.prototype, 'contentChanged');
 defineSignal(DocumentModel.prototype, 'stateChanged');
@@ -168,7 +166,7 @@ defineSignal(DocumentModel.prototype, 'stateChanged');
  * An implementation of a model factory for text files.
  */
 export
-class TextModelFactory implements DocumentRegistry.ModelFactory {
+class TextModelFactory implements DocumentRegistry.CodeModelFactory {
   /**
    * The name of the model type.
    *
@@ -219,7 +217,7 @@ class TextModelFactory implements DocumentRegistry.ModelFactory {
    *
    * @returns A new document model.
    */
-  createNew(languagePreference?: string): DocumentRegistry.IModel {
+  createNew(languagePreference?: string): DocumentRegistry.ICodeModel {
     return new DocumentModel(languagePreference);
   }
 

+ 23 - 0
src/docregistry/registry.ts

@@ -33,6 +33,10 @@ import {
   Widget
 } from 'phosphor/lib/ui/widget';
 
+import {
+  CodeEditor
+} from '../codeeditor';
+
 import {
   IChangedArgs as IChangedArgsGeneric
 } from '../common/interfaces';
@@ -575,6 +579,12 @@ namespace DocumentRegistry {
     fromJSON(value: any): void;
   }
 
+  /**
+   * The interface for a document model that represents code.
+   */
+  export
+  interface ICodeModel extends IModel, CodeEditor.IModel { }
+
   /**
    * The document context object.
    */
@@ -724,6 +734,13 @@ namespace DocumentRegistry {
   export
   type Context = IContext<IModel>;
 
+
+  /**
+   * A type alias for a code context.
+   */
+  export
+  type CodeContext = IContext<ICodeModel>;
+
   /**
    * The options used to initialize a widget factory.
    */
@@ -855,6 +872,12 @@ namespace DocumentRegistry {
   export
   type ModelFactory = IModelFactory<IModel>;
 
+  /**
+   * A type alias for a code model factory.
+   */
+  export
+  type CodeModelFactory = IModelFactory<ICodeModel>;
+
   /**
    * A kernel preference for a given file path and widget.
    */

+ 5 - 5
src/editorwidget/plugin.ts

@@ -175,11 +175,11 @@ function activateEditorHandler(app: JupyterLab, registry: IDocumentRegistry, lay
         return;
       }
       // Get the selected code from the editor.
-      const editorModel = widget.editor.model;
-      const selection = widget.editor.getSelection();
-      const start = editorModel.getOffsetAt(selection.start);
-      const end = editorModel.getOffsetAt(selection.end);
-      const code = editorModel.value.text.substring(start, end);
+      const editor = widget.editor;
+      const selection = editor.getSelection();
+      const start = editor.getOffsetAt(selection.start);
+      const end = editor.getOffsetAt(selection.end);
+      const code = editor.model.value.text.substring(start, end);
       return commands.execute('console:inject', { id, code });
     },
     label: 'Run Code'

+ 15 - 15
src/editorwidget/widget.ts

@@ -98,7 +98,7 @@ class EditorWidget extends CodeEditorWidget {
     value.text = model.toString();
 
     // Prevent the initial loading from disk from being in the editor history.
-    editor.model.clearHistory();
+    editor.clearHistory();
     this._handleDirtyState();
 
     model.stateChanged.connect(this._onModelStateChanged, this);
@@ -183,7 +183,7 @@ namespace EditorWidget {
     /**
      * The document context associated with the editor.
      */
-    context: DocumentRegistry.Context;
+    context: DocumentRegistry.CodeContext;
   }
 }
 
@@ -192,34 +192,34 @@ namespace EditorWidget {
  * A widget factory for editors.
  */
 export
-class EditorWidgetFactory extends ABCWidgetFactory<EditorWidget, DocumentRegistry.IModel> {
+class EditorWidgetFactory extends ABCWidgetFactory<EditorWidget, DocumentRegistry.ICodeModel> {
   /**
    * Construct a new editor widget factory.
    */
   constructor(options: EditorWidgetFactory.IOptions) {
     super(options.factoryOptions);
-    this._mimeTypeService = options.editorServices.mimeTypeService;
-    let factory = options.editorServices.factory;
-    this._factory = (host: Widget) => factory.newDocumentEditor(host.node, {
-      lineNumbers: true,
-      readOnly: false,
-      wordWrap: true
-    });
+    this._services = options.editorServices;
   }
 
   /**
    * Create a new widget given a context.
    */
-  protected createNewWidget(context: DocumentRegistry.Context): EditorWidget {
+  protected createNewWidget(context: DocumentRegistry.CodeContext): EditorWidget {
+    let func = this._services.factory.newDocumentEditor
+    let factory = (host: Widget) => func(host.node, {
+      model: context.model,
+      lineNumbers: true,
+      readOnly: false,
+      wordWrap: true
+    });
     return new EditorWidget({
-      factory: this._factory,
+      factory,
       context,
-      mimeTypeService: this._mimeTypeService
+      mimeTypeService: this._services.mimeTypeService
     });
   }
 
-  private _mimeTypeService: IEditorMimeTypeService;
-  private _factory: (host: Widget) => CodeEditor.IEditor;
+  private _services: IEditorServices;
 }