@itwin/tree-widget-react 3.0.2 → 3.1.0
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 +25 -2
- package/lib/cjs/components/tree-header/TreeHeader.js +1 -1
- package/lib/cjs/components/tree-header/TreeHeader.js.map +1 -1
- package/lib/cjs/components/trees/categories-tree/CategoriesTreeButtons.js +3 -3
- package/lib/cjs/components/trees/categories-tree/CategoriesTreeButtons.js.map +1 -1
- package/lib/cjs/components/trees/categories-tree/CategoriesVisibilityHandler.js +2 -1
- package/lib/cjs/components/trees/categories-tree/CategoriesVisibilityHandler.js.map +1 -1
- package/lib/cjs/components/trees/{models-tree/internal → common}/Tooltip.d.ts +7 -3
- package/lib/cjs/components/trees/{models-tree/internal → common}/Tooltip.js +5 -5
- package/lib/cjs/components/trees/common/Tooltip.js.map +1 -0
- package/lib/cjs/components/trees/common/UseActiveViewport.js.map +1 -1
- package/lib/cjs/components/trees/common/UseHierarchyVisibility.js +6 -3
- package/lib/cjs/components/trees/common/UseHierarchyVisibility.js.map +1 -1
- package/lib/cjs/components/trees/common/Utils.js +1 -1
- package/lib/cjs/components/trees/common/Utils.js.map +1 -1
- package/lib/cjs/components/trees/common/components/TreeNodeCheckbox.js +5 -5
- package/lib/cjs/components/trees/common/components/TreeNodeCheckbox.js.map +1 -1
- package/lib/cjs/components/trees/common/components/TreeRenderer.d.ts +1 -1
- package/lib/cjs/components/trees/common/components/TreeRenderer.js +4 -3
- package/lib/cjs/components/trees/common/components/TreeRenderer.js.map +1 -1
- package/lib/cjs/components/trees/common/components/TreeRenderer.scss +0 -6
- package/lib/cjs/components/trees/models-tree/ModelsTreeButtons.js +13 -13
- package/lib/cjs/components/trees/models-tree/ModelsTreeButtons.js.map +1 -1
- package/lib/cjs/components/trees/models-tree/ModelsTreeComponent.js.map +1 -1
- package/lib/cjs/components/trees/models-tree/ModelsTreeDefinition.js +1 -1
- package/lib/cjs/components/trees/models-tree/ModelsTreeDefinition.js.map +1 -1
- package/lib/cjs/components/trees/models-tree/UseModelsTree.d.ts +1 -1
- package/lib/cjs/components/trees/models-tree/UseModelsTree.js +23 -12
- package/lib/cjs/components/trees/models-tree/UseModelsTree.js.map +1 -1
- package/lib/cjs/components/trees/models-tree/internal/AlwaysAndNeverDrawnElementInfo.d.ts +5 -0
- package/lib/cjs/components/trees/models-tree/internal/AlwaysAndNeverDrawnElementInfo.js +28 -7
- package/lib/cjs/components/trees/models-tree/internal/AlwaysAndNeverDrawnElementInfo.js.map +1 -1
- package/lib/cjs/components/trees/models-tree/internal/FilteredTree.d.ts +25 -0
- package/lib/cjs/components/trees/models-tree/internal/FilteredTree.js +178 -0
- package/lib/cjs/components/trees/models-tree/internal/FilteredTree.js.map +1 -0
- package/lib/cjs/components/trees/models-tree/internal/ModelsTreeIdsCache.d.ts +2 -1
- package/lib/cjs/components/trees/models-tree/internal/ModelsTreeIdsCache.js +55 -23
- package/lib/cjs/components/trees/models-tree/internal/ModelsTreeIdsCache.js.map +1 -1
- package/lib/cjs/components/trees/models-tree/internal/ModelsTreeNode.js +1 -1
- package/lib/cjs/components/trees/models-tree/internal/ModelsTreeNode.js.map +1 -1
- package/lib/cjs/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.d.ts +8 -8
- package/lib/cjs/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js +162 -207
- package/lib/cjs/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js.map +1 -1
- package/lib/cjs/components/trees/models-tree/internal/VisibilityChangeEventListener.d.ts +2 -0
- package/lib/cjs/components/trees/models-tree/internal/VisibilityChangeEventListener.js +11 -1
- package/lib/cjs/components/trees/models-tree/internal/VisibilityChangeEventListener.js.map +1 -1
- package/lib/esm/components/tree-header/TreeHeader.js +1 -1
- package/lib/esm/components/tree-header/TreeHeader.js.map +1 -1
- package/lib/esm/components/trees/categories-tree/CategoriesTreeButtons.js +3 -3
- package/lib/esm/components/trees/categories-tree/CategoriesTreeButtons.js.map +1 -1
- package/lib/esm/components/trees/categories-tree/CategoriesVisibilityHandler.js +2 -1
- package/lib/esm/components/trees/categories-tree/CategoriesVisibilityHandler.js.map +1 -1
- package/lib/esm/components/trees/{models-tree/internal → common}/Tooltip.d.ts +7 -3
- package/lib/esm/components/trees/{models-tree/internal → common}/Tooltip.js +5 -5
- package/lib/esm/components/trees/common/Tooltip.js.map +1 -0
- package/lib/esm/components/trees/common/UseActiveViewport.js.map +1 -1
- package/lib/esm/components/trees/common/UseHierarchyVisibility.js +7 -4
- package/lib/esm/components/trees/common/UseHierarchyVisibility.js.map +1 -1
- package/lib/esm/components/trees/common/Utils.js +1 -1
- package/lib/esm/components/trees/common/Utils.js.map +1 -1
- package/lib/esm/components/trees/common/components/TreeNodeCheckbox.js +6 -6
- package/lib/esm/components/trees/common/components/TreeNodeCheckbox.js.map +1 -1
- package/lib/esm/components/trees/common/components/TreeRenderer.d.ts +1 -1
- package/lib/esm/components/trees/common/components/TreeRenderer.js +4 -3
- package/lib/esm/components/trees/common/components/TreeRenderer.js.map +1 -1
- package/lib/esm/components/trees/common/components/TreeRenderer.scss +0 -6
- package/lib/esm/components/trees/models-tree/ModelsTreeButtons.js +14 -14
- package/lib/esm/components/trees/models-tree/ModelsTreeButtons.js.map +1 -1
- package/lib/esm/components/trees/models-tree/ModelsTreeComponent.js.map +1 -1
- package/lib/esm/components/trees/models-tree/ModelsTreeDefinition.js.map +1 -1
- package/lib/esm/components/trees/models-tree/UseModelsTree.d.ts +1 -1
- package/lib/esm/components/trees/models-tree/UseModelsTree.js +24 -13
- package/lib/esm/components/trees/models-tree/UseModelsTree.js.map +1 -1
- package/lib/esm/components/trees/models-tree/internal/AlwaysAndNeverDrawnElementInfo.d.ts +5 -0
- package/lib/esm/components/trees/models-tree/internal/AlwaysAndNeverDrawnElementInfo.js +29 -8
- package/lib/esm/components/trees/models-tree/internal/AlwaysAndNeverDrawnElementInfo.js.map +1 -1
- package/lib/esm/components/trees/models-tree/internal/FilteredTree.d.ts +25 -0
- package/lib/esm/components/trees/models-tree/internal/FilteredTree.js +173 -0
- package/lib/esm/components/trees/models-tree/internal/FilteredTree.js.map +1 -0
- package/lib/esm/components/trees/models-tree/internal/ModelsTreeIdsCache.d.ts +2 -1
- package/lib/esm/components/trees/models-tree/internal/ModelsTreeIdsCache.js +55 -23
- package/lib/esm/components/trees/models-tree/internal/ModelsTreeIdsCache.js.map +1 -1
- package/lib/esm/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.d.ts +8 -8
- package/lib/esm/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js +161 -206
- package/lib/esm/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js.map +1 -1
- package/lib/esm/components/trees/models-tree/internal/VisibilityChangeEventListener.d.ts +2 -0
- package/lib/esm/components/trees/models-tree/internal/VisibilityChangeEventListener.js +11 -1
- package/lib/esm/components/trees/models-tree/internal/VisibilityChangeEventListener.js.map +1 -1
- package/lib/public/locales/en/TreeWidget.json +47 -43
- package/package.json +11 -11
- package/lib/cjs/components/trees/models-tree/internal/Tooltip.js.map +0 -1
- package/lib/esm/components/trees/models-tree/internal/Tooltip.js.map +0 -1
|
@@ -2,35 +2,18 @@
|
|
|
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, defer, distinct, EMPTY, firstValueFrom, forkJoin, from, map, merge, mergeMap, of, reduce } from "rxjs";
|
|
5
|
+
import { bufferCount, concat, concatAll, concatMap, defer, delay, distinct, EMPTY, filter, firstValueFrom, forkJoin, from, fromEventPattern, map, merge, mergeMap, of, reduce, shareReplay, startWith, Subject, take, takeUntil, tap, } from "rxjs";
|
|
6
6
|
import { assert } from "@itwin/core-bentley";
|
|
7
7
|
import { PerModelCategoryVisibility } from "@itwin/core-frontend";
|
|
8
|
-
import {
|
|
8
|
+
import { HierarchyNode, HierarchyNodeKey } from "@itwin/presentation-hierarchies";
|
|
9
9
|
import { toggleAllCategories } from "../../common/CategoriesVisibilityUtils";
|
|
10
10
|
import { reduceWhile, toVoidPromise } from "../../common/Rxjs";
|
|
11
|
+
import { createVisibilityStatus } from "../../common/Tooltip";
|
|
11
12
|
import { createVisibilityHandlerResult } from "../../common/UseHierarchyVisibility";
|
|
12
13
|
import { AlwaysAndNeverDrawnElementInfo } from "./AlwaysAndNeverDrawnElementInfo";
|
|
14
|
+
import { createFilteredTree, parseCategoryKey } from "./FilteredTree";
|
|
13
15
|
import { ModelsTreeNode } from "./ModelsTreeNode";
|
|
14
|
-
import { createVisibilityStatus } from "./Tooltip";
|
|
15
16
|
import { createVisibilityChangeEventListener } from "./VisibilityChangeEventListener";
|
|
16
|
-
export const SUBJECT_CLASS_NAME = "BisCore.Subject";
|
|
17
|
-
export const MODEL_CLASS_NAME = "BisCore.GeometricModel3d";
|
|
18
|
-
export const CATEGORY_CLASS_NAME = "BisCore.SpatialCategory";
|
|
19
|
-
export const ELEMENT_CLASS_NAME = "BisCore.GeometricElement3d";
|
|
20
|
-
function createCategoryKey(modelId, categoryId) {
|
|
21
|
-
return `${modelId}-${categoryId}`;
|
|
22
|
-
}
|
|
23
|
-
function parseCategoryKey(key) {
|
|
24
|
-
const [modelId, categoryId] = key.split("-");
|
|
25
|
-
return { modelId, categoryId };
|
|
26
|
-
}
|
|
27
|
-
function createElementKey(modelId, categoryId, elementId) {
|
|
28
|
-
return `${modelId}-${categoryId}-${elementId}`;
|
|
29
|
-
}
|
|
30
|
-
function parseElementKey(key) {
|
|
31
|
-
const [modelId, categoryId, elementId] = key.split("-");
|
|
32
|
-
return { modelId, categoryId, elementId };
|
|
33
|
-
}
|
|
34
17
|
/**
|
|
35
18
|
* Creates an instance if `ModelsTreeVisibilityHandler`.
|
|
36
19
|
* @internal
|
|
@@ -41,30 +24,55 @@ export function createModelsTreeVisibilityHandler(props) {
|
|
|
41
24
|
class ModelsTreeVisibilityHandlerImpl {
|
|
42
25
|
constructor(_props) {
|
|
43
26
|
this._props = _props;
|
|
27
|
+
this._elementChangeQueue = new Subject();
|
|
28
|
+
this._subscriptions = [];
|
|
29
|
+
this._changeRequest = new Subject();
|
|
44
30
|
this._eventListener = createVisibilityChangeEventListener(_props.viewport);
|
|
45
31
|
this._alwaysAndNeverDrawnElements = new AlwaysAndNeverDrawnElementInfo(_props.viewport);
|
|
46
32
|
this._idsCache = this._props.idsCache;
|
|
33
|
+
this._filteredTree = _props.filteredPaths ? createFilteredTree(this._props.imodelAccess, _props.filteredPaths) : undefined;
|
|
34
|
+
this._subscriptions.push(this._elementChangeQueue.pipe(concatAll()).subscribe());
|
|
47
35
|
}
|
|
48
36
|
// istanbul ignore next
|
|
49
37
|
get onVisibilityChange() {
|
|
50
38
|
return this._eventListener.onVisibilityChange;
|
|
51
39
|
}
|
|
52
40
|
async getVisibilityStatus(node) {
|
|
53
|
-
return firstValueFrom(this.getVisibilityStatusObs(node)
|
|
41
|
+
return firstValueFrom(this.getVisibilityStatusObs(node).pipe(
|
|
42
|
+
// unsubscribe from the observable if the change request for this node is received
|
|
43
|
+
takeUntil(this._changeRequest.pipe(filter(({ key, depth }) => depth === node.parentKeys.length && HierarchyNodeKey.equals(node.key, key)))),
|
|
44
|
+
// unsubscribe if visibility changes
|
|
45
|
+
takeUntil(fromEventPattern((handler) => {
|
|
46
|
+
this._eventListener.onVisibilityChange.addListener(handler);
|
|
47
|
+
}, (handler) => {
|
|
48
|
+
this._eventListener.onVisibilityChange.removeListener(handler);
|
|
49
|
+
}))));
|
|
54
50
|
}
|
|
55
51
|
async changeVisibility(node, shouldDisplay) {
|
|
56
|
-
|
|
52
|
+
// notify about new change request
|
|
53
|
+
this._changeRequest.next({ key: node.key, depth: node.parentKeys.length });
|
|
54
|
+
const changeObservable = this.changeVisibilityObs(node, shouldDisplay).pipe(
|
|
55
|
+
// unsubscribe from the observable if the change request for this node is received
|
|
56
|
+
takeUntil(this._changeRequest.pipe(filter(({ key, depth }) => depth === node.parentKeys.length && HierarchyNodeKey.equals(node.key, key)))), tap({
|
|
57
|
+
subscribe: () => {
|
|
58
|
+
this._eventListener.suppressChangeEvents();
|
|
59
|
+
this._alwaysAndNeverDrawnElements.suppressChangeEvents();
|
|
60
|
+
},
|
|
61
|
+
finalize: () => {
|
|
62
|
+
this._eventListener.resumeChangeEvents();
|
|
63
|
+
this._alwaysAndNeverDrawnElements.resumeChangeEvents();
|
|
64
|
+
},
|
|
65
|
+
}));
|
|
66
|
+
return toVoidPromise(changeObservable);
|
|
57
67
|
}
|
|
58
68
|
dispose() {
|
|
59
69
|
this._eventListener.dispose();
|
|
60
70
|
this._alwaysAndNeverDrawnElements.dispose();
|
|
71
|
+
this._subscriptions.forEach((x) => x.unsubscribe());
|
|
61
72
|
}
|
|
62
73
|
getVisibilityStatusObs(node) {
|
|
63
74
|
if (node.filtering?.filteredChildrenIdentifierPaths?.length && !node.filtering.isFilterTarget) {
|
|
64
|
-
return this.getFilteredNodeVisibility({
|
|
65
|
-
parentKeys: [...node.parentKeys, node.key],
|
|
66
|
-
filterPaths: node.filtering.filteredChildrenIdentifierPaths,
|
|
67
|
-
});
|
|
75
|
+
return this.getFilteredNodeVisibility({ node });
|
|
68
76
|
}
|
|
69
77
|
if (HierarchyNode.isClassGroupingNode(node)) {
|
|
70
78
|
return this.getClassGroupingNodeDisplayStatus(node);
|
|
@@ -74,10 +82,10 @@ class ModelsTreeVisibilityHandlerImpl {
|
|
|
74
82
|
}
|
|
75
83
|
if (ModelsTreeNode.isSubjectNode(node)) {
|
|
76
84
|
// note: subject nodes may be merged to represent multiple subject instances
|
|
77
|
-
return this.getSubjectNodeVisibilityStatus(node.key.instanceKeys.map((key) => key.id));
|
|
85
|
+
return this.getSubjectNodeVisibilityStatus({ subjectIds: node.key.instanceKeys.map((key) => key.id) });
|
|
78
86
|
}
|
|
79
87
|
if (ModelsTreeNode.isModelNode(node)) {
|
|
80
|
-
return this.getModelVisibilityStatus(node.key.instanceKeys[0].id);
|
|
88
|
+
return this.getModelVisibilityStatus({ modelId: node.key.instanceKeys[0].id });
|
|
81
89
|
}
|
|
82
90
|
const modelId = ModelsTreeNode.getModelId(node);
|
|
83
91
|
if (!modelId) {
|
|
@@ -99,25 +107,25 @@ class ModelsTreeVisibilityHandlerImpl {
|
|
|
99
107
|
categoryId,
|
|
100
108
|
});
|
|
101
109
|
}
|
|
102
|
-
getFilteredNodeVisibility(
|
|
103
|
-
return from(this.
|
|
110
|
+
getFilteredNodeVisibility(props) {
|
|
111
|
+
return from(this.getVisibilityChangeTargets(props)).pipe(mergeMap(({ subjects, models, categories, elements }) => {
|
|
104
112
|
const observables = new Array();
|
|
105
113
|
if (subjects?.size) {
|
|
106
|
-
observables.push(this.getSubjectNodeVisibilityStatus([...subjects]));
|
|
114
|
+
observables.push(this.getSubjectNodeVisibilityStatus({ subjectIds: [...subjects], ignoreTooltip: true }));
|
|
107
115
|
}
|
|
108
116
|
if (models?.size) {
|
|
109
|
-
observables.push(from(models).pipe(mergeMap((modelId) => this.getModelVisibilityStatus(modelId))));
|
|
117
|
+
observables.push(from(models).pipe(mergeMap((modelId) => this.getModelVisibilityStatus({ modelId, ignoreTooltip: true }))));
|
|
110
118
|
}
|
|
111
119
|
if (categories?.size) {
|
|
112
120
|
observables.push(from(categories).pipe(mergeMap((key) => {
|
|
113
121
|
const { modelId, categoryId } = parseCategoryKey(key);
|
|
114
|
-
return this.getCategoryDisplayStatus({ modelId, categoryId });
|
|
122
|
+
return this.getCategoryDisplayStatus({ modelId, categoryId, ignoreTooltip: true });
|
|
115
123
|
})));
|
|
116
124
|
}
|
|
117
125
|
if (elements?.size) {
|
|
118
|
-
observables.push(from(elements).pipe(mergeMap((
|
|
119
|
-
const { modelId, categoryId
|
|
120
|
-
return this.getElementDisplayStatus({ modelId, categoryId, elementId });
|
|
126
|
+
observables.push(from(elements).pipe(releaseMainThreadOnItemsCount(50), mergeMap(([categoryKey, elementIds]) => {
|
|
127
|
+
const { modelId, categoryId } = parseCategoryKey(categoryKey);
|
|
128
|
+
return from(elementIds).pipe(releaseMainThreadOnItemsCount(1000), mergeMap((elementId) => this.getElementDisplayStatus({ modelId, categoryId, elementId, ignoreTooltip: true })));
|
|
121
129
|
})));
|
|
122
130
|
}
|
|
123
131
|
return merge(...observables);
|
|
@@ -126,65 +134,66 @@ class ModelsTreeVisibilityHandlerImpl {
|
|
|
126
134
|
return createVisibilityStatus(x);
|
|
127
135
|
}));
|
|
128
136
|
}
|
|
129
|
-
getSubjectNodeVisibilityStatus(subjectIds) {
|
|
137
|
+
getSubjectNodeVisibilityStatus({ subjectIds, ignoreTooltip }) {
|
|
130
138
|
const result = defer(() => {
|
|
131
139
|
if (!this._props.viewport.view.isSpatialView()) {
|
|
132
|
-
return of(createVisibilityStatus("disabled", "subject.nonSpatialView"));
|
|
140
|
+
return of(createVisibilityStatus("disabled", getTooltipOptions("modelsTree.subject.nonSpatialView", ignoreTooltip)));
|
|
133
141
|
}
|
|
134
|
-
return from(this._idsCache.getSubjectModelIds(subjectIds)).pipe(concatAll(), distinct(), mergeMap((modelId) => this.getModelVisibilityStatus(modelId)), map((x) => x.state), getVisibilityStatusFromTreeNodeChildren({
|
|
135
|
-
visible: "subject.allModelsVisible",
|
|
136
|
-
hidden: "subject.allModelsHidden",
|
|
137
|
-
partial: "subject.someModelsHidden",
|
|
138
|
-
}));
|
|
142
|
+
return from(this._idsCache.getSubjectModelIds(subjectIds)).pipe(concatAll(), distinct(), mergeMap((modelId) => this.getModelVisibilityStatus({ modelId, ignoreTooltip: true })), map((x) => x.state), getVisibilityStatusFromTreeNodeChildren({
|
|
143
|
+
visible: "modelsTree.subject.allModelsVisible",
|
|
144
|
+
hidden: "modelsTree.subject.allModelsHidden",
|
|
145
|
+
partial: "modelsTree.subject.someModelsHidden",
|
|
146
|
+
}, ignoreTooltip));
|
|
139
147
|
});
|
|
140
148
|
return createVisibilityHandlerResult(this, { ids: subjectIds }, result, this._props.overrides?.getSubjectNodeVisibility);
|
|
141
149
|
}
|
|
142
|
-
getModelVisibilityStatus(modelId) {
|
|
150
|
+
getModelVisibilityStatus({ modelId, ignoreTooltip }) {
|
|
143
151
|
const result = defer(() => {
|
|
144
152
|
const viewport = this._props.viewport;
|
|
145
153
|
if (!viewport.view.isSpatialView()) {
|
|
146
|
-
return of(createVisibilityStatus("disabled", "model.nonSpatialView"));
|
|
154
|
+
return of(createVisibilityStatus("disabled", getTooltipOptions("modelsTree.model.nonSpatialView", ignoreTooltip)));
|
|
147
155
|
}
|
|
148
156
|
if (!viewport.view.viewsModel(modelId)) {
|
|
149
|
-
return of(createVisibilityStatus("hidden", "model.hiddenThroughModelSelector"));
|
|
157
|
+
return of(createVisibilityStatus("hidden", getTooltipOptions("modelsTree.model.hiddenThroughModelSelector", ignoreTooltip)));
|
|
150
158
|
}
|
|
151
|
-
return from(this._idsCache.getModelCategories(modelId)).pipe(concatAll(), mergeMap((categoryId) => this.getCategoryDisplayStatus({ modelId, categoryId })), map((x) => x.state), getVisibilityFromTreeNodeChildren, map((visibilityByCategories) => {
|
|
159
|
+
return from(this._idsCache.getModelCategories(modelId)).pipe(concatAll(), mergeMap((categoryId) => this.getCategoryDisplayStatus({ modelId, categoryId, ignoreTooltip: true })), map((x) => x.state), getVisibilityFromTreeNodeChildren, map((visibilityByCategories) => {
|
|
152
160
|
const state = visibilityByCategories === "empty" ? "visible" : visibilityByCategories;
|
|
153
|
-
return createVisibilityStatus(state, state === "partial" ? "model.someCategoriesHidden" : `model.allCategories${state ? "Visible" : "Hidden"}
|
|
161
|
+
return createVisibilityStatus(state, getTooltipOptions(state === "partial" ? "modelsTree.model.someCategoriesHidden" : `modelsTree.model.allCategories${state ? "Visible" : "Hidden"}`, ignoreTooltip));
|
|
154
162
|
}));
|
|
155
163
|
});
|
|
156
164
|
return createVisibilityHandlerResult(this, { id: modelId }, result, this._props.overrides?.getModelDisplayStatus);
|
|
157
165
|
}
|
|
158
|
-
getDefaultCategoryVisibilityStatus({ modelId, categoryId }) {
|
|
166
|
+
getDefaultCategoryVisibilityStatus({ modelId, categoryId, ignoreTooltip, }) {
|
|
159
167
|
const viewport = this._props.viewport;
|
|
160
168
|
if (!viewport.view.viewsModel(modelId)) {
|
|
161
|
-
return createVisibilityStatus("hidden", "category.hiddenThroughModel");
|
|
169
|
+
return createVisibilityStatus("hidden", getTooltipOptions("modelsTree.category.hiddenThroughModel", ignoreTooltip));
|
|
162
170
|
}
|
|
163
171
|
switch (this._props.viewport.perModelCategoryVisibility.getOverride(modelId, categoryId)) {
|
|
164
172
|
case PerModelCategoryVisibility.Override.Show:
|
|
165
|
-
return createVisibilityStatus("visible", "category.displayedThroughPerModelOverride");
|
|
173
|
+
return createVisibilityStatus("visible", getTooltipOptions("modelsTree.category.displayedThroughPerModelOverride", ignoreTooltip));
|
|
166
174
|
case PerModelCategoryVisibility.Override.Hide:
|
|
167
|
-
return createVisibilityStatus("hidden", "category.hiddenThroughPerModelOverride");
|
|
175
|
+
return createVisibilityStatus("hidden", getTooltipOptions("modelsTree.category.hiddenThroughPerModelOverride", ignoreTooltip));
|
|
168
176
|
}
|
|
169
177
|
const isVisible = viewport.view.viewsCategory(categoryId);
|
|
170
178
|
return isVisible
|
|
171
|
-
? createVisibilityStatus("visible", "category.displayedThroughCategorySelector")
|
|
172
|
-
: createVisibilityStatus("hidden", "category.hiddenThroughCategorySelector");
|
|
179
|
+
? createVisibilityStatus("visible", getTooltipOptions("modelsTree.category.displayedThroughCategorySelector", ignoreTooltip))
|
|
180
|
+
: createVisibilityStatus("hidden", getTooltipOptions("modelsTree.category.hiddenThroughCategorySelector", ignoreTooltip));
|
|
173
181
|
}
|
|
174
|
-
getCategoryDisplayStatus(props) {
|
|
182
|
+
getCategoryDisplayStatus({ ignoreTooltip, ...props }) {
|
|
175
183
|
const result = defer(() => {
|
|
176
184
|
if (!this._props.viewport.view.viewsModel(props.modelId)) {
|
|
177
|
-
return of(createVisibilityStatus("hidden", "category.hiddenThroughModel"));
|
|
185
|
+
return of(createVisibilityStatus("hidden", getTooltipOptions("modelsTree.category.hiddenThroughModel", ignoreTooltip)));
|
|
178
186
|
}
|
|
179
187
|
return this.getVisibilityFromAlwaysAndNeverDrawnElements({
|
|
180
188
|
queryProps: props,
|
|
181
189
|
tooltips: {
|
|
182
|
-
allElementsInAlwaysDrawnList: "category.allElementsVisible",
|
|
183
|
-
allElementsInNeverDrawnList: "category.allElementsHidden",
|
|
184
|
-
elementsInBothAlwaysAndNeverDrawn: "category.someElementsAreHidden",
|
|
185
|
-
noElementsInExclusiveAlwaysDrawnList: "category.allElementsHidden",
|
|
190
|
+
allElementsInAlwaysDrawnList: "modelsTree.category.allElementsVisible",
|
|
191
|
+
allElementsInNeverDrawnList: "modelsTree.category.allElementsHidden",
|
|
192
|
+
elementsInBothAlwaysAndNeverDrawn: "modelsTree.category.someElementsAreHidden",
|
|
193
|
+
noElementsInExclusiveAlwaysDrawnList: "modelsTree.category.allElementsHidden",
|
|
186
194
|
},
|
|
187
195
|
defaultStatus: () => this.getDefaultCategoryVisibilityStatus(props),
|
|
196
|
+
ignoreTooltip,
|
|
188
197
|
});
|
|
189
198
|
});
|
|
190
199
|
return createVisibilityHandlerResult(this, props, result, this._props.overrides?.getCategoryDisplayStatus);
|
|
@@ -199,58 +208,54 @@ class ModelsTreeVisibilityHandlerImpl {
|
|
|
199
208
|
return this.getVisibilityFromAlwaysAndNeverDrawnElements({
|
|
200
209
|
elements: elementIds,
|
|
201
210
|
defaultStatus: () => {
|
|
202
|
-
const status = this.getDefaultCategoryVisibilityStatus({ categoryId, modelId });
|
|
203
|
-
return createVisibilityStatus(status.state, `groupingNode.${status.state}ThroughCategory`);
|
|
211
|
+
const status = this.getDefaultCategoryVisibilityStatus({ categoryId, modelId, ignoreTooltip: true });
|
|
212
|
+
return createVisibilityStatus(status.state, getTooltipOptions(`modelsTree.groupingNode.${status.state}ThroughCategory`));
|
|
204
213
|
},
|
|
205
214
|
tooltips: {
|
|
206
|
-
allElementsInAlwaysDrawnList: "groupingNode.allElementsVisible",
|
|
207
|
-
allElementsInNeverDrawnList: "groupingNode.allElementsHidden",
|
|
208
|
-
elementsInBothAlwaysAndNeverDrawn: "groupingNode.someElementsAreHidden",
|
|
209
|
-
noElementsInExclusiveAlwaysDrawnList: "groupingNode.allElementsHidden",
|
|
215
|
+
allElementsInAlwaysDrawnList: "modelsTree.groupingNode.allElementsVisible",
|
|
216
|
+
allElementsInNeverDrawnList: "modelsTree.groupingNode.allElementsHidden",
|
|
217
|
+
elementsInBothAlwaysAndNeverDrawn: "modelsTree.groupingNode.someElementsAreHidden",
|
|
218
|
+
noElementsInExclusiveAlwaysDrawnList: "modelsTree.groupingNode.allElementsHidden",
|
|
210
219
|
},
|
|
211
220
|
});
|
|
212
221
|
});
|
|
213
222
|
return createVisibilityHandlerResult(this, { node }, result, this._props.overrides?.getElementGroupingNodeDisplayStatus);
|
|
214
223
|
}
|
|
215
|
-
getElementOverriddenVisibility(elementId) {
|
|
224
|
+
getElementOverriddenVisibility(elementId, ignoreTooltip) {
|
|
216
225
|
const viewport = this._props.viewport;
|
|
217
226
|
if (viewport.neverDrawn?.has(elementId)) {
|
|
218
|
-
return createVisibilityStatus("hidden", "element.hiddenThroughNeverDrawnList");
|
|
227
|
+
return createVisibilityStatus("hidden", getTooltipOptions("modelsTree.element.hiddenThroughNeverDrawnList", ignoreTooltip));
|
|
219
228
|
}
|
|
220
229
|
if (viewport.alwaysDrawn?.size) {
|
|
221
230
|
if (viewport.alwaysDrawn.has(elementId)) {
|
|
222
|
-
return createVisibilityStatus("visible", "element.displayedThroughAlwaysDrawnList");
|
|
231
|
+
return createVisibilityStatus("visible", getTooltipOptions("modelsTree.element.displayedThroughAlwaysDrawnList", ignoreTooltip));
|
|
223
232
|
}
|
|
224
233
|
if (viewport.isAlwaysDrawnExclusive) {
|
|
225
|
-
return createVisibilityStatus("hidden", "element.hiddenDueToOtherElementsExclusivelyAlwaysDrawn");
|
|
234
|
+
return createVisibilityStatus("hidden", getTooltipOptions("modelsTree.element.hiddenDueToOtherElementsExclusivelyAlwaysDrawn", ignoreTooltip));
|
|
226
235
|
}
|
|
227
236
|
}
|
|
228
237
|
return undefined;
|
|
229
238
|
}
|
|
230
|
-
getElementDisplayStatus(props) {
|
|
239
|
+
getElementDisplayStatus({ ignoreTooltip, ...props }) {
|
|
231
240
|
const result = defer(() => {
|
|
232
241
|
const viewport = this._props.viewport;
|
|
233
242
|
const { elementId, modelId, categoryId } = props;
|
|
234
243
|
if (!viewport.view.viewsModel(modelId)) {
|
|
235
|
-
return of(createVisibilityStatus("hidden", "element.hiddenThroughModel"));
|
|
244
|
+
return of(createVisibilityStatus("hidden", getTooltipOptions("modelsTree.element.hiddenThroughModel", ignoreTooltip)));
|
|
236
245
|
}
|
|
237
|
-
let status = this.getElementOverriddenVisibility(elementId);
|
|
246
|
+
let status = this.getElementOverriddenVisibility(elementId, ignoreTooltip);
|
|
238
247
|
if (status) {
|
|
239
248
|
return of(status);
|
|
240
249
|
}
|
|
241
|
-
status = this.getDefaultCategoryVisibilityStatus({ categoryId, modelId });
|
|
242
|
-
return of(createVisibilityStatus(status.state, status.state === "visible" ? undefined : "element.hiddenThroughCategory"));
|
|
250
|
+
status = this.getDefaultCategoryVisibilityStatus({ categoryId, modelId, ignoreTooltip: true });
|
|
251
|
+
return of(createVisibilityStatus(status.state, getTooltipOptions(status.state === "visible" ? undefined : "modelsTree.element.hiddenThroughCategory", ignoreTooltip)));
|
|
243
252
|
});
|
|
244
253
|
return createVisibilityHandlerResult(this, props, result, this._props.overrides?.getElementDisplayStatus);
|
|
245
254
|
}
|
|
246
255
|
/** Changes visibility of the items represented by the tree node. */
|
|
247
256
|
changeVisibilityObs(node, on) {
|
|
248
257
|
if (node.filtering?.filteredChildrenIdentifierPaths?.length && !node.filtering.isFilterTarget) {
|
|
249
|
-
return this.changeFilteredNodeVisibility({
|
|
250
|
-
parentKeys: [...node.parentKeys, node.key],
|
|
251
|
-
filterPaths: node.filtering.filteredChildrenIdentifierPaths,
|
|
252
|
-
on,
|
|
253
|
-
});
|
|
258
|
+
return this.changeFilteredNodeVisibility({ node, on });
|
|
254
259
|
}
|
|
255
260
|
if (HierarchyNode.isClassGroupingNode(node)) {
|
|
256
261
|
return this.changeElementGroupingNodeState(node, on);
|
|
@@ -283,62 +288,19 @@ class ModelsTreeVisibilityHandlerImpl {
|
|
|
283
288
|
// istanbul ignore next
|
|
284
289
|
return EMPTY;
|
|
285
290
|
}
|
|
286
|
-
return this.
|
|
287
|
-
|
|
291
|
+
return this.changeElementsState({
|
|
292
|
+
elementIds: new Set([...node.key.instanceKeys.map(({ id }) => id)]),
|
|
288
293
|
modelId,
|
|
289
294
|
categoryId,
|
|
290
295
|
on,
|
|
291
296
|
});
|
|
292
297
|
}
|
|
293
|
-
async
|
|
294
|
-
const
|
|
295
|
-
|
|
296
|
-
(filterTargets[targetType] ??= new Set()).add(value);
|
|
297
|
-
}
|
|
298
|
-
const imodelAccess = this._props.imodelAccess;
|
|
299
|
-
// Remove all paths such that there are paths to any of the ancestors of the filter target.
|
|
300
|
-
const paths = reduceFilterPaths(filterPaths);
|
|
301
|
-
await Promise.all(paths.map(async (path) => {
|
|
302
|
-
const target = path[path.length - 1];
|
|
303
|
-
if (!HierarchyNodeIdentifier.isInstanceNodeIdentifier(target)) {
|
|
304
|
-
return;
|
|
305
|
-
}
|
|
306
|
-
const previousPath = path.slice(0, path.length - 1);
|
|
307
|
-
if (await imodelAccess.classDerivesFrom(target.className, SUBJECT_CLASS_NAME)) {
|
|
308
|
-
addFilterTarget("subjects", target.id);
|
|
309
|
-
return;
|
|
310
|
-
}
|
|
311
|
-
if (await imodelAccess.classDerivesFrom(target.className, MODEL_CLASS_NAME)) {
|
|
312
|
-
addFilterTarget("models", target.id);
|
|
313
|
-
return;
|
|
314
|
-
}
|
|
315
|
-
if (await imodelAccess.classDerivesFrom(target.className, CATEGORY_CLASS_NAME)) {
|
|
316
|
-
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
317
|
-
const modelId = await this.findClassIdInFilterPath(previousPath, parentKeys, MODEL_CLASS_NAME);
|
|
318
|
-
addFilterTarget("categories", createCategoryKey(modelId, target.id));
|
|
319
|
-
return;
|
|
320
|
-
}
|
|
321
|
-
const [modelId, categoryId] = await Promise.all([
|
|
322
|
-
this.findClassIdInFilterPath(previousPath, parentKeys, MODEL_CLASS_NAME),
|
|
323
|
-
this.findClassIdInFilterPath(previousPath, parentKeys, CATEGORY_CLASS_NAME),
|
|
324
|
-
]);
|
|
325
|
-
addFilterTarget("elements", createElementKey(modelId, categoryId, target.id));
|
|
326
|
-
// Add parent elements to the filter targets as well
|
|
327
|
-
for (let idx = path.length - 1; idx >= 0; --idx) {
|
|
328
|
-
const pathIdentifier = path[idx];
|
|
329
|
-
if (!HierarchyNodeIdentifier.isInstanceNodeIdentifier(pathIdentifier)) {
|
|
330
|
-
continue;
|
|
331
|
-
}
|
|
332
|
-
if (!(await imodelAccess.classDerivesFrom(pathIdentifier.className, ELEMENT_CLASS_NAME))) {
|
|
333
|
-
break;
|
|
334
|
-
}
|
|
335
|
-
addFilterTarget("elements", createElementKey(modelId, categoryId, pathIdentifier.id));
|
|
336
|
-
}
|
|
337
|
-
}));
|
|
338
|
-
return filterTargets;
|
|
298
|
+
async getVisibilityChangeTargets({ node }) {
|
|
299
|
+
const filteredTree = await this._filteredTree;
|
|
300
|
+
return filteredTree ? filteredTree.getVisibilityChangeTargets(node) : {};
|
|
339
301
|
}
|
|
340
302
|
changeFilteredNodeVisibility({ on, ...props }) {
|
|
341
|
-
return from(this.
|
|
303
|
+
return from(this.getVisibilityChangeTargets(props)).pipe(mergeMap(({ subjects, models, categories, elements }) => {
|
|
342
304
|
const observables = new Array();
|
|
343
305
|
if (subjects?.size) {
|
|
344
306
|
observables.push(this.changeSubjectNodeState([...subjects], on));
|
|
@@ -353,9 +315,9 @@ class ModelsTreeVisibilityHandlerImpl {
|
|
|
353
315
|
})));
|
|
354
316
|
}
|
|
355
317
|
if (elements?.size) {
|
|
356
|
-
observables.push(from(elements).pipe(mergeMap((
|
|
357
|
-
const { modelId, categoryId
|
|
358
|
-
return this.
|
|
318
|
+
observables.push(from(elements).pipe(mergeMap(([categoryKey, elementIds]) => {
|
|
319
|
+
const { modelId, categoryId } = parseCategoryKey(categoryKey);
|
|
320
|
+
return this.changeElementsState({ modelId, categoryId, elementIds, on });
|
|
359
321
|
})));
|
|
360
322
|
}
|
|
361
323
|
return merge(...observables);
|
|
@@ -444,9 +406,9 @@ class ModelsTreeVisibilityHandlerImpl {
|
|
|
444
406
|
const { modelId, categoryId, elementIds } = info;
|
|
445
407
|
const viewport = this._props.viewport;
|
|
446
408
|
return concat(on && !viewport.view.viewsModel(modelId) ? this.showModelWithoutAnyCategoriesOrElements(modelId) : EMPTY, defer(() => {
|
|
447
|
-
const categoryVisibility = this.getDefaultCategoryVisibilityStatus({ categoryId, modelId });
|
|
409
|
+
const categoryVisibility = this.getDefaultCategoryVisibilityStatus({ categoryId, modelId, ignoreTooltip: true });
|
|
448
410
|
const isDisplayedByDefault = categoryVisibility.state === "visible";
|
|
449
|
-
return
|
|
411
|
+
return this.queueElementsVisibilityChange(elementIds, on, isDisplayedByDefault);
|
|
450
412
|
}));
|
|
451
413
|
});
|
|
452
414
|
return createVisibilityHandlerResult(this, { node, on }, result, this._props.overrides?.changeElementGroupingNodeState);
|
|
@@ -455,23 +417,49 @@ class ModelsTreeVisibilityHandlerImpl {
|
|
|
455
417
|
* Updates visibility of an element and all its child elements by adding them to the always/never drawn list.
|
|
456
418
|
* @note If element is to be enabled and model is hidden, it will be enabled.
|
|
457
419
|
*/
|
|
458
|
-
|
|
420
|
+
changeElementsState(props) {
|
|
459
421
|
const result = defer(() => {
|
|
460
|
-
const {
|
|
422
|
+
const { elementIds, on, modelId, categoryId } = props;
|
|
461
423
|
const viewport = this._props.viewport;
|
|
462
424
|
return concat(props.on && !viewport.view.viewsModel(modelId) ? this.showModelWithoutAnyCategoriesOrElements(modelId) : EMPTY, defer(() => {
|
|
463
|
-
const categoryVisibility = this.getDefaultCategoryVisibilityStatus({ categoryId, modelId });
|
|
425
|
+
const categoryVisibility = this.getDefaultCategoryVisibilityStatus({ categoryId, modelId, ignoreTooltip: true });
|
|
464
426
|
const isDisplayedByDefault = categoryVisibility.state === "visible";
|
|
465
|
-
return
|
|
427
|
+
return this.queueElementsVisibilityChange(elementIds, on, isDisplayedByDefault);
|
|
466
428
|
}));
|
|
467
429
|
});
|
|
468
|
-
return createVisibilityHandlerResult(this, props, result, this._props.overrides?.
|
|
430
|
+
return createVisibilityHandlerResult(this, props, result, this._props.overrides?.changeElementsState);
|
|
431
|
+
}
|
|
432
|
+
queueElementsVisibilityChange(elementIds, on, visibleByDefault) {
|
|
433
|
+
const finishedSubject = new Subject();
|
|
434
|
+
// observable to track if visibility change is finished/cancelled
|
|
435
|
+
const changeFinished = finishedSubject.pipe(startWith(false), shareReplay(1), filter((finished) => finished));
|
|
436
|
+
const changeObservable = from(elementIds).pipe(
|
|
437
|
+
// check if visibility change is not finished (cancelled) due to change overall change request being cancelled
|
|
438
|
+
takeUntil(changeFinished), this.changeElementStateNoChildrenOperator({ on, isDisplayedByDefault: visibleByDefault }), tap({
|
|
439
|
+
next: () => {
|
|
440
|
+
// notify that visibility change is finished
|
|
441
|
+
finishedSubject.next(true);
|
|
442
|
+
},
|
|
443
|
+
}));
|
|
444
|
+
// queue visibility change. `changeObservable` will be subscribed to when other queue changes are finished
|
|
445
|
+
this._elementChangeQueue.next(changeObservable);
|
|
446
|
+
// return observable that will emit when visibility change is finished
|
|
447
|
+
return changeFinished.pipe(take(1), tap({
|
|
448
|
+
unsubscribe: () => {
|
|
449
|
+
// if this observable is unsubscribed before visibility change is finished, we have to notify that it queued change request is cancelled
|
|
450
|
+
finishedSubject.next(true);
|
|
451
|
+
},
|
|
452
|
+
}), map(() => undefined));
|
|
469
453
|
}
|
|
470
454
|
changeElementStateNoChildrenOperator(props) {
|
|
471
455
|
return (elementIds) => {
|
|
472
456
|
const { on, isDisplayedByDefault } = props;
|
|
473
457
|
const isAlwaysDrawnExclusive = this._props.viewport.isAlwaysDrawnExclusive;
|
|
474
|
-
return elementIds.pipe(reduce((acc, elementId) => {
|
|
458
|
+
return elementIds.pipe(releaseMainThreadOnItemsCount(500), reduce((acc, elementId) => {
|
|
459
|
+
if (acc.alwaysDrawn === undefined || acc.neverDrawn === undefined) {
|
|
460
|
+
acc.alwaysDrawn = new Set(this._props.viewport.alwaysDrawn || []);
|
|
461
|
+
acc.neverDrawn = new Set(this._props.viewport.neverDrawn || []);
|
|
462
|
+
}
|
|
475
463
|
if (on) {
|
|
476
464
|
const wasRemoved = acc.neverDrawn.delete(elementId);
|
|
477
465
|
acc.changedNeverDrawn ||= wasRemoved;
|
|
@@ -494,39 +482,39 @@ class ModelsTreeVisibilityHandlerImpl {
|
|
|
494
482
|
}, {
|
|
495
483
|
changedNeverDrawn: false,
|
|
496
484
|
changedAlwaysDrawn: false,
|
|
497
|
-
neverDrawn:
|
|
498
|
-
alwaysDrawn:
|
|
485
|
+
neverDrawn: undefined,
|
|
486
|
+
alwaysDrawn: undefined,
|
|
499
487
|
}), map((state) => {
|
|
500
|
-
state.changedNeverDrawn && this._props.viewport.setNeverDrawn(state.neverDrawn);
|
|
501
|
-
state.changedAlwaysDrawn && this._props.viewport.setAlwaysDrawn(state.alwaysDrawn, this._props.viewport.isAlwaysDrawnExclusive);
|
|
488
|
+
state.changedNeverDrawn && state.neverDrawn && this._props.viewport.setNeverDrawn(state.neverDrawn);
|
|
489
|
+
state.changedAlwaysDrawn && state.alwaysDrawn && this._props.viewport.setAlwaysDrawn(state.alwaysDrawn, this._props.viewport.isAlwaysDrawnExclusive);
|
|
502
490
|
}));
|
|
503
491
|
};
|
|
504
492
|
}
|
|
505
493
|
getVisibilityFromAlwaysAndNeverDrawnElementsImpl(props) {
|
|
506
|
-
const { alwaysDrawn, neverDrawn, totalCount } = props;
|
|
494
|
+
const { alwaysDrawn, neverDrawn, totalCount, ignoreTooltip } = props;
|
|
507
495
|
if (neverDrawn?.size === totalCount) {
|
|
508
|
-
return createVisibilityStatus("hidden", props.tooltips.allElementsInNeverDrawnList);
|
|
496
|
+
return createVisibilityStatus("hidden", getTooltipOptions(props.tooltips.allElementsInNeverDrawnList, ignoreTooltip));
|
|
509
497
|
}
|
|
510
498
|
if (alwaysDrawn?.size === totalCount) {
|
|
511
|
-
return createVisibilityStatus("visible", props.tooltips.allElementsInAlwaysDrawnList);
|
|
499
|
+
return createVisibilityStatus("visible", getTooltipOptions(props.tooltips.allElementsInAlwaysDrawnList, ignoreTooltip));
|
|
512
500
|
}
|
|
513
501
|
const viewport = this._props.viewport;
|
|
514
502
|
if (viewport.isAlwaysDrawnExclusive && viewport.alwaysDrawn?.size) {
|
|
515
503
|
return alwaysDrawn?.size
|
|
516
|
-
? createVisibilityStatus("partial", props.tooltips.elementsInBothAlwaysAndNeverDrawn)
|
|
517
|
-
: createVisibilityStatus("hidden", props.tooltips.noElementsInExclusiveAlwaysDrawnList);
|
|
504
|
+
? createVisibilityStatus("partial", getTooltipOptions(props.tooltips.elementsInBothAlwaysAndNeverDrawn, ignoreTooltip))
|
|
505
|
+
: createVisibilityStatus("hidden", getTooltipOptions(props.tooltips.noElementsInExclusiveAlwaysDrawnList, ignoreTooltip));
|
|
518
506
|
}
|
|
519
507
|
const status = props.defaultStatus();
|
|
520
508
|
if ((status.state === "visible" && neverDrawn?.size) || (status.state === "hidden" && alwaysDrawn?.size)) {
|
|
521
|
-
return createVisibilityStatus("partial");
|
|
509
|
+
return createVisibilityStatus("partial", getTooltipOptions(undefined, ignoreTooltip));
|
|
522
510
|
}
|
|
523
511
|
return status;
|
|
524
512
|
}
|
|
525
|
-
getVisibilityFromAlwaysAndNeverDrawnElements(props) {
|
|
513
|
+
getVisibilityFromAlwaysAndNeverDrawnElements({ ignoreTooltip, ...props }) {
|
|
526
514
|
const viewport = this._props.viewport;
|
|
527
515
|
if (viewport.isAlwaysDrawnExclusive) {
|
|
528
516
|
if (!viewport?.alwaysDrawn?.size) {
|
|
529
|
-
return of(createVisibilityStatus("hidden", props.tooltips.noElementsInExclusiveAlwaysDrawnList));
|
|
517
|
+
return of(createVisibilityStatus("hidden", getTooltipOptions(props.tooltips.noElementsInExclusiveAlwaysDrawnList, ignoreTooltip)));
|
|
530
518
|
}
|
|
531
519
|
}
|
|
532
520
|
else if (!viewport?.neverDrawn?.size && !viewport?.alwaysDrawn?.size) {
|
|
@@ -538,6 +526,7 @@ class ModelsTreeVisibilityHandlerImpl {
|
|
|
538
526
|
alwaysDrawn: viewport.alwaysDrawn?.size ? setIntersection(props.elements, viewport.alwaysDrawn) : undefined,
|
|
539
527
|
neverDrawn: viewport.neverDrawn?.size ? setIntersection(props.elements, viewport.neverDrawn) : undefined,
|
|
540
528
|
totalCount: props.elements.size,
|
|
529
|
+
ignoreTooltip,
|
|
541
530
|
}));
|
|
542
531
|
}
|
|
543
532
|
const { modelId, categoryId } = props.queryProps;
|
|
@@ -550,6 +539,7 @@ class ModelsTreeVisibilityHandlerImpl {
|
|
|
550
539
|
return this.getVisibilityFromAlwaysAndNeverDrawnElementsImpl({
|
|
551
540
|
...props,
|
|
552
541
|
...state,
|
|
542
|
+
ignoreTooltip,
|
|
553
543
|
});
|
|
554
544
|
}));
|
|
555
545
|
}
|
|
@@ -580,28 +570,6 @@ class ModelsTreeVisibilityHandlerImpl {
|
|
|
580
570
|
const elementIds = new Set(node.groupedInstanceKeys.map((key) => key.id));
|
|
581
571
|
return { modelId, categoryId, elementIds };
|
|
582
572
|
}
|
|
583
|
-
async findClassIdInFilterPath(path, parentKeys, className) {
|
|
584
|
-
function* keysToCheck() {
|
|
585
|
-
for (let i = path.length - 1; i >= 0; --i) {
|
|
586
|
-
const id = path[i];
|
|
587
|
-
if (HierarchyNodeIdentifier.isInstanceNodeIdentifier(id)) {
|
|
588
|
-
yield id;
|
|
589
|
-
}
|
|
590
|
-
}
|
|
591
|
-
for (let i = parentKeys.length - 1; i >= 0; --i) {
|
|
592
|
-
const key = parentKeys[i];
|
|
593
|
-
if (HierarchyNodeKey.isInstances(key)) {
|
|
594
|
-
yield* key.instanceKeys;
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
for (const parentKey of keysToCheck()) {
|
|
599
|
-
if (await this._props.imodelAccess.classDerivesFrom(parentKey.className, className)) {
|
|
600
|
-
return parentKey.id;
|
|
601
|
-
}
|
|
602
|
-
}
|
|
603
|
-
assert(false, () => `Cannot find an instance of ${className} in instance keys: ${JSON.stringify([...keysToCheck()], undefined, 2)}`);
|
|
604
|
-
}
|
|
605
573
|
}
|
|
606
574
|
function getVisibilityFromTreeNodeChildren(obs) {
|
|
607
575
|
return obs.pipe(reduceWhile((x) => x.allVisible || x.allHidden, (acc, val) => {
|
|
@@ -615,13 +583,13 @@ function getVisibilityFromTreeNodeChildren(obs) {
|
|
|
615
583
|
return x.allVisible ? "visible" : x.allHidden ? "hidden" : "partial";
|
|
616
584
|
}));
|
|
617
585
|
}
|
|
618
|
-
function getVisibilityStatusFromTreeNodeChildren(tooltipMap) {
|
|
586
|
+
function getVisibilityStatusFromTreeNodeChildren(tooltipMap, ignoreTooltip) {
|
|
619
587
|
return (obs) => {
|
|
620
588
|
return getVisibilityFromTreeNodeChildren(obs).pipe(map((visibility) => {
|
|
621
589
|
if (visibility === "empty") {
|
|
622
590
|
visibility = "visible";
|
|
623
591
|
}
|
|
624
|
-
return createVisibilityStatus(visibility, tooltipMap[visibility]);
|
|
592
|
+
return createVisibilityStatus(visibility, getTooltipOptions(tooltipMap[visibility], ignoreTooltip));
|
|
625
593
|
}));
|
|
626
594
|
};
|
|
627
595
|
}
|
|
@@ -635,35 +603,6 @@ function setIntersection(lhs, rhs) {
|
|
|
635
603
|
lhs.forEach((x) => rhs.has(x) && result.add(x));
|
|
636
604
|
return result;
|
|
637
605
|
}
|
|
638
|
-
function reduceFilterPaths(filteringPaths) {
|
|
639
|
-
let paths = filteringPaths.map((filteringPath) => HierarchyFilteringPath.normalize(filteringPath).path);
|
|
640
|
-
const sorted = [...paths].sort((a, b) => a.length - b.length);
|
|
641
|
-
paths = [];
|
|
642
|
-
for (const path of sorted) {
|
|
643
|
-
if (!arraySortedByLengthContainsPrefix(paths, path)) {
|
|
644
|
-
paths.push(path);
|
|
645
|
-
}
|
|
646
|
-
}
|
|
647
|
-
return paths;
|
|
648
|
-
}
|
|
649
|
-
function arraySortedByLengthContainsPrefix(targetArray, source) {
|
|
650
|
-
for (const targetVal of targetArray) {
|
|
651
|
-
if (targetVal.length >= source.length) {
|
|
652
|
-
break;
|
|
653
|
-
}
|
|
654
|
-
let isPrefix = true;
|
|
655
|
-
for (let i = 0; i < targetVal.length; ++i) {
|
|
656
|
-
if (!HierarchyNodeIdentifier.equal(targetVal[i], source[i])) {
|
|
657
|
-
isPrefix = false;
|
|
658
|
-
break;
|
|
659
|
-
}
|
|
660
|
-
}
|
|
661
|
-
if (isPrefix) {
|
|
662
|
-
return true;
|
|
663
|
-
}
|
|
664
|
-
}
|
|
665
|
-
return false;
|
|
666
|
-
}
|
|
667
606
|
/**
|
|
668
607
|
* Enables display of all given models. Also enables display of all categories and clears always and
|
|
669
608
|
* never drawn lists in the viewport.
|
|
@@ -723,4 +662,20 @@ export async function toggleModels(models, enable, viewport) {
|
|
|
723
662
|
export function areAllModelsVisible(models, viewport) {
|
|
724
663
|
return models.length !== 0 ? models.every((id) => viewport.viewsModel(id)) : false;
|
|
725
664
|
}
|
|
665
|
+
function releaseMainThreadOnItemsCount(elementCount) {
|
|
666
|
+
return (obs) => {
|
|
667
|
+
return obs.pipe(bufferCount(elementCount), concatMap((buff, i) => {
|
|
668
|
+
const out = of(buff);
|
|
669
|
+
if (i === 0 && buff.length < elementCount) {
|
|
670
|
+
return out;
|
|
671
|
+
}
|
|
672
|
+
return out.pipe(delay(0));
|
|
673
|
+
}), concatAll());
|
|
674
|
+
};
|
|
675
|
+
}
|
|
676
|
+
function getTooltipOptions(key, ignoreTooltip) {
|
|
677
|
+
return {
|
|
678
|
+
useTooltip: ignoreTooltip ? false : key,
|
|
679
|
+
};
|
|
680
|
+
}
|
|
726
681
|
//# sourceMappingURL=ModelsTreeVisibilityHandler.js.map
|