@itwin/tree-widget-react 4.0.0-alpha.6 → 4.0.0-alpha.7

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.
Files changed (159) hide show
  1. package/CHANGELOG.md +22 -1
  2. package/README.md +2 -1
  3. package/lib/esm/tree-widget-react/TreeWidget.js +1 -1
  4. package/lib/esm/tree-widget-react/TreeWidget.js.map +1 -1
  5. package/lib/esm/tree-widget-react/components/tree-header/SearchBox.d.ts +1 -0
  6. package/lib/esm/tree-widget-react/components/tree-header/SearchBox.js +1 -0
  7. package/lib/esm/tree-widget-react/components/tree-header/SearchBox.js.map +1 -1
  8. package/lib/esm/tree-widget-react/components/tree-header/SelectableTree.css +2 -0
  9. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeButtons.d.ts +9 -2
  10. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeButtons.js +50 -4
  11. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeButtons.js.map +1 -1
  12. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeComponent.js +1 -1
  13. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeComponent.js.map +1 -1
  14. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.d.ts +17 -3
  15. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js +561 -161
  16. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js.map +1 -1
  17. package/lib/esm/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.d.ts +6 -2
  18. package/lib/esm/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.js +115 -40
  19. package/lib/esm/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.js.map +1 -1
  20. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.d.ts +30 -15
  21. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js +192 -38
  22. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js.map +1 -1
  23. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeNode.d.ts +18 -3
  24. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeNode.js +30 -3
  25. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeNode.js.map +1 -1
  26. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeVisibilityHandler.d.ts +24 -0
  27. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeVisibilityHandler.js +785 -0
  28. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeVisibilityHandler.js.map +1 -0
  29. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/FilteredTree.d.ts +39 -0
  30. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/FilteredTree.js +221 -0
  31. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/FilteredTree.js.map +1 -0
  32. package/lib/esm/tree-widget-react/components/trees/common/CategoriesVisibilityUtils.d.ts +5 -17
  33. package/lib/esm/tree-widget-react/components/trees/common/CategoriesVisibilityUtils.js +5 -62
  34. package/lib/esm/tree-widget-react/components/trees/common/CategoriesVisibilityUtils.js.map +1 -1
  35. package/lib/esm/tree-widget-react/components/trees/common/UseHierarchyVisibility.d.ts +2 -0
  36. package/lib/esm/tree-widget-react/components/trees/common/UseHierarchyVisibility.js +4 -2
  37. package/lib/esm/tree-widget-react/components/trees/common/UseHierarchyVisibility.js.map +1 -1
  38. package/lib/esm/tree-widget-react/components/trees/common/UseNodeHighlighting.d.ts +1 -0
  39. package/lib/esm/tree-widget-react/components/trees/common/UseNodeHighlighting.js +2 -1
  40. package/lib/esm/tree-widget-react/components/trees/common/UseNodeHighlighting.js.map +1 -1
  41. package/lib/esm/tree-widget-react/components/trees/common/UseTelemetryContext.d.ts +1 -0
  42. package/lib/esm/tree-widget-react/components/trees/common/UseTelemetryContext.js +2 -1
  43. package/lib/esm/tree-widget-react/components/trees/common/UseTelemetryContext.js.map +1 -1
  44. package/lib/esm/tree-widget-react/components/trees/common/Utils.d.ts +33 -23
  45. package/lib/esm/tree-widget-react/components/trees/common/Utils.js +60 -47
  46. package/lib/esm/tree-widget-react/components/trees/common/Utils.js.map +1 -1
  47. package/lib/esm/tree-widget-react/components/trees/common/components/BaseTreeRenderer.js +3 -3
  48. package/lib/esm/tree-widget-react/components/trees/common/components/BaseTreeRenderer.js.map +1 -1
  49. package/lib/esm/tree-widget-react/components/trees/common/components/Delayed.d.ts +1 -0
  50. package/lib/esm/tree-widget-react/components/trees/common/components/Delayed.js +1 -0
  51. package/lib/esm/tree-widget-react/components/trees/common/components/Delayed.js.map +1 -1
  52. package/lib/esm/tree-widget-react/components/trees/common/components/ProgressOverlay.d.ts +1 -0
  53. package/lib/esm/tree-widget-react/components/trees/common/components/ProgressOverlay.js +1 -0
  54. package/lib/esm/tree-widget-react/components/trees/common/components/ProgressOverlay.js.map +1 -1
  55. package/lib/esm/tree-widget-react/components/trees/common/components/Tree.css +2 -1
  56. package/lib/esm/tree-widget-react/components/trees/common/components/Tree.js +4 -4
  57. package/lib/esm/tree-widget-react/components/trees/common/components/Tree.js.map +1 -1
  58. package/lib/esm/tree-widget-react/components/trees/common/components/UseVisibilityButtonHandler.d.ts +1 -0
  59. package/lib/esm/tree-widget-react/components/trees/common/components/UseVisibilityButtonHandler.js +1 -0
  60. package/lib/esm/tree-widget-react/components/trees/common/components/UseVisibilityButtonHandler.js.map +1 -1
  61. package/lib/esm/tree-widget-react/components/trees/common/components/VisibilityTree.js +1 -1
  62. package/lib/esm/tree-widget-react/components/trees/common/components/VisibilityTree.js.map +1 -1
  63. package/lib/esm/tree-widget-react/components/trees/common/components/VisibilityTreeRenderer.js.map +1 -1
  64. package/lib/esm/tree-widget-react/components/trees/common/internal/AlwaysAndNeverDrawnElementInfo.d.ts +44 -0
  65. package/lib/esm/tree-widget-react/components/trees/{models-tree → common}/internal/AlwaysAndNeverDrawnElementInfo.js +81 -31
  66. package/lib/esm/tree-widget-react/components/trees/common/internal/AlwaysAndNeverDrawnElementInfo.js.map +1 -0
  67. package/lib/esm/tree-widget-react/components/trees/common/internal/ClassNameDefinitions.d.ts +33 -0
  68. package/lib/esm/tree-widget-react/components/trees/common/internal/ClassNameDefinitions.js +37 -0
  69. package/lib/esm/tree-widget-react/components/trees/common/internal/ClassNameDefinitions.js.map +1 -0
  70. package/lib/esm/tree-widget-react/components/trees/common/internal/ModelCategoryElementsCountCache.d.ts +16 -0
  71. package/lib/esm/tree-widget-react/components/trees/common/internal/ModelCategoryElementsCountCache.js +72 -0
  72. package/lib/esm/tree-widget-react/components/trees/common/internal/ModelCategoryElementsCountCache.js.map +1 -0
  73. package/lib/esm/tree-widget-react/components/trees/common/{Rxjs.d.ts → internal/Rxjs.d.ts} +9 -2
  74. package/lib/esm/tree-widget-react/components/trees/common/{Rxjs.js → internal/Rxjs.js} +9 -2
  75. package/lib/esm/tree-widget-react/components/trees/common/internal/Rxjs.js.map +1 -0
  76. package/lib/esm/tree-widget-react/components/trees/common/{Tooltip.d.ts → internal/Tooltip.d.ts} +5 -1
  77. package/lib/esm/tree-widget-react/components/trees/common/{Tooltip.js → internal/Tooltip.js} +7 -1
  78. package/lib/esm/tree-widget-react/components/trees/common/internal/Tooltip.js.map +1 -0
  79. package/lib/esm/tree-widget-react/components/trees/common/internal/Types.d.ts +14 -0
  80. package/lib/esm/tree-widget-react/components/trees/{categories-tree/internal/ClassNameDefinitions.js → common/internal/Types.js} +2 -7
  81. package/lib/esm/tree-widget-react/components/trees/common/internal/Types.js.map +1 -0
  82. package/lib/esm/tree-widget-react/components/trees/common/internal/UseActiveViewport.js.map +1 -0
  83. package/lib/esm/tree-widget-react/components/trees/common/{UseHierarchiesLocalization.d.ts → internal/UseHierarchiesLocalization.d.ts} +1 -0
  84. package/lib/esm/tree-widget-react/components/trees/common/{UseHierarchiesLocalization.js → internal/UseHierarchiesLocalization.js} +6 -2
  85. package/lib/esm/tree-widget-react/components/trees/common/internal/UseHierarchiesLocalization.js.map +1 -0
  86. package/lib/esm/tree-widget-react/components/trees/common/{UseHierarchyFiltering.d.ts → internal/UseHierarchyFiltering.d.ts} +1 -0
  87. package/lib/esm/tree-widget-react/components/trees/common/{UseHierarchyFiltering.js → internal/UseHierarchyFiltering.js} +4 -3
  88. package/lib/esm/tree-widget-react/components/trees/common/internal/UseHierarchyFiltering.js.map +1 -0
  89. package/lib/esm/tree-widget-react/components/trees/common/{UseIModelChangeListener.d.ts → internal/UseIModelChangeListener.d.ts} +1 -0
  90. package/lib/esm/tree-widget-react/components/trees/common/{UseIModelChangeListener.js → internal/UseIModelChangeListener.js} +1 -0
  91. package/lib/esm/tree-widget-react/components/trees/common/internal/UseIModelChangeListener.js.map +1 -0
  92. package/lib/esm/tree-widget-react/components/trees/common/internal/Utils.d.ts +47 -0
  93. package/lib/esm/tree-widget-react/components/trees/common/internal/Utils.js +101 -0
  94. package/lib/esm/tree-widget-react/components/trees/common/internal/Utils.js.map +1 -0
  95. package/lib/esm/tree-widget-react/components/trees/common/internal/VisibilityChangeEventListener.d.ts +20 -0
  96. package/lib/esm/tree-widget-react/components/trees/{models-tree → common}/internal/VisibilityChangeEventListener.js +17 -9
  97. package/lib/esm/tree-widget-react/components/trees/common/internal/VisibilityChangeEventListener.js.map +1 -0
  98. package/lib/esm/tree-widget-react/components/trees/common/internal/VisibilityUtils.d.ts +82 -0
  99. package/lib/esm/tree-widget-react/components/trees/common/internal/VisibilityUtils.js +234 -0
  100. package/lib/esm/tree-widget-react/components/trees/common/internal/VisibilityUtils.js.map +1 -0
  101. package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTree.js.map +1 -1
  102. package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTreeComponent.js.map +1 -1
  103. package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTreeDefinition.d.ts +1 -0
  104. package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTreeDefinition.js +1 -0
  105. package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTreeDefinition.js.map +1 -1
  106. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTree.d.ts +3 -1
  107. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTree.js +13 -9
  108. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTree.js.map +1 -1
  109. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTreeComponent.d.ts +1 -1
  110. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTreeComponent.js.map +1 -1
  111. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTreeDefinition.d.ts +13 -0
  112. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTreeDefinition.js +39 -38
  113. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTreeDefinition.js.map +1 -1
  114. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/internal/IModelContentTreeIdsCache.d.ts +5 -5
  115. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/internal/IModelContentTreeIdsCache.js +25 -24
  116. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/internal/IModelContentTreeIdsCache.js.map +1 -1
  117. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeButtons.js +9 -5
  118. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeButtons.js.map +1 -1
  119. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeComponent.js +1 -1
  120. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeComponent.js.map +1 -1
  121. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.d.ts +7 -2
  122. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js +73 -70
  123. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js.map +1 -1
  124. package/lib/esm/tree-widget-react/components/trees/models-tree/UseModelsTree.js +47 -29
  125. package/lib/esm/tree-widget-react/components/trees/models-tree/UseModelsTree.js.map +1 -1
  126. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/FilteredTree.d.ts +7 -9
  127. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/FilteredTree.js +4 -6
  128. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/FilteredTree.js.map +1 -1
  129. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.d.ts +4 -5
  130. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js +54 -104
  131. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js.map +1 -1
  132. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.d.ts +0 -26
  133. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js +75 -291
  134. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js.map +1 -1
  135. package/lib/public/locales/en/TreeWidget.json +51 -6
  136. package/package.json +17 -18
  137. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.d.ts +0 -37
  138. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.js +0 -214
  139. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.js.map +0 -1
  140. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/ClassNameDefinitions.d.ts +0 -7
  141. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/ClassNameDefinitions.js.map +0 -1
  142. package/lib/esm/tree-widget-react/components/trees/common/Rxjs.js.map +0 -1
  143. package/lib/esm/tree-widget-react/components/trees/common/Tooltip.js.map +0 -1
  144. package/lib/esm/tree-widget-react/components/trees/common/UseActiveViewport.js.map +0 -1
  145. package/lib/esm/tree-widget-react/components/trees/common/UseFiltering.d.ts +0 -11
  146. package/lib/esm/tree-widget-react/components/trees/common/UseFiltering.js +0 -24
  147. package/lib/esm/tree-widget-react/components/trees/common/UseFiltering.js.map +0 -1
  148. package/lib/esm/tree-widget-react/components/trees/common/UseHierarchiesLocalization.js.map +0 -1
  149. package/lib/esm/tree-widget-react/components/trees/common/UseHierarchyFiltering.js.map +0 -1
  150. package/lib/esm/tree-widget-react/components/trees/common/UseIModelChangeListener.js.map +0 -1
  151. package/lib/esm/tree-widget-react/components/trees/models-tree/Utils.d.ts +0 -7
  152. package/lib/esm/tree-widget-react/components/trees/models-tree/Utils.js +0 -21
  153. package/lib/esm/tree-widget-react/components/trees/models-tree/Utils.js.map +0 -1
  154. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/AlwaysAndNeverDrawnElementInfo.d.ts +0 -29
  155. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/AlwaysAndNeverDrawnElementInfo.js.map +0 -1
  156. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/VisibilityChangeEventListener.d.ts +0 -12
  157. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/VisibilityChangeEventListener.js.map +0 -1
  158. /package/lib/esm/tree-widget-react/components/trees/common/{UseActiveViewport.d.ts → internal/UseActiveViewport.d.ts} +0 -0
  159. /package/lib/esm/tree-widget-react/components/trees/common/{UseActiveViewport.js → internal/UseActiveViewport.js} +0 -0
@@ -0,0 +1,785 @@
1
+ /*---------------------------------------------------------------------------------------------
2
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
3
+ * See LICENSE.md in the project root for license terms and full copyright notice.
4
+ *--------------------------------------------------------------------------------------------*/
5
+ import { concat, concatAll, defaultIfEmpty, defer, EMPTY, filter, firstValueFrom, forkJoin, from, fromEventPattern, map, merge, mergeAll, mergeMap, of, reduce, shareReplay, startWith, Subject, take, takeUntil, tap, toArray, } from "rxjs";
6
+ import { assert, Id64 } from "@itwin/core-bentley";
7
+ import { PerModelCategoryVisibility } from "@itwin/core-frontend";
8
+ import { HierarchyNode, HierarchyNodeKey } from "@itwin/presentation-hierarchies";
9
+ import { AlwaysAndNeverDrawnElementInfo } from "../../common/internal/AlwaysAndNeverDrawnElementInfo.js";
10
+ import { toVoidPromise } from "../../common/internal/Rxjs.js";
11
+ import { createVisibilityStatus, getTooltipOptions } from "../../common/internal/Tooltip.js";
12
+ import { getClassesByView, getDistinctMapValues, releaseMainThreadOnItemsCount, setDifference, setIntersection } from "../../common/internal/Utils.js";
13
+ import { createVisibilityChangeEventListener } from "../../common/internal/VisibilityChangeEventListener.js";
14
+ import { changeElementStateNoChildrenOperator, enableCategoryDisplay, enableSubCategoryDisplay, filterSubModeledElementIds, getElementOverriddenVisibility, getElementVisibility, getSubModeledElementsVisibilityStatus, getVisibilityFromAlwaysAndNeverDrawnElementsImpl, mergeVisibilityStatuses, } from "../../common/internal/VisibilityUtils.js";
15
+ import { createVisibilityHandlerResult } from "../../common/UseHierarchyVisibility.js";
16
+ import { CategoriesTreeNode } from "./CategoriesTreeNode.js";
17
+ import { createFilteredTree, parseCategoryKey, parseSubCategoryKey } from "./FilteredTree.js";
18
+ /**
19
+ * Creates an instance if `CategoriesTreeVisibilityHandler`.
20
+ * @internal
21
+ */
22
+ export function createCategoriesTreeVisibilityHandler(props) {
23
+ return new CategoriesTreeVisibilityHandlerImpl(props);
24
+ }
25
+ class CategoriesTreeVisibilityHandlerImpl {
26
+ constructor(_props) {
27
+ this._props = _props;
28
+ this._elementChangeQueue = new Subject();
29
+ this._subscriptions = [];
30
+ this._changeRequest = new Subject();
31
+ this._eventListener = createVisibilityChangeEventListener({
32
+ viewport: _props.viewport,
33
+ listeners: {
34
+ models: _props.hierarchyConfig.showElements,
35
+ categories: true,
36
+ elements: _props.hierarchyConfig.showElements,
37
+ displayStyle: true,
38
+ },
39
+ });
40
+ this._alwaysAndNeverDrawnElements = new AlwaysAndNeverDrawnElementInfo(_props.viewport);
41
+ this._idsCache = this._props.idsCache;
42
+ const { categoryClass, elementClass, modelClass } = getClassesByView(_props.viewport.view.is2d() ? "2d" : "3d");
43
+ if (_props.filteredPaths) {
44
+ this._filteredTree = createFilteredTree({
45
+ idsCache: this._idsCache,
46
+ filteringPaths: _props.filteredPaths,
47
+ categoryClassName: categoryClass,
48
+ categoryElementClassName: elementClass,
49
+ categoryModelClassName: modelClass,
50
+ imodelAccess: this._props.imodelAccess,
51
+ });
52
+ }
53
+ this._subscriptions.push(this._elementChangeQueue.pipe(concatAll()).subscribe());
54
+ }
55
+ get onVisibilityChange() {
56
+ return this._eventListener.onVisibilityChange;
57
+ }
58
+ async getVisibilityStatus(node) {
59
+ return firstValueFrom(this.getVisibilityStatusObs(node).pipe(
60
+ // unsubscribe from the observable if the change request for this node is received
61
+ takeUntil(this._changeRequest.pipe(filter(({ key, depth }) => depth === node.parentKeys.length && HierarchyNodeKey.equals(node.key, key)))),
62
+ // unsubscribe if visibility changes
63
+ takeUntil(fromEventPattern((handler) => {
64
+ this._eventListener.onVisibilityChange.addListener(handler);
65
+ }, (handler) => {
66
+ this._eventListener.onVisibilityChange.removeListener(handler);
67
+ })), defaultIfEmpty(createVisibilityStatus("hidden"))));
68
+ }
69
+ async changeVisibility(node, shouldDisplay) {
70
+ // notify about new change request
71
+ this._changeRequest.next({ key: node.key, depth: node.parentKeys.length });
72
+ const changeObservable = this.changeVisibilityObs(node, shouldDisplay).pipe(
73
+ // unsubscribe from the observable if the change request for this node is received
74
+ takeUntil(this._changeRequest.pipe(filter(({ key, depth }) => depth === node.parentKeys.length && HierarchyNodeKey.equals(node.key, key)))), tap({
75
+ subscribe: () => {
76
+ this._eventListener.suppressChangeEvents();
77
+ this._alwaysAndNeverDrawnElements.suppressChangeEvents();
78
+ },
79
+ finalize: () => {
80
+ this._eventListener.resumeChangeEvents();
81
+ this._alwaysAndNeverDrawnElements.resumeChangeEvents();
82
+ },
83
+ }));
84
+ return toVoidPromise(changeObservable);
85
+ }
86
+ dispose() {
87
+ this[Symbol.dispose]();
88
+ }
89
+ [Symbol.dispose]() {
90
+ this._eventListener[Symbol.dispose]();
91
+ this._alwaysAndNeverDrawnElements[Symbol.dispose]();
92
+ this._subscriptions.forEach((x) => x.unsubscribe());
93
+ }
94
+ getVisibilityStatusObs(node) {
95
+ if (node.filtering?.filteredChildrenIdentifierPaths?.length && !node.filtering.isFilterTarget) {
96
+ return this.getFilteredNodeVisibility({ node });
97
+ }
98
+ if (HierarchyNode.isClassGroupingNode(node)) {
99
+ return this.getClassGroupingNodeDisplayStatus(node);
100
+ }
101
+ if (!HierarchyNode.isInstancesNode(node)) {
102
+ return of(createVisibilityStatus("disabled"));
103
+ }
104
+ if (CategoriesTreeNode.isDefinitionContainerNode(node)) {
105
+ return this.getDefinitionContainerDisplayStatus({
106
+ definitionContainerIds: node.key.instanceKeys.map((instanceKey) => instanceKey.id),
107
+ });
108
+ }
109
+ if (CategoriesTreeNode.isModelNode(node)) {
110
+ return this.getModelVisibilityStatus({
111
+ modelId: node.key.instanceKeys[0].id,
112
+ });
113
+ }
114
+ if (CategoriesTreeNode.isCategoryNode(node)) {
115
+ return this.getCategoryDisplayStatus({
116
+ categoryIds: node.key.instanceKeys.map((instanceKey) => instanceKey.id),
117
+ modelId: CategoriesTreeNode.getModelId(node),
118
+ ignoreSubCategories: node.extendedData?.isCategoryOfSubModel,
119
+ });
120
+ }
121
+ const categoryId = CategoriesTreeNode.getCategoryId(node);
122
+ if (!categoryId) {
123
+ return of(createVisibilityStatus("disabled"));
124
+ }
125
+ if (CategoriesTreeNode.isSubCategoryNode(node)) {
126
+ return this.getSubCategoryDisplayStatus({
127
+ categoryId,
128
+ subCategoryIds: node.key.instanceKeys.map((instanceKey) => instanceKey.id),
129
+ });
130
+ }
131
+ const modelId = CategoriesTreeNode.getModelId(node);
132
+ if (!modelId) {
133
+ return of(createVisibilityStatus("disabled"));
134
+ }
135
+ return this.getElementDisplayStatus({
136
+ elementId: node.key.instanceKeys[0].id,
137
+ modelId,
138
+ categoryId,
139
+ });
140
+ }
141
+ getFilteredNodeVisibility(props) {
142
+ return from(this.getVisibilityChangeTargets(props)).pipe(mergeMap(({ definitionContainerIds: definitionContainers, subCategories, modelIds: models, categories, elements }) => {
143
+ const observables = new Array();
144
+ if (definitionContainers?.size) {
145
+ observables.push(from(definitionContainers).pipe(mergeMap((definitionContainerId) => this.getDefinitionContainerDisplayStatus({ definitionContainerIds: [definitionContainerId], ignoreTooltip: true }))));
146
+ }
147
+ if (models?.size) {
148
+ observables.push(from(models).pipe(mergeMap((modelId) => this.getModelVisibilityStatus({ modelId }))));
149
+ }
150
+ if (categories?.size) {
151
+ observables.push(from(categories).pipe(mergeMap((key) => {
152
+ const { modelId, categoryId } = parseCategoryKey(key);
153
+ return this.getCategoryDisplayStatus({ ignoreTooltip: true, ignoreSubCategories: !!modelId, modelId, categoryIds: [categoryId] });
154
+ })));
155
+ }
156
+ if (subCategories?.size) {
157
+ observables.push(from(subCategories).pipe(mergeMap((key) => {
158
+ const { subCategoryId, categoryId } = parseSubCategoryKey(key);
159
+ return this.getSubCategoryDisplayStatus({ subCategoryIds: [subCategoryId], categoryId, ignoreTooltip: true });
160
+ })));
161
+ }
162
+ if (elements?.size) {
163
+ observables.push(from(elements).pipe(releaseMainThreadOnItemsCount(50), mergeMap(([categoryKey, elementIds]) => {
164
+ const { modelId, categoryId } = parseCategoryKey(categoryKey);
165
+ assert(modelId !== undefined);
166
+ return from(elementIds).pipe(releaseMainThreadOnItemsCount(1000), mergeMap((elementId) => this.getElementDisplayStatus({ modelId, categoryId, elementId, ignoreTooltip: true })));
167
+ })));
168
+ }
169
+ return merge(...observables);
170
+ }), mergeVisibilityStatuses({ visible: undefined, hidden: undefined, partial: undefined }));
171
+ }
172
+ getModelVisibilityStatus({ modelId }) {
173
+ const result = defer(() => {
174
+ const viewport = this._props.viewport;
175
+ if (!viewport.view.viewsModel(modelId)) {
176
+ return from(this._idsCache.getModelCategoryIds(modelId)).pipe(mergeMap((categoryIds) => from(this._idsCache.getCategoriesModeledElements(modelId, categoryIds))), getSubModeledElementsVisibilityStatus({
177
+ ignoreTooltips: true,
178
+ tooltips: { visible: undefined, hidden: undefined, partial: undefined },
179
+ parentNodeVisibilityStatus: createVisibilityStatus("hidden"),
180
+ getModelVisibilityStatus: (modelProps) => this.getModelVisibilityStatus(modelProps),
181
+ }));
182
+ }
183
+ return from(this._idsCache.getModelCategoryIds(modelId)).pipe(mergeAll(), mergeMap((categoryId) => this.getCategoryDisplayStatus({ modelId, categoryIds: [categoryId], ignoreSubCategories: true, ignoreTooltip: true })), mergeVisibilityStatuses({
184
+ visible: undefined,
185
+ hidden: undefined,
186
+ partial: undefined,
187
+ }, true));
188
+ });
189
+ return createVisibilityHandlerResult(this, { id: modelId }, result, undefined);
190
+ }
191
+ getDefinitionContainerDisplayStatus(props) {
192
+ const result = defer(() => {
193
+ return from(this._idsCache.getAllContainedCategories(props.definitionContainerIds)).pipe(mergeAll(), mergeMap((categoryId) => {
194
+ return this.getCategoryDisplayStatus({ categoryIds: [categoryId], ignoreTooltip: true });
195
+ }), mergeVisibilityStatuses({
196
+ visible: "categoriesTree.definitionContainer.visibleThroughCategories",
197
+ hidden: "categoriesTree.definitionContainer.hiddenThroughCategories",
198
+ partial: "categoriesTree.definitionContainer.partialThroughCategories",
199
+ }));
200
+ });
201
+ return createVisibilityHandlerResult(this, props, result, undefined);
202
+ }
203
+ getSubCategoryDisplayStatus(props) {
204
+ const result = defer(() => {
205
+ const { categoryId, subCategoryIds, ignoreTooltip } = props;
206
+ const categoryOverrideResult = this.getCategoryVisibilityFromOverrides([categoryId], ignoreTooltip);
207
+ if (categoryOverrideResult !== "none" && (categoryOverrideResult.state === "hidden" || categoryOverrideResult.state === "visible")) {
208
+ return of(createVisibilityStatus(categoryOverrideResult.state, getTooltipOptions(`categoriesTree.subCategory.${categoryOverrideResult.state}ThroughCategoryOverride`)));
209
+ }
210
+ if (!this._props.viewport.view.viewsCategory(categoryId)) {
211
+ return of(createVisibilityStatus("hidden", getTooltipOptions("categoriesTree.subCategory.hiddenThroughCategory", ignoreTooltip)));
212
+ }
213
+ let visibleCount = 0;
214
+ let hiddenCount = 0;
215
+ for (const subCategoryId of subCategoryIds) {
216
+ const isVisible = this._props.viewport.isSubCategoryVisible(subCategoryId);
217
+ if (isVisible) {
218
+ ++visibleCount;
219
+ }
220
+ else {
221
+ ++hiddenCount;
222
+ }
223
+ if (visibleCount > 0 && hiddenCount > 0) {
224
+ return of(createVisibilityStatus("partial", getTooltipOptions("categoriesTree.subCategory.partialThroughSubCategory", ignoreTooltip)));
225
+ }
226
+ }
227
+ return of(visibleCount > 0 ? createVisibilityStatus("visible") : createVisibilityStatus("hidden"));
228
+ });
229
+ return createVisibilityHandlerResult(this, props, result, undefined);
230
+ }
231
+ getCategoryVisibilityFromOverrides(categoryIds, ignoreTooltip) {
232
+ let showOverrides = 0;
233
+ let hideOverrides = 0;
234
+ for (const currentOverride of this._props.viewport.perModelCategoryVisibility) {
235
+ if (categoryIds.includes(currentOverride.categoryId)) {
236
+ if (currentOverride.visible) {
237
+ ++showOverrides;
238
+ }
239
+ else {
240
+ ++hideOverrides;
241
+ }
242
+ if (showOverrides > 0 && hideOverrides > 0) {
243
+ return createVisibilityStatus("partial", getTooltipOptions("categoriesTree.category.partialThroughOverrides", ignoreTooltip));
244
+ }
245
+ }
246
+ }
247
+ if (showOverrides === 0 && hideOverrides === 0) {
248
+ return "none";
249
+ }
250
+ const visibility = showOverrides > 0 ? "visible" : "hidden";
251
+ return createVisibilityStatus(visibility, getTooltipOptions(`categoriesTree.category.${visibility}ThroughOverrides`, ignoreTooltip));
252
+ }
253
+ getDefaultModelsCategoryVisibilityStatus({ modelId, categoryIds, ignoreTooltip, }) {
254
+ const viewport = this._props.viewport;
255
+ if (!viewport.view.viewsModel(modelId)) {
256
+ return createVisibilityStatus("hidden", getTooltipOptions("categoriesTree.category.hiddenThroughModel", ignoreTooltip));
257
+ }
258
+ let visibleCount = 0;
259
+ let hiddenCount = 0;
260
+ let visibleThroughCategorySelectorCount = 0;
261
+ for (const categoryId of categoryIds) {
262
+ if (viewport.view.viewsCategory(categoryId)) {
263
+ ++visibleThroughCategorySelectorCount;
264
+ }
265
+ const override = this._props.viewport.perModelCategoryVisibility.getOverride(modelId, categoryId);
266
+ if (override === PerModelCategoryVisibility.Override.Show) {
267
+ ++visibleCount;
268
+ continue;
269
+ }
270
+ if (override === PerModelCategoryVisibility.Override.Hide) {
271
+ ++hiddenCount;
272
+ continue;
273
+ }
274
+ if (visibleCount > 0 && hiddenCount > 0) {
275
+ return createVisibilityStatus("partial", getTooltipOptions("categoriesTree.category.partialThroughOverrides", ignoreTooltip));
276
+ }
277
+ }
278
+ if (hiddenCount + visibleCount > 0) {
279
+ const overridenVisibility = hiddenCount > 0 ? "hidden" : "visible";
280
+ return createVisibilityStatus(overridenVisibility, getTooltipOptions(`categoriesTree.category.${overridenVisibility}ThroughOverrides`, ignoreTooltip));
281
+ }
282
+ const visbility = visibleThroughCategorySelectorCount > 0 ? "visible" : "hidden";
283
+ return createVisibilityStatus(visbility, getTooltipOptions(`categoriesTree.category.${visbility}ThroughCategorySelector`, ignoreTooltip));
284
+ }
285
+ async getDefaultCategoryVisibilityStatus({ categoryIds, ignoreTooltip, ignoreSubCategories, }) {
286
+ const overrideResult = this.getCategoryVisibilityFromOverrides(categoryIds);
287
+ if (overrideResult !== "none") {
288
+ return overrideResult;
289
+ }
290
+ let hiddenCount = 0;
291
+ for (const categoryId of categoryIds) {
292
+ const isVisible = this._props.viewport.view.viewsCategory(categoryId);
293
+ if (!isVisible) {
294
+ ++hiddenCount;
295
+ }
296
+ }
297
+ if (hiddenCount > 0 || this._props.hierarchyConfig.hideSubCategories || ignoreSubCategories) {
298
+ const visibility = hiddenCount > 0 ? "hidden" : "visible";
299
+ return createVisibilityStatus(visibility, getTooltipOptions(`categoriesTree.category.${visibility}ThroughCategorySelector`, ignoreTooltip));
300
+ }
301
+ const subCategories = getDistinctMapValues(await this._idsCache.getSubCategories(categoryIds));
302
+ let visibleSubCategoryCount = 0;
303
+ let hiddenSubCategoryCount = 0;
304
+ for (const subCategory of subCategories) {
305
+ const isVisible = this._props.viewport.isSubCategoryVisible(subCategory);
306
+ if (isVisible) {
307
+ ++visibleSubCategoryCount;
308
+ }
309
+ else {
310
+ ++hiddenSubCategoryCount;
311
+ }
312
+ if (hiddenSubCategoryCount > 0 && visibleSubCategoryCount > 0) {
313
+ return createVisibilityStatus("partial", getTooltipOptions("categoriesTree.category.partialThroughSubCategories", ignoreTooltip));
314
+ }
315
+ }
316
+ const subCategoryVisiblity = hiddenSubCategoryCount > 0 ? "hidden" : "visible";
317
+ const reason = subCategories.size > 0 ? "ThroughSubCategories" : "ThroughCategorySelector";
318
+ return createVisibilityStatus(subCategoryVisiblity, getTooltipOptions(`categoriesTree.category.${subCategoryVisiblity}${reason}`, ignoreTooltip));
319
+ }
320
+ getCategoryDisplayStatus({ ignoreTooltip, ...props }) {
321
+ const result = defer(() => {
322
+ if (!this._props.hierarchyConfig.showElements) {
323
+ return from(this.getDefaultCategoryVisibilityStatus({ categoryIds: props.categoryIds, ignoreTooltip }));
324
+ }
325
+ const modelsObservable = props.modelId
326
+ ? of(new Map(props.categoryIds.map((id) => [id, [props.modelId]])))
327
+ : from(this._idsCache.getCategoriesElementModels(props.categoryIds));
328
+ return merge(
329
+ // get visibility status from always and never drawn elements
330
+ this._props.hierarchyConfig.showElements
331
+ ? modelsObservable.pipe(mergeMap((categoryModelsMap) => {
332
+ if (categoryModelsMap.size === 0) {
333
+ return props.modelId
334
+ ? of(this.getDefaultModelsCategoryVisibilityStatus({ modelId: props.modelId, categoryIds: props.categoryIds, ignoreTooltip }))
335
+ : from(this.getDefaultCategoryVisibilityStatus({ categoryIds: props.categoryIds, ignoreTooltip }));
336
+ }
337
+ return from(categoryModelsMap).pipe(mergeMap(([category, models]) => from(models).pipe(mergeMap((model) => {
338
+ if (this._props.viewport.view.viewsModel(model)) {
339
+ return this.getVisibilityFromAlwaysAndNeverDrawnElements({
340
+ queryProps: props,
341
+ tooltips: {
342
+ allElementsInAlwaysDrawnList: "categoriesTree.category.allElementsVisible",
343
+ allElementsInNeverDrawnList: "categoriesTree.category.allElementsHidden",
344
+ elementsInBothAlwaysAndNeverDrawn: "categoriesTree.category.someElementsAreHidden",
345
+ noElementsInExclusiveAlwaysDrawnList: "categoriesTree.category.allElementsHidden",
346
+ },
347
+ defaultStatus: () => this.getDefaultModelsCategoryVisibilityStatus({ modelId: model, categoryIds: [category], ignoreTooltip }),
348
+ ignoreTooltip: true,
349
+ }).pipe(mergeMap((visibilityStatusAlwaysAndNeverDraw) => {
350
+ return from(this._idsCache.getCategoriesModeledElements(model, [category])).pipe(getSubModeledElementsVisibilityStatus({
351
+ tooltips: {
352
+ visible: undefined,
353
+ hidden: undefined,
354
+ partial: undefined,
355
+ },
356
+ parentNodeVisibilityStatus: visibilityStatusAlwaysAndNeverDraw,
357
+ ignoreTooltips: true,
358
+ getModelVisibilityStatus: (modelProps) => this.getModelVisibilityStatus(modelProps),
359
+ }));
360
+ }));
361
+ }
362
+ return from(this._idsCache.getCategoriesModeledElements(model, [category])).pipe(getSubModeledElementsVisibilityStatus({
363
+ tooltips: {
364
+ visible: undefined,
365
+ hidden: undefined,
366
+ partial: undefined,
367
+ },
368
+ parentNodeVisibilityStatus: createVisibilityStatus("hidden"),
369
+ ignoreTooltips: true,
370
+ getModelVisibilityStatus: (modelProps) => this.getModelVisibilityStatus(modelProps),
371
+ }));
372
+ }), mergeVisibilityStatuses({ visible: undefined, hidden: undefined, partial: undefined }))), mergeVisibilityStatuses({
373
+ visible: "categoriesTree.category.allElementsVisible",
374
+ hidden: "categoriesTree.category.allElementsHidden",
375
+ partial: "categoriesTree.category.someElementsHidden",
376
+ }, ignoreTooltip));
377
+ }), map((visibilityStatus) => {
378
+ return { visibilityStatus, type: 0 };
379
+ }))
380
+ : EMPTY,
381
+ // get category status
382
+ (props.modelId
383
+ ? of(this.getDefaultModelsCategoryVisibilityStatus({ modelId: props.modelId, categoryIds: props.categoryIds, ignoreTooltip }))
384
+ : from(this.getDefaultCategoryVisibilityStatus({ categoryIds: props.categoryIds, ignoreTooltip }))).pipe(map((visibilityStatus) => {
385
+ return { visibilityStatus, type: 1 };
386
+ }))).pipe(toArray(), mergeMap(async (visibilityStatusesInfo) => {
387
+ let defaultStatus;
388
+ let alwaysNeverDrawStatus;
389
+ visibilityStatusesInfo.forEach((visibilityStatusInfo) => {
390
+ switch (visibilityStatusInfo.type) {
391
+ case 0:
392
+ alwaysNeverDrawStatus = visibilityStatusInfo.visibilityStatus;
393
+ break;
394
+ case 1:
395
+ defaultStatus = visibilityStatusInfo.visibilityStatus;
396
+ break;
397
+ }
398
+ });
399
+ assert(defaultStatus !== undefined);
400
+ if (defaultStatus.state === "partial") {
401
+ return defaultStatus;
402
+ }
403
+ // This can happen if:
404
+ // a) showElements is set to false
405
+ // b) root category does not have any elements (that dont have Parent)
406
+ // In both cases we don't need to look at modeled elements visibility
407
+ if (alwaysNeverDrawStatus === undefined) {
408
+ return defaultStatus;
409
+ }
410
+ // In cases where
411
+ // a) SubCategories are hidden
412
+ // b) Category needs to ignore subCategories
413
+ // c) Category has model (it means that category is under hidden subModel)
414
+ // We dont need to look at default category status, it is already accounted for in always/never drawn visibility
415
+ if (this._props.hierarchyConfig.hideSubCategories || props.ignoreSubCategories || props.modelId) {
416
+ return alwaysNeverDrawStatus;
417
+ }
418
+ if ((await this._idsCache.getSubCategories(props.categoryIds)).size === 0) {
419
+ return alwaysNeverDrawStatus;
420
+ }
421
+ if (alwaysNeverDrawStatus.state === "partial") {
422
+ return createVisibilityStatus("partial", getTooltipOptions("categoriesTree.category.someChildrenVisible", ignoreTooltip));
423
+ }
424
+ if (alwaysNeverDrawStatus.state === "hidden") {
425
+ if (defaultStatus.state === "hidden") {
426
+ return createVisibilityStatus("hidden", getTooltipOptions("categoriesTree.category.allChildrenHidden", ignoreTooltip));
427
+ }
428
+ return createVisibilityStatus("partial", getTooltipOptions("categoriesTree.category.partialThroughSubCategories", ignoreTooltip));
429
+ }
430
+ if (defaultStatus.state === "hidden") {
431
+ return createVisibilityStatus("partial", getTooltipOptions("categoriesTree.category.someChildrenVisible", ignoreTooltip));
432
+ }
433
+ return createVisibilityStatus("visible", getTooltipOptions("categoriesTree.category.allChildrenVisible", ignoreTooltip));
434
+ }));
435
+ });
436
+ return createVisibilityHandlerResult(this, props, result, undefined);
437
+ }
438
+ getClassGroupingNodeDisplayStatus(node) {
439
+ const result = defer(() => {
440
+ const info = this.getGroupingNodeInfo(node);
441
+ const { modelElementsMap, categoryId } = info;
442
+ return from(modelElementsMap).pipe(mergeMap(([modelId, elementIds]) => {
443
+ if (!this._props.viewport.view.viewsModel(modelId)) {
444
+ return of([...elementIds]).pipe(filterSubModeledElementIds({ doesSubModelExist: async (id) => this._idsCache.hasSubModel(id) }), getSubModeledElementsVisibilityStatus({
445
+ tooltips: {
446
+ visible: undefined,
447
+ hidden: undefined,
448
+ partial: undefined,
449
+ },
450
+ parentNodeVisibilityStatus: createVisibilityStatus("hidden"),
451
+ getModelVisibilityStatus: (modelProps) => this.getModelVisibilityStatus(modelProps),
452
+ }));
453
+ }
454
+ return this.getVisibilityFromAlwaysAndNeverDrawnElements({
455
+ elements: elementIds,
456
+ defaultStatus: () => {
457
+ const status = this.getDefaultModelsCategoryVisibilityStatus({ categoryIds: [categoryId], modelId, ignoreTooltip: true });
458
+ return createVisibilityStatus(status.state, getTooltipOptions(`categoriesTree.groupingNode.${status.state}ThroughCategory`));
459
+ },
460
+ tooltips: {
461
+ allElementsInAlwaysDrawnList: "categoriesTree.groupingNode.allElementsVisible",
462
+ allElementsInNeverDrawnList: "categoriesTree.groupingNode.allElementsHidden",
463
+ elementsInBothAlwaysAndNeverDrawn: "categoriesTree.groupingNode.someElementsAreHidden",
464
+ noElementsInExclusiveAlwaysDrawnList: "categoriesTree.groupingNode.allElementsHidden",
465
+ },
466
+ }).pipe(mergeMap((visibilityStatusAlwaysAndNeverDraw) => {
467
+ return of([...elementIds]).pipe(filterSubModeledElementIds({ doesSubModelExist: async (id) => this._idsCache.hasSubModel(id) }), getSubModeledElementsVisibilityStatus({
468
+ tooltips: {
469
+ visible: undefined,
470
+ hidden: undefined,
471
+ partial: undefined,
472
+ },
473
+ parentNodeVisibilityStatus: visibilityStatusAlwaysAndNeverDraw,
474
+ getModelVisibilityStatus: (modelProps) => this.getModelVisibilityStatus(modelProps),
475
+ }));
476
+ }));
477
+ }), mergeVisibilityStatuses({
478
+ visible: undefined,
479
+ hidden: undefined,
480
+ partial: undefined,
481
+ }, true));
482
+ });
483
+ return createVisibilityHandlerResult(this, { node }, result, undefined);
484
+ }
485
+ getElementDisplayStatus({ ignoreTooltip, ...props }) {
486
+ const result = defer(() => {
487
+ const viewport = this._props.viewport;
488
+ const { elementId, modelId, categoryId } = props;
489
+ const viewsModel = viewport.view.viewsModel(modelId);
490
+ const elementStatus = getElementOverriddenVisibility({
491
+ elementId,
492
+ ignoreTooltip,
493
+ viewport,
494
+ tooltips: {
495
+ visibileThorughAlwaysDrawn: "categoriesTree.element.displayedThroughAlwaysDrawnList",
496
+ hiddenThroughAlwaysDrawnExclusive: "categoriesTree.element.hiddenDueToOtherElementsExclusivelyAlwaysDrawn",
497
+ hiddenThroughNeverDrawn: "categoriesTree.element.hiddenThroughNeverDrawnList",
498
+ },
499
+ });
500
+ return from(this._idsCache.hasSubModel(elementId)).pipe(mergeMap((hasSubModel) => (hasSubModel ? this.getModelVisibilityStatus({ modelId: elementId }) : of(undefined))), map((subModelVisibilityStatus) => getElementVisibility(ignoreTooltip, viewsModel, elementStatus, this.getDefaultModelsCategoryVisibilityStatus({ categoryIds: [categoryId], modelId, ignoreTooltip: true }), "categoriesTree", subModelVisibilityStatus)));
501
+ });
502
+ return createVisibilityHandlerResult(this, props, result, undefined);
503
+ }
504
+ /** Changes visibility of the items represented by the tree node. */
505
+ changeVisibilityObs(node, on) {
506
+ if (node.filtering?.filteredChildrenIdentifierPaths?.length && !node.filtering.isFilterTarget) {
507
+ return this.changeFilteredNodeVisibility({ node, on });
508
+ }
509
+ if (HierarchyNode.isClassGroupingNode(node)) {
510
+ return this.changeElementGroupingNodeState(node, on);
511
+ }
512
+ if (!HierarchyNode.isInstancesNode(node)) {
513
+ return EMPTY;
514
+ }
515
+ if (CategoriesTreeNode.isDefinitionContainerNode(node)) {
516
+ return this.changeDefinitionContainerState({
517
+ definitionContainerIds: node.key.instanceKeys.map((instanceKey) => instanceKey.id),
518
+ on,
519
+ });
520
+ }
521
+ if (CategoriesTreeNode.isModelNode(node)) {
522
+ return this.changeModelState({
523
+ ids: node.key.instanceKeys.map(({ id }) => id),
524
+ on,
525
+ });
526
+ }
527
+ if (CategoriesTreeNode.isCategoryNode(node)) {
528
+ return this.changeCategoryState({
529
+ categoryIds: node.key.instanceKeys.map((instanceKey) => instanceKey.id),
530
+ modelId: CategoriesTreeNode.getModelId(node),
531
+ on,
532
+ ignoreSubCategories: node.extendedData?.isCategoryOfSubModel,
533
+ });
534
+ }
535
+ const categoryId = CategoriesTreeNode.getCategoryId(node);
536
+ if (!categoryId) {
537
+ return EMPTY;
538
+ }
539
+ if (CategoriesTreeNode.isSubCategoryNode(node)) {
540
+ if (this._props.hierarchyConfig.hideSubCategories) {
541
+ return EMPTY;
542
+ }
543
+ return this.changeSubCategoryState({
544
+ categoryId,
545
+ subCategoryIds: node.key.instanceKeys.map((instanceKey) => instanceKey.id),
546
+ on,
547
+ });
548
+ }
549
+ if (!this._props.hierarchyConfig.showElements) {
550
+ return EMPTY;
551
+ }
552
+ const modelId = CategoriesTreeNode.getModelId(node);
553
+ if (!modelId) {
554
+ return EMPTY;
555
+ }
556
+ return this.changeElementsState({
557
+ elementIds: new Set([...node.key.instanceKeys.map(({ id }) => id)]),
558
+ modelId,
559
+ categoryId,
560
+ on,
561
+ });
562
+ }
563
+ async getVisibilityChangeTargets({ node }) {
564
+ const filteredTree = await this._filteredTree;
565
+ return filteredTree ? filteredTree.getVisibilityChangeTargets(node) : {};
566
+ }
567
+ changeFilteredNodeVisibility({ on, ...props }) {
568
+ return from(this.getVisibilityChangeTargets(props)).pipe(mergeMap(({ definitionContainerIds: definitionContainers, subCategories, modelIds: models, categories, elements }) => {
569
+ const observables = new Array();
570
+ if (definitionContainers?.size) {
571
+ observables.push(this.changeDefinitionContainerState({ definitionContainerIds: [...definitionContainers], on }));
572
+ }
573
+ if (models?.size) {
574
+ observables.push(this.changeModelState({ ids: models, on }));
575
+ }
576
+ if (categories?.size) {
577
+ observables.push(from(categories).pipe(mergeMap((key) => {
578
+ const { modelId, categoryId } = parseCategoryKey(key);
579
+ return this.changeCategoryState({ modelId, categoryIds: [categoryId], ignoreSubCategories: false, on });
580
+ })));
581
+ }
582
+ if (subCategories?.size) {
583
+ observables.push(from(subCategories).pipe(mergeMap((key) => {
584
+ const { subCategoryId, categoryId } = parseSubCategoryKey(key);
585
+ return this.changeSubCategoryState({ categoryId, subCategoryIds: [subCategoryId], on });
586
+ })));
587
+ }
588
+ if (elements?.size) {
589
+ observables.push(from(elements).pipe(mergeMap(([categoryKey, elementIds]) => {
590
+ const { modelId, categoryId } = parseCategoryKey(categoryKey);
591
+ assert(modelId !== undefined);
592
+ return this.changeElementsState({ modelId, categoryId, elementIds, on });
593
+ })));
594
+ }
595
+ return merge(...observables);
596
+ }));
597
+ }
598
+ changeModelState(props) {
599
+ const { ids, on } = props;
600
+ if (Id64.sizeOf(ids) === 0) {
601
+ return EMPTY;
602
+ }
603
+ const result = defer(() => {
604
+ const viewport = this._props.viewport;
605
+ viewport.perModelCategoryVisibility.clearOverrides(ids);
606
+ const idsObs = from(Id64.iterable(ids));
607
+ if (!on) {
608
+ viewport.changeModelDisplay(ids, false);
609
+ return idsObs.pipe(mergeMap(async (modelId) => ({ modelId, categoryIds: await this._idsCache.getModelCategoryIds(modelId) })), mergeMap(({ modelId, categoryIds }) => from(this._idsCache.getCategoriesModeledElements(modelId, categoryIds))), mergeMap((modeledElementIds) => this.changeModelState({ ids: modeledElementIds, on })));
610
+ }
611
+ return concat(from(viewport.addViewedModels(ids)), idsObs.pipe(mergeMap((modelId) => {
612
+ return from(this._idsCache.getModelCategoryIds(modelId)).pipe(mergeAll(), mergeMap((categoryId) => this.changeCategoryState({ categoryIds: [categoryId], modelId, on, ignoreSubCategories: true })));
613
+ })));
614
+ });
615
+ return createVisibilityHandlerResult(this, props, result, undefined);
616
+ }
617
+ showModelWithoutAnyCategoriesOrElements(modelId) {
618
+ const viewport = this._props.viewport;
619
+ return forkJoin({
620
+ categories: this._idsCache.getModelCategoryIds(modelId),
621
+ alwaysDrawnElements: this._alwaysAndNeverDrawnElements.getAlwaysDrawnElements({ modelId }),
622
+ }).pipe(mergeMap(async ({ categories, alwaysDrawnElements }) => {
623
+ const alwaysDrawn = this._props.viewport.alwaysDrawn;
624
+ if (alwaysDrawn && alwaysDrawnElements) {
625
+ viewport.setAlwaysDrawn(setDifference(alwaysDrawn, alwaysDrawnElements));
626
+ }
627
+ categories.forEach((categoryId) => {
628
+ this.changeCategoryStateInViewportAccordingToModelVisibility(modelId, categoryId, false, false);
629
+ });
630
+ await viewport.addViewedModels(modelId);
631
+ }));
632
+ }
633
+ changeCategoryStateInViewportAccordingToModelVisibility(modelId, categoryId, on, changeSubCategories) {
634
+ const viewport = this._props.viewport;
635
+ const isDisplayedInSelector = viewport.view.viewsCategory(categoryId);
636
+ const override = on === isDisplayedInSelector
637
+ ? PerModelCategoryVisibility.Override.None
638
+ : on
639
+ ? PerModelCategoryVisibility.Override.Show
640
+ : PerModelCategoryVisibility.Override.Hide;
641
+ viewport.perModelCategoryVisibility.setOverride(modelId, categoryId, override);
642
+ if (override === PerModelCategoryVisibility.Override.None && on) {
643
+ // we took off the override which means the category is displayed in selector, but
644
+ // doesn't mean all its subcategories are displayed - this call ensures that
645
+ viewport.changeCategoryDisplay(categoryId, true, changeSubCategories);
646
+ }
647
+ }
648
+ changeSubCategoryState(props) {
649
+ const result = defer(() => {
650
+ return concat(
651
+ // make sure parent category is enabled
652
+ props.on ? from(enableCategoryDisplay(this._props.viewport, [props.categoryId], props.on, false)) : EMPTY, from(props.subCategoryIds).pipe(map((subCategoryId) => enableSubCategoryDisplay(this._props.viewport, subCategoryId, props.on))));
653
+ });
654
+ return createVisibilityHandlerResult(this, props, result, undefined);
655
+ }
656
+ changeDefinitionContainerState(props) {
657
+ const result = defer(() => {
658
+ return from(this._idsCache.getAllContainedCategories(props.definitionContainerIds)).pipe(mergeAll(), mergeMap((categoryId) => {
659
+ return this.changeCategoryState({ categoryIds: [categoryId], on: props.on });
660
+ }));
661
+ });
662
+ return createVisibilityHandlerResult(this, props, result, undefined);
663
+ }
664
+ changeCategoryState(props) {
665
+ const result = defer(() => {
666
+ const { modelId, categoryIds, on, ignoreSubCategories } = props;
667
+ const viewport = this._props.viewport;
668
+ if (!this._props.hierarchyConfig.showElements) {
669
+ return from(enableCategoryDisplay(viewport, categoryIds, on, on));
670
+ }
671
+ const modelIdsObservable = modelId
672
+ ? of(new Map(categoryIds.map((id) => [id, [modelId]])))
673
+ : from(this._idsCache.getCategoriesElementModels(categoryIds, true));
674
+ return concat(modelId ? EMPTY : from(enableCategoryDisplay(viewport, categoryIds, on, ignoreSubCategories ? false : on)), on
675
+ ? modelIdsObservable.pipe(mergeMap((categoriesMap) => from(categoriesMap.values())), mergeAll(), filter((modelIdToCheck) => !viewport.view.viewsModel(modelIdToCheck)), mergeMap((modelIdToCheck) => this.showModelWithoutAnyCategoriesOrElements(modelIdToCheck)))
676
+ : EMPTY, modelIdsObservable.pipe(mergeMap((categoriesMap) => from(categoriesMap.entries())), mergeMap(([categoryId, modelIds]) => {
677
+ return from(modelIds).pipe(mergeMap((modelOfCategory) => {
678
+ this.changeCategoryStateInViewportAccordingToModelVisibility(modelOfCategory, categoryId, on, !!ignoreSubCategories);
679
+ return this._alwaysAndNeverDrawnElements.clearAlwaysAndNeverDrawnElements({ modelId: modelOfCategory, categoryIds: [categoryId] });
680
+ }));
681
+ })), modelIdsObservable.pipe(mergeMap((categoriesMap) => from(categoriesMap.entries())), mergeMap(([categoryId, modelIds]) => {
682
+ return from(modelIds).pipe(mergeMap((modelOfCategory) => from(this._idsCache.getCategoriesModeledElements(modelOfCategory, [categoryId])).pipe(mergeMap((modeledElementIds) => this.changeModelState({ ids: modeledElementIds, on })))));
683
+ })));
684
+ });
685
+ return createVisibilityHandlerResult(this, props, result, undefined);
686
+ }
687
+ doChangeElementsState(props) {
688
+ return defer(() => {
689
+ const { modelId, categoryId, elementIds, on } = props;
690
+ const viewport = this._props.viewport;
691
+ return concat(on && !viewport.view.viewsModel(modelId) ? this.showModelWithoutAnyCategoriesOrElements(modelId) : EMPTY, defer(() => {
692
+ const categoryVisibility = this.getDefaultModelsCategoryVisibilityStatus({ categoryIds: [categoryId], modelId, ignoreTooltip: true });
693
+ const isDisplayedByDefault = categoryVisibility.state === "visible";
694
+ return this.queueElementsVisibilityChange(elementIds, on, isDisplayedByDefault);
695
+ }), from(elementIds).pipe(mergeMap(async (elementId) => ({ elementId, isSubModel: await this._idsCache.hasSubModel(elementId) })), filter(({ isSubModel }) => isSubModel), map(({ elementId }) => elementId), toArray(), mergeMap((subModelIds) => this.changeModelState({ ids: subModelIds, on }))));
696
+ });
697
+ }
698
+ /**
699
+ * Updates visibility of all grouping node's elements.
700
+ * @see `changeElementState`
701
+ */
702
+ changeElementGroupingNodeState(node, on) {
703
+ const info = this.getGroupingNodeInfo(node);
704
+ const result = from(info.modelElementsMap).pipe(mergeMap(([modelId, elementIds]) => {
705
+ return this.doChangeElementsState({ modelId, elementIds, categoryId: info.categoryId, on });
706
+ }));
707
+ return createVisibilityHandlerResult(this, { node, on }, result, undefined);
708
+ }
709
+ /**
710
+ * Updates visibility of an element and all its child elements by adding them to the always/never drawn list.
711
+ * @note If element is to be enabled and model is hidden, it will be enabled.
712
+ */
713
+ changeElementsState(props) {
714
+ const result = this.doChangeElementsState(props);
715
+ return createVisibilityHandlerResult(this, props, result, undefined);
716
+ }
717
+ queueElementsVisibilityChange(elementIds, on, visibleByDefault) {
718
+ const finishedSubject = new Subject();
719
+ // observable to track if visibility change is finished/cancelled
720
+ const changeFinished = finishedSubject.pipe(startWith(false), shareReplay(1), filter((finished) => finished));
721
+ const changeObservable = from(elementIds).pipe(
722
+ // check if visibility change is not finished (cancelled) due to change overall change request being cancelled
723
+ takeUntil(changeFinished), changeElementStateNoChildrenOperator({ on, isDisplayedByDefault: visibleByDefault, viewport: this._props.viewport }), tap({
724
+ next: () => {
725
+ // notify that visibility change is finished
726
+ finishedSubject.next(true);
727
+ },
728
+ }));
729
+ // queue visibility change. `changeObservable` will be subscribed to when other queue changes are finished
730
+ this._elementChangeQueue.next(changeObservable);
731
+ // return observable that will emit when visibility change is finished
732
+ return changeFinished.pipe(take(1), tap({
733
+ unsubscribe: () => {
734
+ // if this observable is unsubscribed before visibility change is finished, we have to notify that it queued change request is cancelled
735
+ finishedSubject.next(true);
736
+ },
737
+ }), map(() => undefined));
738
+ }
739
+ getVisibilityFromAlwaysAndNeverDrawnElements({ ignoreTooltip, ...props }) {
740
+ const viewport = this._props.viewport;
741
+ if (viewport.isAlwaysDrawnExclusive) {
742
+ if (!viewport?.alwaysDrawn?.size) {
743
+ return of(createVisibilityStatus("hidden", getTooltipOptions(props.tooltips.noElementsInExclusiveAlwaysDrawnList, ignoreTooltip)));
744
+ }
745
+ }
746
+ else if (!viewport?.neverDrawn?.size && !viewport?.alwaysDrawn?.size) {
747
+ return of(props.defaultStatus());
748
+ }
749
+ if ("elements" in props) {
750
+ return of(getVisibilityFromAlwaysAndNeverDrawnElementsImpl({
751
+ ...props,
752
+ alwaysDrawn: viewport.alwaysDrawn?.size ? setIntersection(props.elements, viewport.alwaysDrawn) : undefined,
753
+ neverDrawn: viewport.neverDrawn?.size ? setIntersection(props.elements, viewport.neverDrawn) : undefined,
754
+ totalCount: props.elements.size,
755
+ ignoreTooltip,
756
+ viewport,
757
+ }));
758
+ }
759
+ const { modelId, categoryIds } = props.queryProps;
760
+ const totalCount = (modelId ? of(new Map(categoryIds.map((categoryId) => [categoryId, [modelId]]))) : from(this._idsCache.getCategoriesElementModels(categoryIds))).pipe(mergeMap((categoriesMap) => from(categoriesMap)), mergeMap(([categoryId, modelIds]) => {
761
+ return from(modelIds).pipe(mergeMap((modelOfCategory) => from(this._idsCache.getCategoryElementsCount(modelOfCategory, categoryId))), reduce((acc, specificModelCategoryCount) => {
762
+ return acc + specificModelCategoryCount;
763
+ }, 0));
764
+ }));
765
+ return forkJoin({
766
+ totalCount,
767
+ alwaysDrawn: this._alwaysAndNeverDrawnElements.getAlwaysDrawnElements(props.queryProps),
768
+ neverDrawn: this._alwaysAndNeverDrawnElements.getNeverDrawnElements(props.queryProps),
769
+ }).pipe(map((state) => {
770
+ return getVisibilityFromAlwaysAndNeverDrawnElementsImpl({
771
+ ...props,
772
+ ...state,
773
+ ignoreTooltip,
774
+ viewport,
775
+ });
776
+ }));
777
+ }
778
+ getGroupingNodeInfo(node) {
779
+ const modelElementsMap = node.extendedData?.modelElementsMap;
780
+ const categoryId = node.extendedData?.categoryId;
781
+ assert(!!modelElementsMap && !!categoryId);
782
+ return { modelElementsMap, categoryId };
783
+ }
784
+ }
785
+ //# sourceMappingURL=CategoriesTreeVisibilityHandler.js.map