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
|
@@ -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
|
*/
|
|
@@ -10527,7 +10527,11 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
10527
10527
|
this.panels.forEach((panel) => {
|
|
10528
10528
|
this.rerender(panel);
|
|
10529
10529
|
});
|
|
10530
|
-
if (this._activePanel)
|
|
10530
|
+
if (this._activePanel) {
|
|
10531
|
+
this.contentContainer.renderPanel(this._activePanel, { asActive: true });
|
|
10532
|
+
const { width, height } = this.contentDimensions();
|
|
10533
|
+
this._activePanel.layout(width, height);
|
|
10534
|
+
}
|
|
10531
10535
|
}
|
|
10532
10536
|
get renderContainer() {
|
|
10533
10537
|
var _this$_overwriteRende;
|
|
@@ -11492,7 +11496,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
11492
11496
|
this._group = value;
|
|
11493
11497
|
this._onDidGroupChange.fire({});
|
|
11494
11498
|
this.setupGroupEventListeners(oldGroup);
|
|
11495
|
-
this.
|
|
11499
|
+
this.fireLocationChange();
|
|
11496
11500
|
}
|
|
11497
11501
|
}
|
|
11498
11502
|
get group() {
|
|
@@ -11568,6 +11572,23 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
11568
11572
|
exitMaximized() {
|
|
11569
11573
|
this.group.api.exitMaximized();
|
|
11570
11574
|
}
|
|
11575
|
+
/**
|
|
11576
|
+
* Report that this panel's location may have moved.
|
|
11577
|
+
*
|
|
11578
|
+
* A relocation touches the location more than once - the panel is
|
|
11579
|
+
* reparented into the destination group, then that group is tagged with
|
|
11580
|
+
* the location it ends up at - so the event is coalesced to the end of the
|
|
11581
|
+
* enclosing layout mutation and reports where the panel actually settled.
|
|
11582
|
+
* Firing each signal as it happened surfaced an intermediate `grid`
|
|
11583
|
+
* location the panel was never in, at a point where it was in neither
|
|
11584
|
+
* group's panel list. Outside a mutation this fires straight away.
|
|
11585
|
+
*/
|
|
11586
|
+
fireLocationChange() {
|
|
11587
|
+
this.accessor.deferLocationChange(this, () => {
|
|
11588
|
+
if (this.isDisposed) return;
|
|
11589
|
+
this._onDidLocationChange.fire({ location: this.location });
|
|
11590
|
+
});
|
|
11591
|
+
}
|
|
11571
11592
|
setupGroupEventListeners(previousGroup) {
|
|
11572
11593
|
var _previousGroup$isActi;
|
|
11573
11594
|
let _trackGroupActive = (_previousGroup$isActi = previousGroup === null || previousGroup === void 0 ? void 0 : previousGroup.isActive) !== null && _previousGroup$isActi !== void 0 ? _previousGroup$isActi : false;
|
|
@@ -11576,9 +11597,9 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
11576
11597
|
const hasBecomeVisible = event.isVisible && !this.isVisible;
|
|
11577
11598
|
const isActivePanel = this.group.model.isPanelActive(this.panel);
|
|
11578
11599
|
if (hasBecomeHidden || hasBecomeVisible && isActivePanel) this._onDidVisibilityChange.fire(event);
|
|
11579
|
-
}), this.group.api.onDidLocationChange((
|
|
11600
|
+
}), this.group.api.onDidLocationChange(() => {
|
|
11580
11601
|
if (this.group !== this.panel.group) return;
|
|
11581
|
-
this.
|
|
11602
|
+
this.fireLocationChange();
|
|
11582
11603
|
}), this.group.api.onDidActiveChange(() => {
|
|
11583
11604
|
if (this.group !== this.panel.group) return;
|
|
11584
11605
|
if (_trackGroupActive !== this.isGroupActive) {
|
|
@@ -13604,6 +13625,13 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
13604
13625
|
});
|
|
13605
13626
|
}
|
|
13606
13627
|
};
|
|
13628
|
+
/**
|
|
13629
|
+
* Placeholder handle marking "a reposition frame has been requested but the
|
|
13630
|
+
* real handle is not known yet". Never passed to `cancelAnimationFrame` in
|
|
13631
|
+
* practice — it is replaced within the same synchronous block — and harmless
|
|
13632
|
+
* if it were, since no frame carries this id.
|
|
13633
|
+
*/
|
|
13634
|
+
const SCHEDULED = -1;
|
|
13607
13635
|
function createFocusableElement() {
|
|
13608
13636
|
const element = document.createElement("div");
|
|
13609
13637
|
element.tabIndex = -1;
|
|
@@ -13616,12 +13644,13 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
13616
13644
|
this.accessor = accessor;
|
|
13617
13645
|
this.map = {};
|
|
13618
13646
|
this._disposed = false;
|
|
13647
|
+
this._generation = 0;
|
|
13619
13648
|
this.positionCache = new PositionCache();
|
|
13620
|
-
this.pendingUpdates = /* @__PURE__ */ new Set();
|
|
13621
13649
|
this.addDisposables(Disposable.from(() => {
|
|
13622
13650
|
for (const value of Object.values(this.map)) {
|
|
13623
13651
|
value.disposable.dispose();
|
|
13624
13652
|
value.destroy.dispose();
|
|
13653
|
+
this.cancelPendingUpdate(value);
|
|
13625
13654
|
}
|
|
13626
13655
|
this._disposed = true;
|
|
13627
13656
|
}));
|
|
@@ -13648,11 +13677,24 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
13648
13677
|
this.positionCache.invalidate();
|
|
13649
13678
|
(_entry$resize = entry.resize) === null || _entry$resize === void 0 || _entry$resize.call(entry);
|
|
13650
13679
|
}
|
|
13680
|
+
/**
|
|
13681
|
+
* Drop the reposition frame queued for a panel, if any. A queued frame is
|
|
13682
|
+
* bound to the reference container that was current when it was scheduled,
|
|
13683
|
+
* so it must be discarded whenever that container stops being the one the
|
|
13684
|
+
* overlay should track.
|
|
13685
|
+
*/
|
|
13686
|
+
cancelPendingUpdate(entry) {
|
|
13687
|
+
if (entry.pendingUpdate !== void 0) {
|
|
13688
|
+
cancelAnimationFrame(entry.pendingUpdate);
|
|
13689
|
+
entry.pendingUpdate = void 0;
|
|
13690
|
+
}
|
|
13691
|
+
}
|
|
13651
13692
|
detatch(panel) {
|
|
13652
13693
|
if (this.map[panel.api.id]) {
|
|
13653
|
-
const
|
|
13654
|
-
disposable.dispose();
|
|
13655
|
-
destroy.dispose();
|
|
13694
|
+
const entry = this.map[panel.api.id];
|
|
13695
|
+
entry.disposable.dispose();
|
|
13696
|
+
entry.destroy.dispose();
|
|
13697
|
+
this.cancelPendingUpdate(entry);
|
|
13656
13698
|
delete this.map[panel.api.id];
|
|
13657
13699
|
return true;
|
|
13658
13700
|
}
|
|
@@ -13668,22 +13710,73 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
13668
13710
|
panel,
|
|
13669
13711
|
disposable: Disposable.NONE,
|
|
13670
13712
|
destroy: Disposable.NONE,
|
|
13671
|
-
element
|
|
13713
|
+
element,
|
|
13714
|
+
retainPreviousGeometry: false,
|
|
13715
|
+
positioned: false,
|
|
13716
|
+
generation: ++this._generation
|
|
13672
13717
|
};
|
|
13673
13718
|
}
|
|
13674
|
-
const
|
|
13719
|
+
const mapEntry = this.map[panel.api.id];
|
|
13720
|
+
/**
|
|
13721
|
+
* A *change* of reference container supersedes the previous `attach`:
|
|
13722
|
+
* take a fresh generation so its `resize` closure can no longer run,
|
|
13723
|
+
* and drop the frame it queued against the old container. During
|
|
13724
|
+
* `fromJSON({ reuseExistingPanels: true })` that old container is a
|
|
13725
|
+
* detached staging group measuring 0x0, so leaving its frame in flight
|
|
13726
|
+
* both wastes the update and delays the reposition against the real one.
|
|
13727
|
+
*
|
|
13728
|
+
* Re-attaching over the *same* container (re-open, active panel change)
|
|
13729
|
+
* deliberately leaves scheduled work alone: `repositionPanelOverlay`
|
|
13730
|
+
* (the auto-hide peek) schedules a frame carrying the sticky
|
|
13731
|
+
* `forceVisible`/`clip` state which `attach` does not re-apply, and a
|
|
13732
|
+
* peeked panel's `api.isVisible` is false — so discarding that frame
|
|
13733
|
+
* leaves `visibilityChanged` to hide the overlay and the peek renders
|
|
13734
|
+
* nothing. A newly created entry already holds a fresh generation, so
|
|
13735
|
+
* the stale closures a `detatch` left behind are fenced off either way.
|
|
13736
|
+
*/
|
|
13737
|
+
if (mapEntry.referenceContainer !== referenceContainer) {
|
|
13738
|
+
mapEntry.generation = ++this._generation;
|
|
13739
|
+
this.cancelPendingUpdate(mapEntry);
|
|
13740
|
+
mapEntry.referenceContainer = referenceContainer;
|
|
13741
|
+
/**
|
|
13742
|
+
* Arm the retain flag only here: it means "a replacement reference
|
|
13743
|
+
* container is awaiting layout", so the 0x0 early-return below
|
|
13744
|
+
* holds the last good box rather than blanking the panel mid-move.
|
|
13745
|
+
* Arming it on every re-attach instead would make a container that
|
|
13746
|
+
* genuinely collapses to zero keep its stale geometry forever.
|
|
13747
|
+
*
|
|
13748
|
+
* Gated on `positioned` because an overlay that has never been
|
|
13749
|
+
* positioned has no left/top/width/height, and `.dv-render-overlay`
|
|
13750
|
+
* defaults to 100%/100% — retaining "previous" geometry there would
|
|
13751
|
+
* pin the content over the whole container.
|
|
13752
|
+
*/
|
|
13753
|
+
mapEntry.retainPreviousGeometry = mapEntry.positioned;
|
|
13754
|
+
}
|
|
13755
|
+
const generation = mapEntry.generation;
|
|
13756
|
+
const focusContainer = mapEntry.element;
|
|
13675
13757
|
const contentElement = panel.view.content.element;
|
|
13676
13758
|
if (contentElement.parentElement !== focusContainer) focusContainer.appendChild(contentElement);
|
|
13677
13759
|
if (focusContainer.parentElement !== this.element) this.element.appendChild(focusContainer);
|
|
13678
13760
|
const resize = () => {
|
|
13679
13761
|
const panelId = panel.api.id;
|
|
13680
|
-
|
|
13681
|
-
|
|
13682
|
-
|
|
13762
|
+
const scheduling = this.map[panelId];
|
|
13763
|
+
if ((scheduling === null || scheduling === void 0 ? void 0 : scheduling.generation) !== generation) return;
|
|
13764
|
+
if (scheduling.pendingUpdate !== void 0) return;
|
|
13765
|
+
/**
|
|
13766
|
+
* Claim the slot *before* scheduling. `requestAnimationFrame` is
|
|
13767
|
+
* shimmed to run inline by some hosts (and by several suites here),
|
|
13768
|
+
* in which case the callback below clears `pendingUpdate` while
|
|
13769
|
+
* this call is still on the stack — assigning the handle afterwards
|
|
13770
|
+
* would resurrect a slot that is already spent and block every
|
|
13771
|
+
* later reposition. The sentinel is replaced by the real handle
|
|
13772
|
+
* only if the frame has not already run.
|
|
13773
|
+
*/
|
|
13774
|
+
scheduling.pendingUpdate = SCHEDULED;
|
|
13775
|
+
const handle = requestAnimationFrame(() => {
|
|
13683
13776
|
var _entry$forceVisible;
|
|
13684
|
-
this.pendingUpdates.delete(panelId);
|
|
13685
13777
|
const entry = this.map[panelId];
|
|
13686
|
-
if (
|
|
13778
|
+
if (entry) entry.pendingUpdate = void 0;
|
|
13779
|
+
if (this.isDisposed || (entry === null || entry === void 0 ? void 0 : entry.generation) !== generation) return;
|
|
13687
13780
|
const forceVisible = (_entry$forceVisible = entry.forceVisible) !== null && _entry$forceVisible !== void 0 ? _entry$forceVisible : false;
|
|
13688
13781
|
const clip = entry.clip;
|
|
13689
13782
|
const box = this.positionCache.getPosition(referenceContainer.element);
|
|
@@ -13692,6 +13785,15 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
13692
13785
|
const top = box.top - box2.top;
|
|
13693
13786
|
const width = box.width;
|
|
13694
13787
|
const height = box.height;
|
|
13788
|
+
if (entry.retainPreviousGeometry && (width === 0 || height === 0)) {
|
|
13789
|
+
if (!panel.api.isVisible && !forceVisible) {
|
|
13790
|
+
focusContainer.style.visibility = "hidden";
|
|
13791
|
+
focusContainer.style.pointerEvents = "none";
|
|
13792
|
+
}
|
|
13793
|
+
return;
|
|
13794
|
+
}
|
|
13795
|
+
entry.retainPreviousGeometry = false;
|
|
13796
|
+
entry.positioned = true;
|
|
13695
13797
|
focusContainer.style.left = `${left}px`;
|
|
13696
13798
|
focusContainer.style.top = `${top}px`;
|
|
13697
13799
|
focusContainer.style.width = `${width}px`;
|
|
@@ -13720,11 +13822,30 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
13720
13822
|
} else focusContainer.style.clipPath = "";
|
|
13721
13823
|
toggleClass(focusContainer, "dv-render-overlay-float", panel.group.api.location.type === "floating");
|
|
13722
13824
|
});
|
|
13825
|
+
if (scheduling.pendingUpdate === SCHEDULED) scheduling.pendingUpdate = handle;
|
|
13723
13826
|
};
|
|
13724
13827
|
const visibilityChanged = () => {
|
|
13725
13828
|
if (panel.api.isVisible) {
|
|
13829
|
+
var _this$map$panel$api$i;
|
|
13726
13830
|
this.positionCache.invalidate();
|
|
13727
13831
|
resize();
|
|
13832
|
+
/**
|
|
13833
|
+
* Existing geometry is safe to show while its replacement lays
|
|
13834
|
+
* out. `retainPreviousGeometry` is only set when geometry has
|
|
13835
|
+
* actually been written (see `attach`), so this can never
|
|
13836
|
+
* un-hide an overlay whose left/top/width/height are unset —
|
|
13837
|
+
* `.dv-render-overlay` is 100%/100% by default and would
|
|
13838
|
+
* otherwise cover the whole dock.
|
|
13839
|
+
*
|
|
13840
|
+
* The retained geometry is the panel's position in the previous
|
|
13841
|
+
* layout, so restoring a layout that moves the panel does paint
|
|
13842
|
+
* it at stale coordinates until the reposition lands. That is
|
|
13843
|
+
* bounded to the next frame now that a superseded `attach` can
|
|
13844
|
+
* no longer swallow the reposition (see `attach`); showing
|
|
13845
|
+
* stale-but-real geometry for a frame is the deliberate
|
|
13846
|
+
* trade-off against blanking the panel for the whole rebuild.
|
|
13847
|
+
*/
|
|
13848
|
+
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 = "";
|
|
13728
13849
|
focusContainer.style.pointerEvents = "";
|
|
13729
13850
|
} else {
|
|
13730
13851
|
focusContainer.style.visibility = "hidden";
|
|
@@ -13947,7 +14068,17 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
13947
14068
|
window: externalWindow
|
|
13948
14069
|
});
|
|
13949
14070
|
return new Promise((resolve, reject) => {
|
|
13950
|
-
externalWindow.addEventListener("unload", (
|
|
14071
|
+
externalWindow.addEventListener("unload", () => {});
|
|
14072
|
+
/**
|
|
14073
|
+
* `load` is the only event that resolves this promise with a
|
|
14074
|
+
* container, so a window that goes away first would leave the
|
|
14075
|
+
* caller awaiting a promise that never settles - and
|
|
14076
|
+
* `addPopoutGroup` holds its layout transaction open until it does.
|
|
14077
|
+
* Settle with `null` on close, the same signal a blocked popup
|
|
14078
|
+
* gives and one the caller already handles. `resolve` after the
|
|
14079
|
+
* fact is a no-op, so a `load` that arrived first still wins.
|
|
14080
|
+
*/
|
|
14081
|
+
disposable.addDisposables(_this.onWillClose(() => resolve(null)));
|
|
13951
14082
|
externalWindow.addEventListener("load", () => {
|
|
13952
14083
|
/**
|
|
13953
14084
|
* @see https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event
|
|
@@ -15365,6 +15496,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
15365
15496
|
this._onWillDrop = new Emitter();
|
|
15366
15497
|
this.onWillDrop = this._onWillDrop.event;
|
|
15367
15498
|
this._mutationDepth = 0;
|
|
15499
|
+
this._pendingLocationChanges = /* @__PURE__ */ new Map();
|
|
15368
15500
|
this._origin = "user";
|
|
15369
15501
|
this._originDepth = 0;
|
|
15370
15502
|
this._onWillMutateLayout = new Emitter();
|
|
@@ -15462,7 +15594,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
15462
15594
|
toggleClass(this.element, "dv-debug", !!options.debug);
|
|
15463
15595
|
this.updateTheme();
|
|
15464
15596
|
if (options.debug) this.addDisposables(new StrictEventsSequencing(this));
|
|
15465
|
-
this.addDisposables(this.rootDropTargetContainer, this.floatingDropTargetContainer, addDisposableListener(this._shellManager.element, "dragend", () => {
|
|
15597
|
+
this.addDisposables(Disposable.from(() => this._pendingLocationChanges.clear()), this.rootDropTargetContainer, this.floatingDropTargetContainer, addDisposableListener(this._shellManager.element, "dragend", () => {
|
|
15466
15598
|
var _this$rootDropTargetC2, _this$floatingDropTar;
|
|
15467
15599
|
(_this$rootDropTargetC2 = this.rootDropTargetContainer.model) === null || _this$rootDropTargetC2 === void 0 || _this$rootDropTargetC2.clear();
|
|
15468
15600
|
(_this$floatingDropTar = this.floatingDropTargetContainer.model) === null || _this$floatingDropTar === void 0 || _this$floatingDropTar.clear();
|
|
@@ -15536,7 +15668,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
15536
15668
|
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;
|
|
15537
15669
|
}
|
|
15538
15670
|
addPopoutGroup(itemToPopout, options) {
|
|
15539
|
-
return this.
|
|
15671
|
+
return this.mutationAsync("popout", () => this._doAddPopoutGroup(itemToPopout, options));
|
|
15540
15672
|
}
|
|
15541
15673
|
/** Enumerate the popout groups currently open in their own windows. */
|
|
15542
15674
|
getPopouts() {
|
|
@@ -15633,15 +15765,32 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
15633
15765
|
}
|
|
15634
15766
|
};
|
|
15635
15767
|
let floatingBox;
|
|
15636
|
-
|
|
15637
|
-
|
|
15638
|
-
|
|
15639
|
-
|
|
15640
|
-
|
|
15768
|
+
/**
|
|
15769
|
+
* Popping out rehomes panels into `group`, so like the floating
|
|
15770
|
+
* case it owes the caller an `onDidMovePanel` per panel. The
|
|
15771
|
+
* events are deferred until the window is wired up so listeners
|
|
15772
|
+
* observe the panels' final `popout` location.
|
|
15773
|
+
*/
|
|
15774
|
+
let movedPanels = [];
|
|
15775
|
+
if (!(options === null || options === void 0 ? void 0 : options.overridePopoutGroup) && !(options === null || options === void 0 ? void 0 : options.overridePopoutGridview) && isGroupAddedToDom) if (itemToPopout instanceof DockviewPanel) {
|
|
15776
|
+
const sourceGroup = itemToPopout.group;
|
|
15777
|
+
this.movingLock(() => {
|
|
15778
|
+
const panel = referenceGroup.model.removePanel(itemToPopout);
|
|
15779
|
+
group.model.openPanel(panel);
|
|
15780
|
+
});
|
|
15781
|
+
movedPanels = [{
|
|
15782
|
+
panel: itemToPopout,
|
|
15783
|
+
from: sourceGroup
|
|
15784
|
+
}];
|
|
15785
|
+
} else {
|
|
15641
15786
|
this.movingLock(() => moveGroupWithoutDestroying({
|
|
15642
15787
|
from: referenceGroup,
|
|
15643
15788
|
to: group
|
|
15644
15789
|
}));
|
|
15790
|
+
movedPanels = group.panels.map((panel) => ({
|
|
15791
|
+
panel,
|
|
15792
|
+
from: referenceGroup
|
|
15793
|
+
}));
|
|
15645
15794
|
switch (referenceLocation) {
|
|
15646
15795
|
case "grid":
|
|
15647
15796
|
referenceGroup.api.setVisible(false);
|
|
@@ -15750,6 +15899,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
15750
15899
|
group: value.popoutGroup,
|
|
15751
15900
|
window: value.getWindow()
|
|
15752
15901
|
});
|
|
15902
|
+
for (const { panel, from } of movedPanels) this.fireDidMovePanel(panel, from);
|
|
15753
15903
|
return true;
|
|
15754
15904
|
}).catch((err) => {
|
|
15755
15905
|
console.error("dockview: failed to create popout.", err);
|
|
@@ -15827,6 +15977,16 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
15827
15977
|
const members = this.groups.filter((candidate) => popoutGridview.element.contains(candidate.element));
|
|
15828
15978
|
const anchorPresent = members.includes(group);
|
|
15829
15979
|
const anchorIsSoleMember = anchorPresent && members.length === 1;
|
|
15980
|
+
/**
|
|
15981
|
+
* Popping a group out fires `onDidMovePanel` per panel, so closing the
|
|
15982
|
+
* window owes the caller the same: every panel in it is rehomed, into
|
|
15983
|
+
* the reference group the popout left behind or into a fresh grid slot.
|
|
15984
|
+
* `movingLock` suppresses onDidAddPanel / onDidRemovePanel on these
|
|
15985
|
+
* paths, so `onDidMovePanel` is the only event that can carry it. The
|
|
15986
|
+
* events are deferred to the end so listeners observe the panels at
|
|
15987
|
+
* their final group and location.
|
|
15988
|
+
*/
|
|
15989
|
+
const movedPanels = [];
|
|
15830
15990
|
if (genuineClose) for (const member of members) {
|
|
15831
15991
|
if (member === group) continue;
|
|
15832
15992
|
this.movingLock(() => {
|
|
@@ -15837,12 +15997,21 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
15837
15997
|
});
|
|
15838
15998
|
this.redockGroupToMainGrid(member);
|
|
15839
15999
|
});
|
|
16000
|
+
for (const panel of member.panels) movedPanels.push({
|
|
16001
|
+
panel,
|
|
16002
|
+
from: member
|
|
16003
|
+
});
|
|
15840
16004
|
}
|
|
15841
16005
|
if (anchorPresent && isGroupAddedToDom && this.getPanel(referenceGroup.id)) {
|
|
16006
|
+
const rehomed = [...group.panels];
|
|
15842
16007
|
this.movingLock(() => moveGroupWithoutDestroying({
|
|
15843
16008
|
from: group,
|
|
15844
16009
|
to: referenceGroup
|
|
15845
16010
|
}));
|
|
16011
|
+
for (const panel of rehomed) movedPanels.push({
|
|
16012
|
+
panel,
|
|
16013
|
+
from: group
|
|
16014
|
+
});
|
|
15846
16015
|
if (!referenceGroup.api.isVisible) referenceGroup.api.setVisible(true);
|
|
15847
16016
|
if (this.getPanel(group.id)) this.doRemoveGroup(group, { skipPopoutAssociated: true });
|
|
15848
16017
|
} else if (anchorPresent && this.getPanel(group.id)) {
|
|
@@ -15873,10 +16042,15 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
15873
16042
|
this.movingLock(() => {
|
|
15874
16043
|
this.doAddGroup(group, [0]);
|
|
15875
16044
|
});
|
|
16045
|
+
for (const panel of group.panels) movedPanels.push({
|
|
16046
|
+
panel,
|
|
16047
|
+
from: group
|
|
16048
|
+
});
|
|
15876
16049
|
}
|
|
15877
16050
|
this.doSetGroupAndPanelActive(group);
|
|
15878
16051
|
}
|
|
15879
16052
|
disposePopoutGridview();
|
|
16053
|
+
for (const { panel, from } of movedPanels) this.fireDidMovePanel(panel, from);
|
|
15880
16054
|
}
|
|
15881
16055
|
addFloatingGroup(item, options) {
|
|
15882
16056
|
this.mutation("float", () => this._doAddFloatingGroup(item, options));
|
|
@@ -15885,7 +16059,15 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
15885
16059
|
if (!assertModule(this._floatingGroupService, "FloatingGroup", "api.addFloatingGroup")) return;
|
|
15886
16060
|
if (item instanceof DockviewGroupPanel && item.model.location.type === "edge") return;
|
|
15887
16061
|
let group;
|
|
16062
|
+
/**
|
|
16063
|
+
* Floating relocates panels exactly like a drop onto the grid does, so
|
|
16064
|
+
* it owes the caller an `onDidMovePanel` per panel. The events are
|
|
16065
|
+
* deferred until the window is mounted below: only then do the panels
|
|
16066
|
+
* report their final `floating` location.
|
|
16067
|
+
*/
|
|
16068
|
+
let movedPanels = [];
|
|
15888
16069
|
if (item instanceof DockviewPanel) {
|
|
16070
|
+
const sourceGroup = item.group;
|
|
15889
16071
|
group = this.createGroup();
|
|
15890
16072
|
this._onDidAddGroup.fire(group);
|
|
15891
16073
|
this.movingLock(() => this.removePanel(item, {
|
|
@@ -15894,6 +16076,10 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
15894
16076
|
skipSetActiveGroup: true
|
|
15895
16077
|
}));
|
|
15896
16078
|
this.movingLock(() => group.model.openPanel(item, { skipSetGroupActive: true }));
|
|
16079
|
+
movedPanels = [{
|
|
16080
|
+
panel: item,
|
|
16081
|
+
from: sourceGroup
|
|
16082
|
+
}];
|
|
15897
16083
|
} else {
|
|
15898
16084
|
var _this$_popoutWindowSe8;
|
|
15899
16085
|
group = item;
|
|
@@ -15910,11 +16096,21 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
15910
16096
|
});
|
|
15911
16097
|
this.doRemoveGroup(popoutReferenceGroup, { skipDispose: true });
|
|
15912
16098
|
group = popoutReferenceGroup;
|
|
15913
|
-
|
|
15914
|
-
|
|
15915
|
-
|
|
15916
|
-
|
|
15917
|
-
}
|
|
16099
|
+
movedPanels = group.panels.map((panel) => ({
|
|
16100
|
+
panel,
|
|
16101
|
+
from: item
|
|
16102
|
+
}));
|
|
16103
|
+
} else {
|
|
16104
|
+
this.doRemoveGroup(item, {
|
|
16105
|
+
skipDispose: true,
|
|
16106
|
+
skipPopoutReturn: true,
|
|
16107
|
+
skipPopoutAssociated: false
|
|
16108
|
+
});
|
|
16109
|
+
movedPanels = group.panels.map((panel) => ({
|
|
16110
|
+
panel,
|
|
16111
|
+
from: group
|
|
16112
|
+
}));
|
|
16113
|
+
}
|
|
15918
16114
|
}
|
|
15919
16115
|
function getAnchoredBox() {
|
|
15920
16116
|
if (options === null || options === void 0 ? void 0 : options.position) {
|
|
@@ -15947,6 +16143,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
15947
16143
|
skipActiveGroup: options === null || options === void 0 ? void 0 : options.skipActiveGroup,
|
|
15948
16144
|
disableSmartGuides: options === null || options === void 0 ? void 0 : options.disableSmartGuides
|
|
15949
16145
|
});
|
|
16146
|
+
for (const { panel, from } of movedPanels) this.fireDidMovePanel(panel, from);
|
|
15950
16147
|
}
|
|
15951
16148
|
/**
|
|
15952
16149
|
* Build an empty gridview configured to match the main grid's styling, for
|
|
@@ -16378,35 +16575,119 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
16378
16575
|
if (typeof data !== "object" || data === null) throw new Error("dockview: serialized layout must be a non-null object");
|
|
16379
16576
|
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");
|
|
16380
16577
|
const existingPanels = /* @__PURE__ */ new Map();
|
|
16381
|
-
|
|
16578
|
+
const temporaryGroups = /* @__PURE__ */ new Map();
|
|
16579
|
+
const stagedPanels = [];
|
|
16580
|
+
const temporaryGroupDisposables = [];
|
|
16581
|
+
/**
|
|
16582
|
+
* The staging groups are detached from `_groups` and never enter the
|
|
16583
|
+
* grid, so nothing else will ever tear them down.
|
|
16584
|
+
*
|
|
16585
|
+
* `dispose()` reaches consumer `IContentRenderer.dispose()`, so one
|
|
16586
|
+
* throwing renderer must not abort the rest of the cleanup — that would
|
|
16587
|
+
* re-introduce the very leak this reclaims — nor replace the
|
|
16588
|
+
* deserialization error the caller is being given. Draining the list
|
|
16589
|
+
* also makes this safe to call more than once.
|
|
16590
|
+
*/
|
|
16591
|
+
const disposeTemporaryGroups = () => {
|
|
16592
|
+
for (const disposable of temporaryGroupDisposables) try {
|
|
16593
|
+
disposable.dispose();
|
|
16594
|
+
} catch (err) {
|
|
16595
|
+
console.error("dockview: failed to dispose a temporary group created for reuseExistingPanels", err);
|
|
16596
|
+
}
|
|
16597
|
+
temporaryGroupDisposables.length = 0;
|
|
16598
|
+
};
|
|
16382
16599
|
if (options === null || options === void 0 ? void 0 : options.reuseExistingPanels) {
|
|
16383
16600
|
/**
|
|
16384
|
-
*
|
|
16385
|
-
*
|
|
16386
|
-
*
|
|
16387
|
-
* 2. Remove that temporary group from the group mapping so that it doesn't get cleared when we clear the layout
|
|
16601
|
+
* Visible, always-rendered panels need individual staging groups
|
|
16602
|
+
* to remain active. Other reused panels can share a staging group.
|
|
16603
|
+
* The staging groups are excluded from the layout clear below.
|
|
16388
16604
|
*/
|
|
16389
|
-
tempGroup = this.createGroup();
|
|
16390
|
-
this._groups.delete(tempGroup.api.id);
|
|
16391
16605
|
const newPanels = Object.keys(data.panels);
|
|
16392
|
-
|
|
16393
|
-
|
|
16394
|
-
|
|
16395
|
-
|
|
16396
|
-
|
|
16397
|
-
|
|
16398
|
-
|
|
16399
|
-
|
|
16400
|
-
|
|
16401
|
-
|
|
16402
|
-
|
|
16403
|
-
|
|
16404
|
-
|
|
16606
|
+
let sharedTemporaryGroup;
|
|
16607
|
+
const createTemporaryGroup = () => {
|
|
16608
|
+
const temporaryGroup = this.createGroup();
|
|
16609
|
+
/**
|
|
16610
|
+
* Removing the group from `_groups` also drops the record's
|
|
16611
|
+
* `CompositeDisposable`, so capture it first and tear both it
|
|
16612
|
+
* and the group down in the `finally` below. Left undisposed a
|
|
16613
|
+
* staging group leaks its `ResizeObserver`, its
|
|
16614
|
+
* `onDidOptionsChange` subscription (retained by this
|
|
16615
|
+
* component's emitter) and the watermark its model mounts when
|
|
16616
|
+
* the group empties — once per reused panel, per `fromJSON`.
|
|
16617
|
+
*/
|
|
16618
|
+
const record = this._groups.get(temporaryGroup.api.id);
|
|
16619
|
+
this._groups.delete(temporaryGroup.api.id);
|
|
16620
|
+
temporaryGroupDisposables.push(Disposable.from(() => {
|
|
16621
|
+
/**
|
|
16622
|
+
* Reclaim the group's own resources, never its panels.
|
|
16623
|
+
* Staging is driven by the ids in `data.panels` while
|
|
16624
|
+
* reclaiming is driven by the group `views` that
|
|
16625
|
+
* reference them, so a panel whose state is present but
|
|
16626
|
+
* unreferenced is still staged here — and `dispose()`
|
|
16627
|
+
* on a non-empty group reaches the consumer's
|
|
16628
|
+
* `IContentRenderer.dispose()`. Emptying the group
|
|
16629
|
+
* first leaves those panels exactly as they were before
|
|
16630
|
+
* this teardown existed, which also keeps this safe
|
|
16631
|
+
* against any future path that rebuilds a panel under
|
|
16632
|
+
* an id that is live in the new layout.
|
|
16633
|
+
*/
|
|
16634
|
+
this.movingLock(() => {
|
|
16635
|
+
for (const panel of temporaryGroup.panels.slice()) temporaryGroup.model.removePanel(panel);
|
|
16636
|
+
});
|
|
16637
|
+
record === null || record === void 0 || record.disposable.dispose();
|
|
16638
|
+
temporaryGroup.dispose();
|
|
16639
|
+
}));
|
|
16640
|
+
return temporaryGroup;
|
|
16641
|
+
};
|
|
16642
|
+
/**
|
|
16643
|
+
* Staging and the clear below run before the deserialization
|
|
16644
|
+
* `try`, so a throw here (a consumer `onDidRemovePanel` handler, a
|
|
16645
|
+
* renderer teardown during `clear`) would escape without reclaiming
|
|
16646
|
+
* the staging groups already created.
|
|
16647
|
+
*
|
|
16648
|
+
* The creation loop is inside the guard too, not just the moves and
|
|
16649
|
+
* the clear: `createGroup()` reaches consumer code of its own —
|
|
16650
|
+
* `initialize()` mounts the watermark through
|
|
16651
|
+
* `createWatermarkComponent()` — so a throw on the n-th panel would
|
|
16652
|
+
* otherwise strand the n-1 staging groups already built.
|
|
16653
|
+
*/
|
|
16654
|
+
try {
|
|
16655
|
+
for (const panel of this.panels) if (newPanels.includes(panel.api.id)) {
|
|
16656
|
+
existingPanels.set(panel.api.id, panel);
|
|
16657
|
+
let temporaryGroup;
|
|
16658
|
+
if (panel.api.renderer === "always" && panel.api.isVisible) temporaryGroup = createTemporaryGroup();
|
|
16659
|
+
else {
|
|
16660
|
+
var _sharedTemporaryGroup;
|
|
16661
|
+
(_sharedTemporaryGroup = sharedTemporaryGroup) !== null && _sharedTemporaryGroup !== void 0 || (sharedTemporaryGroup = createTemporaryGroup());
|
|
16662
|
+
temporaryGroup = sharedTemporaryGroup;
|
|
16663
|
+
}
|
|
16664
|
+
temporaryGroups.set(panel.api.id, temporaryGroup);
|
|
16665
|
+
stagedPanels.push({
|
|
16666
|
+
panel,
|
|
16667
|
+
temporaryGroup
|
|
16668
|
+
});
|
|
16669
|
+
}
|
|
16670
|
+
this.movingLock(() => {
|
|
16671
|
+
stagedPanels.forEach(({ panel, temporaryGroup }) => {
|
|
16672
|
+
this.moveGroupOrPanel({
|
|
16673
|
+
from: {
|
|
16674
|
+
groupId: panel.api.group.api.id,
|
|
16675
|
+
panelId: panel.api.id
|
|
16676
|
+
},
|
|
16677
|
+
to: {
|
|
16678
|
+
group: temporaryGroup,
|
|
16679
|
+
position: "center"
|
|
16680
|
+
},
|
|
16681
|
+
keepEmptyGroups: true
|
|
16682
|
+
});
|
|
16405
16683
|
});
|
|
16406
16684
|
});
|
|
16407
|
-
|
|
16408
|
-
|
|
16409
|
-
|
|
16685
|
+
this.clear();
|
|
16686
|
+
} catch (err) {
|
|
16687
|
+
disposeTemporaryGroups();
|
|
16688
|
+
throw err;
|
|
16689
|
+
}
|
|
16690
|
+
} else this.clear();
|
|
16410
16691
|
const { grid, panels, activeGroup } = data;
|
|
16411
16692
|
try {
|
|
16412
16693
|
var _data$floatingGroups, _data$popoutGroups, _this$_popoutWindowSe12, _this$_floatingGroupS5, _this$_watermarkServi2;
|
|
@@ -16438,9 +16719,10 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
16438
16719
|
* due to a corruption of input data.
|
|
16439
16720
|
*/
|
|
16440
16721
|
const existingPanel = existingPanels.get(child);
|
|
16441
|
-
|
|
16722
|
+
const temporaryGroup = temporaryGroups.get(child);
|
|
16723
|
+
if (temporaryGroup && existingPanel) {
|
|
16442
16724
|
this.movingLock(() => {
|
|
16443
|
-
|
|
16725
|
+
temporaryGroup.model.removePanel(existingPanel);
|
|
16444
16726
|
});
|
|
16445
16727
|
createdPanels.push(existingPanel);
|
|
16446
16728
|
existingPanel.updateFromStateModel(panels[child]);
|
|
@@ -16470,7 +16752,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
16470
16752
|
return createGroupFromSerializedState(node.data);
|
|
16471
16753
|
} });
|
|
16472
16754
|
this._layoutFromShell(width, height);
|
|
16473
|
-
if (data.edgeGroups) this.deserializeEdgeGroups(data.edgeGroups, panels);
|
|
16755
|
+
if (data.edgeGroups) this.deserializeEdgeGroups(data.edgeGroups, panels, existingPanels, temporaryGroups);
|
|
16474
16756
|
this.deserializeFloatingWindows((_data$floatingGroups = data.floatingGroups) !== null && _data$floatingGroups !== void 0 ? _data$floatingGroups : [], createGroupFromSerializedState);
|
|
16475
16757
|
const popoutPromises = this.deserializePopoutWindows((_data$popoutGroups = data.popoutGroups) !== null && _data$popoutGroups !== void 0 ? _data$popoutGroups : [], createGroupFromSerializedState);
|
|
16476
16758
|
(_this$_popoutWindowSe12 = this._popoutWindowService) === null || _this$_popoutWindowSe12 === void 0 || _this$_popoutWindowSe12.finishRestoration(popoutPromises);
|
|
@@ -16507,6 +16789,8 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
16507
16789
|
* expect trying to load a corrupted layout to result in an error and not silently fail...
|
|
16508
16790
|
*/
|
|
16509
16791
|
throw err;
|
|
16792
|
+
} finally {
|
|
16793
|
+
disposeTemporaryGroups();
|
|
16510
16794
|
}
|
|
16511
16795
|
this.debouncedUpdateAllPositions();
|
|
16512
16796
|
this._onDidLayoutFromJSON.fire();
|
|
@@ -16529,7 +16813,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
16529
16813
|
members
|
|
16530
16814
|
};
|
|
16531
16815
|
}
|
|
16532
|
-
deserializeEdgeGroups(edgeGroups, panels) {
|
|
16816
|
+
deserializeEdgeGroups(edgeGroups, panels, existingPanels, temporaryGroups) {
|
|
16533
16817
|
const edgeService = assertModule(this._edgeGroupService, "EdgeGroup", "fromJSON edge restoration");
|
|
16534
16818
|
if (!edgeService) return;
|
|
16535
16819
|
for (const _position of [
|
|
@@ -16559,13 +16843,40 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
16559
16843
|
if (groupState) {
|
|
16560
16844
|
const { views, activeView } = groupState;
|
|
16561
16845
|
const createdPanels = [];
|
|
16562
|
-
for (const panelId of views)
|
|
16563
|
-
|
|
16564
|
-
|
|
16846
|
+
for (const panelId of views) {
|
|
16847
|
+
if (!panels[panelId]) continue;
|
|
16848
|
+
/**
|
|
16849
|
+
* Reclaim a staged panel rather than rebuilding it, the
|
|
16850
|
+
* same way the grid path does. Deserializing here instead
|
|
16851
|
+
* would honour `reuseExistingPanels` everywhere except edge
|
|
16852
|
+
* groups: the live panel keeps sitting in its staging group
|
|
16853
|
+
* while a second panel is built under the same id, so the
|
|
16854
|
+
* consumer's renderer for the original is orphaned — never
|
|
16855
|
+
* disposed, and its element left inside the id-keyed
|
|
16856
|
+
* overlay entry the replacement now shares.
|
|
16857
|
+
*/
|
|
16858
|
+
const existingPanel = existingPanels.get(panelId);
|
|
16859
|
+
const temporaryGroup = temporaryGroups.get(panelId);
|
|
16860
|
+
if (temporaryGroup && existingPanel) {
|
|
16861
|
+
this.movingLock(() => {
|
|
16862
|
+
temporaryGroup.model.removePanel(existingPanel);
|
|
16863
|
+
});
|
|
16864
|
+
createdPanels.push(existingPanel);
|
|
16865
|
+
existingPanel.updateFromStateModel(panels[panelId]);
|
|
16866
|
+
} else {
|
|
16867
|
+
const panel = this._deserializer.fromJSON(panels[panelId], edgeGroup);
|
|
16868
|
+
createdPanels.push(panel);
|
|
16869
|
+
}
|
|
16565
16870
|
}
|
|
16566
16871
|
for (const panel of createdPanels) {
|
|
16567
16872
|
const isActive = activeView === panel.id;
|
|
16568
|
-
|
|
16873
|
+
if (existingPanels.has(panel.api.id)) this.movingLock(() => {
|
|
16874
|
+
edgeGroup.model.openPanel(panel, {
|
|
16875
|
+
skipSetActive: !isActive,
|
|
16876
|
+
skipSetGroupActive: true
|
|
16877
|
+
});
|
|
16878
|
+
});
|
|
16879
|
+
else edgeGroup.model.openPanel(panel, {
|
|
16569
16880
|
skipSetActive: !isActive,
|
|
16570
16881
|
skipSetGroupActive: true
|
|
16571
16882
|
});
|
|
@@ -16989,22 +17300,100 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
16989
17300
|
* outermost mutation.
|
|
16990
17301
|
*/
|
|
16991
17302
|
mutation(kind, func) {
|
|
16992
|
-
const
|
|
17303
|
+
const close = this.openMutation(kind);
|
|
17304
|
+
try {
|
|
17305
|
+
return func();
|
|
17306
|
+
} finally {
|
|
17307
|
+
close();
|
|
17308
|
+
}
|
|
17309
|
+
}
|
|
17310
|
+
/**
|
|
17311
|
+
* `mutation()` for an operation whose work continues after the synchronous
|
|
17312
|
+
* call returns. The transaction stays open until the returned promise
|
|
17313
|
+
* settles, so everything the operation does - the group it adds, the panels
|
|
17314
|
+
* it relocates - lands inside the bracket, matching the synchronous
|
|
17315
|
+
* move / float paths.
|
|
17316
|
+
*/
|
|
17317
|
+
mutationAsync(kind, func) {
|
|
17318
|
+
var _this = this;
|
|
17319
|
+
return _asyncToGenerator(function* () {
|
|
17320
|
+
const close = _this.openMutation(kind);
|
|
17321
|
+
try {
|
|
17322
|
+
return yield func();
|
|
17323
|
+
} finally {
|
|
17324
|
+
close();
|
|
17325
|
+
}
|
|
17326
|
+
})();
|
|
17327
|
+
}
|
|
17328
|
+
/**
|
|
17329
|
+
* Open a transaction and return the function that closes it. Shared by the
|
|
17330
|
+
* synchronous and asynchronous brackets; the returned function must be
|
|
17331
|
+
* called exactly once.
|
|
17332
|
+
*
|
|
17333
|
+
* Both ends key off the depth counter reaching zero rather than off which
|
|
17334
|
+
* bracket opened first. For synchronous nesting the two are the same thing
|
|
17335
|
+
* - brackets close in the order they opened - but asynchronous transactions
|
|
17336
|
+
* can *overlap* rather than nest (two `addPopoutGroup` calls in flight at
|
|
17337
|
+
* once, or a restore staggering several), and there the first to open is
|
|
17338
|
+
* not the last to close. Reporting on the opener would fire `didMutate`
|
|
17339
|
+
* while the other transaction was still doing structural work, which is the
|
|
17340
|
+
* very thing the async bracket exists to prevent. Overlapping transactions
|
|
17341
|
+
* therefore report as one, tagged with the kind of the last to finish.
|
|
17342
|
+
*/
|
|
17343
|
+
openMutation(kind) {
|
|
16993
17344
|
const origin = this._origin;
|
|
16994
|
-
if (
|
|
17345
|
+
if (this._mutationDepth === 0) this._onWillMutateLayout.fire({
|
|
16995
17346
|
kind,
|
|
16996
17347
|
origin
|
|
16997
17348
|
});
|
|
16998
17349
|
this._mutationDepth++;
|
|
16999
|
-
|
|
17000
|
-
return func();
|
|
17001
|
-
} finally {
|
|
17350
|
+
return () => {
|
|
17002
17351
|
this._mutationDepth--;
|
|
17003
|
-
if (
|
|
17004
|
-
|
|
17005
|
-
|
|
17006
|
-
|
|
17352
|
+
if (this._mutationDepth === 0) {
|
|
17353
|
+
this.flushLocationChanges();
|
|
17354
|
+
this._onDidMutateLayout.fire({
|
|
17355
|
+
kind,
|
|
17356
|
+
origin
|
|
17357
|
+
});
|
|
17358
|
+
}
|
|
17359
|
+
};
|
|
17360
|
+
}
|
|
17361
|
+
/**
|
|
17362
|
+
* Coalesce a panel's `onDidLocationChange` to the end of the enclosing
|
|
17363
|
+
* transaction, or fire it immediately when no transaction is in flight.
|
|
17364
|
+
*
|
|
17365
|
+
* Relocating a panel touches its location twice: once as it is reparented
|
|
17366
|
+
* into the destination group - which, when that group has just been created
|
|
17367
|
+
* for a floating or popout window, has not been told where it lives yet -
|
|
17368
|
+
* and once as the group is tagged with its final location. Reporting each
|
|
17369
|
+
* signal as it happens therefore leaks an intermediate `grid` location the
|
|
17370
|
+
* panel was never in, at a moment when it belongs to neither group's panel
|
|
17371
|
+
* list and so is missing from `api.panels`.
|
|
17372
|
+
*
|
|
17373
|
+
* Deferring collapses those signals into a single event carrying the
|
|
17374
|
+
* settled location. Note the signals are deliberately *not* compared
|
|
17375
|
+
* against the panel's previous location: a panel can move between two
|
|
17376
|
+
* floating windows without its location type changing, and this event is
|
|
17377
|
+
* the only signal `OverlayRenderContainer` has to re-resolve the panel's
|
|
17378
|
+
* z-index against its new host window.
|
|
17379
|
+
*/
|
|
17380
|
+
deferLocationChange(key, fire) {
|
|
17381
|
+
if (this._mutationDepth === 0) {
|
|
17382
|
+
fire();
|
|
17383
|
+
return;
|
|
17007
17384
|
}
|
|
17385
|
+
this._pendingLocationChanges.set(key, fire);
|
|
17386
|
+
}
|
|
17387
|
+
/**
|
|
17388
|
+
* Report every panel whose location moved during the transaction that has
|
|
17389
|
+
* just closed. Each callback reads the panel's location at this point, so
|
|
17390
|
+
* what it reports is where the panel ended up.
|
|
17391
|
+
*/
|
|
17392
|
+
flushLocationChanges() {
|
|
17393
|
+
if (this._pendingLocationChanges.size === 0) return;
|
|
17394
|
+
const pending = Array.from(this._pendingLocationChanges.values());
|
|
17395
|
+
this._pendingLocationChanges.clear();
|
|
17396
|
+
for (const fire of pending) fire();
|
|
17008
17397
|
}
|
|
17009
17398
|
/**
|
|
17010
17399
|
* The origin of the operation currently in progress (`'user'` by default).
|
|
@@ -17045,6 +17434,18 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
17045
17434
|
origin: this._origin
|
|
17046
17435
|
});
|
|
17047
17436
|
}
|
|
17437
|
+
/**
|
|
17438
|
+
* Announce that `panel` has finished relocating. Must be called once the
|
|
17439
|
+
* move has settled: `to` is read from the panel's current group, so an
|
|
17440
|
+
* early call would report the source group as the destination.
|
|
17441
|
+
*/
|
|
17442
|
+
fireDidMovePanel(panel, from) {
|
|
17443
|
+
this._onDidMovePanel.fire({
|
|
17444
|
+
panel,
|
|
17445
|
+
from,
|
|
17446
|
+
to: panel.group
|
|
17447
|
+
});
|
|
17448
|
+
}
|
|
17048
17449
|
moveGroupOrPanel(options) {
|
|
17049
17450
|
this.mutation("move", () => this._doMoveGroupOrPanel(options));
|
|
17050
17451
|
}
|
|
@@ -17105,10 +17506,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
17105
17506
|
});
|
|
17106
17507
|
});
|
|
17107
17508
|
if (!options.skipSetActive) this.doSetGroupAndPanelActive(destinationGroup);
|
|
17108
|
-
this.
|
|
17109
|
-
panel: removedPanel,
|
|
17110
|
-
from: sourceGroup
|
|
17111
|
-
});
|
|
17509
|
+
this.fireDidMovePanel(removedPanel, sourceGroup);
|
|
17112
17510
|
} else {
|
|
17113
17511
|
/**
|
|
17114
17512
|
* Dropping a panel to the extremities of a group which will place that panel
|
|
@@ -17127,10 +17525,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
17127
17525
|
const [sourceParentLocation, from] = tail(getGridLocation(sourceGroup.element));
|
|
17128
17526
|
if (sequenceEquals(sourceParentLocation, targetParentLocation)) {
|
|
17129
17527
|
this.gridview.moveView(sourceParentLocation, from, to);
|
|
17130
|
-
this.
|
|
17131
|
-
panel: this.getGroupPanel(sourceItemId),
|
|
17132
|
-
from: sourceGroup
|
|
17133
|
-
});
|
|
17528
|
+
this.fireDidMovePanel(this.getGroupPanel(sourceItemId), sourceGroup);
|
|
17134
17529
|
return;
|
|
17135
17530
|
}
|
|
17136
17531
|
}
|
|
@@ -17161,10 +17556,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
17161
17556
|
const newGroup = this.createGroupAtLocation(updatedTargetLocation, void 0, void 0, destinationGridview);
|
|
17162
17557
|
this.movingLock(() => newGroup.model.openPanel(removedPanel, { skipSetActive: true }));
|
|
17163
17558
|
this.doSetGroupAndPanelActive(newGroup);
|
|
17164
|
-
this.
|
|
17165
|
-
panel: this.getGroupPanel(sourceItemId),
|
|
17166
|
-
from: sourceGroup
|
|
17167
|
-
});
|
|
17559
|
+
this.fireDidMovePanel(this.getGroupPanel(sourceItemId), sourceGroup);
|
|
17168
17560
|
return;
|
|
17169
17561
|
}
|
|
17170
17562
|
if (sourceGroup.api.location.type === "edge") {
|
|
@@ -17181,10 +17573,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
17181
17573
|
const newGroup = this.createGroupAtLocation(targetLocation, void 0, void 0, destinationGridview);
|
|
17182
17574
|
this.movingLock(() => newGroup.model.openPanel(removedPanel, { skipSetGroupActive: true }));
|
|
17183
17575
|
this.doSetGroupAndPanelActive(newGroup);
|
|
17184
|
-
this.
|
|
17185
|
-
panel: removedPanel,
|
|
17186
|
-
from: sourceGroup
|
|
17187
|
-
});
|
|
17576
|
+
this.fireDidMovePanel(removedPanel, sourceGroup);
|
|
17188
17577
|
return;
|
|
17189
17578
|
}
|
|
17190
17579
|
const targetGroup = this.movingLock(() => this.doRemoveGroup(sourceGroup, {
|
|
@@ -17196,10 +17585,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
17196
17585
|
this.movingLock(() => this.doAddGroup(targetGroup, location, void 0, destinationGridview));
|
|
17197
17586
|
this.setGroupLocationForRoot(targetGroup, destinationGridview);
|
|
17198
17587
|
this.doSetGroupAndPanelActive(targetGroup);
|
|
17199
|
-
this.
|
|
17200
|
-
panel: this.getGroupPanel(sourceItemId),
|
|
17201
|
-
from: sourceGroup
|
|
17202
|
-
});
|
|
17588
|
+
this.fireDidMovePanel(this.getGroupPanel(sourceItemId), sourceGroup);
|
|
17203
17589
|
} else {
|
|
17204
17590
|
/**
|
|
17205
17591
|
* The group we are removing from has many panels, we need to remove the panels we are moving,
|
|
@@ -17214,10 +17600,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
17214
17600
|
const group = this.createGroupAtLocation(dropLocation, void 0, void 0, destinationGridview);
|
|
17215
17601
|
this.movingLock(() => group.model.openPanel(removedPanel, { skipSetGroupActive: true }));
|
|
17216
17602
|
this.doSetGroupAndPanelActive(group);
|
|
17217
|
-
this.
|
|
17218
|
-
panel: removedPanel,
|
|
17219
|
-
from: sourceGroup
|
|
17220
|
-
});
|
|
17603
|
+
this.fireDidMovePanel(removedPanel, sourceGroup);
|
|
17221
17604
|
}
|
|
17222
17605
|
}
|
|
17223
17606
|
}
|
|
@@ -17252,10 +17635,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
17252
17635
|
});
|
|
17253
17636
|
for (const panel of removedPanels) targetGroup.model.addPanelToTabGroup(newTabGroup.id, panel.id);
|
|
17254
17637
|
if (!options.skipSetActive) this.doSetGroupAndPanelActive(targetGroup);
|
|
17255
|
-
for (const panel of removedPanels) this.
|
|
17256
|
-
panel,
|
|
17257
|
-
from: sourceGroup
|
|
17258
|
-
});
|
|
17638
|
+
for (const panel of removedPanels) this.fireDidMovePanel(panel, sourceGroup);
|
|
17259
17639
|
};
|
|
17260
17640
|
let targetGroup;
|
|
17261
17641
|
if (!destinationTarget || destinationTarget === "center" || !referenceLocation) targetGroup = destinationGroup;
|
|
@@ -17276,10 +17656,12 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
17276
17656
|
this.mutation("maximize", () => super.exitMaximizedGroup());
|
|
17277
17657
|
}
|
|
17278
17658
|
_doMoveGroup(options) {
|
|
17659
|
+
var _mergedPanels;
|
|
17279
17660
|
const from = options.from.group;
|
|
17280
17661
|
const to = options.to.group;
|
|
17281
17662
|
const target = options.to.position;
|
|
17282
17663
|
let source = from;
|
|
17664
|
+
let mergedPanels;
|
|
17283
17665
|
if (target === "center") {
|
|
17284
17666
|
const activePanel = from.activePanel;
|
|
17285
17667
|
const tabGroupSnapshots = from.model.getTabGroups().map((tg) => ({
|
|
@@ -17297,6 +17679,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
17297
17679
|
skipSetGroupActive: true
|
|
17298
17680
|
});
|
|
17299
17681
|
});
|
|
17682
|
+
mergedPanels = panels;
|
|
17300
17683
|
for (const snapshot of tabGroupSnapshots) {
|
|
17301
17684
|
const newTabGroup = to.model.createTabGroup({
|
|
17302
17685
|
label: snapshot.label,
|
|
@@ -17386,11 +17769,8 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
17386
17769
|
this.setGroupLocationForRoot(source, destGridview);
|
|
17387
17770
|
}
|
|
17388
17771
|
}
|
|
17389
|
-
source.panels.forEach((panel) => {
|
|
17390
|
-
this.
|
|
17391
|
-
panel,
|
|
17392
|
-
from
|
|
17393
|
-
});
|
|
17772
|
+
((_mergedPanels = mergedPanels) !== null && _mergedPanels !== void 0 ? _mergedPanels : source.panels).forEach((panel) => {
|
|
17773
|
+
this.fireDidMovePanel(panel, from);
|
|
17394
17774
|
});
|
|
17395
17775
|
this.debouncedUpdateAllPositions();
|
|
17396
17776
|
if (options.skipSetActive === false) {
|