浏览代码

Convert the filebrowser to use the docmanager

Steven Silvester 9 年之前
父节点
当前提交
1d396eb4e3
共有 5 个文件被更改,包括 129 次插入64 次删除
  1. 10 18
      examples/filebrowser/src/index.ts
  2. 81 5
      src/docmanager/index.ts
  3. 17 13
      src/filebrowser/browser.ts
  4. 13 20
      src/filebrowser/buttons.ts
  5. 8 8
      src/filebrowser/listing.ts

+ 10 - 18
examples/filebrowser/src/index.ts

@@ -9,14 +9,14 @@ import {
   ContentsManager, ISessionOptions, NotebookSessionManager
 } from 'jupyter-js-services';
 
-import {
-  FileHandler, FileHandlerRegistry, FileCreator, DirectoryCreator
-} from 'jupyter-js-ui/lib/filehandler';
-
 import {
   FileBrowserWidget, FileBrowserModel
 } from 'jupyter-js-ui/lib/filebrowser';
 
+import {
+  DocumentManager
+} from 'jupyter-js-ui/lib/docmanager';
+
 import {
   showDialog, okButton
 } from 'jupyter-js-ui/lib/dialog';
@@ -63,21 +63,12 @@ function main(): void {
   let sessionsManager = new NotebookSessionManager({ baseUrl: baseUrl });
 
   let fbModel = new FileBrowserModel(contentsManager, sessionsManager);
-  let registry = new FileHandlerRegistry();
-  let fileHandler = new FileHandler(contentsManager);
-
-  registry.addDefaultHandler(fileHandler);
-
-  let fbWidget = new FileBrowserWidget(fbModel, registry);
+  let docManager = new DocumentManager();
 
-  let dirCreator = new DirectoryCreator(contentsManager);
-  let fileCreator = new FileCreator(contentsManager);
-  registry.addCreator(
-    'New Directory', dirCreator.createNew.bind(dirCreator));
-  registry.addCreator('New File', fileCreator.createNew.bind(fileCreator));
+  let fbWidget = new FileBrowserWidget(fbModel, docManager);
 
   let widgets: CodeMirrorWidget[] = [];
-  registry.opened.connect((r, widget) => {
+  docManager.opened.connect((r, widget) => {
     dock.insertTabAfter(widget);
     widgets.push(widget as CodeMirrorWidget);
   });
@@ -129,8 +120,9 @@ function main(): void {
     sequence: ['Accel S'],
     selector: '.jp-CodeMirrorWidget',
     handler: () => {
-      let path = fileHandler.findPath(activeWidget);
-      fileHandler.save(path);
+      // TODO
+      //let path = fileHandler.findPath(activeWidget);
+      //fileHandler.save(path);
       return true;
     }
   }]);

+ 81 - 5
src/docmanager/index.ts

@@ -43,7 +43,7 @@ export interface IDocumentModel {
   deserialize(value: any): void;
 
   /**
-   * The default kernel name for the the document.
+   * The default kernel name for the document.
    *
    * #### Notes
    * This is a read-only property.
@@ -90,6 +90,11 @@ export interface IDocumentContext {
    */
   pathChanged: ISignal<IDocumentContext, string>;
 
+  /**
+   * A signal emitted when the model is saved or reverted.
+   */
+  dirtyCleared: ISignal<IDocumentContext, void>;
+
   /**
    * The current kernel associated with the document.
    *
@@ -112,7 +117,7 @@ export interface IDocumentContext {
   changeKernel(options: IKernelId): Promise<IKernel>;
 
   /**
-   * Save the the document contents to disk.
+   * Save the document contents to disk.
    */
   save(): Promise<void>;
 
@@ -230,6 +235,17 @@ interface IModelFactoryOptions {
  */
 export
 class DocumentManager {
+
+  /**
+   * Construct a new document manager.
+   */
+  constructor() {
+    this._fileTypes['File'] = {
+      extensions: [],
+      canCreate: true
+    }
+  }
+
   /**
    * A signal emitted when a file is opened.
    */
@@ -270,6 +286,39 @@ class DocumentManager {
     return void 0;
   }
 
+  /**
+   * Register a file type.
+   *
+   * @param fileType - the name of the file type.
+   *
+   * @param extensions - a list of file extensions to associate with the type.
+   *
+   * @param canCreate - whether a file type can be used by [createNew].
+   *
+   * @returns A disposable which can be used to unregister the file type.
+   *
+   * #### Notes
+   * The default fileType is 'File', will be used when no matching extensions
+   * are found and can be used to create new files.
+   */
+  registerFileType(fileType: string, extensions: string[], canCreate=false): IDisposable {
+    this._fileTypes[fileType] = {
+      extensions,
+      canCreate
+    }
+    return void 0;
+  }
+
+  /**
+   * List of the registered file types.
+   *
+   * #### Notes
+   * This is a read-only property.
+   */
+  get fileTypes(): string[] {
+    return Object.keys(this._fileTypes);
+  }
+
   /**
    * Open a file and return the widget used to display the contents.
    *
@@ -328,18 +377,22 @@ class DocumentManager {
    *
    * @param fileType - The type of file to create.
    *
+   * @param path - The directory in which to create the file.
+   *
    * @returns A Promise that resolves with the created widget.
    *
    * #### Notes
   * Emits an [opened] signal when the widget is populated.
    */
-  createNew(fileType: string): Promise<Widget> {
+  createNew(fileType: string, path: string): Promise<Widget> {
     return void 0;
   }
 
   /**
    * Create a new file with a dialog asking for options.
    *
+   * @param path - The directory in which to create the file.
+   *
    * @param host - The host node used to display the dialog.
    *
    * @returns A Promise that resolves with the created widget.
@@ -347,7 +400,7 @@ class DocumentManager {
    * #### Notes
    * Emits an [opened] signal when the widget is populated.
    */
-  createNewAdvanced(host=document.body): Promise<Widget> {
+  createNewAdvanced(path: string, host=document.body): Promise<Widget> {
     // Create dialog
 
     // -------------------------------------------
@@ -389,10 +442,24 @@ class DocumentManager {
     // dispose everything in the path->(model, session, context, [list,of,widgets]) mapping for the path (disposing a session should not shut down the kernel - needs change in notebook server)
   }
 
+  /**
+   * Save the document contents to disk.
+   */
+  saveFile(path: string): Promise<void> {
+    return void 0;
+  }
+
+  /**
+   * Revert the document contents to disk contents.
+   */
+  revertFile(path: string): Promise<void> {
+    return void 0;
+  }
+
   /**
    * Close the widgets associated with a given path.
    */
-  close(path: string): void {
+  closeFile(path: string): void {
 
   }
 
@@ -411,6 +478,7 @@ class DocumentManager {
   }
 
   private _data: { [key: string]: Private.IDocumentData } = Object.create(null);
+  private _fileTypes: { [key: string ]: Private.IFileType} = Object.create(null);
 }
 
 
@@ -435,4 +503,12 @@ namespace Private {
     widgets: Widget[];
   }
 
+  /**
+   * A file type registry entry.
+   */
+  export
+  interface IFileType {
+    extensions: string[];
+    canCreate: boolean;
+  }
 }

+ 17 - 13
src/filebrowser/browser.ts

@@ -22,8 +22,8 @@ import {
 } from 'phosphor-widget';
 
 import {
-  FileHandlerRegistry
-} from '../filehandler';
+  DocumentManager
+} from '../docmanager';
 
 import {
   FileButtons
@@ -81,18 +81,22 @@ class FileBrowserWidget extends Widget {
    *
    * @param model - The file browser view model.
    */
-  constructor(model: FileBrowserModel, registry: FileHandlerRegistry) {
+  constructor(model: FileBrowserModel, manager: DocumentManager) {
     super();
     this.addClass(FILE_BROWSER_CLASS);
     this._model = model;
     this._model.refreshed.connect(this._handleRefresh, this);
     this._crumbs = new BreadCrumbs(model);
-    this._buttons = new FileButtons(model, registry);
-    this._listing = new DirListing(model, registry);
-    this._registry = registry;
+    this._buttons = new FileButtons(model, manager);
+    this._listing = new DirListing(model, manager);
+    this._manager = manager;
 
     model.fileChanged.connect((fbModel, args) => {
-      registry.rename(args.oldValue, args.newValue);
+      if (args.newValue) {
+        manager.renameFile(args.oldValue, args.newValue);
+      } else {
+        manager.deleteFile(args.oldValue);
+      }
     });
 
     this._crumbs.addClass(CRUMBS_CLASS);
@@ -126,7 +130,7 @@ class FileBrowserWidget extends Widget {
     this._crumbs = null;
     this._buttons = null;
     this._listing = null;
-    this._registry = null;
+    this._manager = null;
     super.dispose();
   }
 
@@ -155,7 +159,7 @@ class FileBrowserWidget extends Widget {
           showErrorMessage(this, 'Open directory', error)
         );
       } else {
-        this._registry.open(item.path);
+        this._manager.open(item.path);
       }
     }
   }
@@ -170,7 +174,7 @@ class FileBrowserWidget extends Widget {
         continue;
       }
       if (item.type !== 'directory') {
-        this._registry.revert(item.path);
+        this._manager.revertFile(item.path);
       }
     }
   }
@@ -185,7 +189,7 @@ class FileBrowserWidget extends Widget {
         continue;
       }
       if (item.type !== 'directory') {
-        this._registry.save(item.path);
+        this._manager.saveFile(item.path);
       }
     }
   }
@@ -200,7 +204,7 @@ class FileBrowserWidget extends Widget {
         continue;
       }
       if (item.type !== 'directory') {
-        this._registry.close(item.path);
+        this._manager.closeFile(item.path);
       }
     }
   }
@@ -320,5 +324,5 @@ class FileBrowserWidget extends Widget {
   private _buttons: FileButtons = null;
   private _listing: DirListing = null;
   private _timeoutId = -1;
-  private _registry: FileHandlerRegistry = null;
+  private _manager: DocumentManager = null;
 }

+ 13 - 20
src/filebrowser/buttons.ts

@@ -19,8 +19,8 @@ import {
 } from '../dialog';
 
 import {
-  FileHandlerRegistry
-} from '../filehandler';
+  DocumentManager
+} from '../docmanager';
 
 import {
   FileBrowserModel
@@ -86,7 +86,7 @@ class FileButtons extends Widget {
    *
    * @param model - The file browser view model.
    */
-  constructor(model: FileBrowserModel, registry: FileHandlerRegistry) {
+  constructor(model: FileBrowserModel, manager: DocumentManager) {
     super();
     this.addClass(FILE_BUTTONS_CLASS);
     this._model = model;
@@ -101,7 +101,7 @@ class FileButtons extends Widget {
     node.appendChild(this._buttons.upload);
     node.appendChild(this._buttons.refresh);
 
-    this._registry = registry;
+    this._manager = manager;
   }
 
   /**
@@ -111,7 +111,7 @@ class FileButtons extends Widget {
     this._model = null;
     this._buttons = null;
     this._input = null;
-    this._registry = null;
+    this._manager = null;
     super.dispose();
   }
 
@@ -126,10 +126,10 @@ class FileButtons extends Widget {
   }
 
   /**
-   * Get the file handler registry used by the widget.
+   * Get the document manager used by the widget.
    */
-  get registry(): FileHandlerRegistry {
-    return this._registry;
+  get manager(): DocumentManager {
+    return this._manager;
   }
 
   /**
@@ -200,7 +200,7 @@ class FileButtons extends Widget {
   private _model: FileBrowserModel;
   private _buttons = Private.createButtons();
   private _input = Private.createUploadInput();
-  private _registry: FileHandlerRegistry = null
+  private _manager: DocumentManager = null
 }
 
 
@@ -286,8 +286,8 @@ namespace Private {
    */
   export
   function createDropdownMenu(widget: FileButtons): Menu {
-    let registry = widget.registry;
-    let creators = registry.listCreators();
+    let manager = widget.manager;
+    let creators = manager.fileTypes;
     creators = creators.sort((a, b) => a.localeCompare(b));
     let items: MenuItem[] = [];
     for (var text of creators) {
@@ -300,19 +300,12 @@ namespace Private {
    * Create a menu item in the dropdown menu.
    */
   function createItem(text: string, widget: FileButtons): MenuItem {
-    let registry = widget.registry;
+    let manager = widget.manager;
     let model = widget.model;
-    let host = widget.parent.node;
     return new MenuItem({
       text,
       handler: () => {
-        registry.createNew(text, model.path, host).then(contents => {
-          if (contents === void 0) {
-            return;
-          }
-          if (contents.type !== 'directory') {
-            registry.open(contents.path);
-          }
+        manager.createNew(text, model.path).then(() => {
           model.refresh();
         });
       }

+ 8 - 8
src/filebrowser/listing.ts

@@ -29,8 +29,8 @@ import {
 } from '../dialog';
 
 import {
-  FileHandlerRegistry
-} from '../filehandler';
+  DocumentManager
+} from '../docmanager';
 
 import {
   FileBrowserModel
@@ -292,7 +292,7 @@ class DirListing extends Widget {
    *
    * @param model - The file browser view model.
    */
-  constructor(model: FileBrowserModel, registry: FileHandlerRegistry) {
+  constructor(model: FileBrowserModel, manager: DocumentManager) {
     super();
     this.addClass(DIR_LISTING_CLASS);
     this._model = model;
@@ -300,7 +300,7 @@ class DirListing extends Widget {
     this._model.selectionChanged.connect(this._onSelectionChanged, this);
     this._editNode = document.createElement('input');
     this._editNode.className = EDITOR_CLASS;
-    this._registry = registry;
+    this._manager = manager;
   }
 
   /**
@@ -312,7 +312,7 @@ class DirListing extends Widget {
     this._editNode = null;
     this._drag = null;
     this._dragData = null;
-    this._registry = null;
+    this._manager = null;
     super.dispose();
   }
 
@@ -879,7 +879,7 @@ class DirListing extends Widget {
         showErrorMessage(this, 'Open directory', error)
       );
     } else {
-      this._registry.open(item.path);
+      this._manager.open(item.path);
     }
   }
 
@@ -1032,7 +1032,7 @@ class DirListing extends Widget {
     this._drag.mimeData.setData(utils.CONTENTS_MIME, null);
     if (item && item.type !== 'directory') {
       this._drag.mimeData.setData(FACTORY_MIME, () => {
-        this._registry.open(item.path);
+        this._manager.open(item.path);
       });
     }
 
@@ -1254,7 +1254,7 @@ class DirListing extends Widget {
   private _prevPath = '';
   private _clipboard: string[] = [];
   private _softSelection = '';
-  private _registry: FileHandlerRegistry = null;
+  private _manager: DocumentManager = null;
 }