Skip to content

Commit 76d1368

Browse files
authored
Test viewr: Use selection-related status bar items from viewer instead of our own (#1471)
1 parent 226b617 commit 76d1368

File tree

2 files changed

+39
-92
lines changed

2 files changed

+39
-92
lines changed

apps/test-viewer/src/components/Viewer.tsx

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,17 @@ import { SchemaFormatsProvider, SchemaUnitProvider } from "@itwin/ecschema-metad
1010
import { ECSchemaRpcInterface } from "@itwin/ecschema-rpcinterface-common";
1111
import { FrontendDevTools } from "@itwin/frontend-devtools";
1212
import { ArcGisAccessClient } from "@itwin/map-layers-auth";
13-
import { Viewer as WebViewer } from "@itwin/web-viewer-react";
13+
import { QuantityFormatting } from "@itwin/quantity-formatting-react";
14+
import { ViewerStatusbarItemsProvider, Viewer as WebViewer } from "@itwin/web-viewer-react";
1415
import { unifiedSelectionStorage } from "../SelectionStorage";
1516
import { getUiProvidersConfig } from "../UiProvidersConfig";
1617
import { ApiKeys } from "./ApiKeys";
1718
import { useAuthorizationContext } from "./Authorization";
18-
import { statusBarActionsProvider, ViewerOptionsProvider } from "./ViewerOptions";
1919
import { FormatManager } from "./FormatManager";
20+
import { statusBarActionsProvider, ViewerOptionsProvider } from "./ViewerOptions";
2021

22+
import type { ComponentPropsWithoutRef } from "react";
2123
import type { UiProvidersConfig } from "../UiProvidersConfig";
22-
import { QuantityFormatting } from "@itwin/quantity-formatting-react";
2324

2425
export function Viewer() {
2526
return (
@@ -68,7 +69,11 @@ function ViewerWithOptions() {
6869
enablePerformanceMonitors={false}
6970
onIModelAppInit={onIModelAppInit}
7071
// Only set providers once IModelAppInit has fired, otherwise map-layers objects will fail to initialize
71-
uiProviders={uiConfig ? [...uiConfig.getUiItemsProviders(), statusBarActionsProvider] : []}
72+
uiProviders={
73+
uiConfig
74+
? [...uiConfig.getUiItemsProviders(), new ViewerStatusbarItemsProvider({ selectionScope: true, selectionInfo: true }), statusBarActionsProvider]
75+
: []
76+
}
7277
defaultUiConfig={{
7378
hideNavigationAid: false,
7479
hideStatusBar: false,
@@ -90,10 +95,38 @@ function ViewerWithOptions() {
9095
selectionStorage: unifiedSelectionStorage,
9196
},
9297
}}
98+
selectionStorage={unifiedSelectionStorage}
99+
selectionScopes={selectionScopes}
93100
/>
94101
);
95102
}
96103

104+
const selectionScopes: ComponentPropsWithoutRef<typeof WebViewer>["selectionScopes"] = {
105+
available: {
106+
element: {
107+
def: { id: "element" },
108+
label: "Element",
109+
},
110+
assembly: {
111+
def: { id: "element", ancestorLevel: 1 },
112+
label: "Assembly",
113+
},
114+
"top-assembly": {
115+
def: { id: "element", ancestorLevel: 2 },
116+
label: "Top assembly",
117+
},
118+
model: {
119+
def: { id: "model" },
120+
label: "Model",
121+
},
122+
category: {
123+
def: { id: "category" },
124+
label: "Category",
125+
},
126+
},
127+
active: "element",
128+
};
129+
97130
function onIModelConnected(imodel: IModelConnection) {
98131
const setupFormatsProvider = async () => {
99132
try {

apps/test-viewer/src/components/ViewerOptions.tsx

Lines changed: 2 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,13 @@
33
* See LICENSE.md in the project root for license terms and full copyright notice.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { createContext, useContext, useEffect, useState } from "react";
6+
import { createContext, useContext, useState } from "react";
77
import { StatusBarSection, useActiveIModelConnection } from "@itwin/appui-react";
88
import { TransientIdSequence } from "@itwin/core-bentley";
99
import { SvgSelection, SvgVisibilityShow, SvgZoomInCircular } from "@itwin/itwinui-icons-react";
10-
import { IconButton, Select } from "@itwin/itwinui-react";
11-
import { Presentation } from "@itwin/presentation-frontend";
10+
import { IconButton } from "@itwin/itwinui-react";
1211
import { QuantityFormatButton } from "./QuantityFormatButton";
1312

14-
import type { SelectionScopesManager } from "@itwin/presentation-frontend";
1513
import type { PropsWithChildren } from "react";
1614
import type { UiItemsProvider } from "@itwin/appui-react";
1715

@@ -61,12 +59,6 @@ export const statusBarActionsProvider: UiItemsProvider = {
6159
itemPriority: 2,
6260
section: StatusBarSection.Left,
6361
},
64-
{
65-
id: `selectionScopeSelectorButton`,
66-
content: <SelectionScopeSelectorButton />,
67-
itemPriority: 3,
68-
section: StatusBarSection.Left,
69-
},
7062
{
7163
id: `addTransientElementToSelectionButton`,
7264
content: <AddTransientElementToSelectionButton />,
@@ -79,12 +71,6 @@ export const statusBarActionsProvider: UiItemsProvider = {
7971
itemPriority: 5,
8072
section: StatusBarSection.Left,
8173
},
82-
{
83-
id: `selectedElementsCount`,
84-
content: <SelectedElementsCountField />,
85-
itemPriority: 1,
86-
section: StatusBarSection.Right,
87-
},
8874
],
8975
};
9076

@@ -106,67 +92,6 @@ function ToggleTreeNodesSelectionButton() {
10692
);
10793
}
10894

109-
function SelectionScopeSelectorButton() {
110-
// eslint-disable-next-line @typescript-eslint/no-deprecated
111-
const [activeScope, setActiveScope] = useState(getScopeId(Presentation.selection.scopes.activeScope));
112-
return (
113-
<Select
114-
options={Object.entries(scopes).map(([key, { label }]) => ({
115-
value: key,
116-
label,
117-
}))}
118-
value={activeScope}
119-
onChange={(value) => {
120-
const scopeId = value as keyof typeof scopes;
121-
setActiveScope(scopeId);
122-
// TODO: Viewer should allow specifying the active selection scope without using `Presentation.selection`
123-
// eslint-disable-next-line @typescript-eslint/no-deprecated
124-
Presentation.selection.scopes.activeScope = scopes[scopeId].props;
125-
}}
126-
/>
127-
);
128-
}
129-
// eslint-disable-next-line @typescript-eslint/no-deprecated
130-
function getScopeId(scopeArg: SelectionScopesManager["activeScope"]): keyof typeof scopes {
131-
if (!scopeArg) {
132-
return "element";
133-
}
134-
if (typeof scopeArg === "string") {
135-
return scopeArg as keyof typeof scopes;
136-
}
137-
if (scopeArg.id === "element" && "ancestorLevel" in scopeArg) {
138-
if (scopeArg.ancestorLevel === 1) {
139-
return "assembly";
140-
}
141-
if (scopeArg.ancestorLevel === 2) {
142-
return "top-assembly";
143-
}
144-
}
145-
return scopeArg.id as keyof typeof scopes;
146-
}
147-
const scopes = {
148-
element: {
149-
props: { id: "element" },
150-
label: "Element",
151-
},
152-
assembly: {
153-
props: { id: "element", ancestorLevel: 1 },
154-
label: "Assembly",
155-
},
156-
"top-assembly": {
157-
props: { id: "element", ancestorLevel: 2 },
158-
label: "Top assembly",
159-
},
160-
model: {
161-
props: { id: "model" },
162-
label: "Model",
163-
},
164-
category: {
165-
props: { id: "category" },
166-
label: "Category",
167-
},
168-
};
169-
17095
function AddTransientElementToSelectionButton() {
17196
const [sequence] = useState(new TransientIdSequence());
17297
const imodel = useActiveIModelConnection();
@@ -179,14 +104,3 @@ function AddTransientElementToSelectionButton() {
179104
</IconButton>
180105
);
181106
}
182-
183-
function SelectedElementsCountField() {
184-
const imodel = useActiveIModelConnection();
185-
const [count, setCount] = useState(imodel?.selectionSet.size ?? 0);
186-
useEffect(() => {
187-
return imodel?.selectionSet.onChanged.addListener(() => {
188-
setCount(imodel.selectionSet.size);
189-
});
190-
}, [imodel]);
191-
return `Selected elements: ${count}`;
192-
}

0 commit comments

Comments
 (0)