Copyright © Bentley Systems, Incorporated. All rights reserved.
The @itwin/tree-widget-react
package provides React components to build a widget with tree components' selector, along with all the building blocks that can be used individually.
Typically, the package is used with an AppUI based application, but the building blocks may as well be used with any other iTwin.js React app.
In any case, before using any APIs or components delivered with the package, it needs to be initialized:
import { IModelApp } from "@itwin/core-frontend";
import { TreeWidget } from "@itwin/tree-widget-react";
...
await TreeWidget.initialize(IModelApp.localization);
In AppUI based applications widgets are typically provided using UiItemsProvider
implementations. The @itwin/tree-widget-react
package delivers TreeWidgetUiItemsProvider
that can be used to add the tree widget to UI:
import { UiItemsManager } from "@itwin/appui-react";
import { TreeWidgetUiItemsProvider } from "@itwin/tree-widget-react";
...
UiItemsManager.register(
new TreeWidgetUiItemsProvider()
);
The above example uses default widget parameters and results in a component similar to the one visible at the top of this README. Customization is also possible:
import { UiItemsManager } from "@itwin/appui-react";
import { TreeWidgetUiItemsProvider, ModelsTreeComponent } from "@itwin/tree-widget-react";
...
UiItemsManager.register(
new TreeWidgetUiItemsProvider({
// defaults to `StagePanelLocation.Right`
defaultPanelLocation: StagePanelLocation.Left,
// defaults to `StagePanelSection.Start`
defaultPanelSection: StagePanelSection.End,
// defaults to whatever the default `Widget.priority` in AppUI is
defaultTreeWidgetPriority: 1000,
// defaults to `ModelsTreeComponent` and `CategoriesTreeComponent`
trees: [{
id: ModelsTreeComponent.id,
getLabel: ModelsTreeComponent.getLabel,
render: () => <ModelsTreeComponent />,
}, {
id: "my-tree-id",
getLabel: "My Custom Tree",
render: () => <>This is my custom tree.</>,
}];
})
);
As seen in the above code snippet, TreeWidgetUiItemsProvider
takes a list of trees that are displayed in the widget. This package delivers a number of tree components for everyone's use (see below), but providing custom trees is also an option.
While we expect this package to be mostly used with AppUI and widget created through TreeWidgetUiItemsProvider
, the package delivers components used within the widget to meet other use cases:
-
SelectableTree
renders a tree selector and selected tree (based on thetrees
prop). -
Visibility tree components help you build trees that look and feel like Models and Categories trees, letting you control display of elements in the hierarchy.
-
createVisibilityTreeRenderer
returns a tree renderer that renders nodes with "eye" checkboxes. Its building blocks:createVisibilityTreeNodeRenderer
VisibilityTreeNodeCheckbox
-
useVisibilityTreeState
is used to create and manage tree state. -
VisibilityTreeNoFilteredData
is used to render a "no results" when filtering. -
VisibilityTreeEventHandler
is an extension of UnifiedSelectionTreeEventHandler, that additionally handles checkbox events and calls providedIVisibilityHandler
to get/set display of the elements in the hierarchy. -
useTreeTransientState
is used to persist tree scroll position when tree is used in AppUI widget.
-
The component renders a tree that tries to replicate how a typical "Models" tree of the iModel would look like in the source application. There's also a header that renders models search box and various visibility control buttons.
Typical usage:
import { ModelsTreeComponent, ClassGroupingOption } from "@itwin/tree-widget-react";
import { SelectionMode } from "@itwin/components-react";
...
function MyWidget() {
return (
<ModelsTreeComponent
headerButtons={[
(props) => <ModelsTreeComponent.ShowAllButton {...props} />,
(props) => <ModelsTreeComponent.HideAllButton {...props} />,
(props) => <MyCustomButton />,
]}
selectionMode={SelectionMode.Extended}
hierarchyConfig={{
enableElementsClassGrouping: ClassGroupingOption.Yes,
}}
/>
);
}
Available header buttons:
-
ModelsTreeComponent.ShowAllButton
makes everything in the iModel displayed. -
ModelsTreeComponent.HideAllButton
makes everything in the iModel hidden by turning off all models. -
ModelsTreeComponent.InvertButton
inverts display of all models. -
ModelsTreeComponent.View2DButton
toggles plan projection models' display. -
ModelsTreeComponent.View3DButton
toggles non-plan projection models' display.
ModelsTreeComponent
building blocks:
-
ModelsTree
renders the tree without the header. -
ModelsVisibilityHandler
knows how to get and control display of various concepts displayed in the Models tree: Subjects, Models, Categories, Elements.
The component, based on the active view, renders a hierarchy of either spatial (3d) or drawing (2d) categories. The hierarchy consists of two levels - the category (spatial or drawing) and its sub-categories. There's also a header that renders categories search box and various visibility control buttons.
Typical usage:
import { CategoriesTreeComponent } from "@itwin/tree-widget-react";
...
function MyWidget() {
return (
<CategoriesTreeComponent
headerButtons={[
(props) => <CategoriesTreeComponent.ShowAllButton {...props} />,
(props) => <CategoriesTreeComponent.HideAllButton {...props} />,
(props) => <MyCustomButton />,
]}
/>
);
}
Available header buttons:
-
ModelsTreeComponent.ShowAllButton
makes all categories and their subcategories displayed. -
ModelsTreeComponent.HideAllButton
makes all categories hidden. -
ModelsTreeComponent.InvertButton
inverts display of all categories.
CategoriesTreeComponent
building blocks:
-
CategoryTree
renders the tree without the header. -
CategoryVisibilityHandler
knows how to get and control display of Categories and SubCategories.
The component renders a similar hierarchy to Models tree, but with the following changes:
- Only the hierarchy, without a header is rendered.
- Visibility control is not allowed.
- There's less hiding of
Subject
andModel
nodes. - Show not only geometric, but all Models.
In general, the component is expected to be used by advanced users to inspect contents of the iModel.
Typical usage:
import { IModelContentTreeComponent } from "@itwin/tree-widget-react";
...
function MyWidget() {
return (
<IModelContentTreeComponent />
);
}
Components from this package allows consumers to track performance of specific features.
This can be achieved by passing onPerformanceMeasured
function to CategoriesTreeComponent
, ModelsTreeComponent
, IModelContentTreeComponent
or TreeWidgetUiItemsProvider
. The function is invoked with feature id and time elapsed as the component is being used. List of tracked features:
-
"{tree}-initial-load"
- time it takes to load initial nodes after the tree is created. -
"{tree}-hierarchy-level-load"
- time it takes to load children nodes when a node is expanded.
Where {tree}
specifies which tree component the feature is of.
Example:
import { UiItemsManager } from "@itwin/appui-react";
import { TreeWidgetUiItemsProvider, ModelsTreeComponent } from "@itwin/tree-widget-react";
...
UiItemsManager.register(
new TreeWidgetUiItemsProvider({
defaultPanelLocation: StagePanelLocation.Left,
defaultPanelSection: StagePanelSection.End,
defaultTreeWidgetPriority: 1000,
onPerformanceMeasured={(feature, elapsedTime) => {
telemetryClient.log(`TreeWidget [${feature}] took ${elapsedTime} ms`);
}},
trees: [{
id: ModelsTreeComponent.id,
getLabel: ModelsTreeComponent.getLabel,
render: (props) => <ModelsTreeComponent { ...props } />,
}];
})
);
For individual tree components the onPerformanceMeasured
callback should be supplied through props:
return (
<ModelsTreeComponent
onPerformanceMeasured={(feature, elapsedTime) => {
console.log(`TreeWidget [${feature}] took ${elapsedTime} ms`)
}}
/>
);
Components from this package allows consumers to track the usage of specific features.
This can be achieved by passing onFeatureUsed
function to CategoriesTreeComponent
, ModelsTreeComponent
, IModelContentTreeComponent
or TreeWidgetUiItemsProvider
. The function is invoked with feature id as the component is being used. List of tracked features:
-
"choose-{tree}"
- when a tree is selected in the tree selector. -
"use-{tree}"
- when an interaction with a tree hierarchy happens. -
"{tree}-visibility-change"
- when visibility is toggled using an "eye" button. -
"models-tree-showall"
- when "Show All" button is used inModelsTreeComponent
. -
"models-tree-hideall"
- when "Hide All" button is used inModelsTreeComponent
. -
"models-tree-invert"
- when "Invert" button is used inModelsTreeComponent
. -
"models-tree-view2d"
- when "Toggle 2D Views" button is used inModelsTreeComponent
. -
"models-tree-view3d"
- when "Toggle 3D Views" button is used inModelsTreeComponent
. -
"models-tree-zoom-to-node"
- when node is zoomed to inModelsTree
. -
"models-tree-filtering"
- when a filter is applied inModelsTree
. -
"models-tree-hierarchy-level-filtering"
- when a hierarchy level filter is applied inModelsTree
. -
"models-tree-hierarchy-level-size-limit-hit"
- when hierarchy limit is exceeded while loading nodes inModelsTree
. -
"categories-tree-showall"
- when "Show All" button is used inCategoriesTreeComponent
. -
"categories-tree-hideall"
- when "Hide All" button is used inCategoriesTreeComponent
. -
"categories-tree-invert"
- when "Invert" button is used inCategoriesTreeComponent
.
Where {tree}
specifies which tree component the feature is of.
Example:
import { UiItemsManager } from "@itwin/appui-react";
import { TreeWidgetUiItemsProvider, ModelsTreeComponent } from "@itwin/tree-widget-react";
...
UiItemsManager.register(
new TreeWidgetUiItemsProvider({
defaultPanelLocation: StagePanelLocation.Left,
defaultPanelSection: StagePanelSection.End,
defaultTreeWidgetPriority: 1000,
onFeatureUsed={(feature) => {
telemetryClient.log(`TreeWidget [${feature}] used`);
}},
trees: [{
id: ModelsTreeComponent.id,
getLabel: ModelsTreeComponent.getLabel,
render: (props) => <ModelsTreeComponent { ...props } />,
}];
})
);
For individual tree components the onFeatureUsed
callback should be supplied through props:
return (
<ModelsTreeComponent
onFeatureUsed={(feature) => {
console.log(`TreeWidget [${feature}] used`)
}}
/>
);