phosphor-dockpanel
Advanced tools
Comparing version 0.9.2 to 0.9.3
@@ -1,168 +0,115 @@ | ||
import { BoxPanel } from 'phosphor-boxpanel'; | ||
import { Message } from 'phosphor-messaging'; | ||
import { Property } from 'phosphor-properties'; | ||
import { Tab } from 'phosphor-tabs'; | ||
import { StackedPanel } from 'phosphor-stackedpanel'; | ||
import { Widget } from 'phosphor-widget'; | ||
/** | ||
* An enum of docking modes for a dock panel. | ||
*/ | ||
export declare enum DockMode { | ||
/** | ||
* Insert the widget as a new split item above a reference. | ||
*/ | ||
SplitTop = 0, | ||
/** | ||
* Insert the widget as a new split item to the left of a reference. | ||
*/ | ||
SplitLeft = 1, | ||
/** | ||
* Insert the widget as a new split item to the right of a reference. | ||
*/ | ||
SplitRight = 2, | ||
/** | ||
* Insert the widget as a new split item below a reference. | ||
*/ | ||
SplitBottom = 3, | ||
/** | ||
* Insert the widget as a new tab before a reference. | ||
*/ | ||
TabBefore = 4, | ||
/** | ||
* Insert the widget as a new tab after a reference. | ||
*/ | ||
TabAfter = 5, | ||
} | ||
/** | ||
* A widget which provides a flexible docking panel for content widgets. | ||
* A panel which provides a flexible docking area for content widgets. | ||
* | ||
* #### Notes | ||
* Widgets should be added to a `DockPanel` using the [[addWidget]] | ||
* method, **not** the inherited `<prefix>Child` methods. There is | ||
* no corresponding `removeWidget` method; simply set the `parent` | ||
* of a widget to `null` to remove it from a `DockPanel`. | ||
* Widgets should be added to a `DockPanel` using one of the dedicated | ||
* insertion methods. The `children` widget list should not be used. A | ||
* widget can be removed by setting its `parent` to `null`. | ||
*/ | ||
export declare class DockPanel extends BoxPanel { | ||
export declare class DockPanel extends StackedPanel { | ||
/** | ||
* The class name added to DockPanel instances. | ||
* Ensure the specified content widget is selected. | ||
* | ||
* @param widget - The content widget of interest. | ||
* | ||
* #### Notes | ||
* If the widget is not contained in a dock panel, or is already | ||
* the selected tab in its respective tab panel, this is a no-op. | ||
*/ | ||
static p_DockPanel: string; | ||
static select(widget: Widget): void; | ||
/** | ||
* The class name added to a tab which is being docked. | ||
* The property descriptor for the spacing between panels. | ||
* | ||
* The default value is `3`. | ||
* | ||
* **See also:** [[spacing]] | ||
*/ | ||
static p_mod_docking: string; | ||
static spacingProperty: Property<DockPanel, number>; | ||
/** | ||
* A convenience alias of the `SplitTop` [[DockMode]]. | ||
* Construct a new dock panel. | ||
*/ | ||
static SplitTop: DockMode; | ||
constructor(); | ||
/** | ||
* A convenience alias of the `SplitLeft` [[DockMode]]. | ||
* Get the spacing between panels. | ||
* | ||
* #### Notes | ||
* This is a pure delegate to the [[spacingProperty]]. | ||
*/ | ||
static SplitLeft: DockMode; | ||
/** | ||
* A convenience alias of the `SplitRight` [[DockMode]]. | ||
* Set the spacing between panels. | ||
* | ||
* #### Notes | ||
* This is a pure delegate to the [[spacingProperty]]. | ||
*/ | ||
static SplitRight: DockMode; | ||
spacing: number; | ||
/** | ||
* A convenience alias of the `SplitBottom` [[DockMode]]. | ||
*/ | ||
static SplitBottom: DockMode; | ||
/** | ||
* A convenience alias of the `TabBefore` [[DockMode]]. | ||
*/ | ||
static TabBefore: DockMode; | ||
/** | ||
* A convenience alias of the `TabAfter` [[DockMode]]. | ||
*/ | ||
static TabAfter: DockMode; | ||
/** | ||
* The property descriptor for the `tab` attached property. | ||
* Insert a widget as a new panel above a reference widget. | ||
* | ||
* This controls the tab used for a widget in a dock panel. | ||
* @param widget - The widget to insert into the dock panel. | ||
* | ||
* #### Notes | ||
* If the tab for a widget is changed, the new tab will not be | ||
* reflected until the widget is re-inserted into the dock panel. | ||
* However, in-place changes to the tab's properties **will** be | ||
* reflected. | ||
* @param ref - The reference widget. If this is not provided, the | ||
* widget will be inserted at the top edge of the dock panel. | ||
* | ||
* **See also:** [[getTab]], [[setTab]] | ||
* @throws An error if either `widget` or `ref` is invalid. | ||
*/ | ||
static tabProperty: Property<Widget, Tab>; | ||
insertTop(widget: Widget, ref?: Widget): void; | ||
/** | ||
* The property descriptor for the dock panel handle size. | ||
* Insert a widget as a new panel to the left of a reference widget. | ||
* | ||
* The controls the size of the split handles placed between the | ||
* tabbed panel, in pixels. The default value is `3`. | ||
* @param widget - The widget to insert into the dock panel. | ||
* | ||
* **See also:** [[handleSize]] | ||
* @param ref - The reference widget. If this is not provided, the | ||
* widget will be inserted at the left edge of the dock panel. | ||
* | ||
* @throws An error if either `widget` or `ref` is invalid. | ||
*/ | ||
static handleSizeProperty: Property<DockPanel, number>; | ||
insertLeft(widget: Widget, ref?: Widget): void; | ||
/** | ||
* Get the dock panel tab for the given widget. | ||
* Insert a widget as a new panel to the right of a reference widget. | ||
* | ||
* @param widget - The widget of interest. | ||
* @param widget - The widget to insert into the dock panel. | ||
* | ||
* @returns The dock panel tab for the given widget. | ||
* @param ref - The reference widget. If this is not provided, the | ||
* widget will be inserted at the right edge of the dock panel. | ||
* | ||
* #### Notes | ||
* This is a pure delegate for the [[tabProperty]]. | ||
* @throws An error if either `widget` or `ref` is invalid. | ||
*/ | ||
static getTab(widget: Widget): Tab; | ||
insertRight(widget: Widget, ref?: Widget): void; | ||
/** | ||
* Set the dock panel tab for the given widget. | ||
* Insert a widget as a new panel below a reference widget. | ||
* | ||
* @param widget - The widget of interest. | ||
* @param widget - The widget to insert into the dock panel. | ||
* | ||
* @param tab - The tab to use for the widget in a dock panel. | ||
* @param ref - The reference widget. If this is not provided, the | ||
* widget will be inserted at the bottom edge of the dock panel. | ||
* | ||
* #### Notes | ||
* This is a pure delegate for the [[tabProperty]]. | ||
* @throws An error if either `widget` or `ref` is invalid. | ||
*/ | ||
static setTab(widget: Widget, tab: Tab): void; | ||
insertBottom(widget: Widget, ref?: Widget): void; | ||
/** | ||
* Construct a new dock panel. | ||
*/ | ||
constructor(); | ||
/** | ||
* Dispose of the resources held by the widget. | ||
*/ | ||
dispose(): void; | ||
/** | ||
* Get the handle size of the dock split panels. | ||
* Insert a widget as a sibling tab before a reference widget. | ||
* | ||
* #### Notes | ||
* This is a pure delegate to the [[handleSizeProperty]]. | ||
*/ | ||
/** | ||
* Set the handle size of the dock split panels. | ||
* @param widget - The widget to insert into the dock panel. | ||
* | ||
* #### Notes | ||
* This is a pure delegate to the [[handleSizeProperty]]. | ||
* @param ref - The reference widget. If this is not provided, the | ||
* widget will be inserted as the first tab in the top-left panel. | ||
* | ||
* @throws An error if either `widget` or `ref` is invalid. | ||
*/ | ||
handleSize: number; | ||
insertTabBefore(widget: Widget, ref?: Widget): void; | ||
/** | ||
* Add a widget to the dock panel according to the given dock mode. | ||
* Insert a widget as a sibling tab after a reference widget. | ||
* | ||
* @param widget - The widget to add to the dock panel. | ||
* @param widget - The widget to insert into the dock panel. | ||
* | ||
* @param mode - The insertion mode for the widget. This controls how | ||
* the widget is inserted relative to the reference widget. If this | ||
* is not provided, `DockMode.SplitLeft` is assumed. | ||
* @param ref - The reference widget. If this is not provided, the | ||
* widget will be inserted as the last tab in the top-left panel. | ||
* | ||
* @param ref - The reference widget which controls the placement of | ||
* the added widget. If this is not provided, or is not contained | ||
* in the dock panel, the widget is inserted relative to the root. | ||
* | ||
* #### Notes | ||
* If the dock widget is already added to the panel, it will be moved | ||
* to the new location. | ||
* | ||
* The `DockPanel.tab` attached property **must** be set with the tab | ||
* to use for the widget, or an error will be thrown. This can be set | ||
* via `DockPanel.setTab`. This property is assumed to stay constant | ||
* while the widget is contained by the dock panel. | ||
* | ||
* If the `widget` and the `ref` are the same object, an error will | ||
* be thrown. | ||
* @throws An error if either `widget` or `ref` is invalid. | ||
*/ | ||
addWidget(widget: Widget, mode?: DockMode, ref?: Widget): void; | ||
insertTabAfter(widget: Widget, ref?: Widget): void; | ||
/** | ||
@@ -175,97 +122,30 @@ * Handle the DOM events for the dock panel. | ||
* This method implements the DOM `EventListener` interface and is | ||
* called in response to events on the dock panel's DOM node. It | ||
* should not be called directly by user code. | ||
* called in response to events on the dock panel's node. It should | ||
* not be called directly by user code. | ||
*/ | ||
handleEvent(event: Event): void; | ||
/** | ||
* Add the dock widget as a new split panel next to the reference. | ||
* A message handler invoked on an `'after-attach'` message. | ||
*/ | ||
private _splitWidget(widget, ref, orientation, after); | ||
protected onAfterAttach(msg: Message): void; | ||
/** | ||
* Add the dock widget as a tab next to the reference. | ||
* A message handler invoked on a `'before-detach'` message. | ||
*/ | ||
private _tabifyWidget(widget, ref, after); | ||
protected onBeforeDetach(msg: Message): void; | ||
/** | ||
* Add a widget to a new tab panel along the given orientation. | ||
* Handle the `'p-dragenter'` event for the dock panel. | ||
*/ | ||
private _addPanel(widget, orientation, after); | ||
private _evtDragEnter(event); | ||
/** | ||
* Split a dock item with a widget along the given orientation. | ||
* Handle the `'p-dragleave'` event for the dock panel. | ||
*/ | ||
private _splitPanel(target, widget, orientation, after); | ||
private _evtDragLeave(event); | ||
/** | ||
* Add a widget to the tab panel of a given dock item. | ||
* Handle the `'p-dragover'` event for the dock panel. | ||
*/ | ||
private _tabifyPanel(item, widget, after); | ||
private _evtDragOver(event); | ||
/** | ||
* Handle the `'mousemove'` event for the dock panel. | ||
* | ||
* This is triggered on the document during a tab move operation. | ||
* Handle the `'p-drop'` event for the dock panel. | ||
*/ | ||
private _evtMouseMove(event); | ||
/** | ||
* Handle the 'mouseup' event for the dock panel. | ||
* | ||
* This is triggered on the document during a tab move operation. | ||
*/ | ||
private _evtMouseUp(event); | ||
/** | ||
* Ensure the root split panel has the given orientation. | ||
*/ | ||
private _ensureRoot(orientation); | ||
/** | ||
* Create a new dock tab panel and setup the signal handlers. | ||
*/ | ||
private _createTabPanel(); | ||
/** | ||
* Create a new dock split panel for the dock panel. | ||
*/ | ||
private _createSplitPanel(orientation); | ||
/** | ||
* Remove an empty dock tab panel from the hierarchy. | ||
* | ||
* This ensures that the hierarchy is kept consistent by merging an | ||
* ancestor split panel when it contains only a single child widget. | ||
*/ | ||
private _removePanel(panel); | ||
/** | ||
* Abort the tab drag operation if one is in progress. | ||
*/ | ||
private _abortDrag(); | ||
/** | ||
* Find the dock item which contains the given tab. | ||
* | ||
* Returns `undefined` if there is no matching item. | ||
*/ | ||
private _findItemByTab(tab); | ||
/** | ||
* Find the dock item which contains the given widget. | ||
* | ||
* Returns `undefined` if there is no matching item. | ||
*/ | ||
private _findItemByWidget(widget); | ||
/** | ||
* The change handler for the [[handleSizeProperty]]. | ||
*/ | ||
private _onHandleSizeChanged(old, value); | ||
/** | ||
* Handle the `tabSelected` signal from a tab bar. | ||
*/ | ||
private _onTabSelected(sender, args); | ||
/** | ||
* Handle the `tabCloseRequested` signal from a tab bar. | ||
*/ | ||
private _onTabCloseRequested(sender, args); | ||
/** | ||
* Handle the `tabDetachRequested` signal from the tab bar. | ||
*/ | ||
private _onTabDetachRequested(sender, args); | ||
/** | ||
* Handle the `widgetRemoved` signal from a stacked widget. | ||
*/ | ||
private _onWidgetRemoved(sender, args); | ||
private _root; | ||
private _ignoreRemoved; | ||
private _items; | ||
private _dragData; | ||
private _evtDrop(event); | ||
} |
1910
lib/index.js
@@ -15,4 +15,5 @@ /*----------------------------------------------------------------------------- | ||
var arrays = require('phosphor-arrays'); | ||
var phosphor_boxpanel_1 = require('phosphor-boxpanel'); | ||
var phosphor_domutil_1 = require('phosphor-domutil'); | ||
var phosphor_dragdrop_1 = require('phosphor-dragdrop'); | ||
var phosphor_nodewrapper_1 = require('phosphor-nodewrapper'); | ||
var phosphor_properties_1 = require('phosphor-properties'); | ||
@@ -22,41 +23,83 @@ var phosphor_splitpanel_1 = require('phosphor-splitpanel'); | ||
var phosphor_tabs_1 = require('phosphor-tabs'); | ||
var phosphor_widget_1 = require('phosphor-widget'); | ||
require('./index.css'); | ||
/** | ||
* An enum of docking modes for a dock panel. | ||
* The class name added to DockPanel instances. | ||
*/ | ||
(function (DockMode) { | ||
/** | ||
* Insert the widget as a new split item above a reference. | ||
*/ | ||
DockMode[DockMode["SplitTop"] = 0] = "SplitTop"; | ||
/** | ||
* Insert the widget as a new split item to the left of a reference. | ||
*/ | ||
DockMode[DockMode["SplitLeft"] = 1] = "SplitLeft"; | ||
/** | ||
* Insert the widget as a new split item to the right of a reference. | ||
*/ | ||
DockMode[DockMode["SplitRight"] = 2] = "SplitRight"; | ||
/** | ||
* Insert the widget as a new split item below a reference. | ||
*/ | ||
DockMode[DockMode["SplitBottom"] = 3] = "SplitBottom"; | ||
/** | ||
* Insert the widget as a new tab before a reference. | ||
*/ | ||
DockMode[DockMode["TabBefore"] = 4] = "TabBefore"; | ||
/** | ||
* Insert the widget as a new tab after a reference. | ||
*/ | ||
DockMode[DockMode["TabAfter"] = 5] = "TabAfter"; | ||
})(exports.DockMode || (exports.DockMode = {})); | ||
var DockMode = exports.DockMode; | ||
var DOCK_PANEL_CLASS = 'p-DockPanel'; | ||
/** | ||
* A widget which provides a flexible docking panel for content widgets. | ||
* The class name added to dock tab bars. | ||
*/ | ||
var TAB_BAR_CLASS = 'p-DockTabBar'; | ||
/** | ||
* The class name added to dock tab panels. | ||
*/ | ||
var TAB_PANEL_CLASS = 'p-DockTabPanel'; | ||
/** | ||
* The class name added to dock split panels. | ||
*/ | ||
var SPLIT_PANEL_CLASS = 'p-DockSplitPanel'; | ||
/** | ||
* The class name added to dock panel overlays. | ||
*/ | ||
var OVERLAY_CLASS = 'p-DockPanelOverlay'; | ||
/** | ||
* The class name added to hidden overlays and tabs. | ||
*/ | ||
var HIDDEN_CLASS = 'p-mod-hidden'; | ||
/** | ||
* The class name added to top root dock overlays. | ||
*/ | ||
var ROOT_TOP_CLASS = 'p-mod-root-top'; | ||
/** | ||
* The class name added to left root dock overlays. | ||
*/ | ||
var ROOT_LEFT_CLASS = 'p-mod-root-left'; | ||
/** | ||
* The class name added to right root dock overlays. | ||
*/ | ||
var ROOT_RIGHT_CLASS = 'p-mod-root-right'; | ||
/** | ||
* The class name added to bottom root dock overlays. | ||
*/ | ||
var ROOT_BOTTOM_CLASS = 'p-mod-root-bottom'; | ||
/** | ||
* The class name added to center root dock overlays. | ||
*/ | ||
var ROOT_CENTER_CLASS = 'p-mod-root-center'; | ||
/** | ||
* The class name added to top panel dock overlays. | ||
*/ | ||
var PANEL_TOP_CLASS = 'p-mod-panel-top'; | ||
/** | ||
* The class name added to left panel dock overlays. | ||
*/ | ||
var PANEL_LEFT_CLASS = 'p-mod-panel-left'; | ||
/** | ||
* The class name added to right panel dock overlays. | ||
*/ | ||
var PANEL_RIGHT_CLASS = 'p-mod-panel-right'; | ||
/** | ||
* The class name added to bottom panel dock overlays. | ||
*/ | ||
var PANEL_BOTTOM_CLASS = 'p-mod-panel-bottom'; | ||
/** | ||
* The class named added to center panel dock overlays. | ||
*/ | ||
var PANEL_CENTER_CLASS = 'p-mod-panel-center'; | ||
/** | ||
* The factory MIME type supported by the dock panel. | ||
*/ | ||
var FACTORY_MIME = 'application/x-phosphor-widget-factory'; | ||
/** | ||
* The size of the edge dock zone for the root panel. | ||
*/ | ||
var EDGE_SIZE = 30; | ||
/** | ||
* A panel which provides a flexible docking area for content widgets. | ||
* | ||
* #### Notes | ||
* Widgets should be added to a `DockPanel` using the [[addWidget]] | ||
* method, **not** the inherited `<prefix>Child` methods. There is | ||
* no corresponding `removeWidget` method; simply set the `parent` | ||
* of a widget to `null` to remove it from a `DockPanel`. | ||
* Widgets should be added to a `DockPanel` using one of the dedicated | ||
* insertion methods. The `children` widget list should not be used. A | ||
* widget can be removed by setting its `parent` to `null`. | ||
*/ | ||
@@ -70,62 +113,34 @@ var DockPanel = (function (_super) { | ||
_super.call(this); | ||
this._ignoreRemoved = false; | ||
this._items = []; | ||
this._dragData = null; | ||
this.addClass(DockPanel.p_DockPanel); | ||
this._root = this._createSplitPanel(phosphor_splitpanel_1.Orientation.Horizontal); | ||
this.addChild(this._root); | ||
this.addClass(DOCK_PANEL_CLASS); | ||
} | ||
/** | ||
* Get the dock panel tab for the given widget. | ||
* Ensure the specified content widget is selected. | ||
* | ||
* @param widget - The widget of interest. | ||
* @param widget - The content widget of interest. | ||
* | ||
* @returns The dock panel tab for the given widget. | ||
* | ||
* #### Notes | ||
* This is a pure delegate for the [[tabProperty]]. | ||
* If the widget is not contained in a dock panel, or is already | ||
* the selected tab in its respective tab panel, this is a no-op. | ||
*/ | ||
DockPanel.getTab = function (widget) { | ||
return DockPanel.tabProperty.get(widget); | ||
DockPanel.select = function (widget) { | ||
selectWidget(widget); | ||
}; | ||
/** | ||
* Set the dock panel tab for the given widget. | ||
* | ||
* @param widget - The widget of interest. | ||
* | ||
* @param tab - The tab to use for the widget in a dock panel. | ||
* | ||
* #### Notes | ||
* This is a pure delegate for the [[tabProperty]]. | ||
*/ | ||
DockPanel.setTab = function (widget, tab) { | ||
DockPanel.tabProperty.set(widget, tab); | ||
}; | ||
/** | ||
* Dispose of the resources held by the widget. | ||
*/ | ||
DockPanel.prototype.dispose = function () { | ||
this._abortDrag(); | ||
this._root = null; | ||
this._items.length = 0; | ||
_super.prototype.dispose.call(this); | ||
}; | ||
Object.defineProperty(DockPanel.prototype, "handleSize", { | ||
Object.defineProperty(DockPanel.prototype, "spacing", { | ||
/** | ||
* Get the handle size of the dock split panels. | ||
* Get the spacing between panels. | ||
* | ||
* #### Notes | ||
* This is a pure delegate to the [[handleSizeProperty]]. | ||
* This is a pure delegate to the [[spacingProperty]]. | ||
*/ | ||
get: function () { | ||
return DockPanel.handleSizeProperty.get(this); | ||
return DockPanel.spacingProperty.get(this); | ||
}, | ||
/** | ||
* Set the handle size of the dock split panels. | ||
* Set the spacing between panels. | ||
* | ||
* #### Notes | ||
* This is a pure delegate to the [[handleSizeProperty]]. | ||
* This is a pure delegate to the [[spacingProperty]]. | ||
*/ | ||
set: function (value) { | ||
DockPanel.handleSizeProperty.set(this, value); | ||
DockPanel.spacingProperty.set(this, value); | ||
}, | ||
@@ -136,58 +151,80 @@ enumerable: true, | ||
/** | ||
* Add a widget to the dock panel according to the given dock mode. | ||
* Insert a widget as a new panel above a reference widget. | ||
* | ||
* @param widget - The widget to add to the dock panel. | ||
* @param widget - The widget to insert into the dock panel. | ||
* | ||
* @param mode - The insertion mode for the widget. This controls how | ||
* the widget is inserted relative to the reference widget. If this | ||
* is not provided, `DockMode.SplitLeft` is assumed. | ||
* @param ref - The reference widget. If this is not provided, the | ||
* widget will be inserted at the top edge of the dock panel. | ||
* | ||
* @param ref - The reference widget which controls the placement of | ||
* the added widget. If this is not provided, or is not contained | ||
* in the dock panel, the widget is inserted relative to the root. | ||
* @throws An error if either `widget` or `ref` is invalid. | ||
*/ | ||
DockPanel.prototype.insertTop = function (widget, ref) { | ||
insertSplit(this, widget, ref, phosphor_splitpanel_1.Orientation.Vertical, false); | ||
}; | ||
/** | ||
* Insert a widget as a new panel to the left of a reference widget. | ||
* | ||
* #### Notes | ||
* If the dock widget is already added to the panel, it will be moved | ||
* to the new location. | ||
* @param widget - The widget to insert into the dock panel. | ||
* | ||
* The `DockPanel.tab` attached property **must** be set with the tab | ||
* to use for the widget, or an error will be thrown. This can be set | ||
* via `DockPanel.setTab`. This property is assumed to stay constant | ||
* while the widget is contained by the dock panel. | ||
* @param ref - The reference widget. If this is not provided, the | ||
* widget will be inserted at the left edge of the dock panel. | ||
* | ||
* If the `widget` and the `ref` are the same object, an error will | ||
* be thrown. | ||
* @throws An error if either `widget` or `ref` is invalid. | ||
*/ | ||
DockPanel.prototype.addWidget = function (widget, mode, ref) { | ||
if (widget === ref) { | ||
throw new Error('invalid ref widget'); | ||
} | ||
if (!DockPanel.getTab(widget)) { | ||
throw new Error('`DockPanel.tab` property not set'); | ||
} | ||
switch (mode) { | ||
case DockMode.SplitTop: | ||
this._splitWidget(widget, ref, phosphor_splitpanel_1.Orientation.Vertical, false); | ||
break; | ||
case DockMode.SplitLeft: | ||
this._splitWidget(widget, ref, phosphor_splitpanel_1.Orientation.Horizontal, false); | ||
break; | ||
case DockMode.SplitRight: | ||
this._splitWidget(widget, ref, phosphor_splitpanel_1.Orientation.Horizontal, true); | ||
break; | ||
case DockMode.SplitBottom: | ||
this._splitWidget(widget, ref, phosphor_splitpanel_1.Orientation.Vertical, true); | ||
break; | ||
case DockMode.TabBefore: | ||
this._tabifyWidget(widget, ref, false); | ||
break; | ||
case DockMode.TabAfter: | ||
this._tabifyWidget(widget, ref, true); | ||
break; | ||
default: | ||
this._addPanel(widget, phosphor_splitpanel_1.Orientation.Horizontal, false); | ||
break; | ||
} | ||
DockPanel.prototype.insertLeft = function (widget, ref) { | ||
insertSplit(this, widget, ref, phosphor_splitpanel_1.Orientation.Horizontal, false); | ||
}; | ||
/** | ||
* Insert a widget as a new panel to the right of a reference widget. | ||
* | ||
* @param widget - The widget to insert into the dock panel. | ||
* | ||
* @param ref - The reference widget. If this is not provided, the | ||
* widget will be inserted at the right edge of the dock panel. | ||
* | ||
* @throws An error if either `widget` or `ref` is invalid. | ||
*/ | ||
DockPanel.prototype.insertRight = function (widget, ref) { | ||
insertSplit(this, widget, ref, phosphor_splitpanel_1.Orientation.Horizontal, true); | ||
}; | ||
/** | ||
* Insert a widget as a new panel below a reference widget. | ||
* | ||
* @param widget - The widget to insert into the dock panel. | ||
* | ||
* @param ref - The reference widget. If this is not provided, the | ||
* widget will be inserted at the bottom edge of the dock panel. | ||
* | ||
* @throws An error if either `widget` or `ref` is invalid. | ||
*/ | ||
DockPanel.prototype.insertBottom = function (widget, ref) { | ||
insertSplit(this, widget, ref, phosphor_splitpanel_1.Orientation.Vertical, true); | ||
}; | ||
/** | ||
* Insert a widget as a sibling tab before a reference widget. | ||
* | ||
* @param widget - The widget to insert into the dock panel. | ||
* | ||
* @param ref - The reference widget. If this is not provided, the | ||
* widget will be inserted as the first tab in the top-left panel. | ||
* | ||
* @throws An error if either `widget` or `ref` is invalid. | ||
*/ | ||
DockPanel.prototype.insertTabBefore = function (widget, ref) { | ||
insertTab(this, widget, ref, false); | ||
}; | ||
/** | ||
* Insert a widget as a sibling tab after a reference widget. | ||
* | ||
* @param widget - The widget to insert into the dock panel. | ||
* | ||
* @param ref - The reference widget. If this is not provided, the | ||
* widget will be inserted as the last tab in the top-left panel. | ||
* | ||
* @throws An error if either `widget` or `ref` is invalid. | ||
*/ | ||
DockPanel.prototype.insertTabAfter = function (widget, ref) { | ||
insertTab(this, widget, ref, true); | ||
}; | ||
/** | ||
* Handle the DOM events for the dock panel. | ||
@@ -199,830 +236,1029 @@ * | ||
* This method implements the DOM `EventListener` interface and is | ||
* called in response to events on the dock panel's DOM node. It | ||
* should not be called directly by user code. | ||
* called in response to events on the dock panel's node. It should | ||
* not be called directly by user code. | ||
*/ | ||
DockPanel.prototype.handleEvent = function (event) { | ||
switch (event.type) { | ||
case 'mousemove': | ||
this._evtMouseMove(event); | ||
case 'p-dragenter': | ||
this._evtDragEnter(event); | ||
break; | ||
case 'mouseup': | ||
this._evtMouseUp(event); | ||
case 'p-dragleave': | ||
this._evtDragLeave(event); | ||
break; | ||
case 'contextmenu': | ||
event.preventDefault(); | ||
event.stopPropagation(); | ||
case 'p-dragover': | ||
this._evtDragOver(event); | ||
break; | ||
case 'p-drop': | ||
this._evtDrop(event); | ||
break; | ||
} | ||
}; | ||
/** | ||
* Add the dock widget as a new split panel next to the reference. | ||
* A message handler invoked on an `'after-attach'` message. | ||
*/ | ||
DockPanel.prototype._splitWidget = function (widget, ref, orientation, after) { | ||
var item = ref ? this._findItemByWidget(ref) : void 0; | ||
if (item) { | ||
this._splitPanel(item.panel, widget, orientation, after); | ||
} | ||
else { | ||
this._addPanel(widget, orientation, after); | ||
} | ||
DockPanel.prototype.onAfterAttach = function (msg) { | ||
_super.prototype.onAfterAttach.call(this, msg); | ||
var node = this.node; | ||
node.addEventListener('p-dragenter', this); | ||
node.addEventListener('p-dragleave', this); | ||
node.addEventListener('p-dragover', this); | ||
node.addEventListener('p-drop', this); | ||
}; | ||
/** | ||
* Add the dock widget as a tab next to the reference. | ||
* A message handler invoked on a `'before-detach'` message. | ||
*/ | ||
DockPanel.prototype._tabifyWidget = function (widget, ref, after) { | ||
var item = ref ? this._findItemByWidget(ref) : void 0; | ||
if (item) { | ||
this._tabifyPanel(item, widget, after); | ||
} | ||
else { | ||
this._addPanel(widget, phosphor_splitpanel_1.Orientation.Horizontal, after); | ||
} | ||
DockPanel.prototype.onBeforeDetach = function (msg) { | ||
_super.prototype.onBeforeDetach.call(this, msg); | ||
var node = this.node; | ||
node.removeEventListener('p-dragenter', this); | ||
node.removeEventListener('p-dragleave', this); | ||
node.removeEventListener('p-dragover', this); | ||
node.removeEventListener('p-drop', this); | ||
}; | ||
/** | ||
* Add a widget to a new tab panel along the given orientation. | ||
* Handle the `'p-dragenter'` event for the dock panel. | ||
*/ | ||
DockPanel.prototype._addPanel = function (widget, orientation, after) { | ||
// Remove the widget from its current parent. | ||
widget.parent = null; | ||
// Create a new dock tab panel to host the widget. | ||
var panel = this._createTabPanel(); | ||
// Create and add the dock item for the widget. | ||
var tab = DockPanel.getTab(widget); | ||
this._items.push({ tab: tab, widget: widget, panel: panel }); | ||
// Add the widget to the tab panel. | ||
panel.stack.addChild(widget); | ||
panel.tabs.addTab(tab); | ||
// Ensure a proper root and add the new tab panel. | ||
this._ensureRoot(orientation); | ||
this._root.insertChild(after ? this._root.childCount : 0, panel); | ||
DockPanel.prototype._evtDragEnter = function (event) { | ||
if (event.mimeData.hasData(FACTORY_MIME)) { | ||
event.preventDefault(); | ||
event.stopPropagation(); | ||
} | ||
}; | ||
/** | ||
* Split a dock item with a widget along the given orientation. | ||
* Handle the `'p-dragleave'` event for the dock panel. | ||
*/ | ||
DockPanel.prototype._splitPanel = function (target, widget, orientation, after) { | ||
// Remove the widget from its current parent. | ||
widget.parent = null; | ||
// Create a new dock tab panel to host the widget. | ||
var panel = this._createTabPanel(); | ||
// Create and add the dock item for the widget. | ||
var tab = DockPanel.getTab(widget); | ||
this._items.push({ tab: tab, widget: widget, panel: panel }); | ||
// Add the widget to the tab panel. | ||
panel.stack.addChild(widget); | ||
panel.tabs.addTab(tab); | ||
// Add the new panel to the parent split panel. This may require | ||
// creating a new child split panel to adhere to the orientation | ||
// constraint. The split panel sizes are updated reasonably. | ||
var splitPanel = target.parent; | ||
if (splitPanel.orientation !== orientation) { | ||
if (splitPanel.childCount <= 1) { | ||
splitPanel.orientation = orientation; | ||
splitPanel.insertChild(+after, panel); | ||
splitPanel.setSizes([1, 1]); | ||
} | ||
else { | ||
var sizes = splitPanel.sizes(); | ||
var i = splitPanel.childIndex(target); | ||
var childSplit = this._createSplitPanel(orientation); | ||
childSplit.addChild(target); | ||
childSplit.insertChild(+after, panel); | ||
splitPanel.insertChild(i, childSplit); | ||
splitPanel.setSizes(sizes); | ||
childSplit.setSizes([1, 1]); | ||
} | ||
DockPanel.prototype._evtDragLeave = function (event) { | ||
event.preventDefault(); | ||
event.stopPropagation(); | ||
var related = event.relatedTarget; | ||
if (!related || !this.node.contains(related)) { | ||
hideOverlay(this); | ||
} | ||
else { | ||
var i = splitPanel.childIndex(target); | ||
var sizes = splitPanel.sizes(); | ||
var size = sizes[i] = sizes[i] / 2; | ||
splitPanel.insertChild(i + (+after), panel); | ||
arrays.insert(sizes, i + (+after), size); | ||
splitPanel.setSizes(sizes); | ||
} | ||
}; | ||
/** | ||
* Add a widget to the tab panel of a given dock item. | ||
* Handle the `'p-dragover'` event for the dock panel. | ||
*/ | ||
DockPanel.prototype._tabifyPanel = function (item, widget, after) { | ||
// Remove the widget from its current parent. | ||
widget.parent = null; | ||
// Create and add the dock item for the widget. | ||
var tab = DockPanel.getTab(widget); | ||
this._items.push({ tab: tab, widget: widget, panel: item.panel }); | ||
// Add the widget to the tab panel. | ||
var i = item.panel.stack.childIndex(item.widget); | ||
item.panel.stack.addChild(widget); | ||
item.panel.tabs.insertTab(i + (+after), tab); | ||
}; | ||
/** | ||
* Handle the `'mousemove'` event for the dock panel. | ||
* | ||
* This is triggered on the document during a tab move operation. | ||
*/ | ||
DockPanel.prototype._evtMouseMove = function (event) { | ||
DockPanel.prototype._evtDragOver = function (event) { | ||
event.preventDefault(); | ||
event.stopPropagation(); | ||
var dragData = this._dragData; | ||
if (!dragData) { | ||
return; | ||
var zone = showOverlay(this, event.clientX, event.clientY); | ||
if (zone === 10 /* Invalid */) { | ||
event.dropAction = phosphor_dragdrop_1.DropAction.None; | ||
} | ||
// Hit test the panels using the current mouse position. | ||
var clientX = event.clientX; | ||
var clientY = event.clientY; | ||
var hitPanel = iterTabPanels(this._root, function (panel) { | ||
return phosphor_domutil_1.hitTest(panel.node, clientX, clientY) ? panel : void 0; | ||
}); | ||
// If the last hit panel is not this hit panel, clear the overlay. | ||
if (dragData.lastHitPanel && dragData.lastHitPanel !== hitPanel) { | ||
dragData.lastHitPanel.hideOverlay(); | ||
else { | ||
event.dropAction = event.proposedAction; | ||
} | ||
// Clear the reference to the hit panel. It will be updated again | ||
// if the mouse is over a panel, but not over the panel's tab bar. | ||
dragData.lastHitPanel = null; | ||
// If the mouse is not over a tab panel, simply update the tab. | ||
var item = dragData.item; | ||
var tabStyle = item.tab.node.style; | ||
if (!hitPanel) { | ||
tabStyle.left = clientX + 'px'; | ||
tabStyle.top = clientY + 'px'; | ||
return; | ||
} | ||
// Handle the case where the mouse is not over a tab bar. This | ||
// saves a reference to the hit panel so that its overlay can be | ||
// hidden once the mouse leaves the panel, and shows the overlay | ||
// provided that the split target is not the current widget. | ||
if (!phosphor_domutil_1.hitTest(hitPanel.tabs.node, clientX, clientY)) { | ||
dragData.lastHitPanel = hitPanel; | ||
if (hitPanel !== item.panel || hitPanel.tabs.tabCount > 0) { | ||
hitPanel.showOverlay(clientX, clientY); | ||
} | ||
tabStyle.left = clientX + 'px'; | ||
tabStyle.top = clientY + 'px'; | ||
return; | ||
} | ||
// Otherwise the mouse is positioned over a tab bar. Hide the | ||
// overlay before attaching the tab to the new tab bar. | ||
hitPanel.hideOverlay(); | ||
// If the hit panel is not the current owner, the current hit | ||
// panel and tab are saved so that they can be restored later. | ||
if (hitPanel !== item.panel) { | ||
dragData.tempPanel = hitPanel; | ||
dragData.tempTab = hitPanel.tabs.selectedTab; | ||
} | ||
// Reset the tab style before attaching the tab to the tab bar. | ||
item.tab.removeClass(DockPanel.p_mod_docking); | ||
tabStyle.top = ''; | ||
tabStyle.left = ''; | ||
// Attach the tab to the hit tab bar. | ||
hitPanel.tabs.attachTab(item.tab, clientX); | ||
// The tab bar takes over movement of the tab. The dock panel still | ||
// listens for the mouseup event in order to complete the move. | ||
document.removeEventListener('mousemove', this, true); | ||
}; | ||
/** | ||
* Handle the 'mouseup' event for the dock panel. | ||
* | ||
* This is triggered on the document during a tab move operation. | ||
* Handle the `'p-drop'` event for the dock panel. | ||
*/ | ||
DockPanel.prototype._evtMouseUp = function (event) { | ||
if (event.button !== 0) { | ||
return; | ||
} | ||
DockPanel.prototype._evtDrop = function (event) { | ||
event.preventDefault(); | ||
event.stopPropagation(); | ||
document.removeEventListener('mouseup', this, true); | ||
document.removeEventListener('mousemove', this, true); | ||
document.removeEventListener('contextmenu', this, true); | ||
var dragData = this._dragData; | ||
if (!dragData) { | ||
hideOverlay(this); | ||
if (event.proposedAction === phosphor_dragdrop_1.DropAction.None) { | ||
event.dropAction = phosphor_dragdrop_1.DropAction.None; | ||
return; | ||
} | ||
this._dragData = null; | ||
// Restore the application cursor and hide the overlay. | ||
dragData.cursorGrab.dispose(); | ||
if (dragData.lastHitPanel) { | ||
dragData.lastHitPanel.hideOverlay(); | ||
} | ||
// Fetch common variables. | ||
var item = dragData.item; | ||
var ownPanel = item.panel; | ||
var ownBar = ownPanel.tabs; | ||
var ownCount = ownBar.tabCount; | ||
var itemTab = item.tab; | ||
// If the tab was being temporarily borrowed by another panel, | ||
// make that relationship permanent by moving the dock widget. | ||
// If the original owner panel becomes empty, it is removed. | ||
// Otherwise, its current index is updated to the next widget. | ||
// The ignoreRemoved flag is set during the widget swap since | ||
// the widget is not actually being removed from the panel. | ||
if (dragData.tempPanel) { | ||
this._ignoreRemoved = true; | ||
item.panel = dragData.tempPanel; | ||
item.panel.stack.addChild(item.widget); | ||
item.panel.stack.currentWidget = item.widget; | ||
this._ignoreRemoved = false; | ||
if (ownPanel.stack.childCount === 0) { | ||
this._removePanel(ownPanel); | ||
} | ||
else { | ||
var i = ownBar.tabIndex(dragData.prevTab); | ||
if (i === -1) | ||
i = Math.min(dragData.index, ownCount - 1); | ||
ownBar.selectedTab = ownBar.tabAt(i); | ||
} | ||
var target = findDockTarget(this, event.clientX, event.clientY); | ||
if (target.zone === 10 /* Invalid */) { | ||
event.dropAction = phosphor_dragdrop_1.DropAction.None; | ||
return; | ||
} | ||
// Snap the split mode before modifying the DOM with the tab insert. | ||
var mode = SplitMode.Invalid; | ||
var hitPanel = dragData.lastHitPanel; | ||
if (hitPanel && (hitPanel !== ownPanel || ownCount !== 0)) { | ||
mode = hitPanel.splitModeAt(event.clientX, event.clientY); | ||
} | ||
// If the mouse was not released over a panel, or if the hit panel | ||
// is the empty owner panel, restore the tab to its position. | ||
var tabStyle = itemTab.node.style; | ||
if (mode === SplitMode.Invalid) { | ||
if (ownBar.selectedTab !== itemTab) { | ||
itemTab.removeClass(DockPanel.p_mod_docking); | ||
tabStyle.top = ''; | ||
tabStyle.left = ''; | ||
ownBar.insertTab(dragData.index, itemTab); | ||
} | ||
var factory = event.mimeData.getData(FACTORY_MIME); | ||
if (typeof factory !== 'function') { | ||
event.dropAction = phosphor_dragdrop_1.DropAction.None; | ||
return; | ||
} | ||
// Remove the tab from the document body and reset its style. | ||
document.body.removeChild(itemTab.node); | ||
itemTab.removeClass(DockPanel.p_mod_docking); | ||
tabStyle.top = ''; | ||
tabStyle.left = ''; | ||
// Split the target panel with the dock widget. | ||
var after = mode === SplitMode.Right || mode === SplitMode.Bottom; | ||
var horiz = mode === SplitMode.Left || mode === SplitMode.Right; | ||
var orientation = horiz ? phosphor_splitpanel_1.Orientation.Horizontal : phosphor_splitpanel_1.Orientation.Vertical; | ||
this._splitPanel(hitPanel, item.widget, orientation, after); | ||
var i = ownBar.tabIndex(dragData.prevTab); | ||
if (i === -1) | ||
i = Math.min(dragData.index, ownCount - 1); | ||
ownBar.selectedTab = ownBar.tabAt(i); | ||
}; | ||
/** | ||
* Ensure the root split panel has the given orientation. | ||
*/ | ||
DockPanel.prototype._ensureRoot = function (orientation) { | ||
// This is a no-op if the root orientation is correct. | ||
if (this._root.orientation === orientation) { | ||
var widget = factory(); | ||
if (!(widget instanceof phosphor_widget_1.Widget)) { | ||
event.dropAction = phosphor_dragdrop_1.DropAction.None; | ||
return; | ||
} | ||
// If the root has at most one child, update the orientation. | ||
if (this._root.childCount <= 1) { | ||
this._root.orientation = orientation; | ||
return; | ||
} | ||
// Otherwise, create a new root panel with the given orientation. | ||
// The existing root panel is added as a child of the new root. | ||
var panel = this._createSplitPanel(orientation); | ||
panel.addChild(this._root); | ||
this._root = panel; | ||
this.addChild(panel); | ||
handleDrop(this, widget, target); | ||
event.dropAction = event.proposedAction; | ||
}; | ||
/** | ||
* Create a new dock tab panel and setup the signal handlers. | ||
* The property descriptor for the spacing between panels. | ||
* | ||
* The default value is `3`. | ||
* | ||
* **See also:** [[spacing]] | ||
*/ | ||
DockPanel.prototype._createTabPanel = function () { | ||
var panel = new DockTabPanel(); | ||
panel.tabs.tabSelected.connect(this._onTabSelected, this); | ||
panel.tabs.tabCloseRequested.connect(this._onTabCloseRequested, this); | ||
panel.tabs.tabDetachRequested.connect(this._onTabDetachRequested, this); | ||
panel.stack.widgetRemoved.connect(this._onWidgetRemoved, this); | ||
return panel; | ||
}; | ||
DockPanel.spacingProperty = new phosphor_properties_1.Property({ | ||
name: 'spacing', | ||
value: 3, | ||
coerce: function (owner, value) { return Math.max(0, value | 0); }, | ||
changed: onSpacingChanged, | ||
}); | ||
return DockPanel; | ||
})(phosphor_stackedpanel_1.StackedPanel); | ||
exports.DockPanel = DockPanel; | ||
/** | ||
* A custom tab bar used by a DockTabPanel. | ||
*/ | ||
var DockTabBar = (function (_super) { | ||
__extends(DockTabBar, _super); | ||
/** | ||
* Create a new dock split panel for the dock panel. | ||
* Construct a new dock tab bar. | ||
*/ | ||
DockPanel.prototype._createSplitPanel = function (orientation) { | ||
var panel = new DockSplitPanel(); | ||
panel.orientation = orientation; | ||
panel.handleSize = this.handleSize; | ||
return panel; | ||
}; | ||
function DockTabBar() { | ||
_super.call(this); | ||
this._drag = null; | ||
this.addClass(TAB_BAR_CLASS); | ||
this.tabsMovable = true; | ||
} | ||
/** | ||
* Remove an empty dock tab panel from the hierarchy. | ||
* | ||
* This ensures that the hierarchy is kept consistent by merging an | ||
* ancestor split panel when it contains only a single child widget. | ||
* Dispose of the resources held by the tab bar. | ||
*/ | ||
DockPanel.prototype._removePanel = function (panel) { | ||
// The parent of a tab panel is always a split panel. | ||
var splitPanel = panel.parent; | ||
// Dispose the panel to ensure its resources are released. | ||
panel.dispose(); | ||
// If the split panel still has multiple children after removing | ||
// the target panel, nothing else needs to be done. | ||
if (splitPanel.childCount > 1) { | ||
return; | ||
DockTabBar.prototype.dispose = function () { | ||
if (this._drag) { | ||
this._drag.dispose(); | ||
this._drag = null; | ||
} | ||
// If the split panel is the root panel and has a remaining child | ||
// which is a split panel, that child becomes the root. | ||
if (splitPanel === this._root) { | ||
if (splitPanel.childCount === 1) { | ||
var child = splitPanel.childAt(0); | ||
if (child instanceof DockSplitPanel) { | ||
var sizes = child.sizes(); | ||
splitPanel.parent = null; | ||
this._root = child; | ||
this.addChild(child); | ||
child.setSizes(sizes); | ||
splitPanel.dispose(); | ||
} | ||
} | ||
return; | ||
} | ||
// Non-root split panels always have a split panel parent and are | ||
// always created with 2 children, so the split panel is guaranteed | ||
// to have a single child at this point. Also, split panels always | ||
// have an orthogonal orientation to their parent, so a grandparent | ||
// and a grandchild split panel will have the same orientation. This | ||
// means the children of the grandchild can be merged as children of | ||
// the grandparent. | ||
var gParent = splitPanel.parent; | ||
var gSizes = gParent.sizes(); | ||
var gChild = splitPanel.childAt(0); | ||
var index = gParent.childIndex(splitPanel); | ||
splitPanel.parent = null; | ||
if (gChild instanceof DockTabPanel) { | ||
gParent.insertChild(index, gChild); | ||
} | ||
else { | ||
var gcsp = gChild; | ||
var gcspSizes = gcsp.sizes(); | ||
var sizeShare = arrays.removeAt(gSizes, index); | ||
for (var i = 0; gcsp.childCount !== 0; ++i) { | ||
gParent.insertChild(index + i, gcsp.childAt(0)); | ||
arrays.insert(gSizes, index + i, sizeShare * gcspSizes[i]); | ||
} | ||
} | ||
gParent.setSizes(gSizes); | ||
splitPanel.dispose(); | ||
_super.prototype.dispose.call(this); | ||
}; | ||
/** | ||
* Abort the tab drag operation if one is in progress. | ||
* A message handler invoked on a `'tear-off-request'` message. | ||
*/ | ||
DockPanel.prototype._abortDrag = function () { | ||
var dragData = this._dragData; | ||
if (!dragData) { | ||
DockTabBar.prototype.onTearOffRequest = function (msg) { | ||
var _this = this; | ||
// Do nothing if a drag is already in progress. | ||
if (this._drag) { | ||
return; | ||
} | ||
this._dragData = null; | ||
// Release the mouse grab and restore the application cursor. | ||
document.removeEventListener('mouseup', this, true); | ||
document.removeEventListener('mousemove', this, true); | ||
document.removeEventListener('contextmenu', this, true); | ||
dragData.cursorGrab.dispose(); | ||
// Hide the overlay for the last hit panel. | ||
if (dragData.lastHitPanel) { | ||
dragData.lastHitPanel.hideOverlay(); | ||
} | ||
// If the tab is borrowed by another tab bar, remove it from | ||
// that tab bar and restore that tab bar's previous tab. | ||
if (dragData.tempPanel) { | ||
var tabs = dragData.tempPanel.tabs; | ||
tabs.removeTab(tabs.selectedTab); | ||
tabs.selectedTab = dragData.tempTab; | ||
} | ||
// Restore the tab to its original location in its owner panel. | ||
var item = dragData.item; | ||
var ownBar = item.panel.tabs; | ||
if (ownBar.selectedTab !== item.tab) { | ||
var tabStyle = item.tab.node.style; | ||
item.tab.removeClass(DockPanel.p_mod_docking); | ||
tabStyle.top = ''; | ||
tabStyle.left = ''; | ||
ownBar.insertTab(dragData.index, item.tab); | ||
} | ||
// Release the tab bar's hold on the mouse. | ||
this.releaseMouse(); | ||
// Setup the mime data for the drag operation. | ||
var widget = msg.item; | ||
var mimeData = new phosphor_dragdrop_1.MimeData(); | ||
mimeData.setData(FACTORY_MIME, function () { return widget; }); | ||
// Create the drag image for the drag operation. | ||
var tabNode = msg.node; | ||
var dragImage = tabNode.cloneNode(true); | ||
// Create the drag object to manage the drag-drop operation. | ||
this._drag = new phosphor_dragdrop_1.Drag({ | ||
mimeData: mimeData, | ||
dragImage: dragImage, | ||
proposedAction: phosphor_dragdrop_1.DropAction.Move, | ||
supportedActions: phosphor_dragdrop_1.DropActions.Move, | ||
}); | ||
// Start the drag operation and cleanup when done. | ||
tabNode.classList.add(HIDDEN_CLASS); | ||
this._drag.start(msg.clientX, msg.clientY).then(function () { | ||
_this._drag = null; | ||
tabNode.classList.remove(HIDDEN_CLASS); | ||
}); | ||
}; | ||
return DockTabBar; | ||
})(phosphor_tabs_1.TabBar); | ||
/** | ||
* A custom tab panel used by a DockPanel. | ||
*/ | ||
var DockTabPanel = (function (_super) { | ||
__extends(DockTabPanel, _super); | ||
/** | ||
* Find the dock item which contains the given tab. | ||
* | ||
* Returns `undefined` if there is no matching item. | ||
* Construct a new dock tab panel. | ||
*/ | ||
DockPanel.prototype._findItemByTab = function (tab) { | ||
return arrays.find(this._items, function (item) { return item.tab === tab; }); | ||
function DockTabPanel() { | ||
_super.call(this); | ||
this.addClass(TAB_PANEL_CLASS); | ||
this.widgets.changed.connect(this._onWidgetsChanged, this); | ||
} | ||
/** | ||
* Create the tab bar for the tab panel. | ||
*/ | ||
DockTabPanel.createTabBar = function () { | ||
return new DockTabBar(); | ||
}; | ||
/** | ||
* Find the dock item which contains the given widget. | ||
* Handle the `changed` signal for the widget list. | ||
* | ||
* Returns `undefined` if there is no matching item. | ||
* This will remove the tab panel if the widget count is zero. | ||
*/ | ||
DockPanel.prototype._findItemByWidget = function (widget) { | ||
return arrays.find(this._items, function (item) { return item.widget === widget; }); | ||
DockTabPanel.prototype._onWidgetsChanged = function () { | ||
if (this.widgets.length === 0) | ||
removeTabPanel(this); | ||
}; | ||
return DockTabPanel; | ||
})(phosphor_tabs_1.TabPanel); | ||
/** | ||
* A custom split panel used by a DockPanel. | ||
*/ | ||
var DockSplitPanel = (function (_super) { | ||
__extends(DockSplitPanel, _super); | ||
/** | ||
* The change handler for the [[handleSizeProperty]]. | ||
* Construct a new dock split panel. | ||
*/ | ||
DockPanel.prototype._onHandleSizeChanged = function (old, value) { | ||
iterSplitPanels(this._root, function (panel) { panel.handleSize = value; }); | ||
}; | ||
function DockSplitPanel(orientation, spacing) { | ||
_super.call(this); | ||
this.addClass(SPLIT_PANEL_CLASS); | ||
this.orientation = orientation; | ||
this.spacing = spacing; | ||
} | ||
return DockSplitPanel; | ||
})(phosphor_splitpanel_1.SplitPanel); | ||
/** | ||
* A node wrapper used as an overlay dock indicator for a dock panel. | ||
*/ | ||
var DockPanelOverlay = (function (_super) { | ||
__extends(DockPanelOverlay, _super); | ||
/** | ||
* Handle the `tabSelected` signal from a tab bar. | ||
* Construct a new dock panel overlay. | ||
*/ | ||
DockPanel.prototype._onTabSelected = function (sender, args) { | ||
var item = this._findItemByTab(args.tab); | ||
if (item && item.panel.tabs === sender) { | ||
item.panel.stack.currentWidget = item.widget; | ||
} | ||
}; | ||
function DockPanelOverlay() { | ||
_super.call(this); | ||
this._zone = 10 /* Invalid */; | ||
this.addClass(OVERLAY_CLASS); | ||
this.addClass(HIDDEN_CLASS); | ||
} | ||
/** | ||
* Handle the `tabCloseRequested` signal from a tab bar. | ||
* Show the overlay with the given zone and geometry | ||
*/ | ||
DockPanel.prototype._onTabCloseRequested = function (sender, args) { | ||
var item = this._findItemByTab(args.tab); | ||
if (item) | ||
item.widget.close(); | ||
DockPanelOverlay.prototype.show = function (zone, left, top, width, height) { | ||
var style = this.node.style; | ||
style.top = top + 'px'; | ||
style.left = left + 'px'; | ||
style.width = width + 'px'; | ||
style.height = height + 'px'; | ||
this.removeClass(HIDDEN_CLASS); | ||
this._setZone(zone); | ||
}; | ||
/** | ||
* Handle the `tabDetachRequested` signal from the tab bar. | ||
* Hide the overlay and reset its zone. | ||
*/ | ||
DockPanel.prototype._onTabDetachRequested = function (sender, args) { | ||
// Find the dock item for the detach operation. | ||
var item = this._findItemByTab(args.tab); | ||
if (!item) { | ||
return; | ||
} | ||
// Setup the initial drag data if it does not exist. | ||
if (!this._dragData) { | ||
this._dragData = { | ||
item: item, | ||
index: args.index, | ||
prevTab: sender.previousTab, | ||
lastHitPanel: null, | ||
cursorGrab: null, | ||
tempPanel: null, | ||
tempTab: null, | ||
}; | ||
} | ||
// Grab the cursor for the drag operation. | ||
var dragData = this._dragData; | ||
dragData.cursorGrab = phosphor_domutil_1.overrideCursor('default'); | ||
// The tab being detached will have one of two states: | ||
// | ||
// 1) The tab is being detached from its owner tab bar. The current | ||
// index is unset before detaching the tab so that the content | ||
// widget does not change during the drag operation. | ||
// | ||
// 2) The tab is being detached from a tab bar which was borrowing | ||
// the tab temporarily. Its previously selected tab is restored. | ||
if (item.panel.tabs === sender) { | ||
sender.selectedTab = null; | ||
sender.removeTabAt(args.index); | ||
} | ||
else { | ||
sender.removeTabAt(args.index); | ||
sender.selectedTab = dragData.tempTab; | ||
} | ||
// Clear the temp panel and tab | ||
dragData.tempPanel = null; | ||
dragData.tempTab = null; | ||
// Setup the style and position for the floating tab. | ||
var style = args.tab.node.style; | ||
style.zIndex = ''; | ||
style.top = args.clientY + 'px'; | ||
style.left = args.clientX + 'px'; | ||
args.tab.addClass(DockPanel.p_mod_docking); | ||
// Add the tab to the document body. | ||
document.body.appendChild(args.tab.node); | ||
// Attach the necessary mouse event listeners. | ||
document.addEventListener('mouseup', this, true); | ||
document.addEventListener('mousemove', this, true); | ||
document.addEventListener('contextmenu', this, true); | ||
DockPanelOverlay.prototype.hide = function () { | ||
this.addClass(HIDDEN_CLASS); | ||
this._setZone(10 /* Invalid */); | ||
}; | ||
/** | ||
* Handle the `widgetRemoved` signal from a stacked widget. | ||
* Set the dock zone for the overlay. | ||
*/ | ||
DockPanel.prototype._onWidgetRemoved = function (sender, args) { | ||
if (this._ignoreRemoved) { | ||
DockPanelOverlay.prototype._setZone = function (zone) { | ||
if (zone === this._zone) { | ||
return; | ||
} | ||
var item = this._findItemByWidget(args.widget); | ||
if (!item) { | ||
return; | ||
} | ||
this._abortDrag(); | ||
arrays.remove(this._items, item); | ||
item.panel.tabs.removeTab(item.tab); | ||
if (item.panel.stack.childCount === 0) { | ||
this._removePanel(item.panel); | ||
} | ||
var oldClass = DockPanelOverlay.zoneMap[this._zone]; | ||
var newClass = DockPanelOverlay.zoneMap[zone]; | ||
if (oldClass) | ||
this.removeClass(oldClass); | ||
if (newClass) | ||
this.addClass(newClass); | ||
this._zone = zone; | ||
}; | ||
/** | ||
* The class name added to DockPanel instances. | ||
* A mapping of dock zone enum value to modifier class. | ||
*/ | ||
DockPanel.p_DockPanel = 'p-DockPanel'; | ||
/** | ||
* The class name added to a tab which is being docked. | ||
*/ | ||
DockPanel.p_mod_docking = 'p-mod-docking'; | ||
/** | ||
* A convenience alias of the `SplitTop` [[DockMode]]. | ||
*/ | ||
DockPanel.SplitTop = DockMode.SplitTop; | ||
/** | ||
* A convenience alias of the `SplitLeft` [[DockMode]]. | ||
*/ | ||
DockPanel.SplitLeft = DockMode.SplitLeft; | ||
/** | ||
* A convenience alias of the `SplitRight` [[DockMode]]. | ||
*/ | ||
DockPanel.SplitRight = DockMode.SplitRight; | ||
/** | ||
* A convenience alias of the `SplitBottom` [[DockMode]]. | ||
*/ | ||
DockPanel.SplitBottom = DockMode.SplitBottom; | ||
/** | ||
* A convenience alias of the `TabBefore` [[DockMode]]. | ||
*/ | ||
DockPanel.TabBefore = DockMode.TabBefore; | ||
/** | ||
* A convenience alias of the `TabAfter` [[DockMode]]. | ||
*/ | ||
DockPanel.TabAfter = DockMode.TabAfter; | ||
/** | ||
* The property descriptor for the `tab` attached property. | ||
* | ||
* This controls the tab used for a widget in a dock panel. | ||
* | ||
* #### Notes | ||
* If the tab for a widget is changed, the new tab will not be | ||
* reflected until the widget is re-inserted into the dock panel. | ||
* However, in-place changes to the tab's properties **will** be | ||
* reflected. | ||
* | ||
* **See also:** [[getTab]], [[setTab]] | ||
*/ | ||
DockPanel.tabProperty = new phosphor_properties_1.Property({ | ||
value: null, | ||
coerce: function (owner, value) { return value || null; }, | ||
}); | ||
/** | ||
* The property descriptor for the dock panel handle size. | ||
* | ||
* The controls the size of the split handles placed between the | ||
* tabbed panel, in pixels. The default value is `3`. | ||
* | ||
* **See also:** [[handleSize]] | ||
*/ | ||
DockPanel.handleSizeProperty = new phosphor_properties_1.Property({ | ||
value: 3, | ||
coerce: function (owner, value) { return Math.max(0, value | 0); }, | ||
changed: function (owner, old, value) { return owner._onHandleSizeChanged(old, value); }, | ||
}); | ||
return DockPanel; | ||
})(phosphor_boxpanel_1.BoxPanel); | ||
exports.DockPanel = DockPanel; | ||
DockPanelOverlay.zoneMap = [ | ||
ROOT_TOP_CLASS, | ||
ROOT_LEFT_CLASS, | ||
ROOT_RIGHT_CLASS, | ||
ROOT_BOTTOM_CLASS, | ||
ROOT_CENTER_CLASS, | ||
PANEL_TOP_CLASS, | ||
PANEL_LEFT_CLASS, | ||
PANEL_RIGHT_CLASS, | ||
PANEL_BOTTOM_CLASS, | ||
PANEL_CENTER_CLASS | ||
]; | ||
return DockPanelOverlay; | ||
})(phosphor_nodewrapper_1.NodeWrapper); | ||
/** | ||
* Iterate over the DockPanels starting with the given root split panel. | ||
* A private attached property for the dock panel root. | ||
*/ | ||
var rootProperty = new phosphor_properties_1.Property({ | ||
name: 'root', | ||
value: null, | ||
changed: onRootChanged, | ||
}); | ||
/** | ||
* A private attached property for the dock panel overlay. | ||
*/ | ||
var overlayProperty = new phosphor_properties_1.Property({ | ||
name: 'overlay', | ||
create: createOverlay, | ||
}); | ||
/** | ||
* Get the root panel for a dock panel. | ||
*/ | ||
function getRoot(panel) { | ||
return rootProperty.get(panel); | ||
} | ||
/** | ||
* Set the root panel for a dock panel. | ||
*/ | ||
function setRoot(panel, root) { | ||
rootProperty.set(panel, root); | ||
} | ||
/** | ||
* The change handler for the dock panel `rootProperty`. | ||
* | ||
* Iteration stops when the callback returns anything but undefined. | ||
* This will re-parent the new root and set it as the current widget. | ||
* | ||
* The old root is not modified. | ||
*/ | ||
function iterTabPanels(root, cb) { | ||
for (var i = 0, n = root.childCount; i < n; ++i) { | ||
var result = void 0; | ||
var panel = root.childAt(i); | ||
if (panel instanceof DockTabPanel) { | ||
result = cb(panel); | ||
function onRootChanged(panel, old, root) { | ||
if (!root) | ||
return; | ||
root.parent = panel; | ||
panel.currentWidget = root; | ||
} | ||
/** | ||
* Get the overlay for a dock panel. | ||
*/ | ||
function getOverlay(panel) { | ||
return overlayProperty.get(panel); | ||
} | ||
/** | ||
* The creation handler for the dock panel `overlayProperty`. | ||
* | ||
* This will create and install the overlay for the panel. | ||
*/ | ||
function createOverlay(panel) { | ||
var overlay = new DockPanelOverlay(); | ||
panel.node.appendChild(overlay.node); | ||
return overlay; | ||
} | ||
/** | ||
* The change handler for the `spacing` property of a dock panel. | ||
*/ | ||
function onSpacingChanged(panel, old, spacing) { | ||
var root = getRoot(panel); | ||
if (root instanceof DockSplitPanel) { | ||
updateSpacing(root, spacing); | ||
} | ||
} | ||
/** | ||
* Recursively update the spacing of a dock split panel. | ||
*/ | ||
function updateSpacing(panel, spacing) { | ||
var children = panel.children; | ||
for (var i = 0, n = children.length; i < n; ++i) { | ||
var child = children.get(i); | ||
if (child instanceof DockSplitPanel) { | ||
updateSpacing(child, spacing); | ||
} | ||
else if (panel instanceof DockSplitPanel) { | ||
result = iterTabPanels(panel, cb); | ||
} | ||
panel.spacing = spacing; | ||
} | ||
/** | ||
* Throw an internal dock panel error. | ||
*/ | ||
function internalError() { | ||
throw new Error('Internal DockPanel Error.'); | ||
} | ||
/** | ||
* Test whether a dock panel contains the given widget. | ||
* | ||
* For this condition to be `true`, the widget must be a logical child | ||
* of a `DockTabPanel`, which itself must be a proper descendant of the | ||
* given dock panel. | ||
*/ | ||
function dockPanelContains(panel, widget) { | ||
var stack = widget.parent; | ||
if (!stack) { | ||
return false; | ||
} | ||
var tabs = stack.parent; | ||
if (!(tabs instanceof DockTabPanel)) { | ||
return false; | ||
} | ||
var parent = tabs.parent; | ||
while (parent) { | ||
if (parent === panel) { | ||
return true; | ||
} | ||
if (result !== void 0) { | ||
return result; | ||
if (!(parent instanceof DockSplitPanel)) { | ||
return false; | ||
} | ||
parent = parent.parent; | ||
} | ||
return void 0; | ||
return false; | ||
} | ||
/** | ||
* Iterate over the DockSplitPanel starting with the given root panel. | ||
* Find the ancestor dock tab panel for the given widget. | ||
* | ||
* Iteration stops when the callback returns anything but `undefined`. | ||
* This assumes the widget already belongs to a dock panel, and will | ||
* throw an error if that assumption does not hold. | ||
*/ | ||
function iterSplitPanels(root, cb) { | ||
var result = cb(root); | ||
if (result !== void 0) { | ||
return result; | ||
function findTabPanel(widget) { | ||
var stack = widget.parent; | ||
if (!stack) { | ||
internalError(); | ||
} | ||
for (var i = 0, n = root.childCount; i < n; ++i) { | ||
var panel = root.childAt(i); | ||
if (panel instanceof DockSplitPanel) { | ||
result = iterSplitPanels(panel, cb); | ||
if (result !== void 0) { | ||
return result; | ||
} | ||
var tabs = stack.parent; | ||
if (!(tabs instanceof DockTabPanel)) { | ||
internalError(); | ||
} | ||
return tabs; | ||
} | ||
/** | ||
* Find the first dock tab panel for the given dock panel. | ||
* | ||
* This returns `null` if the dock panel has no content. It will throw | ||
* an error if the structure of the dock panel is found to be invalid. | ||
*/ | ||
function findFirstTabPanel(panel) { | ||
var root = getRoot(panel); | ||
while (root) { | ||
if (root instanceof DockTabPanel) { | ||
return root; | ||
} | ||
if (!(root instanceof DockSplitPanel) || root.children.length === 0) { | ||
internalError(); | ||
} | ||
root = root.children.get(0); | ||
} | ||
return void 0; | ||
return null; | ||
} | ||
/** | ||
* Create the overlay node for a dock tab panel. | ||
* Get or create the first dock tab panel for the given dock panel. | ||
* | ||
* If dock panel has no root, a new tab panel will be created and | ||
* added as the root. An error will be thrown if the structure of | ||
* the dock panel is found to be invalid. | ||
*/ | ||
function createOverlay() { | ||
var overlay = document.createElement('div'); | ||
overlay.className = DockTabPanel.p_DockTabPanel_overlay; | ||
overlay.style.display = 'none'; | ||
return overlay; | ||
function ensureFirstTabPanel(panel) { | ||
var tabs = findFirstTabPanel(panel); | ||
if (!tabs) { | ||
tabs = new DockTabPanel(); | ||
setRoot(panel, tabs); | ||
} | ||
return tabs; | ||
} | ||
/** | ||
* The split modes used to indicate a dock panel split direction. | ||
* Ensure the root panel is a splitter with the given orientation. | ||
* | ||
* This will throw an error if the panel does not have a current root, | ||
* since that would violate the invariants of the dock panel structure. | ||
*/ | ||
var SplitMode; | ||
(function (SplitMode) { | ||
SplitMode[SplitMode["Top"] = 0] = "Top"; | ||
SplitMode[SplitMode["Left"] = 1] = "Left"; | ||
SplitMode[SplitMode["Right"] = 2] = "Right"; | ||
SplitMode[SplitMode["Bottom"] = 3] = "Bottom"; | ||
SplitMode[SplitMode["Invalid"] = 4] = "Invalid"; | ||
})(SplitMode || (SplitMode = {})); | ||
function ensureSplitRoot(panel, orientation) { | ||
var oldRoot = getRoot(panel); | ||
if (!oldRoot) { | ||
internalError(); | ||
} | ||
if (oldRoot instanceof DockSplitPanel) { | ||
if (oldRoot.orientation === orientation) { | ||
return oldRoot; | ||
} | ||
if (oldRoot.children.length <= 1) { | ||
oldRoot.orientation = orientation; | ||
return oldRoot; | ||
} | ||
} | ||
var newRoot = new DockSplitPanel(orientation, panel.spacing); | ||
newRoot.children.add(oldRoot); | ||
setRoot(panel, newRoot); | ||
oldRoot.hidden = false; | ||
return newRoot; | ||
} | ||
/** | ||
* A tabbed panel used by a DockPanel. | ||
* Ensure the given widget is the current widget in its tab panel. | ||
* | ||
* This tab panel acts as a simple container for a tab bar and stacked | ||
* panel, plus a bit of logic to manage the docking overlay. The dock | ||
* panel manages the tab bar and stacked panel directly, as there is | ||
* not always a 1:1 association between a tab and panel. | ||
* This is a no-op if the widget is not contained in a dock tab panel. | ||
*/ | ||
var DockTabPanel = (function (_super) { | ||
__extends(DockTabPanel, _super); | ||
/** | ||
* Construct a new dock tab panel. | ||
*/ | ||
function DockTabPanel() { | ||
_super.call(this); | ||
this._overlayTimer = 0; | ||
this._overlayHidden = true; | ||
this._tabs = new phosphor_tabs_1.TabBar(); | ||
this._stack = new phosphor_stackedpanel_1.StackedPanel(); | ||
this.addClass(DockTabPanel.p_DockTabPanel); | ||
this.direction = phosphor_boxpanel_1.BoxPanel.TopToBottom; | ||
this.spacing = 0; | ||
phosphor_boxpanel_1.BoxPanel.setStretch(this._tabs, 0); | ||
phosphor_boxpanel_1.BoxPanel.setStretch(this._stack, 1); | ||
this.addChild(this._tabs); | ||
this.addChild(this._stack); | ||
this._overlay = createOverlay(); | ||
this.node.appendChild(this._overlay); | ||
function selectWidget(widget) { | ||
var stack = widget.parent; | ||
if (!stack) { | ||
return; | ||
} | ||
/** | ||
* Dispose of the resources held by the widget. | ||
*/ | ||
DockTabPanel.prototype.dispose = function () { | ||
this._clearOverlayTimer(); | ||
this._tabs = null; | ||
this._stack = null; | ||
this._overlay = null; | ||
_super.prototype.dispose.call(this); | ||
}; | ||
Object.defineProperty(DockTabPanel.prototype, "tabs", { | ||
/** | ||
* Get the tab bar for the dock tab panel. | ||
*/ | ||
get: function () { | ||
return this._tabs; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
Object.defineProperty(DockTabPanel.prototype, "stack", { | ||
/** | ||
* Get the stacked panel for the dock tab panel. | ||
*/ | ||
get: function () { | ||
return this._stack; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
/** | ||
* Compute the split mode for the given client position. | ||
*/ | ||
DockTabPanel.prototype.splitModeAt = function (clientX, clientY) { | ||
var rect = this.stack.node.getBoundingClientRect(); | ||
var fracX = (clientX - rect.left) / rect.width; | ||
var fracY = (clientY - rect.top) / rect.height; | ||
if (fracX < 0.0 || fracX > 1.0 || fracY < 0.0 || fracY > 1.0) { | ||
return SplitMode.Invalid; | ||
var tabs = stack.parent; | ||
if (!(tabs instanceof DockTabPanel)) { | ||
return; | ||
} | ||
tabs.currentWidget = widget; | ||
} | ||
/** | ||
* Validate the insert arguments for a dock panel. | ||
* | ||
* This will throw an error if the target widget is null, or if the | ||
* reference widget is not null and not contained by the dock panel. | ||
*/ | ||
function validateInsertArgs(panel, widget, ref) { | ||
if (!widget) { | ||
throw new Error('Target widget is null.'); | ||
} | ||
if (ref && !dockPanelContains(panel, ref)) { | ||
throw new Error('Reference widget not contained by the dock panel.'); | ||
} | ||
} | ||
/** | ||
* Insert a widget as a new split panel in a dock panel. | ||
* | ||
* @param panel - The dock panel of interest. | ||
* | ||
* @param widget - The widget to insert. | ||
* | ||
* @param ref - The reference widget. This may be null. | ||
* | ||
* @param orientation - The orientation of the split. | ||
* | ||
* @param after - Whether to insert before or after the reference. | ||
* | ||
* @throws An error if the `widget` or `ref` are invalid. | ||
*/ | ||
function insertSplit(panel, widget, ref, orientation, after) { | ||
// Ensure the insert args are valid. | ||
validateInsertArgs(panel, widget, ref); | ||
// If the widget is the same as the ref, there's nothing to do. | ||
if (widget === ref) { | ||
return; | ||
} | ||
// Unparent the widget before performing the insert. This ensures | ||
// that structural changes to the dock panel occur before searching | ||
// for the insert location. | ||
widget.parent = null; | ||
// Setup the new tab panel to host the widget. | ||
var tabPanel = new DockTabPanel(); | ||
tabPanel.widgets.add(widget); | ||
// If there is no root, add the new tab panel as the root. | ||
if (!getRoot(panel)) { | ||
setRoot(panel, tabPanel); | ||
return; | ||
} | ||
// If the ref widget is null, split the root panel. | ||
if (!ref) { | ||
var root = ensureSplitRoot(panel, orientation); | ||
var sizes_1 = root.sizes(); | ||
var count = sizes_1.length; | ||
arrays.insert(sizes_1, after ? count : 0, 0.5); | ||
root.children.insert(after ? count : 0, tabPanel); | ||
root.setSizes(sizes_1); | ||
return; | ||
} | ||
// Lookup the tab panel for the ref widget. | ||
var refTabPanel = findTabPanel(ref); | ||
// If the ref tab panel parent is the dock panel, split the root. | ||
if (refTabPanel.parent === panel) { | ||
var root = ensureSplitRoot(panel, orientation); | ||
root.children.insert(after ? 1 : 0, tabPanel); | ||
root.setSizes([1, 1]); | ||
return; | ||
} | ||
// Assert the parent of the ref tab panel is a dock split panel. | ||
if (!(refTabPanel.parent instanceof DockSplitPanel)) { | ||
internalError(); | ||
} | ||
// Cast the ref tab panel parent to a dock split panel. | ||
var splitPanel = refTabPanel.parent; | ||
// If the split panel is the correct orientation, the widget | ||
// can be inserted directly and sized to 1/2 the ref space. | ||
if (splitPanel.orientation === orientation) { | ||
var i_1 = splitPanel.children.indexOf(refTabPanel); | ||
var sizes_2 = splitPanel.sizes(); | ||
var size = sizes_2[i_1] = sizes_2[i_1] / 2; | ||
arrays.insert(sizes_2, after ? i_1 + 1 : i_1, size); | ||
splitPanel.children.insert(after ? i_1 + 1 : i_1, tabPanel); | ||
splitPanel.setSizes(sizes_2); | ||
return; | ||
} | ||
// If the split panel only has a single child, its orientation | ||
// can be changed directly and its sizes set to a 1:1 ratio. | ||
if (splitPanel.children.length === 1) { | ||
splitPanel.orientation = orientation; | ||
splitPanel.children.insert(after ? 1 : 0, tabPanel); | ||
splitPanel.setSizes([1, 1]); | ||
return; | ||
} | ||
// Assert the split panel has more than one child. | ||
if (splitPanel.children.length === 0) { | ||
internalError(); | ||
} | ||
// Otherwise, a new split panel with the correct orientation needs | ||
// to be created to hold the ref panel and tab panel, and inserted | ||
// in the previous location of the ref panel. | ||
var sizes = splitPanel.sizes(); | ||
var i = splitPanel.children.indexOf(refTabPanel); | ||
var childSplit = new DockSplitPanel(orientation, panel.spacing); | ||
childSplit.children.add(refTabPanel); | ||
childSplit.children.insert(after ? 1 : 0, tabPanel); | ||
splitPanel.children.insert(i, childSplit); | ||
splitPanel.setSizes(sizes); | ||
childSplit.setSizes([1, 1]); | ||
} | ||
/** | ||
* Insert a widget as a sibling tab in a dock panel. | ||
* | ||
* @param panel - The dock panel of interest. | ||
* | ||
* @param widget - The widget to insert. | ||
* | ||
* @param ref - The reference widget. This may be null. | ||
* | ||
* @param after - Whether to insert before or after the reference. | ||
* | ||
* @throws An error if the `widget` or `ref` are invalid. | ||
*/ | ||
function insertTab(panel, widget, ref, after) { | ||
// Ensure the insert args are valid. | ||
validateInsertArgs(panel, widget, ref); | ||
// If the widget is the same as the ref, there's nothing to do. | ||
if (widget === ref) { | ||
return; | ||
} | ||
// Unparent the widget before performing the insert. This ensures | ||
// that structural changes to the dock panel occur before searching | ||
// for the insert location. | ||
widget.parent = null; | ||
// Find the index and tab panel for the insert operation. | ||
var index; | ||
var tabPanel; | ||
if (ref) { | ||
tabPanel = findTabPanel(ref); | ||
index = tabPanel.widgets.indexOf(ref) + (after ? 1 : 0); | ||
} | ||
else { | ||
tabPanel = ensureFirstTabPanel(panel); | ||
index = after ? tabPanel.widgets.length : 0; | ||
} | ||
// Insert the widget into the tab panel at the proper location. | ||
tabPanel.widgets.insert(index, widget); | ||
} | ||
/** | ||
* Remove an empty dock tab panel from the hierarchy. | ||
* | ||
* This ensures that the hierarchy is kept consistent by merging an | ||
* ancestor split panel when it contains only a single child widget. | ||
*/ | ||
function removeTabPanel(tabPanel) { | ||
// Assert the tab panel is empty. | ||
if (tabPanel.widgets.length !== 0) { | ||
internalError(); | ||
} | ||
// If the parent of the tab panel is a dock panel, just remove it. | ||
if (tabPanel.parent instanceof DockPanel) { | ||
setRoot(tabPanel.parent, null); | ||
tabPanel.dispose(); | ||
return; | ||
} | ||
// Assert the tab panel parent is a dock split panel. | ||
if (!(tabPanel.parent instanceof DockSplitPanel)) { | ||
internalError(); | ||
} | ||
// Cast the tab panel parent to a dock split panel. | ||
var splitPanel = tabPanel.parent; | ||
// Assert the split panel has at least two children. | ||
if (splitPanel.children.length < 2) { | ||
internalError(); | ||
} | ||
// Dispose the tab panel to ensure its resources are released. | ||
tabPanel.dispose(); | ||
// If the split panel still has multiple children, there is | ||
// nothing more to do. | ||
if (splitPanel.children.length > 1) { | ||
return; | ||
} | ||
// Extract the remaining child from the split panel. | ||
var child = splitPanel.children.get(0); | ||
// Assert the remaining child is a proper panel type. | ||
if (!(child instanceof DockTabPanel) && !(child instanceof DockSplitPanel)) { | ||
internalError(); | ||
} | ||
// If the parent of the split panel is a dock panel, replace it. | ||
if (splitPanel.parent instanceof DockPanel) { | ||
setRoot(splitPanel.parent, child); | ||
splitPanel.dispose(); | ||
return; | ||
} | ||
// Assert the split panel parent is a dock split panel. | ||
if (!(splitPanel.parent instanceof DockSplitPanel)) { | ||
internalError(); | ||
} | ||
// Cast the split panel parent to a dock split panel. | ||
var grandPanel = splitPanel.parent; | ||
// If the child is a dock tab panel, replace the split panel. | ||
if (child instanceof DockTabPanel) { | ||
var sizes = grandPanel.sizes(); | ||
var index_1 = grandPanel.children.indexOf(splitPanel); | ||
grandPanel.children.set(index_1, child); | ||
grandPanel.setSizes(sizes); | ||
splitPanel.dispose(); | ||
return; | ||
} | ||
// Cast the child to a dock split panel. | ||
var childSplit = child; | ||
// Child splitters have an orthogonal orientation to their parent. | ||
// Assert the orientation of the child matches the grand parent. | ||
if (childSplit.orientation !== grandPanel.orientation) { | ||
internalError(); | ||
} | ||
// The grand children can now be merged with their grand parent. | ||
// Start by fetching the relevant current sizes and insert index. | ||
var childSizes = childSplit.sizes(); | ||
var grandSizes = grandPanel.sizes(); | ||
var childChildren = childSplit.children; | ||
var grandChildren = grandPanel.children; | ||
// Remove the split panel and store its share of the size. | ||
var index = grandChildren.indexOf(splitPanel); | ||
var sizeShare = arrays.removeAt(grandSizes, index); | ||
splitPanel.parent = null; | ||
// Merge the grand children and maintain their relative size. | ||
for (var i = 0; childChildren.length !== 0; ++i) { | ||
grandChildren.insert(index + i, childChildren.get(0)); | ||
arrays.insert(grandSizes, index + i, sizeShare * childSizes[i]); | ||
} | ||
// Update the grand parent sizes and dispose the removed panel. | ||
grandPanel.setSizes(grandSizes); | ||
splitPanel.dispose(); | ||
} | ||
/** | ||
* Recursively iterate over the dock tab panels of a root panel. | ||
* | ||
* Iteration stops if the callback returns anything but `undefined`. | ||
*/ | ||
function iterTabPanels(root, callback) { | ||
if (root instanceof DockTabPanel) { | ||
return callback(root); | ||
} | ||
if (!(root instanceof DockSplitPanel)) { | ||
internalError(); | ||
} | ||
var children = root.children; | ||
for (var i = 0; i < children.length; ++i) { | ||
var child = children.get(i); | ||
var result = iterTabPanels(child, callback); | ||
if (result !== void 0) | ||
return result; | ||
} | ||
return void 0; | ||
} | ||
/** | ||
* Get the root edge zone for the given node and client position. | ||
* | ||
* This assumes the position lies within the node's client rect. | ||
* | ||
* Returns the `Invalid` zone if the position is not within an edge. | ||
*/ | ||
function getEdgeZone(node, x, y) { | ||
var zone; | ||
var rect = node.getBoundingClientRect(); | ||
if (x < rect.left + EDGE_SIZE) { | ||
if (y - rect.top < x - rect.left) { | ||
zone = 0 /* RootTop */; | ||
} | ||
var mode; | ||
var normX = fracX > 0.5 ? 1 - fracX : fracX; | ||
var normY = fracY > 0.5 ? 1 - fracY : fracY; | ||
if (normX < normY) { | ||
mode = fracX <= 0.5 ? SplitMode.Left : SplitMode.Right; | ||
else if (rect.bottom - y < x - rect.left) { | ||
zone = 3 /* RootBottom */; | ||
} | ||
else { | ||
mode = fracY <= 0.5 ? SplitMode.Top : SplitMode.Bottom; | ||
zone = 1 /* RootLeft */; | ||
} | ||
return mode; | ||
}; | ||
/** | ||
* Show the dock overlay for the given client position. | ||
* | ||
* If the overlay is already visible, it will be adjusted. | ||
*/ | ||
DockTabPanel.prototype.showOverlay = function (clientX, clientY) { | ||
this._clearOverlayTimer(); | ||
var rect = this.node.getBoundingClientRect(); | ||
var box = this.boxSizing; | ||
var top = box.paddingTop; | ||
var left = box.paddingLeft; | ||
var right = box.paddingRight; | ||
var bottom = box.paddingBottom; | ||
switch (this.splitModeAt(clientX, clientY)) { | ||
case SplitMode.Left: | ||
right = rect.width / 2; | ||
break; | ||
case SplitMode.Right: | ||
left = rect.width / 2; | ||
break; | ||
case SplitMode.Top: | ||
bottom = rect.height / 2; | ||
break; | ||
case SplitMode.Bottom: | ||
top = rect.height / 2; | ||
break; | ||
} | ||
else if (x >= rect.right - EDGE_SIZE) { | ||
if (y - rect.top < rect.right - x) { | ||
zone = 0 /* RootTop */; | ||
} | ||
// The first time the overlay is made visible, it is positioned at | ||
// the cursor with zero size before being displayed. This allows | ||
// for a nice transition to the normally computed size. Since the | ||
// elements starts with display: none, a restyle must be forced. | ||
var style = this._overlay.style; | ||
if (this._overlayHidden) { | ||
this._overlayHidden = false; | ||
style.top = clientY - rect.top + 'px'; | ||
style.left = clientX - rect.left + 'px'; | ||
style.right = rect.right - clientX + 'px'; | ||
style.bottom = rect.bottom - clientY + 'px'; | ||
style.display = ''; | ||
this._overlay.offsetWidth; // force layout | ||
else if (rect.bottom - y < rect.right - x) { | ||
zone = 3 /* RootBottom */; | ||
} | ||
style.opacity = '1'; | ||
style.top = top + 'px'; | ||
style.left = left + 'px'; | ||
style.right = right + 'px'; | ||
style.bottom = bottom + 'px'; | ||
}; | ||
/** | ||
* Hide the dock overlay. | ||
* | ||
* If the overlay is already hidden, this is a no-op. | ||
*/ | ||
DockTabPanel.prototype.hideOverlay = function () { | ||
var _this = this; | ||
if (this._overlayHidden) { | ||
return; | ||
else { | ||
zone = 2 /* RootRight */; | ||
} | ||
this._clearOverlayTimer(); | ||
this._overlayHidden = true; | ||
this._overlay.style.opacity = '0'; | ||
this._overlayTimer = setTimeout(function () { | ||
_this._overlayTimer = 0; | ||
_this._overlay.style.display = 'none'; | ||
}, 150); | ||
}; | ||
/** | ||
* Clear the overlay timer. | ||
*/ | ||
DockTabPanel.prototype._clearOverlayTimer = function () { | ||
if (this._overlayTimer) { | ||
clearTimeout(this._overlayTimer); | ||
this._overlayTimer = 0; | ||
} | ||
else if (y < rect.top + EDGE_SIZE) { | ||
zone = 0 /* RootTop */; | ||
} | ||
else if (y >= rect.bottom - EDGE_SIZE) { | ||
zone = 3 /* RootBottom */; | ||
} | ||
else { | ||
zone = 10 /* Invalid */; | ||
} | ||
return zone; | ||
} | ||
/** | ||
* Get the panel zone for the given node and position. | ||
* | ||
* This assumes the position lies within the node's client rect. | ||
* | ||
* This always returns a valid zone. | ||
*/ | ||
function getPanelZone(node, x, y) { | ||
var zone; | ||
var rect = node.getBoundingClientRect(); | ||
var fracX = (x - rect.left) / rect.width; | ||
var fracY = (y - rect.top) / rect.height; | ||
if (fracX < 1 / 3) { | ||
if (fracY < fracX) { | ||
zone = 5 /* PanelTop */; | ||
} | ||
}; | ||
/** | ||
* The class name added to DockTabPanel instances. | ||
*/ | ||
DockTabPanel.p_DockTabPanel = 'p-DockTabPanel'; | ||
/** | ||
* `p-DockTabPanel-overlay`: the class name added to a DockTabPanel overlay. | ||
*/ | ||
DockTabPanel.p_DockTabPanel_overlay = 'p-DockTabPanel-overlay'; | ||
return DockTabPanel; | ||
})(phosphor_boxpanel_1.BoxPanel); | ||
else if (1 - fracY < fracX) { | ||
zone = 8 /* PanelBottom */; | ||
} | ||
else { | ||
zone = 6 /* PanelLeft */; | ||
} | ||
} | ||
else if (fracX < 2 / 3) { | ||
if (fracY < 1 / 3) { | ||
zone = 5 /* PanelTop */; | ||
} | ||
else if (fracY < 2 / 3) { | ||
zone = 9 /* PanelCenter */; | ||
} | ||
else { | ||
zone = 8 /* PanelBottom */; | ||
} | ||
} | ||
else { | ||
if (fracY < 1 - fracX) { | ||
zone = 5 /* PanelTop */; | ||
} | ||
else if (fracY > fracX) { | ||
zone = 8 /* PanelBottom */; | ||
} | ||
else { | ||
zone = 7 /* PanelRight */; | ||
} | ||
} | ||
return zone; | ||
} | ||
/** | ||
* A split panel used by a DockPanel. | ||
* Find the dock target for the given client position. | ||
*/ | ||
function findDockTarget(panel, clientX, clientY) { | ||
var root = getRoot(panel); | ||
if (!root) { | ||
return { zone: 4 /* RootCenter */, panel: null }; | ||
} | ||
if (!phosphor_domutil_1.hitTest(root.node, clientX, clientY)) { | ||
return { zone: 10 /* Invalid */, panel: null }; | ||
} | ||
var edgeZone = getEdgeZone(root.node, clientX, clientY); | ||
if (edgeZone !== 10 /* Invalid */) { | ||
return { zone: edgeZone, panel: null }; | ||
} | ||
var hitPanel = iterTabPanels(root, function (tabs) { | ||
return phosphor_domutil_1.hitTest(tabs.node, clientX, clientY) ? tabs : void 0; | ||
}); | ||
if (!hitPanel) { | ||
return { zone: 10 /* Invalid */, panel: null }; | ||
} | ||
var panelZone = getPanelZone(hitPanel.node, clientX, clientY); | ||
return { zone: panelZone, panel: hitPanel }; | ||
} | ||
/** | ||
* Hide the dock panel overlay for the given dock panel. | ||
*/ | ||
function hideOverlay(panel) { | ||
getOverlay(panel).hide(); | ||
} | ||
/** | ||
* Show the dock panel overlay indicator at the given client position. | ||
* | ||
* This class serves to differentiate a split panel used by a | ||
* dock panel from user provided split panel content widgets. | ||
* If the position is not over a dock zone, the overlay is hidden. | ||
* | ||
* This returns the dock zone used to display the overlay. | ||
*/ | ||
var DockSplitPanel = (function (_super) { | ||
__extends(DockSplitPanel, _super); | ||
/** | ||
* Construct a new dock split panel. | ||
*/ | ||
function DockSplitPanel() { | ||
_super.call(this); | ||
this.addClass(DockSplitPanel.p_DockSplitPanel); | ||
function showOverlay(panel, clientX, clientY) { | ||
// Find the dock target for the given client position. | ||
var target = findDockTarget(panel, clientX, clientY); | ||
// If the dock zone is invalid, hide the overlay and bail. | ||
if (target.zone === 10 /* Invalid */) { | ||
getOverlay(panel).hide(); | ||
return target.zone; | ||
} | ||
/** | ||
* The class name added to DockSplitPanel instances. | ||
*/ | ||
DockSplitPanel.p_DockSplitPanel = 'p-DockSplitPanel'; | ||
return DockSplitPanel; | ||
})(phosphor_splitpanel_1.SplitPanel); | ||
// Setup the variables needed to compute the overlay geometry. | ||
var top; | ||
var left; | ||
var width; | ||
var height; | ||
var pcr; | ||
var box = phosphor_domutil_1.boxSizing(panel.node); // TODO cache this? | ||
var rect = panel.node.getBoundingClientRect(); | ||
// Compute the overlay geometry based on the dock zone. | ||
switch (target.zone) { | ||
case 0 /* RootTop */: | ||
top = box.paddingTop; | ||
left = box.paddingLeft; | ||
width = rect.width - box.horizontalSum; | ||
height = (rect.height - box.verticalSum) / 3; | ||
break; | ||
case 1 /* RootLeft */: | ||
top = box.paddingTop; | ||
left = box.paddingLeft; | ||
width = (rect.width - box.horizontalSum) / 3; | ||
height = rect.height - box.verticalSum; | ||
break; | ||
case 2 /* RootRight */: | ||
top = box.paddingTop; | ||
width = (rect.width - box.horizontalSum) / 3; | ||
left = box.paddingLeft + 2 * width; | ||
height = rect.height - box.verticalSum; | ||
break; | ||
case 3 /* RootBottom */: | ||
height = (rect.height - box.verticalSum) / 3; | ||
top = box.paddingTop + 2 * height; | ||
left = box.paddingLeft; | ||
width = rect.width - box.horizontalSum; | ||
break; | ||
case 4 /* RootCenter */: | ||
top = box.paddingTop; | ||
left = box.paddingLeft; | ||
width = rect.width - box.horizontalSum; | ||
height = rect.height - box.verticalSum; | ||
break; | ||
case 5 /* PanelTop */: | ||
pcr = target.panel.node.getBoundingClientRect(); | ||
top = pcr.top - rect.top - box.borderTop; | ||
left = pcr.left - rect.left - box.borderLeft; | ||
width = pcr.width; | ||
height = pcr.height / 2; | ||
break; | ||
case 6 /* PanelLeft */: | ||
pcr = target.panel.node.getBoundingClientRect(); | ||
top = pcr.top - rect.top - box.borderTop; | ||
left = pcr.left - rect.left - box.borderLeft; | ||
width = pcr.width / 2; | ||
height = pcr.height; | ||
break; | ||
case 7 /* PanelRight */: | ||
pcr = target.panel.node.getBoundingClientRect(); | ||
top = pcr.top - rect.top - box.borderTop; | ||
left = pcr.left - rect.left - box.borderLeft + pcr.width / 2; | ||
width = pcr.width / 2; | ||
height = pcr.height; | ||
break; | ||
case 8 /* PanelBottom */: | ||
pcr = target.panel.node.getBoundingClientRect(); | ||
top = pcr.top - rect.top - box.borderTop + pcr.height / 2; | ||
left = pcr.left - rect.left - box.borderLeft; | ||
width = pcr.width; | ||
height = pcr.height / 2; | ||
break; | ||
case 9 /* PanelCenter */: | ||
pcr = target.panel.node.getBoundingClientRect(); | ||
top = pcr.top - rect.top - box.borderTop; | ||
left = pcr.left - rect.left - box.borderLeft; | ||
width = pcr.width; | ||
height = pcr.height; | ||
break; | ||
} | ||
// Show the overlay and return the dock zone. | ||
getOverlay(panel).show(target.zone, left, top, width, height); | ||
return target.zone; | ||
} | ||
/** | ||
* Drop a widget onto a dock panel using the given dock target. | ||
*/ | ||
function handleDrop(panel, widget, target) { | ||
// Do nothing if the dock zone is invalid. | ||
if (target.zone === 10 /* Invalid */) { | ||
return; | ||
} | ||
// Handle the simple case of root drops first. | ||
switch (target.zone) { | ||
case 0 /* RootTop */: | ||
panel.insertTop(widget); | ||
return; | ||
case 1 /* RootLeft */: | ||
panel.insertLeft(widget); | ||
return; | ||
case 2 /* RootRight */: | ||
panel.insertRight(widget); | ||
return; | ||
case 3 /* RootBottom */: | ||
panel.insertBottom(widget); | ||
return; | ||
case 4 /* RootCenter */: | ||
panel.insertLeft(widget); | ||
return; | ||
} | ||
// Otherwise, it's a panel drop, and that requires more checks. | ||
// Do nothing if the widget is dropped as a tab on its own panel. | ||
if (target.zone === 9 /* PanelCenter */) { | ||
if (target.panel.widgets.contains(widget)) { | ||
return; | ||
} | ||
} | ||
// Do nothing if the panel only contains the drop widget. | ||
if (target.panel.widgets.length === 1) { | ||
if (target.panel.widgets.get(0) === widget) { | ||
return; | ||
} | ||
} | ||
// Find a suitable reference widget for the drop. | ||
var ref = target.panel.widgets.get(-1); | ||
if (ref === widget) { | ||
ref = target.panel.widgets.get(-2); | ||
} | ||
// Insert the widget based on the panel zone. | ||
switch (target.zone) { | ||
case 5 /* PanelTop */: | ||
panel.insertTop(widget, ref); | ||
return; | ||
case 6 /* PanelLeft */: | ||
panel.insertLeft(widget, ref); | ||
return; | ||
case 7 /* PanelRight */: | ||
panel.insertRight(widget, ref); | ||
return; | ||
case 8 /* PanelBottom */: | ||
panel.insertBottom(widget, ref); | ||
return; | ||
case 9 /* PanelCenter */: | ||
panel.insertTabAfter(widget, ref); | ||
selectWidget(widget); | ||
return; | ||
} | ||
} | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "phosphor-dockpanel", | ||
"version": "0.9.2", | ||
"version": "0.9.3", | ||
"description": "A widget which provides a flexible docking area for content widgets.", | ||
@@ -8,11 +8,12 @@ "main": "lib/index.js", | ||
"dependencies": { | ||
"phosphor-arrays": "^1.0.5", | ||
"phosphor-boxpanel": "^0.9.6", | ||
"phosphor-disposable": "^1.0.4", | ||
"phosphor-domutil": "^0.9.5", | ||
"phosphor-properties": "^1.2.0", | ||
"phosphor-splitpanel": "^0.9.7", | ||
"phosphor-stackedpanel": "^0.9.5", | ||
"phosphor-tabs": "^0.9.7", | ||
"phosphor-widget": "^0.9.11" | ||
"phosphor-arrays": "^1.0.6", | ||
"phosphor-domutil": "^1.2.0", | ||
"phosphor-dragdrop": "^0.9.0", | ||
"phosphor-messaging": "^1.0.5", | ||
"phosphor-nodewrapper": "^1.0.4", | ||
"phosphor-properties": "^2.0.0", | ||
"phosphor-splitpanel": "^1.0.0-beta", | ||
"phosphor-stackedpanel": "^1.0.0-beta.1", | ||
"phosphor-tabs": "^1.0.0-beta.3", | ||
"phosphor-widget": "^1.0.0-beta.1" | ||
}, | ||
@@ -61,5 +62,5 @@ "devDependencies": { | ||
"files": [ | ||
"lib/index.js", | ||
"lib/index.css", | ||
"lib/index.d.ts" | ||
"lib/*.css", | ||
"lib/*.d.ts", | ||
"lib/*.js" | ||
], | ||
@@ -72,3 +73,2 @@ "browserify": { | ||
"keywords": [ | ||
"ui", | ||
"dock", | ||
@@ -78,2 +78,3 @@ "docking", | ||
"panel", | ||
"ui", | ||
"widget", | ||
@@ -80,0 +81,0 @@ "widgets" |
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
1434
54567
10
1
+ Addedphosphor-dragdrop@^0.9.0
+ Addedphosphor-messaging@^1.0.5
+ Addedphosphor-nodewrapper@^1.0.4
+ Addedphosphor-boxengine@1.0.1(transitive)
+ Addedphosphor-boxpanel@1.0.0-rc.0(transitive)
+ Addedphosphor-domutil@1.2.0(transitive)
+ Addedphosphor-dragdrop@0.9.1(transitive)
+ Addedphosphor-panel@1.0.0-rc.1(transitive)
+ Addedphosphor-properties@2.0.0(transitive)
+ Addedphosphor-splitpanel@1.0.0-rc.1(transitive)
+ Addedphosphor-stackedpanel@1.0.0-rc.0(transitive)
+ Addedphosphor-tabs@1.0.0-rc.2(transitive)
+ Addedphosphor-widget@1.0.0-rc.1(transitive)
- Removedphosphor-boxpanel@^0.9.6
- Removedphosphor-disposable@^1.0.4
- Removedphosphor-boxengine@0.9.4(transitive)
- Removedphosphor-boxpanel@0.9.7(transitive)
- Removedphosphor-domutil@0.9.6(transitive)
- Removedphosphor-properties@1.3.0(transitive)
- Removedphosphor-splitpanel@0.9.9(transitive)
- Removedphosphor-stackedpanel@0.9.6(transitive)
- Removedphosphor-tabs@0.9.8(transitive)
- Removedphosphor-widget@0.9.13(transitive)
Updatedphosphor-arrays@^1.0.6
Updatedphosphor-domutil@^1.2.0
Updatedphosphor-properties@^2.0.0
Updatedphosphor-tabs@^1.0.0-beta.3