@itwin/tree-widget-react 4.0.0-alpha.17 → 4.0.0-alpha.19
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/CHANGELOG.md +51 -1
- package/lib/esm/tree-widget-react/TreeWidget.d.ts +1 -3
- package/lib/esm/tree-widget-react/TreeWidget.js +19 -19
- package/lib/esm/tree-widget-react/TreeWidget.js.map +1 -1
- package/lib/esm/tree-widget-react/components/TreeWidgetComponentImpl.d.ts +1 -0
- package/lib/esm/tree-widget-react/components/TreeWidgetComponentImpl.js +1 -1
- package/lib/esm/tree-widget-react/components/TreeWidgetComponentImpl.js.map +1 -1
- package/lib/esm/tree-widget-react/components/TreeWidgetUiItemsProvider.js +1 -1
- package/lib/esm/tree-widget-react/components/TreeWidgetUiItemsProvider.js.map +1 -1
- package/lib/esm/tree-widget-react/components/tree-header/SearchBox.js +2 -2
- package/lib/esm/tree-widget-react/components/tree-header/SearchBox.js.map +1 -1
- package/lib/esm/tree-widget-react/components/tree-header/SelectableTree.js.map +1 -1
- package/lib/esm/tree-widget-react/components/tree-header/WidgetHeader.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTree.d.ts +3 -3
- package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTree.js +2 -2
- package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTree.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeButtons.d.ts +0 -2
- package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeButtons.js +13 -11
- package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeButtons.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeComponent.d.ts +1 -1
- package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeComponent.js +2 -2
- package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeComponent.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.d.ts +6 -10
- package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js +137 -92
- package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.js +12 -4
- package/lib/esm/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.d.ts +30 -29
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js +405 -355
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/UseFilteredPaths.d.ts +5 -3
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/UseFilteredPaths.js +8 -6
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/UseFilteredPaths.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/visibility/CategoriesTreeVisibilityHandler.d.ts +4 -1
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/visibility/CategoriesTreeVisibilityHandler.js +20 -12
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/visibility/CategoriesTreeVisibilityHandler.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/visibility/CategoriesTreeVisibilityHelper.d.ts +3 -1
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/visibility/CategoriesTreeVisibilityHelper.js +13 -3
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/visibility/CategoriesTreeVisibilityHelper.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/visibility/FilteredTree.d.ts +4 -1
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/visibility/FilteredTree.js +8 -7
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/visibility/FilteredTree.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTree.d.ts +2 -2
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTree.js +6 -2
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTree.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeComponent.d.ts +1 -1
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeComponent.js +2 -2
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeComponent.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeDefinition.d.ts +3 -5
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeDefinition.js +45 -38
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeDefinition.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/UseClassificationsTree.js +8 -2
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/UseClassificationsTree.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeIdsCache.d.ts +14 -20
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeIdsCache.js +271 -275
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeIdsCache.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/UseFilteredPaths.d.ts +4 -2
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/UseFilteredPaths.js +3 -2
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/UseFilteredPaths.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/visibility/ClassificationsTreeVisibilityHandler.js +22 -15
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/visibility/ClassificationsTreeVisibilityHandler.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/visibility/ClassificationsTreeVisibilityHelper.js +5 -5
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/visibility/ClassificationsTreeVisibilityHelper.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/visibility/FilteredTree.d.ts +7 -2
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/visibility/FilteredTree.js +15 -12
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/visibility/FilteredTree.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/UseHierarchyVisibility.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/Utils.d.ts +2 -1
- package/lib/esm/tree-widget-react/components/trees/common/Utils.js +8 -3
- package/lib/esm/tree-widget-react/components/trees/common/Utils.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/components/EmptyTree.js +4 -4
- package/lib/esm/tree-widget-react/components/trees/common/components/EmptyTree.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/components/ProgressOverlay.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/components/SkeletonTree.d.ts +4 -1
- package/lib/esm/tree-widget-react/components/trees/common/components/SkeletonTree.js +4 -1
- package/lib/esm/tree-widget-react/components/trees/common/components/SkeletonTree.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/components/Tree.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/components/TreeNodeVisibilityButton.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/components/VisibilityTree.d.ts +2 -2
- package/lib/esm/tree-widget-react/components/trees/common/components/VisibilityTree.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/internal/AlwaysAndNeverDrawnElementInfo.d.ts +55 -18
- package/lib/esm/tree-widget-react/components/trees/common/internal/AlwaysAndNeverDrawnElementInfo.js +96 -76
- package/lib/esm/tree-widget-react/components/trees/common/internal/AlwaysAndNeverDrawnElementInfo.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/internal/ModelCategoryElementsCountCache.d.ts +5 -8
- package/lib/esm/tree-widget-react/components/trees/common/internal/ModelCategoryElementsCountCache.js +52 -39
- package/lib/esm/tree-widget-react/components/trees/common/internal/ModelCategoryElementsCountCache.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/internal/UseIModelAccess.d.ts +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/internal/UseIModelAccess.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/internal/Utils.d.ts +29 -4
- package/lib/esm/tree-widget-react/components/trees/common/internal/Utils.js +49 -4
- package/lib/esm/tree-widget-react/components/trees/common/internal/Utils.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/internal/VisibilityUtils.d.ts +2 -7
- package/lib/esm/tree-widget-react/components/trees/common/internal/VisibilityUtils.js +30 -39
- package/lib/esm/tree-widget-react/components/trees/common/internal/VisibilityUtils.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/internal/useGuid.d.ts +3 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/useGuid.js +12 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/useGuid.js.map +1 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/useTreeHooks/UseCachedVisibility.d.ts +5 -1
- package/lib/esm/tree-widget-react/components/trees/common/internal/useTreeHooks/UseCachedVisibility.js +25 -13
- package/lib/esm/tree-widget-react/components/trees/common/internal/useTreeHooks/UseCachedVisibility.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/internal/useTreeHooks/UseIdsCache.d.ts +3 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/useTreeHooks/UseIdsCache.js +7 -7
- package/lib/esm/tree-widget-react/components/trees/common/internal/useTreeHooks/UseIdsCache.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/internal/visibility/BaseFilteredTree.d.ts +8 -4
- package/lib/esm/tree-widget-react/components/trees/common/internal/visibility/BaseFilteredTree.js +16 -11
- package/lib/esm/tree-widget-react/components/trees/common/internal/visibility/BaseFilteredTree.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/internal/visibility/BaseVisibilityHelper.d.ts +2 -1
- package/lib/esm/tree-widget-react/components/trees/common/internal/visibility/BaseVisibilityHelper.js +44 -28
- package/lib/esm/tree-widget-react/components/trees/common/internal/visibility/BaseVisibilityHelper.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/useGuid.d.ts +2 -0
- package/lib/esm/tree-widget-react/components/trees/common/useGuid.js +11 -0
- package/lib/esm/tree-widget-react/components/trees/common/useGuid.js.map +1 -0
- package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTree.d.ts +2 -2
- package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTree.js +5 -2
- package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTree.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTreeComponent.d.ts +2 -2
- package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTreeComponent.js +2 -2
- package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTreeComponent.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTreeDefinition.d.ts +4 -6
- package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTreeDefinition.js +31 -26
- package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTreeDefinition.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTree.d.ts +3 -3
- package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTree.js +6 -4
- package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTree.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTreeComponent.d.ts +2 -2
- package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTreeComponent.js +2 -2
- package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTreeComponent.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTreeDefinition.d.ts +1 -5
- package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTreeDefinition.js +44 -44
- package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTreeDefinition.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/internal/IModelContentTreeIdsCache.d.ts +3 -6
- package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/internal/IModelContentTreeIdsCache.js +20 -16
- package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/internal/IModelContentTreeIdsCache.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/index.d.ts +1 -0
- package/lib/esm/tree-widget-react/components/trees/index.js +1 -0
- package/lib/esm/tree-widget-react/components/trees/index.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTree.d.ts +3 -3
- package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTree.js +2 -2
- package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTree.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeButtons.js +6 -3
- package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeButtons.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeComponent.d.ts +1 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeComponent.js +2 -2
- package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeComponent.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.d.ts +6 -10
- package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js +111 -69
- package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/UseModelsTree.js +7 -2
- package/lib/esm/tree-widget-react/components/trees/models-tree/UseModelsTree.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.d.ts +17 -25
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js +246 -265
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeNode.d.ts +1 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeNode.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/UseFilteredPaths.d.ts +3 -2
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/UseFilteredPaths.js +9 -3
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/UseFilteredPaths.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/visibility/FilteredTree.d.ts +4 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/visibility/FilteredTree.js +6 -6
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/visibility/FilteredTree.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/visibility/ModelsTreeVisibilityHandler.js +17 -11
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/visibility/ModelsTreeVisibilityHandler.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/visibility/ModelsTreeVisibilityHelper.js +3 -3
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/visibility/ModelsTreeVisibilityHelper.js.map +1 -1
- package/lib/esm/tree-widget-react-internal.d.ts +2 -1
- package/lib/esm/tree-widget-react-internal.js +2 -1
- package/lib/esm/tree-widget-react-internal.js.map +1 -1
- package/lib/public/locales/en/TreeWidget.json +1 -1
- package/package.json +12 -12
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
4
4
|
*--------------------------------------------------------------------------------------------*/
|
|
5
5
|
import { useCallback, useEffect, useState } from "react";
|
|
6
|
-
import { defaultIfEmpty, EMPTY, filter, firstValueFrom, from, fromEventPattern, map, mergeMap,
|
|
7
|
-
import {
|
|
6
|
+
import { defaultIfEmpty, EMPTY, filter, firstValueFrom, from, fromEventPattern, map, mergeMap, Subject, takeUntil, tap } from "rxjs";
|
|
7
|
+
import { assert } from "@itwin/core-bentley";
|
|
8
|
+
import { HierarchyNode, HierarchyNodeKey } from "@itwin/presentation-hierarchies";
|
|
8
9
|
import { HierarchyVisibilityOverrideHandler } from "../../UseHierarchyVisibility.js";
|
|
9
10
|
import { AlwaysAndNeverDrawnElementInfo } from "../AlwaysAndNeverDrawnElementInfo.js";
|
|
10
11
|
import { toVoidPromise } from "../Rxjs.js";
|
|
@@ -13,13 +14,14 @@ import { createVisibilityChangeEventListener } from "../VisibilityChangeEventLis
|
|
|
13
14
|
/** @internal */
|
|
14
15
|
export function useCachedVisibility(props) {
|
|
15
16
|
const [filteredPaths, setFilteredPaths] = useState(undefined);
|
|
16
|
-
const { activeView, getCache, createFilteredTree, createTreeSpecificVisibilityHandler } = props;
|
|
17
|
+
const { activeView, getCache, createFilteredTree, createTreeSpecificVisibilityHandler, componentId } = props;
|
|
17
18
|
const [visibilityHandlerFactory, setVisibilityHandlerFactory] = useState(() => createVisibilityHandlerFactory({
|
|
18
19
|
activeView,
|
|
19
20
|
getCache,
|
|
20
21
|
createFilteredTree,
|
|
21
22
|
createTreeSpecificVisibilityHandler,
|
|
22
23
|
filteringPaths: filteredPaths,
|
|
24
|
+
componentId,
|
|
23
25
|
}));
|
|
24
26
|
useEffect(() => {
|
|
25
27
|
setVisibilityHandlerFactory(() => createVisibilityHandlerFactory({
|
|
@@ -28,8 +30,9 @@ export function useCachedVisibility(props) {
|
|
|
28
30
|
createFilteredTree,
|
|
29
31
|
createTreeSpecificVisibilityHandler,
|
|
30
32
|
filteringPaths: filteredPaths,
|
|
33
|
+
componentId,
|
|
31
34
|
}));
|
|
32
|
-
}, [activeView, getCache, filteredPaths, createFilteredTree, createTreeSpecificVisibilityHandler]);
|
|
35
|
+
}, [activeView, getCache, filteredPaths, createFilteredTree, createTreeSpecificVisibilityHandler, componentId]);
|
|
33
36
|
return {
|
|
34
37
|
visibilityHandlerFactory,
|
|
35
38
|
onFilteredPathsChanged: useCallback((paths) => setFilteredPaths(paths), []),
|
|
@@ -37,8 +40,9 @@ export function useCachedVisibility(props) {
|
|
|
37
40
|
};
|
|
38
41
|
}
|
|
39
42
|
function createVisibilityHandlerFactory(props) {
|
|
40
|
-
const { activeView, createFilteredTree, createTreeSpecificVisibilityHandler, getCache, filteringPaths } = props;
|
|
43
|
+
const { activeView, createFilteredTree, createTreeSpecificVisibilityHandler, getCache, filteringPaths, componentId } = props;
|
|
41
44
|
return ({ imodelAccess }) => new HierarchyVisibilityHandlerImpl({
|
|
45
|
+
componentId,
|
|
42
46
|
viewport: activeView,
|
|
43
47
|
getFilteredTree: () => {
|
|
44
48
|
if (filteringPaths) {
|
|
@@ -80,7 +84,7 @@ export class HierarchyVisibilityHandlerImpl {
|
|
|
80
84
|
displayStyle: true,
|
|
81
85
|
},
|
|
82
86
|
});
|
|
83
|
-
this.#alwaysAndNeverDrawnElements = new AlwaysAndNeverDrawnElementInfo(this.#props.viewport);
|
|
87
|
+
this.#alwaysAndNeverDrawnElements = new AlwaysAndNeverDrawnElementInfo({ viewport: this.#props.viewport, componentId: props.componentId });
|
|
84
88
|
this.#treeSpecificVisibilityHandler = this.#props.getTreeSpecificVisibilityHandler(this.#alwaysAndNeverDrawnElements, new HierarchyVisibilityOverrideHandler(this));
|
|
85
89
|
this.#filteredTree = this.#props.getFilteredTree();
|
|
86
90
|
}
|
|
@@ -121,13 +125,23 @@ export class HierarchyVisibilityHandlerImpl {
|
|
|
121
125
|
this.#treeSpecificVisibilityHandler[Symbol.dispose]();
|
|
122
126
|
}
|
|
123
127
|
getVisibilityStatusInternal(node) {
|
|
124
|
-
if (
|
|
128
|
+
if (HierarchyNode.isClassGroupingNode(node)) {
|
|
129
|
+
if (node.extendedData?.hasDirectNonFilteredTargets && !node.filtering?.hasFilterTargetAncestor) {
|
|
130
|
+
return this.getFilteredNodeVisibility({ node });
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (HierarchyNode.isInstancesNode(node) && node.filtering?.filteredChildrenIdentifierPaths?.length && !node.filtering.isFilterTarget) {
|
|
125
134
|
return this.getFilteredNodeVisibility({ node });
|
|
126
135
|
}
|
|
127
136
|
return this.#treeSpecificVisibilityHandler.getVisibilityStatus(node);
|
|
128
137
|
}
|
|
129
138
|
changeVisibilityStatusInternal(node, on) {
|
|
130
|
-
if (
|
|
139
|
+
if (HierarchyNode.isClassGroupingNode(node)) {
|
|
140
|
+
if (node.extendedData?.hasDirectNonFilteredTargets && !node.filtering?.hasFilterTargetAncestor) {
|
|
141
|
+
return this.changeFilteredNodeVisibility({ node, on });
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
if (HierarchyNode.isInstancesNode(node) && node.filtering?.filteredChildrenIdentifierPaths?.length && !node.filtering.isFilterTarget) {
|
|
131
145
|
return this.changeFilteredNodeVisibility({ node, on });
|
|
132
146
|
}
|
|
133
147
|
return this.#treeSpecificVisibilityHandler.changeVisibilityStatus(node, on);
|
|
@@ -140,13 +154,11 @@ export class HierarchyVisibilityHandlerImpl {
|
|
|
140
154
|
return this.#treeSpecificVisibilityHandler.getFilterTargetsVisibilityStatus(targets);
|
|
141
155
|
}));
|
|
142
156
|
}
|
|
143
|
-
getFilteredTreeTargets({ node }) {
|
|
144
|
-
|
|
145
|
-
return of(undefined);
|
|
146
|
-
}
|
|
157
|
+
getFilteredTreeTargets({ node, }) {
|
|
158
|
+
assert(this.#filteredTree !== undefined);
|
|
147
159
|
return from(this.#filteredTree).pipe(map((filteredTree) => filteredTree.getFilterTargets(node)));
|
|
148
160
|
}
|
|
149
|
-
changeFilteredNodeVisibility({ on, node }) {
|
|
161
|
+
changeFilteredNodeVisibility({ on, node, }) {
|
|
150
162
|
return this.getFilteredTreeTargets({ node }).pipe(mergeMap((targets) => {
|
|
151
163
|
if (!targets) {
|
|
152
164
|
return EMPTY;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UseCachedVisibility.js","sourceRoot":"","sources":["../../../../../../../../src/tree-widget-react/components/trees/common/internal/useTreeHooks/UseCachedVisibility.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport { defaultIfEmpty, EMPTY, filter, firstValueFrom, from, fromEventPattern, map, mergeMap, of, Subject, takeUntil, tap } from \"rxjs\";\nimport { HierarchyNodeKey } from \"@itwin/presentation-hierarchies\";\nimport { HierarchyVisibilityOverrideHandler } from \"../../UseHierarchyVisibility.js\";\nimport { AlwaysAndNeverDrawnElementInfo } from \"../AlwaysAndNeverDrawnElementInfo.js\";\nimport { toVoidPromise } from \"../Rxjs.js\";\nimport { createVisibilityStatus } from \"../Tooltip.js\";\nimport { createVisibilityChangeEventListener } from \"../VisibilityChangeEventListener.js\";\n\nimport type { Observable } from \"rxjs\";\nimport type { HierarchyFilteringPath, HierarchyNode } from \"@itwin/presentation-hierarchies\";\nimport type { ECClassHierarchyInspector } from \"@itwin/presentation-shared\";\nimport type { VisibilityTreeProps } from \"../../components/VisibilityTree.js\";\nimport type { TreeWidgetViewport } from \"../../TreeWidgetViewport.js\";\nimport type { HierarchyVisibilityHandler, VisibilityStatus } from \"../../UseHierarchyVisibility.js\";\nimport type { FilteredTree } from \"../visibility/BaseFilteredTree.js\";\nimport type { TreeSpecificVisibilityHandler } from \"../visibility/BaseVisibilityHelper.js\";\nimport type { IVisibilityChangeEventListener } from \"../VisibilityChangeEventListener.js\";\n\n/** @internal */\nexport interface CreateFilteredTreeProps<TCache> {\n getCache: () => TCache;\n imodelAccess: ECClassHierarchyInspector;\n filteringPaths: HierarchyFilteringPath[];\n}\n\n/** @internal */\nexport interface CreateTreeSpecificVisibilityHandlerProps<TCache> {\n info: AlwaysAndNeverDrawnElementInfo;\n getCache: () => TCache;\n viewport: TreeWidgetViewport;\n overrideHandler: HierarchyVisibilityOverrideHandler;\n}\n\n/** @internal */\nexport interface UseCachedVisibilityProps<TCache, TFilterTargets> {\n activeView: TreeWidgetViewport;\n getCache: () => TCache;\n createFilteredTree: (props: CreateFilteredTreeProps<TCache>) => Promise<FilteredTree<TFilterTargets>>;\n createTreeSpecificVisibilityHandler: (props: CreateTreeSpecificVisibilityHandlerProps<TCache>) => TreeSpecificVisibilityHandler<TFilterTargets> & Disposable;\n}\n\n/** @internal */\nexport function useCachedVisibility<TCache, TFilterTargets>(props: UseCachedVisibilityProps<TCache, TFilterTargets>) {\n const [filteredPaths, setFilteredPaths] = useState<HierarchyFilteringPath[] | undefined>(undefined);\n const { activeView, getCache, createFilteredTree, createTreeSpecificVisibilityHandler } = props;\n\n const [visibilityHandlerFactory, setVisibilityHandlerFactory] = useState<VisibilityTreeProps[\"visibilityHandlerFactory\"]>(() =>\n createVisibilityHandlerFactory({\n activeView,\n getCache,\n createFilteredTree,\n createTreeSpecificVisibilityHandler,\n filteringPaths: filteredPaths,\n }),\n );\n\n useEffect(() => {\n setVisibilityHandlerFactory(() =>\n createVisibilityHandlerFactory({\n activeView,\n getCache,\n createFilteredTree,\n createTreeSpecificVisibilityHandler,\n filteringPaths: filteredPaths,\n }),\n );\n }, [activeView, getCache, filteredPaths, createFilteredTree, createTreeSpecificVisibilityHandler]);\n\n return {\n visibilityHandlerFactory,\n onFilteredPathsChanged: useCallback((paths: HierarchyFilteringPath[] | undefined) => setFilteredPaths(paths), []),\n filteredPaths,\n };\n}\n\nfunction createVisibilityHandlerFactory<TCache, TFilterTargets>(\n props: UseCachedVisibilityProps<TCache, TFilterTargets> & {\n filteringPaths: HierarchyFilteringPath[] | undefined;\n },\n): VisibilityTreeProps[\"visibilityHandlerFactory\"] {\n const { activeView, createFilteredTree, createTreeSpecificVisibilityHandler, getCache, filteringPaths } = props;\n return ({ imodelAccess }) =>\n new HierarchyVisibilityHandlerImpl<TFilterTargets>({\n viewport: activeView,\n getFilteredTree: (): Promise<FilteredTree<TFilterTargets>> | undefined => {\n if (filteringPaths) {\n return createFilteredTree({ imodelAccess, filteringPaths, getCache });\n }\n return undefined;\n },\n getTreeSpecificVisibilityHandler: (info, overrideHandler) =>\n createTreeSpecificVisibilityHandler({\n info,\n getCache,\n viewport: activeView,\n overrideHandler,\n }),\n });\n}\n\n/** @internal */\nexport interface HierarchyVisibilityHandlerImplProps<TFilterTargets> {\n viewport: TreeWidgetViewport;\n getTreeSpecificVisibilityHandler: (\n info: AlwaysAndNeverDrawnElementInfo,\n overrideHandler: HierarchyVisibilityOverrideHandler,\n ) => TreeSpecificVisibilityHandler<TFilterTargets> & Disposable;\n getFilteredTree: () => Promise<FilteredTree<TFilterTargets>> | undefined;\n}\n\n/**\n * Class that handles visibility of hierarchy nodes in a tree.\n *\n * - It provides methods to get and change visibility status of nodes.\n * - Also handles filtered tree nodes visibility.\n * - Listens to visibility change events and updates visibility status accordingly.\n * @internal\n */\nexport class HierarchyVisibilityHandlerImpl<TFilterTargets> implements HierarchyVisibilityHandler, Disposable {\n readonly #props: HierarchyVisibilityHandlerImplProps<TFilterTargets>;\n readonly #eventListener: IVisibilityChangeEventListener;\n readonly #alwaysAndNeverDrawnElements: AlwaysAndNeverDrawnElementInfo;\n #treeSpecificVisibilityHandler: TreeSpecificVisibilityHandler<TFilterTargets> & Disposable;\n #changeRequest = new Subject<{ key: HierarchyNodeKey; depth: number }>();\n #filteredTree: Promise<FilteredTree<TFilterTargets>> | undefined;\n\n constructor(props: HierarchyVisibilityHandlerImplProps<TFilterTargets>) {\n this.#props = props;\n this.#eventListener = createVisibilityChangeEventListener({\n viewport: this.#props.viewport,\n listeners: {\n models: true,\n categories: true,\n elements: true,\n displayStyle: true,\n },\n });\n this.#alwaysAndNeverDrawnElements = new AlwaysAndNeverDrawnElementInfo(this.#props.viewport);\n this.#treeSpecificVisibilityHandler = this.#props.getTreeSpecificVisibilityHandler(\n this.#alwaysAndNeverDrawnElements,\n new HierarchyVisibilityOverrideHandler(this),\n );\n this.#filteredTree = this.#props.getFilteredTree();\n }\n\n public get onVisibilityChange() {\n return this.#eventListener.onVisibilityChange;\n }\n\n public async getVisibilityStatus(node: HierarchyNode): Promise<VisibilityStatus> {\n return firstValueFrom(\n this.getVisibilityStatusInternal(node).pipe(\n // unsubscribe from the observable if the change request for this node is received\n takeUntil(this.#changeRequest.pipe(filter(({ key, depth }) => depth === node.parentKeys.length && HierarchyNodeKey.equals(node.key, key)))),\n // unsubscribe if visibility changes\n takeUntil(\n fromEventPattern(\n (handler) => {\n this.#eventListener.onVisibilityChange.addListener(handler);\n },\n (handler) => {\n this.#eventListener.onVisibilityChange.removeListener(handler);\n },\n ),\n ),\n defaultIfEmpty(createVisibilityStatus(\"hidden\")),\n ),\n );\n }\n\n public async changeVisibility(node: HierarchyNode, shouldDisplay: boolean): Promise<void> {\n // notify about new change request\n this.#changeRequest.next({ key: node.key, depth: node.parentKeys.length });\n\n const changeObservable = this.changeVisibilityStatusInternal(node, shouldDisplay).pipe(\n // unsubscribe from the observable if the change request for this node is received\n takeUntil(this.#changeRequest.pipe(filter(({ key, depth }) => depth === node.parentKeys.length && HierarchyNodeKey.equals(node.key, key)))),\n tap({\n subscribe: () => {\n this.#eventListener.suppressChangeEvents();\n this.#alwaysAndNeverDrawnElements.suppressChangeEvents();\n },\n finalize: () => {\n this.#eventListener.resumeChangeEvents();\n this.#alwaysAndNeverDrawnElements.resumeChangeEvents();\n },\n }),\n );\n\n return toVoidPromise(changeObservable);\n }\n\n public [Symbol.dispose]() {\n this.#eventListener[Symbol.dispose]();\n this.#alwaysAndNeverDrawnElements[Symbol.dispose]();\n this.#treeSpecificVisibilityHandler[Symbol.dispose]();\n }\n\n private getVisibilityStatusInternal(node: HierarchyNode) {\n if (node.filtering?.filteredChildrenIdentifierPaths?.length && !node.filtering.isFilterTarget) {\n return this.getFilteredNodeVisibility({ node });\n }\n return this.#treeSpecificVisibilityHandler.getVisibilityStatus(node);\n }\n\n private changeVisibilityStatusInternal(node: HierarchyNode, on: boolean): Observable<void> {\n if (node.filtering?.filteredChildrenIdentifierPaths?.length && !node.filtering.isFilterTarget) {\n return this.changeFilteredNodeVisibility({ node, on });\n }\n return this.#treeSpecificVisibilityHandler.changeVisibilityStatus(node, on);\n }\n\n private getFilteredNodeVisibility(props: { node: HierarchyNode }) {\n return this.getFilteredTreeTargets(props).pipe(\n mergeMap((targets) => {\n if (!targets) {\n return EMPTY;\n }\n return this.#treeSpecificVisibilityHandler.getFilterTargetsVisibilityStatus(targets);\n }),\n );\n }\n\n private getFilteredTreeTargets({ node }: { node: HierarchyNode }): Observable<TFilterTargets | undefined> {\n if (!this.#filteredTree) {\n return of(undefined);\n }\n return from(this.#filteredTree).pipe(map((filteredTree) => filteredTree.getFilterTargets(node)));\n }\n\n private changeFilteredNodeVisibility({ on, node }: { on: boolean; node: HierarchyNode }) {\n return this.getFilteredTreeTargets({ node }).pipe(\n mergeMap((targets) => {\n if (!targets) {\n return EMPTY;\n }\n return this.#treeSpecificVisibilityHandler.changeFilterTargetsVisibilityStatus(targets, on);\n }),\n );\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"UseCachedVisibility.js","sourceRoot":"","sources":["../../../../../../../../src/tree-widget-react/components/trees/common/internal/useTreeHooks/UseCachedVisibility.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport { defaultIfEmpty, EMPTY, filter, firstValueFrom, from, fromEventPattern, map, mergeMap, Subject, takeUntil, tap } from \"rxjs\";\nimport { assert } from \"@itwin/core-bentley\";\nimport { HierarchyNode, HierarchyNodeKey } from \"@itwin/presentation-hierarchies\";\nimport { HierarchyVisibilityOverrideHandler } from \"../../UseHierarchyVisibility.js\";\nimport { AlwaysAndNeverDrawnElementInfo } from \"../AlwaysAndNeverDrawnElementInfo.js\";\nimport { toVoidPromise } from \"../Rxjs.js\";\nimport { createVisibilityStatus } from \"../Tooltip.js\";\nimport { createVisibilityChangeEventListener } from \"../VisibilityChangeEventListener.js\";\n\nimport type { Observable } from \"rxjs\";\nimport type { GuidString } from \"@itwin/core-bentley\";\nimport type { ClassGroupingNodeKey, HierarchyFilteringPath, InstancesNodeKey } from \"@itwin/presentation-hierarchies\";\nimport type { ECClassHierarchyInspector } from \"@itwin/presentation-shared\";\nimport type { VisibilityTreeProps } from \"../../components/VisibilityTree.js\";\nimport type { TreeWidgetViewport } from \"../../TreeWidgetViewport.js\";\nimport type { HierarchyVisibilityHandler, VisibilityStatus } from \"../../UseHierarchyVisibility.js\";\nimport type { FilteredTree } from \"../visibility/BaseFilteredTree.js\";\nimport type { TreeSpecificVisibilityHandler } from \"../visibility/BaseVisibilityHelper.js\";\nimport type { IVisibilityChangeEventListener } from \"../VisibilityChangeEventListener.js\";\n\n/** @internal */\nexport interface CreateFilteredTreeProps<TCache> {\n getCache: () => TCache;\n imodelAccess: ECClassHierarchyInspector;\n filteringPaths: HierarchyFilteringPath[];\n}\n\n/** @internal */\nexport interface CreateTreeSpecificVisibilityHandlerProps<TCache> {\n info: AlwaysAndNeverDrawnElementInfo;\n getCache: () => TCache;\n viewport: TreeWidgetViewport;\n overrideHandler: HierarchyVisibilityOverrideHandler;\n}\n\n/** @internal */\nexport interface UseCachedVisibilityProps<TCache, TFilterTargets> {\n componentId: GuidString;\n activeView: TreeWidgetViewport;\n getCache: () => TCache;\n createFilteredTree: (props: CreateFilteredTreeProps<TCache>) => Promise<FilteredTree<TFilterTargets>>;\n createTreeSpecificVisibilityHandler: (props: CreateTreeSpecificVisibilityHandlerProps<TCache>) => TreeSpecificVisibilityHandler<TFilterTargets> & Disposable;\n}\n\n/** @internal */\nexport function useCachedVisibility<TCache, TFilterTargets>(props: UseCachedVisibilityProps<TCache, TFilterTargets>) {\n const [filteredPaths, setFilteredPaths] = useState<HierarchyFilteringPath[] | undefined>(undefined);\n const { activeView, getCache, createFilteredTree, createTreeSpecificVisibilityHandler, componentId } = props;\n\n const [visibilityHandlerFactory, setVisibilityHandlerFactory] = useState<VisibilityTreeProps[\"visibilityHandlerFactory\"]>(() =>\n createVisibilityHandlerFactory({\n activeView,\n getCache,\n createFilteredTree,\n createTreeSpecificVisibilityHandler,\n filteringPaths: filteredPaths,\n componentId,\n }),\n );\n\n useEffect(() => {\n setVisibilityHandlerFactory(() =>\n createVisibilityHandlerFactory({\n activeView,\n getCache,\n createFilteredTree,\n createTreeSpecificVisibilityHandler,\n filteringPaths: filteredPaths,\n componentId,\n }),\n );\n }, [activeView, getCache, filteredPaths, createFilteredTree, createTreeSpecificVisibilityHandler, componentId]);\n\n return {\n visibilityHandlerFactory,\n onFilteredPathsChanged: useCallback((paths: HierarchyFilteringPath[] | undefined) => setFilteredPaths(paths), []),\n filteredPaths,\n };\n}\n\nfunction createVisibilityHandlerFactory<TCache, TFilterTargets>(\n props: UseCachedVisibilityProps<TCache, TFilterTargets> & {\n filteringPaths: HierarchyFilteringPath[] | undefined;\n },\n): VisibilityTreeProps[\"visibilityHandlerFactory\"] {\n const { activeView, createFilteredTree, createTreeSpecificVisibilityHandler, getCache, filteringPaths, componentId } = props;\n return ({ imodelAccess }) =>\n new HierarchyVisibilityHandlerImpl<TFilterTargets>({\n componentId,\n viewport: activeView,\n getFilteredTree: (): Promise<FilteredTree<TFilterTargets>> | undefined => {\n if (filteringPaths) {\n return createFilteredTree({ imodelAccess, filteringPaths, getCache });\n }\n return undefined;\n },\n getTreeSpecificVisibilityHandler: (info, overrideHandler) =>\n createTreeSpecificVisibilityHandler({\n info,\n getCache,\n viewport: activeView,\n overrideHandler,\n }),\n });\n}\n\n/** @internal */\nexport interface HierarchyVisibilityHandlerImplProps<TFilterTargets> {\n viewport: TreeWidgetViewport;\n getTreeSpecificVisibilityHandler: (\n info: AlwaysAndNeverDrawnElementInfo,\n overrideHandler: HierarchyVisibilityOverrideHandler,\n ) => TreeSpecificVisibilityHandler<TFilterTargets> & Disposable;\n getFilteredTree: () => Promise<FilteredTree<TFilterTargets>> | undefined;\n componentId?: GuidString;\n}\n\n/**\n * Class that handles visibility of hierarchy nodes in a tree.\n *\n * - It provides methods to get and change visibility status of nodes.\n * - Also handles filtered tree nodes visibility.\n * - Listens to visibility change events and updates visibility status accordingly.\n * @internal\n */\nexport class HierarchyVisibilityHandlerImpl<TFilterTargets> implements HierarchyVisibilityHandler, Disposable {\n readonly #props: HierarchyVisibilityHandlerImplProps<TFilterTargets>;\n readonly #eventListener: IVisibilityChangeEventListener;\n readonly #alwaysAndNeverDrawnElements: AlwaysAndNeverDrawnElementInfo;\n #treeSpecificVisibilityHandler: TreeSpecificVisibilityHandler<TFilterTargets> & Disposable;\n #changeRequest = new Subject<{ key: HierarchyNodeKey; depth: number }>();\n #filteredTree: Promise<FilteredTree<TFilterTargets>> | undefined;\n\n constructor(props: HierarchyVisibilityHandlerImplProps<TFilterTargets>) {\n this.#props = props;\n this.#eventListener = createVisibilityChangeEventListener({\n viewport: this.#props.viewport,\n listeners: {\n models: true,\n categories: true,\n elements: true,\n displayStyle: true,\n },\n });\n this.#alwaysAndNeverDrawnElements = new AlwaysAndNeverDrawnElementInfo({ viewport: this.#props.viewport, componentId: props.componentId });\n this.#treeSpecificVisibilityHandler = this.#props.getTreeSpecificVisibilityHandler(\n this.#alwaysAndNeverDrawnElements,\n new HierarchyVisibilityOverrideHandler(this),\n );\n this.#filteredTree = this.#props.getFilteredTree();\n }\n\n public get onVisibilityChange() {\n return this.#eventListener.onVisibilityChange;\n }\n\n public async getVisibilityStatus(node: HierarchyNode): Promise<VisibilityStatus> {\n return firstValueFrom(\n this.getVisibilityStatusInternal(node).pipe(\n // unsubscribe from the observable if the change request for this node is received\n takeUntil(this.#changeRequest.pipe(filter(({ key, depth }) => depth === node.parentKeys.length && HierarchyNodeKey.equals(node.key, key)))),\n // unsubscribe if visibility changes\n takeUntil(\n fromEventPattern(\n (handler) => {\n this.#eventListener.onVisibilityChange.addListener(handler);\n },\n (handler) => {\n this.#eventListener.onVisibilityChange.removeListener(handler);\n },\n ),\n ),\n defaultIfEmpty(createVisibilityStatus(\"hidden\")),\n ),\n );\n }\n\n public async changeVisibility(node: HierarchyNode, shouldDisplay: boolean): Promise<void> {\n // notify about new change request\n this.#changeRequest.next({ key: node.key, depth: node.parentKeys.length });\n\n const changeObservable = this.changeVisibilityStatusInternal(node, shouldDisplay).pipe(\n // unsubscribe from the observable if the change request for this node is received\n takeUntil(this.#changeRequest.pipe(filter(({ key, depth }) => depth === node.parentKeys.length && HierarchyNodeKey.equals(node.key, key)))),\n tap({\n subscribe: () => {\n this.#eventListener.suppressChangeEvents();\n this.#alwaysAndNeverDrawnElements.suppressChangeEvents();\n },\n finalize: () => {\n this.#eventListener.resumeChangeEvents();\n this.#alwaysAndNeverDrawnElements.resumeChangeEvents();\n },\n }),\n );\n\n return toVoidPromise(changeObservable);\n }\n\n public [Symbol.dispose]() {\n this.#eventListener[Symbol.dispose]();\n this.#alwaysAndNeverDrawnElements[Symbol.dispose]();\n this.#treeSpecificVisibilityHandler[Symbol.dispose]();\n }\n\n private getVisibilityStatusInternal(node: HierarchyNode) {\n if (HierarchyNode.isClassGroupingNode(node)) {\n if (node.extendedData?.hasDirectNonFilteredTargets && !node.filtering?.hasFilterTargetAncestor) {\n return this.getFilteredNodeVisibility({ node });\n }\n }\n\n if (HierarchyNode.isInstancesNode(node) && node.filtering?.filteredChildrenIdentifierPaths?.length && !node.filtering.isFilterTarget) {\n return this.getFilteredNodeVisibility({ node });\n }\n return this.#treeSpecificVisibilityHandler.getVisibilityStatus(node);\n }\n\n private changeVisibilityStatusInternal(node: HierarchyNode, on: boolean): Observable<void> {\n if (HierarchyNode.isClassGroupingNode(node)) {\n if (node.extendedData?.hasDirectNonFilteredTargets && !node.filtering?.hasFilterTargetAncestor) {\n return this.changeFilteredNodeVisibility({ node, on });\n }\n }\n if (HierarchyNode.isInstancesNode(node) && node.filtering?.filteredChildrenIdentifierPaths?.length && !node.filtering.isFilterTarget) {\n return this.changeFilteredNodeVisibility({ node, on });\n }\n return this.#treeSpecificVisibilityHandler.changeVisibilityStatus(node, on);\n }\n\n private getFilteredNodeVisibility(props: {\n node: HierarchyNode & {\n key: ClassGroupingNodeKey | InstancesNodeKey;\n };\n }) {\n return this.getFilteredTreeTargets(props).pipe(\n mergeMap((targets) => {\n if (!targets) {\n return EMPTY;\n }\n return this.#treeSpecificVisibilityHandler.getFilterTargetsVisibilityStatus(targets);\n }),\n );\n }\n\n private getFilteredTreeTargets({\n node,\n }: {\n node: HierarchyNode & {\n key: ClassGroupingNodeKey | InstancesNodeKey;\n };\n }): Observable<TFilterTargets | undefined> {\n assert(this.#filteredTree !== undefined);\n return from(this.#filteredTree).pipe(map((filteredTree) => filteredTree.getFilterTargets(node)));\n }\n\n private changeFilteredNodeVisibility({\n on,\n node,\n }: {\n on: boolean;\n node: HierarchyNode & {\n key: ClassGroupingNodeKey | InstancesNodeKey;\n };\n }) {\n return this.getFilteredTreeTargets({ node }).pipe(\n mergeMap((targets) => {\n if (!targets) {\n return EMPTY;\n }\n return this.#treeSpecificVisibilityHandler.changeFilterTargetsVisibilityStatus(targets, on);\n }),\n );\n }\n}\n"]}
|
package/lib/esm/tree-widget-react/components/trees/common/internal/useTreeHooks/UseIdsCache.d.ts
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
|
+
import type { GuidString } from "@itwin/core-bentley";
|
|
1
2
|
import type { IModelConnection } from "@itwin/core-frontend";
|
|
2
3
|
/** @internal */
|
|
3
4
|
export interface CreateCacheProps<TCacheSpecificProps> {
|
|
4
5
|
imodel: IModelConnection;
|
|
5
6
|
specificProps: TCacheSpecificProps;
|
|
7
|
+
componentId: GuidString;
|
|
6
8
|
}
|
|
7
9
|
/** @internal */
|
|
8
10
|
export interface UseIdsCacheProps<TCache, TCacheSpecificProps> {
|
|
9
11
|
imodel: IModelConnection;
|
|
10
12
|
createCache: (props: CreateCacheProps<TCacheSpecificProps>) => TCache;
|
|
11
13
|
cacheSpecificProps: TCacheSpecificProps;
|
|
14
|
+
componentId: GuidString;
|
|
12
15
|
}
|
|
13
16
|
/** @internal */
|
|
14
17
|
export declare function useIdsCache<TCache extends Disposable, TCacheSpecificProps extends object>(props: UseIdsCacheProps<TCache, TCacheSpecificProps>): {
|
package/lib/esm/tree-widget-react/components/trees/common/internal/useTreeHooks/UseIdsCache.js
CHANGED
|
@@ -12,32 +12,32 @@ export function useIdsCache(props) {
|
|
|
12
12
|
cacheRef.current = undefined;
|
|
13
13
|
});
|
|
14
14
|
const { imodel, createCache, cacheSpecificProps } = props;
|
|
15
|
-
const createCacheGetterRef = useRef((currImodel, specificProps) => {
|
|
15
|
+
const createCacheGetterRef = useRef((currImodel, specificProps, componentId) => {
|
|
16
16
|
return () => {
|
|
17
17
|
if (cacheRef.current === undefined) {
|
|
18
|
-
cacheRef.current = createCache({ imodel: currImodel, specificProps });
|
|
18
|
+
cacheRef.current = createCache({ imodel: currImodel, specificProps, componentId });
|
|
19
19
|
}
|
|
20
20
|
return cacheRef.current;
|
|
21
21
|
};
|
|
22
22
|
});
|
|
23
|
-
const [getCache, setCacheGetter] = useState(() => createCacheGetterRef.current(imodel, cacheSpecificProps));
|
|
23
|
+
const [getCache, setCacheGetter] = useState(() => createCacheGetterRef.current(imodel, cacheSpecificProps, props.componentId));
|
|
24
24
|
useEffect(() => {
|
|
25
25
|
// clear cache in case it was created before `useEffect` was run first time
|
|
26
26
|
clearCacheRef.current();
|
|
27
27
|
// make sure all cache users rerender
|
|
28
|
-
setCacheGetter(() => createCacheGetterRef.current(imodel, cacheSpecificProps));
|
|
28
|
+
setCacheGetter(() => createCacheGetterRef.current(imodel, cacheSpecificProps, props.componentId));
|
|
29
29
|
return () => {
|
|
30
30
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
31
31
|
clearCacheRef.current();
|
|
32
32
|
};
|
|
33
|
-
}, [imodel, cacheSpecificProps]);
|
|
33
|
+
}, [imodel, cacheSpecificProps, props.componentId]);
|
|
34
34
|
useIModelChangeListener({
|
|
35
35
|
imodel,
|
|
36
36
|
action: useCallback(() => {
|
|
37
37
|
clearCacheRef.current();
|
|
38
38
|
// make sure all cache users rerender
|
|
39
|
-
setCacheGetter(() => createCacheGetterRef.current(imodel, cacheSpecificProps));
|
|
40
|
-
}, [imodel, cacheSpecificProps]),
|
|
39
|
+
setCacheGetter(() => createCacheGetterRef.current(imodel, cacheSpecificProps, props.componentId));
|
|
40
|
+
}, [imodel, cacheSpecificProps, props.componentId]),
|
|
41
41
|
});
|
|
42
42
|
return {
|
|
43
43
|
getCache,
|
package/lib/esm/tree-widget-react/components/trees/common/internal/useTreeHooks/UseIdsCache.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UseIdsCache.js","sourceRoot":"","sources":["../../../../../../../../src/tree-widget-react/components/trees/common/internal/useTreeHooks/UseIdsCache.ts"],"names":[],"mappings":"AAAA;;;gGAGgG;AAEhG,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjE,OAAO,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"UseIdsCache.js","sourceRoot":"","sources":["../../../../../../../../src/tree-widget-react/components/trees/common/internal/useTreeHooks/UseIdsCache.ts"],"names":[],"mappings":"AAAA;;;gGAGgG;AAEhG,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjE,OAAO,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AAoBxE,gBAAgB;AAChB,MAAM,UAAU,WAAW,CACzB,KAAoD;IAEpD,MAAM,QAAQ,GAAG,MAAM,CAAqB,SAAS,CAAC,CAAC;IACvD,MAAM,aAAa,GAAG,MAAM,CAAC,GAAG,EAAE;QAChC,QAAQ,CAAC,OAAO,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;QACvC,QAAQ,CAAC,OAAO,GAAG,SAAS,CAAC;IAC/B,CAAC,CAAC,CAAC;IACH,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,kBAAkB,EAAE,GAAG,KAAK,CAAC;IAE1D,MAAM,oBAAoB,GAAG,MAAM,CAAC,CAAC,UAA4B,EAAE,aAAkC,EAAE,WAAuB,EAAE,EAAE;QAChI,OAAO,GAAG,EAAE;YACV,IAAI,QAAQ,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;gBACnC,QAAQ,CAAC,OAAO,GAAG,WAAW,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,aAAa,EAAE,WAAW,EAAE,CAAC,CAAC;YACrF,CAAC;YACD,OAAO,QAAQ,CAAC,OAAO,CAAC;QAC1B,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,QAAQ,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAe,GAAG,EAAE,CAAC,oBAAoB,CAAC,OAAO,CAAC,MAAM,EAAE,kBAAkB,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC;IAE7I,SAAS,CAAC,GAAG,EAAE;QACb,2EAA2E;QAC3E,aAAa,CAAC,OAAO,EAAE,CAAC;QAExB,qCAAqC;QACrC,cAAc,CAAC,GAAG,EAAE,CAAC,oBAAoB,CAAC,OAAO,CAAC,MAAM,EAAE,kBAAkB,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC;QAClG,OAAO,GAAG,EAAE;YACV,uDAAuD;YACvD,aAAa,CAAC,OAAO,EAAE,CAAC;QAC1B,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,MAAM,EAAE,kBAAkB,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC;IAEpD,uBAAuB,CAAC;QACtB,MAAM;QACN,MAAM,EAAE,WAAW,CAAC,GAAG,EAAE;YACvB,aAAa,CAAC,OAAO,EAAE,CAAC;YACxB,qCAAqC;YACrC,cAAc,CAAC,GAAG,EAAE,CAAC,oBAAoB,CAAC,OAAO,CAAC,MAAM,EAAE,kBAAkB,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC;QACpG,CAAC,EAAE,CAAC,MAAM,EAAE,kBAAkB,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;KACpD,CAAC,CAAC;IAEH,OAAO;QACL,QAAQ;KACT,CAAC;AACJ,CAAC","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useIModelChangeListener } from \"../UseIModelChangeListener.js\";\n\nimport type { GuidString } from \"@itwin/core-bentley\";\nimport type { IModelConnection } from \"@itwin/core-frontend\";\n\n/** @internal */\nexport interface CreateCacheProps<TCacheSpecificProps> {\n imodel: IModelConnection;\n specificProps: TCacheSpecificProps;\n componentId: GuidString;\n}\n\n/** @internal */\nexport interface UseIdsCacheProps<TCache, TCacheSpecificProps> {\n imodel: IModelConnection;\n createCache: (props: CreateCacheProps<TCacheSpecificProps>) => TCache;\n cacheSpecificProps: TCacheSpecificProps;\n componentId: GuidString;\n}\n\n/** @internal */\nexport function useIdsCache<TCache extends Disposable, TCacheSpecificProps extends object>(\n props: UseIdsCacheProps<TCache, TCacheSpecificProps>,\n): { getCache: () => TCache } {\n const cacheRef = useRef<TCache | undefined>(undefined);\n const clearCacheRef = useRef(() => {\n cacheRef.current?.[Symbol.dispose]?.();\n cacheRef.current = undefined;\n });\n const { imodel, createCache, cacheSpecificProps } = props;\n\n const createCacheGetterRef = useRef((currImodel: IModelConnection, specificProps: TCacheSpecificProps, componentId: GuidString) => {\n return () => {\n if (cacheRef.current === undefined) {\n cacheRef.current = createCache({ imodel: currImodel, specificProps, componentId });\n }\n return cacheRef.current;\n };\n });\n\n const [getCache, setCacheGetter] = useState<() => TCache>(() => createCacheGetterRef.current(imodel, cacheSpecificProps, props.componentId));\n\n useEffect(() => {\n // clear cache in case it was created before `useEffect` was run first time\n clearCacheRef.current();\n\n // make sure all cache users rerender\n setCacheGetter(() => createCacheGetterRef.current(imodel, cacheSpecificProps, props.componentId));\n return () => {\n // eslint-disable-next-line react-hooks/exhaustive-deps\n clearCacheRef.current();\n };\n }, [imodel, cacheSpecificProps, props.componentId]);\n\n useIModelChangeListener({\n imodel,\n action: useCallback(() => {\n clearCacheRef.current();\n // make sure all cache users rerender\n setCacheGetter(() => createCacheGetterRef.current(imodel, cacheSpecificProps, props.componentId));\n }, [imodel, cacheSpecificProps, props.componentId]),\n });\n\n return {\n getCache,\n };\n}\n"]}
|
package/lib/esm/tree-widget-react/components/trees/common/internal/visibility/BaseFilteredTree.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { HierarchyFilteringPath } from "@itwin/presentation-hierarchies";
|
|
1
|
+
import { HierarchyFilteringPath, HierarchyNode } from "@itwin/presentation-hierarchies";
|
|
2
2
|
import type { Id64String } from "@itwin/core-bentley";
|
|
3
|
-
import type {
|
|
3
|
+
import type { ClassGroupingNodeKey, InstancesNodeKey } from "@itwin/presentation-hierarchies";
|
|
4
4
|
import type { InstanceKey } from "@itwin/presentation-shared";
|
|
5
5
|
/** @internal */
|
|
6
6
|
export type FilteredTreeNodeChildren<TFilteredTreeNode> = Map<Id64String, TFilteredTreeNode>;
|
|
@@ -57,7 +57,9 @@ export declare abstract class FilteredNodesHandler<TProcessedFilteredNodes, TFil
|
|
|
57
57
|
parent: TFilteredTreeNode | FilteredTreeRootNode<TFilteredTreeNode>;
|
|
58
58
|
}): TFilteredTreeNode;
|
|
59
59
|
processFilteredNodes(): Promise<{
|
|
60
|
-
getNodeFilterTargets: (node: HierarchyNode
|
|
60
|
+
getNodeFilterTargets: (node: HierarchyNode & {
|
|
61
|
+
key: ClassGroupingNodeKey | InstancesNodeKey;
|
|
62
|
+
}) => TFilterTargets | undefined;
|
|
61
63
|
}>;
|
|
62
64
|
/** Takes a new node and adds it to the tree structure. */
|
|
63
65
|
accept(props: {
|
|
@@ -72,7 +74,9 @@ export declare abstract class FilteredNodesHandler<TProcessedFilteredNodes, TFil
|
|
|
72
74
|
}
|
|
73
75
|
/** @internal */
|
|
74
76
|
export interface FilteredTree<TFilterTargets> {
|
|
75
|
-
getFilterTargets: (node: HierarchyNode
|
|
77
|
+
getFilterTargets: (node: HierarchyNode & {
|
|
78
|
+
key: ClassGroupingNodeKey | InstancesNodeKey;
|
|
79
|
+
}) => TFilterTargets | undefined;
|
|
76
80
|
}
|
|
77
81
|
/** @internal */
|
|
78
82
|
export interface CreateFilteredTreeProps<TProcessedFilteredNodes, TFilterTargets, TFilteredTreeNode extends BaseFilteredTreeNode<TFilteredTreeNode>> {
|
package/lib/esm/tree-widget-react/components/trees/common/internal/visibility/BaseFilteredTree.js
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
3
3
|
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
4
4
|
*--------------------------------------------------------------------------------------------*/
|
|
5
|
-
import {
|
|
5
|
+
import { Id64 } from "@itwin/core-bentley";
|
|
6
|
+
import { HierarchyFilteringPath, HierarchyNode, HierarchyNodeIdentifier, HierarchyNodeKey } from "@itwin/presentation-hierarchies";
|
|
6
7
|
/**
|
|
7
8
|
* Class that provides methods to handle filtered nodes in a tree structure.
|
|
8
9
|
*
|
|
@@ -39,10 +40,6 @@ export class FilteredNodesHandler {
|
|
|
39
40
|
/** Takes a specific node and gets all filter targets related to it. */
|
|
40
41
|
getNodeFilterTargets(node, processedFilteredNodes) {
|
|
41
42
|
let lookupParents = [this.root];
|
|
42
|
-
const nodeKey = node.key;
|
|
43
|
-
if (!HierarchyNodeKey.isInstances(nodeKey)) {
|
|
44
|
-
return undefined;
|
|
45
|
-
}
|
|
46
43
|
// find the filtered parent nodes of the `node`
|
|
47
44
|
for (const parentKey of node.parentKeys) {
|
|
48
45
|
if (!HierarchyNodeKey.isInstances(parentKey)) {
|
|
@@ -50,24 +47,32 @@ export class FilteredNodesHandler {
|
|
|
50
47
|
}
|
|
51
48
|
// tree node might be merged from multiple instances. As filtered tree stores only one instance per node, we need to find all matching nodes
|
|
52
49
|
// and use them when checking for matching node in one level deeper.
|
|
53
|
-
const parentNodes = this.findMatchingFilteredNodes(lookupParents, parentKey.instanceKeys);
|
|
50
|
+
const parentNodes = this.findMatchingFilteredNodes(lookupParents, parentKey.instanceKeys.map((key) => key.id));
|
|
54
51
|
if (parentNodes.length === 0) {
|
|
55
52
|
return undefined;
|
|
56
53
|
}
|
|
57
54
|
lookupParents = parentNodes;
|
|
58
55
|
}
|
|
56
|
+
const ids = HierarchyNode.isInstancesNode(node) ? node.key.instanceKeys.map(({ id }) => id) : node.groupedInstanceKeys.map(({ id }) => id);
|
|
59
57
|
// find filtered nodes that match the `node`
|
|
60
|
-
const filteredNodes = this.findMatchingFilteredNodes(lookupParents,
|
|
58
|
+
const filteredNodes = this.findMatchingFilteredNodes(lookupParents, ids);
|
|
61
59
|
if (filteredNodes.length === 0) {
|
|
62
60
|
return undefined;
|
|
63
61
|
}
|
|
64
62
|
return this.convertNodesToFilterTargets(filteredNodes, processedFilteredNodes);
|
|
65
63
|
}
|
|
66
64
|
/** Finds filtered nodes that match the given keys. */
|
|
67
|
-
findMatchingFilteredNodes(lookupParents,
|
|
68
|
-
return lookupParents
|
|
69
|
-
|
|
70
|
-
|
|
65
|
+
findMatchingFilteredNodes(lookupParents, ids) {
|
|
66
|
+
return lookupParents.flatMap((lookup) => {
|
|
67
|
+
const childrenArray = Array();
|
|
68
|
+
for (const id of Id64.iterable(ids)) {
|
|
69
|
+
const node = lookup.children?.get(id);
|
|
70
|
+
if (node) {
|
|
71
|
+
childrenArray.push(node);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return childrenArray;
|
|
75
|
+
});
|
|
71
76
|
}
|
|
72
77
|
}
|
|
73
78
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseFilteredTree.js","sourceRoot":"","sources":["../../../../../../../../src/tree-widget-react/components/trees/common/internal/visibility/BaseFilteredTree.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\nimport { HierarchyFilteringPath, HierarchyNodeIdentifier, HierarchyNodeKey } from \"@itwin/presentation-hierarchies\";\n\nimport type { Id64String } from \"@itwin/core-bentley\";\nimport type { HierarchyNode } from \"@itwin/presentation-hierarchies\";\nimport type { InstanceKey } from \"@itwin/presentation-shared\";\n\n/** @internal */\nexport type FilteredTreeNodeChildren<TFilteredTreeNode> = Map<Id64String, TFilteredTreeNode>;\n\n/**\n * A generic interface for a filtered tree root node.\n *\n * It differs from `BaseFilteredTreeNode` in that it only contains children details and nothing else.\n * @internal\n */\nexport interface FilteredTreeRootNode<TFilteredTreeNode extends BaseFilteredTreeNode<TFilteredTreeNode>> {\n children: FilteredTreeNodeChildren<TFilteredTreeNode>;\n}\n\n/**\n * A generic interface for a filtered tree node.\n *\n * It represents every node in a filtered tree structure.\n * @internal\n * */\nexport interface BaseFilteredTreeNode<TFilteredTreeNode extends BaseFilteredTreeNode<TFilteredTreeNode>> {\n type: string;\n id: Id64String;\n children?: FilteredTreeNodeChildren<TFilteredTreeNode>;\n isFilterTarget: boolean;\n}\n\n/**\n * Class that provides methods to handle filtered nodes in a tree structure.\n *\n * It provides two methods that can be shared across different filtered trees:\n * - `processFilteredNodes` - processes filtered nodes and returns a function to get filter targets for a node.\n * - `accept` - accepts a new node and adds it to the tree structure.\n * @internal\n */\nexport abstract class FilteredNodesHandler<TProcessedFilteredNodes, TFilterTargets, TFilteredTreeNode extends BaseFilteredTreeNode<TFilteredTreeNode>> {\n public readonly root: FilteredTreeRootNode<TFilteredTreeNode> = {\n children: new Map(),\n };\n public readonly filteredNodesArr = new Array<TFilteredTreeNode>();\n\n /** Returns filtered tree node type based on its' className */\n public abstract getType(className: string): Promise<TFilteredTreeNode[\"type\"]>;\n /** Converts nodes to filter targets */\n public abstract convertNodesToFilterTargets(filteredNodes: TFilteredTreeNode[], processedFilteredNodes: TProcessedFilteredNodes): TFilterTargets | undefined;\n /**\n * Processes filtered nodes.\n *\n * Nodes are created using filtering paths, and some information is not present in the filtering paths.\n * Because of this, some nodes may need to be processed to get additional information.\n *\n * E.g. Retrieving categoryId of elements can't be done using filtering paths.\n */\n public abstract getProcessedFilteredNodes(): Promise<TProcessedFilteredNodes>;\n /** Creates filtered nodes */\n public abstract createFilteredTreeNode(props: {\n type: TFilteredTreeNode[\"type\"];\n id: Id64String;\n isFilterTarget: boolean;\n parent: TFilteredTreeNode | FilteredTreeRootNode<TFilteredTreeNode>;\n }): TFilteredTreeNode;\n\n public async processFilteredNodes(): Promise<{ getNodeFilterTargets: (node: HierarchyNode) => TFilterTargets | undefined }> {\n const processedFilteredNodes = await this.getProcessedFilteredNodes();\n return {\n getNodeFilterTargets: (node: HierarchyNode) => this.getNodeFilterTargets(node, processedFilteredNodes),\n };\n }\n\n /** Takes a new node and adds it to the tree structure. */\n public async accept(props: {\n instanceKey: InstanceKey;\n parentNode: TFilteredTreeNode | FilteredTreeRootNode<TFilteredTreeNode>;\n isFilterTarget: boolean;\n }): Promise<TFilteredTreeNode> {\n const { instanceKey, parentNode, isFilterTarget } = props;\n const type = await this.getType(instanceKey.className);\n\n const newNode = this.createFilteredTreeNode({\n type,\n id: instanceKey.id,\n isFilterTarget,\n parent: parentNode,\n });\n (parentNode.children ??= new Map()).set(instanceKey.id, newNode);\n this.filteredNodesArr.push(newNode);\n return newNode;\n }\n\n /** Takes a specific node and gets all filter targets related to it. */\n private getNodeFilterTargets(node: HierarchyNode, processedFilteredNodes: TProcessedFilteredNodes): TFilterTargets | undefined {\n let lookupParents: Array<{ children?: Map<Id64String, TFilteredTreeNode> }> = [this.root];\n\n const nodeKey = node.key;\n if (!HierarchyNodeKey.isInstances(nodeKey)) {\n return undefined;\n }\n\n // find the filtered parent nodes of the `node`\n for (const parentKey of node.parentKeys) {\n if (!HierarchyNodeKey.isInstances(parentKey)) {\n continue;\n }\n\n // tree node might be merged from multiple instances. As filtered tree stores only one instance per node, we need to find all matching nodes\n // and use them when checking for matching node in one level deeper.\n const parentNodes = this.findMatchingFilteredNodes(lookupParents, parentKey.instanceKeys);\n if (parentNodes.length === 0) {\n return undefined;\n }\n lookupParents = parentNodes;\n }\n\n // find filtered nodes that match the `node`\n const filteredNodes = this.findMatchingFilteredNodes(lookupParents, nodeKey.instanceKeys);\n if (filteredNodes.length === 0) {\n return undefined;\n }\n\n return this.convertNodesToFilterTargets(filteredNodes, processedFilteredNodes);\n }\n\n /** Finds filtered nodes that match the given keys. */\n private findMatchingFilteredNodes(lookupParents: Array<{ children?: Map<Id64String, TFilteredTreeNode> }>, keys: InstanceKey[]) {\n return lookupParents\n .flatMap((lookup) => keys.map((key) => lookup.children?.get(key.id)))\n .filter((lookupNode): lookupNode is TFilteredTreeNode => lookupNode !== undefined);\n }\n}\n\n/** @internal */\nexport interface FilteredTree<TFilterTargets> {\n getFilterTargets: (node: HierarchyNode) => TFilterTargets | undefined;\n}\n\n/** @internal */\nexport interface CreateFilteredTreeProps<TProcessedFilteredNodes, TFilterTargets, TFilteredTreeNode extends BaseFilteredTreeNode<TFilteredTreeNode>> {\n filteredNodesHandler: FilteredNodesHandler<TProcessedFilteredNodes, TFilterTargets, TFilteredTreeNode>;\n filteringPaths: HierarchyFilteringPath[];\n}\n\n/**\n * Function iterates over filtering paths and creates uses `filteredNodesHandler` to create a filtered tree.\n * @internal\n */\nexport async function createFilteredTree<TProcessedFilteredNodes, TFilterTargets, TFilteredTreeNode extends BaseFilteredTreeNode<TFilteredTreeNode>>(\n props: CreateFilteredTreeProps<TProcessedFilteredNodes, TFilterTargets, TFilteredTreeNode>,\n): Promise<FilteredTree<TFilterTargets>> {\n const { filteringPaths, filteredNodesHandler } = props;\n\n for (const filteringPath of filteringPaths) {\n const normalizedPath = HierarchyFilteringPath.normalize(filteringPath).path;\n\n let parentNode: FilteredTreeRootNode<TFilteredTreeNode> | TFilteredTreeNode = filteredNodesHandler.root;\n for (let i = 0; i < normalizedPath.length; ++i) {\n if (\"type\" in parentNode && \"isFilterTarget\" in parentNode && parentNode.isFilterTarget) {\n break;\n }\n\n const identifier = normalizedPath[i];\n\n if (!HierarchyNodeIdentifier.isInstanceNodeIdentifier(identifier)) {\n break;\n }\n\n const currentNode: TFilteredTreeNode | undefined = parentNode.children?.get(identifier.id);\n if (currentNode !== undefined) {\n parentNode = currentNode;\n continue;\n }\n parentNode = await filteredNodesHandler.accept({\n instanceKey: identifier,\n parentNode,\n isFilterTarget: i === normalizedPath.length - 1,\n });\n }\n }\n const processedFilteredNodes = await filteredNodesHandler.processFilteredNodes();\n return {\n getFilterTargets: (node: HierarchyNode) => processedFilteredNodes.getNodeFilterTargets(node),\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"BaseFilteredTree.js","sourceRoot":"","sources":["../../../../../../../../src/tree-widget-react/components/trees/common/internal/visibility/BaseFilteredTree.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Id64 } from \"@itwin/core-bentley\";\nimport { HierarchyFilteringPath, HierarchyNode, HierarchyNodeIdentifier, HierarchyNodeKey } from \"@itwin/presentation-hierarchies\";\n\nimport type { Id64Arg, Id64String } from \"@itwin/core-bentley\";\nimport type { ClassGroupingNodeKey, InstancesNodeKey } from \"@itwin/presentation-hierarchies\";\nimport type { InstanceKey } from \"@itwin/presentation-shared\";\n\n/** @internal */\nexport type FilteredTreeNodeChildren<TFilteredTreeNode> = Map<Id64String, TFilteredTreeNode>;\n\n/**\n * A generic interface for a filtered tree root node.\n *\n * It differs from `BaseFilteredTreeNode` in that it only contains children details and nothing else.\n * @internal\n */\nexport interface FilteredTreeRootNode<TFilteredTreeNode extends BaseFilteredTreeNode<TFilteredTreeNode>> {\n children: FilteredTreeNodeChildren<TFilteredTreeNode>;\n}\n\n/**\n * A generic interface for a filtered tree node.\n *\n * It represents every node in a filtered tree structure.\n * @internal\n * */\nexport interface BaseFilteredTreeNode<TFilteredTreeNode extends BaseFilteredTreeNode<TFilteredTreeNode>> {\n type: string;\n id: Id64String;\n children?: FilteredTreeNodeChildren<TFilteredTreeNode>;\n isFilterTarget: boolean;\n}\n\n/**\n * Class that provides methods to handle filtered nodes in a tree structure.\n *\n * It provides two methods that can be shared across different filtered trees:\n * - `processFilteredNodes` - processes filtered nodes and returns a function to get filter targets for a node.\n * - `accept` - accepts a new node and adds it to the tree structure.\n * @internal\n */\nexport abstract class FilteredNodesHandler<TProcessedFilteredNodes, TFilterTargets, TFilteredTreeNode extends BaseFilteredTreeNode<TFilteredTreeNode>> {\n public readonly root: FilteredTreeRootNode<TFilteredTreeNode> = {\n children: new Map(),\n };\n public readonly filteredNodesArr = new Array<TFilteredTreeNode>();\n\n /** Returns filtered tree node type based on its' className */\n public abstract getType(className: string): Promise<TFilteredTreeNode[\"type\"]>;\n /** Converts nodes to filter targets */\n public abstract convertNodesToFilterTargets(filteredNodes: TFilteredTreeNode[], processedFilteredNodes: TProcessedFilteredNodes): TFilterTargets | undefined;\n /**\n * Processes filtered nodes.\n *\n * Nodes are created using filtering paths, and some information is not present in the filtering paths.\n * Because of this, some nodes may need to be processed to get additional information.\n *\n * E.g. Retrieving categoryId of elements can't be done using filtering paths.\n */\n public abstract getProcessedFilteredNodes(): Promise<TProcessedFilteredNodes>;\n /** Creates filtered nodes */\n public abstract createFilteredTreeNode(props: {\n type: TFilteredTreeNode[\"type\"];\n id: Id64String;\n isFilterTarget: boolean;\n parent: TFilteredTreeNode | FilteredTreeRootNode<TFilteredTreeNode>;\n }): TFilteredTreeNode;\n\n public async processFilteredNodes(): Promise<{\n getNodeFilterTargets: (node: HierarchyNode & { key: ClassGroupingNodeKey | InstancesNodeKey }) => TFilterTargets | undefined;\n }> {\n const processedFilteredNodes = await this.getProcessedFilteredNodes();\n return {\n getNodeFilterTargets: (node: HierarchyNode & { key: ClassGroupingNodeKey | InstancesNodeKey }) => this.getNodeFilterTargets(node, processedFilteredNodes),\n };\n }\n\n /** Takes a new node and adds it to the tree structure. */\n public async accept(props: {\n instanceKey: InstanceKey;\n parentNode: TFilteredTreeNode | FilteredTreeRootNode<TFilteredTreeNode>;\n isFilterTarget: boolean;\n }): Promise<TFilteredTreeNode> {\n const { instanceKey, parentNode, isFilterTarget } = props;\n const type = await this.getType(instanceKey.className);\n\n const newNode = this.createFilteredTreeNode({\n type,\n id: instanceKey.id,\n isFilterTarget,\n parent: parentNode,\n });\n (parentNode.children ??= new Map()).set(instanceKey.id, newNode);\n this.filteredNodesArr.push(newNode);\n return newNode;\n }\n\n /** Takes a specific node and gets all filter targets related to it. */\n private getNodeFilterTargets(\n node: HierarchyNode & { key: ClassGroupingNodeKey | InstancesNodeKey },\n processedFilteredNodes: TProcessedFilteredNodes,\n ): TFilterTargets | undefined {\n let lookupParents: Array<FilteredTreeRootNode<TFilteredTreeNode> | TFilteredTreeNode> = [this.root];\n\n // find the filtered parent nodes of the `node`\n for (const parentKey of node.parentKeys) {\n if (!HierarchyNodeKey.isInstances(parentKey)) {\n continue;\n }\n\n // tree node might be merged from multiple instances. As filtered tree stores only one instance per node, we need to find all matching nodes\n // and use them when checking for matching node in one level deeper.\n const parentNodes = this.findMatchingFilteredNodes(\n lookupParents,\n parentKey.instanceKeys.map((key) => key.id),\n );\n if (parentNodes.length === 0) {\n return undefined;\n }\n lookupParents = parentNodes;\n }\n\n const ids = HierarchyNode.isInstancesNode(node) ? node.key.instanceKeys.map(({ id }) => id) : node.groupedInstanceKeys.map(({ id }) => id);\n // find filtered nodes that match the `node`\n const filteredNodes = this.findMatchingFilteredNodes(lookupParents, ids);\n if (filteredNodes.length === 0) {\n return undefined;\n }\n\n return this.convertNodesToFilterTargets(filteredNodes, processedFilteredNodes);\n }\n\n /** Finds filtered nodes that match the given keys. */\n private findMatchingFilteredNodes(lookupParents: Array<FilteredTreeRootNode<TFilteredTreeNode> | TFilteredTreeNode>, ids: Id64Arg) {\n return lookupParents.flatMap((lookup) => {\n const childrenArray = Array<TFilteredTreeNode>();\n for (const id of Id64.iterable(ids)) {\n const node = lookup.children?.get(id);\n if (node) {\n childrenArray.push(node);\n }\n }\n return childrenArray;\n });\n }\n}\n\n/** @internal */\nexport interface FilteredTree<TFilterTargets> {\n getFilterTargets: (node: HierarchyNode & { key: ClassGroupingNodeKey | InstancesNodeKey }) => TFilterTargets | undefined;\n}\n\n/** @internal */\nexport interface CreateFilteredTreeProps<TProcessedFilteredNodes, TFilterTargets, TFilteredTreeNode extends BaseFilteredTreeNode<TFilteredTreeNode>> {\n filteredNodesHandler: FilteredNodesHandler<TProcessedFilteredNodes, TFilterTargets, TFilteredTreeNode>;\n filteringPaths: HierarchyFilteringPath[];\n}\n\n/**\n * Function iterates over filtering paths and creates uses `filteredNodesHandler` to create a filtered tree.\n * @internal\n */\nexport async function createFilteredTree<TProcessedFilteredNodes, TFilterTargets, TFilteredTreeNode extends BaseFilteredTreeNode<TFilteredTreeNode>>(\n props: CreateFilteredTreeProps<TProcessedFilteredNodes, TFilterTargets, TFilteredTreeNode>,\n): Promise<FilteredTree<TFilterTargets>> {\n const { filteringPaths, filteredNodesHandler } = props;\n\n for (const filteringPath of filteringPaths) {\n const normalizedPath = HierarchyFilteringPath.normalize(filteringPath).path;\n\n let parentNode: FilteredTreeRootNode<TFilteredTreeNode> | TFilteredTreeNode = filteredNodesHandler.root;\n for (let i = 0; i < normalizedPath.length; ++i) {\n if (\"type\" in parentNode && \"isFilterTarget\" in parentNode && parentNode.isFilterTarget) {\n break;\n }\n\n const identifier = normalizedPath[i];\n\n if (!HierarchyNodeIdentifier.isInstanceNodeIdentifier(identifier)) {\n break;\n }\n\n const currentNode: TFilteredTreeNode | undefined = parentNode.children?.get(identifier.id);\n if (currentNode !== undefined) {\n parentNode = currentNode;\n continue;\n }\n parentNode = await filteredNodesHandler.accept({\n instanceKey: identifier,\n parentNode,\n isFilterTarget: i === normalizedPath.length - 1,\n });\n }\n }\n const processedFilteredNodes = await filteredNodesHandler.processFilteredNodes();\n return {\n getFilterTargets: (node: HierarchyNode & { key: ClassGroupingNodeKey | InstancesNodeKey }) => processedFilteredNodes.getNodeFilterTargets(node),\n };\n}\n"]}
|
|
@@ -40,7 +40,7 @@ export interface BaseTreeVisibilityHandlerOverrides {
|
|
|
40
40
|
}
|
|
41
41
|
/** @internal */
|
|
42
42
|
export interface BaseIdsCache {
|
|
43
|
-
hasSubModel: (elementId: Id64String) =>
|
|
43
|
+
hasSubModel: (elementId: Id64String) => Observable<boolean>;
|
|
44
44
|
getElementsCount: (props: {
|
|
45
45
|
modelId: Id64String;
|
|
46
46
|
categoryId: Id64String;
|
|
@@ -66,6 +66,7 @@ export interface BaseIdsCache {
|
|
|
66
66
|
}>;
|
|
67
67
|
getSubModels: (props: {
|
|
68
68
|
modelIds: Id64Arg;
|
|
69
|
+
categoryId?: Id64String;
|
|
69
70
|
} | {
|
|
70
71
|
categoryIds: Id64Arg;
|
|
71
72
|
modelId: Id64String | undefined;
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
3
3
|
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
4
4
|
*--------------------------------------------------------------------------------------------*/
|
|
5
|
-
import { concat, concatAll, defaultIfEmpty, defer, EMPTY, filter, forkJoin, from, map, merge, mergeMap, of, reduce, shareReplay, startWith, Subject, take, takeUntil, tap, } from "rxjs";
|
|
5
|
+
import { concat, concatAll, defaultIfEmpty, defer, EMPTY, filter, forkJoin, from, identity, map, merge, mergeMap, of, reduce, shareReplay, startWith, Subject, take, takeLast, takeUntil, tap, } from "rxjs";
|
|
6
6
|
import { assert, Id64 } from "@itwin/core-bentley";
|
|
7
7
|
import { createVisibilityStatus } from "../Tooltip.js";
|
|
8
|
-
import { getSetFromId64Arg, setDifference, setIntersection } from "../Utils.js";
|
|
8
|
+
import { getSetFromId64Arg, releaseMainThreadOnItemsCount, setDifference, setIntersection } from "../Utils.js";
|
|
9
9
|
import { changeElementStateNoChildrenOperator, enableCategoryDisplay, getVisibilityFromAlwaysAndNeverDrawnElementsImpl, mergeVisibilityStatuses, } from "../VisibilityUtils.js";
|
|
10
10
|
/**
|
|
11
11
|
* Base class for visibility status getters and modifiers.
|
|
@@ -199,7 +199,24 @@ export class BaseVisibilityHelper {
|
|
|
199
199
|
}
|
|
200
200
|
return (modelIdFromProps
|
|
201
201
|
? from(Id64.iterable(categoryIds)).pipe(map((categoryId) => ({ id: categoryId, models: modelIdFromProps })))
|
|
202
|
-
: this.#props.baseIdsCache.getModels({ categoryIds })).pipe(
|
|
202
|
+
: this.#props.baseIdsCache.getModels({ categoryIds })).pipe(mergeMap(({ id, models }) => {
|
|
203
|
+
if (!this.#props.viewport.isAlwaysDrawnExclusive) {
|
|
204
|
+
return of({ id, models });
|
|
205
|
+
}
|
|
206
|
+
// Ignore categories that don't have root geometric elements in always drawn exclusive mode
|
|
207
|
+
if (!models) {
|
|
208
|
+
return EMPTY;
|
|
209
|
+
}
|
|
210
|
+
return from(Id64.iterable(models)).pipe(mergeMap((modelId) => forkJoin({
|
|
211
|
+
modelId: of(modelId),
|
|
212
|
+
elementCount: this.#props.baseIdsCache.getElementsCount({ modelId, categoryId: id }),
|
|
213
|
+
})), reduce((acc, { modelId, elementCount }) => {
|
|
214
|
+
if (elementCount > 0) {
|
|
215
|
+
acc.models.push(modelId);
|
|
216
|
+
}
|
|
217
|
+
return acc;
|
|
218
|
+
}, { id, models: new Array() }), filter(({ models: modelsWithElements }) => modelsWithElements.length > 0));
|
|
219
|
+
}), map(({ id, models }) => {
|
|
203
220
|
const acc = { categoryId: id, visibleModels: new Array(), hiddenModels: new Array() };
|
|
204
221
|
if (!models) {
|
|
205
222
|
return acc;
|
|
@@ -217,7 +234,7 @@ export class BaseVisibilityHelper {
|
|
|
217
234
|
return merge(
|
|
218
235
|
// For hidden models we only need to check subModels
|
|
219
236
|
hiddenModels.length > 0
|
|
220
|
-
? this.#props.baseIdsCache.getSubModels({ modelIds: hiddenModels }).pipe(mergeMap(({ subModels }) => {
|
|
237
|
+
? this.#props.baseIdsCache.getSubModels({ modelIds: hiddenModels, categoryId }).pipe(mergeMap(({ subModels }) => {
|
|
221
238
|
if (subModels && Id64.sizeOf(subModels) > 0) {
|
|
222
239
|
return this.getModelsVisibilityStatus({
|
|
223
240
|
modelIds: subModels,
|
|
@@ -241,7 +258,7 @@ export class BaseVisibilityHelper {
|
|
|
241
258
|
return this.getSubCategoriesVisibilityStatus({ categoryId, modelId: modelIdFromProps, subCategoryIds: subCategories });
|
|
242
259
|
}
|
|
243
260
|
return EMPTY;
|
|
244
|
-
}))).pipe(defaultIfEmpty(createVisibilityStatus(this.#props.viewport.viewsCategory(categoryId) ? "visible" : "hidden")));
|
|
261
|
+
}))).pipe(defaultIfEmpty(createVisibilityStatus(!this.#props.viewport.isAlwaysDrawnExclusive && this.#props.viewport.viewsCategory(categoryId) ? "visible" : "hidden")));
|
|
245
262
|
}), mergeVisibilityStatuses);
|
|
246
263
|
});
|
|
247
264
|
return this.#props.overrideHandler
|
|
@@ -294,7 +311,7 @@ export class BaseVisibilityHelper {
|
|
|
294
311
|
}
|
|
295
312
|
// TODO: check child elements that are subModels
|
|
296
313
|
if (!this.#props.viewport.viewsModel(modelId)) {
|
|
297
|
-
return from(elementIds).pipe(mergeMap((elementId) =>
|
|
314
|
+
return from(elementIds).pipe(releaseMainThreadOnItemsCount(100), mergeMap((elementId) => this.#props.baseIdsCache.hasSubModel(elementId).pipe(mergeMap((isSubModel) => {
|
|
298
315
|
if (isSubModel) {
|
|
299
316
|
return this.getModelsVisibilityStatus({
|
|
300
317
|
modelIds: elementId,
|
|
@@ -311,7 +328,7 @@ export class BaseVisibilityHelper {
|
|
|
311
328
|
elements: elementIds,
|
|
312
329
|
defaultStatus: () => this.getVisibleModelCategoriesDirectVisibilityStatus({ categoryIds: categoryId, modelId }),
|
|
313
330
|
}).pipe(mergeMap((visibilityStatusAlwaysAndNeverDraw) => {
|
|
314
|
-
return from(Id64.iterable(elementIds)).pipe(mergeMap((elementId) =>
|
|
331
|
+
return from(Id64.iterable(elementIds)).pipe(mergeMap((elementId) => this.#props.baseIdsCache.hasSubModel(elementId).pipe(mergeMap((isSubModel) => {
|
|
315
332
|
if (isSubModel) {
|
|
316
333
|
return this.getModelsVisibilityStatus({
|
|
317
334
|
modelIds: elementId,
|
|
@@ -353,14 +370,14 @@ export class BaseVisibilityHelper {
|
|
|
353
370
|
}));
|
|
354
371
|
}
|
|
355
372
|
const { modelId, categoryIds } = props.queryProps;
|
|
356
|
-
|
|
357
|
-
return
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
})
|
|
373
|
+
return from(Id64.iterable(categoryIds)).pipe(releaseMainThreadOnItemsCount(100), mergeMap((categoryId) => {
|
|
374
|
+
return forkJoin({
|
|
375
|
+
categoryId: of(categoryId),
|
|
376
|
+
totalCount: this.#props.baseIdsCache.getElementsCount({ modelId, categoryId }),
|
|
377
|
+
alwaysDrawn: this.#alwaysAndNeverDrawnElements.getAlwaysOrNeverDrawnElements({ modelIds: modelId, categoryIds: categoryId, setType: "always" }),
|
|
378
|
+
neverDrawn: this.#alwaysAndNeverDrawnElements.getAlwaysOrNeverDrawnElements({ modelIds: modelId, categoryIds: categoryId, setType: "never" }),
|
|
379
|
+
});
|
|
380
|
+
}),
|
|
364
381
|
// There is a known bug:
|
|
365
382
|
// Categories that don't have root elements will make visibility result incorrect
|
|
366
383
|
// E.g.:
|
|
@@ -369,13 +386,17 @@ export class BaseVisibilityHelper {
|
|
|
369
386
|
// - ChildElementB (CategoryB is hidden) ChildElementB is in always drawn list
|
|
370
387
|
// Result will be "partial" because CategoryB will return hidden visibility, even though all elements are visible
|
|
371
388
|
// TODO fix with: https://github.com/iTwin/viewer-components-react/issues/1100
|
|
372
|
-
|
|
373
|
-
|
|
389
|
+
mergeMap((state) => {
|
|
390
|
+
if (this.#props.viewport.isAlwaysDrawnExclusive && state.totalCount === 0) {
|
|
391
|
+
return EMPTY;
|
|
392
|
+
}
|
|
393
|
+
return of(getVisibilityFromAlwaysAndNeverDrawnElementsImpl({
|
|
374
394
|
...props,
|
|
375
395
|
...state,
|
|
376
396
|
viewport,
|
|
377
|
-
|
|
378
|
-
|
|
397
|
+
defaultStatus: () => props.defaultStatus(state.categoryId),
|
|
398
|
+
}));
|
|
399
|
+
}), defaultIfEmpty(createVisibilityStatus("hidden")), mergeVisibilityStatuses);
|
|
379
400
|
}
|
|
380
401
|
/**
|
|
381
402
|
* Changes visibility status of models.
|
|
@@ -422,19 +443,14 @@ export class BaseVisibilityHelper {
|
|
|
422
443
|
}
|
|
423
444
|
return acc;
|
|
424
445
|
}, new Set())),
|
|
425
|
-
modelAlwaysDrawnElements: this.#alwaysAndNeverDrawnElements.
|
|
426
|
-
}).pipe(mergeMap(
|
|
446
|
+
modelAlwaysDrawnElements: this.#alwaysAndNeverDrawnElements.getAlwaysOrNeverDrawnElements({ modelIds: modelId, setType: "always" }),
|
|
447
|
+
}).pipe(mergeMap(({ allModelCategories, modelAlwaysDrawnElements }) => {
|
|
427
448
|
const alwaysDrawn = this.#props.viewport.alwaysDrawn;
|
|
428
449
|
if (alwaysDrawn && modelAlwaysDrawnElements) {
|
|
429
450
|
viewport.setAlwaysDrawn({ elementIds: setDifference(alwaysDrawn, modelAlwaysDrawnElements) });
|
|
430
451
|
}
|
|
431
|
-
const categoriesToOverride = categoriesToNotOverride
|
|
432
|
-
? setDifference(allModelCategories, getSetFromId64Arg(categoriesToNotOverride))
|
|
433
|
-
: allModelCategories;
|
|
434
|
-
categoriesToOverride.forEach((categoryId) => {
|
|
435
|
-
this.changeCategoryStateInViewportAccordingToModelVisibility(modelId, categoryId, false, false);
|
|
436
|
-
});
|
|
437
452
|
viewport.changeModelDisplay({ modelIds: modelId, display: true });
|
|
453
|
+
return from(Id64.iterable(allModelCategories)).pipe(categoriesToNotOverride ? filter((modelCategory) => !Id64.has(categoriesToNotOverride, modelCategory)) : identity, map((categoryId) => this.changeCategoryStateInViewportAccordingToModelVisibility(modelId, categoryId, false, false)), takeLast(1), defaultIfEmpty(undefined));
|
|
438
454
|
}));
|
|
439
455
|
}
|
|
440
456
|
/** Adds per-model category overrides based on category visibility in category selector. */
|
|
@@ -542,7 +558,7 @@ export class BaseVisibilityHelper {
|
|
|
542
558
|
return this.queueElementsVisibilityChange(elementIds, on, isDisplayedByDefault);
|
|
543
559
|
}),
|
|
544
560
|
// Change visibility of elements that are models
|
|
545
|
-
from(Id64.iterable(elementIds)).pipe(mergeMap((elementId) =>
|
|
561
|
+
from(Id64.iterable(elementIds)).pipe(releaseMainThreadOnItemsCount(100), mergeMap((elementId) => this.#props.baseIdsCache.hasSubModel(elementId).pipe(mergeMap((isSubModel) => {
|
|
546
562
|
if (isSubModel) {
|
|
547
563
|
return this.changeModelsVisibilityStatus({ modelIds: elementId, on });
|
|
548
564
|
}
|