dockview-core
Version:
Zero dependency layout manager supporting tabs, grids and splitviews
1,050 lines • 94.4 kB
JavaScript
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __read = (this && this.__read) || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
var __values = (this && this.__values) || function(o) {
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
if (m) return m.call(o);
if (o && typeof o.length === "number") return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DockviewComponent = void 0;
var gridview_1 = require("../gridview/gridview");
var droptarget_1 = require("../dnd/droptarget");
var array_1 = require("../array");
var dockviewPanel_1 = require("./dockviewPanel");
var lifecycle_1 = require("../lifecycle");
var events_1 = require("../events");
var watermark_1 = require("./components/watermark/watermark");
var math_1 = require("../math");
var deserializer_1 = require("./deserializer");
var options_1 = require("./options");
var baseComponentGridview_1 = require("../gridview/baseComponentGridview");
var component_api_1 = require("../api/component.api");
var splitview_1 = require("../splitview/splitview");
var dockviewGroupPanelModel_1 = require("./dockviewGroupPanelModel");
var dockviewGroupPanel_1 = require("./dockviewGroupPanel");
var dockviewPanelModel_1 = require("./dockviewPanelModel");
var dataTransfer_1 = require("../dnd/dataTransfer");
var overlay_1 = require("../overlay/overlay");
var dom_1 = require("../dom");
var dockviewFloatingGroupPanel_1 = require("./dockviewFloatingGroupPanel");
var constants_1 = require("../constants");
var overlayRenderContainer_1 = require("../overlay/overlayRenderContainer");
var popoutWindow_1 = require("../popoutWindow");
var strictEventsSequencing_1 = require("./strictEventsSequencing");
var popupService_1 = require("./components/popupService");
var dropTargetAnchorContainer_1 = require("../dnd/dropTargetAnchorContainer");
var theme_1 = require("./theme");
var DEFAULT_ROOT_OVERLAY_MODEL = {
activationSize: { type: 'pixels', value: 10 },
size: { type: 'pixels', value: 20 },
};
function moveGroupWithoutDestroying(options) {
var activePanel = options.from.activePanel;
var panels = __spreadArray([], __read(options.from.panels), false).map(function (panel) {
var removedPanel = options.from.model.removePanel(panel);
options.from.model.renderContainer.detatch(panel);
return removedPanel;
});
panels.forEach(function (panel) {
options.to.model.openPanel(panel, {
skipSetActive: activePanel !== panel,
skipSetGroupActive: true,
});
});
}
var DockviewComponent = /** @class */ (function (_super) {
__extends(DockviewComponent, _super);
function DockviewComponent(container, options) {
var _a, _b, _c;
var _this = _super.call(this, container, {
proportionalLayout: true,
orientation: splitview_1.Orientation.HORIZONTAL,
styles: options.hideBorders
? { separatorBorder: 'transparent' }
: undefined,
disableAutoResizing: options.disableAutoResizing,
locked: options.locked,
margin: (_b = (_a = options.theme) === null || _a === void 0 ? void 0 : _a.gap) !== null && _b !== void 0 ? _b : 0,
className: options.className,
}) || this;
_this.nextGroupId = (0, math_1.sequentialNumberGenerator)();
_this._deserializer = new deserializer_1.DefaultDockviewDeserialzier(_this);
_this._watermark = null;
_this._onWillDragPanel = new events_1.Emitter();
_this.onWillDragPanel = _this._onWillDragPanel.event;
_this._onWillDragGroup = new events_1.Emitter();
_this.onWillDragGroup = _this._onWillDragGroup.event;
_this._onDidDrop = new events_1.Emitter();
_this.onDidDrop = _this._onDidDrop.event;
_this._onWillDrop = new events_1.Emitter();
_this.onWillDrop = _this._onWillDrop.event;
_this._onWillShowOverlay = new events_1.Emitter();
_this.onWillShowOverlay = _this._onWillShowOverlay.event;
_this._onUnhandledDragOverEvent = new events_1.Emitter();
_this.onUnhandledDragOverEvent = _this._onUnhandledDragOverEvent.event;
_this._onDidRemovePanel = new events_1.Emitter();
_this.onDidRemovePanel = _this._onDidRemovePanel.event;
_this._onDidAddPanel = new events_1.Emitter();
_this.onDidAddPanel = _this._onDidAddPanel.event;
_this._onDidPopoutGroupSizeChange = new events_1.Emitter();
_this.onDidPopoutGroupSizeChange = _this._onDidPopoutGroupSizeChange.event;
_this._onDidPopoutGroupPositionChange = new events_1.Emitter();
_this.onDidPopoutGroupPositionChange = _this._onDidPopoutGroupPositionChange.event;
_this._onDidLayoutFromJSON = new events_1.Emitter();
_this.onDidLayoutFromJSON = _this._onDidLayoutFromJSON.event;
_this._onDidActivePanelChange = new events_1.Emitter();
_this.onDidActivePanelChange = _this._onDidActivePanelChange.event;
_this._onDidMovePanel = new events_1.Emitter();
_this.onDidMovePanel = _this._onDidMovePanel.event;
_this._onDidMaximizedGroupChange = new events_1.Emitter();
_this.onDidMaximizedGroupChange = _this._onDidMaximizedGroupChange.event;
_this._floatingGroups = [];
_this._popoutGroups = [];
_this._onDidRemoveGroup = new events_1.Emitter();
_this.onDidRemoveGroup = _this._onDidRemoveGroup.event;
_this._onDidAddGroup = new events_1.Emitter();
_this.onDidAddGroup = _this._onDidAddGroup.event;
_this._onDidOptionsChange = new events_1.Emitter();
_this.onDidOptionsChange = _this._onDidOptionsChange.event;
_this._onDidActiveGroupChange = new events_1.Emitter();
_this.onDidActiveGroupChange = _this._onDidActiveGroupChange.event;
_this._moving = false;
_this._options = options;
_this.popupService = new popupService_1.PopupService(_this.element);
_this._themeClassnames = new dom_1.Classnames(_this.element);
_this._api = new component_api_1.DockviewApi(_this);
_this.rootDropTargetContainer = new dropTargetAnchorContainer_1.DropTargetAnchorContainer(_this.element, { disabled: true });
_this.overlayRenderContainer = new overlayRenderContainer_1.OverlayRenderContainer(_this.gridview.element, _this);
_this._rootDropTarget = new droptarget_1.Droptarget(_this.element, {
className: 'dv-drop-target-edge',
canDisplayOverlay: function (event, position) {
var data = (0, dataTransfer_1.getPanelData)();
if (data) {
if (data.viewId !== _this.id) {
return false;
}
if (position === 'center') {
// center drop target is only allowed if there are no panels in the grid
// floating panels are allowed
return _this.gridview.length === 0;
}
return true;
}
if (position === 'center' && _this.gridview.length !== 0) {
/**
* for external events only show the four-corner drag overlays, disable
* the center position so that external drag events can fall through to the group
* and panel drop target handlers
*/
return false;
}
var firedEvent = new options_1.DockviewUnhandledDragOverEvent(event, 'edge', position, dataTransfer_1.getPanelData);
_this._onUnhandledDragOverEvent.fire(firedEvent);
return firedEvent.isAccepted;
},
acceptedTargetZones: ['top', 'bottom', 'left', 'right', 'center'],
overlayModel: (_c = options.rootOverlayModel) !== null && _c !== void 0 ? _c : DEFAULT_ROOT_OVERLAY_MODEL,
getOverrideTarget: function () { var _a; return (_a = _this.rootDropTargetContainer) === null || _a === void 0 ? void 0 : _a.model; },
});
_this.updateDropTargetModel(options);
(0, dom_1.toggleClass)(_this.gridview.element, 'dv-dockview', true);
(0, dom_1.toggleClass)(_this.element, 'dv-debug', !!options.debug);
_this.updateTheme();
_this.updateWatermark();
if (options.debug) {
_this.addDisposables(new strictEventsSequencing_1.StrictEventsSequencing(_this));
}
_this.addDisposables(_this.rootDropTargetContainer, _this.overlayRenderContainer, _this._onWillDragPanel, _this._onWillDragGroup, _this._onWillShowOverlay, _this._onDidActivePanelChange, _this._onDidAddPanel, _this._onDidRemovePanel, _this._onDidLayoutFromJSON, _this._onDidDrop, _this._onWillDrop, _this._onDidMovePanel, _this._onDidAddGroup, _this._onDidRemoveGroup, _this._onDidActiveGroupChange, _this._onUnhandledDragOverEvent, _this._onDidMaximizedGroupChange, _this._onDidOptionsChange, _this._onDidPopoutGroupSizeChange, _this._onDidPopoutGroupPositionChange, _this.onDidViewVisibilityChangeMicroTaskQueue(function () {
_this.updateWatermark();
}), _this.onDidAdd(function (event) {
if (!_this._moving) {
_this._onDidAddGroup.fire(event);
}
}), _this.onDidRemove(function (event) {
if (!_this._moving) {
_this._onDidRemoveGroup.fire(event);
}
}), _this.onDidActiveChange(function (event) {
if (!_this._moving) {
_this._onDidActiveGroupChange.fire(event);
}
}), _this.onDidMaximizedChange(function (event) {
_this._onDidMaximizedGroupChange.fire({
group: event.panel,
isMaximized: event.isMaximized,
});
}), events_1.Event.any(_this.onDidAdd, _this.onDidRemove)(function () {
_this.updateWatermark();
}), events_1.Event.any(_this.onDidAddPanel, _this.onDidRemovePanel, _this.onDidAddGroup, _this.onDidRemove, _this.onDidMovePanel, _this.onDidActivePanelChange, _this.onDidPopoutGroupPositionChange, _this.onDidPopoutGroupSizeChange)(function () {
_this._bufferOnDidLayoutChange.fire();
}), lifecycle_1.Disposable.from(function () {
var e_1, _a, e_2, _b;
try {
// iterate over a copy of the array since .dispose() mutates the original array
for (var _c = __values(__spreadArray([], __read(_this._floatingGroups), false)), _d = _c.next(); !_d.done; _d = _c.next()) {
var group = _d.value;
group.dispose();
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
}
finally { if (e_1) throw e_1.error; }
}
try {
// iterate over a copy of the array since .dispose() mutates the original array
for (var _e = __values(__spreadArray([], __read(_this._popoutGroups), false)), _f = _e.next(); !_f.done; _f = _e.next()) {
var group = _f.value;
group.disposable.dispose();
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (_f && !_f.done && (_b = _e.return)) _b.call(_e);
}
finally { if (e_2) throw e_2.error; }
}
}), _this._rootDropTarget, _this._rootDropTarget.onWillShowOverlay(function (event) {
if (_this.gridview.length > 0 && event.position === 'center') {
// option only available when no panels in primary grid
return;
}
_this._onWillShowOverlay.fire(new dockviewGroupPanelModel_1.WillShowOverlayLocationEvent(event, {
kind: 'edge',
panel: undefined,
api: _this._api,
group: undefined,
getData: dataTransfer_1.getPanelData,
}));
}), _this._rootDropTarget.onDrop(function (event) {
var _a;
var willDropEvent = new dockviewGroupPanelModel_1.DockviewWillDropEvent({
nativeEvent: event.nativeEvent,
position: event.position,
panel: undefined,
api: _this._api,
group: undefined,
getData: dataTransfer_1.getPanelData,
kind: 'edge',
});
_this._onWillDrop.fire(willDropEvent);
if (willDropEvent.defaultPrevented) {
return;
}
var data = (0, dataTransfer_1.getPanelData)();
if (data) {
_this.moveGroupOrPanel({
from: {
groupId: data.groupId,
panelId: (_a = data.panelId) !== null && _a !== void 0 ? _a : undefined,
},
to: {
group: _this.orthogonalize(event.position),
position: 'center',
},
});
}
else {
_this._onDidDrop.fire(new dockviewGroupPanelModel_1.DockviewDidDropEvent({
nativeEvent: event.nativeEvent,
position: event.position,
panel: undefined,
api: _this._api,
group: undefined,
getData: dataTransfer_1.getPanelData,
}));
}
}), _this._rootDropTarget);
return _this;
}
Object.defineProperty(DockviewComponent.prototype, "orientation", {
get: function () {
return this.gridview.orientation;
},
enumerable: false,
configurable: true
});
Object.defineProperty(DockviewComponent.prototype, "totalPanels", {
get: function () {
return this.panels.length;
},
enumerable: false,
configurable: true
});
Object.defineProperty(DockviewComponent.prototype, "panels", {
get: function () {
return this.groups.flatMap(function (group) { return group.panels; });
},
enumerable: false,
configurable: true
});
Object.defineProperty(DockviewComponent.prototype, "options", {
get: function () {
return this._options;
},
enumerable: false,
configurable: true
});
Object.defineProperty(DockviewComponent.prototype, "activePanel", {
get: function () {
var activeGroup = this.activeGroup;
if (!activeGroup) {
return undefined;
}
return activeGroup.activePanel;
},
enumerable: false,
configurable: true
});
Object.defineProperty(DockviewComponent.prototype, "renderer", {
get: function () {
var _a;
return (_a = this.options.defaultRenderer) !== null && _a !== void 0 ? _a : 'onlyWhenVisible';
},
enumerable: false,
configurable: true
});
Object.defineProperty(DockviewComponent.prototype, "api", {
get: function () {
return this._api;
},
enumerable: false,
configurable: true
});
Object.defineProperty(DockviewComponent.prototype, "floatingGroups", {
get: function () {
return this._floatingGroups;
},
enumerable: false,
configurable: true
});
DockviewComponent.prototype.setVisible = function (panel, visible) {
switch (panel.api.location.type) {
case 'grid':
_super.prototype.setVisible.call(this, panel, visible);
break;
case 'floating': {
var item = this.floatingGroups.find(function (floatingGroup) { return floatingGroup.group === panel; });
if (item) {
item.overlay.setVisible(visible);
panel.api._onDidVisibilityChange.fire({
isVisible: visible,
});
}
break;
}
case 'popout':
console.warn('dockview: You cannot hide a group that is in a popout window');
break;
}
};
DockviewComponent.prototype.addPopoutGroup = function (itemToPopout, options) {
var _this = this;
var _a, _b, _c, _d, _e;
if (itemToPopout instanceof dockviewPanel_1.DockviewPanel &&
itemToPopout.group.size === 1) {
return this.addPopoutGroup(itemToPopout.group, options);
}
var theme = (0, dom_1.getDockviewTheme)(this.gridview.element);
var element = this.element;
function getBox() {
if (options === null || options === void 0 ? void 0 : options.position) {
return options.position;
}
if (itemToPopout instanceof dockviewGroupPanel_1.DockviewGroupPanel) {
return itemToPopout.element.getBoundingClientRect();
}
if (itemToPopout.group) {
return itemToPopout.group.element.getBoundingClientRect();
}
return element.getBoundingClientRect();
}
var box = getBox();
var groupId = (_b = (_a = options === null || options === void 0 ? void 0 : options.overridePopoutGroup) === null || _a === void 0 ? void 0 : _a.id) !== null && _b !== void 0 ? _b : this.getNextGroupId();
var _window = new popoutWindow_1.PopoutWindow("".concat(this.id, "-").concat(groupId), // unique id
theme !== null && theme !== void 0 ? theme : '', {
url: (_e = (_c = options === null || options === void 0 ? void 0 : options.popoutUrl) !== null && _c !== void 0 ? _c : (_d = this.options) === null || _d === void 0 ? void 0 : _d.popoutUrl) !== null && _e !== void 0 ? _e : '/popout.html',
left: window.screenX + box.left,
top: window.screenY + box.top,
width: box.width,
height: box.height,
onDidOpen: options === null || options === void 0 ? void 0 : options.onDidOpen,
onWillClose: options === null || options === void 0 ? void 0 : options.onWillClose,
});
var popoutWindowDisposable = new lifecycle_1.CompositeDisposable(_window, _window.onDidClose(function () {
popoutWindowDisposable.dispose();
}));
return _window
.open()
.then(function (popoutContainer) {
var _a;
if (_window.isDisposed) {
return false;
}
if (popoutContainer === null) {
popoutWindowDisposable.dispose();
return false;
}
var gready = document.createElement('div');
gready.className = 'dv-overlay-render-container';
var overlayRenderContainer = new overlayRenderContainer_1.OverlayRenderContainer(gready, _this);
var referenceGroup = itemToPopout instanceof dockviewPanel_1.DockviewPanel
? itemToPopout.group
: itemToPopout;
var referenceLocation = itemToPopout.api.location.type;
/**
* The group that is being added doesn't already exist within the DOM, the most likely occurance
* of this case is when being called from the `fromJSON(...)` method
*/
var isGroupAddedToDom = referenceGroup.element.parentElement !== null;
var group;
if (!isGroupAddedToDom) {
group = referenceGroup;
}
else if (options === null || options === void 0 ? void 0 : options.overridePopoutGroup) {
group = options.overridePopoutGroup;
}
else {
group = _this.createGroup({ id: groupId });
_this._onDidAddGroup.fire(group);
}
group.model.renderContainer = overlayRenderContainer;
group.layout(_window.window.innerWidth, _window.window.innerHeight);
var floatingBox;
if (!(options === null || options === void 0 ? void 0 : options.overridePopoutGroup) && isGroupAddedToDom) {
if (itemToPopout instanceof dockviewPanel_1.DockviewPanel) {
_this.movingLock(function () {
var panel = referenceGroup.model.removePanel(itemToPopout);
group.model.openPanel(panel);
});
}
else {
_this.movingLock(function () {
return moveGroupWithoutDestroying({
from: referenceGroup,
to: group,
});
});
switch (referenceLocation) {
case 'grid':
referenceGroup.api.setVisible(false);
break;
case 'floating':
case 'popout':
floatingBox = (_a = _this._floatingGroups
.find(function (value) {
return value.group.api.id ===
itemToPopout.api.id;
})) === null || _a === void 0 ? void 0 : _a.overlay.toJSON();
_this.removeGroup(referenceGroup);
break;
}
}
}
popoutContainer.classList.add('dv-dockview');
popoutContainer.style.overflow = 'hidden';
popoutContainer.appendChild(gready);
popoutContainer.appendChild(group.element);
var anchor = document.createElement('div');
var dropTargetContainer = new dropTargetAnchorContainer_1.DropTargetAnchorContainer(anchor, { disabled: _this.rootDropTargetContainer.disabled });
popoutContainer.appendChild(anchor);
group.model.dropTargetContainer = dropTargetContainer;
group.model.location = {
type: 'popout',
getWindow: function () { return _window.window; },
popoutUrl: options === null || options === void 0 ? void 0 : options.popoutUrl,
};
if (isGroupAddedToDom &&
itemToPopout.api.location.type === 'grid') {
itemToPopout.api.setVisible(false);
}
_this.doSetGroupAndPanelActive(group);
popoutWindowDisposable.addDisposables(group.api.onDidActiveChange(function (event) {
var _a;
if (event.isActive) {
(_a = _window.window) === null || _a === void 0 ? void 0 : _a.focus();
}
}), group.api.onWillFocus(function () {
var _a;
(_a = _window.window) === null || _a === void 0 ? void 0 : _a.focus();
}));
var returnedGroup;
var isValidReferenceGroup = isGroupAddedToDom &&
referenceGroup &&
_this.getPanel(referenceGroup.id);
var value = {
window: _window,
popoutGroup: group,
referenceGroup: isValidReferenceGroup
? referenceGroup.id
: undefined,
disposable: {
dispose: function () {
popoutWindowDisposable.dispose();
return returnedGroup;
},
},
};
var _onDidWindowPositionChange = (0, dom_1.onDidWindowMoveEnd)(_window.window);
popoutWindowDisposable.addDisposables(_onDidWindowPositionChange, (0, dom_1.onDidWindowResizeEnd)(_window.window, function () {
_this._onDidPopoutGroupSizeChange.fire({
width: _window.window.innerWidth,
height: _window.window.innerHeight,
group: group,
});
}), _onDidWindowPositionChange.event(function () {
_this._onDidPopoutGroupPositionChange.fire({
screenX: _window.window.screenX,
screenY: _window.window.screenX,
group: group,
});
}),
/**
* ResizeObserver seems slow here, I do not know why but we don't need it
* since we can reply on the window resize event as we will occupy the full
* window dimensions
*/
(0, events_1.addDisposableListener)(_window.window, 'resize', function () {
group.layout(_window.window.innerWidth, _window.window.innerHeight);
}), overlayRenderContainer, lifecycle_1.Disposable.from(function () {
if (_this.isDisposed) {
return; // cleanup may run after instance is disposed
}
if (isGroupAddedToDom &&
_this.getPanel(referenceGroup.id)) {
_this.movingLock(function () {
return moveGroupWithoutDestroying({
from: group,
to: referenceGroup,
});
});
if (!referenceGroup.api.isVisible) {
referenceGroup.api.setVisible(true);
}
if (_this.getPanel(group.id)) {
_this.doRemoveGroup(group, {
skipPopoutAssociated: true,
});
}
}
else if (_this.getPanel(group.id)) {
group.model.renderContainer =
_this.overlayRenderContainer;
group.model.dropTargetContainer =
_this.rootDropTargetContainer;
returnedGroup = group;
var alreadyRemoved = !_this._popoutGroups.find(function (p) { return p.popoutGroup === group; });
if (alreadyRemoved) {
/**
* If this popout group was explicitly removed then we shouldn't run the additional
* steps. To tell if the running of this disposable is the result of this popout group
* being explicitly removed we can check if this popout group is still referenced in
* the `this._popoutGroups` list.
*/
return;
}
if (floatingBox) {
_this.addFloatingGroup(group, {
height: floatingBox.height,
width: floatingBox.width,
position: floatingBox,
});
}
else {
_this.doRemoveGroup(group, {
skipDispose: true,
skipActive: true,
skipPopoutReturn: true,
});
group.model.location = { type: 'grid' };
_this.movingLock(function () {
// suppress group add events since the group already exists
_this.doAddGroup(group, [0]);
});
}
_this.doSetGroupAndPanelActive(group);
}
}));
_this._popoutGroups.push(value);
_this.updateWatermark();
return true;
})
.catch(function (err) {
console.error('dockview: failed to create popout window', err);
return false;
});
};
DockviewComponent.prototype.addFloatingGroup = function (item, options) {
var _this = this;
var _a, _b, _c, _d, _e;
var group;
if (item instanceof dockviewPanel_1.DockviewPanel) {
group = this.createGroup();
this._onDidAddGroup.fire(group);
this.movingLock(function () {
return _this.removePanel(item, {
removeEmptyGroup: true,
skipDispose: true,
skipSetActiveGroup: true,
});
});
this.movingLock(function () {
return group.model.openPanel(item, { skipSetGroupActive: true });
});
}
else {
group = item;
var popoutReferenceGroupId = (_a = this._popoutGroups.find(function (_) { return _.popoutGroup === group; })) === null || _a === void 0 ? void 0 : _a.referenceGroup;
var popoutReferenceGroup_1 = popoutReferenceGroupId
? this.getPanel(popoutReferenceGroupId)
: undefined;
var skip = typeof (options === null || options === void 0 ? void 0 : options.skipRemoveGroup) === 'boolean' &&
options.skipRemoveGroup;
if (!skip) {
if (popoutReferenceGroup_1) {
this.movingLock(function () {
return moveGroupWithoutDestroying({
from: item,
to: popoutReferenceGroup_1,
});
});
this.doRemoveGroup(item, {
skipPopoutReturn: true,
skipPopoutAssociated: true,
});
this.doRemoveGroup(popoutReferenceGroup_1, {
skipDispose: true,
});
group = popoutReferenceGroup_1;
}
else {
this.doRemoveGroup(item, {
skipDispose: true,
skipPopoutReturn: true,
skipPopoutAssociated: false,
});
}
}
}
function getAnchoredBox() {
if (options === null || options === void 0 ? void 0 : options.position) {
var result = {};
if ('left' in options.position) {
result.left = Math.max(options.position.left, 0);
}
else if ('right' in options.position) {
result.right = Math.max(options.position.right, 0);
}
else {
result.left = constants_1.DEFAULT_FLOATING_GROUP_POSITION.left;
}
if ('top' in options.position) {
result.top = Math.max(options.position.top, 0);
}
else if ('bottom' in options.position) {
result.bottom = Math.max(options.position.bottom, 0);
}
else {
result.top = constants_1.DEFAULT_FLOATING_GROUP_POSITION.top;
}
if (typeof options.width === 'number') {
result.width = Math.max(options.width, 0);
}
else {
result.width = constants_1.DEFAULT_FLOATING_GROUP_POSITION.width;
}
if (typeof options.height === 'number') {
result.height = Math.max(options.height, 0);
}
else {
result.height = constants_1.DEFAULT_FLOATING_GROUP_POSITION.height;
}
return result;
}
return {
left: typeof (options === null || options === void 0 ? void 0 : options.x) === 'number'
? Math.max(options.x, 0)
: constants_1.DEFAULT_FLOATING_GROUP_POSITION.left,
top: typeof (options === null || options === void 0 ? void 0 : options.y) === 'number'
? Math.max(options.y, 0)
: constants_1.DEFAULT_FLOATING_GROUP_POSITION.top,
width: typeof (options === null || options === void 0 ? void 0 : options.width) === 'number'
? Math.max(options.width, 0)
: constants_1.DEFAULT_FLOATING_GROUP_POSITION.width,
height: typeof (options === null || options === void 0 ? void 0 : options.height) === 'number'
? Math.max(options.height, 0)
: constants_1.DEFAULT_FLOATING_GROUP_POSITION.height,
};
}
var anchoredBox = getAnchoredBox();
var overlay = new overlay_1.Overlay(__assign(__assign({ container: this.gridview.element, content: group.element }, anchoredBox), { minimumInViewportWidth: this.options.floatingGroupBounds === 'boundedWithinViewport'
? undefined
: (_c = (_b = this.options.floatingGroupBounds) === null || _b === void 0 ? void 0 : _b.minimumWidthWithinViewport) !== null && _c !== void 0 ? _c : constants_1.DEFAULT_FLOATING_GROUP_OVERFLOW_SIZE, minimumInViewportHeight: this.options.floatingGroupBounds === 'boundedWithinViewport'
? undefined
: (_e = (_d = this.options.floatingGroupBounds) === null || _d === void 0 ? void 0 : _d.minimumHeightWithinViewport) !== null && _e !== void 0 ? _e : constants_1.DEFAULT_FLOATING_GROUP_OVERFLOW_SIZE }));
var el = group.element.querySelector('.dv-void-container');
if (!el) {
throw new Error('failed to find drag handle');
}
overlay.setupDrag(el, {
inDragMode: typeof (options === null || options === void 0 ? void 0 : options.inDragMode) === 'boolean'
? options.inDragMode
: false,
});
var floatingGroupPanel = new dockviewFloatingGroupPanel_1.DockviewFloatingGroupPanel(group, overlay);
var disposable = new lifecycle_1.CompositeDisposable(group.api.onDidActiveChange(function (event) {
if (event.isActive) {
overlay.bringToFront();
}
}), (0, dom_1.watchElementResize)(group.element, function (entry) {
var _a = entry.contentRect, width = _a.width, height = _a.height;
group.layout(width, height); // let the group know it's size is changing so it can fire events to the panel
}));
floatingGroupPanel.addDisposables(overlay.onDidChange(function () {
// this is either a resize or a move
// to inform the panels .layout(...) the group with it's current size
// don't care about resize since the above watcher handles that
group.layout(group.width, group.height);
}), overlay.onDidChangeEnd(function () {
_this._bufferOnDidLayoutChange.fire();
}), group.onDidChange(function (event) {
overlay.setBounds({
height: event === null || event === void 0 ? void 0 : event.height,
width: event === null || event === void 0 ? void 0 : event.width,
});
}), {
dispose: function () {
disposable.dispose();
(0, array_1.remove)(_this._floatingGroups, floatingGroupPanel);
group.model.location = { type: 'grid' };
_this.updateWatermark();
},
});
this._floatingGroups.push(floatingGroupPanel);
group.model.location = { type: 'floating' };
if (!(options === null || options === void 0 ? void 0 : options.skipActiveGroup)) {
this.doSetGroupAndPanelActive(group);
}
this.updateWatermark();
};
DockviewComponent.prototype.orthogonalize = function (position, options) {
switch (position) {
case 'top':
case 'bottom':
if (this.gridview.orientation === splitview_1.Orientation.HORIZONTAL) {
// we need to add to a vertical splitview but the current root is a horizontal splitview.
// insert a vertical splitview at the root level and add the existing view as a child
this.gridview.insertOrthogonalSplitviewAtRoot();
}
break;
case 'left':
case 'right':
if (this.gridview.orientation === splitview_1.Orientation.VERTICAL) {
// we need to add to a horizontal splitview but the current root is a vertical splitview.
// insert a horiziontal splitview at the root level and add the existing view as a child
this.gridview.insertOrthogonalSplitviewAtRoot();
}
break;
default:
break;
}
switch (position) {
case 'top':
case 'left':
case 'center':
return this.createGroupAtLocation([0], undefined, options); // insert into first position
case 'bottom':
case 'right':
return this.createGroupAtLocation([this.gridview.length], undefined, options); // insert into last position
default:
throw new Error("unsupported position ".concat(position));
}
};
DockviewComponent.prototype.updateOptions = function (options) {
var e_3, _a;
var _b, _c;
_super.prototype.updateOptions.call(this, options);
if ('floatingGroupBounds' in options) {
try {
for (var _d = __values(this._floatingGroups), _e = _d.next(); !_e.done; _e = _d.next()) {
var group = _e.value;
switch (options.floatingGroupBounds) {
case 'boundedWithinViewport':
group.overlay.minimumInViewportHeight = undefined;
group.overlay.minimumInViewportWidth = undefined;
break;
case undefined:
group.overlay.minimumInViewportHeight =
constants_1.DEFAULT_FLOATING_GROUP_OVERFLOW_SIZE;
group.overlay.minimumInViewportWidth =
constants_1.DEFAULT_FLOATING_GROUP_OVERFLOW_SIZE;
break;
default:
group.overlay.minimumInViewportHeight =
(_b = options.floatingGroupBounds) === null || _b === void 0 ? void 0 : _b.minimumHeightWithinViewport;
group.overlay.minimumInViewportWidth =
(_c = options.floatingGroupBounds) === null || _c === void 0 ? void 0 : _c.minimumWidthWithinViewport;
}
group.overlay.setBounds();
}
}
catch (e_3_1) { e_3 = { error: e_3_1 }; }
finally {
try {
if (_e && !_e.done && (_a = _d.return)) _a.call(_d);
}
finally { if (e_3) throw e_3.error; }
}
}
this.updateDropTargetModel(options);
this._options = __assign(__assign({}, this.options), options);
if ('theme' in options) {
this.updateTheme();
}
this.layout(this.gridview.width, this.gridview.height, true);
};
DockviewComponent.prototype.layout = function (width, height, forceResize) {
var e_4, _a;
_super.prototype.layout.call(this, width, height, forceResize);
if (this._floatingGroups) {
try {
for (var _b = __values(this._floatingGroups), _c = _b.next(); !_c.done; _c = _b.next()) {
var floating = _c.value;
// ensure floting groups stay within visible boundaries
floating.overlay.setBounds();
}
}
catch (e_4_1) { e_4 = { error: e_4_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_4) throw e_4.error; }
}
}
};
DockviewComponent.prototype.focus = function () {
var _a;
(_a = this.activeGroup) === null || _a === void 0 ? void 0 : _a.focus();
};
DockviewComponent.prototype.getGroupPanel = function (id) {
return this.panels.find(function (panel) { return panel.id === id; });
};
DockviewComponent.prototype.setActivePanel = function (panel) {
panel.group.model.openPanel(panel);
this.doSetGroupAndPanelActive(panel.group);
};
DockviewComponent.prototype.moveToNext = function (options) {
var _a;
if (options === void 0) { options = {}; }
if (!options.group) {
if (!this.activeGroup) {
return;
}
options.group = this.activeGroup;
}
if (options.includePanel && options.group) {
if (options.group.activePanel !==
options.group.panels[options.group.panels.length - 1]) {
options.group.model.moveToNext({ suppressRoll: true });
return;
}
}
var location = (0, gridview_1.getGridLocation)(options.group.element);
var next = (_a = this.gridview.next(location)) === null || _a === void 0 ? void 0 : _a.view;
this.doSetGroupAndPanelActive(next);
};
DockviewComponent.prototype.moveToPrevious = function (options) {
var _a;
if (options === void 0) { options = {}; }
if (!options.group) {
if (!this.activeGroup) {
return;
}
options.group = this.activeGroup;
}
if (options.includePanel && options.group) {
if (options.group.activePanel !== options.group.panels[0]) {
options.group.model.moveToPrevious({ suppressRoll: true });
return;
}
}
var location = (0, gridview_1.getGridLocation)(options.group.element);
var next = (_a = this.gridview.previous(location)) === null || _a === void 0 ? void 0 : _a.view;
if (next) {
this.doSetGroupAndPanelActive(next);
}
};
/**
* Serialize the current state of the layout
*
* @returns A JSON respresentation of the layout
*/
DockviewComponent.prototype.toJSON = function () {
var _a;
var data = this.gridview.serialize();
var panels = this.panels.reduce(function (collection, panel) {
collection[panel.id] = panel.toJSON();
return collection;
}, {});
var floats = this._floatingGroups.map(function (group) {
return {
data: group.group.toJSON(),
position: group.overlay.toJSON(),
};
});
var popoutGroups = this._popoutGroups.map(function (group) {
return {
data: group.popoutGroup.toJSON(),
gridReferenceGroup: group.referenceGroup,
position: group.window.dimensions(),
url: group.popoutGroup.api.location.type === 'popout'
? group.popoutGroup.api.location.popoutUrl
: undefined,
};
});
var result = {
grid: data,
panels: panels,
activeGroup: (_a = this.activeGroup) === null || _a === void 0 ? void 0 : _a.id,
};
if (floats.length > 0) {
result.floatingGroups = floats;
}
if (popoutGroups.length > 0) {
result.popoutGroups = popoutGroups;
}
return result;
};
DockviewComponent.prototype.fromJSON = function (data) {
var e_5, _a, e_6, _b, e_7, _c, e_8, _d, e_9, _e, e_10, _f, e_11, _g;
var _this = this;
var _h, _j, _k;
this.clear();
if (typeof data !== 'object' || data === null) {
throw new Error('serialized layout must be a non-null object');
}
var grid = data.grid, panels = data.panels, activeGroup = data.activeGroup;
if (grid.root.type !== 'branch' || !Array.isArray(grid.root.data)) {
throw new Error('root must be of type branch');
}
try {
// take note of the existing dimensions
var width = this.width;
var height = this.height;
var createGroupFromSerializedState_1 = function (data) {
var e_12, _a;
var id = data.id, locked = data.locked, hideHeader = data.hideHeader, views = data.views, activeView = data.activeView;
if (typeof id !== 'string') {
throw new Error('group id must be of type string');
}
var group = _this.createGroup({
id: id,
locked: !!locked,
hideHeader: !!hideHeader,
});
_this._onDidAddGroup.fire(group);
var createdPanels = [];
try {
for (var views_1 = __values(views), views_1_1 = views_1.next(); !views_1_1.done; views_1_1 = views_1.next()) {
var child = views_1_1.value;
/**
* Run the deserializer step seperately since this may fail to due corrupted external state.
* In running this section first we avoid firing lots of 'add' events in the event of a failure
* due to a corruption of input data.
*/
var panel = _this._deserializer.fromJSON(panels[child], group);
createdPanels.push(panel);
}
}
catch (e_12_1) { e_12 = { error: e_12_1 }; }
finally {
try {
if (views_1_1 && !views_1_1.done && (_a = views_1.return)) _a.call(views_1);
}
finally { if (e_12) throw e_12.error; }
}
for (var i = 0; i < views.length; i++) {
var panel = createdPanels[i];
var isActive = typeof activeView === 'string' &&
activeView === panel.id;
group.model.openPanel(panel, {
skipSetActive: !isActive,
skipSetGroupActive: true,
});
}
if (!group.activePanel && group.panels.length > 0) {
group.model.openPanel(group.panels[group.panels.length - 1], {
skipSetGroupActive: true,
});
}
return group;
};
this.gridview.deserialize(grid, {
fromJSON: function (node) {
return createGroupFromSerializedState_1(node.data);
},
});
this.layout(width, height, true);
var serializedFloatingGroups = (_h = data.floatingGroups) !== null && _h !== void 0 ? _h : [];
try {
for (var serializedFloatingGroups_1 = __values(serializedFloatingGroups), serializedFloatingGroups_1_1 = serializedFloatingGroups_1.next()