dockview-core 8.1.0 → 8.2.0
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/dist/cjs/api/dockviewPanelApi.d.ts +12 -0
- package/dist/cjs/dockview/dockviewComponent.d.ts +62 -0
- package/dist/cjs/overlay/overlayRenderContainer.d.ts +13 -1
- package/dist/dockview-core.js +482 -102
- package/dist/dockview-core.min.js +2 -2
- package/dist/dockview-core.min.noStyle.js +2 -2
- package/dist/dockview-core.noStyle.js +482 -102
- package/dist/package/main.cjs.js +482 -102
- package/dist/package/main.cjs.min.js +2 -2
- package/dist/package/main.esm.min.mjs +2 -2
- package/dist/package/main.esm.mjs +482 -102
- package/package.json +1 -1
package/dist/dockview-core.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* dockview-core
|
|
3
|
-
* @version 8.
|
|
3
|
+
* @version 8.2.0
|
|
4
4
|
* @link https://github.com/dockview/dockview
|
|
5
5
|
* @license MIT
|
|
6
6
|
*/
|
|
@@ -10535,7 +10535,11 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
10535
10535
|
this.panels.forEach((panel) => {
|
|
10536
10536
|
this.rerender(panel);
|
|
10537
10537
|
});
|
|
10538
|
-
if (this._activePanel)
|
|
10538
|
+
if (this._activePanel) {
|
|
10539
|
+
this.contentContainer.renderPanel(this._activePanel, { asActive: true });
|
|
10540
|
+
const { width, height } = this.contentDimensions();
|
|
10541
|
+
this._activePanel.layout(width, height);
|
|
10542
|
+
}
|
|
10539
10543
|
}
|
|
10540
10544
|
get renderContainer() {
|
|
10541
10545
|
var _this$_overwriteRende;
|
|
@@ -11500,7 +11504,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
11500
11504
|
this._group = value;
|
|
11501
11505
|
this._onDidGroupChange.fire({});
|
|
11502
11506
|
this.setupGroupEventListeners(oldGroup);
|
|
11503
|
-
this.
|
|
11507
|
+
this.fireLocationChange();
|
|
11504
11508
|
}
|
|
11505
11509
|
}
|
|
11506
11510
|
get group() {
|
|
@@ -11576,6 +11580,23 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
11576
11580
|
exitMaximized() {
|
|
11577
11581
|
this.group.api.exitMaximized();
|
|
11578
11582
|
}
|
|
11583
|
+
/**
|
|
11584
|
+
* Report that this panel's location may have moved.
|
|
11585
|
+
*
|
|
11586
|
+
* A relocation touches the location more than once - the panel is
|
|
11587
|
+
* reparented into the destination group, then that group is tagged with
|
|
11588
|
+
* the location it ends up at - so the event is coalesced to the end of the
|
|
11589
|
+
* enclosing layout mutation and reports where the panel actually settled.
|
|
11590
|
+
* Firing each signal as it happened surfaced an intermediate `grid`
|
|
11591
|
+
* location the panel was never in, at a point where it was in neither
|
|
11592
|
+
* group's panel list. Outside a mutation this fires straight away.
|
|
11593
|
+
*/
|
|
11594
|
+
fireLocationChange() {
|
|
11595
|
+
this.accessor.deferLocationChange(this, () => {
|
|
11596
|
+
if (this.isDisposed) return;
|
|
11597
|
+
this._onDidLocationChange.fire({ location: this.location });
|
|
11598
|
+
});
|
|
11599
|
+
}
|
|
11579
11600
|
setupGroupEventListeners(previousGroup) {
|
|
11580
11601
|
var _previousGroup$isActi;
|
|
11581
11602
|
let _trackGroupActive = (_previousGroup$isActi = previousGroup === null || previousGroup === void 0 ? void 0 : previousGroup.isActive) !== null && _previousGroup$isActi !== void 0 ? _previousGroup$isActi : false;
|
|
@@ -11584,9 +11605,9 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
11584
11605
|
const hasBecomeVisible = event.isVisible && !this.isVisible;
|
|
11585
11606
|
const isActivePanel = this.group.model.isPanelActive(this.panel);
|
|
11586
11607
|
if (hasBecomeHidden || hasBecomeVisible && isActivePanel) this._onDidVisibilityChange.fire(event);
|
|
11587
|
-
}), this.group.api.onDidLocationChange((
|
|
11608
|
+
}), this.group.api.onDidLocationChange(() => {
|
|
11588
11609
|
if (this.group !== this.panel.group) return;
|
|
11589
|
-
this.
|
|
11610
|
+
this.fireLocationChange();
|
|
11590
11611
|
}), this.group.api.onDidActiveChange(() => {
|
|
11591
11612
|
if (this.group !== this.panel.group) return;
|
|
11592
11613
|
if (_trackGroupActive !== this.isGroupActive) {
|
|
@@ -13612,6 +13633,13 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
13612
13633
|
});
|
|
13613
13634
|
}
|
|
13614
13635
|
};
|
|
13636
|
+
/**
|
|
13637
|
+
* Placeholder handle marking "a reposition frame has been requested but the
|
|
13638
|
+
* real handle is not known yet". Never passed to `cancelAnimationFrame` in
|
|
13639
|
+
* practice — it is replaced within the same synchronous block — and harmless
|
|
13640
|
+
* if it were, since no frame carries this id.
|
|
13641
|
+
*/
|
|
13642
|
+
const SCHEDULED = -1;
|
|
13615
13643
|
function createFocusableElement() {
|
|
13616
13644
|
const element = document.createElement("div");
|
|
13617
13645
|
element.tabIndex = -1;
|
|
@@ -13624,12 +13652,13 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
13624
13652
|
this.accessor = accessor;
|
|
13625
13653
|
this.map = {};
|
|
13626
13654
|
this._disposed = false;
|
|
13655
|
+
this._generation = 0;
|
|
13627
13656
|
this.positionCache = new PositionCache();
|
|
13628
|
-
this.pendingUpdates = /* @__PURE__ */ new Set();
|
|
13629
13657
|
this.addDisposables(Disposable.from(() => {
|
|
13630
13658
|
for (const value of Object.values(this.map)) {
|
|
13631
13659
|
value.disposable.dispose();
|
|
13632
13660
|
value.destroy.dispose();
|
|
13661
|
+
this.cancelPendingUpdate(value);
|
|
13633
13662
|
}
|
|
13634
13663
|
this._disposed = true;
|
|
13635
13664
|
}));
|
|
@@ -13656,11 +13685,24 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
13656
13685
|
this.positionCache.invalidate();
|
|
13657
13686
|
(_entry$resize = entry.resize) === null || _entry$resize === void 0 || _entry$resize.call(entry);
|
|
13658
13687
|
}
|
|
13688
|
+
/**
|
|
13689
|
+
* Drop the reposition frame queued for a panel, if any. A queued frame is
|
|
13690
|
+
* bound to the reference container that was current when it was scheduled,
|
|
13691
|
+
* so it must be discarded whenever that container stops being the one the
|
|
13692
|
+
* overlay should track.
|
|
13693
|
+
*/
|
|
13694
|
+
cancelPendingUpdate(entry) {
|
|
13695
|
+
if (entry.pendingUpdate !== void 0) {
|
|
13696
|
+
cancelAnimationFrame(entry.pendingUpdate);
|
|
13697
|
+
entry.pendingUpdate = void 0;
|
|
13698
|
+
}
|
|
13699
|
+
}
|
|
13659
13700
|
detatch(panel) {
|
|
13660
13701
|
if (this.map[panel.api.id]) {
|
|
13661
|
-
const
|
|
13662
|
-
disposable.dispose();
|
|
13663
|
-
destroy.dispose();
|
|
13702
|
+
const entry = this.map[panel.api.id];
|
|
13703
|
+
entry.disposable.dispose();
|
|
13704
|
+
entry.destroy.dispose();
|
|
13705
|
+
this.cancelPendingUpdate(entry);
|
|
13664
13706
|
delete this.map[panel.api.id];
|
|
13665
13707
|
return true;
|
|
13666
13708
|
}
|
|
@@ -13676,22 +13718,73 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
13676
13718
|
panel,
|
|
13677
13719
|
disposable: Disposable.NONE,
|
|
13678
13720
|
destroy: Disposable.NONE,
|
|
13679
|
-
element
|
|
13721
|
+
element,
|
|
13722
|
+
retainPreviousGeometry: false,
|
|
13723
|
+
positioned: false,
|
|
13724
|
+
generation: ++this._generation
|
|
13680
13725
|
};
|
|
13681
13726
|
}
|
|
13682
|
-
const
|
|
13727
|
+
const mapEntry = this.map[panel.api.id];
|
|
13728
|
+
/**
|
|
13729
|
+
* A *change* of reference container supersedes the previous `attach`:
|
|
13730
|
+
* take a fresh generation so its `resize` closure can no longer run,
|
|
13731
|
+
* and drop the frame it queued against the old container. During
|
|
13732
|
+
* `fromJSON({ reuseExistingPanels: true })` that old container is a
|
|
13733
|
+
* detached staging group measuring 0x0, so leaving its frame in flight
|
|
13734
|
+
* both wastes the update and delays the reposition against the real one.
|
|
13735
|
+
*
|
|
13736
|
+
* Re-attaching over the *same* container (re-open, active panel change)
|
|
13737
|
+
* deliberately leaves scheduled work alone: `repositionPanelOverlay`
|
|
13738
|
+
* (the auto-hide peek) schedules a frame carrying the sticky
|
|
13739
|
+
* `forceVisible`/`clip` state which `attach` does not re-apply, and a
|
|
13740
|
+
* peeked panel's `api.isVisible` is false — so discarding that frame
|
|
13741
|
+
* leaves `visibilityChanged` to hide the overlay and the peek renders
|
|
13742
|
+
* nothing. A newly created entry already holds a fresh generation, so
|
|
13743
|
+
* the stale closures a `detatch` left behind are fenced off either way.
|
|
13744
|
+
*/
|
|
13745
|
+
if (mapEntry.referenceContainer !== referenceContainer) {
|
|
13746
|
+
mapEntry.generation = ++this._generation;
|
|
13747
|
+
this.cancelPendingUpdate(mapEntry);
|
|
13748
|
+
mapEntry.referenceContainer = referenceContainer;
|
|
13749
|
+
/**
|
|
13750
|
+
* Arm the retain flag only here: it means "a replacement reference
|
|
13751
|
+
* container is awaiting layout", so the 0x0 early-return below
|
|
13752
|
+
* holds the last good box rather than blanking the panel mid-move.
|
|
13753
|
+
* Arming it on every re-attach instead would make a container that
|
|
13754
|
+
* genuinely collapses to zero keep its stale geometry forever.
|
|
13755
|
+
*
|
|
13756
|
+
* Gated on `positioned` because an overlay that has never been
|
|
13757
|
+
* positioned has no left/top/width/height, and `.dv-render-overlay`
|
|
13758
|
+
* defaults to 100%/100% — retaining "previous" geometry there would
|
|
13759
|
+
* pin the content over the whole container.
|
|
13760
|
+
*/
|
|
13761
|
+
mapEntry.retainPreviousGeometry = mapEntry.positioned;
|
|
13762
|
+
}
|
|
13763
|
+
const generation = mapEntry.generation;
|
|
13764
|
+
const focusContainer = mapEntry.element;
|
|
13683
13765
|
const contentElement = panel.view.content.element;
|
|
13684
13766
|
if (contentElement.parentElement !== focusContainer) focusContainer.appendChild(contentElement);
|
|
13685
13767
|
if (focusContainer.parentElement !== this.element) this.element.appendChild(focusContainer);
|
|
13686
13768
|
const resize = () => {
|
|
13687
13769
|
const panelId = panel.api.id;
|
|
13688
|
-
|
|
13689
|
-
|
|
13690
|
-
|
|
13770
|
+
const scheduling = this.map[panelId];
|
|
13771
|
+
if ((scheduling === null || scheduling === void 0 ? void 0 : scheduling.generation) !== generation) return;
|
|
13772
|
+
if (scheduling.pendingUpdate !== void 0) return;
|
|
13773
|
+
/**
|
|
13774
|
+
* Claim the slot *before* scheduling. `requestAnimationFrame` is
|
|
13775
|
+
* shimmed to run inline by some hosts (and by several suites here),
|
|
13776
|
+
* in which case the callback below clears `pendingUpdate` while
|
|
13777
|
+
* this call is still on the stack — assigning the handle afterwards
|
|
13778
|
+
* would resurrect a slot that is already spent and block every
|
|
13779
|
+
* later reposition. The sentinel is replaced by the real handle
|
|
13780
|
+
* only if the frame has not already run.
|
|
13781
|
+
*/
|
|
13782
|
+
scheduling.pendingUpdate = SCHEDULED;
|
|
13783
|
+
const handle = requestAnimationFrame(() => {
|
|
13691
13784
|
var _entry$forceVisible;
|
|
13692
|
-
this.pendingUpdates.delete(panelId);
|
|
13693
13785
|
const entry = this.map[panelId];
|
|
13694
|
-
if (
|
|
13786
|
+
if (entry) entry.pendingUpdate = void 0;
|
|
13787
|
+
if (this.isDisposed || (entry === null || entry === void 0 ? void 0 : entry.generation) !== generation) return;
|
|
13695
13788
|
const forceVisible = (_entry$forceVisible = entry.forceVisible) !== null && _entry$forceVisible !== void 0 ? _entry$forceVisible : false;
|
|
13696
13789
|
const clip = entry.clip;
|
|
13697
13790
|
const box = this.positionCache.getPosition(referenceContainer.element);
|
|
@@ -13700,6 +13793,15 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
13700
13793
|
const top = box.top - box2.top;
|
|
13701
13794
|
const width = box.width;
|
|
13702
13795
|
const height = box.height;
|
|
13796
|
+
if (entry.retainPreviousGeometry && (width === 0 || height === 0)) {
|
|
13797
|
+
if (!panel.api.isVisible && !forceVisible) {
|
|
13798
|
+
focusContainer.style.visibility = "hidden";
|
|
13799
|
+
focusContainer.style.pointerEvents = "none";
|
|
13800
|
+
}
|
|
13801
|
+
return;
|
|
13802
|
+
}
|
|
13803
|
+
entry.retainPreviousGeometry = false;
|
|
13804
|
+
entry.positioned = true;
|
|
13703
13805
|
focusContainer.style.left = `${left}px`;
|
|
13704
13806
|
focusContainer.style.top = `${top}px`;
|
|
13705
13807
|
focusContainer.style.width = `${width}px`;
|
|
@@ -13728,11 +13830,30 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
13728
13830
|
} else focusContainer.style.clipPath = "";
|
|
13729
13831
|
toggleClass(focusContainer, "dv-render-overlay-float", panel.group.api.location.type === "floating");
|
|
13730
13832
|
});
|
|
13833
|
+
if (scheduling.pendingUpdate === SCHEDULED) scheduling.pendingUpdate = handle;
|
|
13731
13834
|
};
|
|
13732
13835
|
const visibilityChanged = () => {
|
|
13733
13836
|
if (panel.api.isVisible) {
|
|
13837
|
+
var _this$map$panel$api$i;
|
|
13734
13838
|
this.positionCache.invalidate();
|
|
13735
13839
|
resize();
|
|
13840
|
+
/**
|
|
13841
|
+
* Existing geometry is safe to show while its replacement lays
|
|
13842
|
+
* out. `retainPreviousGeometry` is only set when geometry has
|
|
13843
|
+
* actually been written (see `attach`), so this can never
|
|
13844
|
+
* un-hide an overlay whose left/top/width/height are unset —
|
|
13845
|
+
* `.dv-render-overlay` is 100%/100% by default and would
|
|
13846
|
+
* otherwise cover the whole dock.
|
|
13847
|
+
*
|
|
13848
|
+
* The retained geometry is the panel's position in the previous
|
|
13849
|
+
* layout, so restoring a layout that moves the panel does paint
|
|
13850
|
+
* it at stale coordinates until the reposition lands. That is
|
|
13851
|
+
* bounded to the next frame now that a superseded `attach` can
|
|
13852
|
+
* no longer swallow the reposition (see `attach`); showing
|
|
13853
|
+
* stale-but-real geometry for a frame is the deliberate
|
|
13854
|
+
* trade-off against blanking the panel for the whole rebuild.
|
|
13855
|
+
*/
|
|
13856
|
+
if ((_this$map$panel$api$i = this.map[panel.api.id]) === null || _this$map$panel$api$i === void 0 ? void 0 : _this$map$panel$api$i.retainPreviousGeometry) focusContainer.style.visibility = "";
|
|
13736
13857
|
focusContainer.style.pointerEvents = "";
|
|
13737
13858
|
} else {
|
|
13738
13859
|
focusContainer.style.visibility = "hidden";
|
|
@@ -13955,7 +14076,17 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
13955
14076
|
window: externalWindow
|
|
13956
14077
|
});
|
|
13957
14078
|
return new Promise((resolve, reject) => {
|
|
13958
|
-
externalWindow.addEventListener("unload", (
|
|
14079
|
+
externalWindow.addEventListener("unload", () => {});
|
|
14080
|
+
/**
|
|
14081
|
+
* `load` is the only event that resolves this promise with a
|
|
14082
|
+
* container, so a window that goes away first would leave the
|
|
14083
|
+
* caller awaiting a promise that never settles - and
|
|
14084
|
+
* `addPopoutGroup` holds its layout transaction open until it does.
|
|
14085
|
+
* Settle with `null` on close, the same signal a blocked popup
|
|
14086
|
+
* gives and one the caller already handles. `resolve` after the
|
|
14087
|
+
* fact is a no-op, so a `load` that arrived first still wins.
|
|
14088
|
+
*/
|
|
14089
|
+
disposable.addDisposables(_this.onWillClose(() => resolve(null)));
|
|
13959
14090
|
externalWindow.addEventListener("load", () => {
|
|
13960
14091
|
/**
|
|
13961
14092
|
* @see https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event
|
|
@@ -15373,6 +15504,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
15373
15504
|
this._onWillDrop = new Emitter();
|
|
15374
15505
|
this.onWillDrop = this._onWillDrop.event;
|
|
15375
15506
|
this._mutationDepth = 0;
|
|
15507
|
+
this._pendingLocationChanges = /* @__PURE__ */ new Map();
|
|
15376
15508
|
this._origin = "user";
|
|
15377
15509
|
this._originDepth = 0;
|
|
15378
15510
|
this._onWillMutateLayout = new Emitter();
|
|
@@ -15470,7 +15602,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
15470
15602
|
toggleClass(this.element, "dv-debug", !!options.debug);
|
|
15471
15603
|
this.updateTheme();
|
|
15472
15604
|
if (options.debug) this.addDisposables(new StrictEventsSequencing(this));
|
|
15473
|
-
this.addDisposables(this.rootDropTargetContainer, this.floatingDropTargetContainer, addDisposableListener(this._shellManager.element, "dragend", () => {
|
|
15605
|
+
this.addDisposables(Disposable.from(() => this._pendingLocationChanges.clear()), this.rootDropTargetContainer, this.floatingDropTargetContainer, addDisposableListener(this._shellManager.element, "dragend", () => {
|
|
15474
15606
|
var _this$rootDropTargetC2, _this$floatingDropTar;
|
|
15475
15607
|
(_this$rootDropTargetC2 = this.rootDropTargetContainer.model) === null || _this$rootDropTargetC2 === void 0 || _this$rootDropTargetC2.clear();
|
|
15476
15608
|
(_this$floatingDropTar = this.floatingDropTargetContainer.model) === null || _this$floatingDropTar === void 0 || _this$floatingDropTar.clear();
|
|
@@ -15544,7 +15676,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
15544
15676
|
return (_this$_popoutWindowSe3 = (_this$_popoutWindowSe4 = this._popoutWindowService) === null || _this$_popoutWindowSe4 === void 0 || (_this$_popoutWindowSe4 = _this$_popoutWindowSe4.findByGroup(group)) === null || _this$_popoutWindowSe4 === void 0 ? void 0 : _this$_popoutWindowSe4.popupService) !== null && _this$_popoutWindowSe3 !== void 0 ? _this$_popoutWindowSe3 : this.popupService;
|
|
15545
15677
|
}
|
|
15546
15678
|
addPopoutGroup(itemToPopout, options) {
|
|
15547
|
-
return this.
|
|
15679
|
+
return this.mutationAsync("popout", () => this._doAddPopoutGroup(itemToPopout, options));
|
|
15548
15680
|
}
|
|
15549
15681
|
/** Enumerate the popout groups currently open in their own windows. */
|
|
15550
15682
|
getPopouts() {
|
|
@@ -15641,15 +15773,32 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
15641
15773
|
}
|
|
15642
15774
|
};
|
|
15643
15775
|
let floatingBox;
|
|
15644
|
-
|
|
15645
|
-
|
|
15646
|
-
|
|
15647
|
-
|
|
15648
|
-
|
|
15776
|
+
/**
|
|
15777
|
+
* Popping out rehomes panels into `group`, so like the floating
|
|
15778
|
+
* case it owes the caller an `onDidMovePanel` per panel. The
|
|
15779
|
+
* events are deferred until the window is wired up so listeners
|
|
15780
|
+
* observe the panels' final `popout` location.
|
|
15781
|
+
*/
|
|
15782
|
+
let movedPanels = [];
|
|
15783
|
+
if (!(options === null || options === void 0 ? void 0 : options.overridePopoutGroup) && !(options === null || options === void 0 ? void 0 : options.overridePopoutGridview) && isGroupAddedToDom) if (itemToPopout instanceof DockviewPanel) {
|
|
15784
|
+
const sourceGroup = itemToPopout.group;
|
|
15785
|
+
this.movingLock(() => {
|
|
15786
|
+
const panel = referenceGroup.model.removePanel(itemToPopout);
|
|
15787
|
+
group.model.openPanel(panel);
|
|
15788
|
+
});
|
|
15789
|
+
movedPanels = [{
|
|
15790
|
+
panel: itemToPopout,
|
|
15791
|
+
from: sourceGroup
|
|
15792
|
+
}];
|
|
15793
|
+
} else {
|
|
15649
15794
|
this.movingLock(() => moveGroupWithoutDestroying({
|
|
15650
15795
|
from: referenceGroup,
|
|
15651
15796
|
to: group
|
|
15652
15797
|
}));
|
|
15798
|
+
movedPanels = group.panels.map((panel) => ({
|
|
15799
|
+
panel,
|
|
15800
|
+
from: referenceGroup
|
|
15801
|
+
}));
|
|
15653
15802
|
switch (referenceLocation) {
|
|
15654
15803
|
case "grid":
|
|
15655
15804
|
referenceGroup.api.setVisible(false);
|
|
@@ -15758,6 +15907,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
15758
15907
|
group: value.popoutGroup,
|
|
15759
15908
|
window: value.getWindow()
|
|
15760
15909
|
});
|
|
15910
|
+
for (const { panel, from } of movedPanels) this.fireDidMovePanel(panel, from);
|
|
15761
15911
|
return true;
|
|
15762
15912
|
}).catch((err) => {
|
|
15763
15913
|
console.error("dockview: failed to create popout.", err);
|
|
@@ -15835,6 +15985,16 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
15835
15985
|
const members = this.groups.filter((candidate) => popoutGridview.element.contains(candidate.element));
|
|
15836
15986
|
const anchorPresent = members.includes(group);
|
|
15837
15987
|
const anchorIsSoleMember = anchorPresent && members.length === 1;
|
|
15988
|
+
/**
|
|
15989
|
+
* Popping a group out fires `onDidMovePanel` per panel, so closing the
|
|
15990
|
+
* window owes the caller the same: every panel in it is rehomed, into
|
|
15991
|
+
* the reference group the popout left behind or into a fresh grid slot.
|
|
15992
|
+
* `movingLock` suppresses onDidAddPanel / onDidRemovePanel on these
|
|
15993
|
+
* paths, so `onDidMovePanel` is the only event that can carry it. The
|
|
15994
|
+
* events are deferred to the end so listeners observe the panels at
|
|
15995
|
+
* their final group and location.
|
|
15996
|
+
*/
|
|
15997
|
+
const movedPanels = [];
|
|
15838
15998
|
if (genuineClose) for (const member of members) {
|
|
15839
15999
|
if (member === group) continue;
|
|
15840
16000
|
this.movingLock(() => {
|
|
@@ -15845,12 +16005,21 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
15845
16005
|
});
|
|
15846
16006
|
this.redockGroupToMainGrid(member);
|
|
15847
16007
|
});
|
|
16008
|
+
for (const panel of member.panels) movedPanels.push({
|
|
16009
|
+
panel,
|
|
16010
|
+
from: member
|
|
16011
|
+
});
|
|
15848
16012
|
}
|
|
15849
16013
|
if (anchorPresent && isGroupAddedToDom && this.getPanel(referenceGroup.id)) {
|
|
16014
|
+
const rehomed = [...group.panels];
|
|
15850
16015
|
this.movingLock(() => moveGroupWithoutDestroying({
|
|
15851
16016
|
from: group,
|
|
15852
16017
|
to: referenceGroup
|
|
15853
16018
|
}));
|
|
16019
|
+
for (const panel of rehomed) movedPanels.push({
|
|
16020
|
+
panel,
|
|
16021
|
+
from: group
|
|
16022
|
+
});
|
|
15854
16023
|
if (!referenceGroup.api.isVisible) referenceGroup.api.setVisible(true);
|
|
15855
16024
|
if (this.getPanel(group.id)) this.doRemoveGroup(group, { skipPopoutAssociated: true });
|
|
15856
16025
|
} else if (anchorPresent && this.getPanel(group.id)) {
|
|
@@ -15881,10 +16050,15 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
15881
16050
|
this.movingLock(() => {
|
|
15882
16051
|
this.doAddGroup(group, [0]);
|
|
15883
16052
|
});
|
|
16053
|
+
for (const panel of group.panels) movedPanels.push({
|
|
16054
|
+
panel,
|
|
16055
|
+
from: group
|
|
16056
|
+
});
|
|
15884
16057
|
}
|
|
15885
16058
|
this.doSetGroupAndPanelActive(group);
|
|
15886
16059
|
}
|
|
15887
16060
|
disposePopoutGridview();
|
|
16061
|
+
for (const { panel, from } of movedPanels) this.fireDidMovePanel(panel, from);
|
|
15888
16062
|
}
|
|
15889
16063
|
addFloatingGroup(item, options) {
|
|
15890
16064
|
this.mutation("float", () => this._doAddFloatingGroup(item, options));
|
|
@@ -15893,7 +16067,15 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
15893
16067
|
if (!assertModule(this._floatingGroupService, "FloatingGroup", "api.addFloatingGroup")) return;
|
|
15894
16068
|
if (item instanceof DockviewGroupPanel && item.model.location.type === "edge") return;
|
|
15895
16069
|
let group;
|
|
16070
|
+
/**
|
|
16071
|
+
* Floating relocates panels exactly like a drop onto the grid does, so
|
|
16072
|
+
* it owes the caller an `onDidMovePanel` per panel. The events are
|
|
16073
|
+
* deferred until the window is mounted below: only then do the panels
|
|
16074
|
+
* report their final `floating` location.
|
|
16075
|
+
*/
|
|
16076
|
+
let movedPanels = [];
|
|
15896
16077
|
if (item instanceof DockviewPanel) {
|
|
16078
|
+
const sourceGroup = item.group;
|
|
15897
16079
|
group = this.createGroup();
|
|
15898
16080
|
this._onDidAddGroup.fire(group);
|
|
15899
16081
|
this.movingLock(() => this.removePanel(item, {
|
|
@@ -15902,6 +16084,10 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
15902
16084
|
skipSetActiveGroup: true
|
|
15903
16085
|
}));
|
|
15904
16086
|
this.movingLock(() => group.model.openPanel(item, { skipSetGroupActive: true }));
|
|
16087
|
+
movedPanels = [{
|
|
16088
|
+
panel: item,
|
|
16089
|
+
from: sourceGroup
|
|
16090
|
+
}];
|
|
15905
16091
|
} else {
|
|
15906
16092
|
var _this$_popoutWindowSe8;
|
|
15907
16093
|
group = item;
|
|
@@ -15918,11 +16104,21 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
15918
16104
|
});
|
|
15919
16105
|
this.doRemoveGroup(popoutReferenceGroup, { skipDispose: true });
|
|
15920
16106
|
group = popoutReferenceGroup;
|
|
15921
|
-
|
|
15922
|
-
|
|
15923
|
-
|
|
15924
|
-
|
|
15925
|
-
}
|
|
16107
|
+
movedPanels = group.panels.map((panel) => ({
|
|
16108
|
+
panel,
|
|
16109
|
+
from: item
|
|
16110
|
+
}));
|
|
16111
|
+
} else {
|
|
16112
|
+
this.doRemoveGroup(item, {
|
|
16113
|
+
skipDispose: true,
|
|
16114
|
+
skipPopoutReturn: true,
|
|
16115
|
+
skipPopoutAssociated: false
|
|
16116
|
+
});
|
|
16117
|
+
movedPanels = group.panels.map((panel) => ({
|
|
16118
|
+
panel,
|
|
16119
|
+
from: group
|
|
16120
|
+
}));
|
|
16121
|
+
}
|
|
15926
16122
|
}
|
|
15927
16123
|
function getAnchoredBox() {
|
|
15928
16124
|
if (options === null || options === void 0 ? void 0 : options.position) {
|
|
@@ -15955,6 +16151,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
15955
16151
|
skipActiveGroup: options === null || options === void 0 ? void 0 : options.skipActiveGroup,
|
|
15956
16152
|
disableSmartGuides: options === null || options === void 0 ? void 0 : options.disableSmartGuides
|
|
15957
16153
|
});
|
|
16154
|
+
for (const { panel, from } of movedPanels) this.fireDidMovePanel(panel, from);
|
|
15958
16155
|
}
|
|
15959
16156
|
/**
|
|
15960
16157
|
* Build an empty gridview configured to match the main grid's styling, for
|
|
@@ -16386,35 +16583,119 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
16386
16583
|
if (typeof data !== "object" || data === null) throw new Error("dockview: serialized layout must be a non-null object");
|
|
16387
16584
|
if (!data.grid || ((_data$grid$root = data.grid.root) === null || _data$grid$root === void 0 ? void 0 : _data$grid$root.type) !== "branch" || !Array.isArray(data.grid.root.data)) throw new Error("dockview: root must be of type branch");
|
|
16388
16585
|
const existingPanels = /* @__PURE__ */ new Map();
|
|
16389
|
-
|
|
16586
|
+
const temporaryGroups = /* @__PURE__ */ new Map();
|
|
16587
|
+
const stagedPanels = [];
|
|
16588
|
+
const temporaryGroupDisposables = [];
|
|
16589
|
+
/**
|
|
16590
|
+
* The staging groups are detached from `_groups` and never enter the
|
|
16591
|
+
* grid, so nothing else will ever tear them down.
|
|
16592
|
+
*
|
|
16593
|
+
* `dispose()` reaches consumer `IContentRenderer.dispose()`, so one
|
|
16594
|
+
* throwing renderer must not abort the rest of the cleanup — that would
|
|
16595
|
+
* re-introduce the very leak this reclaims — nor replace the
|
|
16596
|
+
* deserialization error the caller is being given. Draining the list
|
|
16597
|
+
* also makes this safe to call more than once.
|
|
16598
|
+
*/
|
|
16599
|
+
const disposeTemporaryGroups = () => {
|
|
16600
|
+
for (const disposable of temporaryGroupDisposables) try {
|
|
16601
|
+
disposable.dispose();
|
|
16602
|
+
} catch (err) {
|
|
16603
|
+
console.error("dockview: failed to dispose a temporary group created for reuseExistingPanels", err);
|
|
16604
|
+
}
|
|
16605
|
+
temporaryGroupDisposables.length = 0;
|
|
16606
|
+
};
|
|
16390
16607
|
if (options === null || options === void 0 ? void 0 : options.reuseExistingPanels) {
|
|
16391
16608
|
/**
|
|
16392
|
-
*
|
|
16393
|
-
*
|
|
16394
|
-
*
|
|
16395
|
-
* 2. Remove that temporary group from the group mapping so that it doesn't get cleared when we clear the layout
|
|
16609
|
+
* Visible, always-rendered panels need individual staging groups
|
|
16610
|
+
* to remain active. Other reused panels can share a staging group.
|
|
16611
|
+
* The staging groups are excluded from the layout clear below.
|
|
16396
16612
|
*/
|
|
16397
|
-
tempGroup = this.createGroup();
|
|
16398
|
-
this._groups.delete(tempGroup.api.id);
|
|
16399
16613
|
const newPanels = Object.keys(data.panels);
|
|
16400
|
-
|
|
16401
|
-
|
|
16402
|
-
|
|
16403
|
-
|
|
16404
|
-
|
|
16405
|
-
|
|
16406
|
-
|
|
16407
|
-
|
|
16408
|
-
|
|
16409
|
-
|
|
16410
|
-
|
|
16411
|
-
|
|
16412
|
-
|
|
16614
|
+
let sharedTemporaryGroup;
|
|
16615
|
+
const createTemporaryGroup = () => {
|
|
16616
|
+
const temporaryGroup = this.createGroup();
|
|
16617
|
+
/**
|
|
16618
|
+
* Removing the group from `_groups` also drops the record's
|
|
16619
|
+
* `CompositeDisposable`, so capture it first and tear both it
|
|
16620
|
+
* and the group down in the `finally` below. Left undisposed a
|
|
16621
|
+
* staging group leaks its `ResizeObserver`, its
|
|
16622
|
+
* `onDidOptionsChange` subscription (retained by this
|
|
16623
|
+
* component's emitter) and the watermark its model mounts when
|
|
16624
|
+
* the group empties — once per reused panel, per `fromJSON`.
|
|
16625
|
+
*/
|
|
16626
|
+
const record = this._groups.get(temporaryGroup.api.id);
|
|
16627
|
+
this._groups.delete(temporaryGroup.api.id);
|
|
16628
|
+
temporaryGroupDisposables.push(Disposable.from(() => {
|
|
16629
|
+
/**
|
|
16630
|
+
* Reclaim the group's own resources, never its panels.
|
|
16631
|
+
* Staging is driven by the ids in `data.panels` while
|
|
16632
|
+
* reclaiming is driven by the group `views` that
|
|
16633
|
+
* reference them, so a panel whose state is present but
|
|
16634
|
+
* unreferenced is still staged here — and `dispose()`
|
|
16635
|
+
* on a non-empty group reaches the consumer's
|
|
16636
|
+
* `IContentRenderer.dispose()`. Emptying the group
|
|
16637
|
+
* first leaves those panels exactly as they were before
|
|
16638
|
+
* this teardown existed, which also keeps this safe
|
|
16639
|
+
* against any future path that rebuilds a panel under
|
|
16640
|
+
* an id that is live in the new layout.
|
|
16641
|
+
*/
|
|
16642
|
+
this.movingLock(() => {
|
|
16643
|
+
for (const panel of temporaryGroup.panels.slice()) temporaryGroup.model.removePanel(panel);
|
|
16644
|
+
});
|
|
16645
|
+
record === null || record === void 0 || record.disposable.dispose();
|
|
16646
|
+
temporaryGroup.dispose();
|
|
16647
|
+
}));
|
|
16648
|
+
return temporaryGroup;
|
|
16649
|
+
};
|
|
16650
|
+
/**
|
|
16651
|
+
* Staging and the clear below run before the deserialization
|
|
16652
|
+
* `try`, so a throw here (a consumer `onDidRemovePanel` handler, a
|
|
16653
|
+
* renderer teardown during `clear`) would escape without reclaiming
|
|
16654
|
+
* the staging groups already created.
|
|
16655
|
+
*
|
|
16656
|
+
* The creation loop is inside the guard too, not just the moves and
|
|
16657
|
+
* the clear: `createGroup()` reaches consumer code of its own —
|
|
16658
|
+
* `initialize()` mounts the watermark through
|
|
16659
|
+
* `createWatermarkComponent()` — so a throw on the n-th panel would
|
|
16660
|
+
* otherwise strand the n-1 staging groups already built.
|
|
16661
|
+
*/
|
|
16662
|
+
try {
|
|
16663
|
+
for (const panel of this.panels) if (newPanels.includes(panel.api.id)) {
|
|
16664
|
+
existingPanels.set(panel.api.id, panel);
|
|
16665
|
+
let temporaryGroup;
|
|
16666
|
+
if (panel.api.renderer === "always" && panel.api.isVisible) temporaryGroup = createTemporaryGroup();
|
|
16667
|
+
else {
|
|
16668
|
+
var _sharedTemporaryGroup;
|
|
16669
|
+
(_sharedTemporaryGroup = sharedTemporaryGroup) !== null && _sharedTemporaryGroup !== void 0 || (sharedTemporaryGroup = createTemporaryGroup());
|
|
16670
|
+
temporaryGroup = sharedTemporaryGroup;
|
|
16671
|
+
}
|
|
16672
|
+
temporaryGroups.set(panel.api.id, temporaryGroup);
|
|
16673
|
+
stagedPanels.push({
|
|
16674
|
+
panel,
|
|
16675
|
+
temporaryGroup
|
|
16676
|
+
});
|
|
16677
|
+
}
|
|
16678
|
+
this.movingLock(() => {
|
|
16679
|
+
stagedPanels.forEach(({ panel, temporaryGroup }) => {
|
|
16680
|
+
this.moveGroupOrPanel({
|
|
16681
|
+
from: {
|
|
16682
|
+
groupId: panel.api.group.api.id,
|
|
16683
|
+
panelId: panel.api.id
|
|
16684
|
+
},
|
|
16685
|
+
to: {
|
|
16686
|
+
group: temporaryGroup,
|
|
16687
|
+
position: "center"
|
|
16688
|
+
},
|
|
16689
|
+
keepEmptyGroups: true
|
|
16690
|
+
});
|
|
16413
16691
|
});
|
|
16414
16692
|
});
|
|
16415
|
-
|
|
16416
|
-
|
|
16417
|
-
|
|
16693
|
+
this.clear();
|
|
16694
|
+
} catch (err) {
|
|
16695
|
+
disposeTemporaryGroups();
|
|
16696
|
+
throw err;
|
|
16697
|
+
}
|
|
16698
|
+
} else this.clear();
|
|
16418
16699
|
const { grid, panels, activeGroup } = data;
|
|
16419
16700
|
try {
|
|
16420
16701
|
var _data$floatingGroups, _data$popoutGroups, _this$_popoutWindowSe12, _this$_floatingGroupS5, _this$_watermarkServi2;
|
|
@@ -16446,9 +16727,10 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
16446
16727
|
* due to a corruption of input data.
|
|
16447
16728
|
*/
|
|
16448
16729
|
const existingPanel = existingPanels.get(child);
|
|
16449
|
-
|
|
16730
|
+
const temporaryGroup = temporaryGroups.get(child);
|
|
16731
|
+
if (temporaryGroup && existingPanel) {
|
|
16450
16732
|
this.movingLock(() => {
|
|
16451
|
-
|
|
16733
|
+
temporaryGroup.model.removePanel(existingPanel);
|
|
16452
16734
|
});
|
|
16453
16735
|
createdPanels.push(existingPanel);
|
|
16454
16736
|
existingPanel.updateFromStateModel(panels[child]);
|
|
@@ -16478,7 +16760,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
16478
16760
|
return createGroupFromSerializedState(node.data);
|
|
16479
16761
|
} });
|
|
16480
16762
|
this._layoutFromShell(width, height);
|
|
16481
|
-
if (data.edgeGroups) this.deserializeEdgeGroups(data.edgeGroups, panels);
|
|
16763
|
+
if (data.edgeGroups) this.deserializeEdgeGroups(data.edgeGroups, panels, existingPanels, temporaryGroups);
|
|
16482
16764
|
this.deserializeFloatingWindows((_data$floatingGroups = data.floatingGroups) !== null && _data$floatingGroups !== void 0 ? _data$floatingGroups : [], createGroupFromSerializedState);
|
|
16483
16765
|
const popoutPromises = this.deserializePopoutWindows((_data$popoutGroups = data.popoutGroups) !== null && _data$popoutGroups !== void 0 ? _data$popoutGroups : [], createGroupFromSerializedState);
|
|
16484
16766
|
(_this$_popoutWindowSe12 = this._popoutWindowService) === null || _this$_popoutWindowSe12 === void 0 || _this$_popoutWindowSe12.finishRestoration(popoutPromises);
|
|
@@ -16515,6 +16797,8 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
16515
16797
|
* expect trying to load a corrupted layout to result in an error and not silently fail...
|
|
16516
16798
|
*/
|
|
16517
16799
|
throw err;
|
|
16800
|
+
} finally {
|
|
16801
|
+
disposeTemporaryGroups();
|
|
16518
16802
|
}
|
|
16519
16803
|
this.debouncedUpdateAllPositions();
|
|
16520
16804
|
this._onDidLayoutFromJSON.fire();
|
|
@@ -16537,7 +16821,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
16537
16821
|
members
|
|
16538
16822
|
};
|
|
16539
16823
|
}
|
|
16540
|
-
deserializeEdgeGroups(edgeGroups, panels) {
|
|
16824
|
+
deserializeEdgeGroups(edgeGroups, panels, existingPanels, temporaryGroups) {
|
|
16541
16825
|
const edgeService = assertModule(this._edgeGroupService, "EdgeGroup", "fromJSON edge restoration");
|
|
16542
16826
|
if (!edgeService) return;
|
|
16543
16827
|
for (const _position of [
|
|
@@ -16567,13 +16851,40 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
16567
16851
|
if (groupState) {
|
|
16568
16852
|
const { views, activeView } = groupState;
|
|
16569
16853
|
const createdPanels = [];
|
|
16570
|
-
for (const panelId of views)
|
|
16571
|
-
|
|
16572
|
-
|
|
16854
|
+
for (const panelId of views) {
|
|
16855
|
+
if (!panels[panelId]) continue;
|
|
16856
|
+
/**
|
|
16857
|
+
* Reclaim a staged panel rather than rebuilding it, the
|
|
16858
|
+
* same way the grid path does. Deserializing here instead
|
|
16859
|
+
* would honour `reuseExistingPanels` everywhere except edge
|
|
16860
|
+
* groups: the live panel keeps sitting in its staging group
|
|
16861
|
+
* while a second panel is built under the same id, so the
|
|
16862
|
+
* consumer's renderer for the original is orphaned — never
|
|
16863
|
+
* disposed, and its element left inside the id-keyed
|
|
16864
|
+
* overlay entry the replacement now shares.
|
|
16865
|
+
*/
|
|
16866
|
+
const existingPanel = existingPanels.get(panelId);
|
|
16867
|
+
const temporaryGroup = temporaryGroups.get(panelId);
|
|
16868
|
+
if (temporaryGroup && existingPanel) {
|
|
16869
|
+
this.movingLock(() => {
|
|
16870
|
+
temporaryGroup.model.removePanel(existingPanel);
|
|
16871
|
+
});
|
|
16872
|
+
createdPanels.push(existingPanel);
|
|
16873
|
+
existingPanel.updateFromStateModel(panels[panelId]);
|
|
16874
|
+
} else {
|
|
16875
|
+
const panel = this._deserializer.fromJSON(panels[panelId], edgeGroup);
|
|
16876
|
+
createdPanels.push(panel);
|
|
16877
|
+
}
|
|
16573
16878
|
}
|
|
16574
16879
|
for (const panel of createdPanels) {
|
|
16575
16880
|
const isActive = activeView === panel.id;
|
|
16576
|
-
|
|
16881
|
+
if (existingPanels.has(panel.api.id)) this.movingLock(() => {
|
|
16882
|
+
edgeGroup.model.openPanel(panel, {
|
|
16883
|
+
skipSetActive: !isActive,
|
|
16884
|
+
skipSetGroupActive: true
|
|
16885
|
+
});
|
|
16886
|
+
});
|
|
16887
|
+
else edgeGroup.model.openPanel(panel, {
|
|
16577
16888
|
skipSetActive: !isActive,
|
|
16578
16889
|
skipSetGroupActive: true
|
|
16579
16890
|
});
|
|
@@ -16997,22 +17308,100 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
16997
17308
|
* outermost mutation.
|
|
16998
17309
|
*/
|
|
16999
17310
|
mutation(kind, func) {
|
|
17000
|
-
const
|
|
17311
|
+
const close = this.openMutation(kind);
|
|
17312
|
+
try {
|
|
17313
|
+
return func();
|
|
17314
|
+
} finally {
|
|
17315
|
+
close();
|
|
17316
|
+
}
|
|
17317
|
+
}
|
|
17318
|
+
/**
|
|
17319
|
+
* `mutation()` for an operation whose work continues after the synchronous
|
|
17320
|
+
* call returns. The transaction stays open until the returned promise
|
|
17321
|
+
* settles, so everything the operation does - the group it adds, the panels
|
|
17322
|
+
* it relocates - lands inside the bracket, matching the synchronous
|
|
17323
|
+
* move / float paths.
|
|
17324
|
+
*/
|
|
17325
|
+
mutationAsync(kind, func) {
|
|
17326
|
+
var _this = this;
|
|
17327
|
+
return _asyncToGenerator(function* () {
|
|
17328
|
+
const close = _this.openMutation(kind);
|
|
17329
|
+
try {
|
|
17330
|
+
return yield func();
|
|
17331
|
+
} finally {
|
|
17332
|
+
close();
|
|
17333
|
+
}
|
|
17334
|
+
})();
|
|
17335
|
+
}
|
|
17336
|
+
/**
|
|
17337
|
+
* Open a transaction and return the function that closes it. Shared by the
|
|
17338
|
+
* synchronous and asynchronous brackets; the returned function must be
|
|
17339
|
+
* called exactly once.
|
|
17340
|
+
*
|
|
17341
|
+
* Both ends key off the depth counter reaching zero rather than off which
|
|
17342
|
+
* bracket opened first. For synchronous nesting the two are the same thing
|
|
17343
|
+
* - brackets close in the order they opened - but asynchronous transactions
|
|
17344
|
+
* can *overlap* rather than nest (two `addPopoutGroup` calls in flight at
|
|
17345
|
+
* once, or a restore staggering several), and there the first to open is
|
|
17346
|
+
* not the last to close. Reporting on the opener would fire `didMutate`
|
|
17347
|
+
* while the other transaction was still doing structural work, which is the
|
|
17348
|
+
* very thing the async bracket exists to prevent. Overlapping transactions
|
|
17349
|
+
* therefore report as one, tagged with the kind of the last to finish.
|
|
17350
|
+
*/
|
|
17351
|
+
openMutation(kind) {
|
|
17001
17352
|
const origin = this._origin;
|
|
17002
|
-
if (
|
|
17353
|
+
if (this._mutationDepth === 0) this._onWillMutateLayout.fire({
|
|
17003
17354
|
kind,
|
|
17004
17355
|
origin
|
|
17005
17356
|
});
|
|
17006
17357
|
this._mutationDepth++;
|
|
17007
|
-
|
|
17008
|
-
return func();
|
|
17009
|
-
} finally {
|
|
17358
|
+
return () => {
|
|
17010
17359
|
this._mutationDepth--;
|
|
17011
|
-
if (
|
|
17012
|
-
|
|
17013
|
-
|
|
17014
|
-
|
|
17360
|
+
if (this._mutationDepth === 0) {
|
|
17361
|
+
this.flushLocationChanges();
|
|
17362
|
+
this._onDidMutateLayout.fire({
|
|
17363
|
+
kind,
|
|
17364
|
+
origin
|
|
17365
|
+
});
|
|
17366
|
+
}
|
|
17367
|
+
};
|
|
17368
|
+
}
|
|
17369
|
+
/**
|
|
17370
|
+
* Coalesce a panel's `onDidLocationChange` to the end of the enclosing
|
|
17371
|
+
* transaction, or fire it immediately when no transaction is in flight.
|
|
17372
|
+
*
|
|
17373
|
+
* Relocating a panel touches its location twice: once as it is reparented
|
|
17374
|
+
* into the destination group - which, when that group has just been created
|
|
17375
|
+
* for a floating or popout window, has not been told where it lives yet -
|
|
17376
|
+
* and once as the group is tagged with its final location. Reporting each
|
|
17377
|
+
* signal as it happens therefore leaks an intermediate `grid` location the
|
|
17378
|
+
* panel was never in, at a moment when it belongs to neither group's panel
|
|
17379
|
+
* list and so is missing from `api.panels`.
|
|
17380
|
+
*
|
|
17381
|
+
* Deferring collapses those signals into a single event carrying the
|
|
17382
|
+
* settled location. Note the signals are deliberately *not* compared
|
|
17383
|
+
* against the panel's previous location: a panel can move between two
|
|
17384
|
+
* floating windows without its location type changing, and this event is
|
|
17385
|
+
* the only signal `OverlayRenderContainer` has to re-resolve the panel's
|
|
17386
|
+
* z-index against its new host window.
|
|
17387
|
+
*/
|
|
17388
|
+
deferLocationChange(key, fire) {
|
|
17389
|
+
if (this._mutationDepth === 0) {
|
|
17390
|
+
fire();
|
|
17391
|
+
return;
|
|
17015
17392
|
}
|
|
17393
|
+
this._pendingLocationChanges.set(key, fire);
|
|
17394
|
+
}
|
|
17395
|
+
/**
|
|
17396
|
+
* Report every panel whose location moved during the transaction that has
|
|
17397
|
+
* just closed. Each callback reads the panel's location at this point, so
|
|
17398
|
+
* what it reports is where the panel ended up.
|
|
17399
|
+
*/
|
|
17400
|
+
flushLocationChanges() {
|
|
17401
|
+
if (this._pendingLocationChanges.size === 0) return;
|
|
17402
|
+
const pending = Array.from(this._pendingLocationChanges.values());
|
|
17403
|
+
this._pendingLocationChanges.clear();
|
|
17404
|
+
for (const fire of pending) fire();
|
|
17016
17405
|
}
|
|
17017
17406
|
/**
|
|
17018
17407
|
* The origin of the operation currently in progress (`'user'` by default).
|
|
@@ -17053,6 +17442,18 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
17053
17442
|
origin: this._origin
|
|
17054
17443
|
});
|
|
17055
17444
|
}
|
|
17445
|
+
/**
|
|
17446
|
+
* Announce that `panel` has finished relocating. Must be called once the
|
|
17447
|
+
* move has settled: `to` is read from the panel's current group, so an
|
|
17448
|
+
* early call would report the source group as the destination.
|
|
17449
|
+
*/
|
|
17450
|
+
fireDidMovePanel(panel, from) {
|
|
17451
|
+
this._onDidMovePanel.fire({
|
|
17452
|
+
panel,
|
|
17453
|
+
from,
|
|
17454
|
+
to: panel.group
|
|
17455
|
+
});
|
|
17456
|
+
}
|
|
17056
17457
|
moveGroupOrPanel(options) {
|
|
17057
17458
|
this.mutation("move", () => this._doMoveGroupOrPanel(options));
|
|
17058
17459
|
}
|
|
@@ -17113,10 +17514,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
17113
17514
|
});
|
|
17114
17515
|
});
|
|
17115
17516
|
if (!options.skipSetActive) this.doSetGroupAndPanelActive(destinationGroup);
|
|
17116
|
-
this.
|
|
17117
|
-
panel: removedPanel,
|
|
17118
|
-
from: sourceGroup
|
|
17119
|
-
});
|
|
17517
|
+
this.fireDidMovePanel(removedPanel, sourceGroup);
|
|
17120
17518
|
} else {
|
|
17121
17519
|
/**
|
|
17122
17520
|
* Dropping a panel to the extremities of a group which will place that panel
|
|
@@ -17135,10 +17533,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
17135
17533
|
const [sourceParentLocation, from] = tail(getGridLocation(sourceGroup.element));
|
|
17136
17534
|
if (sequenceEquals(sourceParentLocation, targetParentLocation)) {
|
|
17137
17535
|
this.gridview.moveView(sourceParentLocation, from, to);
|
|
17138
|
-
this.
|
|
17139
|
-
panel: this.getGroupPanel(sourceItemId),
|
|
17140
|
-
from: sourceGroup
|
|
17141
|
-
});
|
|
17536
|
+
this.fireDidMovePanel(this.getGroupPanel(sourceItemId), sourceGroup);
|
|
17142
17537
|
return;
|
|
17143
17538
|
}
|
|
17144
17539
|
}
|
|
@@ -17169,10 +17564,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
17169
17564
|
const newGroup = this.createGroupAtLocation(updatedTargetLocation, void 0, void 0, destinationGridview);
|
|
17170
17565
|
this.movingLock(() => newGroup.model.openPanel(removedPanel, { skipSetActive: true }));
|
|
17171
17566
|
this.doSetGroupAndPanelActive(newGroup);
|
|
17172
|
-
this.
|
|
17173
|
-
panel: this.getGroupPanel(sourceItemId),
|
|
17174
|
-
from: sourceGroup
|
|
17175
|
-
});
|
|
17567
|
+
this.fireDidMovePanel(this.getGroupPanel(sourceItemId), sourceGroup);
|
|
17176
17568
|
return;
|
|
17177
17569
|
}
|
|
17178
17570
|
if (sourceGroup.api.location.type === "edge") {
|
|
@@ -17189,10 +17581,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
17189
17581
|
const newGroup = this.createGroupAtLocation(targetLocation, void 0, void 0, destinationGridview);
|
|
17190
17582
|
this.movingLock(() => newGroup.model.openPanel(removedPanel, { skipSetGroupActive: true }));
|
|
17191
17583
|
this.doSetGroupAndPanelActive(newGroup);
|
|
17192
|
-
this.
|
|
17193
|
-
panel: removedPanel,
|
|
17194
|
-
from: sourceGroup
|
|
17195
|
-
});
|
|
17584
|
+
this.fireDidMovePanel(removedPanel, sourceGroup);
|
|
17196
17585
|
return;
|
|
17197
17586
|
}
|
|
17198
17587
|
const targetGroup = this.movingLock(() => this.doRemoveGroup(sourceGroup, {
|
|
@@ -17204,10 +17593,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
17204
17593
|
this.movingLock(() => this.doAddGroup(targetGroup, location, void 0, destinationGridview));
|
|
17205
17594
|
this.setGroupLocationForRoot(targetGroup, destinationGridview);
|
|
17206
17595
|
this.doSetGroupAndPanelActive(targetGroup);
|
|
17207
|
-
this.
|
|
17208
|
-
panel: this.getGroupPanel(sourceItemId),
|
|
17209
|
-
from: sourceGroup
|
|
17210
|
-
});
|
|
17596
|
+
this.fireDidMovePanel(this.getGroupPanel(sourceItemId), sourceGroup);
|
|
17211
17597
|
} else {
|
|
17212
17598
|
/**
|
|
17213
17599
|
* The group we are removing from has many panels, we need to remove the panels we are moving,
|
|
@@ -17222,10 +17608,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
17222
17608
|
const group = this.createGroupAtLocation(dropLocation, void 0, void 0, destinationGridview);
|
|
17223
17609
|
this.movingLock(() => group.model.openPanel(removedPanel, { skipSetGroupActive: true }));
|
|
17224
17610
|
this.doSetGroupAndPanelActive(group);
|
|
17225
|
-
this.
|
|
17226
|
-
panel: removedPanel,
|
|
17227
|
-
from: sourceGroup
|
|
17228
|
-
});
|
|
17611
|
+
this.fireDidMovePanel(removedPanel, sourceGroup);
|
|
17229
17612
|
}
|
|
17230
17613
|
}
|
|
17231
17614
|
}
|
|
@@ -17260,10 +17643,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
17260
17643
|
});
|
|
17261
17644
|
for (const panel of removedPanels) targetGroup.model.addPanelToTabGroup(newTabGroup.id, panel.id);
|
|
17262
17645
|
if (!options.skipSetActive) this.doSetGroupAndPanelActive(targetGroup);
|
|
17263
|
-
for (const panel of removedPanels) this.
|
|
17264
|
-
panel,
|
|
17265
|
-
from: sourceGroup
|
|
17266
|
-
});
|
|
17646
|
+
for (const panel of removedPanels) this.fireDidMovePanel(panel, sourceGroup);
|
|
17267
17647
|
};
|
|
17268
17648
|
let targetGroup;
|
|
17269
17649
|
if (!destinationTarget || destinationTarget === "center" || !referenceLocation) targetGroup = destinationGroup;
|
|
@@ -17284,10 +17664,12 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
17284
17664
|
this.mutation("maximize", () => super.exitMaximizedGroup());
|
|
17285
17665
|
}
|
|
17286
17666
|
_doMoveGroup(options) {
|
|
17667
|
+
var _mergedPanels;
|
|
17287
17668
|
const from = options.from.group;
|
|
17288
17669
|
const to = options.to.group;
|
|
17289
17670
|
const target = options.to.position;
|
|
17290
17671
|
let source = from;
|
|
17672
|
+
let mergedPanels;
|
|
17291
17673
|
if (target === "center") {
|
|
17292
17674
|
const activePanel = from.activePanel;
|
|
17293
17675
|
const tabGroupSnapshots = from.model.getTabGroups().map((tg) => ({
|
|
@@ -17305,6 +17687,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
17305
17687
|
skipSetGroupActive: true
|
|
17306
17688
|
});
|
|
17307
17689
|
});
|
|
17690
|
+
mergedPanels = panels;
|
|
17308
17691
|
for (const snapshot of tabGroupSnapshots) {
|
|
17309
17692
|
const newTabGroup = to.model.createTabGroup({
|
|
17310
17693
|
label: snapshot.label,
|
|
@@ -17394,11 +17777,8 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
17394
17777
|
this.setGroupLocationForRoot(source, destGridview);
|
|
17395
17778
|
}
|
|
17396
17779
|
}
|
|
17397
|
-
source.panels.forEach((panel) => {
|
|
17398
|
-
this.
|
|
17399
|
-
panel,
|
|
17400
|
-
from
|
|
17401
|
-
});
|
|
17780
|
+
((_mergedPanels = mergedPanels) !== null && _mergedPanels !== void 0 ? _mergedPanels : source.panels).forEach((panel) => {
|
|
17781
|
+
this.fireDidMovePanel(panel, from);
|
|
17402
17782
|
});
|
|
17403
17783
|
this.debouncedUpdateAllPositions();
|
|
17404
17784
|
if (options.skipSetActive === false) {
|