New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

phosphor-dockpanel

Package Overview
Dependencies
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

phosphor-dockpanel - npm Package Compare versions

Comparing version 0.9.2 to 0.9.3

288

lib/index.d.ts

@@ -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);
}

@@ -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

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc