Ver Fonte

Merge pull request #1158 from blink1073/codemirror-refresh-throttle

Codemirror Refresh Throttle
Jason Grout há 8 anos atrás
pai
commit
aa00055b07
2 ficheiros alterados com 38 adições e 177 exclusões
  1. 1 1
      package.json
  2. 37 176
      src/codemirror/widget.ts

+ 1 - 1
package.json

@@ -10,7 +10,7 @@
     "@jupyterlab/services": "^0.24.0",
     "ansi_up": "^1.3.0",
     "backbone": "^1.2.0",
-    "codemirror": "5.17.0",
+    "codemirror": "^5.20.2",
     "d3-dsv": "^1.0.0",
     "diff-match-patch": "^1.0.0",
     "es6-promise": "^3.2.1",

+ 37 - 176
src/codemirror/widget.ts

@@ -5,16 +5,11 @@ import * as CodeMirror
   from 'codemirror';
 
 import 'codemirror/mode/meta';
-import 'codemirror/addon/runmode/runmode';
 
 import {
   Message
 } from 'phosphor/lib/core/messaging';
 
-import {
-  PanelLayout
-} from 'phosphor/lib/ui/panel';
-
 import {
   ResizeMessage, Widget
 } from 'phosphor/lib/ui/widget';
@@ -25,16 +20,6 @@ import {
  */
 const EDITOR_CLASS = 'jp-CodeMirrorWidget';
 
-/**
- * The class name added to a live codemirror widget.
- */
-const LIVE_CLASS = 'jp-CodeMirrorWidget-live';
-
-/**
- * The class name added to a static codemirror widget.
- */
-const STATIC_CLASS = 'jp-CodeMirrorWidget-static';
-
 /**
  * The name of the default CodeMirror theme
  */
@@ -54,38 +39,28 @@ class CodeMirrorWidget extends Widget {
   constructor(options: CodeMirror.EditorConfiguration = {}) {
     super();
     this.addClass(EDITOR_CLASS);
-    let layout = this.layout = new PanelLayout();
-    this.node.tabIndex = -1;
     options.theme = (options.theme || DEFAULT_CODEMIRROR_THEME);
-    this._live = new LiveCodeMirror(options);
-    this._static = new StaticCodeMirror(this._live.editor);
-    layout.addWidget(this._static);
-    layout.addWidget(this._live);
-    this._live.hide();
+    this._editor = CodeMirror(this.node, options);
   }
 
   /**
    * Dispose of the resources held by the widget.
    */
   dispose(): void {
-    this._static.dispose();
-    this._live.dispose();
+    clearTimeout(this._resizing);
+    this._editor = null;
     super.dispose();
   }
 
   /**
    * Get the editor wrapped by the widget.
+   *
+   * #### Notes
+   * This is a ready-only property.
    */
-  get editor(): CodeMirror.Editor {
-    return this._live.editor;
-  }
-
-  /**
-   * Handle `'activate-request'` messages.
-   */
-  protected onActivateRequest(msg: Message): void {
-    this._activate();
-  }
+   get editor(): CodeMirror.Editor {
+     return this._editor;
+   }
 
   /**
    * Handle the DOM events for the widget.
@@ -99,15 +74,9 @@ class CodeMirrorWidget extends Widget {
    */
   handleEvent(event: Event): void {
     switch (event.type) {
-    case 'mousedown':
-      this._evtMouseDown(event as MouseEvent);
-      break;
     case 'focus':
       this._evtFocus(event as FocusEvent);
       break;
-    case 'blur':
-      this._evtBlur(event as FocusEvent);
-      break;
     default:
       break;
     }
@@ -117,108 +86,30 @@ class CodeMirrorWidget extends Widget {
    * A message handler invoked on an `'after-attach'` message.
    */
   protected onAfterAttach(msg: Message): void {
-    this.node.addEventListener('mousedown', this);
     this.node.addEventListener('focus', this, true);
-    this.node.addEventListener('blur', this, true);
+    if (!this.isVisible) {
+      this._needsRefresh = true;
+      return;
+    }
+    this._editor.refresh();
+    this._needsRefresh = false;
   }
 
   /**
    * Handle `before_detach` messages for the widget.
    */
   protected onBeforeDetach(msg: Message): void {
-    this.node.removeEventListener('mousedown', this);
     this.node.removeEventListener('focus', this, true);
-    this.node.removeEventListener('blur', this, true);
-  }
-
-  /**
-   * Handle `mousedown` events for the widget.
-   */
-  private _evtMouseDown(event: MouseEvent): void {
-    if (this._live.isVisible) {
-      return;
-    }
-    this._lastMouseDown = event;
-  }
-
-  /**
-   * Handle `focus` events for the widget.
-   */
-  private _evtFocus(event: FocusEvent): void {
-    this._activate();
-  }
-
-  /**
-   * Handle `blur` events for the widget.
-   */
-  private _evtBlur(event: FocusEvent): void {
-    this._lastMouseDown = null;
-    if (this.node.contains(event.relatedTarget as HTMLElement)) {
-      return;
-    }
-    this._live.hide();
-    this._static.show();
-  }
-
-  /**
-   * Handle an activation message or a focus event.
-   */
-  private _activate(): void {
-    let editor = this.editor;
-    if (editor.getOption('readOnly') !== false) {
-      this._lastMouseDown = null;
-      return;
-    }
-    this._static.hide();
-    this._live.show();
-    if (this._lastMouseDown) {
-      let x = this._lastMouseDown.clientX;
-      let y = this._lastMouseDown.clientY;
-      let pos = editor.coordsChar({ left: x, top: y });
-      editor.getDoc().setCursor(pos);
-    }
-    editor.focus();
-  }
-
-  private _live: LiveCodeMirror;
-  private _static: StaticCodeMirror;
-  private _lastMouseDown: MouseEvent;
-}
-
-
-/**
- * A widget that hosts a codemirror instance.
- */
-class LiveCodeMirror extends Widget {
-  /**
-   * Construct a live codemirror.
-   */
-  constructor(options: CodeMirror.EditorConfiguration) {
-    super();
-    this.addClass(LIVE_CLASS);
-    this._editor = CodeMirror(this.node, options);
-  }
-
-  /**
-   * Dispose of the resources held by the widget.
-   */
-  dispose(): void {
-    this._editor = null;
-    super.dispose();
-  }
-
-  /**
-   * Get the editor wrapped by the widget.
-   */
-  get editor(): CodeMirror.Editor {
-     return this._editor;
   }
 
   /**
    * A message handler invoked on an `'after-show'` message.
    */
   protected onAfterShow(msg: Message): void {
-    this._editor.refresh();
+    if (this._needsRefresh) {
+      this._editor.refresh();
+      this._needsRefresh = false;
+    }
   }
 
   /**
@@ -226,66 +117,36 @@ class LiveCodeMirror extends Widget {
    */
   protected onResize(msg: ResizeMessage): void {
     if (msg.width < 0 || msg.height < 0) {
-      this._editor.refresh();
+      if (this._resizing === -1) {
+        this._resizing = setTimeout(() => {
+          this._editor.setSize(null, null);
+          this._resizing = -1;
+        }, 500);
+      }
     } else {
       this._editor.setSize(msg.width, msg.height);
     }
-  }
-
-  private _editor: CodeMirror.Editor = null;
-}
-
-
-/**
- * A widget that holds rendered codemirror text.
- */
-class StaticCodeMirror extends Widget {
-  /**
-   * Construct a new static code mirror widget.
-   */
-  constructor(editor: CodeMirror.Editor) {
-    super({ node: document.createElement('pre') });
-    this._editor = editor;
-    this.addClass(`cm-s-${editor.getOption('theme')}`);
-    this.addClass('CodeMirror');
-    this.addClass(STATIC_CLASS);
-    CodeMirror.on(this._editor.getDoc(), 'change', (instance, change) => {
-      if (this.isVisible) {
-        this._render();
-      }
-    });
-  }
-
-  /**
-   * Dispose of the resources held by the widget.
-   */
-  dispose(): void {
-    this._editor = null;
-    super.dispose();
+    this._needsRefresh = true;
   }
 
   /**
-   * A message handler invoked on an `'after-attach'` message.
-   */
-  protected onAfterAttach(msg: Message): void {
-    this._render();
-  }
-
-  /**
-   * A message handler invoked on an `'after-show'` message.
+   * Handle `'activate-request'` messages.
    */
-  protected onAfterShow(msg: Message): void {
-    this._render();
+  protected onActivateRequest(msg: Message): void {
+    this._editor.focus();
   }
 
   /**
-   * Render the static content.
+   * Handle `focus` events for the widget.
    */
-  private _render(): void {
-    CodeMirror.runMode(this._editor.getDoc().getValue(),
-                       this._editor.getOption('mode'),
-                       this.node);
+  private _evtFocus(event: FocusEvent): void {
+    if (this._needsRefresh) {
+      this._editor.refresh();
+      this._needsRefresh = false;
+    }
   }
 
   private _editor: CodeMirror.Editor = null;
+  private _needsRefresh = true;
+  private _resizing = -1;
 }