Browse Source

Merge pull request #2015 from R-Brain/ak/issue_2014

Fixes jupyterlab/jupyterlab#2014
Steven Silvester 8 years ago
parent
commit
58a05d0a57

+ 8 - 0
packages/codeeditor/src/editor.ts

@@ -456,9 +456,17 @@ namespace CodeEditor {
 
     /**
      * Repaint the editor.
+     * 
+     * #### Notes
+     * A repainted editor should fit to its host node.
      */
     refresh(): void;
 
+    /**
+     * Resize the editor to fit its host node.
+     */
+    resizeToFit(): void;
+
     /**
      * Add a keydown handler to the editor.
      *

+ 1 - 46
packages/codeeditor/src/widget.ts

@@ -67,26 +67,6 @@ class CodeEditorWidget extends Widget {
     this._editor = null;
   }
 
-  /**
-   * Handle the DOM events for the widget.
-   *
-   * @param event - The DOM event sent to the widget.
-   *
-   * #### Notes
-   * This method implements the DOM `EventListener` interface and is
-   * called in response to events on the panel's DOM node. It should
-   * not be called directly by user code.
-   */
-  handleEvent(event: Event): void {
-    switch (event.type) {
-    case 'focus':
-      this._evtFocus(event as FocusEvent);
-      break;
-    default:
-      break;
-    }
-  }
-
   /**
    * Handle `'activate-request'` messages.
    */
@@ -99,10 +79,8 @@ class CodeEditorWidget extends Widget {
    */
   protected onAfterAttach(msg: Message): void {
     super.onAfterAttach(msg);
-    this.node.addEventListener('focus', this, true);
     if (this.isVisible) {
       this._editor.refresh();
-      this._needsRefresh = false;
     }
   }
 
@@ -111,14 +89,6 @@ class CodeEditorWidget extends Widget {
    */
   protected onAfterShow(msg: Message): void {
     this._editor.refresh();
-    this._needsRefresh = false;
-  }
-
-  /**
-   * Handle `before-detach` messages for the widget.
-   */
-  protected onBeforeDetach(msg: Message): void {
-    this.node.removeEventListener('focus', this, true);
   }
 
   /**
@@ -127,22 +97,8 @@ class CodeEditorWidget extends Widget {
   protected onResize(msg: Widget.ResizeMessage): void {
     if (msg.width >= 0 && msg.height >= 0) {
       this._editor.setSize(msg);
-      this._needsRefresh = false;
-    } else if (this._editor.hasFocus()) {
-      this._editor.refresh();
-      this._needsRefresh = false;
     } else {
-      this._needsRefresh = true;
-    }
-  }
-
-  /**
-   * Handle `focus` events for the widget.
-   */
-  private _evtFocus(event: FocusEvent): void {
-    if (this._needsRefresh) {
-      this._editor.refresh();
-      this._needsRefresh = false;
+      this._editor.resizeToFit();
     }
   }
 
@@ -160,7 +116,6 @@ class CodeEditorWidget extends Widget {
   }
 
   private _editor: CodeEditor.IEditor = null;
-  private _needsRefresh = false;
 }
 
 

+ 46 - 0
packages/codemirror/src/editor.ts

@@ -74,6 +74,7 @@ class CodeMirrorEditor implements CodeEditor.IEditor {
   constructor(options: CodeEditor.IOptions, config: CodeMirror.EditorConfiguration={}) {
     let host = this.host = options.host;
     host.classList.add(EDITOR_CLASS);
+    host.addEventListener('focus', this, true);
 
     this._uuid = options.uuid || uuid();
     this._selectionStyle = options.selectionStyle || {};
@@ -233,6 +234,7 @@ class CodeMirrorEditor implements CodeEditor.IEditor {
     if (this._editor === null) {
       return;
     }
+    this.host.removeEventListener('focus', this, true);
     this._editor = null;
     this._model = null;
     this._keydownHandlers.length = 0;
@@ -311,6 +313,19 @@ class CodeMirrorEditor implements CodeEditor.IEditor {
    */
   refresh(): void {
     this._editor.refresh();
+    this._needsRefresh = false;
+  }
+
+  /**
+   * Refresh the editor if it is focused;
+   * otherwise postpone refreshing till focusing.
+   */
+  resizeToFit(): void {
+    if (this.hasFocus()) {
+      this.refresh();
+    } else {
+      this._needsRefresh = true;
+    }
   }
 
   /**
@@ -336,6 +351,7 @@ class CodeMirrorEditor implements CodeEditor.IEditor {
     } else {
       this._editor.setSize(null, null);
     }
+    this._needsRefresh = false;
   }
 
   /**
@@ -645,6 +661,35 @@ class CodeMirrorEditor implements CodeEditor.IEditor {
     this._changeGuard = false;
   }
 
+  /**
+   * Handle the DOM events for the editor.
+   *
+   * @param event - The DOM event sent to the editor.
+   *
+   * #### Notes
+   * This method implements the DOM `EventListener` interface and is
+   * called in response to events on the editor's DOM node. It should
+   * not be called directly by user code.
+   */
+  handleEvent(event: Event): void {
+    switch (event.type) {
+    case 'focus':
+      this._evtFocus(event as FocusEvent);
+      break;
+    default:
+      break;
+    }
+  }
+
+  /**
+   * Handle `focus` events for the editor.
+   */
+  private _evtFocus(event: FocusEvent): void {
+    if (this._needsRefresh) {
+      this.refresh();
+    }
+  }
+
   private _model: CodeEditor.IModel;
   private _editor: CodeMirror.Editor;
   protected selectionMarkers: { [key: string]: CodeMirror.TextMarker[] | undefined } = {};
@@ -652,6 +697,7 @@ class CodeMirrorEditor implements CodeEditor.IEditor {
   private _changeGuard = false;
   private _selectionStyle: CodeEditor.ISelectionStyle;
   private _uuid = '';
+  private _needsRefresh = false;
 }
 
 

+ 24 - 27
test/src/codeeditor/widget.spec.ts

@@ -27,6 +27,12 @@ import {
 class LogEditor extends CodeMirrorEditor {
 
   methods: string[] = [];
+  events: string[] = [];
+
+  handleEvent(event: Event): void {
+    super.handleEvent(event);
+    this.events.push(event.type);
+  }
 
   refresh(): void {
     super.refresh();
@@ -43,12 +49,6 @@ class LogEditor extends CodeMirrorEditor {
 class LogWidget extends CodeEditorWidget {
 
   methods: string[] = [];
-  events: string[] = [];
-
-  handleEvent(event: Event): void {
-    super.handleEvent(event);
-    this.events.push(event.type);
-  }
 
   protected onActivateRequest(msg: Message): void {
     super.onActivateRequest(msg);
@@ -100,6 +100,13 @@ describe('CodeEditorWidget', () => {
       expect(widget).to.be.a(CodeEditorWidget);
     });
 
+    it('should add a focus listener', () => {
+      widget.node.tabIndex = -1;
+      simulate(widget.node, 'focus');
+      let editor = widget.editor as LogEditor;
+      expect(editor.events).to.contain('focus');
+    });
+
   });
 
   describe('#editor', () => {
@@ -120,6 +127,17 @@ describe('CodeEditorWidget', () => {
       expect(widget.isDisposed).to.be(true);
     });
 
+    it('should remove the focus listener', () => {
+      let editor = widget.editor as LogEditor;
+      expect(editor.isDisposed).to.be(false);
+      widget.dispose();
+      expect(editor.isDisposed).to.be(true);
+
+      widget.node.tabIndex = -1;
+      simulate(widget.node, 'focus');
+      expect(editor.events).to.not.contain('focus');
+    });
+
   });
 
   describe('#handleEvent()', () => {
@@ -160,14 +178,6 @@ describe('CodeEditorWidget', () => {
 
   describe('#onAfterAttach()', () => {
 
-    it('should add a focus listener', () => {
-      Widget.attach(widget, document.body);
-      expect(widget.methods).to.contain('onAfterAttach');
-      widget.node.tabIndex = -1;
-      simulate(widget.node, 'focus');
-      expect(widget.events).to.contain('focus');
-    });
-
     it('should refresh the editor', () => {
       Widget.attach(widget, document.body);
       let editor = widget.editor as LogEditor;
@@ -176,19 +186,6 @@ describe('CodeEditorWidget', () => {
 
   });
 
-  describe('#onBeforeDetach()', () => {
-
-    it('should remove the focus listener', () => {
-      Widget.attach(widget, document.body);
-      Widget.detach(widget);
-      expect(widget.methods).to.contain('onBeforeDetach');
-      widget.node.tabIndex = -1;
-      simulate(widget.node, 'focus');
-      expect(widget.events).to.not.contain('focus');
-    });
-
-  });
-
   describe('#onAfterShow()', () => {
 
     it('should refresh the editor', () => {