@itwin/tree-widget-react 3.16.1 → 3.17.1
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 +24 -2
- package/lib/cjs/tree-widget-react/components/SelectableTree.js.map +1 -1
- package/lib/cjs/tree-widget-react/components/TreeSelector.js.map +1 -1
- package/lib/cjs/tree-widget-react/components/TreeWidgetUiItemsProvider.js +1 -1
- package/lib/cjs/tree-widget-react/components/TreeWidgetUiItemsProvider.js.map +1 -1
- package/lib/cjs/tree-widget-react/components/tree-header/TreeHeader.js.map +1 -1
- package/lib/cjs/tree-widget-react/components/tree-header/TreeWithHeader.js.map +1 -1
- package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTree.d.ts +2 -2
- package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTree.js +2 -1
- package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTree.js.map +1 -1
- package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTreeButtons.js.map +1 -1
- package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTreeComponent.d.ts +1 -1
- package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTreeComponent.js.map +1 -1
- package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.d.ts +13 -0
- package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js +92 -74
- package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js.map +1 -1
- package/lib/cjs/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.d.ts +3 -1
- package/lib/cjs/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.js +21 -8
- package/lib/cjs/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.js.map +1 -1
- package/lib/cjs/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.d.ts +21 -9
- package/lib/cjs/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js +300 -251
- package/lib/cjs/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js.map +1 -1
- package/lib/cjs/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.d.ts +2 -0
- package/lib/cjs/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.js +66 -107
- package/lib/cjs/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.js.map +1 -1
- package/lib/cjs/tree-widget-react/components/trees/common/CategoriesVisibilityUtils.js +22 -12
- package/lib/cjs/tree-widget-react/components/trees/common/CategoriesVisibilityUtils.js.map +1 -1
- package/lib/cjs/tree-widget-react/components/trees/common/UseActiveViewport.js.map +1 -1
- package/lib/cjs/tree-widget-react/components/trees/common/UseHierarchyVisibility.js.map +1 -1
- package/lib/cjs/tree-widget-react/components/trees/common/components/ProgressOverlay.js.map +1 -1
- package/lib/cjs/tree-widget-react/components/trees/common/components/Tree.d.ts +2 -2
- package/lib/cjs/tree-widget-react/components/trees/common/components/Tree.js.map +1 -1
- package/lib/cjs/tree-widget-react/components/trees/common/components/TreeNodeCheckbox.d.ts +1 -1
- package/lib/cjs/tree-widget-react/components/trees/common/components/TreeNodeCheckbox.js.map +1 -1
- package/lib/cjs/tree-widget-react/components/trees/common/components/TreeRenderer.d.ts +1 -1
- package/lib/cjs/tree-widget-react/components/trees/common/components/TreeRenderer.js +2 -2
- package/lib/cjs/tree-widget-react/components/trees/common/components/TreeRenderer.js.map +1 -1
- package/lib/cjs/tree-widget-react/components/trees/common/components/VisibilityTree.d.ts +3 -3
- package/lib/cjs/tree-widget-react/components/trees/common/components/VisibilityTree.js.map +1 -1
- package/lib/cjs/tree-widget-react/components/trees/common/components/VisibilityTreeRenderer.d.ts +1 -1
- package/lib/cjs/tree-widget-react/components/trees/common/components/VisibilityTreeRenderer.js.map +1 -1
- package/lib/cjs/tree-widget-react/components/trees/common/internal/Utils.d.ts +25 -0
- package/lib/cjs/tree-widget-react/components/trees/common/internal/Utils.js +83 -0
- package/lib/cjs/tree-widget-react/components/trees/common/internal/Utils.js.map +1 -0
- package/lib/cjs/tree-widget-react/components/trees/models-tree/ModelsTree.d.ts +1 -1
- package/lib/cjs/tree-widget-react/components/trees/models-tree/ModelsTree.js.map +1 -1
- package/lib/cjs/tree-widget-react/components/trees/models-tree/ModelsTreeButtons.js.map +1 -1
- package/lib/cjs/tree-widget-react/components/trees/models-tree/ModelsTreeComponent.js.map +1 -1
- package/lib/cjs/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.d.ts +1 -0
- package/lib/cjs/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js +86 -28
- package/lib/cjs/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js.map +1 -1
- package/lib/cjs/tree-widget-react/components/trees/models-tree/UseModelsTree.js +2 -1
- package/lib/cjs/tree-widget-react/components/trees/models-tree/UseModelsTree.js.map +1 -1
- package/lib/cjs/tree-widget-react/components/trees/models-tree/Utils.d.ts +5 -6
- package/lib/cjs/tree-widget-react/components/trees/models-tree/Utils.js +5 -17
- package/lib/cjs/tree-widget-react/components/trees/models-tree/Utils.js.map +1 -1
- package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/AlwaysAndNeverDrawnElementInfo.js +5 -4
- package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/AlwaysAndNeverDrawnElementInfo.js.map +1 -1
- package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/FilteredTree.d.ts +7 -1
- package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/FilteredTree.js +52 -0
- package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/FilteredTree.js.map +1 -1
- package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.d.ts +28 -12
- package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js +382 -278
- package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js.map +1 -1
- package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeNode.d.ts +1 -1
- package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeNode.js.map +1 -1
- package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js +272 -139
- package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js.map +1 -1
- package/lib/cjs/tree-widget-react-internal.d.ts +2 -1
- package/lib/cjs/tree-widget-react-internal.js +4 -1
- package/lib/cjs/tree-widget-react-internal.js.map +1 -1
- package/lib/esm/tree-widget-react/components/SelectableTree.js.map +1 -1
- package/lib/esm/tree-widget-react/components/TreeSelector.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/TreeHeader.js.map +1 -1
- package/lib/esm/tree-widget-react/components/tree-header/TreeWithHeader.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTree.d.ts +2 -2
- package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTree.js +2 -1
- 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.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.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.d.ts +13 -0
- package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js +92 -74
- 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.d.ts +3 -1
- package/lib/esm/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.js +22 -9
- 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 +21 -9
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js +301 -252
- 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/CategoriesVisibilityHandler.d.ts +2 -0
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.js +67 -108
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/CategoriesVisibilityUtils.js +23 -13
- package/lib/esm/tree-widget-react/components/trees/common/CategoriesVisibilityUtils.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/UseActiveViewport.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/components/ProgressOverlay.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/components/Tree.d.ts +2 -2
- 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/TreeNodeCheckbox.d.ts +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/components/TreeNodeCheckbox.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/components/TreeRenderer.d.ts +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/components/TreeRenderer.js +2 -2
- package/lib/esm/tree-widget-react/components/trees/common/components/TreeRenderer.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/components/VisibilityTree.d.ts +3 -3
- package/lib/esm/tree-widget-react/components/trees/common/components/VisibilityTree.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/components/VisibilityTreeRenderer.d.ts +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/components/VisibilityTreeRenderer.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/internal/Utils.d.ts +25 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/Utils.js +74 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/Utils.js.map +1 -0
- package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTree.d.ts +1 -1
- 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.map +1 -1
- 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 +1 -0
- package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js +83 -25
- 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 +2 -1
- 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/Utils.d.ts +5 -6
- package/lib/esm/tree-widget-react/components/trees/models-tree/Utils.js +4 -16
- package/lib/esm/tree-widget-react/components/trees/models-tree/Utils.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/AlwaysAndNeverDrawnElementInfo.js +4 -3
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/AlwaysAndNeverDrawnElementInfo.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/FilteredTree.d.ts +7 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/FilteredTree.js +52 -0
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/FilteredTree.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.d.ts +28 -12
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js +382 -278
- 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/ModelsTreeVisibilityHandler.js +257 -124
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.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/package.json +1 -1
|
@@ -7,10 +7,11 @@ import { assert, Id64 } from "@itwin/core-bentley";
|
|
|
7
7
|
import { PerModelCategoryVisibility } from "@itwin/core-frontend";
|
|
8
8
|
import { HierarchyNode, HierarchyNodeKey } from "@itwin/presentation-hierarchies";
|
|
9
9
|
import { enableCategoryDisplay, loadCategoriesFromViewport } from "../../common/CategoriesVisibilityUtils.js";
|
|
10
|
-
import {
|
|
10
|
+
import { getTooltipOptions, mergeVisibilityStatuses, releaseMainThreadOnItemsCount, setDifference, setIntersection } from "../../common/internal/Utils.js";
|
|
11
|
+
import { toVoidPromise } from "../../common/Rxjs.js";
|
|
11
12
|
import { createVisibilityStatus } from "../../common/Tooltip.js";
|
|
12
13
|
import { createVisibilityHandlerResult } from "../../common/UseHierarchyVisibility.js";
|
|
13
|
-
import { getIdsFromChildrenTree
|
|
14
|
+
import { getIdsFromChildrenTree } from "../Utils.js";
|
|
14
15
|
import { AlwaysAndNeverDrawnElementInfo } from "./AlwaysAndNeverDrawnElementInfo.js";
|
|
15
16
|
import { createFilteredTree, parseCategoryKey } from "./FilteredTree.js";
|
|
16
17
|
import { ModelsTreeNode } from "./ModelsTreeNode.js";
|
|
@@ -88,7 +89,9 @@ class ModelsTreeVisibilityHandlerImpl {
|
|
|
88
89
|
if (!HierarchyNode.isInstancesNode(node)) {
|
|
89
90
|
return of(createVisibilityStatus("disabled"));
|
|
90
91
|
}
|
|
91
|
-
|
|
92
|
+
// Only call getFilteredNodeVisibility when node is not a filter target, is not a child of filter target and has filtered children.
|
|
93
|
+
// Otherwise, it can be handled normally.
|
|
94
|
+
if (node.filtering?.filteredChildrenIdentifierPaths?.length && !node.filtering.isFilterTarget && !node.filtering.hasFilterTargetAncestor) {
|
|
92
95
|
return this.getFilteredNodeVisibility({ node });
|
|
93
96
|
}
|
|
94
97
|
if (ModelsTreeNode.isSubjectNode(node)) {
|
|
@@ -109,13 +112,18 @@ class ModelsTreeVisibilityHandlerImpl {
|
|
|
109
112
|
});
|
|
110
113
|
}
|
|
111
114
|
const categoryId = ModelsTreeNode.getCategoryId(node);
|
|
115
|
+
const rootCategoryIds = getRootCategoryIds({ parentKeys: node.parentKeys, modelId });
|
|
116
|
+
assert(rootCategoryIds !== undefined);
|
|
112
117
|
if (!categoryId) {
|
|
113
118
|
return of(createVisibilityStatus("disabled"));
|
|
114
119
|
}
|
|
115
120
|
return this.getElementDisplayStatus({
|
|
116
121
|
elementIds: node.key.instanceKeys.map(({ id }) => id),
|
|
122
|
+
parentKeys: node.parentKeys,
|
|
123
|
+
rootCategoryIds,
|
|
117
124
|
modelId,
|
|
118
125
|
categoryId,
|
|
126
|
+
totalChildrenCount: node.extendedData?.childrenCount ?? 0,
|
|
119
127
|
});
|
|
120
128
|
}
|
|
121
129
|
getFilteredNodeVisibility(props) {
|
|
@@ -135,14 +143,53 @@ class ModelsTreeVisibilityHandlerImpl {
|
|
|
135
143
|
})));
|
|
136
144
|
}
|
|
137
145
|
if (elements?.size) {
|
|
138
|
-
|
|
146
|
+
const filterTargetElements = new Array();
|
|
147
|
+
elements.forEach((elementsMap) => elementsMap.forEach(({ isFilterTarget }, elementId) => {
|
|
148
|
+
if (isFilterTarget) {
|
|
149
|
+
filterTargetElements.push(elementId);
|
|
150
|
+
}
|
|
151
|
+
}));
|
|
152
|
+
let childrenCountMapObs;
|
|
153
|
+
if (HierarchyNode.isClassGroupingNode(props.node)) {
|
|
154
|
+
const groupingNodesFilterTargets = props.node.extendedData?.filterTargets;
|
|
155
|
+
const nestedFilterTargetElements = filterTargetElements.filter((filterTarget) => !groupingNodesFilterTargets?.has(filterTarget));
|
|
156
|
+
// Only need to request children count for indirect children filter targets.
|
|
157
|
+
// Direct children filter targets already have children count stored in grouping nodes extended data.
|
|
158
|
+
childrenCountMapObs = this.#idsCache.getAllChildrenCount({ elementIds: nestedFilterTargetElements });
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
childrenCountMapObs = this.#idsCache.getAllChildrenCount({ elementIds: filterTargetElements });
|
|
162
|
+
}
|
|
163
|
+
observables.push(childrenCountMapObs.pipe(
|
|
164
|
+
// Get children count for all filter target elements.
|
|
165
|
+
map((elementCountMap) => {
|
|
166
|
+
if (!HierarchyNode.isClassGroupingNode(props.node) || !props.node.extendedData?.filterTargets) {
|
|
167
|
+
return elementCountMap;
|
|
168
|
+
}
|
|
169
|
+
// Need to add children count (stored in grouping nodes' extended data) of direct children filter targets.
|
|
170
|
+
const groupingNodesFilterTargets = props.node.extendedData.filterTargets;
|
|
171
|
+
groupingNodesFilterTargets.forEach((value, key) => elementCountMap.set(key, value.childrenCount));
|
|
172
|
+
return elementCountMap;
|
|
173
|
+
}), mergeMap((elementCountMap) => from(elements).pipe(releaseMainThreadOnItemsCount(50), mergeMap(([categoryKey, elementsMap]) => {
|
|
139
174
|
const { modelId, categoryId } = parseCategoryKey(categoryKey);
|
|
175
|
+
let totalChildrenCount = 0;
|
|
176
|
+
elementsMap.forEach((_, elementId) => {
|
|
177
|
+
const childCount = elementCountMap.get(elementId);
|
|
178
|
+
if (childCount) {
|
|
179
|
+
totalChildrenCount += childCount;
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
const parentElementIdsPath = getParentElementsIdsPath({ parentKeys: props.node.parentKeys, modelId });
|
|
183
|
+
const rootCategoryIds = getRootCategoryIds({ parentKeys: props.node.parentKeys, modelId });
|
|
140
184
|
return this.getElementsDisplayStatus({
|
|
141
185
|
elementIds: [...elementsMap.keys()],
|
|
186
|
+
rootCategoryIds: rootCategoryIds ?? categoryId,
|
|
187
|
+
parentElementIdsPath,
|
|
142
188
|
modelId,
|
|
143
189
|
categoryId,
|
|
190
|
+
childrenCount: totalChildrenCount,
|
|
144
191
|
});
|
|
145
|
-
})));
|
|
192
|
+
})))));
|
|
146
193
|
}
|
|
147
194
|
return merge(...observables);
|
|
148
195
|
}), mergeVisibilityStatuses());
|
|
@@ -152,7 +199,7 @@ class ModelsTreeVisibilityHandlerImpl {
|
|
|
152
199
|
if (!this.#props.viewport.view.isSpatialView()) {
|
|
153
200
|
return of(createVisibilityStatus("disabled", getTooltipOptions("modelsTree.subject.nonSpatialView", ignoreTooltip)));
|
|
154
201
|
}
|
|
155
|
-
return
|
|
202
|
+
return this.#idsCache.getSubjectModelIds(subjectIds).pipe(mergeMap((modelIds) => this.getModelVisibilityStatus({ modelIds, ignoreTooltip: true })), mergeVisibilityStatuses({
|
|
156
203
|
visible: "modelsTree.subject.allModelsVisible",
|
|
157
204
|
hidden: "modelsTree.subject.allModelsHidden",
|
|
158
205
|
partial: "modelsTree.subject.someModelsHidden",
|
|
@@ -168,14 +215,18 @@ class ModelsTreeVisibilityHandlerImpl {
|
|
|
168
215
|
}
|
|
169
216
|
return from(Id64.iterable(modelIds)).pipe(distinct(), mergeMap((modelId) => {
|
|
170
217
|
if (!viewport.view.viewsModel(modelId)) {
|
|
171
|
-
return
|
|
218
|
+
return this.#idsCache.getModelCategories(modelId).pipe(mergeMap((categoryIds) => this.#idsCache.getCategoriesModeledElements(modelId, categoryIds)), this.getSubModeledElementsVisibilityStatus({
|
|
172
219
|
ignoreTooltips: ignoreTooltip,
|
|
173
220
|
haveSubModel: "yes",
|
|
174
221
|
tooltips: { visible: undefined, hidden: "modelsTree.model.hiddenThroughModelSelector", partial: "modelsTree.model.someSubModelsVisible" },
|
|
175
222
|
parentNodeVisibilityStatus: createVisibilityStatus("hidden"),
|
|
176
223
|
}));
|
|
177
224
|
}
|
|
178
|
-
return
|
|
225
|
+
return this.#idsCache.getModelCategories(modelId).pipe(mergeMap((categoryIds) => {
|
|
226
|
+
return categoryIds.length === 0
|
|
227
|
+
? of(createVisibilityStatus("visible"))
|
|
228
|
+
: this.getCategoryDisplayStatus({ modelId, categoryIds, ignoreTooltip: true });
|
|
229
|
+
}), mergeVisibilityStatuses({
|
|
179
230
|
visible: "modelsTree.model.allCategoriesVisible",
|
|
180
231
|
partial: "modelsTree.model.someCategoriesHidden",
|
|
181
232
|
hidden: "modelsTree.model.allCategoriesHidden",
|
|
@@ -221,7 +272,7 @@ class ModelsTreeVisibilityHandlerImpl {
|
|
|
221
272
|
getCategoryDisplayStatus({ ignoreTooltip, ...props }) {
|
|
222
273
|
const result = defer(() => {
|
|
223
274
|
if (!this.#props.viewport.view.viewsModel(props.modelId)) {
|
|
224
|
-
return
|
|
275
|
+
return this.#idsCache.getCategoriesModeledElements(props.modelId, props.categoryIds).pipe(this.getSubModeledElementsVisibilityStatus({
|
|
225
276
|
ignoreTooltips: ignoreTooltip,
|
|
226
277
|
parentNodeVisibilityStatus: createVisibilityStatus("hidden"),
|
|
227
278
|
tooltips: {
|
|
@@ -245,7 +296,7 @@ class ModelsTreeVisibilityHandlerImpl {
|
|
|
245
296
|
: this.getDefaultCategoryVisibilityStatus({ modelId: props.modelId, categoryIds: props.categoryIds }),
|
|
246
297
|
ignoreTooltip,
|
|
247
298
|
}).pipe(mergeMap((visibilityStatusAlwaysAndNeverDraw) => {
|
|
248
|
-
return
|
|
299
|
+
return this.#idsCache.getCategoriesModeledElements(props.modelId, props.categoryIds).pipe(this.getSubModeledElementsVisibilityStatus({
|
|
249
300
|
tooltips: {
|
|
250
301
|
visible: undefined,
|
|
251
302
|
hidden: "modelsTree.category.allElementsAndSubModelsHidden",
|
|
@@ -260,25 +311,33 @@ class ModelsTreeVisibilityHandlerImpl {
|
|
|
260
311
|
return createVisibilityHandlerResult(this, props, result, this.#props.overrides?.getCategoryDisplayStatus);
|
|
261
312
|
}
|
|
262
313
|
getClassGroupingNodeDisplayStatus(node) {
|
|
263
|
-
const { elementIds, modelId, categoryId } = this.getGroupingNodeInfo(node);
|
|
314
|
+
const { elementIds, modelId, categoryId, childrenCount } = this.getGroupingNodeInfo(node);
|
|
315
|
+
const rootCategoryIds = getRootCategoryIds({ parentKeys: node.parentKeys, modelId });
|
|
316
|
+
assert(rootCategoryIds !== undefined);
|
|
264
317
|
const result = this.getElementsDisplayStatus({
|
|
265
318
|
elementIds,
|
|
266
319
|
modelId,
|
|
267
320
|
categoryId,
|
|
321
|
+
rootCategoryIds,
|
|
322
|
+
parentElementIdsPath: getParentElementsIdsPath({ parentKeys: node.parentKeys, modelId }),
|
|
323
|
+
childrenCount: childrenCount ?? 0,
|
|
268
324
|
});
|
|
269
325
|
return createVisibilityHandlerResult(this, { node }, result, this.#props.overrides?.getElementGroupingNodeDisplayStatus);
|
|
270
326
|
}
|
|
271
|
-
getElementDisplayStatus({ elementIds, modelId, categoryId, }) {
|
|
327
|
+
getElementDisplayStatus({ parentKeys, totalChildrenCount, elementIds, modelId, rootCategoryIds, categoryId, }) {
|
|
272
328
|
const result = this.getElementsDisplayStatus({
|
|
329
|
+
rootCategoryIds,
|
|
273
330
|
elementIds,
|
|
274
331
|
modelId,
|
|
275
332
|
categoryId,
|
|
333
|
+
parentElementIdsPath: getParentElementsIdsPath({ parentKeys, modelId }),
|
|
334
|
+
childrenCount: totalChildrenCount,
|
|
276
335
|
});
|
|
277
336
|
return createVisibilityHandlerResult(this, { elementId: elementIds[0], modelId, categoryId }, result, this.#props.overrides?.getElementDisplayStatus);
|
|
278
337
|
}
|
|
279
338
|
getElementsDisplayStatus(props) {
|
|
280
339
|
return defer(() => {
|
|
281
|
-
const { modelId, categoryId, elementIds } = props;
|
|
340
|
+
const { modelId, categoryId, elementIds, parentElementIdsPath, childrenCount, rootCategoryIds } = props;
|
|
282
341
|
if (!this.#props.viewport.view.viewsModel(modelId)) {
|
|
283
342
|
return of(elementIds).pipe(this.getSubModeledElementsVisibilityStatus({
|
|
284
343
|
tooltips: {
|
|
@@ -292,6 +351,10 @@ class ModelsTreeVisibilityHandlerImpl {
|
|
|
292
351
|
}
|
|
293
352
|
return this.getVisibilityFromAlwaysAndNeverDrawnElements({
|
|
294
353
|
elements: elementIds,
|
|
354
|
+
parentElementIdsPath,
|
|
355
|
+
modelIds: modelId,
|
|
356
|
+
rootCategoryIds,
|
|
357
|
+
childrenCount,
|
|
295
358
|
defaultStatus: () => {
|
|
296
359
|
const status = this.getDefaultCategoryVisibilityStatus({ categoryIds: categoryId, modelId, ignoreTooltip: true });
|
|
297
360
|
return createVisibilityStatus(status.state, getTooltipOptions(`modelsTree.groupingNode.${status.state}ThroughCategory`));
|
|
@@ -327,7 +390,9 @@ class ModelsTreeVisibilityHandlerImpl {
|
|
|
327
390
|
if (!HierarchyNode.isInstancesNode(node)) {
|
|
328
391
|
return EMPTY;
|
|
329
392
|
}
|
|
330
|
-
|
|
393
|
+
// Only call changeFilteredNodeVisibility when node is not a filter target, is not a child of filter target and has filtered children.
|
|
394
|
+
// Otherwise, it can be handled normally.
|
|
395
|
+
if (node.filtering?.filteredChildrenIdentifierPaths?.length && !node.filtering.isFilterTarget && !node.filtering.hasFilterTargetAncestor) {
|
|
331
396
|
return this.changeFilteredNodeVisibility({ node, on });
|
|
332
397
|
}
|
|
333
398
|
if (ModelsTreeNode.isSubjectNode(node)) {
|
|
@@ -351,12 +416,18 @@ class ModelsTreeVisibilityHandlerImpl {
|
|
|
351
416
|
if (!categoryId) {
|
|
352
417
|
return EMPTY;
|
|
353
418
|
}
|
|
354
|
-
|
|
355
|
-
|
|
419
|
+
const elementIds = new Set(node.key.instanceKeys.map(({ id }) => id));
|
|
420
|
+
return this.#idsCache.getChildrenTree({ elementIds }).pipe(map((childrenTree) => {
|
|
421
|
+
// Children tree contains provided elementIds, they are at the root of this tree.
|
|
422
|
+
// We want to skip them and only get ids of children.
|
|
423
|
+
return getIdsFromChildrenTree({ tree: childrenTree, predicate: ({ depth }) => depth > 0 });
|
|
424
|
+
}), mergeMap((children) => this.changeElementsState({
|
|
425
|
+
elementIds,
|
|
356
426
|
modelId,
|
|
427
|
+
children: children.size > 0 ? children : undefined,
|
|
357
428
|
categoryId,
|
|
358
429
|
on,
|
|
359
|
-
});
|
|
430
|
+
})));
|
|
360
431
|
});
|
|
361
432
|
if (this.#props.viewport.isAlwaysDrawnExclusive) {
|
|
362
433
|
return concat(this.removeAlwaysDrawnExclusive(), changeObs);
|
|
@@ -365,7 +436,7 @@ class ModelsTreeVisibilityHandlerImpl {
|
|
|
365
436
|
}
|
|
366
437
|
changeFilteredNodeVisibility({ on, ...props }) {
|
|
367
438
|
assert(this.#filteredTree !== undefined);
|
|
368
|
-
return from(this.#filteredTree).pipe(map((filteredTree) => filteredTree.getVisibilityChangeTargets(props.node)), mergeMap(({ subjects,
|
|
439
|
+
return from(this.#filteredTree).pipe(map((filteredTree) => filteredTree.getVisibilityChangeTargets(props.node)), mergeMap(({ subjects, categories, elements, models }) => {
|
|
369
440
|
const observables = new Array();
|
|
370
441
|
if (subjects?.size) {
|
|
371
442
|
observables.push(this.changeSubjectNodeState([...subjects], on));
|
|
@@ -380,16 +451,30 @@ class ModelsTreeVisibilityHandlerImpl {
|
|
|
380
451
|
})));
|
|
381
452
|
}
|
|
382
453
|
if (elements?.size) {
|
|
383
|
-
|
|
454
|
+
const filterTargetElements = new Array();
|
|
455
|
+
const elementsSet = new Set();
|
|
456
|
+
elements.forEach((elementsMap) => elementsMap.forEach(({ isFilterTarget }, elementId) => {
|
|
457
|
+
elementsSet.add(elementId);
|
|
458
|
+
if (isFilterTarget) {
|
|
459
|
+
filterTargetElements.push(elementId);
|
|
460
|
+
}
|
|
461
|
+
}));
|
|
462
|
+
observables.push(this.#idsCache.getChildrenTree({ elementIds: filterTargetElements }).pipe(map((childrenTree) => getIdsFromChildrenTree({ tree: childrenTree })), map((childrenIds) => setDifference(childrenIds, elementsSet)), mergeMap((childElementIds) => from(elements).pipe(mergeMap(([categoryKey, elementsMap]) => {
|
|
384
463
|
const { modelId, categoryId } = parseCategoryKey(categoryKey);
|
|
385
|
-
return this.changeElementsState({
|
|
386
|
-
|
|
464
|
+
return this.changeElementsState({
|
|
465
|
+
modelId,
|
|
466
|
+
categoryId,
|
|
467
|
+
elementIds: new Set([...elementsMap.keys()]),
|
|
468
|
+
on,
|
|
469
|
+
children: childElementIds.size > 0 ? childElementIds : undefined,
|
|
470
|
+
});
|
|
471
|
+
})))));
|
|
387
472
|
}
|
|
388
473
|
return merge(...observables);
|
|
389
474
|
}));
|
|
390
475
|
}
|
|
391
476
|
removeAlwaysDrawnExclusive() {
|
|
392
|
-
return
|
|
477
|
+
return this.#idsCache.getAllCategories().pipe(map((categoryIds) => {
|
|
393
478
|
this.#props.viewport.changeCategoryDisplay(categoryIds, false, false);
|
|
394
479
|
this.#props.viewport.clearNeverDrawn();
|
|
395
480
|
this.#props.viewport.perModelCategoryVisibility.clearOverrides();
|
|
@@ -401,7 +486,7 @@ class ModelsTreeVisibilityHandlerImpl {
|
|
|
401
486
|
if (!this.#props.viewport.view.isSpatialView()) {
|
|
402
487
|
return EMPTY;
|
|
403
488
|
}
|
|
404
|
-
return
|
|
489
|
+
return this.#idsCache.getSubjectModelIds(ids).pipe(mergeMap((modelIds) => this.changeModelState({ ids: modelIds, on })));
|
|
405
490
|
});
|
|
406
491
|
return createVisibilityHandlerResult(this, { ids, on }, result, this.#props.overrides?.changeSubjectNodeState);
|
|
407
492
|
}
|
|
@@ -418,13 +503,13 @@ class ModelsTreeVisibilityHandlerImpl {
|
|
|
418
503
|
const idsObs = from(Id64.iterable(ids));
|
|
419
504
|
if (!on) {
|
|
420
505
|
viewport.changeModelDisplay(ids, false);
|
|
421
|
-
return idsObs.pipe(mergeMap(
|
|
506
|
+
return idsObs.pipe(mergeMap((modelId) => forkJoin({ categoryIds: this.#idsCache.getModelCategories(modelId), modelId: of(modelId) })), mergeMap(({ modelId, categoryIds }) => this.#idsCache.getCategoriesModeledElements(modelId, categoryIds)), mergeMap((modeledElementIds) => this.changeModelState({ ids: modeledElementIds, on })));
|
|
422
507
|
}
|
|
423
508
|
return concat(defer(() => {
|
|
424
509
|
viewport.perModelCategoryVisibility.clearOverrides(ids);
|
|
425
510
|
return from(viewport.addViewedModels(ids));
|
|
426
511
|
}), idsObs.pipe(mergeMap((modelId) => {
|
|
427
|
-
return
|
|
512
|
+
return this.#idsCache.getModelCategories(modelId).pipe(mergeMap((categoryIds) => this.changeCategoryState({ categoryIds, modelId, on: true })));
|
|
428
513
|
})));
|
|
429
514
|
});
|
|
430
515
|
return createVisibilityHandlerResult(this, props, result, this.#props.overrides?.changeModelState);
|
|
@@ -434,15 +519,12 @@ class ModelsTreeVisibilityHandlerImpl {
|
|
|
434
519
|
return forkJoin({
|
|
435
520
|
categories: this.#idsCache.getModelCategories(modelId),
|
|
436
521
|
alwaysDrawnElements: this.getAlwaysOrNeverDrawnElements({ modelIds: modelId, setType: "always" }),
|
|
437
|
-
}).pipe(mergeMap(
|
|
522
|
+
}).pipe(mergeMap(({ categories, alwaysDrawnElements }) => {
|
|
438
523
|
const alwaysDrawn = this.#props.viewport.alwaysDrawn;
|
|
439
524
|
if (alwaysDrawn && alwaysDrawnElements) {
|
|
440
525
|
viewport.setAlwaysDrawn(setDifference(alwaysDrawn, alwaysDrawnElements));
|
|
441
526
|
}
|
|
442
|
-
categories.
|
|
443
|
-
this.changeCategoryStateInViewportAccordingToModelVisibility(modelId, categoryId, false);
|
|
444
|
-
});
|
|
445
|
-
await viewport.addViewedModels(modelId);
|
|
527
|
+
return concat(from(Id64.iterable(categories)).pipe(releaseMainThreadOnItemsCount(300), map((categoryId) => this.changeCategoryStateInViewportAccordingToModelVisibility(modelId, categoryId, false))), defer(async () => viewport.addViewedModels(modelId)));
|
|
446
528
|
}));
|
|
447
529
|
}
|
|
448
530
|
changeCategoryStateInViewportAccordingToModelVisibility(modelId, categoryId, on) {
|
|
@@ -464,24 +546,37 @@ class ModelsTreeVisibilityHandlerImpl {
|
|
|
464
546
|
const result = defer(() => {
|
|
465
547
|
const viewport = this.#props.viewport;
|
|
466
548
|
const { modelId, categoryIds, on } = props;
|
|
467
|
-
return concat(props.on && !viewport.view.viewsModel(modelId) ? this.showModelWithoutAnyCategoriesOrElements(modelId) : EMPTY,
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
}
|
|
471
|
-
return this.clearAlwaysAndNeverDrawnElements(props);
|
|
472
|
-
}), from(this.#idsCache.getCategoriesModeledElements(modelId, categoryIds)).pipe(mergeMap((modeledElementIds) => this.changeModelState({ ids: modeledElementIds, on }))));
|
|
549
|
+
return concat(props.on && !viewport.view.viewsModel(modelId) ? this.showModelWithoutAnyCategoriesOrElements(modelId) : EMPTY, from(Id64.iterable(categoryIds)).pipe(releaseMainThreadOnItemsCount(300), map((categoryId) => this.changeCategoryStateInViewportAccordingToModelVisibility(modelId, categoryId, on))), this.clearAlwaysAndNeverDrawnElements(props), this.#idsCache
|
|
550
|
+
.getCategoriesModeledElements(modelId, categoryIds)
|
|
551
|
+
.pipe(mergeMap((modeledElementIds) => this.changeModelState({ ids: modeledElementIds, on }))));
|
|
473
552
|
});
|
|
474
553
|
return createVisibilityHandlerResult(this, props, result, this.#props.overrides?.changeCategoryState);
|
|
475
554
|
}
|
|
476
555
|
doChangeElementsState(props) {
|
|
477
556
|
return defer(() => {
|
|
478
|
-
const { modelId, categoryId, elementIds, on } = props;
|
|
557
|
+
const { modelId, categoryId, elementIds, on, children } = props;
|
|
479
558
|
const viewport = this.#props.viewport;
|
|
480
559
|
return concat(on && !viewport.view.viewsModel(modelId) ? this.showModelWithoutAnyCategoriesOrElements(modelId) : EMPTY, defer(() => {
|
|
481
560
|
const categoryVisibility = this.getDefaultCategoryVisibilityStatus({ categoryIds: categoryId, modelId, ignoreTooltip: true });
|
|
482
|
-
const
|
|
483
|
-
|
|
484
|
-
|
|
561
|
+
const isCategoryVisible = categoryVisibility.state === "visible";
|
|
562
|
+
// Make sure to add all children to always/never drawn list.
|
|
563
|
+
const isDisplayedByDefault =
|
|
564
|
+
// When category is visible and elements need to be turned off, or when category is hidden and elements need to be turned on,
|
|
565
|
+
// We can set isDisplayedByDefault to isCategoryVisible. This allows to not check if each element is in the elementIds list or not.
|
|
566
|
+
isCategoryVisible === !on
|
|
567
|
+
? () => isCategoryVisible
|
|
568
|
+
: (elementId) => {
|
|
569
|
+
if (elementIds.has(elementId)) {
|
|
570
|
+
return isCategoryVisible;
|
|
571
|
+
}
|
|
572
|
+
return !on;
|
|
573
|
+
};
|
|
574
|
+
const elementsToChange = children ? [...elementIds, ...(typeof children === "string" ? [children] : children)] : elementIds;
|
|
575
|
+
return this.queueElementsVisibilityChange(elementsToChange, on, isDisplayedByDefault);
|
|
576
|
+
}), from(elementIds).pipe(mergeMap((elementId) => forkJoin({
|
|
577
|
+
elementId: of(elementId),
|
|
578
|
+
isSubModel: this.#idsCache.hasSubModel(elementId),
|
|
579
|
+
})), filter(({ isSubModel }) => isSubModel), map(({ elementId }) => elementId), toArray(), mergeMap((subModelIds) => this.changeModelState({ ids: subModelIds, on }))));
|
|
485
580
|
});
|
|
486
581
|
}
|
|
487
582
|
/**
|
|
@@ -489,7 +584,14 @@ class ModelsTreeVisibilityHandlerImpl {
|
|
|
489
584
|
* @see `changeElementState`
|
|
490
585
|
*/
|
|
491
586
|
changeElementGroupingNodeState(node, on) {
|
|
492
|
-
const
|
|
587
|
+
const { modelId, categoryId, elementIds } = this.getGroupingNodeInfo(node);
|
|
588
|
+
const result = this.#idsCache.getChildrenTree({ elementIds }).pipe(map((childrenTree) => getIdsFromChildrenTree({ tree: childrenTree, predicate: ({ depth }) => depth > 0 })), mergeMap((children) => this.doChangeElementsState({
|
|
589
|
+
modelId,
|
|
590
|
+
categoryId,
|
|
591
|
+
elementIds,
|
|
592
|
+
children: children.size > 0 ? children : undefined,
|
|
593
|
+
on,
|
|
594
|
+
})));
|
|
493
595
|
return createVisibilityHandlerResult(this, { node, on }, result, this.#props.overrides?.changeElementGroupingNodeState);
|
|
494
596
|
}
|
|
495
597
|
/**
|
|
@@ -504,7 +606,7 @@ class ModelsTreeVisibilityHandlerImpl {
|
|
|
504
606
|
const finishedSubject = new Subject();
|
|
505
607
|
// observable to track if visibility change is finished/cancelled
|
|
506
608
|
const changeFinished = finishedSubject.pipe(startWith(false), shareReplay(1), filter((finished) => finished));
|
|
507
|
-
const changeObservable = from(elementIds).pipe(
|
|
609
|
+
const changeObservable = from(Id64.iterable(elementIds)).pipe(
|
|
508
610
|
// check if visibility change is not finished (cancelled) due to change overall change request being cancelled
|
|
509
611
|
takeUntil(changeFinished), this.changeElementStateNoChildrenOperator({ on, isDisplayedByDefault: visibleByDefault }), tap({
|
|
510
612
|
next: () => {
|
|
@@ -535,7 +637,7 @@ class ModelsTreeVisibilityHandlerImpl {
|
|
|
535
637
|
const wasRemoved = acc.neverDrawn.delete(elementId);
|
|
536
638
|
acc.changedNeverDrawn ||= wasRemoved;
|
|
537
639
|
// If exclusive mode is enabled, we must add the element to the always drawn list.
|
|
538
|
-
if ((!isDisplayedByDefault || isAlwaysDrawnExclusive) && !acc.alwaysDrawn.has(elementId)) {
|
|
640
|
+
if ((!isDisplayedByDefault(elementId) || isAlwaysDrawnExclusive) && !acc.alwaysDrawn.has(elementId)) {
|
|
539
641
|
acc.alwaysDrawn.add(elementId);
|
|
540
642
|
acc.changedAlwaysDrawn = true;
|
|
541
643
|
}
|
|
@@ -544,7 +646,7 @@ class ModelsTreeVisibilityHandlerImpl {
|
|
|
544
646
|
const wasRemoved = acc.alwaysDrawn.delete(elementId);
|
|
545
647
|
acc.changedAlwaysDrawn ||= wasRemoved;
|
|
546
648
|
// If exclusive mode is not enabled, we have to add the element to the never drawn list.
|
|
547
|
-
if (isDisplayedByDefault && !isAlwaysDrawnExclusive && !acc.neverDrawn.has(elementId)) {
|
|
649
|
+
if (isDisplayedByDefault(elementId) && !isAlwaysDrawnExclusive && !acc.neverDrawn.has(elementId)) {
|
|
548
650
|
acc.neverDrawn.add(elementId);
|
|
549
651
|
acc.changedNeverDrawn = true;
|
|
550
652
|
}
|
|
@@ -566,20 +668,22 @@ class ModelsTreeVisibilityHandlerImpl {
|
|
|
566
668
|
if (totalCount === 0) {
|
|
567
669
|
return props.defaultStatus();
|
|
568
670
|
}
|
|
569
|
-
|
|
671
|
+
const neverDrawnSize = neverDrawn ? Id64.sizeOf(neverDrawn) : undefined;
|
|
672
|
+
const alwaysDrawnSize = alwaysDrawn ? Id64.sizeOf(alwaysDrawn) : undefined;
|
|
673
|
+
if (neverDrawnSize === totalCount) {
|
|
570
674
|
return createVisibilityStatus("hidden", getTooltipOptions(props.tooltips.allElementsInNeverDrawnList, ignoreTooltip));
|
|
571
675
|
}
|
|
572
|
-
if (
|
|
676
|
+
if (alwaysDrawnSize === totalCount) {
|
|
573
677
|
return createVisibilityStatus("visible", getTooltipOptions(props.tooltips.allElementsInAlwaysDrawnList, ignoreTooltip));
|
|
574
678
|
}
|
|
575
679
|
const viewport = this.#props.viewport;
|
|
576
680
|
if (viewport.isAlwaysDrawnExclusive && viewport.alwaysDrawn?.size) {
|
|
577
|
-
return
|
|
681
|
+
return alwaysDrawnSize
|
|
578
682
|
? createVisibilityStatus("partial", getTooltipOptions(props.tooltips.elementsInBothAlwaysAndNeverDrawn, ignoreTooltip))
|
|
579
683
|
: createVisibilityStatus("hidden", getTooltipOptions(props.tooltips.noElementsInExclusiveAlwaysDrawnList, ignoreTooltip));
|
|
580
684
|
}
|
|
581
685
|
const status = props.defaultStatus();
|
|
582
|
-
if ((status.state === "visible" &&
|
|
686
|
+
if ((status.state === "visible" && neverDrawnSize) || (status.state === "hidden" && alwaysDrawnSize)) {
|
|
583
687
|
return createVisibilityStatus("partial", getTooltipOptions(undefined, ignoreTooltip));
|
|
584
688
|
}
|
|
585
689
|
return status;
|
|
@@ -595,44 +699,84 @@ class ModelsTreeVisibilityHandlerImpl {
|
|
|
595
699
|
return of(props.defaultStatus());
|
|
596
700
|
}
|
|
597
701
|
if ("elements" in props) {
|
|
598
|
-
|
|
599
|
-
...props,
|
|
600
|
-
alwaysDrawn: viewport.alwaysDrawn?.size ? setIntersection(props.elements, viewport.alwaysDrawn) : undefined,
|
|
601
|
-
neverDrawn: viewport.neverDrawn?.size ? setIntersection(props.elements, viewport.neverDrawn) : undefined,
|
|
602
|
-
totalCount: Id64.sizeOf(props.elements),
|
|
603
|
-
ignoreTooltip,
|
|
604
|
-
}));
|
|
605
|
-
}
|
|
606
|
-
const { modelId, categoryIds } = props.categoryProps;
|
|
607
|
-
return from(Id64.iterable(categoryIds)).pipe(mergeMap((categoryId) => {
|
|
608
|
-
const totalCount = this.#idsCache.getCategoryElementsCount(modelId, categoryId);
|
|
702
|
+
const parentElementIdsPath = [...props.parentElementIdsPath, props.elements];
|
|
609
703
|
return forkJoin({
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
map((
|
|
704
|
+
childAlwaysDrawn: this.getAlwaysOrNeverDrawnElements({
|
|
705
|
+
modelIds: props.modelIds,
|
|
706
|
+
categoryIds: props.rootCategoryIds,
|
|
707
|
+
parentElementIdsPath,
|
|
708
|
+
setType: "always",
|
|
709
|
+
}),
|
|
710
|
+
childNeverDrawn: this.getAlwaysOrNeverDrawnElements({
|
|
711
|
+
modelIds: props.modelIds,
|
|
712
|
+
categoryIds: props.rootCategoryIds,
|
|
713
|
+
parentElementIdsPath,
|
|
714
|
+
setType: "never",
|
|
715
|
+
}),
|
|
716
|
+
}).pipe(map(({ childAlwaysDrawn, childNeverDrawn }) => {
|
|
717
|
+
const alwaysDrawn = new Set([...childAlwaysDrawn, ...(viewport.alwaysDrawn?.size ? setIntersection(props.elements, viewport.alwaysDrawn) : [])]);
|
|
718
|
+
const neverDrawn = new Set([...childNeverDrawn, ...(viewport.neverDrawn?.size ? setIntersection(props.elements, viewport.neverDrawn) : [])]);
|
|
623
719
|
return this.getVisibilityFromAlwaysAndNeverDrawnElementsImpl({
|
|
624
720
|
...props,
|
|
625
|
-
|
|
626
|
-
|
|
721
|
+
alwaysDrawn: alwaysDrawn.size > 0 ? alwaysDrawn : undefined,
|
|
722
|
+
neverDrawn: neverDrawn.size > 0 ? neverDrawn : undefined,
|
|
723
|
+
totalCount: props.childrenCount + Id64.sizeOf(props.elements),
|
|
627
724
|
ignoreTooltip,
|
|
628
725
|
});
|
|
629
726
|
}));
|
|
727
|
+
}
|
|
728
|
+
const { modelId, categoryIds } = props.categoryProps;
|
|
729
|
+
return from(Id64.iterable(categoryIds)).pipe(releaseMainThreadOnItemsCount(100), mergeMap((categoryId) => {
|
|
730
|
+
return forkJoin({
|
|
731
|
+
categoryId: of(categoryId),
|
|
732
|
+
totalCount: this.#idsCache.getCategoryElementsCount(modelId, categoryId),
|
|
733
|
+
alwaysDrawn: this.getAlwaysOrNeverDrawnElements({ modelIds: modelId, categoryIds: categoryId, setType: "always" }),
|
|
734
|
+
neverDrawn: this.getAlwaysOrNeverDrawnElements({ modelIds: modelId, categoryIds: categoryId, setType: "never" }),
|
|
735
|
+
});
|
|
736
|
+
}),
|
|
737
|
+
// There is a known bug:
|
|
738
|
+
// Categories that don't have root elements will make visibility result incorrect
|
|
739
|
+
// E.g.:
|
|
740
|
+
// - CategoryA
|
|
741
|
+
// - ElementA (CategoryA is visible)
|
|
742
|
+
// - ChildElementB (CategoryB is hidden) ChildElementB is in always drawn list
|
|
743
|
+
// Result will be "partial" because CategoryB will return hidden visibility, even though all elements are visible
|
|
744
|
+
// TODO fix with: https://github.com/iTwin/viewer-components-react/issues/1100
|
|
745
|
+
map((state) => {
|
|
746
|
+
return this.getVisibilityFromAlwaysAndNeverDrawnElementsImpl({
|
|
747
|
+
...props,
|
|
748
|
+
...state,
|
|
749
|
+
defaultStatus: () => props.defaultStatus(state.categoryId),
|
|
750
|
+
ignoreTooltip,
|
|
751
|
+
});
|
|
630
752
|
}), mergeVisibilityStatuses());
|
|
631
753
|
}
|
|
632
754
|
getAlwaysOrNeverDrawnElements(props) {
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
755
|
+
if (!this.#filteredTree) {
|
|
756
|
+
return this.#alwaysAndNeverDrawnElements
|
|
757
|
+
.getElementsTree(props)
|
|
758
|
+
.pipe(map((childrenTree) => getIdsFromChildrenTree({ tree: childrenTree, predicate: ({ treeEntry }) => treeEntry.isInAlwaysOrNeverDrawnSet })));
|
|
759
|
+
}
|
|
760
|
+
// When filtered tree is present, children tree retrieved from alwaysAndNeverDrawnElements may include elements that are not present in filtered tree.
|
|
761
|
+
// Need to filter out such elements.
|
|
762
|
+
return forkJoin({
|
|
763
|
+
filteredTree: from(this.#filteredTree),
|
|
764
|
+
childrenTree: this.#alwaysAndNeverDrawnElements.getElementsTree(props),
|
|
765
|
+
}).pipe(map(({ filteredTree, childrenTree }) => {
|
|
766
|
+
const parentIdsPath = [props.modelIds];
|
|
767
|
+
if ("categoryIds" in props) {
|
|
768
|
+
parentIdsPath.push(props.categoryIds);
|
|
769
|
+
if ("parentElementIdsPath" in props) {
|
|
770
|
+
props.parentElementIdsPath.forEach((parentElementIds) => parentIdsPath.push(parentElementIds));
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
// Get all ids that exist in filtered tree.
|
|
774
|
+
const elements = filteredTree.getElementsFromUnfilteredChildrenTree({ parentIdsPath, childrenTree });
|
|
775
|
+
return elements
|
|
776
|
+
? // Need to filter elements that are in always/never drawn set.
|
|
777
|
+
setIntersection(elements, getIdsFromChildrenTree({ tree: childrenTree, predicate: ({ treeEntry }) => treeEntry.isInAlwaysOrNeverDrawnSet }))
|
|
778
|
+
: new Set();
|
|
779
|
+
}));
|
|
636
780
|
}
|
|
637
781
|
clearAlwaysAndNeverDrawnElements(props) {
|
|
638
782
|
return forkJoin({
|
|
@@ -653,7 +797,9 @@ class ModelsTreeVisibilityHandlerImpl {
|
|
|
653
797
|
const categoryId = ModelsTreeNode.getCategoryId(node);
|
|
654
798
|
assert(!!modelId && !!categoryId);
|
|
655
799
|
const elementIds = new Set(node.groupedInstanceKeys.map((key) => key.id));
|
|
656
|
-
|
|
800
|
+
const childrenCount = node.extendedData?.childrenCount;
|
|
801
|
+
const isFiltered = node.extendedData?.isFiltered;
|
|
802
|
+
return { modelId, categoryId, elementIds, childrenCount, isFiltered };
|
|
657
803
|
}
|
|
658
804
|
getSubModeledElementsVisibilityStatus({ parentNodeVisibilityStatus, haveSubModel, tooltips, ignoreTooltips, }) {
|
|
659
805
|
return (obs) => {
|
|
@@ -663,58 +809,21 @@ class ModelsTreeVisibilityHandlerImpl {
|
|
|
663
809
|
if (haveSubModel === "yes") {
|
|
664
810
|
return of(modeledElementIds);
|
|
665
811
|
}
|
|
666
|
-
return from(Id64.iterable(modeledElementIds)).pipe(
|
|
812
|
+
return from(Id64.iterable(modeledElementIds)).pipe(releaseMainThreadOnItemsCount(100), mergeMap((elementId) => forkJoin({
|
|
813
|
+
hasSubModel: this.#idsCache.hasSubModel(elementId),
|
|
814
|
+
elementId: of(elementId),
|
|
815
|
+
})), filter(({ hasSubModel }) => hasSubModel), map(({ elementId }) => elementId), toArray());
|
|
667
816
|
}),
|
|
668
817
|
// combine visibility status of sub-models with visibility status of parent node
|
|
669
818
|
mergeMap((modeledElementIds) => {
|
|
670
819
|
if (Id64.sizeOf(modeledElementIds) === 0) {
|
|
671
820
|
return of(parentNodeVisibilityStatus);
|
|
672
821
|
}
|
|
673
|
-
return this.getModelVisibilityStatus({ modelIds: modeledElementIds }).pipe(startWith(parentNodeVisibilityStatus), mergeVisibilityStatuses(tooltips, ignoreTooltips));
|
|
822
|
+
return this.getModelVisibilityStatus({ modelIds: typeof modeledElementIds === "string" ? [modeledElementIds] : modeledElementIds }).pipe(startWith(parentNodeVisibilityStatus), mergeVisibilityStatuses(tooltips, ignoreTooltips));
|
|
674
823
|
}));
|
|
675
824
|
};
|
|
676
825
|
}
|
|
677
826
|
}
|
|
678
|
-
function mergeVisibilities(obs) {
|
|
679
|
-
return obs.pipe(reduceWhile((x) => x.allVisible || x.allHidden, (acc, val) => {
|
|
680
|
-
acc.allVisible &&= val === "visible";
|
|
681
|
-
acc.allHidden &&= val === "hidden";
|
|
682
|
-
return acc;
|
|
683
|
-
}, { allVisible: true, allHidden: true }), map((x) => {
|
|
684
|
-
if (!x) {
|
|
685
|
-
return "empty";
|
|
686
|
-
}
|
|
687
|
-
return x.allVisible ? "visible" : x.allHidden ? "hidden" : "partial";
|
|
688
|
-
}));
|
|
689
|
-
}
|
|
690
|
-
function mergeVisibilityStatuses(tooltipMap, ignoreTooltip) {
|
|
691
|
-
return (obs) => {
|
|
692
|
-
return obs.pipe(map((visibilityStatus) => visibilityStatus.state), mergeVisibilities, map((visibility) => {
|
|
693
|
-
if (visibility === "empty") {
|
|
694
|
-
visibility = "visible";
|
|
695
|
-
}
|
|
696
|
-
return createVisibilityStatus(visibility, getTooltipOptions(tooltipMap?.[visibility], ignoreTooltip));
|
|
697
|
-
}));
|
|
698
|
-
};
|
|
699
|
-
}
|
|
700
|
-
function setDifference(lhs, rhs) {
|
|
701
|
-
const result = new Set();
|
|
702
|
-
for (const x of lhs) {
|
|
703
|
-
if (!rhs.has(x)) {
|
|
704
|
-
result.add(x);
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
return result;
|
|
708
|
-
}
|
|
709
|
-
function setIntersection(lhs, rhs) {
|
|
710
|
-
const result = new Set();
|
|
711
|
-
for (const x of lhs) {
|
|
712
|
-
if (rhs.has(x)) {
|
|
713
|
-
result.add(x);
|
|
714
|
-
}
|
|
715
|
-
}
|
|
716
|
-
return result;
|
|
717
|
-
}
|
|
718
827
|
/**
|
|
719
828
|
* Enables display of all given models. Also enables display of all categories and clears always and
|
|
720
829
|
* never drawn lists in the viewport.
|
|
@@ -781,9 +890,33 @@ export async function toggleModels(models, enable, viewport) {
|
|
|
781
890
|
export function areAllModelsVisible(models, viewport) {
|
|
782
891
|
return models.length !== 0 ? models.every((id) => viewport.viewsModel(id)) : false;
|
|
783
892
|
}
|
|
784
|
-
function
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
893
|
+
function getParentElementsIdsPath(props) {
|
|
894
|
+
const parentElementIdsPath = new Array();
|
|
895
|
+
const modelIndex = props.parentKeys.findIndex((parentKey) => HierarchyNodeKey.isInstances(parentKey) && parentKey.instanceKeys.some((instanceKey) => instanceKey.id === props.modelId));
|
|
896
|
+
if (modelIndex === -1) {
|
|
897
|
+
return parentElementIdsPath;
|
|
898
|
+
}
|
|
899
|
+
// Hierarchy is model -> category -> root elements.
|
|
900
|
+
// Root elements index is 2 more than models'.
|
|
901
|
+
const firstParentIndex = modelIndex + 2;
|
|
902
|
+
for (let i = firstParentIndex; i < props.parentKeys.length; ++i) {
|
|
903
|
+
const parentKey = props.parentKeys[i];
|
|
904
|
+
if (!HierarchyNodeKey.isInstances(parentKey)) {
|
|
905
|
+
continue;
|
|
906
|
+
}
|
|
907
|
+
parentElementIdsPath.push(parentKey.instanceKeys.map(({ id }) => id));
|
|
908
|
+
}
|
|
909
|
+
return parentElementIdsPath;
|
|
910
|
+
}
|
|
911
|
+
function getRootCategoryIds(props) {
|
|
912
|
+
const modelIndex = props.parentKeys.findIndex((parentKey) => HierarchyNodeKey.isInstances(parentKey) && parentKey.instanceKeys.some((instanceKey) => instanceKey.id === props.modelId));
|
|
913
|
+
if (modelIndex === -1 || modelIndex + 1 === props.parentKeys.length) {
|
|
914
|
+
return undefined;
|
|
915
|
+
}
|
|
916
|
+
const rootCategoryKeys = props.parentKeys[modelIndex + 1];
|
|
917
|
+
if (!HierarchyNodeKey.isInstances(rootCategoryKeys)) {
|
|
918
|
+
return undefined;
|
|
919
|
+
}
|
|
920
|
+
return rootCategoryKeys.instanceKeys.map(({ id }) => id);
|
|
788
921
|
}
|
|
789
922
|
//# sourceMappingURL=ModelsTreeVisibilityHandler.js.map
|