@itwin/appui-react 3.4.0-dev.34 → 3.4.0-dev.37
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/lib/cjs/appui-react/childwindow/ChildWindowManager.d.ts.map +1 -1
- package/lib/cjs/appui-react/childwindow/ChildWindowManager.js +4 -5
- package/lib/cjs/appui-react/childwindow/ChildWindowManager.js.map +1 -1
- package/lib/cjs/appui-react/frontstage/FrontstageDef.d.ts +13 -1
- package/lib/cjs/appui-react/frontstage/FrontstageDef.d.ts.map +1 -1
- package/lib/cjs/appui-react/frontstage/FrontstageDef.js +140 -96
- package/lib/cjs/appui-react/frontstage/FrontstageDef.js.map +1 -1
- package/lib/cjs/appui-react/stagepanels/StagePanelDef.d.ts +0 -6
- package/lib/cjs/appui-react/stagepanels/StagePanelDef.d.ts.map +1 -1
- package/lib/cjs/appui-react/widget-panels/Frontstage.d.ts +20 -697
- package/lib/cjs/appui-react/widget-panels/Frontstage.d.ts.map +1 -1
- package/lib/cjs/appui-react/widget-panels/Frontstage.js +275 -278
- package/lib/cjs/appui-react/widget-panels/Frontstage.js.map +1 -1
- package/lib/cjs/appui-react/widget-panels/useWidgetDirection.js +1 -1
- package/lib/cjs/appui-react/widget-panels/useWidgetDirection.js.map +1 -1
- package/lib/cjs/appui-react/widgets/WidgetDef.d.ts +13 -6
- package/lib/cjs/appui-react/widgets/WidgetDef.d.ts.map +1 -1
- package/lib/cjs/appui-react/widgets/WidgetDef.js +6 -1
- package/lib/cjs/appui-react/widgets/WidgetDef.js.map +1 -1
- package/lib/esm/appui-react/childwindow/ChildWindowManager.d.ts.map +1 -1
- package/lib/esm/appui-react/childwindow/ChildWindowManager.js +4 -5
- package/lib/esm/appui-react/childwindow/ChildWindowManager.js.map +1 -1
- package/lib/esm/appui-react/frontstage/FrontstageDef.d.ts +13 -1
- package/lib/esm/appui-react/frontstage/FrontstageDef.d.ts.map +1 -1
- package/lib/esm/appui-react/frontstage/FrontstageDef.js +142 -98
- package/lib/esm/appui-react/frontstage/FrontstageDef.js.map +1 -1
- package/lib/esm/appui-react/stagepanels/StagePanelDef.d.ts +0 -6
- package/lib/esm/appui-react/stagepanels/StagePanelDef.d.ts.map +1 -1
- package/lib/esm/appui-react/widget-panels/Frontstage.d.ts +20 -697
- package/lib/esm/appui-react/widget-panels/Frontstage.d.ts.map +1 -1
- package/lib/esm/appui-react/widget-panels/Frontstage.js +266 -272
- package/lib/esm/appui-react/widget-panels/Frontstage.js.map +1 -1
- package/lib/esm/appui-react/widget-panels/useWidgetDirection.js +2 -2
- package/lib/esm/appui-react/widget-panels/useWidgetDirection.js.map +1 -1
- package/lib/esm/appui-react/widgets/WidgetDef.d.ts +13 -6
- package/lib/esm/appui-react/widgets/WidgetDef.d.ts.map +1 -1
- package/lib/esm/appui-react/widgets/WidgetDef.js +6 -1
- package/lib/esm/appui-react/widgets/WidgetDef.js.map +1 -1
- package/package.json +32 -32
|
@@ -8,13 +8,13 @@
|
|
|
8
8
|
*/
|
|
9
9
|
// cSpell:ignore popout
|
|
10
10
|
import "./Frontstage.scss";
|
|
11
|
-
import produce
|
|
11
|
+
import produce from "immer";
|
|
12
12
|
import * as React from "react";
|
|
13
13
|
import { assert, Logger, ProcessDetector } from "@itwin/core-bentley";
|
|
14
14
|
import { StagePanelLocation, UiItemsManager, WidgetState } from "@itwin/appui-abstract";
|
|
15
|
-
import { Size, UiStateStorageStatus } from "@itwin/core-react";
|
|
15
|
+
import { Rectangle, Size, UiStateStorageStatus } from "@itwin/core-react";
|
|
16
16
|
import { ToolbarPopupAutoHideContext } from "@itwin/components-react";
|
|
17
|
-
import { addPanelWidget, addTab,
|
|
17
|
+
import { addFloatingWidget, addPanelWidget, addTab, addTabToWidget, convertAllPopupWidgetContainersToFloating, createNineZoneState, floatingWidgetBringToFront, FloatingWidgets, getTabLocation, getUniqueId, getWidgetPanelSectionId, insertPanelWidget, insertTabToWidget, isFloatingTabLocation, isHorizontalPanelSide, isPanelTabLocation, isPopoutTabLocation, NineZone, NineZoneStateReducer, panelSides, removeTab, removeTabFromWidget, toolSettingsTabId, WidgetPanels, } from "@itwin/appui-layout-react";
|
|
18
18
|
import { useActiveFrontstageDef } from "../frontstage/Frontstage";
|
|
19
19
|
import { FrontstageManager } from "../frontstage/FrontstageManager";
|
|
20
20
|
import { StagePanelState } from "../stagepanels/StagePanelDef";
|
|
@@ -259,7 +259,6 @@ export function appendWidgets(state, widgetDefs, side, preferredWidgetIndex) {
|
|
|
259
259
|
const saveTab = state.tabs[widgetDef.id];
|
|
260
260
|
const preferredPanelWidgetSize = saveTab ? saveTab.preferredPanelWidgetSize : widgetDef.preferredPanelSize;
|
|
261
261
|
const preferredFloatingWidgetSize = saveTab ? saveTab.preferredFloatingWidgetSize : widgetDef.defaultFloatingSize;
|
|
262
|
-
const preferredPopoutWidgetSize = saveTab ? saveTab.preferredPopoutWidgetSize : undefined;
|
|
263
262
|
// if a defaultFloatingSize is specified then this mean the widget can't determine its intrinsic size and must be explicitly sized
|
|
264
263
|
const userSized = saveTab ? (saveTab.userSized || !!widgetDef.defaultFloatingSize && !!saveTab.preferredFloatingWidgetSize)
|
|
265
264
|
: !!widgetDef.defaultFloatingSize;
|
|
@@ -269,7 +268,6 @@ export function appendWidgets(state, widgetDefs, side, preferredWidgetIndex) {
|
|
|
269
268
|
canPopout: widgetDef.canPopout,
|
|
270
269
|
preferredPanelWidgetSize,
|
|
271
270
|
preferredFloatingWidgetSize,
|
|
272
|
-
preferredPopoutWidgetSize,
|
|
273
271
|
userSized,
|
|
274
272
|
isFloatingStateWindowResizable: widgetDef.isFloatingStateWindowResizable,
|
|
275
273
|
hideWithUiWhenFloating: !!widgetDef.hideWithUiWhenFloating,
|
|
@@ -277,13 +275,35 @@ export function appendWidgets(state, widgetDefs, side, preferredWidgetIndex) {
|
|
|
277
275
|
if (widgetDef.isFloatingStateSupported && widgetDef.defaultState === WidgetState.Floating) {
|
|
278
276
|
const floatingContainerId = (_a = widgetDef.floatingContainerId) !== null && _a !== void 0 ? _a : getUniqueId();
|
|
279
277
|
const widgetContainerId = getWidgetId(side, panelZoneKeys[preferredWidgetIndex]);
|
|
280
|
-
const
|
|
278
|
+
const home = { side, widgetId: widgetContainerId, widgetIndex: 0 };
|
|
281
279
|
const preferredPosition = widgetDef.defaultFloatingPosition;
|
|
282
|
-
|
|
280
|
+
if (floatingContainerId in state.widgets) {
|
|
281
|
+
state = addTabToWidget(state, widgetDef.id, floatingContainerId);
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
284
|
+
const tab = state.tabs[widgetDef.id];
|
|
285
|
+
const size = { height: 200, width: 300, ...tab.preferredFloatingWidgetSize };
|
|
286
|
+
const preferredPoint = preferredPosition !== null && preferredPosition !== void 0 ? preferredPosition : { x: (state.size.width - size.width) / 2, y: (state.size.height - size.height) / 2 };
|
|
287
|
+
const nzBounds = Rectangle.createFromSize(state.size);
|
|
288
|
+
const bounds = Rectangle.createFromSize(size).offset(preferredPoint);
|
|
289
|
+
const containedBounds = bounds.containIn(nzBounds);
|
|
290
|
+
state = addFloatingWidget(state, floatingContainerId, [widgetDef.id], {
|
|
291
|
+
bounds: containedBounds.toProps(),
|
|
292
|
+
home,
|
|
293
|
+
userSized,
|
|
294
|
+
}, {
|
|
295
|
+
isFloatingStateWindowResizable: widgetDef.isFloatingStateWindowResizable,
|
|
296
|
+
});
|
|
297
|
+
}
|
|
283
298
|
}
|
|
284
299
|
else {
|
|
285
300
|
const widgetPanelSectionId = getWidgetPanelSectionId(side, preferredWidgetIndex);
|
|
286
|
-
|
|
301
|
+
if (widgetPanelSectionId in state.widgets) {
|
|
302
|
+
state = addTabToWidget(state, widgetDef.id, widgetPanelSectionId);
|
|
303
|
+
}
|
|
304
|
+
else {
|
|
305
|
+
state = addPanelWidget(state, side, widgetPanelSectionId, [widgetDef.id]);
|
|
306
|
+
}
|
|
287
307
|
}
|
|
288
308
|
}
|
|
289
309
|
return state;
|
|
@@ -329,17 +349,15 @@ export function addMissingWidgets(frontstageDef, initialState) {
|
|
|
329
349
|
state = appendWidgets(state, determineNewWidgets((_t = frontstageDef.bottomPanel) === null || _t === void 0 ? void 0 : _t.panelZones.end.widgetDefs, state), "bottom", 1);
|
|
330
350
|
return state;
|
|
331
351
|
}
|
|
332
|
-
/**
|
|
333
|
-
function
|
|
352
|
+
/** Hide widgets with Hidden defaultState. */
|
|
353
|
+
function hideWidgets(state, frontstageDef) {
|
|
334
354
|
const tabs = Object.values(state.tabs);
|
|
335
355
|
for (const tab of tabs) {
|
|
336
356
|
const widgetDef = frontstageDef.findWidgetDef(tab.id);
|
|
337
357
|
if (!widgetDef)
|
|
338
358
|
continue;
|
|
339
359
|
if (widgetDef.defaultState === WidgetState.Hidden) {
|
|
340
|
-
state =
|
|
341
|
-
hideWidget(draft, widgetDef);
|
|
342
|
-
});
|
|
360
|
+
state = hideWidget(state, widgetDef);
|
|
343
361
|
}
|
|
344
362
|
}
|
|
345
363
|
return state;
|
|
@@ -348,16 +366,15 @@ function removeHiddenWidgets(state, frontstageDef) {
|
|
|
348
366
|
* @internal
|
|
349
367
|
*/
|
|
350
368
|
export function removeMissingWidgets(frontstageDef, initialState) {
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
});
|
|
369
|
+
let state = initialState;
|
|
370
|
+
for (const [, tab] of Object.entries(state.tabs)) {
|
|
371
|
+
if (tab.id === toolSettingsTabId)
|
|
372
|
+
continue;
|
|
373
|
+
const widgetDef = frontstageDef.findWidgetDef(tab.id);
|
|
374
|
+
if (widgetDef)
|
|
375
|
+
continue;
|
|
376
|
+
state = removeTab(state, tab.id);
|
|
377
|
+
}
|
|
361
378
|
return state;
|
|
362
379
|
}
|
|
363
380
|
function getWidgetLabel(label) {
|
|
@@ -508,23 +525,23 @@ export function isFrontstageStateSettingResult(settingsResult) {
|
|
|
508
525
|
return false;
|
|
509
526
|
}
|
|
510
527
|
/** @internal */
|
|
511
|
-
export function initializePanel(
|
|
512
|
-
|
|
528
|
+
export function initializePanel(state, frontstageDef, panelSide) {
|
|
529
|
+
state = addPanelWidgets(state, frontstageDef, panelSide);
|
|
513
530
|
const location = toStagePanelLocation(panelSide);
|
|
514
531
|
const panelDef = frontstageDef.getStagePanelDef(location);
|
|
515
|
-
|
|
532
|
+
state = produce(state, (draft) => {
|
|
516
533
|
var _a, _b, _c;
|
|
517
534
|
const panel = draft.panels[panelSide];
|
|
518
535
|
panel.minSize = (_a = panelDef === null || panelDef === void 0 ? void 0 : panelDef.minSize) !== null && _a !== void 0 ? _a : panel.minSize;
|
|
519
536
|
panel.pinned = (_b = panelDef === null || panelDef === void 0 ? void 0 : panelDef.pinned) !== null && _b !== void 0 ? _b : panel.pinned;
|
|
520
537
|
panel.resizable = (_c = panelDef === null || panelDef === void 0 ? void 0 : panelDef.resizable) !== null && _c !== void 0 ? _c : panel.resizable;
|
|
521
538
|
if (panelDef === null || panelDef === void 0 ? void 0 : panelDef.maxSizeSpec) {
|
|
522
|
-
panel.maxSize = getPanelMaxSize(panelDef.maxSizeSpec, panelSide,
|
|
539
|
+
panel.maxSize = getPanelMaxSize(panelDef.maxSizeSpec, panelSide, state.size);
|
|
523
540
|
}
|
|
524
541
|
const size = panelDef === null || panelDef === void 0 ? void 0 : panelDef.size;
|
|
525
542
|
panel.size = size === undefined ? size : Math.min(Math.max(size, panel.minSize), panel.maxSize);
|
|
526
543
|
});
|
|
527
|
-
return
|
|
544
|
+
return state;
|
|
528
545
|
}
|
|
529
546
|
function getPanelMaxSize(maxSizeSpec, panel, nineZoneSize) {
|
|
530
547
|
if (typeof maxSizeSpec === "number") {
|
|
@@ -533,7 +550,7 @@ function getPanelMaxSize(maxSizeSpec, panel, nineZoneSize) {
|
|
|
533
550
|
const size = isHorizontalPanelSide(panel) ? nineZoneSize.height : nineZoneSize.width;
|
|
534
551
|
return maxSizeSpec.percentage / 100 * size;
|
|
535
552
|
}
|
|
536
|
-
const stateVersion =
|
|
553
|
+
const stateVersion = 13; // this needs to be bumped when NineZoneState is changed (to recreate the layout).
|
|
537
554
|
/** @internal */
|
|
538
555
|
export function initializeNineZoneState(frontstageDef) {
|
|
539
556
|
let nineZone = defaultNineZone;
|
|
@@ -555,6 +572,7 @@ export function initializeNineZoneState(frontstageDef) {
|
|
|
555
572
|
for (const [, panel] of Object.entries(stateDraft.panels)) {
|
|
556
573
|
const expanded = panel.widgets.find((widgetId) => stateDraft.widgets[widgetId].minimized === false);
|
|
557
574
|
const firstWidget = panel.widgets.length > 0 ? stateDraft.widgets[panel.widgets[0]] : undefined;
|
|
575
|
+
// istanbul ignore next
|
|
558
576
|
if (!expanded && firstWidget) {
|
|
559
577
|
firstWidget.minimized = false;
|
|
560
578
|
}
|
|
@@ -583,7 +601,7 @@ export function initializeNineZoneState(frontstageDef) {
|
|
|
583
601
|
}
|
|
584
602
|
});
|
|
585
603
|
nineZone = addMissingWidgets(frontstageDef, nineZone);
|
|
586
|
-
nineZone =
|
|
604
|
+
nineZone = hideWidgets(nineZone, frontstageDef);
|
|
587
605
|
nineZone = processPopoutWidgets(nineZone, frontstageDef);
|
|
588
606
|
return nineZone;
|
|
589
607
|
}
|
|
@@ -595,29 +613,32 @@ export function initializeNineZoneState(frontstageDef) {
|
|
|
595
613
|
export function restoreNineZoneState(frontstageDef, saved) {
|
|
596
614
|
let restored = {
|
|
597
615
|
...saved,
|
|
598
|
-
tabs:
|
|
616
|
+
tabs: defaultNineZone.tabs,
|
|
599
617
|
};
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
618
|
+
for (const [, tab] of Object.entries(saved.tabs)) {
|
|
619
|
+
// Re-add the placeholder tab in order to correctly remove it from the state if WidgetDef is not found.
|
|
620
|
+
restored = addTab(restored, tab.id);
|
|
621
|
+
const widgetDef = frontstageDef.findWidgetDef(tab.id);
|
|
622
|
+
if (!widgetDef) {
|
|
623
|
+
Logger.logInfo(UiFramework.loggerCategory(restoreNineZoneState), "WidgetDef is not found for saved tab.", () => ({
|
|
624
|
+
frontstageId: frontstageDef.id,
|
|
625
|
+
tabId: tab.id,
|
|
626
|
+
}));
|
|
627
|
+
restored = removeTab(restored, tab.id);
|
|
628
|
+
continue;
|
|
629
|
+
}
|
|
630
|
+
restored = produce(restored, (draft) => {
|
|
612
631
|
draft.tabs[tab.id] = {
|
|
613
632
|
...tab,
|
|
614
|
-
label: getWidgetLabel(
|
|
615
|
-
hideWithUiWhenFloating: widgetDef
|
|
616
|
-
iconSpec: widgetDef
|
|
617
|
-
canPopout: widgetDef
|
|
618
|
-
isFloatingStateWindowResizable: widgetDef
|
|
633
|
+
label: getWidgetLabel(widgetDef.label),
|
|
634
|
+
hideWithUiWhenFloating: widgetDef.hideWithUiWhenFloating,
|
|
635
|
+
iconSpec: widgetDef.iconSpec,
|
|
636
|
+
canPopout: widgetDef.canPopout,
|
|
637
|
+
isFloatingStateWindowResizable: widgetDef.isFloatingStateWindowResizable,
|
|
619
638
|
};
|
|
620
|
-
}
|
|
639
|
+
});
|
|
640
|
+
}
|
|
641
|
+
restored = produce(restored, (draft) => {
|
|
621
642
|
// remove center panel section if one is found in left or right panels
|
|
622
643
|
const oldLeftMiddleIndex = saved.panels.left.widgets.findIndex((value) => value === "leftMiddle");
|
|
623
644
|
// istanbul ignore next
|
|
@@ -645,14 +666,6 @@ export function restoreNineZoneState(frontstageDef, saved) {
|
|
|
645
666
|
}
|
|
646
667
|
return;
|
|
647
668
|
});
|
|
648
|
-
// TODO: remove when isUUID check is refactored.
|
|
649
|
-
restored = produce(restored, (draft) => {
|
|
650
|
-
// Floating widget might have been removed when saving, dock tool settings if tab is not found.
|
|
651
|
-
const location = findTab(draft, toolSettingsTabId);
|
|
652
|
-
if (!location) {
|
|
653
|
-
draft.toolSettings.type = "docked";
|
|
654
|
-
}
|
|
655
|
-
});
|
|
656
669
|
if (FrontstageManager.nineZoneSize && (0 !== FrontstageManager.nineZoneSize.height || 0 !== FrontstageManager.nineZoneSize.width)) {
|
|
657
670
|
restored = FrameworkStateReducer(restored, {
|
|
658
671
|
type: "RESIZE",
|
|
@@ -664,20 +677,6 @@ export function restoreNineZoneState(frontstageDef, saved) {
|
|
|
664
677
|
}
|
|
665
678
|
return restored;
|
|
666
679
|
}
|
|
667
|
-
/**
|
|
668
|
-
* Checks to see whether a widget id is one of our generated uuids
|
|
669
|
-
* @param uuid the string value to test
|
|
670
|
-
* @returns boolean
|
|
671
|
-
*/
|
|
672
|
-
function isUUID(uuid) {
|
|
673
|
-
const s = `${uuid}`;
|
|
674
|
-
const result = s.match("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$");
|
|
675
|
-
// istanbul ignore else
|
|
676
|
-
if (result === null) {
|
|
677
|
-
return false;
|
|
678
|
-
}
|
|
679
|
-
return true;
|
|
680
|
-
}
|
|
681
680
|
/** Prepares NineZoneState to be saved.
|
|
682
681
|
* @note Removes toolSettings tab.
|
|
683
682
|
* @note Removes tab labels and iconSpec.
|
|
@@ -692,31 +691,60 @@ export function packNineZoneState(state) {
|
|
|
692
691
|
for (const [, tab] of Object.entries(state.tabs)) {
|
|
693
692
|
if (tab.id === toolSettingsTabId)
|
|
694
693
|
continue;
|
|
695
|
-
// istanbul ignore else
|
|
696
|
-
if (isUUID(tab.id))
|
|
697
|
-
continue;
|
|
698
694
|
draft.tabs[tab.id] = {
|
|
699
695
|
id: tab.id,
|
|
700
696
|
preferredFloatingWidgetSize: tab.preferredFloatingWidgetSize,
|
|
701
|
-
preferredPopoutWidgetSize: tab.preferredPopoutWidgetSize,
|
|
702
697
|
allowedPanelTargets: tab.allowedPanelTargets,
|
|
703
698
|
userSized: tab.userSized,
|
|
704
699
|
};
|
|
705
700
|
}
|
|
706
701
|
});
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
702
|
+
return packed;
|
|
703
|
+
}
|
|
704
|
+
// TODO: clean-up of saved widgets.
|
|
705
|
+
// istanbul ignore next
|
|
706
|
+
function packSavedWidgets(savedWidgets, frontstageDef) {
|
|
707
|
+
for (const widgetDef of frontstageDef.widgetDefs) {
|
|
708
|
+
const id = widgetDef.id;
|
|
709
|
+
const initialWidget = {
|
|
710
|
+
id,
|
|
711
|
+
};
|
|
712
|
+
const widget = produce(initialWidget, (draft) => {
|
|
713
|
+
if (widgetDef.tabLocation) {
|
|
714
|
+
draft.tabLocation = { ...widgetDef.tabLocation };
|
|
716
715
|
}
|
|
716
|
+
if (widgetDef.popoutBounds) {
|
|
717
|
+
draft.popoutBounds = widgetDef.popoutBounds.toProps();
|
|
718
|
+
}
|
|
719
|
+
});
|
|
720
|
+
if (widget === initialWidget)
|
|
721
|
+
continue;
|
|
722
|
+
savedWidgets = produce(savedWidgets, (draft) => {
|
|
723
|
+
draft.push(widget);
|
|
724
|
+
});
|
|
725
|
+
}
|
|
726
|
+
return savedWidgets;
|
|
727
|
+
}
|
|
728
|
+
// istanbul ignore next
|
|
729
|
+
function restoreSavedWidgets(savedWidgets, frontstage) {
|
|
730
|
+
let i = savedWidgets.length;
|
|
731
|
+
while (i--) {
|
|
732
|
+
const savedWidget = savedWidgets[i];
|
|
733
|
+
const widgetId = savedWidget.id;
|
|
734
|
+
const widgetDef = frontstage.findWidgetDef(widgetId);
|
|
735
|
+
if (!widgetDef)
|
|
736
|
+
continue;
|
|
737
|
+
if (savedWidget.tabLocation) {
|
|
738
|
+
widgetDef.tabLocation = { ...savedWidget.tabLocation };
|
|
717
739
|
}
|
|
718
|
-
|
|
719
|
-
|
|
740
|
+
if (savedWidget.popoutBounds) {
|
|
741
|
+
widgetDef.popoutBounds = Rectangle.create(savedWidget.popoutBounds);
|
|
742
|
+
}
|
|
743
|
+
savedWidgets = produce(savedWidgets, (draft) => {
|
|
744
|
+
draft.splice(i, 1);
|
|
745
|
+
});
|
|
746
|
+
}
|
|
747
|
+
return savedWidgets;
|
|
720
748
|
}
|
|
721
749
|
/** @internal */
|
|
722
750
|
export function isPanelCollapsed(zoneStates, panelStates) {
|
|
@@ -724,121 +752,116 @@ export function isPanelCollapsed(zoneStates, panelStates) {
|
|
|
724
752
|
const openPanel = panelStates.find((panelState) => panelState === StagePanelState.Open);
|
|
725
753
|
return !openZone && !openPanel;
|
|
726
754
|
}
|
|
727
|
-
function
|
|
728
|
-
|
|
729
|
-
const
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
isFloatingStateWindowResizable: widgetDef.isFloatingStateWindowResizable,
|
|
735
|
-
hideWithUiWhenFloating: !!widgetDef.hideWithUiWhenFloating,
|
|
736
|
-
});
|
|
737
|
-
nineZone.tabs[newTab.id] = newTab;
|
|
738
|
-
if (widgetDef.tabLocation.widgetId in nineZone.widgets) {
|
|
739
|
-
// Add to existing widget (by widget id).
|
|
740
|
-
const widgetId = widgetDef.tabLocation.widgetId;
|
|
741
|
-
const newTabWidget = nineZone.widgets[widgetId];
|
|
742
|
-
newTabWidget.tabs.splice(widgetDef.tabLocation.tabIndex, 0, newTab.id);
|
|
755
|
+
function addHiddenWidget(state, widgetDef) {
|
|
756
|
+
const tabLocation = widgetDef.tabLocation || widgetDef.defaultTabLocation;
|
|
757
|
+
const tabId = widgetDef.id;
|
|
758
|
+
const widgetId = tabLocation.widgetId;
|
|
759
|
+
if (widgetId in state.widgets) {
|
|
760
|
+
// Add to an existing widget (by widget id).
|
|
761
|
+
return insertTabToWidget(state, tabId, widgetId, tabLocation.tabIndex);
|
|
743
762
|
}
|
|
744
|
-
else if (
|
|
745
|
-
const
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
else {
|
|
752
|
-
const home = { side: widgetDef.tabLocation.side, widgetId: widgetDef.floatingContainerId, widgetIndex: 0 };
|
|
753
|
-
addWidgetTabToDraftFloatingPanel(nineZone, (_b = widgetDef.floatingContainerId) !== null && _b !== void 0 ? _b : widgetDef.id, widgetDef.id, home, newTab);
|
|
763
|
+
else if (tabLocation.floatingWidget) {
|
|
764
|
+
const floatingWidget = tabLocation.floatingWidget;
|
|
765
|
+
const floatingWidgetId = floatingWidget.id;
|
|
766
|
+
// Add to an existing floating widget.
|
|
767
|
+
// istanbul ignore next
|
|
768
|
+
if (floatingWidgetId in state.widgets) {
|
|
769
|
+
return insertTabToWidget(state, tabId, floatingWidgetId, tabLocation.tabIndex);
|
|
754
770
|
}
|
|
771
|
+
// Add to a new floating widget.
|
|
772
|
+
const nzBounds = Rectangle.createFromSize(state.size);
|
|
773
|
+
const bounds = Rectangle.create(floatingWidget.bounds).containIn(nzBounds);
|
|
774
|
+
return addFloatingWidget(state, floatingWidgetId, [tabId], {
|
|
775
|
+
...floatingWidget,
|
|
776
|
+
bounds: bounds.toProps(),
|
|
777
|
+
});
|
|
755
778
|
}
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
newTabWidget.tabs.splice(widgetDef.tabLocation.tabIndex, 0, newTab.id);
|
|
764
|
-
}
|
|
765
|
-
else {
|
|
766
|
-
// Create a new panel widget.
|
|
767
|
-
const newWidget = createWidgetState(getUniqueId(), [newTab.id]);
|
|
768
|
-
nineZone.widgets[newWidget.id] = castDraft(newWidget);
|
|
769
|
-
newTabPanel.widgets.splice(widgetDef.tabLocation.widgetIndex, 0, newWidget.id);
|
|
770
|
-
}
|
|
779
|
+
// Add to a panel section.
|
|
780
|
+
const panel = state.panels[tabLocation.side];
|
|
781
|
+
// Add to existing panel section.
|
|
782
|
+
if (panel.widgets.length >= panel.maxWidgetCount) {
|
|
783
|
+
const sectionIndex = Math.min(panel.maxWidgetCount - 1, tabLocation.widgetIndex);
|
|
784
|
+
const sectionId = panel.widgets[sectionIndex];
|
|
785
|
+
return insertTabToWidget(state, tabId, sectionId, tabLocation.tabIndex);
|
|
771
786
|
}
|
|
787
|
+
// Create a new panel section.
|
|
788
|
+
const newSectionId = getUniqueId();
|
|
789
|
+
return insertPanelWidget(state, panel.side, newSectionId, [tabId], tabLocation.widgetIndex);
|
|
772
790
|
}
|
|
773
791
|
/** @internal */
|
|
774
|
-
export
|
|
775
|
-
|
|
776
|
-
|
|
792
|
+
export function setWidgetState(state, widgetDef, widgetState) {
|
|
793
|
+
if (widgetState === WidgetState.Hidden) {
|
|
794
|
+
return hideWidget(state, widgetDef);
|
|
795
|
+
}
|
|
796
|
+
else if (widgetState === WidgetState.Open) {
|
|
777
797
|
const id = widgetDef.id;
|
|
778
|
-
let location =
|
|
798
|
+
let location = getTabLocation(state, id);
|
|
779
799
|
if (!location) {
|
|
780
|
-
|
|
781
|
-
location =
|
|
782
|
-
assert(!!location);
|
|
783
|
-
}
|
|
784
|
-
if (!!widgetDef.tabLocation.floating) {
|
|
785
|
-
nineZone.floatingWidgets.byId[(_a = widgetDef.floatingContainerId) !== null && _a !== void 0 ? _a : widgetDef.id].hidden = false;
|
|
800
|
+
state = addHiddenWidget(state, widgetDef);
|
|
801
|
+
location = getTabLocation(state, id);
|
|
786
802
|
}
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
panel.size = (_b = panel.minSize) !== null && _b !== void 0 ? _b : 200;
|
|
803
|
+
return produce(state, (draft) => {
|
|
804
|
+
var _a;
|
|
805
|
+
assert(!!location);
|
|
806
|
+
const widget = draft.widgets[location.widgetId];
|
|
807
|
+
widget.minimized = false;
|
|
808
|
+
widget.activeTabId = id;
|
|
809
|
+
if (isFloatingTabLocation(location)) {
|
|
810
|
+
const floatingWidget = draft.floatingWidgets.byId[location.floatingWidgetId];
|
|
811
|
+
floatingWidget.hidden = false;
|
|
812
|
+
// istanbul ignore else
|
|
798
813
|
}
|
|
799
|
-
|
|
814
|
+
else if (isPanelTabLocation(location)) {
|
|
815
|
+
const panel = draft.panels[location.side];
|
|
816
|
+
panel.collapsed = false;
|
|
817
|
+
if (undefined === panel.size || 0 === panel.size) {
|
|
818
|
+
// istanbul ignore next
|
|
819
|
+
panel.size = (_a = panel.minSize) !== null && _a !== void 0 ? _a : 200;
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
});
|
|
800
823
|
}
|
|
801
|
-
else if (
|
|
824
|
+
else if (widgetState === WidgetState.Closed) {
|
|
802
825
|
const id = widgetDef.id;
|
|
803
|
-
let location =
|
|
826
|
+
let location = getTabLocation(state, id);
|
|
804
827
|
if (!location) {
|
|
805
|
-
|
|
806
|
-
location =
|
|
807
|
-
assert(!!location);
|
|
828
|
+
state = addHiddenWidget(state, widgetDef);
|
|
829
|
+
location = getTabLocation(state, id);
|
|
808
830
|
}
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
831
|
+
// TODO: should change activeTabId of a widget with multiple tabs.
|
|
832
|
+
return produce(state, (draft) => {
|
|
833
|
+
assert(!!location);
|
|
834
|
+
const widget = draft.widgets[location.widgetId];
|
|
835
|
+
if (isFloatingTabLocation(location)) {
|
|
836
|
+
if (id === widget.activeTabId) {
|
|
837
|
+
widget.minimized = true;
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
});
|
|
818
841
|
}
|
|
819
|
-
|
|
842
|
+
return state;
|
|
843
|
+
}
|
|
820
844
|
/** Stores widget location and hides it in the UI. */
|
|
821
845
|
function hideWidget(state, widgetDef) {
|
|
822
|
-
const location =
|
|
846
|
+
const location = getTabLocation(state, widgetDef.id);
|
|
823
847
|
if (!location)
|
|
824
|
-
return;
|
|
825
|
-
|
|
826
|
-
|
|
848
|
+
return state;
|
|
849
|
+
// istanbul ignore else
|
|
850
|
+
if (isFloatingTabLocation(location)) {
|
|
851
|
+
const floatingWidget = state.floatingWidgets.byId[location.widgetId];
|
|
827
852
|
widgetDef.setFloatingContainerId(location.floatingWidgetId);
|
|
828
853
|
widgetDef.tabLocation = {
|
|
829
|
-
side:
|
|
830
|
-
tabIndex:
|
|
854
|
+
side: floatingWidget.home.side,
|
|
855
|
+
tabIndex: floatingWidget.home.widgetIndex,
|
|
831
856
|
widgetId: widgetDef.id,
|
|
832
|
-
widgetIndex:
|
|
833
|
-
|
|
857
|
+
widgetIndex: floatingWidget.home.widgetIndex,
|
|
858
|
+
floatingWidget,
|
|
834
859
|
};
|
|
835
860
|
}
|
|
836
|
-
else
|
|
837
|
-
// istanbul ignore else
|
|
838
|
-
if (!isPopoutLocation(location)) {
|
|
861
|
+
else if (!isPopoutTabLocation(location)) {
|
|
839
862
|
const widgetId = location.widgetId;
|
|
840
|
-
const side =
|
|
841
|
-
const widgetIndex =
|
|
863
|
+
const side = isPanelTabLocation(location) ? location.side : "left";
|
|
864
|
+
const widgetIndex = isPanelTabLocation(location) ? state.panels[side].widgets.indexOf(widgetId) : 0;
|
|
842
865
|
const tabIndex = state.widgets[location.widgetId].tabs.indexOf(widgetDef.id);
|
|
843
866
|
widgetDef.tabLocation = {
|
|
844
867
|
side,
|
|
@@ -847,50 +870,53 @@ function hideWidget(state, widgetDef) {
|
|
|
847
870
|
widgetIndex,
|
|
848
871
|
};
|
|
849
872
|
}
|
|
850
|
-
|
|
873
|
+
return removeTabFromWidget(state, widgetDef.id);
|
|
851
874
|
}
|
|
852
875
|
/** @internal */
|
|
853
|
-
export
|
|
854
|
-
const location =
|
|
876
|
+
export function showWidget(state, id) {
|
|
877
|
+
const location = getTabLocation(state, id);
|
|
855
878
|
if (!location)
|
|
856
|
-
return;
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
const panel = nineZone.panels[location.side];
|
|
860
|
-
panel.collapsed = false;
|
|
861
|
-
widget.minimized = false;
|
|
879
|
+
return state;
|
|
880
|
+
state = produce(state, (draft) => {
|
|
881
|
+
const widget = draft.widgets[location.widgetId];
|
|
862
882
|
widget.activeTabId = id;
|
|
863
|
-
|
|
883
|
+
widget.minimized = false;
|
|
884
|
+
if (isPanelTabLocation(location)) {
|
|
885
|
+
const panel = draft.panels[location.side];
|
|
886
|
+
panel.collapsed = false;
|
|
887
|
+
}
|
|
888
|
+
});
|
|
889
|
+
if (isFloatingTabLocation(location)) {
|
|
890
|
+
state = floatingWidgetBringToFront(state, location.floatingWidgetId);
|
|
864
891
|
}
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
isFloatingLocation(location) && floatingWidgetBringToFront(nineZone, location.floatingWidgetId);
|
|
868
|
-
});
|
|
892
|
+
return state;
|
|
893
|
+
}
|
|
869
894
|
/** @internal */
|
|
870
|
-
export
|
|
871
|
-
const location =
|
|
895
|
+
export function expandWidget(state, id) {
|
|
896
|
+
const location = getTabLocation(state, id);
|
|
872
897
|
if (!location)
|
|
873
|
-
return;
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
898
|
+
return state;
|
|
899
|
+
return produce(state, (draft) => {
|
|
900
|
+
const widget = draft.widgets[location.widgetId];
|
|
901
|
+
if (isPanelTabLocation(location)) {
|
|
902
|
+
const panel = draft.panels[location.side];
|
|
903
|
+
panel.widgets.forEach((wId) => {
|
|
904
|
+
const w = draft.widgets[wId];
|
|
905
|
+
w.minimized = true;
|
|
906
|
+
});
|
|
907
|
+
}
|
|
881
908
|
widget.minimized = false;
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
widget.minimized = false;
|
|
885
|
-
return;
|
|
886
|
-
});
|
|
909
|
+
});
|
|
910
|
+
}
|
|
887
911
|
/** @internal */
|
|
888
|
-
export
|
|
889
|
-
if (!(id in
|
|
890
|
-
return;
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
912
|
+
export function setWidgetLabel(state, id, label) {
|
|
913
|
+
if (!(id in state.tabs))
|
|
914
|
+
return state;
|
|
915
|
+
return produce(state, (draft) => {
|
|
916
|
+
const tab = draft.tabs[id];
|
|
917
|
+
tab.label = label;
|
|
918
|
+
});
|
|
919
|
+
}
|
|
894
920
|
/** @internal */
|
|
895
921
|
export function useSavedFrontstageState(frontstageDef) {
|
|
896
922
|
const uiStateStorage = useUiStateStorageHandler();
|
|
@@ -911,20 +937,23 @@ export function useSavedFrontstageState(frontstageDef) {
|
|
|
911
937
|
}
|
|
912
938
|
const id = frontstageDef.id;
|
|
913
939
|
const version = frontstageDef.version;
|
|
914
|
-
const
|
|
915
|
-
if (isMountedRef.current)
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
940
|
+
const settingResult = await uiStateStorageRef.current.getSetting(FRONTSTAGE_SETTINGS_NAMESPACE, getFrontstageStateSettingName(id));
|
|
941
|
+
if (!isMountedRef.current)
|
|
942
|
+
return;
|
|
943
|
+
if (isFrontstageStateSettingResult(settingResult)) {
|
|
944
|
+
const setting = settingResult.setting;
|
|
945
|
+
if (setting.version >= version && setting.stateVersion >= stateVersion) {
|
|
946
|
+
const restored = restoreNineZoneState(frontstageDef, setting.nineZone);
|
|
947
|
+
const savedWidgets = restoreSavedWidgets(setting.widgets, frontstageDef);
|
|
920
948
|
let state = addMissingWidgets(frontstageDef, restored);
|
|
921
|
-
state =
|
|
949
|
+
state = hideWidgets(state, frontstageDef);
|
|
922
950
|
state = processPopoutWidgets(state, frontstageDef);
|
|
923
951
|
frontstageDef.nineZoneState = state;
|
|
952
|
+
frontstageDef.savedWidgetDefs = savedWidgets;
|
|
924
953
|
return;
|
|
925
954
|
}
|
|
926
|
-
frontstageDef.nineZoneState = initializeNineZoneState(frontstageDef);
|
|
927
955
|
}
|
|
956
|
+
frontstageDef.nineZoneState = initializeNineZoneState(frontstageDef);
|
|
928
957
|
}
|
|
929
958
|
fetchFrontstageState(); // eslint-disable-line @typescript-eslint/no-floating-promises
|
|
930
959
|
}, [frontstageDef]);
|
|
@@ -933,16 +962,19 @@ export function useSavedFrontstageState(frontstageDef) {
|
|
|
933
962
|
export function useSaveFrontstageSettings(frontstageDef) {
|
|
934
963
|
const nineZone = useNineZoneState(frontstageDef);
|
|
935
964
|
const uiSettingsStorage = useUiStateStorageHandler();
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
965
|
+
const saveSetting = React.useMemo(() => {
|
|
966
|
+
return debounce(async (frontstage, state, savedWidgets) => {
|
|
967
|
+
const id = frontstage.id;
|
|
968
|
+
const setting = {
|
|
969
|
+
id,
|
|
970
|
+
version: frontstage.version,
|
|
971
|
+
stateVersion,
|
|
972
|
+
nineZone: packNineZoneState(state),
|
|
973
|
+
widgets: packSavedWidgets(savedWidgets, frontstage),
|
|
974
|
+
};
|
|
975
|
+
await uiSettingsStorage.saveSetting(FRONTSTAGE_SETTINGS_NAMESPACE, getFrontstageStateSettingName(id), setting);
|
|
976
|
+
}, 1000);
|
|
977
|
+
}, [uiSettingsStorage]);
|
|
946
978
|
React.useEffect(() => {
|
|
947
979
|
return () => {
|
|
948
980
|
saveSetting.cancel();
|
|
@@ -951,7 +983,8 @@ export function useSaveFrontstageSettings(frontstageDef) {
|
|
|
951
983
|
React.useEffect(() => {
|
|
952
984
|
if (!nineZone || nineZone.draggedTab)
|
|
953
985
|
return;
|
|
954
|
-
|
|
986
|
+
const savedWidgets = frontstageDef.savedWidgetDefs || [];
|
|
987
|
+
saveSetting(frontstageDef, nineZone, savedWidgets);
|
|
955
988
|
}, [frontstageDef, nineZone, saveSetting]);
|
|
956
989
|
}
|
|
957
990
|
/** @internal */
|
|
@@ -1085,7 +1118,7 @@ export function useItemsManager(frontstageDef) {
|
|
|
1085
1118
|
return;
|
|
1086
1119
|
state = addMissingWidgets(def, state);
|
|
1087
1120
|
state = removeMissingWidgets(def, state);
|
|
1088
|
-
state =
|
|
1121
|
+
state = hideWidgets(state, def); // TODO: should only apply to widgets provided by registered provider in onUiProviderRegisteredEvent.
|
|
1089
1122
|
def.nineZoneState = state;
|
|
1090
1123
|
};
|
|
1091
1124
|
React.useEffect(() => {
|
|
@@ -1098,47 +1131,8 @@ export function useItemsManager(frontstageDef) {
|
|
|
1098
1131
|
return remove;
|
|
1099
1132
|
}, [frontstageDef]);
|
|
1100
1133
|
}
|
|
1101
|
-
function tabShownInCurrentWidget(def, state) {
|
|
1102
|
-
for (const [, widget] of Object.entries(state.widgets)) {
|
|
1103
|
-
const foundTab = widget.tabs.find((tabId) => tabId === def.id);
|
|
1104
|
-
// istanbul ignore else
|
|
1105
|
-
if (foundTab)
|
|
1106
|
-
return true;
|
|
1107
|
-
}
|
|
1108
|
-
return false;
|
|
1109
|
-
}
|
|
1110
1134
|
// istanbul ignore next
|
|
1111
1135
|
function determineNewWidgets(defs, state) {
|
|
1112
|
-
|
|
1113
|
-
return (defs || []).filter((def) => !(def.id in state.tabs) || !tabShownInCurrentWidget(def, state));
|
|
1114
|
-
}
|
|
1115
|
-
/** @internal */
|
|
1116
|
-
export async function saveFrontstagePopoutWidgetSizeAndPosition(state, stageId, stageVersion, childWindowId, childWindow) {
|
|
1117
|
-
const location = findWidget(state, childWindowId);
|
|
1118
|
-
// istanbul ignore else
|
|
1119
|
-
if (location) {
|
|
1120
|
-
const adjustmentWidth = ProcessDetector.isElectronAppFrontend ? 16 : 0;
|
|
1121
|
-
const adjustmentHeight = ProcessDetector.isElectronAppFrontend ? 39 : 0;
|
|
1122
|
-
const newState = produce(state, (draft) => {
|
|
1123
|
-
const widget = draft.widgets[childWindowId];
|
|
1124
|
-
const tab = draft.tabs[widget.activeTabId];
|
|
1125
|
-
tab.preferredPopoutWidgetSize = {
|
|
1126
|
-
x: childWindow.screenX,
|
|
1127
|
-
y: childWindow.screenY,
|
|
1128
|
-
width: childWindow.innerWidth + adjustmentWidth,
|
|
1129
|
-
height: childWindow.innerHeight + adjustmentHeight,
|
|
1130
|
-
};
|
|
1131
|
-
});
|
|
1132
|
-
const setting = {
|
|
1133
|
-
id: stageId,
|
|
1134
|
-
nineZone: packNineZoneState(newState),
|
|
1135
|
-
stateVersion,
|
|
1136
|
-
version: stageVersion,
|
|
1137
|
-
};
|
|
1138
|
-
await UiFramework.getUiStateStorage().saveSetting(FRONTSTAGE_SETTINGS_NAMESPACE, getFrontstageStateSettingName(stageId), setting);
|
|
1139
|
-
return newState;
|
|
1140
|
-
}
|
|
1141
|
-
// istanbul ignore next
|
|
1142
|
-
return state;
|
|
1136
|
+
return (defs || []).filter((def) => !(def.id in state.tabs));
|
|
1143
1137
|
}
|
|
1144
1138
|
//# sourceMappingURL=Frontstage.js.map
|