dockview 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/dockview.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* dockview
|
|
3
|
-
* @version 8.
|
|
3
|
+
* @version 8.2.0
|
|
4
4
|
* @link https://github.com/dockview/dockview
|
|
5
5
|
* @license MIT
|
|
6
6
|
*/
|
|
@@ -22,7 +22,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
22
22
|
//#region ../dockview-core/dist/package/main.esm.mjs
|
|
23
23
|
/**
|
|
24
24
|
* dockview-core
|
|
25
|
-
* @version 8.
|
|
25
|
+
* @version 8.2.0
|
|
26
26
|
* @link https://github.com/dockview/dockview
|
|
27
27
|
* @license MIT
|
|
28
28
|
*/
|
|
@@ -10366,7 +10366,11 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
10366
10366
|
this.panels.forEach((panel) => {
|
|
10367
10367
|
this.rerender(panel);
|
|
10368
10368
|
});
|
|
10369
|
-
if (this._activePanel)
|
|
10369
|
+
if (this._activePanel) {
|
|
10370
|
+
this.contentContainer.renderPanel(this._activePanel, { asActive: true });
|
|
10371
|
+
const { width, height } = this.contentDimensions();
|
|
10372
|
+
this._activePanel.layout(width, height);
|
|
10373
|
+
}
|
|
10370
10374
|
}
|
|
10371
10375
|
get renderContainer() {
|
|
10372
10376
|
var _this$_overwriteRende;
|
|
@@ -11313,7 +11317,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
11313
11317
|
this._group = value;
|
|
11314
11318
|
this._onDidGroupChange.fire({});
|
|
11315
11319
|
this.setupGroupEventListeners(oldGroup);
|
|
11316
|
-
this.
|
|
11320
|
+
this.fireLocationChange();
|
|
11317
11321
|
}
|
|
11318
11322
|
}
|
|
11319
11323
|
get group() {
|
|
@@ -11389,6 +11393,23 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
11389
11393
|
exitMaximized() {
|
|
11390
11394
|
this.group.api.exitMaximized();
|
|
11391
11395
|
}
|
|
11396
|
+
/**
|
|
11397
|
+
* Report that this panel's location may have moved.
|
|
11398
|
+
*
|
|
11399
|
+
* A relocation touches the location more than once - the panel is
|
|
11400
|
+
* reparented into the destination group, then that group is tagged with
|
|
11401
|
+
* the location it ends up at - so the event is coalesced to the end of the
|
|
11402
|
+
* enclosing layout mutation and reports where the panel actually settled.
|
|
11403
|
+
* Firing each signal as it happened surfaced an intermediate `grid`
|
|
11404
|
+
* location the panel was never in, at a point where it was in neither
|
|
11405
|
+
* group's panel list. Outside a mutation this fires straight away.
|
|
11406
|
+
*/
|
|
11407
|
+
fireLocationChange() {
|
|
11408
|
+
this.accessor.deferLocationChange(this, () => {
|
|
11409
|
+
if (this.isDisposed) return;
|
|
11410
|
+
this._onDidLocationChange.fire({ location: this.location });
|
|
11411
|
+
});
|
|
11412
|
+
}
|
|
11392
11413
|
setupGroupEventListeners(previousGroup) {
|
|
11393
11414
|
var _previousGroup$isActi;
|
|
11394
11415
|
let _trackGroupActive = (_previousGroup$isActi = previousGroup === null || previousGroup === void 0 ? void 0 : previousGroup.isActive) !== null && _previousGroup$isActi !== void 0 ? _previousGroup$isActi : false;
|
|
@@ -11397,9 +11418,9 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
11397
11418
|
const hasBecomeVisible = event.isVisible && !this.isVisible;
|
|
11398
11419
|
const isActivePanel = this.group.model.isPanelActive(this.panel);
|
|
11399
11420
|
if (hasBecomeHidden || hasBecomeVisible && isActivePanel) this._onDidVisibilityChange.fire(event);
|
|
11400
|
-
}), this.group.api.onDidLocationChange((
|
|
11421
|
+
}), this.group.api.onDidLocationChange(() => {
|
|
11401
11422
|
if (this.group !== this.panel.group) return;
|
|
11402
|
-
this.
|
|
11423
|
+
this.fireLocationChange();
|
|
11403
11424
|
}), this.group.api.onDidActiveChange(() => {
|
|
11404
11425
|
if (this.group !== this.panel.group) return;
|
|
11405
11426
|
if (_trackGroupActive !== this.isGroupActive) {
|
|
@@ -13359,6 +13380,13 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
13359
13380
|
});
|
|
13360
13381
|
}
|
|
13361
13382
|
};
|
|
13383
|
+
/**
|
|
13384
|
+
* Placeholder handle marking "a reposition frame has been requested but the
|
|
13385
|
+
* real handle is not known yet". Never passed to `cancelAnimationFrame` in
|
|
13386
|
+
* practice — it is replaced within the same synchronous block — and harmless
|
|
13387
|
+
* if it were, since no frame carries this id.
|
|
13388
|
+
*/
|
|
13389
|
+
const SCHEDULED = -1;
|
|
13362
13390
|
function createFocusableElement() {
|
|
13363
13391
|
const element = document.createElement("div");
|
|
13364
13392
|
element.tabIndex = -1;
|
|
@@ -13371,12 +13399,13 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
13371
13399
|
this.accessor = accessor;
|
|
13372
13400
|
this.map = {};
|
|
13373
13401
|
this._disposed = false;
|
|
13402
|
+
this._generation = 0;
|
|
13374
13403
|
this.positionCache = new PositionCache();
|
|
13375
|
-
this.pendingUpdates = /* @__PURE__ */ new Set();
|
|
13376
13404
|
this.addDisposables(Disposable.from(() => {
|
|
13377
13405
|
for (const value of Object.values(this.map)) {
|
|
13378
13406
|
value.disposable.dispose();
|
|
13379
13407
|
value.destroy.dispose();
|
|
13408
|
+
this.cancelPendingUpdate(value);
|
|
13380
13409
|
}
|
|
13381
13410
|
this._disposed = true;
|
|
13382
13411
|
}));
|
|
@@ -13403,11 +13432,24 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
13403
13432
|
this.positionCache.invalidate();
|
|
13404
13433
|
(_entry$resize = entry.resize) === null || _entry$resize === void 0 || _entry$resize.call(entry);
|
|
13405
13434
|
}
|
|
13435
|
+
/**
|
|
13436
|
+
* Drop the reposition frame queued for a panel, if any. A queued frame is
|
|
13437
|
+
* bound to the reference container that was current when it was scheduled,
|
|
13438
|
+
* so it must be discarded whenever that container stops being the one the
|
|
13439
|
+
* overlay should track.
|
|
13440
|
+
*/
|
|
13441
|
+
cancelPendingUpdate(entry) {
|
|
13442
|
+
if (entry.pendingUpdate !== void 0) {
|
|
13443
|
+
cancelAnimationFrame(entry.pendingUpdate);
|
|
13444
|
+
entry.pendingUpdate = void 0;
|
|
13445
|
+
}
|
|
13446
|
+
}
|
|
13406
13447
|
detatch(panel) {
|
|
13407
13448
|
if (this.map[panel.api.id]) {
|
|
13408
|
-
const
|
|
13409
|
-
disposable.dispose();
|
|
13410
|
-
destroy.dispose();
|
|
13449
|
+
const entry = this.map[panel.api.id];
|
|
13450
|
+
entry.disposable.dispose();
|
|
13451
|
+
entry.destroy.dispose();
|
|
13452
|
+
this.cancelPendingUpdate(entry);
|
|
13411
13453
|
delete this.map[panel.api.id];
|
|
13412
13454
|
return true;
|
|
13413
13455
|
}
|
|
@@ -13423,22 +13465,73 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
13423
13465
|
panel,
|
|
13424
13466
|
disposable: Disposable.NONE,
|
|
13425
13467
|
destroy: Disposable.NONE,
|
|
13426
|
-
element
|
|
13468
|
+
element,
|
|
13469
|
+
retainPreviousGeometry: false,
|
|
13470
|
+
positioned: false,
|
|
13471
|
+
generation: ++this._generation
|
|
13427
13472
|
};
|
|
13428
13473
|
}
|
|
13429
|
-
const
|
|
13474
|
+
const mapEntry = this.map[panel.api.id];
|
|
13475
|
+
/**
|
|
13476
|
+
* A *change* of reference container supersedes the previous `attach`:
|
|
13477
|
+
* take a fresh generation so its `resize` closure can no longer run,
|
|
13478
|
+
* and drop the frame it queued against the old container. During
|
|
13479
|
+
* `fromJSON({ reuseExistingPanels: true })` that old container is a
|
|
13480
|
+
* detached staging group measuring 0x0, so leaving its frame in flight
|
|
13481
|
+
* both wastes the update and delays the reposition against the real one.
|
|
13482
|
+
*
|
|
13483
|
+
* Re-attaching over the *same* container (re-open, active panel change)
|
|
13484
|
+
* deliberately leaves scheduled work alone: `repositionPanelOverlay`
|
|
13485
|
+
* (the auto-hide peek) schedules a frame carrying the sticky
|
|
13486
|
+
* `forceVisible`/`clip` state which `attach` does not re-apply, and a
|
|
13487
|
+
* peeked panel's `api.isVisible` is false — so discarding that frame
|
|
13488
|
+
* leaves `visibilityChanged` to hide the overlay and the peek renders
|
|
13489
|
+
* nothing. A newly created entry already holds a fresh generation, so
|
|
13490
|
+
* the stale closures a `detatch` left behind are fenced off either way.
|
|
13491
|
+
*/
|
|
13492
|
+
if (mapEntry.referenceContainer !== referenceContainer) {
|
|
13493
|
+
mapEntry.generation = ++this._generation;
|
|
13494
|
+
this.cancelPendingUpdate(mapEntry);
|
|
13495
|
+
mapEntry.referenceContainer = referenceContainer;
|
|
13496
|
+
/**
|
|
13497
|
+
* Arm the retain flag only here: it means "a replacement reference
|
|
13498
|
+
* container is awaiting layout", so the 0x0 early-return below
|
|
13499
|
+
* holds the last good box rather than blanking the panel mid-move.
|
|
13500
|
+
* Arming it on every re-attach instead would make a container that
|
|
13501
|
+
* genuinely collapses to zero keep its stale geometry forever.
|
|
13502
|
+
*
|
|
13503
|
+
* Gated on `positioned` because an overlay that has never been
|
|
13504
|
+
* positioned has no left/top/width/height, and `.dv-render-overlay`
|
|
13505
|
+
* defaults to 100%/100% — retaining "previous" geometry there would
|
|
13506
|
+
* pin the content over the whole container.
|
|
13507
|
+
*/
|
|
13508
|
+
mapEntry.retainPreviousGeometry = mapEntry.positioned;
|
|
13509
|
+
}
|
|
13510
|
+
const generation = mapEntry.generation;
|
|
13511
|
+
const focusContainer = mapEntry.element;
|
|
13430
13512
|
const contentElement = panel.view.content.element;
|
|
13431
13513
|
if (contentElement.parentElement !== focusContainer) focusContainer.appendChild(contentElement);
|
|
13432
13514
|
if (focusContainer.parentElement !== this.element) this.element.appendChild(focusContainer);
|
|
13433
13515
|
const resize = () => {
|
|
13434
13516
|
const panelId = panel.api.id;
|
|
13435
|
-
|
|
13436
|
-
|
|
13437
|
-
|
|
13517
|
+
const scheduling = this.map[panelId];
|
|
13518
|
+
if ((scheduling === null || scheduling === void 0 ? void 0 : scheduling.generation) !== generation) return;
|
|
13519
|
+
if (scheduling.pendingUpdate !== void 0) return;
|
|
13520
|
+
/**
|
|
13521
|
+
* Claim the slot *before* scheduling. `requestAnimationFrame` is
|
|
13522
|
+
* shimmed to run inline by some hosts (and by several suites here),
|
|
13523
|
+
* in which case the callback below clears `pendingUpdate` while
|
|
13524
|
+
* this call is still on the stack — assigning the handle afterwards
|
|
13525
|
+
* would resurrect a slot that is already spent and block every
|
|
13526
|
+
* later reposition. The sentinel is replaced by the real handle
|
|
13527
|
+
* only if the frame has not already run.
|
|
13528
|
+
*/
|
|
13529
|
+
scheduling.pendingUpdate = SCHEDULED;
|
|
13530
|
+
const handle = requestAnimationFrame(() => {
|
|
13438
13531
|
var _entry$forceVisible;
|
|
13439
|
-
this.pendingUpdates.delete(panelId);
|
|
13440
13532
|
const entry = this.map[panelId];
|
|
13441
|
-
if (
|
|
13533
|
+
if (entry) entry.pendingUpdate = void 0;
|
|
13534
|
+
if (this.isDisposed || (entry === null || entry === void 0 ? void 0 : entry.generation) !== generation) return;
|
|
13442
13535
|
const forceVisible = (_entry$forceVisible = entry.forceVisible) !== null && _entry$forceVisible !== void 0 ? _entry$forceVisible : false;
|
|
13443
13536
|
const clip = entry.clip;
|
|
13444
13537
|
const box = this.positionCache.getPosition(referenceContainer.element);
|
|
@@ -13447,6 +13540,15 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
13447
13540
|
const top = box.top - box2.top;
|
|
13448
13541
|
const width = box.width;
|
|
13449
13542
|
const height = box.height;
|
|
13543
|
+
if (entry.retainPreviousGeometry && (width === 0 || height === 0)) {
|
|
13544
|
+
if (!panel.api.isVisible && !forceVisible) {
|
|
13545
|
+
focusContainer.style.visibility = "hidden";
|
|
13546
|
+
focusContainer.style.pointerEvents = "none";
|
|
13547
|
+
}
|
|
13548
|
+
return;
|
|
13549
|
+
}
|
|
13550
|
+
entry.retainPreviousGeometry = false;
|
|
13551
|
+
entry.positioned = true;
|
|
13450
13552
|
focusContainer.style.left = `${left}px`;
|
|
13451
13553
|
focusContainer.style.top = `${top}px`;
|
|
13452
13554
|
focusContainer.style.width = `${width}px`;
|
|
@@ -13475,11 +13577,30 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
13475
13577
|
} else focusContainer.style.clipPath = "";
|
|
13476
13578
|
toggleClass(focusContainer, "dv-render-overlay-float", panel.group.api.location.type === "floating");
|
|
13477
13579
|
});
|
|
13580
|
+
if (scheduling.pendingUpdate === SCHEDULED) scheduling.pendingUpdate = handle;
|
|
13478
13581
|
};
|
|
13479
13582
|
const visibilityChanged = () => {
|
|
13480
13583
|
if (panel.api.isVisible) {
|
|
13584
|
+
var _this$map$panel$api$i;
|
|
13481
13585
|
this.positionCache.invalidate();
|
|
13482
13586
|
resize();
|
|
13587
|
+
/**
|
|
13588
|
+
* Existing geometry is safe to show while its replacement lays
|
|
13589
|
+
* out. `retainPreviousGeometry` is only set when geometry has
|
|
13590
|
+
* actually been written (see `attach`), so this can never
|
|
13591
|
+
* un-hide an overlay whose left/top/width/height are unset —
|
|
13592
|
+
* `.dv-render-overlay` is 100%/100% by default and would
|
|
13593
|
+
* otherwise cover the whole dock.
|
|
13594
|
+
*
|
|
13595
|
+
* The retained geometry is the panel's position in the previous
|
|
13596
|
+
* layout, so restoring a layout that moves the panel does paint
|
|
13597
|
+
* it at stale coordinates until the reposition lands. That is
|
|
13598
|
+
* bounded to the next frame now that a superseded `attach` can
|
|
13599
|
+
* no longer swallow the reposition (see `attach`); showing
|
|
13600
|
+
* stale-but-real geometry for a frame is the deliberate
|
|
13601
|
+
* trade-off against blanking the panel for the whole rebuild.
|
|
13602
|
+
*/
|
|
13603
|
+
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 = "";
|
|
13483
13604
|
focusContainer.style.pointerEvents = "";
|
|
13484
13605
|
} else {
|
|
13485
13606
|
focusContainer.style.visibility = "hidden";
|
|
@@ -13696,7 +13817,17 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
13696
13817
|
window: externalWindow
|
|
13697
13818
|
});
|
|
13698
13819
|
return new Promise((resolve, reject) => {
|
|
13699
|
-
externalWindow.addEventListener("unload", (
|
|
13820
|
+
externalWindow.addEventListener("unload", () => {});
|
|
13821
|
+
/**
|
|
13822
|
+
* `load` is the only event that resolves this promise with a
|
|
13823
|
+
* container, so a window that goes away first would leave the
|
|
13824
|
+
* caller awaiting a promise that never settles - and
|
|
13825
|
+
* `addPopoutGroup` holds its layout transaction open until it does.
|
|
13826
|
+
* Settle with `null` on close, the same signal a blocked popup
|
|
13827
|
+
* gives and one the caller already handles. `resolve` after the
|
|
13828
|
+
* fact is a no-op, so a `load` that arrived first still wins.
|
|
13829
|
+
*/
|
|
13830
|
+
disposable.addDisposables(_this.onWillClose(() => resolve(null)));
|
|
13700
13831
|
externalWindow.addEventListener("load", () => {
|
|
13701
13832
|
/**
|
|
13702
13833
|
* @see https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event
|
|
@@ -15096,6 +15227,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
15096
15227
|
this._onWillDrop = new Emitter();
|
|
15097
15228
|
this.onWillDrop = this._onWillDrop.event;
|
|
15098
15229
|
this._mutationDepth = 0;
|
|
15230
|
+
this._pendingLocationChanges = /* @__PURE__ */ new Map();
|
|
15099
15231
|
this._origin = "user";
|
|
15100
15232
|
this._originDepth = 0;
|
|
15101
15233
|
this._onWillMutateLayout = new Emitter();
|
|
@@ -15193,7 +15325,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
15193
15325
|
toggleClass(this.element, "dv-debug", !!options.debug);
|
|
15194
15326
|
this.updateTheme();
|
|
15195
15327
|
if (options.debug) this.addDisposables(new StrictEventsSequencing(this));
|
|
15196
|
-
this.addDisposables(this.rootDropTargetContainer, this.floatingDropTargetContainer, addDisposableListener(this._shellManager.element, "dragend", () => {
|
|
15328
|
+
this.addDisposables(Disposable.from(() => this._pendingLocationChanges.clear()), this.rootDropTargetContainer, this.floatingDropTargetContainer, addDisposableListener(this._shellManager.element, "dragend", () => {
|
|
15197
15329
|
var _this$rootDropTargetC2, _this$floatingDropTar;
|
|
15198
15330
|
(_this$rootDropTargetC2 = this.rootDropTargetContainer.model) === null || _this$rootDropTargetC2 === void 0 || _this$rootDropTargetC2.clear();
|
|
15199
15331
|
(_this$floatingDropTar = this.floatingDropTargetContainer.model) === null || _this$floatingDropTar === void 0 || _this$floatingDropTar.clear();
|
|
@@ -15267,7 +15399,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
15267
15399
|
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;
|
|
15268
15400
|
}
|
|
15269
15401
|
addPopoutGroup(itemToPopout, options) {
|
|
15270
|
-
return this.
|
|
15402
|
+
return this.mutationAsync("popout", () => this._doAddPopoutGroup(itemToPopout, options));
|
|
15271
15403
|
}
|
|
15272
15404
|
/** Enumerate the popout groups currently open in their own windows. */
|
|
15273
15405
|
getPopouts() {
|
|
@@ -15364,15 +15496,32 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
15364
15496
|
}
|
|
15365
15497
|
};
|
|
15366
15498
|
let floatingBox;
|
|
15367
|
-
|
|
15368
|
-
|
|
15369
|
-
|
|
15370
|
-
|
|
15371
|
-
|
|
15499
|
+
/**
|
|
15500
|
+
* Popping out rehomes panels into `group`, so like the floating
|
|
15501
|
+
* case it owes the caller an `onDidMovePanel` per panel. The
|
|
15502
|
+
* events are deferred until the window is wired up so listeners
|
|
15503
|
+
* observe the panels' final `popout` location.
|
|
15504
|
+
*/
|
|
15505
|
+
let movedPanels = [];
|
|
15506
|
+
if (!(options === null || options === void 0 ? void 0 : options.overridePopoutGroup) && !(options === null || options === void 0 ? void 0 : options.overridePopoutGridview) && isGroupAddedToDom) if (itemToPopout instanceof DockviewPanel) {
|
|
15507
|
+
const sourceGroup = itemToPopout.group;
|
|
15508
|
+
this.movingLock(() => {
|
|
15509
|
+
const panel = referenceGroup.model.removePanel(itemToPopout);
|
|
15510
|
+
group.model.openPanel(panel);
|
|
15511
|
+
});
|
|
15512
|
+
movedPanels = [{
|
|
15513
|
+
panel: itemToPopout,
|
|
15514
|
+
from: sourceGroup
|
|
15515
|
+
}];
|
|
15516
|
+
} else {
|
|
15372
15517
|
this.movingLock(() => moveGroupWithoutDestroying({
|
|
15373
15518
|
from: referenceGroup,
|
|
15374
15519
|
to: group
|
|
15375
15520
|
}));
|
|
15521
|
+
movedPanels = group.panels.map((panel) => ({
|
|
15522
|
+
panel,
|
|
15523
|
+
from: referenceGroup
|
|
15524
|
+
}));
|
|
15376
15525
|
switch (referenceLocation) {
|
|
15377
15526
|
case "grid":
|
|
15378
15527
|
referenceGroup.api.setVisible(false);
|
|
@@ -15481,6 +15630,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
15481
15630
|
group: value.popoutGroup,
|
|
15482
15631
|
window: value.getWindow()
|
|
15483
15632
|
});
|
|
15633
|
+
for (const { panel, from } of movedPanels) this.fireDidMovePanel(panel, from);
|
|
15484
15634
|
return true;
|
|
15485
15635
|
}).catch((err) => {
|
|
15486
15636
|
console.error("dockview: failed to create popout.", err);
|
|
@@ -15558,6 +15708,16 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
15558
15708
|
const members = this.groups.filter((candidate) => popoutGridview.element.contains(candidate.element));
|
|
15559
15709
|
const anchorPresent = members.includes(group);
|
|
15560
15710
|
const anchorIsSoleMember = anchorPresent && members.length === 1;
|
|
15711
|
+
/**
|
|
15712
|
+
* Popping a group out fires `onDidMovePanel` per panel, so closing the
|
|
15713
|
+
* window owes the caller the same: every panel in it is rehomed, into
|
|
15714
|
+
* the reference group the popout left behind or into a fresh grid slot.
|
|
15715
|
+
* `movingLock` suppresses onDidAddPanel / onDidRemovePanel on these
|
|
15716
|
+
* paths, so `onDidMovePanel` is the only event that can carry it. The
|
|
15717
|
+
* events are deferred to the end so listeners observe the panels at
|
|
15718
|
+
* their final group and location.
|
|
15719
|
+
*/
|
|
15720
|
+
const movedPanels = [];
|
|
15561
15721
|
if (genuineClose) for (const member of members) {
|
|
15562
15722
|
if (member === group) continue;
|
|
15563
15723
|
this.movingLock(() => {
|
|
@@ -15568,12 +15728,21 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
15568
15728
|
});
|
|
15569
15729
|
this.redockGroupToMainGrid(member);
|
|
15570
15730
|
});
|
|
15731
|
+
for (const panel of member.panels) movedPanels.push({
|
|
15732
|
+
panel,
|
|
15733
|
+
from: member
|
|
15734
|
+
});
|
|
15571
15735
|
}
|
|
15572
15736
|
if (anchorPresent && isGroupAddedToDom && this.getPanel(referenceGroup.id)) {
|
|
15737
|
+
const rehomed = [...group.panels];
|
|
15573
15738
|
this.movingLock(() => moveGroupWithoutDestroying({
|
|
15574
15739
|
from: group,
|
|
15575
15740
|
to: referenceGroup
|
|
15576
15741
|
}));
|
|
15742
|
+
for (const panel of rehomed) movedPanels.push({
|
|
15743
|
+
panel,
|
|
15744
|
+
from: group
|
|
15745
|
+
});
|
|
15577
15746
|
if (!referenceGroup.api.isVisible) referenceGroup.api.setVisible(true);
|
|
15578
15747
|
if (this.getPanel(group.id)) this.doRemoveGroup(group, { skipPopoutAssociated: true });
|
|
15579
15748
|
} else if (anchorPresent && this.getPanel(group.id)) {
|
|
@@ -15604,10 +15773,15 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
15604
15773
|
this.movingLock(() => {
|
|
15605
15774
|
this.doAddGroup(group, [0]);
|
|
15606
15775
|
});
|
|
15776
|
+
for (const panel of group.panels) movedPanels.push({
|
|
15777
|
+
panel,
|
|
15778
|
+
from: group
|
|
15779
|
+
});
|
|
15607
15780
|
}
|
|
15608
15781
|
this.doSetGroupAndPanelActive(group);
|
|
15609
15782
|
}
|
|
15610
15783
|
disposePopoutGridview();
|
|
15784
|
+
for (const { panel, from } of movedPanels) this.fireDidMovePanel(panel, from);
|
|
15611
15785
|
}
|
|
15612
15786
|
addFloatingGroup(item, options) {
|
|
15613
15787
|
this.mutation("float", () => this._doAddFloatingGroup(item, options));
|
|
@@ -15616,7 +15790,15 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
15616
15790
|
if (!assertModule(this._floatingGroupService, "FloatingGroup", "api.addFloatingGroup")) return;
|
|
15617
15791
|
if (item instanceof DockviewGroupPanel && item.model.location.type === "edge") return;
|
|
15618
15792
|
let group;
|
|
15793
|
+
/**
|
|
15794
|
+
* Floating relocates panels exactly like a drop onto the grid does, so
|
|
15795
|
+
* it owes the caller an `onDidMovePanel` per panel. The events are
|
|
15796
|
+
* deferred until the window is mounted below: only then do the panels
|
|
15797
|
+
* report their final `floating` location.
|
|
15798
|
+
*/
|
|
15799
|
+
let movedPanels = [];
|
|
15619
15800
|
if (item instanceof DockviewPanel) {
|
|
15801
|
+
const sourceGroup = item.group;
|
|
15620
15802
|
group = this.createGroup();
|
|
15621
15803
|
this._onDidAddGroup.fire(group);
|
|
15622
15804
|
this.movingLock(() => this.removePanel(item, {
|
|
@@ -15625,6 +15807,10 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
15625
15807
|
skipSetActiveGroup: true
|
|
15626
15808
|
}));
|
|
15627
15809
|
this.movingLock(() => group.model.openPanel(item, { skipSetGroupActive: true }));
|
|
15810
|
+
movedPanels = [{
|
|
15811
|
+
panel: item,
|
|
15812
|
+
from: sourceGroup
|
|
15813
|
+
}];
|
|
15628
15814
|
} else {
|
|
15629
15815
|
var _this$_popoutWindowSe8;
|
|
15630
15816
|
group = item;
|
|
@@ -15641,11 +15827,21 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
15641
15827
|
});
|
|
15642
15828
|
this.doRemoveGroup(popoutReferenceGroup, { skipDispose: true });
|
|
15643
15829
|
group = popoutReferenceGroup;
|
|
15644
|
-
|
|
15645
|
-
|
|
15646
|
-
|
|
15647
|
-
|
|
15648
|
-
}
|
|
15830
|
+
movedPanels = group.panels.map((panel) => ({
|
|
15831
|
+
panel,
|
|
15832
|
+
from: item
|
|
15833
|
+
}));
|
|
15834
|
+
} else {
|
|
15835
|
+
this.doRemoveGroup(item, {
|
|
15836
|
+
skipDispose: true,
|
|
15837
|
+
skipPopoutReturn: true,
|
|
15838
|
+
skipPopoutAssociated: false
|
|
15839
|
+
});
|
|
15840
|
+
movedPanels = group.panels.map((panel) => ({
|
|
15841
|
+
panel,
|
|
15842
|
+
from: group
|
|
15843
|
+
}));
|
|
15844
|
+
}
|
|
15649
15845
|
}
|
|
15650
15846
|
function getAnchoredBox() {
|
|
15651
15847
|
if (options === null || options === void 0 ? void 0 : options.position) {
|
|
@@ -15678,6 +15874,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
15678
15874
|
skipActiveGroup: options === null || options === void 0 ? void 0 : options.skipActiveGroup,
|
|
15679
15875
|
disableSmartGuides: options === null || options === void 0 ? void 0 : options.disableSmartGuides
|
|
15680
15876
|
});
|
|
15877
|
+
for (const { panel, from } of movedPanels) this.fireDidMovePanel(panel, from);
|
|
15681
15878
|
}
|
|
15682
15879
|
/**
|
|
15683
15880
|
* Build an empty gridview configured to match the main grid's styling, for
|
|
@@ -16109,35 +16306,119 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
16109
16306
|
if (typeof data !== "object" || data === null) throw new Error("dockview: serialized layout must be a non-null object");
|
|
16110
16307
|
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");
|
|
16111
16308
|
const existingPanels = /* @__PURE__ */ new Map();
|
|
16112
|
-
|
|
16309
|
+
const temporaryGroups = /* @__PURE__ */ new Map();
|
|
16310
|
+
const stagedPanels = [];
|
|
16311
|
+
const temporaryGroupDisposables = [];
|
|
16312
|
+
/**
|
|
16313
|
+
* The staging groups are detached from `_groups` and never enter the
|
|
16314
|
+
* grid, so nothing else will ever tear them down.
|
|
16315
|
+
*
|
|
16316
|
+
* `dispose()` reaches consumer `IContentRenderer.dispose()`, so one
|
|
16317
|
+
* throwing renderer must not abort the rest of the cleanup — that would
|
|
16318
|
+
* re-introduce the very leak this reclaims — nor replace the
|
|
16319
|
+
* deserialization error the caller is being given. Draining the list
|
|
16320
|
+
* also makes this safe to call more than once.
|
|
16321
|
+
*/
|
|
16322
|
+
const disposeTemporaryGroups = () => {
|
|
16323
|
+
for (const disposable of temporaryGroupDisposables) try {
|
|
16324
|
+
disposable.dispose();
|
|
16325
|
+
} catch (err) {
|
|
16326
|
+
console.error("dockview: failed to dispose a temporary group created for reuseExistingPanels", err);
|
|
16327
|
+
}
|
|
16328
|
+
temporaryGroupDisposables.length = 0;
|
|
16329
|
+
};
|
|
16113
16330
|
if (options === null || options === void 0 ? void 0 : options.reuseExistingPanels) {
|
|
16114
16331
|
/**
|
|
16115
|
-
*
|
|
16116
|
-
*
|
|
16117
|
-
*
|
|
16118
|
-
* 2. Remove that temporary group from the group mapping so that it doesn't get cleared when we clear the layout
|
|
16332
|
+
* Visible, always-rendered panels need individual staging groups
|
|
16333
|
+
* to remain active. Other reused panels can share a staging group.
|
|
16334
|
+
* The staging groups are excluded from the layout clear below.
|
|
16119
16335
|
*/
|
|
16120
|
-
tempGroup = this.createGroup();
|
|
16121
|
-
this._groups.delete(tempGroup.api.id);
|
|
16122
16336
|
const newPanels = Object.keys(data.panels);
|
|
16123
|
-
|
|
16124
|
-
|
|
16125
|
-
|
|
16126
|
-
|
|
16127
|
-
|
|
16128
|
-
|
|
16129
|
-
|
|
16130
|
-
|
|
16131
|
-
|
|
16132
|
-
|
|
16133
|
-
|
|
16134
|
-
|
|
16135
|
-
|
|
16337
|
+
let sharedTemporaryGroup;
|
|
16338
|
+
const createTemporaryGroup = () => {
|
|
16339
|
+
const temporaryGroup = this.createGroup();
|
|
16340
|
+
/**
|
|
16341
|
+
* Removing the group from `_groups` also drops the record's
|
|
16342
|
+
* `CompositeDisposable`, so capture it first and tear both it
|
|
16343
|
+
* and the group down in the `finally` below. Left undisposed a
|
|
16344
|
+
* staging group leaks its `ResizeObserver`, its
|
|
16345
|
+
* `onDidOptionsChange` subscription (retained by this
|
|
16346
|
+
* component's emitter) and the watermark its model mounts when
|
|
16347
|
+
* the group empties — once per reused panel, per `fromJSON`.
|
|
16348
|
+
*/
|
|
16349
|
+
const record = this._groups.get(temporaryGroup.api.id);
|
|
16350
|
+
this._groups.delete(temporaryGroup.api.id);
|
|
16351
|
+
temporaryGroupDisposables.push(Disposable.from(() => {
|
|
16352
|
+
/**
|
|
16353
|
+
* Reclaim the group's own resources, never its panels.
|
|
16354
|
+
* Staging is driven by the ids in `data.panels` while
|
|
16355
|
+
* reclaiming is driven by the group `views` that
|
|
16356
|
+
* reference them, so a panel whose state is present but
|
|
16357
|
+
* unreferenced is still staged here — and `dispose()`
|
|
16358
|
+
* on a non-empty group reaches the consumer's
|
|
16359
|
+
* `IContentRenderer.dispose()`. Emptying the group
|
|
16360
|
+
* first leaves those panels exactly as they were before
|
|
16361
|
+
* this teardown existed, which also keeps this safe
|
|
16362
|
+
* against any future path that rebuilds a panel under
|
|
16363
|
+
* an id that is live in the new layout.
|
|
16364
|
+
*/
|
|
16365
|
+
this.movingLock(() => {
|
|
16366
|
+
for (const panel of temporaryGroup.panels.slice()) temporaryGroup.model.removePanel(panel);
|
|
16367
|
+
});
|
|
16368
|
+
record === null || record === void 0 || record.disposable.dispose();
|
|
16369
|
+
temporaryGroup.dispose();
|
|
16370
|
+
}));
|
|
16371
|
+
return temporaryGroup;
|
|
16372
|
+
};
|
|
16373
|
+
/**
|
|
16374
|
+
* Staging and the clear below run before the deserialization
|
|
16375
|
+
* `try`, so a throw here (a consumer `onDidRemovePanel` handler, a
|
|
16376
|
+
* renderer teardown during `clear`) would escape without reclaiming
|
|
16377
|
+
* the staging groups already created.
|
|
16378
|
+
*
|
|
16379
|
+
* The creation loop is inside the guard too, not just the moves and
|
|
16380
|
+
* the clear: `createGroup()` reaches consumer code of its own —
|
|
16381
|
+
* `initialize()` mounts the watermark through
|
|
16382
|
+
* `createWatermarkComponent()` — so a throw on the n-th panel would
|
|
16383
|
+
* otherwise strand the n-1 staging groups already built.
|
|
16384
|
+
*/
|
|
16385
|
+
try {
|
|
16386
|
+
for (const panel of this.panels) if (newPanels.includes(panel.api.id)) {
|
|
16387
|
+
existingPanels.set(panel.api.id, panel);
|
|
16388
|
+
let temporaryGroup;
|
|
16389
|
+
if (panel.api.renderer === "always" && panel.api.isVisible) temporaryGroup = createTemporaryGroup();
|
|
16390
|
+
else {
|
|
16391
|
+
var _sharedTemporaryGroup;
|
|
16392
|
+
(_sharedTemporaryGroup = sharedTemporaryGroup) !== null && _sharedTemporaryGroup !== void 0 || (sharedTemporaryGroup = createTemporaryGroup());
|
|
16393
|
+
temporaryGroup = sharedTemporaryGroup;
|
|
16394
|
+
}
|
|
16395
|
+
temporaryGroups.set(panel.api.id, temporaryGroup);
|
|
16396
|
+
stagedPanels.push({
|
|
16397
|
+
panel,
|
|
16398
|
+
temporaryGroup
|
|
16399
|
+
});
|
|
16400
|
+
}
|
|
16401
|
+
this.movingLock(() => {
|
|
16402
|
+
stagedPanels.forEach(({ panel, temporaryGroup }) => {
|
|
16403
|
+
this.moveGroupOrPanel({
|
|
16404
|
+
from: {
|
|
16405
|
+
groupId: panel.api.group.api.id,
|
|
16406
|
+
panelId: panel.api.id
|
|
16407
|
+
},
|
|
16408
|
+
to: {
|
|
16409
|
+
group: temporaryGroup,
|
|
16410
|
+
position: "center"
|
|
16411
|
+
},
|
|
16412
|
+
keepEmptyGroups: true
|
|
16413
|
+
});
|
|
16136
16414
|
});
|
|
16137
16415
|
});
|
|
16138
|
-
|
|
16139
|
-
|
|
16140
|
-
|
|
16416
|
+
this.clear();
|
|
16417
|
+
} catch (err) {
|
|
16418
|
+
disposeTemporaryGroups();
|
|
16419
|
+
throw err;
|
|
16420
|
+
}
|
|
16421
|
+
} else this.clear();
|
|
16141
16422
|
const { grid, panels, activeGroup } = data;
|
|
16142
16423
|
try {
|
|
16143
16424
|
var _data$floatingGroups, _data$popoutGroups, _this$_popoutWindowSe12, _this$_floatingGroupS5, _this$_watermarkServi2;
|
|
@@ -16169,9 +16450,10 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
16169
16450
|
* due to a corruption of input data.
|
|
16170
16451
|
*/
|
|
16171
16452
|
const existingPanel = existingPanels.get(child);
|
|
16172
|
-
|
|
16453
|
+
const temporaryGroup = temporaryGroups.get(child);
|
|
16454
|
+
if (temporaryGroup && existingPanel) {
|
|
16173
16455
|
this.movingLock(() => {
|
|
16174
|
-
|
|
16456
|
+
temporaryGroup.model.removePanel(existingPanel);
|
|
16175
16457
|
});
|
|
16176
16458
|
createdPanels.push(existingPanel);
|
|
16177
16459
|
existingPanel.updateFromStateModel(panels[child]);
|
|
@@ -16201,7 +16483,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
16201
16483
|
return createGroupFromSerializedState(node.data);
|
|
16202
16484
|
} });
|
|
16203
16485
|
this._layoutFromShell(width, height);
|
|
16204
|
-
if (data.edgeGroups) this.deserializeEdgeGroups(data.edgeGroups, panels);
|
|
16486
|
+
if (data.edgeGroups) this.deserializeEdgeGroups(data.edgeGroups, panels, existingPanels, temporaryGroups);
|
|
16205
16487
|
this.deserializeFloatingWindows((_data$floatingGroups = data.floatingGroups) !== null && _data$floatingGroups !== void 0 ? _data$floatingGroups : [], createGroupFromSerializedState);
|
|
16206
16488
|
const popoutPromises = this.deserializePopoutWindows((_data$popoutGroups = data.popoutGroups) !== null && _data$popoutGroups !== void 0 ? _data$popoutGroups : [], createGroupFromSerializedState);
|
|
16207
16489
|
(_this$_popoutWindowSe12 = this._popoutWindowService) === null || _this$_popoutWindowSe12 === void 0 || _this$_popoutWindowSe12.finishRestoration(popoutPromises);
|
|
@@ -16238,6 +16520,8 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
16238
16520
|
* expect trying to load a corrupted layout to result in an error and not silently fail...
|
|
16239
16521
|
*/
|
|
16240
16522
|
throw err;
|
|
16523
|
+
} finally {
|
|
16524
|
+
disposeTemporaryGroups();
|
|
16241
16525
|
}
|
|
16242
16526
|
this.debouncedUpdateAllPositions();
|
|
16243
16527
|
this._onDidLayoutFromJSON.fire();
|
|
@@ -16260,7 +16544,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
16260
16544
|
members
|
|
16261
16545
|
};
|
|
16262
16546
|
}
|
|
16263
|
-
deserializeEdgeGroups(edgeGroups, panels) {
|
|
16547
|
+
deserializeEdgeGroups(edgeGroups, panels, existingPanels, temporaryGroups) {
|
|
16264
16548
|
const edgeService = assertModule(this._edgeGroupService, "EdgeGroup", "fromJSON edge restoration");
|
|
16265
16549
|
if (!edgeService) return;
|
|
16266
16550
|
for (const _position of [
|
|
@@ -16290,13 +16574,40 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
16290
16574
|
if (groupState) {
|
|
16291
16575
|
const { views, activeView } = groupState;
|
|
16292
16576
|
const createdPanels = [];
|
|
16293
|
-
for (const panelId of views)
|
|
16294
|
-
|
|
16295
|
-
|
|
16577
|
+
for (const panelId of views) {
|
|
16578
|
+
if (!panels[panelId]) continue;
|
|
16579
|
+
/**
|
|
16580
|
+
* Reclaim a staged panel rather than rebuilding it, the
|
|
16581
|
+
* same way the grid path does. Deserializing here instead
|
|
16582
|
+
* would honour `reuseExistingPanels` everywhere except edge
|
|
16583
|
+
* groups: the live panel keeps sitting in its staging group
|
|
16584
|
+
* while a second panel is built under the same id, so the
|
|
16585
|
+
* consumer's renderer for the original is orphaned — never
|
|
16586
|
+
* disposed, and its element left inside the id-keyed
|
|
16587
|
+
* overlay entry the replacement now shares.
|
|
16588
|
+
*/
|
|
16589
|
+
const existingPanel = existingPanels.get(panelId);
|
|
16590
|
+
const temporaryGroup = temporaryGroups.get(panelId);
|
|
16591
|
+
if (temporaryGroup && existingPanel) {
|
|
16592
|
+
this.movingLock(() => {
|
|
16593
|
+
temporaryGroup.model.removePanel(existingPanel);
|
|
16594
|
+
});
|
|
16595
|
+
createdPanels.push(existingPanel);
|
|
16596
|
+
existingPanel.updateFromStateModel(panels[panelId]);
|
|
16597
|
+
} else {
|
|
16598
|
+
const panel = this._deserializer.fromJSON(panels[panelId], edgeGroup);
|
|
16599
|
+
createdPanels.push(panel);
|
|
16600
|
+
}
|
|
16296
16601
|
}
|
|
16297
16602
|
for (const panel of createdPanels) {
|
|
16298
16603
|
const isActive = activeView === panel.id;
|
|
16299
|
-
|
|
16604
|
+
if (existingPanels.has(panel.api.id)) this.movingLock(() => {
|
|
16605
|
+
edgeGroup.model.openPanel(panel, {
|
|
16606
|
+
skipSetActive: !isActive,
|
|
16607
|
+
skipSetGroupActive: true
|
|
16608
|
+
});
|
|
16609
|
+
});
|
|
16610
|
+
else edgeGroup.model.openPanel(panel, {
|
|
16300
16611
|
skipSetActive: !isActive,
|
|
16301
16612
|
skipSetGroupActive: true
|
|
16302
16613
|
});
|
|
@@ -16720,22 +17031,100 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
16720
17031
|
* outermost mutation.
|
|
16721
17032
|
*/
|
|
16722
17033
|
mutation(kind, func) {
|
|
16723
|
-
const
|
|
17034
|
+
const close = this.openMutation(kind);
|
|
17035
|
+
try {
|
|
17036
|
+
return func();
|
|
17037
|
+
} finally {
|
|
17038
|
+
close();
|
|
17039
|
+
}
|
|
17040
|
+
}
|
|
17041
|
+
/**
|
|
17042
|
+
* `mutation()` for an operation whose work continues after the synchronous
|
|
17043
|
+
* call returns. The transaction stays open until the returned promise
|
|
17044
|
+
* settles, so everything the operation does - the group it adds, the panels
|
|
17045
|
+
* it relocates - lands inside the bracket, matching the synchronous
|
|
17046
|
+
* move / float paths.
|
|
17047
|
+
*/
|
|
17048
|
+
mutationAsync(kind, func) {
|
|
17049
|
+
var _this = this;
|
|
17050
|
+
return _asyncToGenerator(function* () {
|
|
17051
|
+
const close = _this.openMutation(kind);
|
|
17052
|
+
try {
|
|
17053
|
+
return yield func();
|
|
17054
|
+
} finally {
|
|
17055
|
+
close();
|
|
17056
|
+
}
|
|
17057
|
+
})();
|
|
17058
|
+
}
|
|
17059
|
+
/**
|
|
17060
|
+
* Open a transaction and return the function that closes it. Shared by the
|
|
17061
|
+
* synchronous and asynchronous brackets; the returned function must be
|
|
17062
|
+
* called exactly once.
|
|
17063
|
+
*
|
|
17064
|
+
* Both ends key off the depth counter reaching zero rather than off which
|
|
17065
|
+
* bracket opened first. For synchronous nesting the two are the same thing
|
|
17066
|
+
* - brackets close in the order they opened - but asynchronous transactions
|
|
17067
|
+
* can *overlap* rather than nest (two `addPopoutGroup` calls in flight at
|
|
17068
|
+
* once, or a restore staggering several), and there the first to open is
|
|
17069
|
+
* not the last to close. Reporting on the opener would fire `didMutate`
|
|
17070
|
+
* while the other transaction was still doing structural work, which is the
|
|
17071
|
+
* very thing the async bracket exists to prevent. Overlapping transactions
|
|
17072
|
+
* therefore report as one, tagged with the kind of the last to finish.
|
|
17073
|
+
*/
|
|
17074
|
+
openMutation(kind) {
|
|
16724
17075
|
const origin = this._origin;
|
|
16725
|
-
if (
|
|
17076
|
+
if (this._mutationDepth === 0) this._onWillMutateLayout.fire({
|
|
16726
17077
|
kind,
|
|
16727
17078
|
origin
|
|
16728
17079
|
});
|
|
16729
17080
|
this._mutationDepth++;
|
|
16730
|
-
|
|
16731
|
-
return func();
|
|
16732
|
-
} finally {
|
|
17081
|
+
return () => {
|
|
16733
17082
|
this._mutationDepth--;
|
|
16734
|
-
if (
|
|
16735
|
-
|
|
16736
|
-
|
|
16737
|
-
|
|
17083
|
+
if (this._mutationDepth === 0) {
|
|
17084
|
+
this.flushLocationChanges();
|
|
17085
|
+
this._onDidMutateLayout.fire({
|
|
17086
|
+
kind,
|
|
17087
|
+
origin
|
|
17088
|
+
});
|
|
17089
|
+
}
|
|
17090
|
+
};
|
|
17091
|
+
}
|
|
17092
|
+
/**
|
|
17093
|
+
* Coalesce a panel's `onDidLocationChange` to the end of the enclosing
|
|
17094
|
+
* transaction, or fire it immediately when no transaction is in flight.
|
|
17095
|
+
*
|
|
17096
|
+
* Relocating a panel touches its location twice: once as it is reparented
|
|
17097
|
+
* into the destination group - which, when that group has just been created
|
|
17098
|
+
* for a floating or popout window, has not been told where it lives yet -
|
|
17099
|
+
* and once as the group is tagged with its final location. Reporting each
|
|
17100
|
+
* signal as it happens therefore leaks an intermediate `grid` location the
|
|
17101
|
+
* panel was never in, at a moment when it belongs to neither group's panel
|
|
17102
|
+
* list and so is missing from `api.panels`.
|
|
17103
|
+
*
|
|
17104
|
+
* Deferring collapses those signals into a single event carrying the
|
|
17105
|
+
* settled location. Note the signals are deliberately *not* compared
|
|
17106
|
+
* against the panel's previous location: a panel can move between two
|
|
17107
|
+
* floating windows without its location type changing, and this event is
|
|
17108
|
+
* the only signal `OverlayRenderContainer` has to re-resolve the panel's
|
|
17109
|
+
* z-index against its new host window.
|
|
17110
|
+
*/
|
|
17111
|
+
deferLocationChange(key, fire) {
|
|
17112
|
+
if (this._mutationDepth === 0) {
|
|
17113
|
+
fire();
|
|
17114
|
+
return;
|
|
16738
17115
|
}
|
|
17116
|
+
this._pendingLocationChanges.set(key, fire);
|
|
17117
|
+
}
|
|
17118
|
+
/**
|
|
17119
|
+
* Report every panel whose location moved during the transaction that has
|
|
17120
|
+
* just closed. Each callback reads the panel's location at this point, so
|
|
17121
|
+
* what it reports is where the panel ended up.
|
|
17122
|
+
*/
|
|
17123
|
+
flushLocationChanges() {
|
|
17124
|
+
if (this._pendingLocationChanges.size === 0) return;
|
|
17125
|
+
const pending = Array.from(this._pendingLocationChanges.values());
|
|
17126
|
+
this._pendingLocationChanges.clear();
|
|
17127
|
+
for (const fire of pending) fire();
|
|
16739
17128
|
}
|
|
16740
17129
|
/**
|
|
16741
17130
|
* The origin of the operation currently in progress (`'user'` by default).
|
|
@@ -16776,6 +17165,18 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
16776
17165
|
origin: this._origin
|
|
16777
17166
|
});
|
|
16778
17167
|
}
|
|
17168
|
+
/**
|
|
17169
|
+
* Announce that `panel` has finished relocating. Must be called once the
|
|
17170
|
+
* move has settled: `to` is read from the panel's current group, so an
|
|
17171
|
+
* early call would report the source group as the destination.
|
|
17172
|
+
*/
|
|
17173
|
+
fireDidMovePanel(panel, from) {
|
|
17174
|
+
this._onDidMovePanel.fire({
|
|
17175
|
+
panel,
|
|
17176
|
+
from,
|
|
17177
|
+
to: panel.group
|
|
17178
|
+
});
|
|
17179
|
+
}
|
|
16779
17180
|
moveGroupOrPanel(options) {
|
|
16780
17181
|
this.mutation("move", () => this._doMoveGroupOrPanel(options));
|
|
16781
17182
|
}
|
|
@@ -16836,10 +17237,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
16836
17237
|
});
|
|
16837
17238
|
});
|
|
16838
17239
|
if (!options.skipSetActive) this.doSetGroupAndPanelActive(destinationGroup);
|
|
16839
|
-
this.
|
|
16840
|
-
panel: removedPanel,
|
|
16841
|
-
from: sourceGroup
|
|
16842
|
-
});
|
|
17240
|
+
this.fireDidMovePanel(removedPanel, sourceGroup);
|
|
16843
17241
|
} else {
|
|
16844
17242
|
/**
|
|
16845
17243
|
* Dropping a panel to the extremities of a group which will place that panel
|
|
@@ -16858,10 +17256,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
16858
17256
|
const [sourceParentLocation, from] = tail(getGridLocation(sourceGroup.element));
|
|
16859
17257
|
if (sequenceEquals(sourceParentLocation, targetParentLocation)) {
|
|
16860
17258
|
this.gridview.moveView(sourceParentLocation, from, to);
|
|
16861
|
-
this.
|
|
16862
|
-
panel: this.getGroupPanel(sourceItemId),
|
|
16863
|
-
from: sourceGroup
|
|
16864
|
-
});
|
|
17259
|
+
this.fireDidMovePanel(this.getGroupPanel(sourceItemId), sourceGroup);
|
|
16865
17260
|
return;
|
|
16866
17261
|
}
|
|
16867
17262
|
}
|
|
@@ -16892,10 +17287,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
16892
17287
|
const newGroup = this.createGroupAtLocation(updatedTargetLocation, void 0, void 0, destinationGridview);
|
|
16893
17288
|
this.movingLock(() => newGroup.model.openPanel(removedPanel, { skipSetActive: true }));
|
|
16894
17289
|
this.doSetGroupAndPanelActive(newGroup);
|
|
16895
|
-
this.
|
|
16896
|
-
panel: this.getGroupPanel(sourceItemId),
|
|
16897
|
-
from: sourceGroup
|
|
16898
|
-
});
|
|
17290
|
+
this.fireDidMovePanel(this.getGroupPanel(sourceItemId), sourceGroup);
|
|
16899
17291
|
return;
|
|
16900
17292
|
}
|
|
16901
17293
|
if (sourceGroup.api.location.type === "edge") {
|
|
@@ -16912,10 +17304,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
16912
17304
|
const newGroup = this.createGroupAtLocation(targetLocation, void 0, void 0, destinationGridview);
|
|
16913
17305
|
this.movingLock(() => newGroup.model.openPanel(removedPanel, { skipSetGroupActive: true }));
|
|
16914
17306
|
this.doSetGroupAndPanelActive(newGroup);
|
|
16915
|
-
this.
|
|
16916
|
-
panel: removedPanel,
|
|
16917
|
-
from: sourceGroup
|
|
16918
|
-
});
|
|
17307
|
+
this.fireDidMovePanel(removedPanel, sourceGroup);
|
|
16919
17308
|
return;
|
|
16920
17309
|
}
|
|
16921
17310
|
const targetGroup = this.movingLock(() => this.doRemoveGroup(sourceGroup, {
|
|
@@ -16927,10 +17316,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
16927
17316
|
this.movingLock(() => this.doAddGroup(targetGroup, location, void 0, destinationGridview));
|
|
16928
17317
|
this.setGroupLocationForRoot(targetGroup, destinationGridview);
|
|
16929
17318
|
this.doSetGroupAndPanelActive(targetGroup);
|
|
16930
|
-
this.
|
|
16931
|
-
panel: this.getGroupPanel(sourceItemId),
|
|
16932
|
-
from: sourceGroup
|
|
16933
|
-
});
|
|
17319
|
+
this.fireDidMovePanel(this.getGroupPanel(sourceItemId), sourceGroup);
|
|
16934
17320
|
} else {
|
|
16935
17321
|
/**
|
|
16936
17322
|
* The group we are removing from has many panels, we need to remove the panels we are moving,
|
|
@@ -16945,10 +17331,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
16945
17331
|
const group = this.createGroupAtLocation(dropLocation, void 0, void 0, destinationGridview);
|
|
16946
17332
|
this.movingLock(() => group.model.openPanel(removedPanel, { skipSetGroupActive: true }));
|
|
16947
17333
|
this.doSetGroupAndPanelActive(group);
|
|
16948
|
-
this.
|
|
16949
|
-
panel: removedPanel,
|
|
16950
|
-
from: sourceGroup
|
|
16951
|
-
});
|
|
17334
|
+
this.fireDidMovePanel(removedPanel, sourceGroup);
|
|
16952
17335
|
}
|
|
16953
17336
|
}
|
|
16954
17337
|
}
|
|
@@ -16983,10 +17366,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
16983
17366
|
});
|
|
16984
17367
|
for (const panel of removedPanels) targetGroup.model.addPanelToTabGroup(newTabGroup.id, panel.id);
|
|
16985
17368
|
if (!options.skipSetActive) this.doSetGroupAndPanelActive(targetGroup);
|
|
16986
|
-
for (const panel of removedPanels) this.
|
|
16987
|
-
panel,
|
|
16988
|
-
from: sourceGroup
|
|
16989
|
-
});
|
|
17369
|
+
for (const panel of removedPanels) this.fireDidMovePanel(panel, sourceGroup);
|
|
16990
17370
|
};
|
|
16991
17371
|
let targetGroup;
|
|
16992
17372
|
if (!destinationTarget || destinationTarget === "center" || !referenceLocation) targetGroup = destinationGroup;
|
|
@@ -17007,10 +17387,12 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
17007
17387
|
this.mutation("maximize", () => super.exitMaximizedGroup());
|
|
17008
17388
|
}
|
|
17009
17389
|
_doMoveGroup(options) {
|
|
17390
|
+
var _mergedPanels;
|
|
17010
17391
|
const from = options.from.group;
|
|
17011
17392
|
const to = options.to.group;
|
|
17012
17393
|
const target = options.to.position;
|
|
17013
17394
|
let source = from;
|
|
17395
|
+
let mergedPanels;
|
|
17014
17396
|
if (target === "center") {
|
|
17015
17397
|
const activePanel = from.activePanel;
|
|
17016
17398
|
const tabGroupSnapshots = from.model.getTabGroups().map((tg) => ({
|
|
@@ -17028,6 +17410,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
17028
17410
|
skipSetGroupActive: true
|
|
17029
17411
|
});
|
|
17030
17412
|
});
|
|
17413
|
+
mergedPanels = panels;
|
|
17031
17414
|
for (const snapshot of tabGroupSnapshots) {
|
|
17032
17415
|
const newTabGroup = to.model.createTabGroup({
|
|
17033
17416
|
label: snapshot.label,
|
|
@@ -17117,11 +17500,8 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
17117
17500
|
this.setGroupLocationForRoot(source, destGridview);
|
|
17118
17501
|
}
|
|
17119
17502
|
}
|
|
17120
|
-
source.panels.forEach((panel) => {
|
|
17121
|
-
this.
|
|
17122
|
-
panel,
|
|
17123
|
-
from
|
|
17124
|
-
});
|
|
17503
|
+
((_mergedPanels = mergedPanels) !== null && _mergedPanels !== void 0 ? _mergedPanels : source.panels).forEach((panel) => {
|
|
17504
|
+
this.fireDidMovePanel(panel, from);
|
|
17125
17505
|
});
|
|
17126
17506
|
this.debouncedUpdateAllPositions();
|
|
17127
17507
|
if (options.skipSetActive === false) {
|