Browse Source

Work on outputarea

Brian E. Granger 8 years ago
parent
commit
c7b8f418cd
2 changed files with 130 additions and 327 deletions
  1. 124 311
      packages/outputarea/src/widget.ts
  2. 6 16
      packages/outputarea/style/index.css

+ 124 - 311
packages/outputarea/src/widget.ts

@@ -9,14 +9,6 @@ import {
   Message
 } from '@phosphor/messaging';
 
-import {
-  MimeData
-} from '@phosphor/coreutils';
-
-import {
-  Drag
-} from '@phosphor/dragdrop';
-
 import {
   Panel, PanelLayout
 } from '@phosphor/widgets';
@@ -42,75 +34,60 @@ import {
 } from './model';
 
 
-/**
- * The threshold in pixels to start a drag event.
- */
-const DRAG_THRESHOLD = 5;
-
-/**
- * The factory MIME type supported by phosphor dock panels.
- */
-const FACTORY_MIME = 'application/vnd.phosphor.widget-factory';
-
 /**
  * The class name added to an output area widget.
  */
 const OUTPUT_AREA_CLASS = 'jp-OutputArea';
 
 /**
- * The class name added to a "mirrored" output area widget created by a drag.
+ * The class name added to the direction children of OutputArea
  */
-const MIRRORED_OUTPUT_AREA_CLASS = 'jp-MirroredOutputArea';
+const OUTPUT_AREA_ITEM_CLASS = 'jp-OutputArea-item';
 
 /**
- * The class name added to an child widget.
+ * The class name added to actual outputs
  */
-const CHILD_CLASS = 'jp-OutputArea-child';
+const OUTPUT_AREA_OUTPUT_CLASS = 'jp-OutputArea-output';
 
 /**
- * The class name added to output area gutters.
+ * The class name added to prompt children of OutputArea.
  */
-const GUTTER_CLASS = 'jp-OutputArea-gutter';
+const OUTPUT_AREA_PROMPT_CLASS = 'jp-OutputArea-prompt';
 
 /**
- * The class name added to output area outputs.
+ * The class name added to OutputPrompt.
  */
-const OUTPUT_CLASS = 'jp-OutputArea-output';
+const OUTPUT_PROMPT_CLASS = 'jp-OutputPrompt';
 
 /**
  * The class name added to an execution result.
  */
-const EXECTUTE_CLASS = 'jp-OutputArea-executeResult';
+const EXECUTE_CLASS = 'jp-OutputArea-executeResult';
 
 /**
- * The class name added to stdin data.
+ * The class name added stdin items of OutputArea
  */
-const STDIN_CLASS = 'jp-OutputArea-stdin';
+const OUTPUT_AREA_STDIN_ITEM_CLASS = 'jp-OutputArea-stdin-item';
 
 /**
- * The class name added to stdin data prompt nodes.
+ * The class name added to stdin widgets.
  */
-const STDIN_PROMPT_CLASS = 'jp-StdinWidget-prompt';
+const STDIN_CLASS = 'jp-Stdin';
 
 /**
- * The class name added to stdin data input nodes.
- */
-const STDIN_INPUT_CLASS = 'jp-StdinWidget-input';
-
-/**
- * The class name added to stdin rendered text nodes.
+ * The class name added to stdin data prompt nodes.
  */
-const STDIN_RENDERED_CLASS = 'jp-StdinWidget-rendered';
+const STDIN_PROMPT_CLASS = 'jp-Stdin-prompt';
 
 /**
- * The class name added to fixed height output areas.
+ * The class name added to stdin data input nodes.
  */
-const FIXED_HEIGHT_CLASS = 'jp-mod-fixedHeight';
+const STDIN_INPUT_CLASS = 'jp-Stdin-input';
 
 /**
- * The class name added to collaped output areas.
+ * The class name added to stdin rendered text nodes.
  */
-const COLLAPSED_CLASS = 'jp-mod-collapsed';
+const STDIN_RENDERED_CLASS = 'jp-Stdin-rendered';
 
 
 /**
@@ -143,20 +120,6 @@ class OutputArea extends Widget {
     model.changed.connect(this.onModelChanged, this);
   }
 
-  /**
-   * Create a mirrored output area widget.
-   */
-  mirror(): OutputArea {
-    let rendermime = this.rendermime;
-    let contentFactory = this.contentFactory;
-    let model = this.model;
-    let widget = new OutputArea({ model, rendermime, contentFactory });
-    widget.title.label = 'Mirrored Output';
-    widget.title.closable = true;
-    widget.addClass(MIRRORED_OUTPUT_AREA_CLASS);
-    return widget;
-  }
-
   /**
    * The model used by the widget.
    */
@@ -179,34 +142,6 @@ class OutputArea extends Widget {
     return (this.layout as PanelLayout).widgets;
   }
 
-  /**
-   * The collapsed state of the widget.
-   */
-  get collapsed(): boolean {
-    return this._collapsed;
-  }
-  set collapsed(value: boolean) {
-    if (this._collapsed === value) {
-      return;
-    }
-    this._collapsed = value;
-    this.update();
-  }
-
-  /**
-   * The fixed height state of the widget.
-   */
-  get fixedHeight(): boolean {
-    return this._fixedHeight;
-  }
-  set fixedHeight(value: boolean) {
-    if (this._fixedHeight === value) {
-      return;
-    }
-    this._fixedHeight = value;
-    this.update();
-  }
-
   /**
    * Execute code on a client session and handle response messages.
    */
@@ -254,14 +189,6 @@ class OutputArea extends Widget {
     });
   }
 
-  /**
-   * Handle `update-request` messages.
-   */
-  protected onUpdateRequest(msg: Message): void {
-    this.toggleClass(COLLAPSED_CLASS, this.collapsed);
-    this.toggleClass(FIXED_HEIGHT_CLASS, this.fixedHeight);
-  }
-
   /**
    * Follow changes on the model state.
    */
@@ -375,47 +302,26 @@ class OutputArea extends Widget {
   private _onInputRequest(msg: KernelMessage.IInputRequestMsg, session: IClientSession): void {
     // Add an output widget to the end.
     let factory = this.contentFactory;
-    let prompt = msg.content.prompt;
+    let stdinPrompt = msg.content.prompt;
     let password = msg.content.password;
 
     let panel = new Panel();
-    panel.addClass(CHILD_CLASS);
-    panel.addClass(STDIN_CLASS);
+    panel.addClass(OUTPUT_AREA_ITEM_CLASS);
+    panel.addClass(OUTPUT_AREA_STDIN_ITEM_CLASS);
 
-    let gutter = factory.createGutter();
-    gutter.addClass(GUTTER_CLASS);
-    panel.addWidget(gutter);
+    let prompt = factory.createPrompt();
+    prompt.addClass(OUTPUT_AREA_PROMPT_CLASS);
+    panel.addWidget(prompt);
 
     let kernel = session.kernel;
-    let input = factory.createStdin({ prompt, password, kernel });
-    input.addClass(STDIN_CLASS);
+    let input = factory.createStdin({ prompt: stdinPrompt, password, kernel });
+    input.addClass(OUTPUT_AREA_OUTPUT_CLASS);
     panel.addWidget(input);
 
     let layout = this.layout as PanelLayout;
     layout.addWidget(panel);
   }
 
-  /**
-   * Insert an output to the layout.
-   */
-  private _insertOutput(index: number, model: IOutputModel): void {
-    let panel = new Panel();
-    panel.addClass(CHILD_CLASS);
-    panel.addClass(OUTPUT_CLASS);
-
-    let gutter = this.contentFactory.createGutter();
-    gutter.executionCount = model.executionCount;
-    gutter.addClass(GUTTER_CLASS);
-    panel.addWidget(gutter);
-
-    let output = this._createOutput(model);
-    output.toggleClass(EXECTUTE_CLASS, model.executionCount !== null);
-    panel.addWidget(output);
-
-    let layout = this.layout as PanelLayout;
-    layout.insertWidget(index, panel);
-  }
-
   /**
    * Update an output in place.
    */
@@ -424,7 +330,7 @@ class OutputArea extends Widget {
     let widgets = this.widgets;
     // Skip any stdin widgets to find the correct index.
     for (let i = 0; i < index; i++) {
-      if (widgets[i].hasClass(STDIN_CLASS)) {
+      if (widgets[i].hasClass(OUTPUT_AREA_STDIN_ITEM_CLASS)) {
         index++;
       }
     }
@@ -433,17 +339,34 @@ class OutputArea extends Widget {
   }
 
   /**
-   * Create an output.
+   * Render and insert a single output into the layout.
+   */
+  private _insertOutput(index: number, model: IOutputModel): void {
+    let output = this._createOutputItem(model);
+    output.toggleClass(EXECUTE_CLASS, model.executionCount !== null);
+    let layout = this.layout as PanelLayout;
+    layout.insertWidget(index, output);
+  }
+
+  /**
+   * Create an output item with a prompt and actual output
    */
-  private _createOutput(model: IOutputModel): Widget {
-    let widget = this.rendermime.render(model);
-    widget.addClass(CHILD_CLASS);
-    widget.addClass(OUTPUT_CLASS);
-    return widget;
+  private _createOutputItem(model: IOutputModel): Widget {
+    let panel = new Panel();
+    panel.addClass(OUTPUT_AREA_ITEM_CLASS);
+
+    let prompt = this.contentFactory.createPrompt();
+    prompt.executionCount = model.executionCount;
+    prompt.addClass(OUTPUT_AREA_PROMPT_CLASS);
+    panel.addWidget(prompt);
+
+    let output = this.rendermime.render(model);
+    output.addClass(OUTPUT_AREA_OUTPUT_CLASS);
+    panel.addWidget(output);
+
+    return panel;
   }
 
-  private _fixedHeight = false;
-  private _collapsed = false;
   private _minHeightTimeout: number = null;
 }
 
@@ -477,90 +400,128 @@ namespace OutputArea {
   }
 
   /**
-   * The interface for a gutter widget.
+   * An output widget content factory.
    */
   export
-  interface IGutterWidget extends Widget {
+  interface IContentFactory {
     /**
-     * The execution count for the widget.
+     * Create a gutter for an output or input.
+     *
      */
-    executionCount: nbformat.ExecutionCount;
+    createPrompt(): IOutputPrompt;
+
+    /**
+     * Create an stdin widget.
+     */
+    createStdin(options: IStdinOptions): Widget;
   }
 
   /**
-   * The options to create a stdin widget.
+   * The default implementation of `IContentFactory`.
    */
   export
-  interface IStdinOptions {
+  class ContentFactory implements IContentFactory {
     /**
-     * The prompt text.
+     * Create the gutter for the widget.
      */
-    prompt: string;
+    createPrompt(): IOutputPrompt {
+      return new OutputPrompt();
+    }
 
     /**
-     * Whether the input is a password.
+     * Create an stdin widget.
      */
-    password: boolean;
+    createStdin(options: IStdinOptions): IStdin {
+      return new Stdin(options);
+    }
+  }
+
+  /**
+   * The default `ContentFactory` instance.
+   */
+  export
+  const defaultContentFactory = new ContentFactory();
 
+  /**
+   * The interface for a gutter widget.
+   */
+  export
+  interface IOutputPrompt extends Widget {
     /**
-     * The kernel associated with the request.
+     * The execution count for the widget.
      */
-    kernel: Kernel.IKernelConnection;
+    executionCount: nbformat.ExecutionCount;
   }
 
   /**
-   * An output widget content factory.
+   * The default output prompt implementation
    */
   export
-  interface IContentFactory {
-    /**
-     * Create a gutter for an output or input.
-     *
+  class OutputPrompt extends Widget implements IOutputPrompt {
+    /*
+     * Create an output prompt widget.
      */
-    createGutter(): IGutterWidget;
+    constructor() {
+      super();
+      this.addClass(OUTPUT_PROMPT_CLASS);
+    }
 
     /**
-     * Create an stdin widget.
+     * The execution count for the widget.
      */
-    createStdin(options: IStdinOptions): Widget;
+    get executionCount(): nbformat.ExecutionCount {
+      return this._executionCount;
+    }
+    set executionCount(value: nbformat.ExecutionCount) {
+      this._executionCount = value;
+      if (value === null) {
+        this.node.textContent = '';
+      } else {
+         this.node.textContent = `Out[${value}]:`;
+      }
+    }
+
+    private _executionCount: nbformat.ExecutionCount = null;
   }
 
   /**
-   * The default implementation of `IContentFactory`.
+   * The options to create a stdin widget.
    */
   export
-  class ContentFactory implements IContentFactory {
+  interface IStdinOptions {
     /**
-     * Create the gutter for the widget.
+     * The prompt text.
      */
-    createGutter(): IGutterWidget {
-      return new GutterWidget();
-    }
+    prompt: string;
 
     /**
-     * Create an stdin widget.
+     * Whether the input is a password.
      */
-    createStdin(options: IStdinOptions): Widget {
-      return new StdinWidget(options);
-    }
+    password: boolean;
+
+    /**
+     * The kernel associated with the request.
+     */
+    kernel: Kernel.IKernelConnection;
   }
 
   /**
-   * The default `ContentFactory` instance.
+   * The stdin interface
    */
   export
-  const defaultContentFactory = new ContentFactory();
+  interface IStdin extends Widget {}
 
   /**
    * The default stdin widget.
    */
   export
-  class StdinWidget extends Widget {
+  class Stdin extends Widget implements IStdin {
     /**
      * Construct a new input widget.
      */
     constructor(options: IStdinOptions) {
       super({ node: Private.createInputWidgetNode() });
+      this.addClass(STDIN_CLASS);
       let text = this.node.firstChild as HTMLElement;
       text.textContent = options.prompt;
       this._input = this.node.lastChild as HTMLInputElement;
@@ -625,154 +586,6 @@ namespace OutputArea {
     private _input: HTMLInputElement = null;
   }
 
-  /**
-   * The default output gutter.
-   */
-  export
-  class GutterWidget extends Widget {
-    /**
-     * The execution count for the widget.
-     */
-    get executionCount(): nbformat.ExecutionCount {
-      return this._executionCount;
-    }
-    set executionCount(value: nbformat.ExecutionCount) {
-      this._executionCount = value;
-      if (value === null) {
-        this.node.textContent = '';
-      } else {
-         this.node.textContent = `Out[${value}]:`;
-      }
-    }
-
-    /**
-     * Handle the DOM events for the output gutter 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 'mousedown':
-        this._evtMousedown(event as MouseEvent);
-        break;
-      case 'mouseup':
-        this._evtMouseup(event as MouseEvent);
-        break;
-      case 'mousemove':
-        this._evtMousemove(event as MouseEvent);
-        break;
-      default:
-        break;
-      }
-    }
-
-    /**
-     * A message handler invoked on an `'after-attach'` message.
-     */
-    protected onAfterAttach(msg: Message): void {
-      super.onAfterAttach(msg);
-      this.node.addEventListener('mousedown', this);
-    }
-
-    /**
-     * A message handler invoked on a `'before-detach'` message.
-     */
-    protected onBeforeDetach(msg: Message): void {
-      super.onBeforeDetach(msg);
-      let node = this.node;
-      node.removeEventListener('mousedown', this);
-    }
-
-    /**
-     * Handle the `'mousedown'` event for the widget.
-     */
-    private _evtMousedown(event: MouseEvent): void {
-      // Left mouse press for drag start.
-      if (event.button === 0) {
-        this._dragData = { pressX: event.clientX, pressY: event.clientY };
-        document.addEventListener('mouseup', this, true);
-        document.addEventListener('mousemove', this, true);
-      }
-    }
-
-    /**
-     * Handle the `'mouseup'` event for the widget.
-     */
-    private _evtMouseup(event: MouseEvent): void {
-      if (event.button !== 0 || !this._drag) {
-        document.removeEventListener('mousemove', this, true);
-        document.removeEventListener('mouseup', this, true);
-        return;
-      }
-      event.preventDefault();
-      event.stopPropagation();
-    }
-
-    /**
-     * Handle the `'mousemove'` event for the widget.
-     */
-    private _evtMousemove(event: MouseEvent): void {
-      event.preventDefault();
-      event.stopPropagation();
-
-      // Bail if we are the one dragging.
-      if (this._drag) {
-        return;
-      }
-
-      // Check for a drag initialization.
-      let data = this._dragData;
-      let dx = Math.abs(event.clientX - data.pressX);
-      let dy = Math.abs(event.clientY - data.pressY);
-      if (dx < DRAG_THRESHOLD && dy < DRAG_THRESHOLD) {
-        return;
-      }
-
-      this._startDrag(event.clientX, event.clientY);
-    }
-
-    /**
-     * Start a drag event.
-     */
-    private _startDrag(clientX: number, clientY: number): void {
-      // Set up the drag event.
-      this._drag = new Drag({
-        mimeData: new MimeData(),
-        supportedActions: 'copy',
-        proposedAction: 'copy'
-      });
-
-      this._drag.mimeData.setData(FACTORY_MIME, () => {
-        let outputArea = this.parent.parent as OutputArea;
-        return outputArea.mirror();
-      });
-
-      // Remove mousemove and mouseup listeners and start the drag.
-      document.removeEventListener('mousemove', this, true);
-      document.removeEventListener('mouseup', this, true);
-      this._drag.start(clientX, clientY).then(action => {
-        this._drag = null;
-      });
-    }
-
-    /**
-     * Dispose of the resources held by the widget.
-     */
-    dispose() {
-      this._dragData = null;
-      this._drag = null;
-      super.dispose();
-    }
-
-    private _drag: Drag = null;
-    private _dragData: { pressX: number, pressY: number } = null;
-    private _executionCount: nbformat.ExecutionCount = null;
-  }
 }
 
 

+ 6 - 16
packages/outputarea/style/index.css

@@ -38,14 +38,14 @@
 }
 
 
-.jp-StdinWidget-prompt {
+.jp-Stdin-prompt {
   padding-right: var(--jp-code-padding);
   vertical-align: baseline;
   flex: 0 0 auto;
 }
 
 
-.jp-StdinWidget-input {
+.jp-Stdin-input {
   font-family: var(--jp-code-font-family);
   font-size: inherit;
   color: inherit;
@@ -59,12 +59,12 @@
 }
 
 
-.jp-StdinWidget-input:focus {
+.jp-Stdin-input:focus {
     box-shadow: none;
 }
 
 
-.jp-OutputArea-gutter {
+.jp-OutputArea-prompt {
   color: var(--jp-private-outputarea-prompt-color);
   font-family: var(--jp-code-font-family);
   text-align: right;
@@ -78,7 +78,7 @@
 }
 
 
-.jp-OutputArea-gutter:hover {
+.jp-OutputArea-prompt:hover {
   background: var(--md-grey-100);
 }
 
@@ -92,21 +92,11 @@
  *  - nested output areas (e.g. in the case of output widgets)
  *  - mirrored output areas
  */
-.jp-OutputArea .jp-OutputArea .jp-OutputArea-gutter, 
-.jp-MirroredOutputArea .jp-OutputArea-gutter {
+.jp-OutputArea .jp-OutputArea .jp-OutputArea-prompt {
   display: none;
 }
 
 
-/**
- * Allow outputs to expand in mirrored output areas.
- */
-.jp-MirroredOutputArea .jp-OutputArea-output {
-  width: 100%;
-  height: 100%;
-}
-
-
 /*-----------------------------------------------------------------------------
 | executeResult is added to any Output-result for the display of the object
 | returned by a cell