From c8c682a2f5b67d3d9dc817e9ec56764ea7f35489 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20LEMIEUX?= <1904889+raplemie@users.noreply.github.com> Date: Wed, 15 Jun 2022 14:26:01 -0400 Subject: [PATCH] Use active tool name as tool settings label (#3814) * Add useToolAsToolSettingsLabel option to UiFramework * Extract api * rush change --- common/api/appui-react.api.md | 18 +++++-- common/api/summary/appui-react.exports.csv | 2 +- ...lAsToolSettingsLabel_2022-06-14-18-56.json | 10 ++++ .../public/locales/en/UiFramework.json | 7 ++- ui/appui-react/src/appui-react/UiFramework.ts | 10 ++++ .../src/appui-react/configurableui/state.ts | 7 +++ .../settings/ui/UiSettingsPage.tsx | 17 +++++-- .../src/appui-react/uistate/AppUiSettings.ts | 10 ++++ .../appui-react/widget-panels/Frontstage.tsx | 39 ++++++++++++++- .../src/test/redux/StateManager.test.ts | 4 ++ .../src/test/settings/UiSettingsPage.test.tsx | 23 +++++++-- .../src/test/uisettings/AppUiSettings.test.ts | 5 ++ .../test/widget-panels/Frontstage.test.tsx | 49 +++++++++++++++++++ 13 files changed, 188 insertions(+), 13 deletions(-) create mode 100644 common/changes/@itwin/appui-react/raplemie-useToolAsToolSettingsLabel_2022-06-14-18-56.json diff --git a/common/api/appui-react.api.md b/common/api/appui-react.api.md index 59de89e91c8e..43a948003ebf 100644 --- a/common/api/appui-react.api.md +++ b/common/api/appui-react.api.md @@ -572,6 +572,8 @@ export class AppUiSettings implements UserSettingsProvider { // (undocumented) showWidgetIcon: UiStateEntry; // (undocumented) + useToolAsToolSettingsLabel: UiStateEntry; + // (undocumented) widgetOpacity: UiStateEntry; } @@ -1178,7 +1180,9 @@ export enum ConfigurableUiActionId { // (undocumented) SetViewOverlayDisplay = "configurableui:set-view-overlay-display", // (undocumented) - SetWidgetOpacity = "configurableui:set_widget_opacity" + SetWidgetOpacity = "configurableui:set_widget_opacity", + // (undocumented) + UseToolAsToolSettingsLabel = "configurableui:set-use-tool-as-tool-settings-label" } // @public @@ -1193,6 +1197,7 @@ export const ConfigurableUiActions: { setAutoCollapseUnpinnedPanels: (autoCollapse: boolean) => import("../redux/redux-ts").ActionWithPayload; setViewOverlayDisplay: (displayViewOverlay: boolean) => import("../redux/redux-ts").ActionWithPayload; setAnimateToolSettings: (animateToolSettings: boolean) => import("../redux/redux-ts").ActionWithPayload; + setUseToolAsToolSettingsLabel: (useToolAsToolSettingsLabel: boolean) => import("../redux/redux-ts").ActionWithPayload; }; // @public @@ -1301,6 +1306,8 @@ export interface ConfigurableUiState { // (undocumented) useDragInteraction: boolean; // (undocumented) + useToolAsToolSettingsLabel: boolean; + // (undocumented) viewOverlayDisplay: boolean; // (undocumented) widgetOpacity: number; @@ -2379,7 +2386,7 @@ export class FrameworkAccuDraw extends AccuDraw implements UserSettingsProvider export const FrameworkReducer: (state: import("./redux-ts").CombinedReducerState<{ configurableUiState: typeof ConfigurableUiReducer; sessionState: typeof SessionStateReducer; -}>, action: import("./redux-ts").DeepReadonlyObject> | import("./redux-ts").DeepReadonlyObject> | import("./redux-ts").DeepReadonlyObject> | import("./redux-ts").DeepReadonlyObject> | import("./redux-ts").DeepReadonlyObject> | import("./redux-ts").DeepReadonlyObject> | import("./redux-ts").DeepReadonlyObject> | import("./redux-ts").DeepReadonlyObject> | import("./redux-ts").DeepReadonlyObject> | import("./redux-ts").DeepReadonlyObject> | import("./redux-ts").DeepReadonlyObject> | import("./redux-ts").DeepReadonlyObject>> | import("./redux-ts").DeepReadonlyObject> | import("./redux-ts").DeepReadonlyObject> | import("./redux-ts").DeepReadonlyObject> | import("./redux-ts").DeepReadonlyObject> | import("./redux-ts").DeepReadonlyObject> | import("./redux-ts").DeepReadonlyObject> | import("./redux-ts").DeepReadonlyObject>>) => import("./redux-ts").CombinedReducerState<{ +}>, action: import("./redux-ts").DeepReadonlyObject> | import("./redux-ts").DeepReadonlyObject> | import("./redux-ts").DeepReadonlyObject> | import("./redux-ts").DeepReadonlyObject> | import("./redux-ts").DeepReadonlyObject> | import("./redux-ts").DeepReadonlyObject> | import("./redux-ts").DeepReadonlyObject> | import("./redux-ts").DeepReadonlyObject> | import("./redux-ts").DeepReadonlyObject> | import("./redux-ts").DeepReadonlyObject> | import("./redux-ts").DeepReadonlyObject> | import("./redux-ts").DeepReadonlyObject> | import("./redux-ts").DeepReadonlyObject>> | import("./redux-ts").DeepReadonlyObject> | import("./redux-ts").DeepReadonlyObject> | import("./redux-ts").DeepReadonlyObject> | import("./redux-ts").DeepReadonlyObject> | import("./redux-ts").DeepReadonlyObject> | import("./redux-ts").DeepReadonlyObject> | import("./redux-ts").DeepReadonlyObject>>) => import("./redux-ts").CombinedReducerState<{ configurableUiState: typeof ConfigurableUiReducer; sessionState: typeof SessionStateReducer; }>; @@ -3322,6 +3329,8 @@ export interface InitialAppUiSettings { // (undocumented) showWidgetIcon?: boolean; // (undocumented) + useToolAsToolSettingsLabel?: boolean; + // (undocumented) widgetOpacity: number; } @@ -6909,6 +6918,8 @@ export class UiFramework { static setUiVersion(version: FrameworkVersionId): void; // (undocumented) static setUseDragInteraction(useDragInteraction: boolean): void; + // (undocumented) + static setUseToolAsToolSettingsLabel(value: boolean): void; static setViewOverlayDisplay(display: boolean): void; // (undocumented) static setWidgetOpacity(opacity: number): void; @@ -6923,6 +6934,7 @@ export class UiFramework { static useDefaultPopoutUrl: boolean; // (undocumented) static get useDragInteraction(): boolean; + static get useToolAsToolSettingsLabel(): boolean; static get viewOverlayDisplay(): boolean; // @alpha (undocumented) static get widgetManager(): WidgetManager; @@ -7071,7 +7083,7 @@ export const useDefaultToolbarItems: (manager: ToolbarItemsManager) => readonly export function useFrameworkVersion(): FrameworkVersionId; // @internal (undocumented) -export function useFrontstageManager(frontstageDef: FrontstageDef): void; +export function useFrontstageManager(frontstageDef: FrontstageDef, useToolAsToolSettingsLabel?: boolean): void; // @internal (undocumented) export const useGroupedItems: (items: ReadonlyArray) => GroupedItems; diff --git a/common/api/summary/appui-react.exports.csv b/common/api/summary/appui-react.exports.csv index 610be432c298..1e9a46913941 100644 --- a/common/api/summary/appui-react.exports.csv +++ b/common/api/summary/appui-react.exports.csv @@ -692,7 +692,7 @@ internal;useDefaultBackstageItems: (manager: BackstageItemsManager) => readonly public;useDefaultStatusBarItems: (manager: StatusBarItemsManager_2) => readonly CommonStatusBarItem[] public;useDefaultToolbarItems: (manager: ToolbarItemsManager) => readonly CommonToolbarItem[] public;useFrameworkVersion(): FrameworkVersionId -internal;useFrontstageManager(frontstageDef: FrontstageDef): void +internal;useFrontstageManager(frontstageDef: FrontstageDef, useToolAsToolSettingsLabel?: boolean): void internal;useGroupedItems: (items: ReadonlyArray internal;useHorizontalToolSettingNodes(): ToolSettingsEntry[] | undefined public;useIsBackstageOpen: (manager: BackstageManager) => boolean diff --git a/common/changes/@itwin/appui-react/raplemie-useToolAsToolSettingsLabel_2022-06-14-18-56.json b/common/changes/@itwin/appui-react/raplemie-useToolAsToolSettingsLabel_2022-06-14-18-56.json new file mode 100644 index 000000000000..9298ea14a336 --- /dev/null +++ b/common/changes/@itwin/appui-react/raplemie-useToolAsToolSettingsLabel_2022-06-14-18-56.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@itwin/appui-react", + "comment": "Add option to display active tool name as the Tool Settings tab label.", + "type": "none" + } + ], + "packageName": "@itwin/appui-react" +} \ No newline at end of file diff --git a/ui/appui-react/public/locales/en/UiFramework.json b/ui/appui-react/public/locales/en/UiFramework.json index 975f0d63b162..edb97751e03f 100644 --- a/ui/appui-react/public/locales/en/UiFramework.json +++ b/ui/appui-react/public/locales/en/UiFramework.json @@ -168,7 +168,9 @@ "autoCollapseUnpinnedPanelsTitle": "Auto Collapse Unpinned Panels", "autoCollapseUnpinnedPanelsDescription": "Collapse unpinned widget panels when mouse leaves panel boundary. If false, mouse down outside is required.", "animateToolSettingsTitle": "Animate Docked Tool Settings on appear", - "animateToolSettingsDescription": "Animate tool settings when they appear in the docked bar." + "animateToolSettingsDescription": "Animate tool settings when they appear in the docked bar.", + "useToolAsToolSettingsLabelTitle": "Use tool as tool settings label", + "useToolAsToolSettingsLabelDescription": "Use active tool name as the Tool Settings tab label, if false, will always be titled 'Tool Settings'." } }, "tools": { @@ -301,6 +303,9 @@ "pin": "Pin" }, "widget": { + "labels": { + "toolSettings": "Tool Settings" + }, "tooltips": { "dockToolSettings": "Dock to top", "moreWidgets": "More widgets", diff --git a/ui/appui-react/src/appui-react/UiFramework.ts b/ui/appui-react/src/appui-react/UiFramework.ts index 50154ef077f8..2e293ff9fbe9 100644 --- a/ui/appui-react/src/appui-react/UiFramework.ts +++ b/ui/appui-react/src/appui-react/UiFramework.ts @@ -533,6 +533,16 @@ export class UiFramework { UiFramework.dispatchActionToStore(ConfigurableUiActionId.AnimateToolSettings, value, true); } + /** Use Tool Name As Tool Settings Widget Tab Label */ + public static get useToolAsToolSettingsLabel(): boolean { + return UiFramework.frameworkState ? UiFramework.frameworkState.configurableUiState.useToolAsToolSettingsLabel : /* istanbul ignore next */ false; + } + public static setUseToolAsToolSettingsLabel(value: boolean) { + if (UiFramework.useToolAsToolSettingsLabel === value) + return; + UiFramework.dispatchActionToStore(ConfigurableUiActionId.UseToolAsToolSettingsLabel, value, true); + } + /** @alpha */ public static get autoCollapseUnpinnedPanels(): boolean { return UiFramework.frameworkState ? UiFramework.frameworkState.configurableUiState.autoCollapseUnpinnedPanels : /* istanbul ignore next */ false; diff --git a/ui/appui-react/src/appui-react/configurableui/state.ts b/ui/appui-react/src/appui-react/configurableui/state.ts index 9997a803e418..a05bed2b4fa4 100644 --- a/ui/appui-react/src/appui-react/configurableui/state.ts +++ b/ui/appui-react/src/appui-react/configurableui/state.ts @@ -29,6 +29,7 @@ export enum ConfigurableUiActionId { AutoCollapseUnpinnedPanels = "configurableui:set-auto-collapse-unpinned-panels", SetViewOverlayDisplay = "configurableui:set-view-overlay-display", AnimateToolSettings = "configurableui:set-animate-tool-settings", + UseToolAsToolSettingsLabel = "configurableui:set-use-tool-as-tool-settings-label", } /** The portion of state managed by the ConfigurableUiReducer. @@ -46,6 +47,7 @@ export interface ConfigurableUiState { autoCollapseUnpinnedPanels: boolean; viewOverlayDisplay: boolean; animateToolSettings: boolean; + useToolAsToolSettingsLabel: boolean; } /** used on first call of ConfigurableUiReducer */ @@ -60,6 +62,7 @@ const initialState: ConfigurableUiState = { autoCollapseUnpinnedPanels: false, viewOverlayDisplay: true, animateToolSettings: false, + useToolAsToolSettingsLabel: false, }; /** An object with a function that creates each ConfigurableUiReducer that can be handled by our reducer. @@ -82,6 +85,7 @@ export const ConfigurableUiActions = { // eslint-disable-line @typescript-esli setAutoCollapseUnpinnedPanels: (autoCollapse: boolean) => createAction(ConfigurableUiActionId.AutoCollapseUnpinnedPanels, autoCollapse), setViewOverlayDisplay: (displayViewOverlay: boolean) => createAction(ConfigurableUiActionId.SetViewOverlayDisplay, displayViewOverlay), setAnimateToolSettings: (animateToolSettings: boolean) => createAction(ConfigurableUiActionId.AnimateToolSettings, animateToolSettings), + setUseToolAsToolSettingsLabel: (useToolAsToolSettingsLabel: boolean) => createAction(ConfigurableUiActionId.UseToolAsToolSettingsLabel, useToolAsToolSettingsLabel), }; /** Union of ConfigurableUi Redux actions @@ -127,6 +131,9 @@ export function ConfigurableUiReducer(state: ConfigurableUiState = initialState, case ConfigurableUiActionId.AnimateToolSettings: { return { ...state, animateToolSettings: action.payload }; } + case ConfigurableUiActionId.UseToolAsToolSettingsLabel: { + return { ...state, useToolAsToolSettingsLabel: action.payload }; + } } return outState; } diff --git a/ui/appui-react/src/appui-react/settings/ui/UiSettingsPage.tsx b/ui/appui-react/src/appui-react/settings/ui/UiSettingsPage.tsx index 70583742aed2..6b19cf4dd748 100644 --- a/ui/appui-react/src/appui-react/settings/ui/UiSettingsPage.tsx +++ b/ui/appui-react/src/appui-react/settings/ui/UiSettingsPage.tsx @@ -57,6 +57,8 @@ export function UiSettingsPage({ allowSettingUiFrameworkVersion }: { allowSettin const autoCollapseUnpinnedPanelsDescription = React.useRef(UiFramework.translate("settings.uiSettingsPage.autoCollapseUnpinnedPanelsDescription")); const animateToolSettingsTitle = React.useRef(UiFramework.translate("settings.uiSettingsPage.animateToolSettingsTitle")); const animateToolSettingsDescription = React.useRef(UiFramework.translate("settings.uiSettingsPage.animateToolSettingsDescription")); + const useToolAsToolSettingsLabelTitle = React.useRef(UiFramework.translate("settings.uiSettingsPage.useToolAsToolSettingsLabelTitle")); + const useToolAsToolSettingsLabelDescription = React.useRef(UiFramework.translate("settings.uiSettingsPage.useToolAsToolSettingsLabelDescription")); const [theme, setTheme] = React.useState(() => UiFramework.getColorTheme()); const [uiVersion, setUiVersion] = React.useState(() => UiFramework.uiVersion); @@ -64,6 +66,7 @@ export function UiSettingsPage({ allowSettingUiFrameworkVersion }: { allowSettin const [showWidgetIcon, setShowWidgetIcon] = React.useState(() => UiFramework.showWidgetIcon); const [autoCollapseUnpinnedPanels, setAutoCollapseUnpinnedPanels] = React.useState(() => UiFramework.autoCollapseUnpinnedPanels); const [animateToolSettings, setAnimateToolSettings] = React.useState(() => UiFramework.animateToolSettings); + const [useToolAsToolSettingsLabel, setUseToolAsToolSettingsLabel] = React.useState(() => UiFramework.useToolAsToolSettingsLabel); const [widgetOpacity, setWidgetOpacity] = React.useState(() => UiFramework.getWidgetOpacity()); const [autoHideUi, setAutoHideUi] = React.useState(() => UiShowHideManager.autoHideUi); const [useProximityOpacity, setUseProximityOpacity] = React.useState(() => UiShowHideManager.useProximityOpacity); @@ -72,7 +75,7 @@ export function UiSettingsPage({ allowSettingUiFrameworkVersion }: { allowSettin React.useEffect(() => { const syncIdsOfInterest = ["configurableui:set_theme", "configurableui:set_widget_opacity", "configurableui:set-show-widget-icon", "configurableui:set-drag-interaction", "configurableui:set-framework-version", - "configurableui:set-auto-collapse-unpinned-panels", "configurableui:set-animate-tool-settings", SyncUiEventId.ShowHideManagerSettingChange]; + "configurableui:set-auto-collapse-unpinned-panels", "configurableui:set-animate-tool-settings", "configurableui:set-use-tool-as-tool-settings-label", SyncUiEventId.ShowHideManagerSettingChange]; const handleSyncUiEvent = (args: UiSyncEventArgs) => { // istanbul ignore else @@ -99,11 +102,13 @@ export function UiSettingsPage({ allowSettingUiFrameworkVersion }: { allowSettin setSnapWidgetOpacity(UiShowHideManager.snapWidgetOpacity); if (UiFramework.animateToolSettings !== animateToolSettings) setAnimateToolSettings(UiFramework.animateToolSettings); + if (UiFramework.useToolAsToolSettingsLabel !== useToolAsToolSettingsLabel) + setUseToolAsToolSettingsLabel(UiFramework.useToolAsToolSettingsLabel); } }; return SyncUiEventDispatcher.onSyncUiEvent.addListener(handleSyncUiEvent); }, [autoCollapseUnpinnedPanels, autoHideUi, showWidgetIcon, snapWidgetOpacity, theme, uiVersion, - useDragInteraction, useProximityOpacity, widgetOpacity, animateToolSettings]); + useDragInteraction, useProximityOpacity, widgetOpacity, animateToolSettings, useToolAsToolSettingsLabel]); const defaultThemeOption = { label: systemPreferredLabel.current, value: SYSTEM_PREFERRED_COLOR_THEME }; const themeOptions: SelectOption[] = [ @@ -155,6 +160,10 @@ export function UiSettingsPage({ allowSettingUiFrameworkVersion }: { allowSettin }, [animateToolSettings]); const currentTheme = UiFramework.getColorTheme(); + const OnToggleUseToolAsToolSettingsLabel = React.useCallback(async () => { + UiFramework.setUseToolAsToolSettingsLabel(!useToolAsToolSettingsLabel); + }, [useToolAsToolSettingsLabel]); + return (
} /> - + } + /> } ; public autoCollapseUnpinnedPanels: UiStateEntry; public animateToolSettings: UiStateEntry; + public useToolAsToolSettingsLabel: UiStateEntry; private setColorTheme = (theme: string) => { UiFramework.setColorTheme(theme); @@ -94,6 +96,11 @@ export class AppUiSettings implements UserSettingsProvider { (value: boolean) => UiFramework.setAnimateToolSettings(value), defaults.animateToolSettings); this._settings.push(this.animateToolSettings); + this.useToolAsToolSettingsLabel = new UiStateEntry(AppUiSettings._settingNamespace, "UseToolAsToolSettingsLabel", + () => UiFramework.useToolAsToolSettingsLabel, + (value: boolean) => UiFramework.setUseToolAsToolSettingsLabel(value), defaults.useToolAsToolSettingsLabel); + this._settings.push(this.useToolAsToolSettingsLabel); + SyncUiEventDispatcher.onSyncUiEvent.addListener(this.handleSyncUiEvent); } @@ -124,6 +131,9 @@ export class AppUiSettings implements UserSettingsProvider { if (args.eventIds.has("configurableui:set-animate-tool-settings")) await this.animateToolSettings.saveSetting(UiFramework.getUiStateStorage()); + + if (args.eventIds.has("configurableui:set-use-tool-as-tool-settings-label")) + await this.useToolAsToolSettingsLabel.saveSetting(UiFramework.getUiStateStorage()); }; public async apply(storage: UiStateStorage): Promise { diff --git a/ui/appui-react/src/appui-react/widget-panels/Frontstage.tsx b/ui/appui-react/src/appui-react/widget-panels/Frontstage.tsx index 835a5327bf22..16908ebc1c5f 100644 --- a/ui/appui-react/src/appui-react/widget-panels/Frontstage.tsx +++ b/ui/appui-react/src/appui-react/widget-panels/Frontstage.tsx @@ -43,6 +43,7 @@ import { useEscapeSetFocusToHome } from "../hooks/useEscapeSetFocusToHome"; import { FrameworkRootState } from "../redux/StateManager"; import { useSelector } from "react-redux"; import { useUiVisibility } from "../hooks/useUiVisibility"; +import { IModelApp } from "@itwin/core-frontend"; const panelZoneKeys: StagePanelZoneDefKeys[] = ["start", "end"]; @@ -221,7 +222,6 @@ export function ActiveFrontstageDefProvider({ frontstageDef }: { frontstageDef: useUpdateNineZoneSize(frontstageDef); useSavedFrontstageState(frontstageDef); useSaveFrontstageSettings(frontstageDef); - useFrontstageManager(frontstageDef); useItemsManager(frontstageDef); const labels = useLabels(); const uiIsVisible = useUiVisibility(); @@ -237,6 +237,11 @@ export function ActiveFrontstageDefProvider({ frontstageDef }: { frontstageDef: const frameworkState = (state as any)[UiFramework.frameworkStateKey]; return !!frameworkState.configurableUiState.animateToolSettings; }); + const useToolAsToolSettingsLabel = useSelector((state: FrameworkRootState) => { + const frameworkState = (state as any)[UiFramework.frameworkStateKey]; + return !!frameworkState.configurableUiState.useToolAsToolSettingsLabel; + }); + useFrontstageManager(frontstageDef, useToolAsToolSettingsLabel); const handleKeyDown = useEscapeSetFocusToHome(); return ( @@ -1064,7 +1069,7 @@ const createListener = void>(frontstageDef: Front }; /** @internal */ -export function useFrontstageManager(frontstageDef: FrontstageDef) { +export function useFrontstageManager(frontstageDef: FrontstageDef, useToolAsToolSettingsLabel?: boolean) { React.useEffect(() => { const listener = createListener(frontstageDef, ({ widgetDef, widgetState }: WidgetStateChangedEventArgs) => { assert(!!frontstageDef.nineZoneState); @@ -1124,6 +1129,36 @@ export function useFrontstageManager(frontstageDef: FrontstageDef) { FrontstageManager.onWidgetLabelChangedEvent.removeListener(listener); }; }, [frontstageDef]); + + const defaultLabel = React.useMemo( + () => UiFramework.translate("widget.labels.toolSettings"),[] + ); + React.useEffect(() => { + const updateLabel = createListener(frontstageDef, () => { + const toolId = FrontstageManager.activeToolId; + assert(!!frontstageDef.nineZoneState); + const label = useToolAsToolSettingsLabel ? + IModelApp.tools.find(toolId)?.flyover || defaultLabel : defaultLabel; + frontstageDef.nineZoneState = setWidgetLabel(frontstageDef.nineZoneState, toolSettingsTabId, label); + }); + // Whenever the frontstageDef or the useTool... changes, keep the label up to date. + updateLabel(); + // If useTool... is true, listen for events to keep up the label up to date. + if(useToolAsToolSettingsLabel) { + FrontstageManager.onFrontstageReadyEvent.addListener(updateLabel); + FrontstageManager.onFrontstageRestoreLayoutEvent.addListener(updateLabel); + FrontstageManager.onToolActivatedEvent.addListener(updateLabel); + FrontstageManager.onToolSettingsReloadEvent.addListener(updateLabel); + } + return () => { + if(useToolAsToolSettingsLabel) { + FrontstageManager.onFrontstageReadyEvent.removeListener(updateLabel); + FrontstageManager.onFrontstageRestoreLayoutEvent.removeListener(updateLabel); + FrontstageManager.onToolActivatedEvent.removeListener(updateLabel); + FrontstageManager.onToolSettingsReloadEvent.removeListener(updateLabel); + } + }; + }, [frontstageDef, useToolAsToolSettingsLabel, defaultLabel]); } /** @internal */ diff --git a/ui/appui-react/src/test/redux/StateManager.test.ts b/ui/appui-react/src/test/redux/StateManager.test.ts index e853d9267555..bdfed5df3199 100644 --- a/ui/appui-react/src/test/redux/StateManager.test.ts +++ b/ui/appui-react/src/test/redux/StateManager.test.ts @@ -196,6 +196,7 @@ describe("ConfigurableUiReducer", () => { autoCollapseUnpinnedPanels: true, viewOverlayDisplay: true, animateToolSettings: false, + useToolAsToolSettingsLabel: false, }; let outState = ConfigurableUiReducer(initialState, ConfigurableUiActions.setDragInteraction(true)); @@ -227,5 +228,8 @@ describe("ConfigurableUiReducer", () => { outState = ConfigurableUiReducer(initialState, ConfigurableUiActions.setAnimateToolSettings(true)); expect(outState.animateToolSettings).to.be.true; + + outState = ConfigurableUiReducer(initialState, ConfigurableUiActions.setUseToolAsToolSettingsLabel(true)); + expect(outState.useToolAsToolSettingsLabel).to.be.true; }); }); diff --git a/ui/appui-react/src/test/settings/UiSettingsPage.test.tsx b/ui/appui-react/src/test/settings/UiSettingsPage.test.tsx index d73ca72970d6..739668c02cce 100644 --- a/ui/appui-react/src/test/settings/UiSettingsPage.test.tsx +++ b/ui/appui-react/src/test/settings/UiSettingsPage.test.tsx @@ -138,7 +138,7 @@ describe("UiSettingsPage", () => { expect(checkbox).not.to.be.null; fireEvent.click(checkbox!); await TestUtils.flushAsyncOperations(); - expect(wrapper.container.querySelectorAll("span.title").length).to.eq(10); + expect(wrapper.container.querySelectorAll("span.title").length).to.eq(11); wrapper.unmount(); }); @@ -216,7 +216,7 @@ describe("UiSettingsPage", () => { await TestUtils.flushAsyncOperations(); const wrapper = render(); expect(wrapper).not.to.be.undefined; - expect(wrapper.container.querySelectorAll("span.title").length).to.eq(10); + expect(wrapper.container.querySelectorAll("span.title").length).to.eq(11); const uiVersionSpan = wrapper.getByText("settings.uiSettingsPage.newUiTitle"); const checkbox = getInputBySpanTitle(uiVersionSpan); @@ -226,7 +226,7 @@ describe("UiSettingsPage", () => { fireEvent.click(checkbox!); await TestUtils.flushAsyncOperations(); - expect(wrapper.container.querySelectorAll("span.title").length).to.eq(10); + expect(wrapper.container.querySelectorAll("span.title").length).to.eq(11); wrapper.unmount(); }); @@ -248,4 +248,21 @@ describe("UiSettingsPage", () => { wrapper.unmount(); }); + it("renders useToolAsToolSettingsLabel toggle", async () => { + UiFramework.setUiVersion("2"); + await TestUtils.flushAsyncOperations(); + const wrapper = render(); + expect(wrapper).not.to.be.undefined; + + const titleSpan = wrapper.getByText("settings.uiSettingsPage.useToolAsToolSettingsLabelTitle"); + const checkbox = getInputBySpanTitle(titleSpan); + fireEvent.click(checkbox!); + await TestUtils.flushAsyncOperations(); + expect(checkbox?.checked).to.be.true; + fireEvent.click(checkbox!); + await TestUtils.flushAsyncOperations(); + expect(checkbox?.checked).to.be.false; + wrapper.unmount(); + }); + }); diff --git a/ui/appui-react/src/test/uisettings/AppUiSettings.test.ts b/ui/appui-react/src/test/uisettings/AppUiSettings.test.ts index 06c164e73f44..ccc65ede2e06 100644 --- a/ui/appui-react/src/test/uisettings/AppUiSettings.test.ts +++ b/ui/appui-react/src/test/uisettings/AppUiSettings.test.ts @@ -36,6 +36,7 @@ describe("AppUiSettings", () => { const showWidgetIcon = false; const animateToolSettings = false; const autoCollapseUnpinnedPanels = true; + const useToolAsToolSettingsLabel = false; UiFramework.setUiVersion(uiVersion); UiFramework.setWidgetOpacity(opacity); @@ -46,6 +47,7 @@ describe("AppUiSettings", () => { UiFramework.setShowWidgetIcon(showWidgetIcon); UiFramework.setAutoCollapseUnpinnedPanels(autoCollapseUnpinnedPanels); UiFramework.setAnimateToolSettings(animateToolSettings); + UiFramework.setUseToolAsToolSettingsLabel(useToolAsToolSettingsLabel); await TestUtils.flushAsyncOperations(); expect(UiFramework.uiVersion).to.eql(uiVersion); expect(UiFramework.getWidgetOpacity()).to.eql(opacity); @@ -54,6 +56,7 @@ describe("AppUiSettings", () => { expect(UiFramework.showWidgetIcon).to.eql(showWidgetIcon); expect(UiFramework.autoCollapseUnpinnedPanels).to.eql(autoCollapseUnpinnedPanels); expect(UiFramework.animateToolSettings).to.eql(animateToolSettings); + expect(UiFramework.useToolAsToolSettingsLabel).to.eql(useToolAsToolSettingsLabel); }); it("should used default settings", async () => { @@ -65,6 +68,7 @@ describe("AppUiSettings", () => { showWidgetIcon: true, autoCollapseUnpinnedPanels: true, animateToolSettings: true, + useToolAsToolSettingsLabel: true, }; const uiSetting = new AppUiSettings(defaults); @@ -77,6 +81,7 @@ describe("AppUiSettings", () => { expect(UiFramework.showWidgetIcon).to.eql(defaults.showWidgetIcon); expect(UiFramework.autoCollapseUnpinnedPanels).to.eql(defaults.autoCollapseUnpinnedPanels); expect(UiFramework.animateToolSettings).to.eql(defaults.animateToolSettings); + expect(UiFramework.useToolAsToolSettingsLabel).to.eql(defaults.useToolAsToolSettingsLabel); }); }); diff --git a/ui/appui-react/src/test/widget-panels/Frontstage.test.tsx b/ui/appui-react/src/test/widget-panels/Frontstage.test.tsx index 420fe7d3fb76..5814097e2861 100644 --- a/ui/appui-react/src/test/widget-panels/Frontstage.test.tsx +++ b/ui/appui-react/src/test/widget-panels/Frontstage.test.tsx @@ -1082,6 +1082,55 @@ describe("Frontstage local storage wrapper", () => { }).should.not.throw(); }); }); + + describe("useToolAsToolSettingsLabel", () => { + + it("should use localized default name when false", () => { + const frontstageDef = new FrontstageDef(); + let state = createNineZoneState(); + state = addPanelWidget(state, "left", "w1", [toolSettingsTabId]); + state = addTab(state, toolSettingsTabId); + frontstageDef.nineZoneState = state; + + renderHook(() => useFrontstageManager(frontstageDef, false)); + + frontstageDef.nineZoneState?.tabs[toolSettingsTabId].label.should.eq("widget.labels.toolSettings"); + }); + + it("should use localized default name when tool or flyover is not defined", () => { + const frontstageDef = new FrontstageDef(); + let state = createNineZoneState(); + state = addPanelWidget(state, "left", "w1", [toolSettingsTabId]); + state = addTab(state, toolSettingsTabId); + frontstageDef.nineZoneState = state; + + renderHook(() => useFrontstageManager(frontstageDef, true)); + + frontstageDef.nineZoneState?.tabs[toolSettingsTabId].label.should.eq("widget.labels.toolSettings"); + }); + + it("should use tool label when true", () => { + const frontstageDef = new FrontstageDef(); + let state = createNineZoneState(); + state = addPanelWidget(state, "left", "w1", [toolSettingsTabId]); + state = addTab(state, toolSettingsTabId); + frontstageDef.nineZoneState = state; + const fakeActiveToolId = "activeTool1"; + const fakeToolLabel = "activeToolLabel"; + + sinon.stub(FrontstageManager, "activeToolId").get(() =>fakeActiveToolId); + const findSpy = sinon.stub(IModelApp.tools, "find").returns({flyover: fakeToolLabel} as any); + + renderHook(() => useFrontstageManager(frontstageDef, true)); + + findSpy.calledWith(fakeActiveToolId).should.be.true; + frontstageDef.nineZoneState?.tabs[toolSettingsTabId].label.should.eq(fakeToolLabel); + + sinon.restore(); + }); + + }); + }); describe("initializeNineZoneState", () => {