dockview-core 6.6.1 → 7.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -1
- package/dist/cjs/api/component.api.d.ts +42 -21
- package/dist/cjs/api/component.api.js +111 -20
- package/dist/cjs/api/dockviewGroupPanelApi.d.ts +23 -8
- package/dist/cjs/api/dockviewGroupPanelApi.js +24 -1
- package/dist/cjs/api/dockviewPanelApi.d.ts +4 -3
- package/dist/cjs/api/dockviewPanelApi.js +8 -0
- package/dist/cjs/dnd/dropTargetAnchorContainer.js +1 -2
- package/dist/cjs/dnd/droptarget.d.ts +8 -0
- package/dist/cjs/dnd/droptarget.js +28 -0
- package/dist/cjs/dnd/pointer/longPress.js +1 -1
- package/dist/cjs/dnd/pointer/pointerDragController.js +9 -7
- package/dist/cjs/dnd/pointer/pointerDragSource.js +4 -2
- package/dist/cjs/dockview/accessibilityMessages.d.ts +32 -0
- package/dist/cjs/dockview/accessibilityMessages.js +51 -0
- package/dist/cjs/dockview/allModules.d.ts +8 -0
- package/dist/cjs/dockview/allModules.js +25 -0
- package/dist/cjs/dockview/components/panel/content.d.ts +2 -0
- package/dist/cjs/dockview/components/panel/content.js +41 -10
- package/dist/cjs/dockview/components/popupService.js +1 -1
- package/dist/cjs/dockview/components/tab/tab.js +35 -7
- package/dist/cjs/dockview/components/titlebar/floatingTitleBar.d.ts +34 -0
- package/dist/cjs/dockview/components/titlebar/floatingTitleBar.js +95 -0
- package/dist/cjs/dockview/components/titlebar/groupDragSource.d.ts +51 -0
- package/dist/cjs/dockview/components/titlebar/groupDragSource.js +218 -0
- package/dist/cjs/dockview/components/titlebar/tabGroupIndicator.d.ts +2 -1
- package/dist/cjs/dockview/components/titlebar/tabGroupIndicator.js +36 -30
- package/dist/cjs/dockview/components/titlebar/tabGroups.d.ts +27 -5
- package/dist/cjs/dockview/components/titlebar/tabGroups.js +104 -53
- package/dist/cjs/dockview/components/titlebar/tabs.d.ts +12 -0
- package/dist/cjs/dockview/components/titlebar/tabs.js +121 -25
- package/dist/cjs/dockview/components/titlebar/tabsContainer.d.ts +4 -0
- package/dist/cjs/dockview/components/titlebar/tabsContainer.js +13 -3
- package/dist/cjs/dockview/components/titlebar/voidContainer.d.ts +1 -4
- package/dist/cjs/dockview/components/titlebar/voidContainer.js +32 -156
- package/dist/cjs/dockview/dndCapabilities.js +3 -3
- package/dist/cjs/dockview/dockviewComponent.d.ts +304 -49
- package/dist/cjs/dockview/dockviewComponent.js +1839 -1075
- package/dist/cjs/dockview/dockviewFloatingGroupPanel.d.ts +33 -2
- package/dist/cjs/dockview/dockviewFloatingGroupPanel.js +39 -3
- package/dist/cjs/dockview/dockviewGroupPanel.d.ts +1 -2
- package/dist/cjs/dockview/dockviewGroupPanelModel.d.ts +36 -14
- package/dist/cjs/dockview/dockviewGroupPanelModel.js +151 -125
- package/dist/cjs/dockview/dockviewPanel.d.ts +2 -2
- package/dist/cjs/dockview/dockviewPanel.js +4 -5
- package/dist/cjs/dockview/dockviewShell.d.ts +29 -7
- package/dist/cjs/dockview/dockviewShell.js +94 -36
- package/dist/cjs/dockview/edgeGroupService.d.ts +38 -0
- package/dist/cjs/dockview/edgeGroupService.js +128 -0
- package/dist/cjs/dockview/floatingGroupService.d.ts +37 -0
- package/dist/cjs/dockview/floatingGroupService.js +231 -0
- package/dist/cjs/dockview/headerActionsService.d.ts +32 -0
- package/dist/cjs/dockview/headerActionsService.js +149 -0
- package/dist/cjs/dockview/liveRegionService.d.ts +53 -0
- package/dist/cjs/dockview/liveRegionService.js +185 -0
- package/dist/cjs/dockview/moduleContracts.d.ts +119 -0
- package/dist/cjs/dockview/moduleContracts.js +2 -0
- package/dist/cjs/dockview/modules.d.ts +110 -0
- package/dist/cjs/dockview/modules.js +304 -0
- package/dist/cjs/dockview/options.d.ts +159 -6
- package/dist/cjs/dockview/options.js +8 -1
- package/dist/cjs/dockview/popoutWindowService.d.ts +95 -0
- package/dist/cjs/dockview/popoutWindowService.js +261 -0
- package/dist/cjs/dockview/rootDropTargetService.d.ts +35 -0
- package/dist/cjs/dockview/rootDropTargetService.js +87 -0
- package/dist/cjs/dockview/strictEventsSequencing.js +6 -6
- package/dist/cjs/dockview/tabGroup.js +3 -3
- package/dist/cjs/dockview/tabGroupAccent.js +1 -3
- package/dist/cjs/dockview/watermarkService.d.ts +30 -0
- package/dist/cjs/dockview/watermarkService.js +61 -0
- package/dist/cjs/dom.js +1 -1
- package/dist/cjs/events.js +1 -1
- package/dist/cjs/gridview/baseComponentGridview.d.ts +1 -1
- package/dist/cjs/gridview/baseComponentGridview.js +6 -10
- package/dist/cjs/gridview/branchNode.js +13 -17
- package/dist/cjs/gridview/gridview.js +8 -8
- package/dist/cjs/gridview/gridviewComponent.d.ts +3 -3
- package/dist/cjs/gridview/gridviewComponent.js +1 -6
- package/dist/cjs/gridview/gridviewPanel.d.ts +1 -1
- package/dist/cjs/index.d.ts +11 -4
- package/dist/cjs/index.js +14 -1
- package/dist/cjs/overlay/overlay.d.ts +43 -1
- package/dist/cjs/overlay/overlay.js +82 -36
- package/dist/cjs/overlay/overlayRenderContainer.js +3 -4
- package/dist/cjs/paneview/draggablePaneviewPanel.d.ts +2 -2
- package/dist/cjs/paneview/draggablePaneviewPanel.js +5 -5
- package/dist/cjs/paneview/paneviewComponent.d.ts +3 -3
- package/dist/cjs/paneview/paneviewComponent.js +7 -11
- package/dist/cjs/popoutWindow.js +4 -4
- package/dist/cjs/scrollbar.d.ts +1 -1
- package/dist/cjs/scrollbar.js +7 -6
- package/dist/cjs/splitview/splitview.d.ts +1 -1
- package/dist/cjs/splitview/splitview.js +21 -20
- package/dist/cjs/splitview/viewItem.js +1 -1
- package/dist/dockview-core.js +3548 -1544
- package/dist/dockview-core.min.js +2 -2
- package/dist/dockview-core.min.js.map +1 -1
- package/dist/dockview-core.min.noStyle.js +2 -2
- package/dist/dockview-core.min.noStyle.js.map +1 -1
- package/dist/dockview-core.noStyle.js +3547 -1543
- package/dist/esm/api/component.api.d.ts +42 -21
- package/dist/esm/api/component.api.js +63 -18
- package/dist/esm/api/dockviewGroupPanelApi.d.ts +23 -8
- package/dist/esm/api/dockviewGroupPanelApi.js +20 -1
- package/dist/esm/api/dockviewPanelApi.d.ts +4 -3
- package/dist/esm/api/dockviewPanelApi.js +7 -0
- package/dist/esm/dnd/dropTargetAnchorContainer.js +1 -2
- package/dist/esm/dnd/droptarget.d.ts +8 -0
- package/dist/esm/dnd/droptarget.js +28 -0
- package/dist/esm/dnd/pointer/longPress.js +1 -1
- package/dist/esm/dnd/pointer/pointerDragController.js +9 -7
- package/dist/esm/dnd/pointer/pointerDragSource.js +4 -2
- package/dist/esm/dockview/accessibilityMessages.d.ts +32 -0
- package/dist/esm/dockview/accessibilityMessages.js +30 -0
- package/dist/esm/dockview/allModules.d.ts +8 -0
- package/dist/esm/dockview/allModules.js +22 -0
- package/dist/esm/dockview/components/panel/content.d.ts +2 -0
- package/dist/esm/dockview/components/panel/content.js +42 -11
- package/dist/esm/dockview/components/popupService.js +1 -1
- package/dist/esm/dockview/components/tab/tab.js +35 -7
- package/dist/esm/dockview/components/titlebar/floatingTitleBar.d.ts +34 -0
- package/dist/esm/dockview/components/titlebar/floatingTitleBar.js +65 -0
- package/dist/esm/dockview/components/titlebar/groupDragSource.d.ts +51 -0
- package/dist/esm/dockview/components/titlebar/groupDragSource.js +178 -0
- package/dist/esm/dockview/components/titlebar/tabGroupIndicator.d.ts +2 -1
- package/dist/esm/dockview/components/titlebar/tabGroupIndicator.js +36 -30
- package/dist/esm/dockview/components/titlebar/tabGroups.d.ts +27 -5
- package/dist/esm/dockview/components/titlebar/tabGroups.js +91 -41
- package/dist/esm/dockview/components/titlebar/tabs.d.ts +12 -0
- package/dist/esm/dockview/components/titlebar/tabs.js +119 -26
- package/dist/esm/dockview/components/titlebar/tabsContainer.d.ts +4 -0
- package/dist/esm/dockview/components/titlebar/tabsContainer.js +8 -2
- package/dist/esm/dockview/components/titlebar/voidContainer.d.ts +1 -4
- package/dist/esm/dockview/components/titlebar/voidContainer.js +34 -146
- package/dist/esm/dockview/dndCapabilities.js +3 -3
- package/dist/esm/dockview/dockviewComponent.d.ts +304 -49
- package/dist/esm/dockview/dockviewComponent.js +1459 -772
- package/dist/esm/dockview/dockviewFloatingGroupPanel.d.ts +33 -2
- package/dist/esm/dockview/dockviewFloatingGroupPanel.js +35 -3
- package/dist/esm/dockview/dockviewGroupPanel.d.ts +1 -2
- package/dist/esm/dockview/dockviewGroupPanelModel.d.ts +36 -14
- package/dist/esm/dockview/dockviewGroupPanelModel.js +127 -117
- package/dist/esm/dockview/dockviewPanel.d.ts +2 -2
- package/dist/esm/dockview/dockviewPanel.js +1 -2
- package/dist/esm/dockview/dockviewShell.d.ts +29 -7
- package/dist/esm/dockview/dockviewShell.js +89 -37
- package/dist/esm/dockview/edgeGroupService.d.ts +38 -0
- package/dist/esm/dockview/edgeGroupService.js +63 -0
- package/dist/esm/dockview/floatingGroupService.d.ts +37 -0
- package/dist/esm/dockview/floatingGroupService.js +150 -0
- package/dist/esm/dockview/headerActionsService.d.ts +32 -0
- package/dist/esm/dockview/headerActionsService.js +86 -0
- package/dist/esm/dockview/liveRegionService.d.ts +53 -0
- package/dist/esm/dockview/liveRegionService.js +159 -0
- package/dist/esm/dockview/moduleContracts.d.ts +119 -0
- package/dist/esm/dockview/moduleContracts.js +1 -0
- package/dist/esm/dockview/modules.d.ts +110 -0
- package/dist/esm/dockview/modules.js +170 -0
- package/dist/esm/dockview/options.d.ts +159 -6
- package/dist/esm/dockview/options.js +8 -1
- package/dist/esm/dockview/popoutWindowService.d.ts +95 -0
- package/dist/esm/dockview/popoutWindowService.js +175 -0
- package/dist/esm/dockview/rootDropTargetService.d.ts +35 -0
- package/dist/esm/dockview/rootDropTargetService.js +82 -0
- package/dist/esm/dockview/strictEventsSequencing.js +6 -6
- package/dist/esm/dockview/tabGroup.js +3 -3
- package/dist/esm/dockview/tabGroupAccent.js +1 -3
- package/dist/esm/dockview/watermarkService.d.ts +30 -0
- package/dist/esm/dockview/watermarkService.js +56 -0
- package/dist/esm/dom.js +1 -1
- package/dist/esm/events.js +1 -1
- package/dist/esm/gridview/baseComponentGridview.d.ts +1 -1
- package/dist/esm/gridview/baseComponentGridview.js +5 -10
- package/dist/esm/gridview/branchNode.js +13 -15
- package/dist/esm/gridview/gridview.js +8 -8
- package/dist/esm/gridview/gridviewComponent.d.ts +3 -3
- package/dist/esm/gridview/gridviewComponent.js +1 -6
- package/dist/esm/gridview/gridviewPanel.d.ts +1 -1
- package/dist/esm/index.d.ts +11 -4
- package/dist/esm/index.js +4 -0
- package/dist/esm/overlay/overlay.d.ts +43 -1
- package/dist/esm/overlay/overlay.js +78 -36
- package/dist/esm/overlay/overlayRenderContainer.js +3 -4
- package/dist/esm/paneview/draggablePaneviewPanel.d.ts +2 -2
- package/dist/esm/paneview/draggablePaneviewPanel.js +5 -5
- package/dist/esm/paneview/paneviewComponent.d.ts +3 -3
- package/dist/esm/paneview/paneviewComponent.js +7 -11
- package/dist/esm/popoutWindow.js +4 -4
- package/dist/esm/scrollbar.d.ts +1 -1
- package/dist/esm/scrollbar.js +7 -6
- package/dist/esm/splitview/splitview.d.ts +1 -1
- package/dist/esm/splitview/splitview.js +21 -20
- package/dist/esm/splitview/viewItem.js +1 -1
- package/dist/package/main.cjs.js +3550 -1546
- package/dist/package/main.cjs.min.js +2 -2
- package/dist/package/main.esm.min.mjs +2 -2
- package/dist/package/main.esm.mjs +3538 -1545
- package/dist/styles/dockview.css +283 -21
- package/package.json +10 -1
- package/dist/cjs/dockview/contextMenu.d.ts +0 -10
- package/dist/cjs/dockview/contextMenu.js +0 -313
- package/dist/esm/dockview/contextMenu.d.ts +0 -10
- package/dist/esm/dockview/contextMenu.js +0 -228
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { getRelativeLocation, getGridLocation, orthogonal, } from '../gridview/gridview';
|
|
1
|
+
import { getRelativeLocation, getGridLocation, orthogonal, Gridview, } from '../gridview/gridview';
|
|
2
2
|
import { directionToPosition, } from '../dnd/droptarget';
|
|
3
|
-
import {
|
|
4
|
-
import { tail, sequenceEquals, remove } from '../array';
|
|
3
|
+
import { tail, sequenceEquals } from '../array';
|
|
5
4
|
import { DockviewPanel } from './dockviewPanel';
|
|
6
5
|
import { CompositeDisposable, Disposable } from '../lifecycle';
|
|
7
6
|
import { Event, Emitter, addDisposableListener } from '../events';
|
|
@@ -11,29 +10,26 @@ import { DefaultDockviewDeserialzier } from './deserializer';
|
|
|
11
10
|
import { DockviewUnhandledDragOverEvent, isGroupOptionsWithGroup, isGroupOptionsWithPanel, isPanelOptionsWithGroup, isPanelOptionsWithPanel, } from './options';
|
|
12
11
|
import { BaseGrid, toTarget, } from '../gridview/baseComponentGridview';
|
|
13
12
|
import { DockviewApi } from '../api/component.api';
|
|
14
|
-
import { Orientation } from '../splitview/splitview';
|
|
13
|
+
import { Orientation, Sizing } from '../splitview/splitview';
|
|
15
14
|
import { DockviewDidDropEvent, DockviewWillDropEvent, } from './dockviewGroupPanelModel';
|
|
16
15
|
import { DockviewWillShowOverlayLocationEvent, } from './events';
|
|
17
16
|
import { DockviewGroupPanel } from './dockviewGroupPanel';
|
|
18
17
|
import { DockviewPanelModel } from './dockviewPanelModel';
|
|
19
18
|
import { getPanelData } from '../dnd/dataTransfer';
|
|
20
19
|
import { Overlay } from '../overlay/overlay';
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
20
|
+
import { Classnames, getDockviewTheme, onDidWindowResizeEnd, onDidWindowMoveEnd, toggleClass, } from '../dom';
|
|
21
|
+
import { FloatingTitleBar } from './components/titlebar/floatingTitleBar';
|
|
22
|
+
import { assertModule, getRegisteredModules, isDockviewPackageLoaded, ModuleRegistry, } from './modules';
|
|
23
|
+
import { AllModules } from './allModules';
|
|
23
24
|
import { DEFAULT_FLOATING_GROUP_OVERFLOW_SIZE, DEFAULT_FLOATING_GROUP_POSITION, DESERIALIZATION_POPOUT_DELAY_MS, } from '../constants';
|
|
24
25
|
import { OverlayRenderContainer, } from '../overlay/overlayRenderContainer';
|
|
25
26
|
import { PopoutWindow } from '../popoutWindow';
|
|
26
27
|
import { StrictEventsSequencing } from './strictEventsSequencing';
|
|
27
28
|
import { PopupService } from './components/popupService';
|
|
28
|
-
import { ContextMenuController } from './contextMenu';
|
|
29
29
|
import { DropTargetAnchorContainer } from '../dnd/dropTargetAnchorContainer';
|
|
30
30
|
import { themeAbyss } from './theme';
|
|
31
31
|
import { ShellManager, } from './dockviewShell';
|
|
32
32
|
import { DEFAULT_TAB_GROUP_COLORS, TabGroupColorPalette, } from './tabGroupAccent';
|
|
33
|
-
const DEFAULT_ROOT_OVERLAY_MODEL = {
|
|
34
|
-
activationSize: { type: 'pixels', value: 10 },
|
|
35
|
-
size: { type: 'pixels', value: 20 },
|
|
36
|
-
};
|
|
37
33
|
function buildTabGroupColorPalette(options) {
|
|
38
34
|
var _a;
|
|
39
35
|
const entries = (_a = options.tabGroupColors) !== null && _a !== void 0 ? _a : DEFAULT_TAB_GROUP_COLORS;
|
|
@@ -54,7 +50,51 @@ function moveGroupWithoutDestroying(options) {
|
|
|
54
50
|
});
|
|
55
51
|
});
|
|
56
52
|
}
|
|
53
|
+
let _hasWarnedUsingCoreDirectly = false;
|
|
54
|
+
/**
|
|
55
|
+
* `dockview-core` is an internal package. The public `dockview` package calls
|
|
56
|
+
* `markDockviewPackageLoaded()` on import; if that marker is absent the consumer
|
|
57
|
+
* is using `dockview-core` directly, so emit a one-time console warning
|
|
58
|
+
* steering them to `dockview`.
|
|
59
|
+
*
|
|
60
|
+
* Suppressed in production builds: it is a development-time nudge and most
|
|
61
|
+
* bundlers inline `process.env.NODE_ENV` so the branch is dropped entirely. The
|
|
62
|
+
* `typeof process` guard keeps this safe in plain browser/UMD contexts where
|
|
63
|
+
* `process` is undefined.
|
|
64
|
+
*/
|
|
65
|
+
function warnIfUsingCoreDirectly() {
|
|
66
|
+
var _a;
|
|
67
|
+
if (typeof process !== 'undefined' &&
|
|
68
|
+
((_a = process.env) === null || _a === void 0 ? void 0 : _a.NODE_ENV) === 'production') {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
if (_hasWarnedUsingCoreDirectly || isDockviewPackageLoaded()) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
_hasWarnedUsingCoreDirectly = true;
|
|
75
|
+
console.warn('dockview: do not use "dockview-core" directly — it is an internal ' +
|
|
76
|
+
'package. Use the "dockview" package, the JavaScript version of ' +
|
|
77
|
+
'dockview, instead. This notice is shown once.');
|
|
78
|
+
}
|
|
57
79
|
export class DockviewComponent extends BaseGrid {
|
|
80
|
+
fireDidCreateTabGroup(event) {
|
|
81
|
+
this._onDidCreateTabGroup.fire(event);
|
|
82
|
+
}
|
|
83
|
+
fireDidDestroyTabGroup(event) {
|
|
84
|
+
this._onDidDestroyTabGroup.fire(event);
|
|
85
|
+
}
|
|
86
|
+
fireDidAddPanelToTabGroup(event) {
|
|
87
|
+
this._onDidAddPanelToTabGroup.fire(event);
|
|
88
|
+
}
|
|
89
|
+
fireDidRemovePanelFromTabGroup(event) {
|
|
90
|
+
this._onDidRemovePanelFromTabGroup.fire(event);
|
|
91
|
+
}
|
|
92
|
+
fireDidTabGroupChange(event) {
|
|
93
|
+
this._onDidTabGroupChange.fire(event);
|
|
94
|
+
}
|
|
95
|
+
fireDidTabGroupCollapsedChange(event) {
|
|
96
|
+
this._onDidTabGroupCollapsedChange.fire(event);
|
|
97
|
+
}
|
|
58
98
|
get orientation() {
|
|
59
99
|
return this.gridview.orientation;
|
|
60
100
|
}
|
|
@@ -89,17 +129,210 @@ export class DockviewComponent extends BaseGrid {
|
|
|
89
129
|
return this._api;
|
|
90
130
|
}
|
|
91
131
|
get floatingGroups() {
|
|
92
|
-
|
|
132
|
+
var _a, _b, _c;
|
|
133
|
+
return ((_c = (_b = (_a = this._moduleRegistry) === null || _a === void 0 ? void 0 : _a.services.floatingGroupService) === null || _b === void 0 ? void 0 : _b.floatingGroups) !== null && _c !== void 0 ? _c : []);
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Boxes of the floating groups other than `exclude`, in coordinates
|
|
137
|
+
* relative to the floating overlay container. Supplied to a
|
|
138
|
+
* `transformFloatingGroupDrag` callback as `context.others` so it can
|
|
139
|
+
* align the dragged float against its siblings.
|
|
140
|
+
*/
|
|
141
|
+
_gatherFloatingGroupBoxes(exclude) {
|
|
142
|
+
var _a;
|
|
143
|
+
const container = (_a = this._floatingOverlayHost) !== null && _a !== void 0 ? _a : this.gridview.element;
|
|
144
|
+
const containerRect = container.getBoundingClientRect();
|
|
145
|
+
return this.floatingGroups
|
|
146
|
+
.filter((floating) => floating.group !== exclude)
|
|
147
|
+
.map((floating) => {
|
|
148
|
+
const rect = floating.overlay.element.getBoundingClientRect();
|
|
149
|
+
return {
|
|
150
|
+
left: rect.left - containerRect.left,
|
|
151
|
+
top: rect.top - containerRect.top,
|
|
152
|
+
width: rect.width,
|
|
153
|
+
height: rect.height,
|
|
154
|
+
};
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
get _floatingGroupService() {
|
|
158
|
+
return this._moduleRegistry.services.floatingGroupService;
|
|
159
|
+
}
|
|
160
|
+
get _popoutWindowService() {
|
|
161
|
+
return this._moduleRegistry.services.popoutWindowService;
|
|
162
|
+
}
|
|
163
|
+
get _watermarkService() {
|
|
164
|
+
// Tier 1 module — optional. Callers must `?.`-guard so the module
|
|
165
|
+
// can be removed from AllModules without crashing the component.
|
|
166
|
+
return this._moduleRegistry.services.watermarkService;
|
|
167
|
+
}
|
|
168
|
+
get _edgeGroupService() {
|
|
169
|
+
return this._moduleRegistry.services.edgeGroupService;
|
|
170
|
+
}
|
|
171
|
+
get _rootDropTargetService() {
|
|
172
|
+
// Optional like every other module service — RootDropTargetModule can be
|
|
173
|
+
// removed from the registered set without crashing the component.
|
|
174
|
+
return this._moduleRegistry.services.rootDropTargetService;
|
|
175
|
+
}
|
|
176
|
+
get _advancedDnDService() {
|
|
177
|
+
// Optional — callers `?.`-guard so the module can be removed from
|
|
178
|
+
// AllModules. Absent ⇒ the onWill* hooks simply don't fire (≡ no
|
|
179
|
+
// subscriber), which is invisible to apps not customising DnD.
|
|
180
|
+
return this._moduleRegistry.services.advancedDnDService;
|
|
181
|
+
}
|
|
182
|
+
get headerActionsService() {
|
|
183
|
+
return this._moduleRegistry.services.headerActionsService;
|
|
184
|
+
}
|
|
185
|
+
isGridEmpty() {
|
|
186
|
+
return this.gridview.length === 0;
|
|
187
|
+
}
|
|
188
|
+
rootDropTargetOverrideTarget() {
|
|
189
|
+
var _a;
|
|
190
|
+
return (_a = this.rootDropTargetContainer) === null || _a === void 0 ? void 0 : _a.model;
|
|
191
|
+
}
|
|
192
|
+
dispatchUnhandledDragOver(nativeEvent, position) {
|
|
193
|
+
const event = new DockviewUnhandledDragOverEvent(nativeEvent, 'edge', position, getPanelData);
|
|
194
|
+
this._onUnhandledDragOver.fire(event);
|
|
195
|
+
return event.isAccepted;
|
|
196
|
+
}
|
|
197
|
+
// IAdvancedDnDHost — the emitters stay here so the public onWill* event
|
|
198
|
+
// shape is unchanged; AdvancedDnDService routes the per-group fires
|
|
199
|
+
// through these. Engine guards (e.g. disableDnd) run on the component
|
|
200
|
+
// ahead of the dispatch.
|
|
201
|
+
fireWillDragPanel(event) {
|
|
202
|
+
this._onWillDragPanel.fire(event);
|
|
203
|
+
}
|
|
204
|
+
fireWillDragGroup(event) {
|
|
205
|
+
this._onWillDragGroup.fire(event);
|
|
206
|
+
}
|
|
207
|
+
fireWillDrop(event) {
|
|
208
|
+
this._onWillDrop.fire(event);
|
|
209
|
+
}
|
|
210
|
+
fireWillShowOverlay(event) {
|
|
211
|
+
this._onWillShowOverlay.fire(event);
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Resolve the custom group drag ghost (via the AdvancedDnD module), or
|
|
215
|
+
* `undefined` to fall back to the default chip. Returns `undefined` when
|
|
216
|
+
* the module is absent — the default ghost then renders.
|
|
217
|
+
*/
|
|
218
|
+
buildGroupDragGhost(group) {
|
|
219
|
+
var _a;
|
|
220
|
+
return (_a = this._advancedDnDService) === null || _a === void 0 ? void 0 : _a.buildGroupDragGhost(group);
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Resolve the app-supplied drop overlay model (via the AdvancedDnD module)
|
|
224
|
+
* for a group drop target, or `undefined` to keep the target's default.
|
|
225
|
+
*/
|
|
226
|
+
resolveDropOverlayModel(location, group) {
|
|
227
|
+
var _a;
|
|
228
|
+
return (_a = this._advancedDnDService) === null || _a === void 0 ? void 0 : _a.resolveOverlayModel(location, group);
|
|
229
|
+
}
|
|
230
|
+
// IAccessibilityHost — keyboard docking reaches the AdvancedDnD preview +
|
|
231
|
+
// LiveRegion announcer through these so the service stays decoupled.
|
|
232
|
+
/** Outermost element — the shell (incl. edge groups) once built, else the gridview. */
|
|
233
|
+
get rootElement() {
|
|
234
|
+
var _a, _b;
|
|
235
|
+
return (_b = (_a = this._shellManager) === null || _a === void 0 ? void 0 : _a.element) !== null && _b !== void 0 ? _b : this.element;
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* The next / previous group in gridview (spatial) order, wrapping round.
|
|
239
|
+
* The keyboard accessibility module's focus navigation is built on this
|
|
240
|
+
* primitive — the only piece that needs the grid internals; the rest of
|
|
241
|
+
* the navigation logic lives in the AccessibilityService.
|
|
242
|
+
*/
|
|
243
|
+
adjacentGroup(group, reverse) {
|
|
244
|
+
var _a;
|
|
245
|
+
// gridview traversal only covers grid groups; a floating/popout group
|
|
246
|
+
// isn't in the grid, so there's no adjacent grid group to step to.
|
|
247
|
+
if (group.api.location.type !== 'grid') {
|
|
248
|
+
return undefined;
|
|
249
|
+
}
|
|
250
|
+
const location = getGridLocation(group.element);
|
|
251
|
+
return ((_a = (reverse
|
|
252
|
+
? this.gridview.previous(location)
|
|
253
|
+
: this.gridview.next(location))) === null || _a === void 0 ? void 0 : _a.view);
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* The nearest grid group in a spatial direction from `group`, by
|
|
257
|
+
* comparing group centre points. Floating and popout groups sit outside
|
|
258
|
+
* the grid's geometry and are ignored. Returns `undefined` when there is
|
|
259
|
+
* no group in that direction.
|
|
260
|
+
*/
|
|
261
|
+
adjacentGroupInDirection(group, direction) {
|
|
262
|
+
if (group.api.location.type !== 'grid') {
|
|
263
|
+
return undefined;
|
|
264
|
+
}
|
|
265
|
+
const from = group.element.getBoundingClientRect();
|
|
266
|
+
const fromX = from.left + from.width / 2;
|
|
267
|
+
const fromY = from.top + from.height / 2;
|
|
268
|
+
let best;
|
|
269
|
+
let bestDistance = Number.POSITIVE_INFINITY;
|
|
270
|
+
for (const candidate of this.groups) {
|
|
271
|
+
if (candidate === group || candidate.api.location.type !== 'grid') {
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
const rect = candidate.element.getBoundingClientRect();
|
|
275
|
+
const dx = rect.left + rect.width / 2 - fromX;
|
|
276
|
+
const dy = rect.top + rect.height / 2 - fromY;
|
|
277
|
+
// Require the candidate to sit predominantly in the asked-for
|
|
278
|
+
// direction (dominant axis), so 'left' ignores a group that's
|
|
279
|
+
// mostly above/below.
|
|
280
|
+
const inDirection = direction === 'left'
|
|
281
|
+
? dx < 0 && Math.abs(dx) >= Math.abs(dy)
|
|
282
|
+
: direction === 'right'
|
|
283
|
+
? dx > 0 && Math.abs(dx) >= Math.abs(dy)
|
|
284
|
+
: direction === 'up'
|
|
285
|
+
? dy < 0 && Math.abs(dy) >= Math.abs(dx)
|
|
286
|
+
: dy > 0 && Math.abs(dy) >= Math.abs(dx);
|
|
287
|
+
if (!inDirection) {
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
const distance = dx * dx + dy * dy;
|
|
291
|
+
if (distance < bestDistance) {
|
|
292
|
+
bestDistance = distance;
|
|
293
|
+
best = candidate;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
return best;
|
|
297
|
+
}
|
|
298
|
+
showDropPreview(group, position) {
|
|
299
|
+
var _a, _b;
|
|
300
|
+
return ((_b = (_a = this._advancedDnDService) === null || _a === void 0 ? void 0 : _a.showPreviewOverlay(group, position)) !== null && _b !== void 0 ? _b : Disposable.NONE);
|
|
301
|
+
}
|
|
302
|
+
announce(message) {
|
|
303
|
+
var _a;
|
|
304
|
+
(_a = this._moduleRegistry.services.liveRegionService) === null || _a === void 0 ? void 0 : _a.announce(message);
|
|
305
|
+
}
|
|
306
|
+
dockPanel(panel, group, position) {
|
|
307
|
+
this.moveGroupOrPanel({
|
|
308
|
+
from: { groupId: panel.group.id, panelId: panel.id },
|
|
309
|
+
to: { group, position },
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
get contextMenuService() {
|
|
313
|
+
// Owned by ContextMenuModule — undefined when the module is not
|
|
314
|
+
// registered, so callers must `?.`-guard.
|
|
315
|
+
return this._moduleRegistry.services.contextMenuService;
|
|
316
|
+
}
|
|
317
|
+
get mountElement() {
|
|
318
|
+
return this.gridview.element;
|
|
319
|
+
}
|
|
320
|
+
hasVisibleGridGroup() {
|
|
321
|
+
return this.groups.some((group) => group.api.location.type === 'grid' && group.api.isVisible);
|
|
322
|
+
}
|
|
323
|
+
fireLayoutChange() {
|
|
324
|
+
this._bufferOnDidLayoutChange.fire();
|
|
93
325
|
}
|
|
94
326
|
/**
|
|
95
327
|
* Promise that resolves when all popout groups from the last fromJSON call are restored.
|
|
96
328
|
* Useful for tests that need to wait for delayed popout creation.
|
|
97
329
|
*/
|
|
98
330
|
get popoutRestorationPromise() {
|
|
99
|
-
|
|
331
|
+
var _a, _b;
|
|
332
|
+
return ((_b = (_a = this._popoutWindowService) === null || _a === void 0 ? void 0 : _a.restorationPromise) !== null && _b !== void 0 ? _b : Promise.resolve());
|
|
100
333
|
}
|
|
101
334
|
constructor(container, options) {
|
|
102
|
-
var _a, _b, _c, _d, _e
|
|
335
|
+
var _a, _b, _c, _d, _e;
|
|
103
336
|
super(container, {
|
|
104
337
|
proportionalLayout: true,
|
|
105
338
|
orientation: Orientation.HORIZONTAL,
|
|
@@ -113,8 +346,7 @@ export class DockviewComponent extends BaseGrid {
|
|
|
113
346
|
});
|
|
114
347
|
this.nextGroupId = sequentialNumberGenerator();
|
|
115
348
|
this._deserializer = new DefaultDockviewDeserialzier(this);
|
|
116
|
-
this.
|
|
117
|
-
this._popoutPopupServices = new Map();
|
|
349
|
+
this._moduleRegistry = new ModuleRegistry();
|
|
118
350
|
this._onWillDragPanel = new Emitter();
|
|
119
351
|
this.onWillDragPanel = this._onWillDragPanel.event;
|
|
120
352
|
this._onWillDragGroup = new Emitter();
|
|
@@ -123,10 +355,25 @@ export class DockviewComponent extends BaseGrid {
|
|
|
123
355
|
this.onDidDrop = this._onDidDrop.event;
|
|
124
356
|
this._onWillDrop = new Emitter();
|
|
125
357
|
this.onWillDrop = this._onWillDrop.event;
|
|
358
|
+
// Transaction boundary bracketing each top-level structural mutation.
|
|
359
|
+
// Compound operations (e.g. a drag that relocates a panel) nest via the
|
|
360
|
+
// depth counter and bracket as a single transaction. See `mutation()`.
|
|
361
|
+
this._mutationDepth = 0;
|
|
362
|
+
// Current operation origin. Defaults to `'user'`; the DockviewApi boundary
|
|
363
|
+
// flips it to `'api'` for the duration of a programmatic call via
|
|
364
|
+
// `withOrigin`. Nested operations inherit the outermost origin (tracked by
|
|
365
|
+
// `_originDepth`, independent of mutation bracketing so it also covers
|
|
366
|
+
// active-panel changes that are not structural mutations).
|
|
367
|
+
this._origin = 'user';
|
|
368
|
+
this._originDepth = 0;
|
|
369
|
+
this._onWillMutateLayout = new Emitter();
|
|
370
|
+
this.onWillMutateLayout = this._onWillMutateLayout.event;
|
|
371
|
+
this._onDidMutateLayout = new Emitter();
|
|
372
|
+
this.onDidMutateLayout = this._onDidMutateLayout.event;
|
|
126
373
|
this._onWillShowOverlay = new Emitter();
|
|
127
374
|
this.onWillShowOverlay = this._onWillShowOverlay.event;
|
|
128
|
-
this.
|
|
129
|
-
this.
|
|
375
|
+
this._onUnhandledDragOver = new Emitter();
|
|
376
|
+
this.onUnhandledDragOver = this._onUnhandledDragOver.event;
|
|
130
377
|
this._onDidRemovePanel = new Emitter();
|
|
131
378
|
this.onDidRemovePanel = this._onDidRemovePanel.event;
|
|
132
379
|
this._onDidAddPanel = new Emitter();
|
|
@@ -135,6 +382,10 @@ export class DockviewComponent extends BaseGrid {
|
|
|
135
382
|
this.onDidPopoutGroupSizeChange = this._onDidPopoutGroupSizeChange.event;
|
|
136
383
|
this._onDidPopoutGroupPositionChange = new Emitter();
|
|
137
384
|
this.onDidPopoutGroupPositionChange = this._onDidPopoutGroupPositionChange.event;
|
|
385
|
+
this._onDidAddPopoutGroup = new Emitter();
|
|
386
|
+
this.onDidAddPopoutGroup = this._onDidAddPopoutGroup.event;
|
|
387
|
+
this._onDidRemovePopoutGroup = new Emitter();
|
|
388
|
+
this.onDidRemovePopoutGroup = this._onDidRemovePopoutGroup.event;
|
|
138
389
|
this._onDidOpenPopoutWindowFail = new Emitter();
|
|
139
390
|
this.onDidOpenPopoutWindowFail = this._onDidOpenPopoutWindowFail.event;
|
|
140
391
|
this._onDidLayoutFromJSON = new Emitter();
|
|
@@ -158,12 +409,6 @@ export class DockviewComponent extends BaseGrid {
|
|
|
158
409
|
this._onDidMaximizedGroupChange = new Emitter();
|
|
159
410
|
this.onDidMaximizedGroupChange = this._onDidMaximizedGroupChange.event;
|
|
160
411
|
this._inShellLayout = false;
|
|
161
|
-
this._edgeGroups = new Map();
|
|
162
|
-
this._edgeGroupDisposables = new Map();
|
|
163
|
-
this._floatingGroups = [];
|
|
164
|
-
this._popoutGroups = [];
|
|
165
|
-
this._popoutRestorationPromise = Promise.resolve();
|
|
166
|
-
this._popoutRestorationCleanups = new Set();
|
|
167
412
|
this._onDidRemoveGroup = new Emitter();
|
|
168
413
|
this.onDidRemoveGroup = this._onDidRemoveGroup.event;
|
|
169
414
|
this._onDidAddGroup = new Emitter();
|
|
@@ -175,13 +420,43 @@ export class DockviewComponent extends BaseGrid {
|
|
|
175
420
|
this._moving = false;
|
|
176
421
|
this._options = options;
|
|
177
422
|
this._tabGroupColorPalette = buildTabGroupColorPalette(options);
|
|
423
|
+
// Internal seam: defaults to the full set, but tests can supply a
|
|
424
|
+
// subset to assert every module is independently removable (and the
|
|
425
|
+
// opt-in module API will build on this later). Not part of the public
|
|
426
|
+
// options surface.
|
|
427
|
+
const explicitModules = options
|
|
428
|
+
.modules;
|
|
429
|
+
const modules = explicitModules !== null && explicitModules !== void 0 ? explicitModules : [
|
|
430
|
+
...AllModules,
|
|
431
|
+
...getRegisteredModules(),
|
|
432
|
+
];
|
|
433
|
+
for (const module of modules) {
|
|
434
|
+
this._moduleRegistry.register(module);
|
|
435
|
+
}
|
|
436
|
+
this._moduleRegistry.initialize(this);
|
|
437
|
+
// Surface popout removal symmetrically with `onDidAddPopoutGroup`. The
|
|
438
|
+
// service is the single point every removal path funnels through — a
|
|
439
|
+
// genuine window close and an explicit removal alike — and it suppresses
|
|
440
|
+
// the event during component teardown.
|
|
441
|
+
const popoutWindowService = this._popoutWindowService;
|
|
442
|
+
if (popoutWindowService) {
|
|
443
|
+
this.addDisposables(popoutWindowService.onDidRemove((entry) => {
|
|
444
|
+
this._onDidRemovePopoutGroup.fire({
|
|
445
|
+
id: entry.popoutGroup.id,
|
|
446
|
+
group: entry.popoutGroup,
|
|
447
|
+
window: entry.getWindow(),
|
|
448
|
+
});
|
|
449
|
+
}));
|
|
450
|
+
}
|
|
451
|
+
// Purely a developer warning (no functional effect): nudge anyone using
|
|
452
|
+
// the internal `dockview-core` package directly towards `dockview`.
|
|
453
|
+
warnIfUsingCoreDirectly();
|
|
178
454
|
this.popupService = new PopupService(this.element);
|
|
179
|
-
this.contextMenuController = new ContextMenuController(this);
|
|
180
455
|
this._api = new DockviewApi(this);
|
|
181
456
|
// The shell always wraps the dockview element so edge groups can be
|
|
182
457
|
// added at any time via addEdgeGroup() without re-parenting the DOM.
|
|
183
458
|
this.disableResizing = true;
|
|
184
|
-
|
|
459
|
+
this.element.remove();
|
|
185
460
|
this._shellManager = new ShellManager(container, this.element, (w, h) => this._layoutFromShell(w, h), (_d = (_c = options.theme) === null || _c === void 0 ? void 0 : _c.gap) !== null && _d !== void 0 ? _d : 0, (_e = options.theme) === null || _e === void 0 ? void 0 : _e.edgeGroupCollapsedSize);
|
|
186
461
|
// The shell wraps the dockview element, so move the popup anchor
|
|
187
462
|
// into the shell so overflow dropdowns in edge groups position correctly
|
|
@@ -198,69 +473,23 @@ export class DockviewComponent extends BaseGrid {
|
|
|
198
473
|
this._floatingOverlayHost = document.createElement('div');
|
|
199
474
|
this._floatingOverlayHost.className = 'dv-floating-overlay-host';
|
|
200
475
|
this._shellManager.element.appendChild(this._floatingOverlayHost);
|
|
201
|
-
const rootCanDisplayOverlay = (event, position) => {
|
|
202
|
-
const data = getPanelData();
|
|
203
|
-
if (data) {
|
|
204
|
-
if (data.viewId !== this.id) {
|
|
205
|
-
return false;
|
|
206
|
-
}
|
|
207
|
-
if (position === 'center') {
|
|
208
|
-
// center drop target is only allowed if there are no panels in the grid
|
|
209
|
-
// floating panels are allowed
|
|
210
|
-
return this.gridview.length === 0;
|
|
211
|
-
}
|
|
212
|
-
return true;
|
|
213
|
-
}
|
|
214
|
-
if (position === 'center' && this.gridview.length !== 0) {
|
|
215
|
-
/**
|
|
216
|
-
* for external events only show the four-corner drag overlays, disable
|
|
217
|
-
* the center position so that external drag events can fall through to the group
|
|
218
|
-
* and panel drop target handlers
|
|
219
|
-
*/
|
|
220
|
-
return false;
|
|
221
|
-
}
|
|
222
|
-
const firedEvent = new DockviewUnhandledDragOverEvent(event, 'edge', position, getPanelData);
|
|
223
|
-
this._onUnhandledDragOverEvent.fire(firedEvent);
|
|
224
|
-
return firedEvent.isAccepted;
|
|
225
|
-
};
|
|
226
|
-
this._rootDropTarget = html5Backend.createDropTarget(this.element, {
|
|
227
|
-
className: 'dv-drop-target-edge',
|
|
228
|
-
canDisplayOverlay: rootCanDisplayOverlay,
|
|
229
|
-
acceptedTargetZones: ['top', 'bottom', 'left', 'right', 'center'],
|
|
230
|
-
overlayModel: (_f = options.rootOverlayModel) !== null && _f !== void 0 ? _f : DEFAULT_ROOT_OVERLAY_MODEL,
|
|
231
|
-
getOverrideTarget: () => { var _a; return (_a = this.rootDropTargetContainer) === null || _a === void 0 ? void 0 : _a.model; },
|
|
232
|
-
});
|
|
233
|
-
this._rootPointerDropTarget = pointerBackend.createDropTarget(this.element, {
|
|
234
|
-
className: 'dv-drop-target-edge',
|
|
235
|
-
canDisplayOverlay: rootCanDisplayOverlay,
|
|
236
|
-
acceptedTargetZones: [
|
|
237
|
-
'top',
|
|
238
|
-
'bottom',
|
|
239
|
-
'left',
|
|
240
|
-
'right',
|
|
241
|
-
'center',
|
|
242
|
-
],
|
|
243
|
-
overlayModel: (_g = options.rootOverlayModel) !== null && _g !== void 0 ? _g : DEFAULT_ROOT_OVERLAY_MODEL,
|
|
244
|
-
getOverrideTarget: () => { var _a; return (_a = this.rootDropTargetContainer) === null || _a === void 0 ? void 0 : _a.model; },
|
|
245
|
-
});
|
|
246
|
-
this.updateDropTargetModel(options);
|
|
247
476
|
toggleClass(this.gridview.element, 'dv-dockview', true);
|
|
248
477
|
toggleClass(this.element, 'dv-debug', !!options.debug);
|
|
249
478
|
this.updateTheme();
|
|
250
|
-
this.updateWatermark();
|
|
251
479
|
if (options.debug) {
|
|
252
480
|
this.addDisposables(new StrictEventsSequencing(this));
|
|
253
481
|
}
|
|
254
|
-
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._onDidMovePanel.event(() => {
|
|
482
|
+
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._onWillMutateLayout, this._onDidMutateLayout, this._onDidMovePanel, this._onDidMovePanel.event(() => {
|
|
255
483
|
/**
|
|
256
484
|
* Update overlay positions after DOM layout completes to prevent 0×0 dimensions.
|
|
257
485
|
* With defaultRenderer="always" this results in panel content not showing after move operations.
|
|
258
486
|
* Debounced to avoid multiple calls when moving groups with multiple panels.
|
|
259
487
|
*/
|
|
260
488
|
this.debouncedUpdateAllPositions();
|
|
261
|
-
}), this._onDidAddGroup, this._onDidRemoveGroup, this._onDidActiveGroupChange, this.
|
|
262
|
-
|
|
263
|
-
|
|
489
|
+
}), this._onDidAddGroup, this._onDidRemoveGroup, this._onDidActiveGroupChange, this._onUnhandledDragOver, this._onDidMaximizedGroupChange, this._onDidPopoutGroupSizeChange, this._onDidPopoutGroupPositionChange, this._onDidAddPopoutGroup, this._onDidRemovePopoutGroup, this._onDidOpenPopoutWindowFail, this._onDidCreateTabGroup, this._onDidDestroyTabGroup, this._onDidAddPanelToTabGroup, this._onDidRemovePanelFromTabGroup, this._onDidTabGroupChange, this._onDidTabGroupCollapsedChange, Event.any(this.onDidPopoutGroupSizeChange, this.onDidPopoutGroupPositionChange, this.onDidCreateTabGroup, this.onDidDestroyTabGroup, this.onDidAddPanelToTabGroup, this.onDidRemovePanelFromTabGroup, this.onDidTabGroupChange, this.onDidTabGroupCollapsedChange)(() => {
|
|
490
|
+
// Popout size/position and tab-group mutations persist as layout changes.
|
|
491
|
+
this.fireLayoutChange();
|
|
492
|
+
}), this._onDidOptionsChange, this.onDidAdd((event) => {
|
|
264
493
|
if (!this._moving) {
|
|
265
494
|
this._onDidAddGroup.fire(event);
|
|
266
495
|
}
|
|
@@ -277,84 +506,80 @@ export class DockviewComponent extends BaseGrid {
|
|
|
277
506
|
group: event.panel,
|
|
278
507
|
isMaximized: event.isMaximized,
|
|
279
508
|
});
|
|
280
|
-
}), Event.any(this.
|
|
281
|
-
this.updateWatermark();
|
|
282
|
-
}), Event.any(this.onDidAddPanel, this.onDidRemovePanel, this.onDidAddGroup, this.onDidRemove, this.onDidRemoveGroup, this.onDidMovePanel, this.onDidActivePanelChange, this.onDidPopoutGroupPositionChange, this.onDidPopoutGroupSizeChange, this.onDidCreateTabGroup, this.onDidDestroyTabGroup, this.onDidAddPanelToTabGroup, this.onDidRemovePanelFromTabGroup, this.onDidTabGroupChange, this.onDidTabGroupCollapsedChange)(() => {
|
|
509
|
+
}), Event.any(this.onDidAddPanel, this.onDidRemovePanel, this.onDidAddGroup, this.onDidRemove, this.onDidRemoveGroup, this.onDidMovePanel, this.onDidActivePanelChange)(() => {
|
|
283
510
|
this._bufferOnDidLayoutChange.fire();
|
|
284
511
|
}), Disposable.from(() => {
|
|
285
512
|
var _a;
|
|
286
|
-
//
|
|
287
|
-
//
|
|
288
|
-
//
|
|
289
|
-
//
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
this._popoutRestorationCleanups.clear();
|
|
294
|
-
// iterate over a copy of the array since .dispose() mutates the original array
|
|
295
|
-
for (const group of [...this._floatingGroups]) {
|
|
296
|
-
group.dispose();
|
|
297
|
-
}
|
|
298
|
-
// iterate over a copy of the array since .dispose() mutates the original array
|
|
299
|
-
for (const group of [...this._popoutGroups]) {
|
|
300
|
-
group.disposable.dispose();
|
|
301
|
-
}
|
|
513
|
+
// Registry disposes init() subscriptions then every module
|
|
514
|
+
// service that implements IDisposable. The order matters so
|
|
515
|
+
// init handlers stop firing into services about to be torn
|
|
516
|
+
// down. Includes popout-restoration timer cancellation that
|
|
517
|
+
// resolves promises so awaiters of popoutRestorationPromise
|
|
518
|
+
// don't hang. See issue #851.
|
|
519
|
+
this._moduleRegistry.dispose();
|
|
302
520
|
(_a = this._shellManager) === null || _a === void 0 ? void 0 : _a.dispose();
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
panel: undefined,
|
|
325
|
-
api: this._api,
|
|
326
|
-
group: undefined,
|
|
327
|
-
getData: getPanelData,
|
|
328
|
-
kind: 'edge',
|
|
329
|
-
});
|
|
330
|
-
this._onWillDrop.fire(willDropEvent);
|
|
331
|
-
if (willDropEvent.defaultPrevented) {
|
|
332
|
-
return;
|
|
333
|
-
}
|
|
334
|
-
const data = getPanelData();
|
|
335
|
-
if (data) {
|
|
336
|
-
this.moveGroupOrPanel({
|
|
337
|
-
from: {
|
|
338
|
-
groupId: data.groupId,
|
|
339
|
-
panelId: (_a = data.panelId) !== null && _a !== void 0 ? _a : undefined,
|
|
340
|
-
},
|
|
341
|
-
to: {
|
|
342
|
-
group: this.orthogonalize(event.position),
|
|
343
|
-
position: 'center',
|
|
344
|
-
},
|
|
345
|
-
});
|
|
346
|
-
}
|
|
347
|
-
else {
|
|
348
|
-
this._onDidDrop.fire(new DockviewDidDropEvent({
|
|
521
|
+
}));
|
|
522
|
+
// Root edge-drop wiring lives with its (optional) module — guard it so
|
|
523
|
+
// the module is independently removable.
|
|
524
|
+
const rootDropTarget = this._rootDropTargetService;
|
|
525
|
+
if (rootDropTarget) {
|
|
526
|
+
this.addDisposables(rootDropTarget.onWillShowOverlay((event) => {
|
|
527
|
+
if (this.gridview.length > 0 &&
|
|
528
|
+
event.position === 'center') {
|
|
529
|
+
// option only available when no panels in primary grid
|
|
530
|
+
return;
|
|
531
|
+
}
|
|
532
|
+
this._onWillShowOverlay.fire(new DockviewWillShowOverlayLocationEvent(event, {
|
|
533
|
+
kind: 'edge',
|
|
534
|
+
panel: undefined,
|
|
535
|
+
api: this._api,
|
|
536
|
+
group: undefined,
|
|
537
|
+
getData: getPanelData,
|
|
538
|
+
}));
|
|
539
|
+
}), rootDropTarget.onDrop((event) => {
|
|
540
|
+
var _a;
|
|
541
|
+
const willDropEvent = new DockviewWillDropEvent({
|
|
349
542
|
nativeEvent: event.nativeEvent,
|
|
350
543
|
position: event.position,
|
|
351
544
|
panel: undefined,
|
|
352
545
|
api: this._api,
|
|
353
546
|
group: undefined,
|
|
354
547
|
getData: getPanelData,
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
548
|
+
kind: 'edge',
|
|
549
|
+
});
|
|
550
|
+
this._onWillDrop.fire(willDropEvent);
|
|
551
|
+
if (willDropEvent.defaultPrevented) {
|
|
552
|
+
return;
|
|
553
|
+
}
|
|
554
|
+
const data = getPanelData();
|
|
555
|
+
if (data) {
|
|
556
|
+
this.moveGroupOrPanel({
|
|
557
|
+
from: {
|
|
558
|
+
groupId: data.groupId,
|
|
559
|
+
panelId: (_a = data.panelId) !== null && _a !== void 0 ? _a : undefined,
|
|
560
|
+
},
|
|
561
|
+
to: {
|
|
562
|
+
group: this.orthogonalize(event.position),
|
|
563
|
+
position: 'center',
|
|
564
|
+
},
|
|
565
|
+
});
|
|
566
|
+
}
|
|
567
|
+
else {
|
|
568
|
+
this._onDidDrop.fire(new DockviewDidDropEvent({
|
|
569
|
+
nativeEvent: event.nativeEvent,
|
|
570
|
+
position: event.position,
|
|
571
|
+
panel: undefined,
|
|
572
|
+
api: this._api,
|
|
573
|
+
group: undefined,
|
|
574
|
+
getData: getPanelData,
|
|
575
|
+
}));
|
|
576
|
+
}
|
|
577
|
+
}));
|
|
578
|
+
}
|
|
579
|
+
// Final module wiring: runs after the host is fully constructed.
|
|
580
|
+
// Modules subscribe to host events here so the component doesn't
|
|
581
|
+
// need to manually invoke them at scattered call sites.
|
|
582
|
+
this._moduleRegistry.postConstruct(this);
|
|
358
583
|
}
|
|
359
584
|
setVisible(panel, visible) {
|
|
360
585
|
switch (panel.api.location.type) {
|
|
@@ -386,11 +611,29 @@ export class DockviewComponent extends BaseGrid {
|
|
|
386
611
|
* and dismisses on events from that window.
|
|
387
612
|
*/
|
|
388
613
|
getPopupServiceForGroup(group) {
|
|
389
|
-
var _a;
|
|
390
|
-
return (_a = this.
|
|
614
|
+
var _a, _b;
|
|
615
|
+
return ((_b = (_a = this._popoutWindowService) === null || _a === void 0 ? void 0 : _a.getPopupService(group.id)) !== null && _b !== void 0 ? _b : this.popupService);
|
|
391
616
|
}
|
|
392
617
|
addPopoutGroup(itemToPopout, options) {
|
|
393
|
-
|
|
618
|
+
// The transaction brackets the synchronous structural change; the
|
|
619
|
+
// popout window opens asynchronously after it resolves.
|
|
620
|
+
return this.mutation('popout', () => this._doAddPopoutGroup(itemToPopout, options));
|
|
621
|
+
}
|
|
622
|
+
/** Enumerate the popout groups currently open in their own windows. */
|
|
623
|
+
getPopouts() {
|
|
624
|
+
var _a, _b;
|
|
625
|
+
return ((_b = (_a = this._popoutWindowService) === null || _a === void 0 ? void 0 : _a.entries.map((entry) => ({
|
|
626
|
+
id: entry.popoutGroup.id,
|
|
627
|
+
group: entry.popoutGroup,
|
|
628
|
+
window: entry.getWindow(),
|
|
629
|
+
}))) !== null && _b !== void 0 ? _b : []);
|
|
630
|
+
}
|
|
631
|
+
_doAddPopoutGroup(itemToPopout, options) {
|
|
632
|
+
var _a, _b, _c, _d, _e;
|
|
633
|
+
const service = assertModule(this._popoutWindowService, 'PopoutWindow', 'api.addPopoutGroup');
|
|
634
|
+
if (!service) {
|
|
635
|
+
return Promise.resolve(false);
|
|
636
|
+
}
|
|
394
637
|
if (itemToPopout instanceof DockviewGroupPanel &&
|
|
395
638
|
itemToPopout.model.location.type === 'edge') {
|
|
396
639
|
// edge groups are permanent structural elements and cannot be popped out
|
|
@@ -416,16 +659,21 @@ export class DockviewComponent extends BaseGrid {
|
|
|
416
659
|
}
|
|
417
660
|
const box = getBox();
|
|
418
661
|
const 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();
|
|
662
|
+
// Resolve the configured popout URL once (per-call override → global
|
|
663
|
+
// option). Recorded on the entry / group locations so it survives
|
|
664
|
+
// serialization; the '/popout.html' default is applied only when
|
|
665
|
+
// actually opening the window, not baked into saved layouts.
|
|
666
|
+
const resolvedPopoutUrl = (_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;
|
|
419
667
|
const _window = new PopoutWindow(`${this.id}-${groupId}`, // unique id
|
|
420
668
|
theme !== null && theme !== void 0 ? theme : '', {
|
|
421
|
-
url:
|
|
669
|
+
url: resolvedPopoutUrl !== null && resolvedPopoutUrl !== void 0 ? resolvedPopoutUrl : '/popout.html',
|
|
422
670
|
left: window.screenX + box.left,
|
|
423
671
|
top: window.screenY + box.top,
|
|
424
672
|
width: box.width,
|
|
425
673
|
height: box.height,
|
|
426
674
|
onDidOpen: options === null || options === void 0 ? void 0 : options.onDidOpen,
|
|
427
675
|
onWillClose: options === null || options === void 0 ? void 0 : options.onWillClose,
|
|
428
|
-
nonce: (
|
|
676
|
+
nonce: (_e = this.options) === null || _e === void 0 ? void 0 : _e.nonce,
|
|
429
677
|
});
|
|
430
678
|
const popoutWindowDisposable = new CompositeDisposable(_window, _window.onDidClose(() => {
|
|
431
679
|
popoutWindowDisposable.dispose();
|
|
@@ -433,15 +681,13 @@ export class DockviewComponent extends BaseGrid {
|
|
|
433
681
|
return _window
|
|
434
682
|
.open()
|
|
435
683
|
.then((popoutContainer) => {
|
|
436
|
-
var _a;
|
|
684
|
+
var _a, _b, _c, _d;
|
|
437
685
|
if (_window.isDisposed) {
|
|
438
686
|
return false;
|
|
439
687
|
}
|
|
440
|
-
const referenceGroup = (options === null || options === void 0 ? void 0 : options.referenceGroup)
|
|
441
|
-
?
|
|
442
|
-
: itemToPopout
|
|
443
|
-
? itemToPopout.group
|
|
444
|
-
: itemToPopout;
|
|
688
|
+
const referenceGroup = (_a = options === null || options === void 0 ? void 0 : options.referenceGroup) !== null && _a !== void 0 ? _a : (itemToPopout instanceof DockviewPanel
|
|
689
|
+
? itemToPopout.group
|
|
690
|
+
: itemToPopout);
|
|
445
691
|
const referenceLocation = itemToPopout.api.location.type;
|
|
446
692
|
/**
|
|
447
693
|
* The group that is being added doesn't already exist within the DOM, the most likely occurrence
|
|
@@ -449,7 +695,12 @@ export class DockviewComponent extends BaseGrid {
|
|
|
449
695
|
*/
|
|
450
696
|
const isGroupAddedToDom = referenceGroup.element.parentElement !== null;
|
|
451
697
|
let group;
|
|
452
|
-
if (
|
|
698
|
+
if (options === null || options === void 0 ? void 0 : options.overridePopoutGridview) {
|
|
699
|
+
// Restoring a multi-group window: the anchor group is
|
|
700
|
+
// already built inside the supplied gridview.
|
|
701
|
+
group = (_b = options.overridePopoutGroup) !== null && _b !== void 0 ? _b : referenceGroup;
|
|
702
|
+
}
|
|
703
|
+
else if (!isGroupAddedToDom) {
|
|
453
704
|
group = referenceGroup;
|
|
454
705
|
}
|
|
455
706
|
else if (options === null || options === void 0 ? void 0 : options.overridePopoutGroup) {
|
|
@@ -462,27 +713,46 @@ export class DockviewComponent extends BaseGrid {
|
|
|
462
713
|
}
|
|
463
714
|
}
|
|
464
715
|
if (popoutContainer === null) {
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
from: group,
|
|
472
|
-
to: referenceGroup,
|
|
473
|
-
}));
|
|
474
|
-
if (!referenceGroup.api.isVisible) {
|
|
475
|
-
referenceGroup.api.setVisible(true);
|
|
476
|
-
}
|
|
716
|
+
this.handleBlockedPopout({
|
|
717
|
+
group,
|
|
718
|
+
referenceGroup,
|
|
719
|
+
options,
|
|
720
|
+
popoutWindowDisposable,
|
|
721
|
+
});
|
|
477
722
|
return false;
|
|
478
723
|
}
|
|
479
724
|
const gready = document.createElement('div');
|
|
480
725
|
gready.className = 'dv-overlay-render-container';
|
|
481
726
|
const overlayRenderContainer = new OverlayRenderContainer(gready, this);
|
|
482
727
|
group.model.renderContainer = overlayRenderContainer;
|
|
483
|
-
|
|
728
|
+
// The popout window hosts its own gridview so it can grow into
|
|
729
|
+
// a nested splitview layout. The window starts with the single
|
|
730
|
+
// anchor group; further groups arrive via drag-and-drop. On
|
|
731
|
+
// restore a pre-populated gridview is supplied instead.
|
|
732
|
+
const popoutGridview = (_c = options === null || options === void 0 ? void 0 : options.overridePopoutGridview) !== null && _c !== void 0 ? _c : this.createNestedGridview();
|
|
733
|
+
if (!(options === null || options === void 0 ? void 0 : options.overridePopoutGridview)) {
|
|
734
|
+
popoutGridview.addView(group, Sizing.Distribute, [0]);
|
|
735
|
+
}
|
|
736
|
+
// Fill the popout window. Unlike the main grid (explicit px) and
|
|
737
|
+
// floating windows (CSS inside .dv-resize-container), the popout
|
|
738
|
+
// gridview has no sizing context, so without this it collapses
|
|
739
|
+
// to 0 height and nothing renders.
|
|
740
|
+
popoutGridview.element.style.width = '100%';
|
|
741
|
+
popoutGridview.element.style.height = '100%';
|
|
742
|
+
popoutGridview.layout(_window.window.innerWidth, _window.window.innerHeight);
|
|
743
|
+
// Guarded so the teardown's re-entrant paths (window close
|
|
744
|
+
// re-enters via the anchor's doRemoveGroup) never double-dispose.
|
|
745
|
+
let popoutGridviewDisposed = false;
|
|
746
|
+
const disposePopoutGridview = () => {
|
|
747
|
+
if (!popoutGridviewDisposed) {
|
|
748
|
+
popoutGridviewDisposed = true;
|
|
749
|
+
popoutGridview.dispose();
|
|
750
|
+
}
|
|
751
|
+
};
|
|
484
752
|
let floatingBox;
|
|
485
|
-
if (!(options === null || options === void 0 ? void 0 : options.overridePopoutGroup) &&
|
|
753
|
+
if (!(options === null || options === void 0 ? void 0 : options.overridePopoutGroup) &&
|
|
754
|
+
!(options === null || options === void 0 ? void 0 : options.overridePopoutGridview) &&
|
|
755
|
+
isGroupAddedToDom) {
|
|
486
756
|
if (itemToPopout instanceof DockviewPanel) {
|
|
487
757
|
this.movingLock(() => {
|
|
488
758
|
const panel = referenceGroup.model.removePanel(itemToPopout);
|
|
@@ -500,9 +770,9 @@ export class DockviewComponent extends BaseGrid {
|
|
|
500
770
|
break;
|
|
501
771
|
case 'floating':
|
|
502
772
|
case 'popout':
|
|
503
|
-
floatingBox = (
|
|
773
|
+
floatingBox = (_d = this.floatingGroups
|
|
504
774
|
.find((value) => value.group.api.id ===
|
|
505
|
-
itemToPopout.api.id)) === null ||
|
|
775
|
+
itemToPopout.api.id)) === null || _d === void 0 ? void 0 : _d.overlay.toJSON();
|
|
506
776
|
this.removeGroup(referenceGroup);
|
|
507
777
|
break;
|
|
508
778
|
}
|
|
@@ -511,7 +781,7 @@ export class DockviewComponent extends BaseGrid {
|
|
|
511
781
|
popoutContainer.classList.add('dv-dockview');
|
|
512
782
|
popoutContainer.style.overflow = 'hidden';
|
|
513
783
|
popoutContainer.appendChild(gready);
|
|
514
|
-
popoutContainer.appendChild(
|
|
784
|
+
popoutContainer.appendChild(popoutGridview.element);
|
|
515
785
|
const anchor = document.createElement('div');
|
|
516
786
|
const dropTargetContainer = new DropTargetAnchorContainer(anchor, { disabled: this.rootDropTargetContainer.disabled });
|
|
517
787
|
popoutContainer.appendChild(anchor);
|
|
@@ -522,20 +792,42 @@ export class DockviewComponent extends BaseGrid {
|
|
|
522
792
|
// their pointerdown/keydown listeners fire on the right
|
|
523
793
|
// window for outside-click and Escape dismissal.
|
|
524
794
|
const popoutPopupService = new PopupService(popoutContainer, _window.window);
|
|
525
|
-
|
|
795
|
+
service.setPopupService(group.id, popoutPopupService);
|
|
526
796
|
popoutWindowDisposable.addDisposables(popoutPopupService, Disposable.from(() => {
|
|
527
|
-
|
|
797
|
+
service.deletePopupService(group.id);
|
|
528
798
|
}));
|
|
529
799
|
group.model.location = {
|
|
530
800
|
type: 'popout',
|
|
531
801
|
getWindow: () => _window.window,
|
|
532
|
-
popoutUrl:
|
|
802
|
+
popoutUrl: resolvedPopoutUrl,
|
|
533
803
|
};
|
|
804
|
+
if (options === null || options === void 0 ? void 0 : options.overridePopoutGridview) {
|
|
805
|
+
// Restored multi-group window. Wire every member (including
|
|
806
|
+
// the anchor) to this window's containers and popout
|
|
807
|
+
// location now that the gridview is attached and laid out —
|
|
808
|
+
// re-setting renderContainer forces a re-render at the right
|
|
809
|
+
// time so 'always'-rendered content positions in this
|
|
810
|
+
// window rather than where it was first created.
|
|
811
|
+
const members = this.groups.filter((candidate) => popoutGridview.element.contains(candidate.element));
|
|
812
|
+
for (const member of members) {
|
|
813
|
+
member.model.renderContainer = overlayRenderContainer;
|
|
814
|
+
member.model.dropTargetContainer = dropTargetContainer;
|
|
815
|
+
member.model.location = {
|
|
816
|
+
type: 'popout',
|
|
817
|
+
getWindow: () => _window.window,
|
|
818
|
+
popoutUrl: resolvedPopoutUrl,
|
|
819
|
+
};
|
|
820
|
+
}
|
|
821
|
+
}
|
|
534
822
|
if (isGroupAddedToDom &&
|
|
535
823
|
itemToPopout.api.location.type === 'grid') {
|
|
536
824
|
itemToPopout.api.setVisible(false);
|
|
537
825
|
}
|
|
538
826
|
this.doSetGroupAndPanelActive(group);
|
|
827
|
+
const resizeObserverDisposable = service.observeGridviewSize(_window, popoutGridview, overlayRenderContainer);
|
|
828
|
+
if (resizeObserverDisposable) {
|
|
829
|
+
popoutWindowDisposable.addDisposables(resizeObserverDisposable);
|
|
830
|
+
}
|
|
539
831
|
popoutWindowDisposable.addDisposables(group.api.onDidActiveChange((event) => {
|
|
540
832
|
var _a;
|
|
541
833
|
if (event.isActive) {
|
|
@@ -545,20 +837,28 @@ export class DockviewComponent extends BaseGrid {
|
|
|
545
837
|
var _a;
|
|
546
838
|
(_a = _window.window) === null || _a === void 0 ? void 0 : _a.focus();
|
|
547
839
|
}));
|
|
548
|
-
|
|
840
|
+
// Holder so the close teardown (extracted below) can publish
|
|
841
|
+
// the group that was returned to the main grid back to the
|
|
842
|
+
// entry's `dispose()` contract.
|
|
843
|
+
const closeResult = {};
|
|
549
844
|
const isValidReferenceGroup = isGroupAddedToDom &&
|
|
550
845
|
referenceGroup &&
|
|
551
846
|
this.getPanel(referenceGroup.id);
|
|
552
847
|
const value = {
|
|
553
848
|
window: _window,
|
|
554
849
|
popoutGroup: group,
|
|
850
|
+
gridview: popoutGridview,
|
|
851
|
+
overlayRenderContainer,
|
|
852
|
+
dropTargetContainer,
|
|
853
|
+
getWindow: () => _window.window,
|
|
854
|
+
popoutUrl: resolvedPopoutUrl,
|
|
555
855
|
referenceGroup: isValidReferenceGroup
|
|
556
856
|
? referenceGroup.id
|
|
557
857
|
: undefined,
|
|
558
858
|
disposable: {
|
|
559
859
|
dispose: () => {
|
|
560
860
|
popoutWindowDisposable.dispose();
|
|
561
|
-
return returnedGroup;
|
|
861
|
+
return closeResult.returnedGroup;
|
|
562
862
|
},
|
|
563
863
|
},
|
|
564
864
|
};
|
|
@@ -575,73 +875,23 @@ export class DockviewComponent extends BaseGrid {
|
|
|
575
875
|
screenY: _window.window.screenX,
|
|
576
876
|
group,
|
|
577
877
|
});
|
|
578
|
-
}),
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
}));
|
|
596
|
-
if (!referenceGroup.api.isVisible) {
|
|
597
|
-
referenceGroup.api.setVisible(true);
|
|
598
|
-
}
|
|
599
|
-
if (this.getPanel(group.id)) {
|
|
600
|
-
this.doRemoveGroup(group, {
|
|
601
|
-
skipPopoutAssociated: true,
|
|
602
|
-
});
|
|
603
|
-
}
|
|
604
|
-
}
|
|
605
|
-
else if (this.getPanel(group.id)) {
|
|
606
|
-
group.model.renderContainer =
|
|
607
|
-
this.overlayRenderContainer;
|
|
608
|
-
group.model.dropTargetContainer =
|
|
609
|
-
this.rootDropTargetContainer;
|
|
610
|
-
returnedGroup = group;
|
|
611
|
-
const alreadyRemoved = !this._popoutGroups.find((p) => p.popoutGroup === group);
|
|
612
|
-
if (alreadyRemoved) {
|
|
613
|
-
/**
|
|
614
|
-
* If this popout group was explicitly removed then we shouldn't run the additional
|
|
615
|
-
* steps. To tell if the running of this disposable is the result of this popout group
|
|
616
|
-
* being explicitly removed we can check if this popout group is still referenced in
|
|
617
|
-
* the `this._popoutGroups` list.
|
|
618
|
-
*/
|
|
619
|
-
return;
|
|
620
|
-
}
|
|
621
|
-
if (floatingBox) {
|
|
622
|
-
this.addFloatingGroup(group, {
|
|
623
|
-
height: floatingBox.height,
|
|
624
|
-
width: floatingBox.width,
|
|
625
|
-
position: floatingBox,
|
|
626
|
-
});
|
|
627
|
-
}
|
|
628
|
-
else {
|
|
629
|
-
this.doRemoveGroup(group, {
|
|
630
|
-
skipDispose: true,
|
|
631
|
-
skipActive: true,
|
|
632
|
-
skipPopoutReturn: true,
|
|
633
|
-
});
|
|
634
|
-
group.model.location = { type: 'grid' };
|
|
635
|
-
this.movingLock(() => {
|
|
636
|
-
// suppress group add events since the group already exists
|
|
637
|
-
this.doAddGroup(group, [0]);
|
|
638
|
-
});
|
|
639
|
-
}
|
|
640
|
-
this.doSetGroupAndPanelActive(group);
|
|
641
|
-
}
|
|
642
|
-
}));
|
|
643
|
-
this._popoutGroups.push(value);
|
|
644
|
-
this.updateWatermark();
|
|
878
|
+
}), addDisposableListener(_window.window, 'resize', () => {
|
|
879
|
+
popoutGridview.layout(_window.window.innerWidth, _window.window.innerHeight);
|
|
880
|
+
}), overlayRenderContainer, Disposable.from(() => this.disposePopoutWindow({
|
|
881
|
+
group,
|
|
882
|
+
referenceGroup,
|
|
883
|
+
popoutGridview,
|
|
884
|
+
isGroupAddedToDom,
|
|
885
|
+
floatingBox,
|
|
886
|
+
disposePopoutGridview,
|
|
887
|
+
closeResult,
|
|
888
|
+
})));
|
|
889
|
+
service.add(value);
|
|
890
|
+
this._onDidAddPopoutGroup.fire({
|
|
891
|
+
id: value.popoutGroup.id,
|
|
892
|
+
group: value.popoutGroup,
|
|
893
|
+
window: value.getWindow(),
|
|
894
|
+
});
|
|
645
895
|
return true;
|
|
646
896
|
})
|
|
647
897
|
.catch((err) => {
|
|
@@ -649,8 +899,189 @@ export class DockviewComponent extends BaseGrid {
|
|
|
649
899
|
return false;
|
|
650
900
|
});
|
|
651
901
|
}
|
|
902
|
+
/**
|
|
903
|
+
* The popout window was blocked (e.g. by the browser's popup blocker —
|
|
904
|
+
* common when restoring popouts on load). Fall back gracefully so the
|
|
905
|
+
* group(s) end up valid and visible in the main grid rather than as
|
|
906
|
+
* orphans that later crash clear()/remove().
|
|
907
|
+
*/
|
|
908
|
+
handleBlockedPopout(params) {
|
|
909
|
+
const { group, referenceGroup, options, popoutWindowDisposable } = params;
|
|
910
|
+
console.error('dockview: failed to create popout. perhaps you need to allow pop-ups for this website');
|
|
911
|
+
popoutWindowDisposable.dispose();
|
|
912
|
+
this._onDidOpenPopoutWindowFail.fire();
|
|
913
|
+
if (options === null || options === void 0 ? void 0 : options.overridePopoutGridview) {
|
|
914
|
+
// Restoring a multi-group popout window: its nested gridview was
|
|
915
|
+
// built up-front but never attached to a window. Dock every member
|
|
916
|
+
// into the main grid so no group is lost, then discard the
|
|
917
|
+
// detached gridview.
|
|
918
|
+
const blockedGridview = options.overridePopoutGridview;
|
|
919
|
+
const members = this.groups.filter((candidate) => blockedGridview.element.contains(candidate.element));
|
|
920
|
+
for (const member of members) {
|
|
921
|
+
this.movingLock(() => {
|
|
922
|
+
blockedGridview.remove(member);
|
|
923
|
+
this.redockGroupToMainGrid(member);
|
|
924
|
+
});
|
|
925
|
+
}
|
|
926
|
+
blockedGridview.dispose();
|
|
927
|
+
if (referenceGroup && !referenceGroup.api.isVisible) {
|
|
928
|
+
referenceGroup.api.setVisible(true);
|
|
929
|
+
}
|
|
930
|
+
return;
|
|
931
|
+
}
|
|
932
|
+
if (group === referenceGroup) {
|
|
933
|
+
// No separate grid group to return to (e.g. restoring a popout
|
|
934
|
+
// straight from JSON) — dock this group into the main grid.
|
|
935
|
+
if (!this.gridview.element.contains(group.element)) {
|
|
936
|
+
this.movingLock(() => this.doAddGroup(group, [0]));
|
|
937
|
+
group.model.location = { type: 'grid' };
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
else {
|
|
941
|
+
// A fresh group was created for the popout — return its panels to
|
|
942
|
+
// the reference group and discard the now-empty popout group so it
|
|
943
|
+
// doesn't linger as an orphan.
|
|
944
|
+
this.movingLock(() => moveGroupWithoutDestroying({
|
|
945
|
+
from: group,
|
|
946
|
+
to: referenceGroup,
|
|
947
|
+
}));
|
|
948
|
+
if (group.model.size === 0 && this._groups.has(group.id)) {
|
|
949
|
+
group.dispose();
|
|
950
|
+
this._groups.delete(group.id);
|
|
951
|
+
this._onDidRemoveGroup.fire(group);
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
if (!referenceGroup.api.isVisible) {
|
|
955
|
+
referenceGroup.api.setVisible(true);
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
/**
|
|
959
|
+
* Wire a group that has been displaced from a floating / popout window back
|
|
960
|
+
* to the main grid's render & drop-target containers and dock it at the
|
|
961
|
+
* root. The caller is responsible for first detaching it from its old
|
|
962
|
+
* gridview — the detach strategy differs between the window-teardown path
|
|
963
|
+
* (`doRemoveGroup`) and the blocked-window path (`gridview.remove`).
|
|
964
|
+
*/
|
|
965
|
+
redockGroupToMainGrid(group) {
|
|
966
|
+
group.model.renderContainer = this.overlayRenderContainer;
|
|
967
|
+
group.model.dropTargetContainer = this.rootDropTargetContainer;
|
|
968
|
+
group.model.location = { type: 'grid' };
|
|
969
|
+
this.doAddGroup(group, [0]);
|
|
970
|
+
}
|
|
971
|
+
/**
|
|
972
|
+
* Teardown for a popout window's `popoutWindowDisposable`. Runs when the
|
|
973
|
+
* window closes (by user, by `removeGroup`, or by component disposal):
|
|
974
|
+
* relocates every member group back to the main grid (or to a floating
|
|
975
|
+
* window when the anchor came from one), then disposes the nested gridview.
|
|
976
|
+
* `closeResult.returnedGroup` is read by the entry's `dispose()` contract.
|
|
977
|
+
*/
|
|
978
|
+
disposePopoutWindow(params) {
|
|
979
|
+
var _a;
|
|
980
|
+
const { group, referenceGroup, popoutGridview, isGroupAddedToDom, floatingBox, disposePopoutGridview, closeResult, } = params;
|
|
981
|
+
if (this.isDisposed) {
|
|
982
|
+
// cleanup may run after instance is disposed; just tear down the
|
|
983
|
+
// nested gridview.
|
|
984
|
+
disposePopoutGridview();
|
|
985
|
+
return;
|
|
986
|
+
}
|
|
987
|
+
// Distinguish a genuine window close from an explicit `removeGroup`:
|
|
988
|
+
// the explicit-removal paths remove the service entry *before* this
|
|
989
|
+
// disposable runs. Key off the stable `popoutGridview` rather than the
|
|
990
|
+
// captured `group`, which may no longer be the window's anchor (it can
|
|
991
|
+
// have been dragged out, promoting another member to anchor).
|
|
992
|
+
const genuineClose = !!((_a = this._popoutWindowService) === null || _a === void 0 ? void 0 : _a.entries.find((entry) => entry.gridview === popoutGridview));
|
|
993
|
+
// The groups still living in this window, resolved from the gridview so
|
|
994
|
+
// a reassigned anchor doesn't hide surviving members.
|
|
995
|
+
const members = this.groups.filter((candidate) => popoutGridview.element.contains(candidate.element));
|
|
996
|
+
const anchorPresent = members.includes(group);
|
|
997
|
+
const anchorIsSoleMember = anchorPresent && members.length === 1;
|
|
998
|
+
// On a genuine close, relocate every member that ISN'T the captured
|
|
999
|
+
// anchor back to the main grid. The captured anchor (if still here) gets
|
|
1000
|
+
// the reference-return / re-float treatment below. Explicit removal
|
|
1001
|
+
// relocates via its own path, so the loop is skipped for it.
|
|
1002
|
+
if (genuineClose) {
|
|
1003
|
+
for (const member of members) {
|
|
1004
|
+
if (member === group) {
|
|
1005
|
+
continue;
|
|
1006
|
+
}
|
|
1007
|
+
this.movingLock(() => {
|
|
1008
|
+
this.doRemoveGroup(member, {
|
|
1009
|
+
skipDispose: true,
|
|
1010
|
+
skipActive: true,
|
|
1011
|
+
skipPopoutReturn: true,
|
|
1012
|
+
});
|
|
1013
|
+
this.redockGroupToMainGrid(member);
|
|
1014
|
+
});
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
if (anchorPresent &&
|
|
1018
|
+
isGroupAddedToDom &&
|
|
1019
|
+
this.getPanel(referenceGroup.id)) {
|
|
1020
|
+
this.movingLock(() => moveGroupWithoutDestroying({
|
|
1021
|
+
from: group,
|
|
1022
|
+
to: referenceGroup,
|
|
1023
|
+
}));
|
|
1024
|
+
if (!referenceGroup.api.isVisible) {
|
|
1025
|
+
referenceGroup.api.setVisible(true);
|
|
1026
|
+
}
|
|
1027
|
+
if (this.getPanel(group.id)) {
|
|
1028
|
+
this.doRemoveGroup(group, {
|
|
1029
|
+
skipPopoutAssociated: true,
|
|
1030
|
+
});
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
else if (anchorPresent && this.getPanel(group.id)) {
|
|
1034
|
+
group.model.renderContainer = this.overlayRenderContainer;
|
|
1035
|
+
group.model.dropTargetContainer = this.rootDropTargetContainer;
|
|
1036
|
+
closeResult.returnedGroup = group;
|
|
1037
|
+
if (!genuineClose) {
|
|
1038
|
+
/**
|
|
1039
|
+
* If this popout group was explicitly removed then we shouldn't run the additional
|
|
1040
|
+
* steps. The explicit remover re-docks the returned group itself; here we only hand
|
|
1041
|
+
* it back (above) and tear down the nested gridview.
|
|
1042
|
+
*/
|
|
1043
|
+
disposePopoutGridview();
|
|
1044
|
+
return;
|
|
1045
|
+
}
|
|
1046
|
+
// Re-float only restores the pre-popout state of a SINGLE popped-out
|
|
1047
|
+
// group. A multi-group window must not be split (anchor re-floats
|
|
1048
|
+
// while the rest dock to the grid), so dock the anchor to the grid
|
|
1049
|
+
// alongside the other members once they're no longer alone.
|
|
1050
|
+
if (floatingBox && anchorIsSoleMember) {
|
|
1051
|
+
this.addFloatingGroup(group, {
|
|
1052
|
+
height: floatingBox.height,
|
|
1053
|
+
width: floatingBox.width,
|
|
1054
|
+
position: floatingBox,
|
|
1055
|
+
});
|
|
1056
|
+
}
|
|
1057
|
+
else {
|
|
1058
|
+
this.doRemoveGroup(group, {
|
|
1059
|
+
skipDispose: true,
|
|
1060
|
+
skipActive: true,
|
|
1061
|
+
skipPopoutReturn: true,
|
|
1062
|
+
});
|
|
1063
|
+
group.model.location = { type: 'grid' };
|
|
1064
|
+
this.movingLock(() => {
|
|
1065
|
+
// suppress group add events since the group already exists
|
|
1066
|
+
this.doAddGroup(group, [0]);
|
|
1067
|
+
});
|
|
1068
|
+
}
|
|
1069
|
+
this.doSetGroupAndPanelActive(group);
|
|
1070
|
+
}
|
|
1071
|
+
// All members have been relocated out; tear down the window's nested
|
|
1072
|
+
// gridview (does not dispose the leaf views — their lifecycle stays
|
|
1073
|
+
// with `_groups`).
|
|
1074
|
+
disposePopoutGridview();
|
|
1075
|
+
}
|
|
652
1076
|
addFloatingGroup(item, options) {
|
|
653
|
-
|
|
1077
|
+
this.mutation('float', () => this._doAddFloatingGroup(item, options));
|
|
1078
|
+
}
|
|
1079
|
+
_doAddFloatingGroup(item, options) {
|
|
1080
|
+
var _a;
|
|
1081
|
+
const service = assertModule(this._floatingGroupService, 'FloatingGroup', 'api.addFloatingGroup');
|
|
1082
|
+
if (!service) {
|
|
1083
|
+
return;
|
|
1084
|
+
}
|
|
654
1085
|
if (item instanceof DockviewGroupPanel &&
|
|
655
1086
|
item.model.location.type === 'edge') {
|
|
656
1087
|
// edge groups are permanent structural elements and cannot be floated
|
|
@@ -669,7 +1100,7 @@ export class DockviewComponent extends BaseGrid {
|
|
|
669
1100
|
}
|
|
670
1101
|
else {
|
|
671
1102
|
group = item;
|
|
672
|
-
const popoutReferenceGroupId = (_a = this.
|
|
1103
|
+
const popoutReferenceGroupId = (_a = this._popoutWindowService) === null || _a === void 0 ? void 0 : _a.findReferenceGroupId(group);
|
|
673
1104
|
const popoutReferenceGroup = popoutReferenceGroupId
|
|
674
1105
|
? this.getPanel(popoutReferenceGroupId)
|
|
675
1106
|
: undefined;
|
|
@@ -750,65 +1181,87 @@ export class DockviewComponent extends BaseGrid {
|
|
|
750
1181
|
};
|
|
751
1182
|
}
|
|
752
1183
|
const anchoredBox = getAnchoredBox();
|
|
753
|
-
|
|
1184
|
+
// The floating window hosts its own gridview so it can grow into a
|
|
1185
|
+
// nested splitview layout. The window starts with the single anchor
|
|
1186
|
+
// group; further groups are added via drag-and-drop.
|
|
1187
|
+
const floatingGridview = this.createNestedGridview();
|
|
1188
|
+
floatingGridview.addView(group, Sizing.Distribute, [0]);
|
|
1189
|
+
this.mountFloatingWindow(floatingGridview, group, [group], anchoredBox, {
|
|
1190
|
+
dragHandle: options === null || options === void 0 ? void 0 : options.dragHandle,
|
|
1191
|
+
inDragMode: options === null || options === void 0 ? void 0 : options.inDragMode,
|
|
1192
|
+
skipActiveGroup: options === null || options === void 0 ? void 0 : options.skipActiveGroup,
|
|
1193
|
+
});
|
|
1194
|
+
}
|
|
1195
|
+
/**
|
|
1196
|
+
* Build an empty gridview configured to match the main grid's styling, for
|
|
1197
|
+
* hosting a nested layout inside a floating or popout window.
|
|
1198
|
+
*/
|
|
1199
|
+
createNestedGridview(orientation = Orientation.HORIZONTAL) {
|
|
1200
|
+
var _a, _b;
|
|
1201
|
+
return new Gridview(true, this.options.hideBorders
|
|
1202
|
+
? { separatorBorder: 'transparent' }
|
|
1203
|
+
: undefined, orientation, false, (_b = (_a = this.options.theme) === null || _a === void 0 ? void 0 : _a.gap) !== null && _b !== void 0 ? _b : 0);
|
|
1204
|
+
}
|
|
1205
|
+
/**
|
|
1206
|
+
* Wrap a (populated) floating gridview in an overlay window: title bar /
|
|
1207
|
+
* move handle, drag wiring, the floating-group service entry and the
|
|
1208
|
+
* `floating` location tag for every member group.
|
|
1209
|
+
*/
|
|
1210
|
+
mountFloatingWindow(floatingGridview, anchorGroup, members, anchoredBox, options) {
|
|
1211
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
1212
|
+
const service = assertModule(this._floatingGroupService, 'FloatingGroup', 'api.addFloatingGroup');
|
|
1213
|
+
if (!service) {
|
|
1214
|
+
return;
|
|
1215
|
+
}
|
|
1216
|
+
const dragHandleMode = (_b = (_a = options === null || options === void 0 ? void 0 : options.dragHandle) !== null && _a !== void 0 ? _a : this.options.floatingGroupDragHandle) !== null && _b !== void 0 ? _b : 'titlebar';
|
|
1217
|
+
// `'titlebar'` renders a dedicated grab bar above the tab bar and uses
|
|
1218
|
+
// it as the move handle; `'tabbar'` falls back to moving via the
|
|
1219
|
+
// tab-bar void container.
|
|
1220
|
+
const titleBar = dragHandleMode === 'titlebar'
|
|
1221
|
+
? new FloatingTitleBar(this, anchorGroup)
|
|
1222
|
+
: undefined;
|
|
1223
|
+
const overlay = new Overlay(Object.assign(Object.assign({ container: (_c = this._floatingOverlayHost) !== null && _c !== void 0 ? _c : this.gridview.element, content: floatingGridview.element, header: titleBar === null || titleBar === void 0 ? void 0 : titleBar.element }, anchoredBox), { minimumInViewportWidth: this.options.floatingGroupBounds === 'boundedWithinViewport'
|
|
754
1224
|
? undefined
|
|
755
|
-
: ((
|
|
1225
|
+
: ((_e = (_d = this.options.floatingGroupBounds) === null || _d === void 0 ? void 0 : _d.minimumWidthWithinViewport) !== null && _e !== void 0 ? _e : DEFAULT_FLOATING_GROUP_OVERFLOW_SIZE), minimumInViewportHeight: this.options.floatingGroupBounds === 'boundedWithinViewport'
|
|
756
1226
|
? undefined
|
|
757
|
-
: ((
|
|
758
|
-
|
|
759
|
-
|
|
1227
|
+
: ((_g = (_f = this.options.floatingGroupBounds) === null || _f === void 0 ? void 0 : _f.minimumHeightWithinViewport) !== null && _g !== void 0 ? _g : DEFAULT_FLOATING_GROUP_OVERFLOW_SIZE), transformDragPosition: this.options.transformFloatingGroupDrag
|
|
1228
|
+
? (context) => this.options.transformFloatingGroupDrag({
|
|
1229
|
+
group: anchorGroup,
|
|
1230
|
+
proposed: context.proposed,
|
|
1231
|
+
container: context.container,
|
|
1232
|
+
others: context.others,
|
|
1233
|
+
})
|
|
1234
|
+
: undefined, getSiblingBoxes: () => this._gatherFloatingGroupBoxes(anchorGroup) }));
|
|
1235
|
+
const dragHandle = (_h = titleBar === null || titleBar === void 0 ? void 0 : titleBar.element) !== null && _h !== void 0 ? _h : anchorGroup.element.querySelector('.dv-void-container');
|
|
1236
|
+
if (!dragHandle) {
|
|
760
1237
|
throw new Error('dockview: failed to find drag handle');
|
|
761
1238
|
}
|
|
762
|
-
overlay.setupDrag(
|
|
1239
|
+
overlay.setupDrag(dragHandle, {
|
|
763
1240
|
inDragMode: typeof (options === null || options === void 0 ? void 0 : options.inDragMode) === 'boolean'
|
|
764
1241
|
? options.inDragMode
|
|
765
1242
|
: false,
|
|
766
1243
|
});
|
|
767
|
-
const floatingGroupPanel =
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
})());
|
|
786
|
-
floatingGroupPanel.addDisposables(overlay.onDidChange(() => {
|
|
787
|
-
// this is either a resize or a move
|
|
788
|
-
// to inform the panels .layout(...) the group with it's current size
|
|
789
|
-
// don't care about resize since the above watcher handles that
|
|
790
|
-
group.layout(group.width, group.height);
|
|
791
|
-
}), overlay.onDidChangeEnd(() => {
|
|
792
|
-
this._bufferOnDidLayoutChange.fire();
|
|
793
|
-
}), group.onDidChange((event) => {
|
|
794
|
-
overlay.setBounds({
|
|
795
|
-
height: event === null || event === void 0 ? void 0 : event.height,
|
|
796
|
-
width: event === null || event === void 0 ? void 0 : event.width,
|
|
797
|
-
});
|
|
798
|
-
}), {
|
|
799
|
-
dispose: () => {
|
|
800
|
-
disposable.dispose();
|
|
801
|
-
remove(this._floatingGroups, floatingGroupPanel);
|
|
802
|
-
group.model.location = { type: 'grid' };
|
|
803
|
-
this.updateWatermark();
|
|
804
|
-
},
|
|
805
|
-
});
|
|
806
|
-
this._floatingGroups.push(floatingGroupPanel);
|
|
807
|
-
group.model.location = { type: 'floating' };
|
|
1244
|
+
const floatingGroupPanel = service.add(anchorGroup, overlay, floatingGridview);
|
|
1245
|
+
if (titleBar) {
|
|
1246
|
+
// Tie the title bar's lifetime to the floating window and surface
|
|
1247
|
+
// its redock drag through the same public `onWillDragGroup` event
|
|
1248
|
+
// the tab-bar handle uses. Register it so anchor reassignment (when
|
|
1249
|
+
// the original anchor leaves a multi-group window) retargets the
|
|
1250
|
+
// bar at a group that still lives here.
|
|
1251
|
+
floatingGroupPanel.setTitleBar(titleBar);
|
|
1252
|
+
floatingGroupPanel.addDisposables(titleBar, Disposable.from(() => floatingGroupPanel.setTitleBar(undefined)), titleBar.onDragStart((event) => {
|
|
1253
|
+
this._onWillDragGroup.fire({
|
|
1254
|
+
nativeEvent: event,
|
|
1255
|
+
group: floatingGroupPanel.group,
|
|
1256
|
+
});
|
|
1257
|
+
}));
|
|
1258
|
+
}
|
|
1259
|
+
for (const member of members) {
|
|
1260
|
+
member.model.location = { type: 'floating' };
|
|
1261
|
+
}
|
|
808
1262
|
if (!(options === null || options === void 0 ? void 0 : options.skipActiveGroup)) {
|
|
809
|
-
this.doSetGroupAndPanelActive(
|
|
1263
|
+
this.doSetGroupAndPanelActive(anchorGroup);
|
|
810
1264
|
}
|
|
811
|
-
this.updateWatermark();
|
|
812
1265
|
}
|
|
813
1266
|
orthogonalize(position, options) {
|
|
814
1267
|
this.gridview.normalize();
|
|
@@ -847,29 +1300,8 @@ export class DockviewComponent extends BaseGrid {
|
|
|
847
1300
|
updateOptions(options) {
|
|
848
1301
|
var _a, _b, _c, _d, _e;
|
|
849
1302
|
super.updateOptions(options);
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
switch (options.floatingGroupBounds) {
|
|
853
|
-
case 'boundedWithinViewport':
|
|
854
|
-
group.overlay.minimumInViewportHeight = undefined;
|
|
855
|
-
group.overlay.minimumInViewportWidth = undefined;
|
|
856
|
-
break;
|
|
857
|
-
case undefined:
|
|
858
|
-
group.overlay.minimumInViewportHeight =
|
|
859
|
-
DEFAULT_FLOATING_GROUP_OVERFLOW_SIZE;
|
|
860
|
-
group.overlay.minimumInViewportWidth =
|
|
861
|
-
DEFAULT_FLOATING_GROUP_OVERFLOW_SIZE;
|
|
862
|
-
break;
|
|
863
|
-
default:
|
|
864
|
-
group.overlay.minimumInViewportHeight =
|
|
865
|
-
(_a = options.floatingGroupBounds) === null || _a === void 0 ? void 0 : _a.minimumHeightWithinViewport;
|
|
866
|
-
group.overlay.minimumInViewportWidth =
|
|
867
|
-
(_b = options.floatingGroupBounds) === null || _b === void 0 ? void 0 : _b.minimumWidthWithinViewport;
|
|
868
|
-
}
|
|
869
|
-
group.overlay.setBounds();
|
|
870
|
-
}
|
|
871
|
-
}
|
|
872
|
-
this.updateDropTargetModel(options);
|
|
1303
|
+
(_a = this._floatingGroupService) === null || _a === void 0 ? void 0 : _a.updateBounds(options);
|
|
1304
|
+
(_b = this._rootDropTargetService) === null || _b === void 0 ? void 0 : _b.setOptions(options);
|
|
873
1305
|
const oldDisableDnd = this.options.disableDnd;
|
|
874
1306
|
const oldDndStrategy = this.options.dndStrategy;
|
|
875
1307
|
this._options = Object.assign(Object.assign({}, this.options), options);
|
|
@@ -885,17 +1317,10 @@ export class DockviewComponent extends BaseGrid {
|
|
|
885
1317
|
if ('createRightHeaderActionComponent' in options ||
|
|
886
1318
|
'createLeftHeaderActionComponent' in options ||
|
|
887
1319
|
'createPrefixHeaderActionComponent' in options) {
|
|
888
|
-
|
|
889
|
-
group.model.updateHeaderActions();
|
|
890
|
-
}
|
|
1320
|
+
(_c = this.headerActionsService) === null || _c === void 0 ? void 0 : _c.refreshAll();
|
|
891
1321
|
}
|
|
892
1322
|
if ('createWatermarkComponent' in options) {
|
|
893
|
-
|
|
894
|
-
this._watermark.element.parentElement.remove();
|
|
895
|
-
(_d = (_c = this._watermark).dispose) === null || _d === void 0 ? void 0 : _d.call(_c);
|
|
896
|
-
this._watermark = null;
|
|
897
|
-
}
|
|
898
|
-
this.updateWatermark();
|
|
1323
|
+
(_d = this._watermarkService) === null || _d === void 0 ? void 0 : _d.refresh();
|
|
899
1324
|
for (const group of this.groups) {
|
|
900
1325
|
group.model.refreshWatermark();
|
|
901
1326
|
}
|
|
@@ -912,6 +1337,7 @@ export class DockviewComponent extends BaseGrid {
|
|
|
912
1337
|
this._layoutFromShell(this.gridview.width, this.gridview.height);
|
|
913
1338
|
}
|
|
914
1339
|
layout(width, height, forceResize) {
|
|
1340
|
+
var _a, _b;
|
|
915
1341
|
if (this._shellManager && !this._inShellLayout) {
|
|
916
1342
|
this._shellManager.layout(width, height);
|
|
917
1343
|
}
|
|
@@ -919,12 +1345,9 @@ export class DockviewComponent extends BaseGrid {
|
|
|
919
1345
|
super.layout(width, height, forceResize);
|
|
920
1346
|
}
|
|
921
1347
|
this._syncFloatingOverlayHost();
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
floating.overlay.setBounds();
|
|
926
|
-
}
|
|
927
|
-
}
|
|
1348
|
+
// floatingGroupService may be undefined during super() (BaseGrid calls
|
|
1349
|
+
// layout(0, 0) before subclass field initialisers run).
|
|
1350
|
+
(_b = (_a = this._moduleRegistry) === null || _a === void 0 ? void 0 : _a.services.floatingGroupService) === null || _b === void 0 ? void 0 : _b.constrainBounds();
|
|
928
1351
|
}
|
|
929
1352
|
_syncFloatingOverlayHost() {
|
|
930
1353
|
if (!this._floatingOverlayHost || !this._shellManager) {
|
|
@@ -952,27 +1375,32 @@ export class DockviewComponent extends BaseGrid {
|
|
|
952
1375
|
}
|
|
953
1376
|
}
|
|
954
1377
|
addEdgeGroup(position, options) {
|
|
955
|
-
|
|
1378
|
+
const service = assertModule(this._edgeGroupService, 'EdgeGroup', 'api.addEdgeGroup');
|
|
1379
|
+
if (!service) {
|
|
1380
|
+
throw new Error(`dockview: EdgeGroup module is not registered`);
|
|
1381
|
+
}
|
|
1382
|
+
if (service.has(position)) {
|
|
956
1383
|
throw new Error(`dockview: edge group already exists at position '${position}'`);
|
|
957
1384
|
}
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
}
|
|
1385
|
+
return this.mutation('add', () => {
|
|
1386
|
+
const group = this.createGroup({ id: options.id });
|
|
1387
|
+
group.model.location = { type: 'edge', position };
|
|
1388
|
+
group.model.headerPosition = position;
|
|
1389
|
+
// Collapse when the group becomes empty
|
|
1390
|
+
const autoCollapseDisposable = group.model.onDidRemovePanel(() => {
|
|
1391
|
+
if (group.model.isEmpty) {
|
|
1392
|
+
this.setEdgeGroupCollapsed(group, true);
|
|
1393
|
+
}
|
|
1394
|
+
});
|
|
1395
|
+
service.add(position, group, autoCollapseDisposable);
|
|
1396
|
+
this._onDidAddGroup.fire(group);
|
|
1397
|
+
this._shellManager.addEdgeView(position, options, group);
|
|
1398
|
+
return group.api;
|
|
968
1399
|
});
|
|
969
|
-
this._edgeGroupDisposables.set(position, autoCollapseDisposable);
|
|
970
|
-
this._shellManager.addEdgeView(position, options, group);
|
|
971
|
-
return group.api;
|
|
972
1400
|
}
|
|
973
1401
|
getEdgeGroup(position) {
|
|
974
|
-
var _a;
|
|
975
|
-
return (_a = this.
|
|
1402
|
+
var _a, _b;
|
|
1403
|
+
return (_b = (_a = this._edgeGroupService) === null || _a === void 0 ? void 0 : _a.get(position)) === null || _b === void 0 ? void 0 : _b.api;
|
|
976
1404
|
}
|
|
977
1405
|
setEdgeGroupVisible(position, visible) {
|
|
978
1406
|
this._shellManager.setEdgeGroupVisible(position, visible);
|
|
@@ -981,54 +1409,54 @@ export class DockviewComponent extends BaseGrid {
|
|
|
981
1409
|
return this._shellManager.isEdgeGroupVisible(position);
|
|
982
1410
|
}
|
|
983
1411
|
removeEdgeGroup(position) {
|
|
984
|
-
|
|
985
|
-
|
|
1412
|
+
const service = assertModule(this._edgeGroupService, 'EdgeGroup', 'api.removeEdgeGroup');
|
|
1413
|
+
if (!service) {
|
|
1414
|
+
return;
|
|
1415
|
+
}
|
|
1416
|
+
const group = service.get(position);
|
|
986
1417
|
if (!group) {
|
|
987
1418
|
throw new Error(`dockview: no edge group exists at position '${position}'`);
|
|
988
1419
|
}
|
|
989
|
-
//
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
(_a = this._edgeGroupDisposables.get(position)) === null || _a === void 0 ? void 0 : _a.dispose();
|
|
998
|
-
this._edgeGroupDisposables.delete(position);
|
|
999
|
-
// Remove from the shell splitview
|
|
1000
|
-
this._shellManager.removeEdgeView(position);
|
|
1001
|
-
// Clean up group state
|
|
1002
|
-
this._edgeGroups.delete(position);
|
|
1003
|
-
group.dispose();
|
|
1004
|
-
this._groups.delete(group.id);
|
|
1005
|
-
this._onDidRemoveGroup.fire(group);
|
|
1006
|
-
}
|
|
1007
|
-
setEdgeGroupCollapsed(group, collapsed) {
|
|
1008
|
-
for (const [position, edgeGroup] of this._edgeGroups) {
|
|
1009
|
-
if (edgeGroup === group) {
|
|
1010
|
-
if (this._shellManager.isEdgeGroupCollapsed(position) ===
|
|
1011
|
-
collapsed) {
|
|
1012
|
-
// Skip the splitview resize on a no-op: with non-zero
|
|
1013
|
-
// theme gap, redundant resizeView calls accumulate
|
|
1014
|
-
// rounding drift that gradually shrinks the group.
|
|
1015
|
-
return;
|
|
1016
|
-
}
|
|
1017
|
-
this._shellManager.setEdgeGroupCollapsed(position, collapsed);
|
|
1018
|
-
edgeGroup.api._onDidCollapsedChange.fire({
|
|
1019
|
-
isCollapsed: collapsed,
|
|
1420
|
+
// One transaction — the per-panel removals below nest via the depth
|
|
1421
|
+
// counter, so consumers see a single edge-group removal.
|
|
1422
|
+
this.mutation('remove', () => {
|
|
1423
|
+
// Remove panels inside the group first
|
|
1424
|
+
for (const panel of [...group.panels]) {
|
|
1425
|
+
this.removePanel(panel, {
|
|
1426
|
+
removeEmptyGroup: false,
|
|
1427
|
+
skipDispose: false,
|
|
1020
1428
|
});
|
|
1021
|
-
return;
|
|
1022
1429
|
}
|
|
1430
|
+
// Remove from the shell splitview
|
|
1431
|
+
this._shellManager.removeEdgeView(position);
|
|
1432
|
+
// Clean up service-tracked state + group itself
|
|
1433
|
+
service.remove(position);
|
|
1434
|
+
group.dispose();
|
|
1435
|
+
this._groups.delete(group.id);
|
|
1436
|
+
this._onDidRemoveGroup.fire(group);
|
|
1437
|
+
});
|
|
1438
|
+
}
|
|
1439
|
+
setEdgeGroupCollapsed(group, collapsed) {
|
|
1440
|
+
var _a;
|
|
1441
|
+
const position = (_a = this._edgeGroupService) === null || _a === void 0 ? void 0 : _a.findPositionOf(group);
|
|
1442
|
+
if (!position) {
|
|
1443
|
+
return;
|
|
1444
|
+
}
|
|
1445
|
+
if (this._shellManager.isEdgeGroupCollapsed(position) === collapsed) {
|
|
1446
|
+
// Skip the splitview resize on a no-op: with non-zero theme gap,
|
|
1447
|
+
// redundant resizeView calls accumulate rounding drift that
|
|
1448
|
+
// gradually shrinks the group.
|
|
1449
|
+
return;
|
|
1023
1450
|
}
|
|
1451
|
+
this._shellManager.setEdgeGroupCollapsed(position, collapsed);
|
|
1452
|
+
group.api._onDidCollapsedChange.fire({ isCollapsed: collapsed });
|
|
1024
1453
|
}
|
|
1025
1454
|
isEdgeGroupCollapsed(group) {
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
return false;
|
|
1455
|
+
var _a;
|
|
1456
|
+
const position = (_a = this._edgeGroupService) === null || _a === void 0 ? void 0 : _a.findPositionOf(group);
|
|
1457
|
+
return position
|
|
1458
|
+
? this._shellManager.isEdgeGroupCollapsed(position)
|
|
1459
|
+
: false;
|
|
1032
1460
|
}
|
|
1033
1461
|
updateDragAndDropState() {
|
|
1034
1462
|
// Update draggable state for all tabs and void containers
|
|
@@ -1092,32 +1520,18 @@ export class DockviewComponent extends BaseGrid {
|
|
|
1092
1520
|
* @returns A JSON respresentation of the layout
|
|
1093
1521
|
*/
|
|
1094
1522
|
toJSON() {
|
|
1095
|
-
var _a;
|
|
1523
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
1096
1524
|
const data = this.gridview.serialize();
|
|
1097
1525
|
const panels = this.panels.reduce((collection, panel) => {
|
|
1098
1526
|
collection[panel.id] = panel.toJSON();
|
|
1099
1527
|
return collection;
|
|
1100
1528
|
}, {});
|
|
1101
|
-
const floats = this.
|
|
1102
|
-
|
|
1103
|
-
data: group.group.toJSON(),
|
|
1104
|
-
position: group.overlay.toJSON(),
|
|
1105
|
-
};
|
|
1106
|
-
});
|
|
1107
|
-
const popoutGroups = this._popoutGroups.map((group) => {
|
|
1108
|
-
return {
|
|
1109
|
-
data: group.popoutGroup.toJSON(),
|
|
1110
|
-
gridReferenceGroup: group.referenceGroup,
|
|
1111
|
-
position: group.window.dimensions(),
|
|
1112
|
-
url: group.popoutGroup.api.location.type === 'popout'
|
|
1113
|
-
? group.popoutGroup.api.location.popoutUrl
|
|
1114
|
-
: undefined,
|
|
1115
|
-
};
|
|
1116
|
-
});
|
|
1529
|
+
const floats = (_b = (_a = this._floatingGroupService) === null || _a === void 0 ? void 0 : _a.serialize()) !== null && _b !== void 0 ? _b : [];
|
|
1530
|
+
const popoutGroups = (_d = (_c = this._popoutWindowService) === null || _c === void 0 ? void 0 : _c.serialize()) !== null && _d !== void 0 ? _d : [];
|
|
1117
1531
|
const result = {
|
|
1118
1532
|
grid: data,
|
|
1119
1533
|
panels,
|
|
1120
|
-
activeGroup: (
|
|
1534
|
+
activeGroup: (_e = this.activeGroup) === null || _e === void 0 ? void 0 : _e.id,
|
|
1121
1535
|
};
|
|
1122
1536
|
if (floats.length > 0) {
|
|
1123
1537
|
result.floatingGroups = floats;
|
|
@@ -1125,10 +1539,11 @@ export class DockviewComponent extends BaseGrid {
|
|
|
1125
1539
|
if (popoutGroups.length > 0) {
|
|
1126
1540
|
result.popoutGroups = popoutGroups;
|
|
1127
1541
|
}
|
|
1128
|
-
|
|
1542
|
+
const edgeEntries = (_g = (_f = this._edgeGroupService) === null || _f === void 0 ? void 0 : _f.entries()) !== null && _g !== void 0 ? _g : [];
|
|
1543
|
+
if ((_h = this._edgeGroupService) === null || _h === void 0 ? void 0 : _h.hasAny()) {
|
|
1129
1544
|
const shellSerialized = this._shellManager.toJSON();
|
|
1130
1545
|
// Augment each entry with the serialized group state
|
|
1131
|
-
for (const [position, group] of
|
|
1546
|
+
for (const [position, group] of edgeEntries) {
|
|
1132
1547
|
const entry = shellSerialized[position];
|
|
1133
1548
|
if (entry) {
|
|
1134
1549
|
entry.group = group.toJSON();
|
|
@@ -1139,17 +1554,19 @@ export class DockviewComponent extends BaseGrid {
|
|
|
1139
1554
|
return result;
|
|
1140
1555
|
}
|
|
1141
1556
|
fromJSON(data, options) {
|
|
1142
|
-
|
|
1557
|
+
// One 'load' transaction for the whole deserialization — the many
|
|
1558
|
+
// nested add/remove mutations join it via the depth counter.
|
|
1559
|
+
this.mutation('load', () => this._doFromJSON(data, options));
|
|
1560
|
+
}
|
|
1561
|
+
_doFromJSON(data, options) {
|
|
1562
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
1143
1563
|
// Cancel any popout-restoration timers queued by a previous fromJSON
|
|
1144
|
-
// that haven't fired yet.
|
|
1145
|
-
//
|
|
1146
|
-
//
|
|
1147
|
-
//
|
|
1148
|
-
//
|
|
1149
|
-
|
|
1150
|
-
cleanup();
|
|
1151
|
-
}
|
|
1152
|
-
this._popoutRestorationCleanups.clear();
|
|
1564
|
+
// that haven't fired yet. The cancel path also disposes orphan groups
|
|
1565
|
+
// registered in _groups synchronously but never parented into a popout
|
|
1566
|
+
// window — otherwise the upcoming clear() would call gridview.remove()
|
|
1567
|
+
// on an unparented element and throw "Invalid grid element". See
|
|
1568
|
+
// issue #1304.
|
|
1569
|
+
(_a = this._popoutWindowService) === null || _a === void 0 ? void 0 : _a.cancelPendingRestorations();
|
|
1153
1570
|
const existingPanels = new Map();
|
|
1154
1571
|
let tempGroup;
|
|
1155
1572
|
if (options === null || options === void 0 ? void 0 : options.reuseExistingPanels) {
|
|
@@ -1198,7 +1615,7 @@ export class DockviewComponent extends BaseGrid {
|
|
|
1198
1615
|
const createGroupFromSerializedState = (data) => {
|
|
1199
1616
|
const { id, locked, hideHeader, headerPosition, views, activeView, } = data;
|
|
1200
1617
|
if (typeof id !== 'string') {
|
|
1201
|
-
throw new
|
|
1618
|
+
throw new TypeError('dockview: group id must be of type string');
|
|
1202
1619
|
}
|
|
1203
1620
|
const group = this.createGroup({
|
|
1204
1621
|
id,
|
|
@@ -1266,138 +1683,23 @@ export class DockviewComponent extends BaseGrid {
|
|
|
1266
1683
|
});
|
|
1267
1684
|
this._layoutFromShell(width, height);
|
|
1268
1685
|
if (data.edgeGroups) {
|
|
1269
|
-
|
|
1270
|
-
// that don't already have a group registered (e.g. when fromJSON
|
|
1271
|
-
// is called before the user has called addEdgeGroup).
|
|
1272
|
-
for (const _position of [
|
|
1273
|
-
'top',
|
|
1274
|
-
'bottom',
|
|
1275
|
-
'left',
|
|
1276
|
-
'right',
|
|
1277
|
-
]) {
|
|
1278
|
-
const fixedData = data.edgeGroups[_position];
|
|
1279
|
-
if (fixedData && !this._edgeGroups.has(_position)) {
|
|
1280
|
-
const groupState = fixedData.group;
|
|
1281
|
-
const id = (_a = groupState === null || groupState === void 0 ? void 0 : groupState.id) !== null && _a !== void 0 ? _a : `${_position}-group`;
|
|
1282
|
-
this.addEdgeGroup(_position, { id });
|
|
1283
|
-
}
|
|
1284
|
-
}
|
|
1285
|
-
// Restore panel contents of edge groups
|
|
1286
|
-
for (const [position, edgeGroup] of this._edgeGroups) {
|
|
1287
|
-
const edgeData = data.edgeGroups[position];
|
|
1288
|
-
const groupState = edgeData === null || edgeData === void 0 ? void 0 : edgeData.group;
|
|
1289
|
-
if (groupState) {
|
|
1290
|
-
const { views, activeView } = groupState;
|
|
1291
|
-
const createdPanels = [];
|
|
1292
|
-
for (const panelId of views) {
|
|
1293
|
-
if (panels[panelId]) {
|
|
1294
|
-
const panel = this._deserializer.fromJSON(panels[panelId], edgeGroup);
|
|
1295
|
-
createdPanels.push(panel);
|
|
1296
|
-
}
|
|
1297
|
-
}
|
|
1298
|
-
for (let i = 0; i < createdPanels.length; i++) {
|
|
1299
|
-
const panel = createdPanels[i];
|
|
1300
|
-
const isActive = activeView === panel.id;
|
|
1301
|
-
edgeGroup.model.openPanel(panel, {
|
|
1302
|
-
skipSetActive: !isActive,
|
|
1303
|
-
skipSetGroupActive: true,
|
|
1304
|
-
});
|
|
1305
|
-
}
|
|
1306
|
-
// Restore tab groups before activating a fallback panel
|
|
1307
|
-
if (groupState.tabGroups &&
|
|
1308
|
-
groupState.tabGroups.length > 0) {
|
|
1309
|
-
edgeGroup.model.restoreTabGroups(groupState.tabGroups);
|
|
1310
|
-
}
|
|
1311
|
-
if (!edgeGroup.activePanel &&
|
|
1312
|
-
edgeGroup.panels.length > 0) {
|
|
1313
|
-
edgeGroup.model.openPanel(edgeGroup.panels[edgeGroup.panels.length - 1], { skipSetGroupActive: true });
|
|
1314
|
-
}
|
|
1315
|
-
}
|
|
1316
|
-
}
|
|
1317
|
-
this._shellManager.fromJSON(data.edgeGroups);
|
|
1318
|
-
}
|
|
1319
|
-
const serializedFloatingGroups = (_b = data.floatingGroups) !== null && _b !== void 0 ? _b : [];
|
|
1320
|
-
for (const serializedFloatingGroup of serializedFloatingGroups) {
|
|
1321
|
-
const { data, position } = serializedFloatingGroup;
|
|
1322
|
-
const group = createGroupFromSerializedState(data);
|
|
1323
|
-
this.addFloatingGroup(group, {
|
|
1324
|
-
position: position,
|
|
1325
|
-
width: position.width,
|
|
1326
|
-
height: position.height,
|
|
1327
|
-
skipRemoveGroup: true,
|
|
1328
|
-
inDragMode: false,
|
|
1329
|
-
});
|
|
1330
|
-
}
|
|
1331
|
-
const serializedPopoutGroups = (_c = data.popoutGroups) !== null && _c !== void 0 ? _c : [];
|
|
1332
|
-
// Create a promise that resolves when all popout groups are created
|
|
1333
|
-
const popoutPromises = [];
|
|
1334
|
-
// Queue popup group creation with delays to avoid browser blocking
|
|
1335
|
-
serializedPopoutGroups.forEach((serializedPopoutGroup, index) => {
|
|
1336
|
-
const { data, position, gridReferenceGroup, url } = serializedPopoutGroup;
|
|
1337
|
-
const group = createGroupFromSerializedState(data);
|
|
1338
|
-
// Add a small delay for each popup after the first to avoid browser popup blocking
|
|
1339
|
-
const popoutPromise = new Promise((resolve) => {
|
|
1340
|
-
const cleanup = () => {
|
|
1341
|
-
this._popoutRestorationCleanups.delete(cleanup);
|
|
1342
|
-
clearTimeout(handle);
|
|
1343
|
-
// The group was registered in _groups synchronously
|
|
1344
|
-
// but the timer that would parent it into the popout
|
|
1345
|
-
// window never ran. Dispose the orphan here so the
|
|
1346
|
-
// next clear() doesn't trip over an unparented
|
|
1347
|
-
// element. See issue #1304.
|
|
1348
|
-
if (!this.isDisposed &&
|
|
1349
|
-
this._groups.has(group.id) &&
|
|
1350
|
-
group.element.parentElement === null) {
|
|
1351
|
-
for (const panel of [...group.panels]) {
|
|
1352
|
-
this.removePanel(panel, {
|
|
1353
|
-
removeEmptyGroup: false,
|
|
1354
|
-
});
|
|
1355
|
-
}
|
|
1356
|
-
group.dispose();
|
|
1357
|
-
this._groups.delete(group.id);
|
|
1358
|
-
this._onDidRemoveGroup.fire(group);
|
|
1359
|
-
}
|
|
1360
|
-
resolve();
|
|
1361
|
-
};
|
|
1362
|
-
const handle = setTimeout(() => {
|
|
1363
|
-
this._popoutRestorationCleanups.delete(cleanup);
|
|
1364
|
-
// Guard against the component being disposed before
|
|
1365
|
-
// this timer fires. Under React StrictMode the
|
|
1366
|
-
// component is mounted -> disposed -> remounted, and
|
|
1367
|
-
// without this guard the first instance's queued
|
|
1368
|
-
// restoration would open a second popout window.
|
|
1369
|
-
// See issue #851.
|
|
1370
|
-
if (this.isDisposed) {
|
|
1371
|
-
resolve();
|
|
1372
|
-
return;
|
|
1373
|
-
}
|
|
1374
|
-
this.addPopoutGroup(group, {
|
|
1375
|
-
position: position !== null && position !== void 0 ? position : undefined,
|
|
1376
|
-
overridePopoutGroup: gridReferenceGroup
|
|
1377
|
-
? group
|
|
1378
|
-
: undefined,
|
|
1379
|
-
referenceGroup: gridReferenceGroup
|
|
1380
|
-
? this.getPanel(gridReferenceGroup)
|
|
1381
|
-
: undefined,
|
|
1382
|
-
popoutUrl: url,
|
|
1383
|
-
});
|
|
1384
|
-
resolve();
|
|
1385
|
-
}, index * DESERIALIZATION_POPOUT_DELAY_MS); // 100ms delay between each popup
|
|
1386
|
-
this._popoutRestorationCleanups.add(cleanup);
|
|
1387
|
-
});
|
|
1388
|
-
popoutPromises.push(popoutPromise);
|
|
1389
|
-
});
|
|
1390
|
-
// Store the promise for tests to wait on
|
|
1391
|
-
this._popoutRestorationPromise = Promise.all(popoutPromises).then(() => void 0);
|
|
1392
|
-
for (const floatingGroup of this._floatingGroups) {
|
|
1393
|
-
floatingGroup.overlay.setBounds();
|
|
1686
|
+
this.deserializeEdgeGroups(data.edgeGroups, panels);
|
|
1394
1687
|
}
|
|
1688
|
+
this.deserializeFloatingWindows((_b = data.floatingGroups) !== null && _b !== void 0 ? _b : [], createGroupFromSerializedState);
|
|
1689
|
+
const popoutPromises = this.deserializePopoutWindows((_c = data.popoutGroups) !== null && _c !== void 0 ? _c : [], createGroupFromSerializedState);
|
|
1690
|
+
(_d = this._popoutWindowService) === null || _d === void 0 ? void 0 : _d.finishRestoration(popoutPromises);
|
|
1691
|
+
(_e = this._floatingGroupService) === null || _e === void 0 ? void 0 : _e.constrainBounds();
|
|
1395
1692
|
if (typeof activeGroup === 'string') {
|
|
1396
1693
|
const panel = this.getPanel(activeGroup);
|
|
1397
1694
|
if (panel) {
|
|
1398
1695
|
this.doSetGroupAndPanelActive(panel);
|
|
1399
1696
|
}
|
|
1400
1697
|
}
|
|
1698
|
+
// `gridview.deserialize()` rebuilds the grid without firing the
|
|
1699
|
+
// BaseGrid add events the watermark module reacts to, so the
|
|
1700
|
+
// watermark mounted during `clear()` would otherwise persist over
|
|
1701
|
+
// the restored layout. Re-evaluate now the layout is in place.
|
|
1702
|
+
(_f = this._watermarkService) === null || _f === void 0 ? void 0 : _f.update();
|
|
1401
1703
|
}
|
|
1402
1704
|
catch (err) {
|
|
1403
1705
|
console.error('dockview: failed to deserialize layout. Reverting changes', err);
|
|
@@ -1421,10 +1723,7 @@ export class DockviewComponent extends BaseGrid {
|
|
|
1421
1723
|
this._groups.delete(group.id);
|
|
1422
1724
|
this._onDidRemoveGroup.fire(group);
|
|
1423
1725
|
}
|
|
1424
|
-
|
|
1425
|
-
for (const floatingGroup of [...this._floatingGroups]) {
|
|
1426
|
-
floatingGroup.dispose();
|
|
1427
|
-
}
|
|
1726
|
+
(_g = this._floatingGroupService) === null || _g === void 0 ? void 0 : _g.disposeAll();
|
|
1428
1727
|
// fires clean-up events and clears the underlying HTML gridview.
|
|
1429
1728
|
this.clear();
|
|
1430
1729
|
/**
|
|
@@ -1434,16 +1733,178 @@ export class DockviewComponent extends BaseGrid {
|
|
|
1434
1733
|
*/
|
|
1435
1734
|
throw err;
|
|
1436
1735
|
}
|
|
1437
|
-
this.updateWatermark();
|
|
1438
1736
|
// Force position updates for always visible panels after DOM layout is complete
|
|
1439
1737
|
this.debouncedUpdateAllPositions();
|
|
1440
1738
|
this._onDidLayoutFromJSON.fire();
|
|
1441
1739
|
}
|
|
1740
|
+
/**
|
|
1741
|
+
* Rebuild a floating / popout window's nested gridview from its serialized
|
|
1742
|
+
* tree, collecting the member groups (in deserialization order) so the
|
|
1743
|
+
* caller can mount or restore the window.
|
|
1744
|
+
*/
|
|
1745
|
+
deserializeNestedGridview(grid, createGroup) {
|
|
1746
|
+
const gridview = this.createNestedGridview(grid.orientation);
|
|
1747
|
+
const members = [];
|
|
1748
|
+
gridview.deserialize(grid, {
|
|
1749
|
+
fromJSON: (node) => {
|
|
1750
|
+
const group = createGroup(node.data);
|
|
1751
|
+
members.push(group);
|
|
1752
|
+
return group;
|
|
1753
|
+
},
|
|
1754
|
+
});
|
|
1755
|
+
return { gridview, members };
|
|
1756
|
+
}
|
|
1757
|
+
deserializeEdgeGroups(edgeGroups, panels) {
|
|
1758
|
+
var _a;
|
|
1759
|
+
const edgeService = assertModule(this._edgeGroupService, 'EdgeGroup', 'fromJSON edge restoration');
|
|
1760
|
+
if (!edgeService) {
|
|
1761
|
+
return;
|
|
1762
|
+
}
|
|
1763
|
+
// Auto-create edge groups for positions in the serialized state that
|
|
1764
|
+
// don't already have a group registered (e.g. when fromJSON is called
|
|
1765
|
+
// before the user has called addEdgeGroup).
|
|
1766
|
+
for (const _position of [
|
|
1767
|
+
'top',
|
|
1768
|
+
'bottom',
|
|
1769
|
+
'left',
|
|
1770
|
+
'right',
|
|
1771
|
+
]) {
|
|
1772
|
+
const fixedData = edgeGroups[_position];
|
|
1773
|
+
if (fixedData && !edgeService.has(_position)) {
|
|
1774
|
+
const groupState = fixedData.group;
|
|
1775
|
+
const id = (_a = groupState === null || groupState === void 0 ? void 0 : groupState.id) !== null && _a !== void 0 ? _a : `${_position}-group`;
|
|
1776
|
+
this.addEdgeGroup(_position, { id });
|
|
1777
|
+
}
|
|
1778
|
+
}
|
|
1779
|
+
// Restore panel contents of edge groups
|
|
1780
|
+
for (const [position, edgeGroup] of edgeService.entries()) {
|
|
1781
|
+
const edgeData = edgeGroups[position];
|
|
1782
|
+
const groupState = edgeData === null || edgeData === void 0 ? void 0 : edgeData.group;
|
|
1783
|
+
if (groupState) {
|
|
1784
|
+
const { views, activeView } = groupState;
|
|
1785
|
+
const createdPanels = [];
|
|
1786
|
+
for (const panelId of views) {
|
|
1787
|
+
if (panels[panelId]) {
|
|
1788
|
+
const panel = this._deserializer.fromJSON(panels[panelId], edgeGroup);
|
|
1789
|
+
createdPanels.push(panel);
|
|
1790
|
+
}
|
|
1791
|
+
}
|
|
1792
|
+
for (const panel of createdPanels) {
|
|
1793
|
+
const isActive = activeView === panel.id;
|
|
1794
|
+
edgeGroup.model.openPanel(panel, {
|
|
1795
|
+
skipSetActive: !isActive,
|
|
1796
|
+
skipSetGroupActive: true,
|
|
1797
|
+
});
|
|
1798
|
+
}
|
|
1799
|
+
// Restore tab groups before activating a fallback panel
|
|
1800
|
+
if (groupState.tabGroups && groupState.tabGroups.length > 0) {
|
|
1801
|
+
edgeGroup.model.restoreTabGroups(groupState.tabGroups);
|
|
1802
|
+
}
|
|
1803
|
+
if (!edgeGroup.activePanel && edgeGroup.panels.length > 0) {
|
|
1804
|
+
edgeGroup.model.openPanel(edgeGroup.panels[edgeGroup.panels.length - 1], { skipSetGroupActive: true });
|
|
1805
|
+
}
|
|
1806
|
+
}
|
|
1807
|
+
}
|
|
1808
|
+
this._shellManager.fromJSON(edgeGroups);
|
|
1809
|
+
}
|
|
1810
|
+
deserializeFloatingWindows(serialized, createGroup) {
|
|
1811
|
+
for (const serializedFloatingGroup of serialized) {
|
|
1812
|
+
const { data, grid, position } = serializedFloatingGroup;
|
|
1813
|
+
if (grid) {
|
|
1814
|
+
// Multi-group window: rebuild the window's nested gridview from
|
|
1815
|
+
// its serialized tree.
|
|
1816
|
+
const { gridview: floatingGridview, members } = this.deserializeNestedGridview(grid, createGroup);
|
|
1817
|
+
if (members.length === 0) {
|
|
1818
|
+
continue;
|
|
1819
|
+
}
|
|
1820
|
+
this.mountFloatingWindow(floatingGridview, members[0], members, position, { inDragMode: false });
|
|
1821
|
+
}
|
|
1822
|
+
else if (data) {
|
|
1823
|
+
const group = createGroup(data);
|
|
1824
|
+
this.addFloatingGroup(group, {
|
|
1825
|
+
position: position,
|
|
1826
|
+
width: position.width,
|
|
1827
|
+
height: position.height,
|
|
1828
|
+
skipRemoveGroup: true,
|
|
1829
|
+
inDragMode: false,
|
|
1830
|
+
});
|
|
1831
|
+
}
|
|
1832
|
+
}
|
|
1833
|
+
}
|
|
1834
|
+
deserializePopoutWindows(serialized, createGroup) {
|
|
1835
|
+
const popoutService = serialized.length > 0
|
|
1836
|
+
? assertModule(this._popoutWindowService, 'PopoutWindow', 'fromJSON popout restoration')
|
|
1837
|
+
: this._popoutWindowService;
|
|
1838
|
+
if (!popoutService) {
|
|
1839
|
+
return [];
|
|
1840
|
+
}
|
|
1841
|
+
// Queue popup group creation with delays to avoid browser blocking
|
|
1842
|
+
return serialized.flatMap((serializedPopoutGroup, index) => {
|
|
1843
|
+
const { data, grid, position, gridReferenceGroup, url } = serializedPopoutGroup;
|
|
1844
|
+
// Multi-group popout windows rebuild their nested gridview from the
|
|
1845
|
+
// serialized tree; single-group windows use the legacy single-group
|
|
1846
|
+
// path.
|
|
1847
|
+
let overridePopoutGridview;
|
|
1848
|
+
let members = [];
|
|
1849
|
+
if (grid) {
|
|
1850
|
+
const built = this.deserializeNestedGridview(grid, createGroup);
|
|
1851
|
+
overridePopoutGridview = built.gridview;
|
|
1852
|
+
members = built.members;
|
|
1853
|
+
if (members.length === 0) {
|
|
1854
|
+
// A serialized window with no groups: nothing to restore.
|
|
1855
|
+
// Mirror the floating path's guard and discard the empty
|
|
1856
|
+
// gridview rather than passing an undefined anchor to
|
|
1857
|
+
// addPopoutGroup.
|
|
1858
|
+
overridePopoutGridview.dispose();
|
|
1859
|
+
return [];
|
|
1860
|
+
}
|
|
1861
|
+
}
|
|
1862
|
+
const group = grid ? members[0] : createGroup(data);
|
|
1863
|
+
return popoutService.scheduleRestoration(index * DESERIALIZATION_POPOUT_DELAY_MS, () => {
|
|
1864
|
+
this.addPopoutGroup(group, {
|
|
1865
|
+
position: position !== null && position !== void 0 ? position : undefined,
|
|
1866
|
+
overridePopoutGroup: gridReferenceGroup
|
|
1867
|
+
? group
|
|
1868
|
+
: undefined,
|
|
1869
|
+
overridePopoutGridview,
|
|
1870
|
+
referenceGroup: gridReferenceGroup
|
|
1871
|
+
? this.getPanel(gridReferenceGroup)
|
|
1872
|
+
: undefined,
|
|
1873
|
+
popoutUrl: url,
|
|
1874
|
+
});
|
|
1875
|
+
}, () => {
|
|
1876
|
+
// The group was registered in _groups synchronously but the
|
|
1877
|
+
// timer that would parent it into the popout window never
|
|
1878
|
+
// ran. Dispose the orphan here so the next clear() doesn't
|
|
1879
|
+
// trip over an unparented element. See issue #1304.
|
|
1880
|
+
for (const orphan of members.length > 0
|
|
1881
|
+
? members
|
|
1882
|
+
: [group]) {
|
|
1883
|
+
if (!this.isDisposed &&
|
|
1884
|
+
this._groups.has(orphan.id) &&
|
|
1885
|
+
orphan.element.parentElement === null) {
|
|
1886
|
+
for (const panel of [...orphan.panels]) {
|
|
1887
|
+
this.removePanel(panel, {
|
|
1888
|
+
removeEmptyGroup: false,
|
|
1889
|
+
});
|
|
1890
|
+
}
|
|
1891
|
+
orphan.dispose();
|
|
1892
|
+
this._groups.delete(orphan.id);
|
|
1893
|
+
this._onDidRemoveGroup.fire(orphan);
|
|
1894
|
+
}
|
|
1895
|
+
}
|
|
1896
|
+
});
|
|
1897
|
+
});
|
|
1898
|
+
}
|
|
1442
1899
|
clear() {
|
|
1900
|
+
this.mutation('clear', () => this._doClear());
|
|
1901
|
+
}
|
|
1902
|
+
_doClear() {
|
|
1903
|
+
var _a;
|
|
1443
1904
|
const groups = Array.from(this._groups.values()).map((_) => _.value);
|
|
1444
1905
|
const hasActiveGroup = !!this.activeGroup;
|
|
1445
1906
|
for (const group of groups) {
|
|
1446
|
-
if (
|
|
1907
|
+
if ((_a = this._edgeGroupService) === null || _a === void 0 ? void 0 : _a.includes(group)) {
|
|
1447
1908
|
// Edge groups are structural - only clear their panels, not the group itself
|
|
1448
1909
|
const panels = [...group.panels];
|
|
1449
1910
|
for (const panel of panels) {
|
|
@@ -1460,14 +1921,21 @@ export class DockviewComponent extends BaseGrid {
|
|
|
1460
1921
|
this.gridview.clear();
|
|
1461
1922
|
}
|
|
1462
1923
|
closeAllGroups() {
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1924
|
+
// One transaction — the per-panel removals inside nest via the depth
|
|
1925
|
+
// counter, so consumers (undo, announcements) see a single mutation.
|
|
1926
|
+
this.mutation('remove', () => {
|
|
1927
|
+
for (const entry of this._groups.entries()) {
|
|
1928
|
+
const [_, group] = entry;
|
|
1929
|
+
group.value.model.closeAllPanels();
|
|
1930
|
+
}
|
|
1931
|
+
});
|
|
1467
1932
|
}
|
|
1468
1933
|
addPanel(options) {
|
|
1469
|
-
|
|
1470
|
-
|
|
1934
|
+
return this.mutation('add', () => this._doAddPanel(options));
|
|
1935
|
+
}
|
|
1936
|
+
_doAddPanel(options) {
|
|
1937
|
+
var _a, _b, _c, _d;
|
|
1938
|
+
if (this.panels.some((_) => _.id === options.id)) {
|
|
1471
1939
|
throw new Error(`dockview: panel with id ${options.id} already exists`);
|
|
1472
1940
|
}
|
|
1473
1941
|
let referenceGroup;
|
|
@@ -1486,18 +1954,24 @@ export class DockviewComponent extends BaseGrid {
|
|
|
1486
1954
|
: options.position.referencePanel;
|
|
1487
1955
|
index = options.position.index;
|
|
1488
1956
|
if (!referencePanel) {
|
|
1489
|
-
|
|
1957
|
+
const referenceId = typeof options.position.referencePanel === 'string'
|
|
1958
|
+
? options.position.referencePanel
|
|
1959
|
+
: (_a = options.position.referencePanel) === null || _a === void 0 ? void 0 : _a.id;
|
|
1960
|
+
throw new Error(`dockview: referencePanel '${referenceId}' does not exist`);
|
|
1490
1961
|
}
|
|
1491
1962
|
referenceGroup = this.findGroup(referencePanel);
|
|
1492
1963
|
}
|
|
1493
1964
|
else if (isPanelOptionsWithGroup(options.position)) {
|
|
1494
1965
|
referenceGroup =
|
|
1495
1966
|
typeof options.position.referenceGroup === 'string'
|
|
1496
|
-
? (
|
|
1967
|
+
? (_b = this._groups.get(options.position.referenceGroup)) === null || _b === void 0 ? void 0 : _b.value
|
|
1497
1968
|
: options.position.referenceGroup;
|
|
1498
1969
|
index = options.position.index;
|
|
1499
1970
|
if (!referenceGroup) {
|
|
1500
|
-
|
|
1971
|
+
const referenceId = typeof options.position.referenceGroup === 'string'
|
|
1972
|
+
? options.position.referenceGroup
|
|
1973
|
+
: (_c = options.position.referenceGroup) === null || _c === void 0 ? void 0 : _c.id;
|
|
1974
|
+
throw new Error(`dockview: referenceGroup '${referenceId}' does not exist`);
|
|
1501
1975
|
}
|
|
1502
1976
|
}
|
|
1503
1977
|
else {
|
|
@@ -1523,7 +1997,7 @@ export class DockviewComponent extends BaseGrid {
|
|
|
1523
1997
|
}
|
|
1524
1998
|
let panel;
|
|
1525
1999
|
if (referenceGroup) {
|
|
1526
|
-
const target = toTarget(((
|
|
2000
|
+
const target = toTarget(((_d = options.position) === null || _d === void 0 ? void 0 : _d.direction) || 'within');
|
|
1527
2001
|
if (options.floating) {
|
|
1528
2002
|
const group = this.createGroup();
|
|
1529
2003
|
this._onDidAddGroup.fire(group);
|
|
@@ -1605,9 +2079,17 @@ export class DockviewComponent extends BaseGrid {
|
|
|
1605
2079
|
}
|
|
1606
2080
|
return panel;
|
|
1607
2081
|
}
|
|
1608
|
-
removePanel(panel, options
|
|
1609
|
-
|
|
1610
|
-
|
|
2082
|
+
removePanel(panel, options) {
|
|
2083
|
+
this.mutation('remove', () => {
|
|
2084
|
+
var _a;
|
|
2085
|
+
return this._doRemovePanel(panel, {
|
|
2086
|
+
removeEmptyGroup: (_a = options === null || options === void 0 ? void 0 : options.removeEmptyGroup) !== null && _a !== void 0 ? _a : true,
|
|
2087
|
+
skipDispose: options === null || options === void 0 ? void 0 : options.skipDispose,
|
|
2088
|
+
skipSetActiveGroup: options === null || options === void 0 ? void 0 : options.skipSetActiveGroup,
|
|
2089
|
+
});
|
|
2090
|
+
});
|
|
2091
|
+
}
|
|
2092
|
+
_doRemovePanel(panel, options) {
|
|
1611
2093
|
const group = panel.group;
|
|
1612
2094
|
if (!group) {
|
|
1613
2095
|
throw new Error(`dockview: cannot remove panel ${panel.id}. it's missing a group.`);
|
|
@@ -1629,50 +2111,38 @@ export class DockviewComponent extends BaseGrid {
|
|
|
1629
2111
|
}
|
|
1630
2112
|
return new Watermark();
|
|
1631
2113
|
}
|
|
1632
|
-
updateWatermark() {
|
|
1633
|
-
var _a, _b;
|
|
1634
|
-
if (this.groups.filter((x) => x.api.location.type === 'grid' && x.api.isVisible).length === 0) {
|
|
1635
|
-
if (!this._watermark) {
|
|
1636
|
-
this._watermark = this.createWatermarkComponent();
|
|
1637
|
-
this._watermark.init({
|
|
1638
|
-
containerApi: new DockviewApi(this),
|
|
1639
|
-
});
|
|
1640
|
-
const watermarkContainer = document.createElement('div');
|
|
1641
|
-
watermarkContainer.className = 'dv-watermark-container';
|
|
1642
|
-
addTestId(watermarkContainer, 'watermark-component');
|
|
1643
|
-
watermarkContainer.appendChild(this._watermark.element);
|
|
1644
|
-
this.gridview.element.appendChild(watermarkContainer);
|
|
1645
|
-
}
|
|
1646
|
-
}
|
|
1647
|
-
else if (this._watermark) {
|
|
1648
|
-
this._watermark.element.parentElement.remove();
|
|
1649
|
-
(_b = (_a = this._watermark).dispose) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
1650
|
-
this._watermark = null;
|
|
1651
|
-
}
|
|
1652
|
-
}
|
|
1653
2114
|
addGroup(options) {
|
|
1654
|
-
|
|
2115
|
+
return this.mutation('add', () => this._doAddGroup(options));
|
|
2116
|
+
}
|
|
2117
|
+
_doAddGroup(options) {
|
|
2118
|
+
var _a, _b, _c;
|
|
1655
2119
|
if (options) {
|
|
1656
2120
|
let referenceGroup;
|
|
1657
2121
|
if (isGroupOptionsWithPanel(options)) {
|
|
1658
2122
|
const referencePanel = typeof options.referencePanel === 'string'
|
|
1659
2123
|
? this.panels.find((panel) => panel.id === options.referencePanel)
|
|
1660
2124
|
: options.referencePanel;
|
|
2125
|
+
const referencePanelId = typeof options.referencePanel === 'string'
|
|
2126
|
+
? options.referencePanel
|
|
2127
|
+
: (_a = options.referencePanel) === null || _a === void 0 ? void 0 : _a.id;
|
|
1661
2128
|
if (!referencePanel) {
|
|
1662
|
-
throw new Error(`dockview: reference panel ${
|
|
2129
|
+
throw new Error(`dockview: reference panel ${referencePanelId} does not exist`);
|
|
1663
2130
|
}
|
|
1664
2131
|
referenceGroup = this.findGroup(referencePanel);
|
|
1665
2132
|
if (!referenceGroup) {
|
|
1666
|
-
throw new Error(`dockview: reference group for reference panel ${
|
|
2133
|
+
throw new Error(`dockview: reference group for reference panel ${referencePanelId} does not exist`);
|
|
1667
2134
|
}
|
|
1668
2135
|
}
|
|
1669
2136
|
else if (isGroupOptionsWithGroup(options)) {
|
|
1670
2137
|
referenceGroup =
|
|
1671
2138
|
typeof options.referenceGroup === 'string'
|
|
1672
|
-
? (
|
|
2139
|
+
? (_b = this._groups.get(options.referenceGroup)) === null || _b === void 0 ? void 0 : _b.value
|
|
1673
2140
|
: options.referenceGroup;
|
|
1674
2141
|
if (!referenceGroup) {
|
|
1675
|
-
|
|
2142
|
+
const referenceId = typeof options.referenceGroup === 'string'
|
|
2143
|
+
? options.referenceGroup
|
|
2144
|
+
: (_c = options.referenceGroup) === null || _c === void 0 ? void 0 : _c.id;
|
|
2145
|
+
throw new Error(`dockview: reference group ${referenceId} does not exist`);
|
|
1676
2146
|
}
|
|
1677
2147
|
}
|
|
1678
2148
|
else {
|
|
@@ -1710,12 +2180,71 @@ export class DockviewComponent extends BaseGrid {
|
|
|
1710
2180
|
: Orientation.VERTICAL;
|
|
1711
2181
|
}
|
|
1712
2182
|
removeGroup(group, options) {
|
|
1713
|
-
this.doRemoveGroup(group, options);
|
|
2183
|
+
this.mutation('remove', () => this.doRemoveGroup(group, options));
|
|
2184
|
+
}
|
|
2185
|
+
/**
|
|
2186
|
+
* Detach a single group from the nested gridview of its floating / popout
|
|
2187
|
+
* window, keeping the window and its remaining members alive, and reassign
|
|
2188
|
+
* the window's anchor if the detached group was it.
|
|
2189
|
+
*
|
|
2190
|
+
* @returns `true` if the group was detached from a multi-member window;
|
|
2191
|
+
* `false` if `group` is not in a nested window, or is the window's only
|
|
2192
|
+
* member — in which case the caller is responsible for disposing the whole
|
|
2193
|
+
* window.
|
|
2194
|
+
*/
|
|
2195
|
+
detachFromNestedWindow(group) {
|
|
2196
|
+
var _a, _b;
|
|
2197
|
+
const floating = (_a = this._floatingGroupService) === null || _a === void 0 ? void 0 : _a.findByGroup(group);
|
|
2198
|
+
if (floating) {
|
|
2199
|
+
const members = this.nestedWindowMembers(group);
|
|
2200
|
+
if (members.length <= 1) {
|
|
2201
|
+
return false;
|
|
2202
|
+
}
|
|
2203
|
+
floating.gridview.remove(group);
|
|
2204
|
+
if (floating.group === group) {
|
|
2205
|
+
// The anchor left; promote a remaining member.
|
|
2206
|
+
floating.setAnchorGroup(members.find((m) => m !== group));
|
|
2207
|
+
}
|
|
2208
|
+
return true;
|
|
2209
|
+
}
|
|
2210
|
+
const popout = (_b = this._popoutWindowService) === null || _b === void 0 ? void 0 : _b.findByGroup(group);
|
|
2211
|
+
if (popout) {
|
|
2212
|
+
const members = this.nestedWindowMembers(group);
|
|
2213
|
+
if (members.length <= 1) {
|
|
2214
|
+
return false;
|
|
2215
|
+
}
|
|
2216
|
+
popout.gridview.remove(group);
|
|
2217
|
+
if (popout.popoutGroup === group) {
|
|
2218
|
+
// The anchor left; promote a remaining member.
|
|
2219
|
+
popout.popoutGroup = members.find((m) => m !== group);
|
|
2220
|
+
}
|
|
2221
|
+
return true;
|
|
2222
|
+
}
|
|
2223
|
+
return false;
|
|
2224
|
+
}
|
|
2225
|
+
/**
|
|
2226
|
+
* Dispose a group and forget it: remove it from `_groups` and fire the
|
|
2227
|
+
* removed event.
|
|
2228
|
+
*/
|
|
2229
|
+
disposeGroupRecord(group) {
|
|
2230
|
+
group.dispose();
|
|
2231
|
+
this._groups.delete(group.id);
|
|
2232
|
+
this._onDidRemoveGroup.fire(group);
|
|
2233
|
+
}
|
|
2234
|
+
/**
|
|
2235
|
+
* When `removed` was the active group, fall the active selection back to
|
|
2236
|
+
* the first remaining group (or clear it when none remain).
|
|
2237
|
+
*/
|
|
2238
|
+
activateFallbackGroupIfRemoved(removed, skipActive) {
|
|
2239
|
+
if (!skipActive && this._activeGroup === removed) {
|
|
2240
|
+
const groups = Array.from(this._groups.values());
|
|
2241
|
+
this.doSetGroupAndPanelActive(groups.length > 0 ? groups[0].value : undefined);
|
|
2242
|
+
}
|
|
1714
2243
|
}
|
|
1715
2244
|
doRemoveGroup(group, options) {
|
|
1716
|
-
var _a;
|
|
2245
|
+
var _a, _b, _c, _d, _e;
|
|
1717
2246
|
// Edge groups are permanent structural elements - never remove them from the layout
|
|
1718
|
-
if (
|
|
2247
|
+
if ((_a = this._edgeGroupService) === null || _a === void 0 ? void 0 : _a.includes(group)) {
|
|
1719
2248
|
return group;
|
|
1720
2249
|
}
|
|
1721
2250
|
const panels = [...group.panels]; // reassign since group panels will mutate
|
|
@@ -1723,64 +2252,99 @@ export class DockviewComponent extends BaseGrid {
|
|
|
1723
2252
|
for (const panel of panels) {
|
|
1724
2253
|
this.removePanel(panel, {
|
|
1725
2254
|
removeEmptyGroup: false,
|
|
1726
|
-
skipDispose: (
|
|
2255
|
+
skipDispose: (_b = options === null || options === void 0 ? void 0 : options.skipDispose) !== null && _b !== void 0 ? _b : false,
|
|
1727
2256
|
});
|
|
1728
2257
|
}
|
|
1729
2258
|
}
|
|
1730
2259
|
const activePanel = this.activePanel;
|
|
1731
2260
|
if (group.api.location.type === 'floating') {
|
|
1732
|
-
const floatingGroup = this.
|
|
1733
|
-
if (floatingGroup) {
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
2261
|
+
const floatingGroup = (_c = this._floatingGroupService) === null || _c === void 0 ? void 0 : _c.findByGroup(group);
|
|
2262
|
+
if (!floatingGroup) {
|
|
2263
|
+
throw new Error('dockview: failed to find floating group');
|
|
2264
|
+
}
|
|
2265
|
+
if (this.detachFromNestedWindow(group)) {
|
|
2266
|
+
// The floating window hosts other groups and stays alive —
|
|
2267
|
+
// finalize just this group.
|
|
2268
|
+
if (options === null || options === void 0 ? void 0 : options.skipDispose) {
|
|
2269
|
+
// Relocation: reset location so the destination root can
|
|
2270
|
+
// re-tag it.
|
|
2271
|
+
group.model.location = { type: 'grid' };
|
|
1738
2272
|
}
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
if (!(options === null || options === void 0 ? void 0 : options.skipActive) && this._activeGroup === group) {
|
|
1742
|
-
const groups = Array.from(this._groups.values());
|
|
1743
|
-
this.doSetGroupAndPanelActive(groups.length > 0 ? groups[0].value : undefined);
|
|
2273
|
+
else {
|
|
2274
|
+
this.disposeGroupRecord(group);
|
|
1744
2275
|
}
|
|
1745
|
-
|
|
2276
|
+
this.activateFallbackGroupIfRemoved(group, options === null || options === void 0 ? void 0 : options.skipActive);
|
|
2277
|
+
return group;
|
|
2278
|
+
}
|
|
2279
|
+
// Last group leaving — dispose the whole floating window.
|
|
2280
|
+
if (!(options === null || options === void 0 ? void 0 : options.skipDispose)) {
|
|
2281
|
+
this.disposeGroupRecord(group);
|
|
1746
2282
|
}
|
|
1747
|
-
|
|
2283
|
+
// floatingGroup.dispose() removes itself from the service array
|
|
2284
|
+
floatingGroup.dispose();
|
|
2285
|
+
this.activateFallbackGroupIfRemoved(group, options === null || options === void 0 ? void 0 : options.skipActive);
|
|
2286
|
+
return group;
|
|
1748
2287
|
}
|
|
1749
2288
|
if (group.api.location.type === 'popout') {
|
|
1750
|
-
const selectedGroup = this.
|
|
1751
|
-
if (selectedGroup) {
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
}
|
|
1761
|
-
selectedGroup.popoutGroup.dispose();
|
|
1762
|
-
this._groups.delete(group.id);
|
|
1763
|
-
this._onDidRemoveGroup.fire(group);
|
|
2289
|
+
const selectedGroup = (_d = this._popoutWindowService) === null || _d === void 0 ? void 0 : _d.findByGroup(group);
|
|
2290
|
+
if (!selectedGroup) {
|
|
2291
|
+
throw new Error('dockview: failed to find popout group');
|
|
2292
|
+
}
|
|
2293
|
+
if (this.detachFromNestedWindow(group)) {
|
|
2294
|
+
// The popout window hosts other groups and stays alive —
|
|
2295
|
+
// finalize just this group.
|
|
2296
|
+
if (options === null || options === void 0 ? void 0 : options.skipDispose) {
|
|
2297
|
+
// Relocation: reset location so the destination root can
|
|
2298
|
+
// re-tag it.
|
|
2299
|
+
group.model.location = { type: 'grid' };
|
|
1764
2300
|
}
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
if (!(options === null || options === void 0 ? void 0 : options.skipPopoutReturn) && removedGroup) {
|
|
1768
|
-
this.doAddGroup(removedGroup, [0]);
|
|
1769
|
-
this.doSetGroupAndPanelActive(removedGroup);
|
|
2301
|
+
else {
|
|
2302
|
+
this.disposeGroupRecord(group);
|
|
1770
2303
|
}
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
2304
|
+
this.activateFallbackGroupIfRemoved(group, options === null || options === void 0 ? void 0 : options.skipActive);
|
|
2305
|
+
return group;
|
|
2306
|
+
}
|
|
2307
|
+
// Last group leaving — tear the whole popout window down.
|
|
2308
|
+
if (!(options === null || options === void 0 ? void 0 : options.skipDispose)) {
|
|
2309
|
+
if (!(options === null || options === void 0 ? void 0 : options.skipPopoutAssociated)) {
|
|
2310
|
+
const refGroup = selectedGroup.referenceGroup
|
|
2311
|
+
? this.getPanel(selectedGroup.referenceGroup)
|
|
2312
|
+
: undefined;
|
|
2313
|
+
if ((refGroup === null || refGroup === void 0 ? void 0 : refGroup.panels.length) === 0) {
|
|
2314
|
+
this.removeGroup(refGroup);
|
|
2315
|
+
}
|
|
1774
2316
|
}
|
|
1775
|
-
|
|
1776
|
-
|
|
2317
|
+
selectedGroup.popoutGroup.dispose();
|
|
2318
|
+
this._groups.delete(group.id);
|
|
2319
|
+
this._onDidRemoveGroup.fire(group);
|
|
1777
2320
|
}
|
|
1778
|
-
|
|
2321
|
+
(_e = this._popoutWindowService) === null || _e === void 0 ? void 0 : _e.remove(selectedGroup);
|
|
2322
|
+
const removedGroup = selectedGroup.disposable.dispose();
|
|
2323
|
+
if (!(options === null || options === void 0 ? void 0 : options.skipPopoutReturn) && removedGroup) {
|
|
2324
|
+
this.doAddGroup(removedGroup, [0]);
|
|
2325
|
+
this.doSetGroupAndPanelActive(removedGroup);
|
|
2326
|
+
}
|
|
2327
|
+
this.activateFallbackGroupIfRemoved(group, options === null || options === void 0 ? void 0 : options.skipActive);
|
|
2328
|
+
return selectedGroup.popoutGroup;
|
|
2329
|
+
}
|
|
2330
|
+
// A `grid`-location group whose element isn't actually in the gridview
|
|
2331
|
+
// is an orphan — e.g. a popout-destined group created during fromJSON
|
|
2332
|
+
// whose window hasn't opened yet, swept up by clear()/a re-entrant
|
|
2333
|
+
// fromJSON. `gridview.remove()` would throw "Invalid grid element", so
|
|
2334
|
+
// dispose it directly.
|
|
2335
|
+
if (!this.gridview.element.contains(group.element)) {
|
|
2336
|
+
if (!(options === null || options === void 0 ? void 0 : options.skipDispose)) {
|
|
2337
|
+
const item = this._groups.get(group.id);
|
|
2338
|
+
item === null || item === void 0 ? void 0 : item.disposable.dispose();
|
|
2339
|
+
this.disposeGroupRecord(group);
|
|
2340
|
+
}
|
|
2341
|
+
this.activateFallbackGroupIfRemoved(group, options === null || options === void 0 ? void 0 : options.skipActive);
|
|
2342
|
+
return group;
|
|
1779
2343
|
}
|
|
1780
2344
|
const re = super.doRemoveGroup(group, options);
|
|
1781
2345
|
if (!(options === null || options === void 0 ? void 0 : options.skipActive)) {
|
|
1782
2346
|
if (this.activePanel !== activePanel) {
|
|
1783
|
-
this.
|
|
2347
|
+
this.fireActivePanelChange(this.activePanel);
|
|
1784
2348
|
}
|
|
1785
2349
|
}
|
|
1786
2350
|
return re;
|
|
@@ -1790,8 +2354,15 @@ export class DockviewComponent extends BaseGrid {
|
|
|
1790
2354
|
cancelAnimationFrame(this._updatePositionsFrameId);
|
|
1791
2355
|
}
|
|
1792
2356
|
this._updatePositionsFrameId = requestAnimationFrame(() => {
|
|
2357
|
+
var _a, _b;
|
|
1793
2358
|
this._updatePositionsFrameId = undefined;
|
|
1794
2359
|
this.overlayRenderContainer.updateAllPositions();
|
|
2360
|
+
// Popout windows have their own render containers; reposition those
|
|
2361
|
+
// too so panels moved/split within a popout are laid out (the main
|
|
2362
|
+
// container only covers grid + floating, which share it).
|
|
2363
|
+
for (const entry of (_b = (_a = this._popoutWindowService) === null || _a === void 0 ? void 0 : _a.entries) !== null && _b !== void 0 ? _b : []) {
|
|
2364
|
+
entry.overlayRenderContainer.updateAllPositions();
|
|
2365
|
+
}
|
|
1795
2366
|
});
|
|
1796
2367
|
}
|
|
1797
2368
|
movingLock(func) {
|
|
@@ -1804,8 +2375,74 @@ export class DockviewComponent extends BaseGrid {
|
|
|
1804
2375
|
this._moving = isMoving;
|
|
1805
2376
|
}
|
|
1806
2377
|
}
|
|
2378
|
+
/**
|
|
2379
|
+
* Bracket a structural mutation with `onWillMutateLayout` /
|
|
2380
|
+
* `onDidMutateLayout`. Re-entrant: nested calls (a compound operation such
|
|
2381
|
+
* as a drag that relocates a panel) join the outermost transaction, so the
|
|
2382
|
+
* events fire exactly once around the whole operation. `kind` reflects the
|
|
2383
|
+
* outermost mutation.
|
|
2384
|
+
*/
|
|
2385
|
+
mutation(kind, func) {
|
|
2386
|
+
const outer = this._mutationDepth === 0;
|
|
2387
|
+
const origin = this._origin;
|
|
2388
|
+
if (outer) {
|
|
2389
|
+
this._onWillMutateLayout.fire({ kind, origin });
|
|
2390
|
+
}
|
|
2391
|
+
this._mutationDepth++;
|
|
2392
|
+
try {
|
|
2393
|
+
return func();
|
|
2394
|
+
}
|
|
2395
|
+
finally {
|
|
2396
|
+
this._mutationDepth--;
|
|
2397
|
+
if (outer) {
|
|
2398
|
+
this._onDidMutateLayout.fire({ kind, origin });
|
|
2399
|
+
}
|
|
2400
|
+
}
|
|
2401
|
+
}
|
|
2402
|
+
/**
|
|
2403
|
+
* The origin of the operation currently in progress (`'user'` by default).
|
|
2404
|
+
* Read inside a `mutation()` or active-panel change to learn whether the
|
|
2405
|
+
* change was driven by application code (via the {@link DockviewApi}) or a
|
|
2406
|
+
* user gesture.
|
|
2407
|
+
*/
|
|
2408
|
+
currentOrigin() {
|
|
2409
|
+
return this._origin;
|
|
2410
|
+
}
|
|
2411
|
+
/**
|
|
2412
|
+
* Run `func` with the operation origin set to `origin`, restoring the
|
|
2413
|
+
* previous value afterwards. Used by the DockviewApi boundary to tag
|
|
2414
|
+
* programmatic operations as `'api'`, and by user-gesture handlers to tag
|
|
2415
|
+
* `'user'`. Only the outermost caller sets the origin — a nested call (or a
|
|
2416
|
+
* call made while a mutation is already in flight) keeps whatever the
|
|
2417
|
+
* enclosing operation established, so the trigger always wins.
|
|
2418
|
+
*/
|
|
2419
|
+
withOrigin(origin, func) {
|
|
2420
|
+
if (this._originDepth > 0 || this._mutationDepth > 0) {
|
|
2421
|
+
return func();
|
|
2422
|
+
}
|
|
2423
|
+
const previous = this._origin;
|
|
2424
|
+
this._origin = origin;
|
|
2425
|
+
this._originDepth++;
|
|
2426
|
+
try {
|
|
2427
|
+
return func();
|
|
2428
|
+
}
|
|
2429
|
+
finally {
|
|
2430
|
+
this._originDepth--;
|
|
2431
|
+
this._origin = previous;
|
|
2432
|
+
}
|
|
2433
|
+
}
|
|
2434
|
+
/**
|
|
2435
|
+
* Fire `onDidActivePanelChange` with the panel and the current operation
|
|
2436
|
+
* {@link DockviewOrigin}. Callers keep their own dedupe guards.
|
|
2437
|
+
*/
|
|
2438
|
+
fireActivePanelChange(panel) {
|
|
2439
|
+
this._onDidActivePanelChange.fire({ panel, origin: this._origin });
|
|
2440
|
+
}
|
|
1807
2441
|
moveGroupOrPanel(options) {
|
|
1808
|
-
|
|
2442
|
+
this.mutation('move', () => this._doMoveGroupOrPanel(options));
|
|
2443
|
+
}
|
|
2444
|
+
_doMoveGroupOrPanel(options) {
|
|
2445
|
+
var _a, _b;
|
|
1809
2446
|
const destinationGroup = options.to.group;
|
|
1810
2447
|
const sourceGroupId = options.from.groupId;
|
|
1811
2448
|
const sourceItemId = options.from.panelId;
|
|
@@ -1886,15 +2523,20 @@ export class DockviewComponent extends BaseGrid {
|
|
|
1886
2523
|
* Dropping a panel to the extremities of a group which will place that panel
|
|
1887
2524
|
* into an adjacent group
|
|
1888
2525
|
*/
|
|
2526
|
+
// The destination group may live in the main grid or in a floating
|
|
2527
|
+
// window's nested gridview — resolve which root we are dropping
|
|
2528
|
+
// into so locations/orientation are computed against it.
|
|
2529
|
+
const destinationGridview = this.getGridviewForGroup(destinationGroup);
|
|
1889
2530
|
const referenceLocation = getGridLocation(destinationGroup.element);
|
|
1890
|
-
const targetLocation = getRelativeLocation(
|
|
2531
|
+
const targetLocation = getRelativeLocation(destinationGridview.orientation, referenceLocation, destinationTarget);
|
|
1891
2532
|
if (sourceGroup.size < 2) {
|
|
1892
2533
|
/**
|
|
1893
2534
|
* If we are moving from a group which only has one panel left we will consider
|
|
1894
2535
|
* moving the group itself rather than moving the panel into a newly created group
|
|
1895
2536
|
*/
|
|
1896
2537
|
const [targetParentLocation, to] = tail(targetLocation);
|
|
1897
|
-
if (sourceGroup.api.location.type === 'grid'
|
|
2538
|
+
if (sourceGroup.api.location.type === 'grid' &&
|
|
2539
|
+
destinationGridview === this.gridview) {
|
|
1898
2540
|
const sourceLocation = getGridLocation(sourceGroup.element);
|
|
1899
2541
|
const [sourceParentLocation, from] = tail(sourceLocation);
|
|
1900
2542
|
if (sequenceEquals(sourceParentLocation, targetParentLocation)) {
|
|
@@ -1909,9 +2551,11 @@ export class DockviewComponent extends BaseGrid {
|
|
|
1909
2551
|
return;
|
|
1910
2552
|
}
|
|
1911
2553
|
}
|
|
1912
|
-
if (sourceGroup.api.location.type === 'popout'
|
|
2554
|
+
if (sourceGroup.api.location.type === 'popout' &&
|
|
2555
|
+
this.nestedWindowMembers(sourceGroup).length <= 1) {
|
|
1913
2556
|
/**
|
|
1914
|
-
* the source group is
|
|
2557
|
+
* the source group is the only group in a popout window and
|
|
2558
|
+
* has a single panel
|
|
1915
2559
|
*
|
|
1916
2560
|
* 1. remove the panel from the group without triggering any events
|
|
1917
2561
|
* 2. remove the popout group — this may cascade-remove the empty
|
|
@@ -1919,15 +2563,21 @@ export class DockviewComponent extends BaseGrid {
|
|
|
1919
2563
|
* doRemoveGroup for popout groups), which can shift grid indices
|
|
1920
2564
|
* 3. recompute the target location now that the grid is stable
|
|
1921
2565
|
* 4. create a new group at the recomputed location and add that panel
|
|
2566
|
+
*
|
|
2567
|
+
* Multi-group popout windows fall through to the generic
|
|
2568
|
+
* detach-and-re-add path so the window stays alive.
|
|
1922
2569
|
*/
|
|
1923
|
-
const popoutGroup = this.
|
|
2570
|
+
const popoutGroup = (_b = this._popoutWindowService) === null || _b === void 0 ? void 0 : _b.findByGroup(sourceGroup);
|
|
2571
|
+
if (!popoutGroup) {
|
|
2572
|
+
return;
|
|
2573
|
+
}
|
|
1924
2574
|
const removedPanel = this.movingLock(() => popoutGroup.popoutGroup.model.removePanel(popoutGroup.popoutGroup.panels[0], {
|
|
1925
2575
|
skipSetActive: true,
|
|
1926
2576
|
skipSetActiveGroup: true,
|
|
1927
2577
|
}));
|
|
1928
2578
|
this.doRemoveGroup(sourceGroup, { skipActive: true });
|
|
1929
|
-
const updatedTargetLocation = getRelativeLocation(
|
|
1930
|
-
const newGroup = this.createGroupAtLocation(updatedTargetLocation);
|
|
2579
|
+
const updatedTargetLocation = getRelativeLocation(destinationGridview.orientation, getGridLocation(destinationGroup.element), destinationTarget);
|
|
2580
|
+
const newGroup = this.createGroupAtLocation(updatedTargetLocation, undefined, undefined, destinationGridview);
|
|
1931
2581
|
this.movingLock(() => newGroup.model.openPanel(removedPanel, {
|
|
1932
2582
|
skipSetActive: true,
|
|
1933
2583
|
}));
|
|
@@ -1951,7 +2601,7 @@ export class DockviewComponent extends BaseGrid {
|
|
|
1951
2601
|
if (!removedPanel) {
|
|
1952
2602
|
throw new Error(`dockview: No panel with id ${sourceItemId}`);
|
|
1953
2603
|
}
|
|
1954
|
-
const newGroup = this.createGroupAtLocation(targetLocation);
|
|
2604
|
+
const newGroup = this.createGroupAtLocation(targetLocation, undefined, undefined, destinationGridview);
|
|
1955
2605
|
this.movingLock(() => newGroup.model.openPanel(removedPanel, {
|
|
1956
2606
|
skipSetGroupActive: true,
|
|
1957
2607
|
}));
|
|
@@ -1969,8 +2619,9 @@ export class DockviewComponent extends BaseGrid {
|
|
|
1969
2619
|
}));
|
|
1970
2620
|
// after deleting the group we need to re-evaulate the ref location
|
|
1971
2621
|
const updatedReferenceLocation = getGridLocation(destinationGroup.element);
|
|
1972
|
-
const location = getRelativeLocation(
|
|
1973
|
-
this.movingLock(() => this.doAddGroup(targetGroup, location));
|
|
2622
|
+
const location = getRelativeLocation(destinationGridview.orientation, updatedReferenceLocation, destinationTarget);
|
|
2623
|
+
this.movingLock(() => this.doAddGroup(targetGroup, location, undefined, destinationGridview));
|
|
2624
|
+
this.setGroupLocationForRoot(targetGroup, destinationGridview);
|
|
1974
2625
|
this.doSetGroupAndPanelActive(targetGroup);
|
|
1975
2626
|
this._onDidMovePanel.fire({
|
|
1976
2627
|
panel: this.getGroupPanel(sourceItemId),
|
|
@@ -1989,8 +2640,8 @@ export class DockviewComponent extends BaseGrid {
|
|
|
1989
2640
|
if (!removedPanel) {
|
|
1990
2641
|
throw new Error(`dockview: No panel with id ${sourceItemId}`);
|
|
1991
2642
|
}
|
|
1992
|
-
const dropLocation = getRelativeLocation(
|
|
1993
|
-
const group = this.createGroupAtLocation(dropLocation);
|
|
2643
|
+
const dropLocation = getRelativeLocation(destinationGridview.orientation, referenceLocation, destinationTarget);
|
|
2644
|
+
const group = this.createGroupAtLocation(dropLocation, undefined, undefined, destinationGridview);
|
|
1994
2645
|
this.movingLock(() => group.model.openPanel(removedPanel, {
|
|
1995
2646
|
skipSetGroupActive: true,
|
|
1996
2647
|
}));
|
|
@@ -2085,6 +2736,21 @@ export class DockviewComponent extends BaseGrid {
|
|
|
2085
2736
|
addPanelsToGroup(targetGroup);
|
|
2086
2737
|
}
|
|
2087
2738
|
moveGroup(options) {
|
|
2739
|
+
this.mutation('move', () => this._doMoveGroup(options));
|
|
2740
|
+
}
|
|
2741
|
+
// Bracket maximize/restore as a 'maximize' transaction. The maximized node
|
|
2742
|
+
// is serialized by the gridview (`SerializedGridview.maximizedNode`), so
|
|
2743
|
+
// the state round-trips through toJSON/fromJSON and is restorable on undo.
|
|
2744
|
+
// When the exit is a side-effect of another bracketed operation (e.g. a
|
|
2745
|
+
// move that activates a different group) the depth counter folds it in.
|
|
2746
|
+
maximizeGroup(panel) {
|
|
2747
|
+
this.mutation('maximize', () => super.maximizeGroup(panel));
|
|
2748
|
+
}
|
|
2749
|
+
exitMaximizedGroup() {
|
|
2750
|
+
this.mutation('maximize', () => super.exitMaximizedGroup());
|
|
2751
|
+
}
|
|
2752
|
+
_doMoveGroup(options) {
|
|
2753
|
+
var _a, _b, _c;
|
|
2088
2754
|
const from = options.from.group;
|
|
2089
2755
|
const to = options.to.group;
|
|
2090
2756
|
const target = options.to.position;
|
|
@@ -2165,6 +2831,13 @@ export class DockviewComponent extends BaseGrid {
|
|
|
2165
2831
|
}));
|
|
2166
2832
|
const movedPanels = this.movingLock(() => [...from.panels].map((p) => from.model.removePanel(p.id, { skipSetActive: true })));
|
|
2167
2833
|
source = this.createGroup();
|
|
2834
|
+
// The new source group enters the layout via gridview.addView
|
|
2835
|
+
// below, which bypasses doAddGroup and so doesn't fire
|
|
2836
|
+
// BaseGrid._onDidAdd. Modules (TabGroupChips, etc.) drive
|
|
2837
|
+
// per-group attachment off _onDidAddGroup, so we fire it
|
|
2838
|
+
// explicitly here — matches the pattern in addFloatingGroup
|
|
2839
|
+
// and addEdgeGroup.
|
|
2840
|
+
this._onDidAddGroup.fire(source);
|
|
2168
2841
|
this.movingLock(() => {
|
|
2169
2842
|
for (const panel of movedPanels) {
|
|
2170
2843
|
source.model.openPanel(panel, {
|
|
@@ -2191,23 +2864,34 @@ export class DockviewComponent extends BaseGrid {
|
|
|
2191
2864
|
this.gridview.removeView(getGridLocation(from.element));
|
|
2192
2865
|
break;
|
|
2193
2866
|
case 'floating': {
|
|
2194
|
-
const selectedFloatingGroup = this.
|
|
2867
|
+
const selectedFloatingGroup = (_a = this._floatingGroupService) === null || _a === void 0 ? void 0 : _a.findByGroup(from);
|
|
2195
2868
|
if (!selectedFloatingGroup) {
|
|
2196
2869
|
throw new Error('dockview: failed to find floating group');
|
|
2197
2870
|
}
|
|
2198
|
-
|
|
2871
|
+
// Detach just this group from the floating window's
|
|
2872
|
+
// nested gridview, keeping the window (and its other
|
|
2873
|
+
// groups) alive. If it was the only member, dispose the
|
|
2874
|
+
// whole window.
|
|
2875
|
+
if (!this.detachFromNestedWindow(from)) {
|
|
2876
|
+
selectedFloatingGroup.dispose();
|
|
2877
|
+
}
|
|
2199
2878
|
break;
|
|
2200
2879
|
}
|
|
2201
2880
|
case 'popout': {
|
|
2202
|
-
const selectedPopoutGroup = this.
|
|
2881
|
+
const selectedPopoutGroup = (_b = this._popoutWindowService) === null || _b === void 0 ? void 0 : _b.findByGroup(from);
|
|
2203
2882
|
if (!selectedPopoutGroup) {
|
|
2204
2883
|
throw new Error('dockview: failed to find popout group');
|
|
2205
2884
|
}
|
|
2206
|
-
//
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2885
|
+
// Detach just this group from the popout window's
|
|
2886
|
+
// nested gridview, keeping the window + its other groups
|
|
2887
|
+
// alive. Destination containers/location are applied by
|
|
2888
|
+
// the placement block below.
|
|
2889
|
+
if (this.detachFromNestedWindow(from)) {
|
|
2890
|
+
break;
|
|
2210
2891
|
}
|
|
2892
|
+
// Last group leaving — tear the window down. Remove from
|
|
2893
|
+
// the service first to prevent automatic restoration.
|
|
2894
|
+
(_c = this._popoutWindowService) === null || _c === void 0 ? void 0 : _c.remove(selectedPopoutGroup);
|
|
2211
2895
|
// Clean up the reference group (ghost) if it exists and is hidden
|
|
2212
2896
|
if (selectedPopoutGroup.referenceGroup) {
|
|
2213
2897
|
const referenceGroup = this.getPanel(selectedPopoutGroup.referenceGroup);
|
|
@@ -2218,34 +2902,25 @@ export class DockviewComponent extends BaseGrid {
|
|
|
2218
2902
|
});
|
|
2219
2903
|
}
|
|
2220
2904
|
}
|
|
2221
|
-
//
|
|
2905
|
+
// Dispose the window without triggering restoration. The
|
|
2906
|
+
// placement block below applies the destination
|
|
2907
|
+
// location and containers to `from`.
|
|
2222
2908
|
selectedPopoutGroup.window.dispose();
|
|
2223
|
-
// Update group's location and containers for target
|
|
2224
|
-
if (to.api.location.type === 'grid') {
|
|
2225
|
-
from.model.renderContainer =
|
|
2226
|
-
this.overlayRenderContainer;
|
|
2227
|
-
from.model.dropTargetContainer =
|
|
2228
|
-
this.rootDropTargetContainer;
|
|
2229
|
-
from.model.location = { type: 'grid' };
|
|
2230
|
-
}
|
|
2231
|
-
else if (to.api.location.type === 'floating') {
|
|
2232
|
-
from.model.renderContainer =
|
|
2233
|
-
this.overlayRenderContainer;
|
|
2234
|
-
from.model.dropTargetContainer =
|
|
2235
|
-
this.rootDropTargetContainer;
|
|
2236
|
-
from.model.location = { type: 'floating' };
|
|
2237
|
-
}
|
|
2238
2909
|
break;
|
|
2239
2910
|
}
|
|
2240
2911
|
}
|
|
2241
2912
|
}
|
|
2242
|
-
//
|
|
2243
|
-
|
|
2913
|
+
// Place `source` next to `to`, in whichever gridview root `to`
|
|
2914
|
+
// lives in. When `to` is inside a floating / popout window this
|
|
2915
|
+
// splits that window's nested layout rather than spawning a new one.
|
|
2916
|
+
if (to.api.location.type === 'grid' ||
|
|
2917
|
+
to.api.location.type === 'floating' ||
|
|
2918
|
+
to.api.location.type === 'popout') {
|
|
2919
|
+
const destGridview = this.getGridviewForGroup(to);
|
|
2244
2920
|
const referenceLocation = getGridLocation(to.element);
|
|
2245
|
-
const dropLocation = getRelativeLocation(
|
|
2246
|
-
// Add to grid for all moves targeting grid location
|
|
2921
|
+
const dropLocation = getRelativeLocation(destGridview.orientation, referenceLocation, target);
|
|
2247
2922
|
let size;
|
|
2248
|
-
switch (
|
|
2923
|
+
switch (destGridview.orientation) {
|
|
2249
2924
|
case Orientation.VERTICAL:
|
|
2250
2925
|
size =
|
|
2251
2926
|
referenceLocation.length % 2 == 0
|
|
@@ -2259,43 +2934,8 @@ export class DockviewComponent extends BaseGrid {
|
|
|
2259
2934
|
: from.api.width;
|
|
2260
2935
|
break;
|
|
2261
2936
|
}
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
else if (to.api.location.type === 'floating') {
|
|
2265
|
-
// For moves to floating locations, add as floating group
|
|
2266
|
-
// Get the position/size from the target floating group
|
|
2267
|
-
const targetFloatingGroup = this._floatingGroups.find((x) => x.group === to);
|
|
2268
|
-
if (targetFloatingGroup) {
|
|
2269
|
-
const box = targetFloatingGroup.overlay.toJSON();
|
|
2270
|
-
// Calculate position based on available properties
|
|
2271
|
-
let left, top;
|
|
2272
|
-
if ('left' in box) {
|
|
2273
|
-
left = box.left + 50;
|
|
2274
|
-
}
|
|
2275
|
-
else if ('right' in box) {
|
|
2276
|
-
left = Math.max(0, box.right - box.width - 50);
|
|
2277
|
-
}
|
|
2278
|
-
else {
|
|
2279
|
-
left = 50; // Default fallback
|
|
2280
|
-
}
|
|
2281
|
-
if ('top' in box) {
|
|
2282
|
-
top = box.top + 50;
|
|
2283
|
-
}
|
|
2284
|
-
else if ('bottom' in box) {
|
|
2285
|
-
top = Math.max(0, box.bottom - box.height - 50);
|
|
2286
|
-
}
|
|
2287
|
-
else {
|
|
2288
|
-
top = 50; // Default fallback
|
|
2289
|
-
}
|
|
2290
|
-
this.addFloatingGroup(source, {
|
|
2291
|
-
height: box.height,
|
|
2292
|
-
width: box.width,
|
|
2293
|
-
position: {
|
|
2294
|
-
left,
|
|
2295
|
-
top,
|
|
2296
|
-
},
|
|
2297
|
-
});
|
|
2298
|
-
}
|
|
2937
|
+
destGridview.addView(source, size, dropLocation);
|
|
2938
|
+
this.setGroupLocationForRoot(source, destGridview);
|
|
2299
2939
|
}
|
|
2300
2940
|
}
|
|
2301
2941
|
source.panels.forEach((panel) => {
|
|
@@ -2316,14 +2956,16 @@ export class DockviewComponent extends BaseGrid {
|
|
|
2316
2956
|
}
|
|
2317
2957
|
}
|
|
2318
2958
|
doSetGroupActive(group) {
|
|
2959
|
+
var _a;
|
|
2319
2960
|
super.doSetGroupActive(group);
|
|
2320
2961
|
const activePanel = this.activePanel;
|
|
2321
2962
|
if (!this._moving &&
|
|
2322
|
-
activePanel !== this._onDidActivePanelChange.value) {
|
|
2323
|
-
this.
|
|
2963
|
+
activePanel !== ((_a = this._onDidActivePanelChange.value) === null || _a === void 0 ? void 0 : _a.panel)) {
|
|
2964
|
+
this.fireActivePanelChange(activePanel);
|
|
2324
2965
|
}
|
|
2325
2966
|
}
|
|
2326
2967
|
doSetGroupAndPanelActive(group) {
|
|
2968
|
+
var _a;
|
|
2327
2969
|
super.doSetGroupActive(group);
|
|
2328
2970
|
const activePanel = this.activePanel;
|
|
2329
2971
|
if (group &&
|
|
@@ -2332,8 +2974,8 @@ export class DockviewComponent extends BaseGrid {
|
|
|
2332
2974
|
this.exitMaximizedGroup();
|
|
2333
2975
|
}
|
|
2334
2976
|
if (!this._moving &&
|
|
2335
|
-
activePanel !== this._onDidActivePanelChange.value) {
|
|
2336
|
-
this.
|
|
2977
|
+
activePanel !== ((_a = this._onDidActivePanelChange.value) === null || _a === void 0 ? void 0 : _a.panel)) {
|
|
2978
|
+
this.fireActivePanelChange(activePanel);
|
|
2337
2979
|
}
|
|
2338
2980
|
}
|
|
2339
2981
|
getNextGroupId() {
|
|
@@ -2344,9 +2986,7 @@ export class DockviewComponent extends BaseGrid {
|
|
|
2344
2986
|
return id;
|
|
2345
2987
|
}
|
|
2346
2988
|
createGroup(options) {
|
|
2347
|
-
|
|
2348
|
-
options = {};
|
|
2349
|
-
}
|
|
2989
|
+
options !== null && options !== void 0 ? options : (options = {});
|
|
2350
2990
|
let id = options === null || options === void 0 ? void 0 : options.id;
|
|
2351
2991
|
if (id && this._groups.has(options.id)) {
|
|
2352
2992
|
console.warn(`dockview: Duplicate group id ${options === null || options === void 0 ? void 0 : options.id}. reassigning group id to avoid errors`);
|
|
@@ -2362,9 +3002,11 @@ export class DockviewComponent extends BaseGrid {
|
|
|
2362
3002
|
view.init({ params: {}, accessor: this });
|
|
2363
3003
|
if (!this._groups.has(view.id)) {
|
|
2364
3004
|
const disposable = new CompositeDisposable(view.model.onTabDragStart((event) => {
|
|
2365
|
-
|
|
3005
|
+
var _a;
|
|
3006
|
+
(_a = this._advancedDnDService) === null || _a === void 0 ? void 0 : _a.dispatchWillDragPanel(event);
|
|
2366
3007
|
}), view.model.onGroupDragStart((event) => {
|
|
2367
|
-
|
|
3008
|
+
var _a;
|
|
3009
|
+
(_a = this._advancedDnDService) === null || _a === void 0 ? void 0 : _a.dispatchWillDragGroup(event);
|
|
2368
3010
|
}), view.model.onMove((event) => {
|
|
2369
3011
|
const { groupId, itemId, target, index, tabGroupId } = event;
|
|
2370
3012
|
this.moveGroupOrPanel({
|
|
@@ -2382,15 +3024,19 @@ export class DockviewComponent extends BaseGrid {
|
|
|
2382
3024
|
}), view.model.onDidDrop((event) => {
|
|
2383
3025
|
this._onDidDrop.fire(event);
|
|
2384
3026
|
}), view.model.onWillDrop((event) => {
|
|
2385
|
-
|
|
3027
|
+
var _a;
|
|
3028
|
+
(_a = this._advancedDnDService) === null || _a === void 0 ? void 0 : _a.dispatchWillDrop(event);
|
|
2386
3029
|
}), view.model.onWillShowOverlay((event) => {
|
|
3030
|
+
var _a;
|
|
2387
3031
|
if (this.options.disableDnd) {
|
|
3032
|
+
// Engine policy — stays in core, ahead of any
|
|
3033
|
+
// customisation dispatch.
|
|
2388
3034
|
event.preventDefault();
|
|
2389
3035
|
return;
|
|
2390
3036
|
}
|
|
2391
|
-
this.
|
|
2392
|
-
}), view.model.
|
|
2393
|
-
this.
|
|
3037
|
+
(_a = this._advancedDnDService) === null || _a === void 0 ? void 0 : _a.dispatchWillShowOverlay(event);
|
|
3038
|
+
}), view.model.onUnhandledDragOver((event) => {
|
|
3039
|
+
this._onUnhandledDragOver.fire(event);
|
|
2394
3040
|
}), view.model.onDidAddPanel((event) => {
|
|
2395
3041
|
if (this._moving) {
|
|
2396
3042
|
return;
|
|
@@ -2402,27 +3048,17 @@ export class DockviewComponent extends BaseGrid {
|
|
|
2402
3048
|
}
|
|
2403
3049
|
this._onDidRemovePanel.fire(event.panel);
|
|
2404
3050
|
}), view.model.onDidActivePanelChange((event) => {
|
|
3051
|
+
var _a;
|
|
2405
3052
|
if (this._moving) {
|
|
2406
3053
|
return;
|
|
2407
3054
|
}
|
|
2408
3055
|
if (event.panel !== this.activePanel) {
|
|
2409
3056
|
return;
|
|
2410
3057
|
}
|
|
2411
|
-
if (this._onDidActivePanelChange.value
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
this._onDidCreateTabGroup.fire(e);
|
|
2416
|
-
}), view.model.onDidDestroyTabGroup((e) => {
|
|
2417
|
-
this._onDidDestroyTabGroup.fire(e);
|
|
2418
|
-
}), view.model.onDidAddPanelToTabGroup((e) => {
|
|
2419
|
-
this._onDidAddPanelToTabGroup.fire(e);
|
|
2420
|
-
}), view.model.onDidRemovePanelFromTabGroup((e) => {
|
|
2421
|
-
this._onDidRemovePanelFromTabGroup.fire(e);
|
|
2422
|
-
}), view.model.onDidTabGroupChange((e) => {
|
|
2423
|
-
this._onDidTabGroupChange.fire(e);
|
|
2424
|
-
}), view.model.onDidTabGroupCollapsedChange((e) => {
|
|
2425
|
-
this._onDidTabGroupCollapsedChange.fire(e);
|
|
3058
|
+
if (((_a = this._onDidActivePanelChange.value) === null || _a === void 0 ? void 0 : _a.panel) !==
|
|
3059
|
+
event.panel) {
|
|
3060
|
+
this.fireActivePanelChange(event.panel);
|
|
3061
|
+
}
|
|
2426
3062
|
}), Event.any(view.model.onDidPanelTitleChange, view.model.onDidPanelParametersChange)(() => {
|
|
2427
3063
|
this._bufferOnDidLayoutChange.fire();
|
|
2428
3064
|
}));
|
|
@@ -2450,11 +3086,73 @@ export class DockviewComponent extends BaseGrid {
|
|
|
2450
3086
|
});
|
|
2451
3087
|
return panel;
|
|
2452
3088
|
}
|
|
2453
|
-
createGroupAtLocation(location, size, options) {
|
|
3089
|
+
createGroupAtLocation(location, size, options, gridview = this.gridview) {
|
|
2454
3090
|
const group = this.createGroup(options);
|
|
2455
|
-
this.doAddGroup(group, location, size);
|
|
3091
|
+
this.doAddGroup(group, location, size, gridview);
|
|
3092
|
+
this.setGroupLocationForRoot(group, gridview);
|
|
2456
3093
|
return group;
|
|
2457
3094
|
}
|
|
3095
|
+
/**
|
|
3096
|
+
* Tag a group with the location and render / drop-target containers
|
|
3097
|
+
* matching the gridview root it now lives in: the main grid, a floating
|
|
3098
|
+
* window (shares the main containers), or a popout window (uses its own
|
|
3099
|
+
* window-local containers).
|
|
3100
|
+
*/
|
|
3101
|
+
setGroupLocationForRoot(group, gridview) {
|
|
3102
|
+
var _a;
|
|
3103
|
+
const popout = (_a = this._popoutWindowService) === null || _a === void 0 ? void 0 : _a.entries.find((entry) => entry.gridview === gridview);
|
|
3104
|
+
if (popout) {
|
|
3105
|
+
if (group.model.renderContainer !== popout.overlayRenderContainer) {
|
|
3106
|
+
group.model.renderContainer = popout.overlayRenderContainer;
|
|
3107
|
+
}
|
|
3108
|
+
group.model.dropTargetContainer = popout.dropTargetContainer;
|
|
3109
|
+
group.model.location = {
|
|
3110
|
+
type: 'popout',
|
|
3111
|
+
getWindow: popout.getWindow,
|
|
3112
|
+
popoutUrl: popout.popoutUrl,
|
|
3113
|
+
};
|
|
3114
|
+
return;
|
|
3115
|
+
}
|
|
3116
|
+
// grid / floating both render through the main containers
|
|
3117
|
+
if (group.model.renderContainer !== this.overlayRenderContainer) {
|
|
3118
|
+
group.model.renderContainer = this.overlayRenderContainer;
|
|
3119
|
+
}
|
|
3120
|
+
group.model.dropTargetContainer = this.rootDropTargetContainer;
|
|
3121
|
+
group.model.location =
|
|
3122
|
+
gridview === this.gridview
|
|
3123
|
+
? { type: 'grid' }
|
|
3124
|
+
: { type: 'floating' };
|
|
3125
|
+
}
|
|
3126
|
+
/**
|
|
3127
|
+
* Resolve which gridview root currently owns a group: the main grid, or
|
|
3128
|
+
* the nested gridview of the floating / popout window it lives in.
|
|
3129
|
+
*/
|
|
3130
|
+
getGridviewForGroup(group) {
|
|
3131
|
+
var _a, _b;
|
|
3132
|
+
const floating = (_a = this._floatingGroupService) === null || _a === void 0 ? void 0 : _a.findByGroup(group);
|
|
3133
|
+
if (floating) {
|
|
3134
|
+
return floating.gridview;
|
|
3135
|
+
}
|
|
3136
|
+
// Use findByGroup (anchor-identity OR containment) for symmetry with
|
|
3137
|
+
// the floating branch — it also resolves an anchor whose element is
|
|
3138
|
+
// briefly detached from the gridview during a move/restore.
|
|
3139
|
+
const popout = (_b = this._popoutWindowService) === null || _b === void 0 ? void 0 : _b.findByGroup(group);
|
|
3140
|
+
if (popout) {
|
|
3141
|
+
return popout.gridview;
|
|
3142
|
+
}
|
|
3143
|
+
return this.gridview;
|
|
3144
|
+
}
|
|
3145
|
+
/**
|
|
3146
|
+
* The groups that live within the same floating / popout window as `group`
|
|
3147
|
+
* (including `group` itself). Empty when `group` is in the main grid.
|
|
3148
|
+
*/
|
|
3149
|
+
nestedWindowMembers(group) {
|
|
3150
|
+
const gridview = this.getGridviewForGroup(group);
|
|
3151
|
+
if (gridview === this.gridview) {
|
|
3152
|
+
return [];
|
|
3153
|
+
}
|
|
3154
|
+
return this.groups.filter((candidate) => gridview.element.contains(candidate.element));
|
|
3155
|
+
}
|
|
2458
3156
|
findGroup(panel) {
|
|
2459
3157
|
var _a;
|
|
2460
3158
|
return (_a = Array.from(this._groups.values()).find((group) => group.value.model.containsPanel(panel))) === null || _a === void 0 ? void 0 : _a.value;
|
|
@@ -2465,44 +3163,33 @@ export class DockviewComponent extends BaseGrid {
|
|
|
2465
3163
|
? rootOrientation
|
|
2466
3164
|
: orthogonal(rootOrientation);
|
|
2467
3165
|
}
|
|
2468
|
-
updateDropTargetModel(options) {
|
|
2469
|
-
if ('dndEdges' in options) {
|
|
2470
|
-
const disabled = typeof options.dndEdges === 'boolean' &&
|
|
2471
|
-
options.dndEdges === false;
|
|
2472
|
-
this._rootDropTarget.disabled = disabled;
|
|
2473
|
-
this._rootPointerDropTarget.disabled = disabled;
|
|
2474
|
-
if (typeof options.dndEdges === 'object' &&
|
|
2475
|
-
options.dndEdges !== null) {
|
|
2476
|
-
this._rootDropTarget.setOverlayModel(options.dndEdges);
|
|
2477
|
-
this._rootPointerDropTarget.setOverlayModel(options.dndEdges);
|
|
2478
|
-
}
|
|
2479
|
-
else {
|
|
2480
|
-
this._rootDropTarget.setOverlayModel(DEFAULT_ROOT_OVERLAY_MODEL);
|
|
2481
|
-
this._rootPointerDropTarget.setOverlayModel(DEFAULT_ROOT_OVERLAY_MODEL);
|
|
2482
|
-
}
|
|
2483
|
-
}
|
|
2484
|
-
if ('rootOverlayModel' in options) {
|
|
2485
|
-
this.updateDropTargetModel({ dndEdges: options.dndEdges });
|
|
2486
|
-
}
|
|
2487
|
-
}
|
|
2488
3166
|
updateTheme() {
|
|
2489
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
3167
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
2490
3168
|
const theme = (_a = this._options.theme) !== null && _a !== void 0 ? _a : themeAbyss;
|
|
2491
3169
|
// Apply the theme class only to the shell so edge groups and the
|
|
2492
3170
|
// main grid both inherit its CSS custom properties via the cascade.
|
|
2493
3171
|
// Re-declaring it on `.dv-dockview` would block consumer overrides
|
|
2494
3172
|
// set on the shell from reaching the dockview subtree.
|
|
2495
3173
|
(_b = this._shellThemeClassnames) === null || _b === void 0 ? void 0 : _b.setClassNames(theme.className);
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
3174
|
+
const gap = (_c = theme.gap) !== null && _c !== void 0 ? _c : 0;
|
|
3175
|
+
this.gridview.margin = gap;
|
|
3176
|
+
// Floating / popout windows host their own nested gridviews; keep their
|
|
3177
|
+
// gap in sync with the main grid when the theme changes at runtime.
|
|
3178
|
+
for (const floating of this.floatingGroups) {
|
|
3179
|
+
floating.gridview.margin = gap;
|
|
3180
|
+
}
|
|
3181
|
+
for (const entry of (_e = (_d = this._popoutWindowService) === null || _d === void 0 ? void 0 : _d.entries) !== null && _e !== void 0 ? _e : []) {
|
|
3182
|
+
entry.gridview.margin = gap;
|
|
3183
|
+
}
|
|
3184
|
+
(_f = this._shellManager) === null || _f === void 0 ? void 0 : _f.updateTheme(gap, (_g = theme.edgeGroupCollapsedSize) !== null && _g !== void 0 ? _g : 35);
|
|
3185
|
+
if (theme.dndOverlayBorder === undefined) {
|
|
2503
3186
|
this.element.style.removeProperty('--dv-drag-over-border');
|
|
2504
3187
|
(_h = this._shellManager) === null || _h === void 0 ? void 0 : _h.element.style.removeProperty('--dv-drag-over-border');
|
|
2505
3188
|
}
|
|
3189
|
+
else {
|
|
3190
|
+
this.element.style.setProperty('--dv-drag-over-border', theme.dndOverlayBorder);
|
|
3191
|
+
(_j = this._shellManager) === null || _j === void 0 ? void 0 : _j.element.style.setProperty('--dv-drag-over-border', theme.dndOverlayBorder);
|
|
3192
|
+
}
|
|
2506
3193
|
switch (theme.dndOverlayMounting) {
|
|
2507
3194
|
case 'absolute':
|
|
2508
3195
|
this.rootDropTargetContainer.disabled = false;
|
|
@@ -2514,7 +3201,7 @@ export class DockviewComponent extends BaseGrid {
|
|
|
2514
3201
|
}
|
|
2515
3202
|
// Toggle a CSS class so theme stylesheets can scope pure-CSS
|
|
2516
3203
|
// tab group indicator rules to the 'none' mode only.
|
|
2517
|
-
const indicatorNone = ((
|
|
3204
|
+
const indicatorNone = ((_k = theme.tabGroupIndicator) !== null && _k !== void 0 ? _k : 'wrap') === 'none';
|
|
2518
3205
|
toggleClass(this.element, 'dv-tab-group-indicator-none', indicatorNone);
|
|
2519
3206
|
if (this._shellManager) {
|
|
2520
3207
|
toggleClass(this._shellManager.element, 'dv-tab-group-indicator-none', indicatorNone);
|