@itwin/presentation-frontend 4.0.0-dev.21 → 4.0.0-dev.23

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 (123) hide show
  1. package/lib/cjs/presentation-frontend/ConnectivityInformationProvider.d.ts +29 -29
  2. package/lib/cjs/presentation-frontend/ConnectivityInformationProvider.js +47 -47
  3. package/lib/cjs/presentation-frontend/ConnectivityInformationProvider.js.map +1 -1
  4. package/lib/cjs/presentation-frontend/Diagnostics.d.ts +14 -14
  5. package/lib/cjs/presentation-frontend/Diagnostics.js +61 -61
  6. package/lib/cjs/presentation-frontend/Diagnostics.js.map +1 -1
  7. package/lib/cjs/presentation-frontend/FrontendLoggerCategory.d.ts +12 -12
  8. package/lib/cjs/presentation-frontend/FrontendLoggerCategory.js +20 -20
  9. package/lib/cjs/presentation-frontend/FrontendLoggerCategory.js.map +1 -1
  10. package/lib/cjs/presentation-frontend/IpcRequestsHandler.d.ts +10 -10
  11. package/lib/cjs/presentation-frontend/IpcRequestsHandler.js +41 -41
  12. package/lib/cjs/presentation-frontend/IpcRequestsHandler.js.map +1 -1
  13. package/lib/cjs/presentation-frontend/LocalizationHelper.d.ts +10 -10
  14. package/lib/cjs/presentation-frontend/LocalizationHelper.js +31 -31
  15. package/lib/cjs/presentation-frontend/LocalizationHelper.js.map +1 -1
  16. package/lib/cjs/presentation-frontend/Presentation.d.ts +73 -73
  17. package/lib/cjs/presentation-frontend/Presentation.js +160 -160
  18. package/lib/cjs/presentation-frontend/Presentation.js.map +1 -1
  19. package/lib/cjs/presentation-frontend/PresentationManager.d.ts +186 -186
  20. package/lib/cjs/presentation-frontend/PresentationManager.js +436 -436
  21. package/lib/cjs/presentation-frontend/PresentationManager.js.map +1 -1
  22. package/lib/cjs/presentation-frontend/RulesetManager.d.ts +63 -63
  23. package/lib/cjs/presentation-frontend/RulesetManager.js +85 -85
  24. package/lib/cjs/presentation-frontend/RulesetManager.js.map +1 -1
  25. package/lib/cjs/presentation-frontend/RulesetVariablesManager.d.ts +143 -143
  26. package/lib/cjs/presentation-frontend/RulesetVariablesManager.js +195 -195
  27. package/lib/cjs/presentation-frontend/RulesetVariablesManager.js.map +1 -1
  28. package/lib/cjs/presentation-frontend/StateTracker.d.ts +38 -38
  29. package/lib/cjs/presentation-frontend/StateTracker.js +129 -129
  30. package/lib/cjs/presentation-frontend/StateTracker.js.map +1 -1
  31. package/lib/cjs/presentation-frontend/favorite-properties/FavoritePropertiesManager.d.ts +132 -132
  32. package/lib/cjs/presentation-frontend/favorite-properties/FavoritePropertiesManager.js +525 -525
  33. package/lib/cjs/presentation-frontend/favorite-properties/FavoritePropertiesManager.js.map +1 -1
  34. package/lib/cjs/presentation-frontend/favorite-properties/FavoritePropertiesStorage.d.ts +111 -111
  35. package/lib/cjs/presentation-frontend/favorite-properties/FavoritePropertiesStorage.js +293 -293
  36. package/lib/cjs/presentation-frontend/favorite-properties/FavoritePropertiesStorage.js.map +1 -1
  37. package/lib/cjs/presentation-frontend/selection/HiliteRules.json +172 -172
  38. package/lib/cjs/presentation-frontend/selection/HiliteSetProvider.d.ts +52 -52
  39. package/lib/cjs/presentation-frontend/selection/HiliteSetProvider.js +97 -97
  40. package/lib/cjs/presentation-frontend/selection/HiliteSetProvider.js.map +1 -1
  41. package/lib/cjs/presentation-frontend/selection/ISelectionProvider.d.ts +19 -19
  42. package/lib/cjs/presentation-frontend/selection/ISelectionProvider.js +9 -9
  43. package/lib/cjs/presentation-frontend/selection/ISelectionProvider.js.map +1 -1
  44. package/lib/cjs/presentation-frontend/selection/SelectionChangeEvent.d.ts +52 -52
  45. package/lib/cjs/presentation-frontend/selection/SelectionChangeEvent.js +33 -33
  46. package/lib/cjs/presentation-frontend/selection/SelectionChangeEvent.js.map +1 -1
  47. package/lib/cjs/presentation-frontend/selection/SelectionHandler.d.ts +103 -103
  48. package/lib/cjs/presentation-frontend/selection/SelectionHandler.js +108 -108
  49. package/lib/cjs/presentation-frontend/selection/SelectionHandler.js.map +1 -1
  50. package/lib/cjs/presentation-frontend/selection/SelectionHelper.d.ts +17 -17
  51. package/lib/cjs/presentation-frontend/selection/SelectionHelper.js +40 -40
  52. package/lib/cjs/presentation-frontend/selection/SelectionHelper.js.map +1 -1
  53. package/lib/cjs/presentation-frontend/selection/SelectionManager.d.ts +139 -139
  54. package/lib/cjs/presentation-frontend/selection/SelectionManager.js +414 -414
  55. package/lib/cjs/presentation-frontend/selection/SelectionManager.js.map +1 -1
  56. package/lib/cjs/presentation-frontend/selection/SelectionScopesManager.d.ts +59 -59
  57. package/lib/cjs/presentation-frontend/selection/SelectionScopesManager.js +91 -91
  58. package/lib/cjs/presentation-frontend/selection/SelectionScopesManager.js.map +1 -1
  59. package/lib/cjs/presentation-frontend.d.ts +34 -34
  60. package/lib/cjs/presentation-frontend.js +50 -50
  61. package/lib/cjs/presentation-frontend.js.map +1 -1
  62. package/lib/esm/presentation-frontend/ConnectivityInformationProvider.d.ts +29 -29
  63. package/lib/esm/presentation-frontend/ConnectivityInformationProvider.js +43 -43
  64. package/lib/esm/presentation-frontend/ConnectivityInformationProvider.js.map +1 -1
  65. package/lib/esm/presentation-frontend/Diagnostics.d.ts +14 -14
  66. package/lib/esm/presentation-frontend/Diagnostics.js +56 -56
  67. package/lib/esm/presentation-frontend/Diagnostics.js.map +1 -1
  68. package/lib/esm/presentation-frontend/FrontendLoggerCategory.d.ts +12 -12
  69. package/lib/esm/presentation-frontend/FrontendLoggerCategory.js +17 -17
  70. package/lib/esm/presentation-frontend/FrontendLoggerCategory.js.map +1 -1
  71. package/lib/esm/presentation-frontend/IpcRequestsHandler.d.ts +10 -10
  72. package/lib/esm/presentation-frontend/IpcRequestsHandler.js +37 -37
  73. package/lib/esm/presentation-frontend/IpcRequestsHandler.js.map +1 -1
  74. package/lib/esm/presentation-frontend/LocalizationHelper.d.ts +10 -10
  75. package/lib/esm/presentation-frontend/LocalizationHelper.js +27 -27
  76. package/lib/esm/presentation-frontend/LocalizationHelper.js.map +1 -1
  77. package/lib/esm/presentation-frontend/Presentation.d.ts +73 -73
  78. package/lib/esm/presentation-frontend/Presentation.js +156 -156
  79. package/lib/esm/presentation-frontend/Presentation.js.map +1 -1
  80. package/lib/esm/presentation-frontend/PresentationManager.d.ts +186 -186
  81. package/lib/esm/presentation-frontend/PresentationManager.js +431 -431
  82. package/lib/esm/presentation-frontend/PresentationManager.js.map +1 -1
  83. package/lib/esm/presentation-frontend/RulesetManager.d.ts +63 -63
  84. package/lib/esm/presentation-frontend/RulesetManager.js +81 -81
  85. package/lib/esm/presentation-frontend/RulesetManager.js.map +1 -1
  86. package/lib/esm/presentation-frontend/RulesetVariablesManager.d.ts +143 -143
  87. package/lib/esm/presentation-frontend/RulesetVariablesManager.js +191 -191
  88. package/lib/esm/presentation-frontend/RulesetVariablesManager.js.map +1 -1
  89. package/lib/esm/presentation-frontend/StateTracker.d.ts +38 -38
  90. package/lib/esm/presentation-frontend/StateTracker.js +125 -125
  91. package/lib/esm/presentation-frontend/StateTracker.js.map +1 -1
  92. package/lib/esm/presentation-frontend/favorite-properties/FavoritePropertiesManager.d.ts +132 -132
  93. package/lib/esm/presentation-frontend/favorite-properties/FavoritePropertiesManager.js +519 -519
  94. package/lib/esm/presentation-frontend/favorite-properties/FavoritePropertiesManager.js.map +1 -1
  95. package/lib/esm/presentation-frontend/favorite-properties/FavoritePropertiesStorage.d.ts +111 -111
  96. package/lib/esm/presentation-frontend/favorite-properties/FavoritePropertiesStorage.js +285 -285
  97. package/lib/esm/presentation-frontend/favorite-properties/FavoritePropertiesStorage.js.map +1 -1
  98. package/lib/esm/presentation-frontend/selection/HiliteRules.json +172 -172
  99. package/lib/esm/presentation-frontend/selection/HiliteSetProvider.d.ts +52 -52
  100. package/lib/esm/presentation-frontend/selection/HiliteSetProvider.js +93 -93
  101. package/lib/esm/presentation-frontend/selection/HiliteSetProvider.js.map +1 -1
  102. package/lib/esm/presentation-frontend/selection/ISelectionProvider.d.ts +19 -19
  103. package/lib/esm/presentation-frontend/selection/ISelectionProvider.js +8 -8
  104. package/lib/esm/presentation-frontend/selection/ISelectionProvider.js.map +1 -1
  105. package/lib/esm/presentation-frontend/selection/SelectionChangeEvent.d.ts +52 -52
  106. package/lib/esm/presentation-frontend/selection/SelectionChangeEvent.js +29 -29
  107. package/lib/esm/presentation-frontend/selection/SelectionChangeEvent.js.map +1 -1
  108. package/lib/esm/presentation-frontend/selection/SelectionHandler.d.ts +103 -103
  109. package/lib/esm/presentation-frontend/selection/SelectionHandler.js +104 -104
  110. package/lib/esm/presentation-frontend/selection/SelectionHandler.js.map +1 -1
  111. package/lib/esm/presentation-frontend/selection/SelectionHelper.d.ts +17 -17
  112. package/lib/esm/presentation-frontend/selection/SelectionHelper.js +36 -36
  113. package/lib/esm/presentation-frontend/selection/SelectionHelper.js.map +1 -1
  114. package/lib/esm/presentation-frontend/selection/SelectionManager.d.ts +139 -139
  115. package/lib/esm/presentation-frontend/selection/SelectionManager.js +409 -409
  116. package/lib/esm/presentation-frontend/selection/SelectionManager.js.map +1 -1
  117. package/lib/esm/presentation-frontend/selection/SelectionScopesManager.d.ts +59 -59
  118. package/lib/esm/presentation-frontend/selection/SelectionScopesManager.js +85 -85
  119. package/lib/esm/presentation-frontend/selection/SelectionScopesManager.js.map +1 -1
  120. package/lib/esm/presentation-frontend.d.ts +34 -34
  121. package/lib/esm/presentation-frontend.js +38 -38
  122. package/lib/esm/presentation-frontend.js.map +1 -1
  123. package/package.json +14 -14
@@ -1,410 +1,410 @@
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
- /** @packageDocumentation
6
- * @module UnifiedSelection
7
- */
8
- import { Id64, using } from "@itwin/core-bentley";
9
- import { IModelConnection, SelectionSetEventType } from "@itwin/core-frontend";
10
- import { AsyncTasksTracker, KeySet } from "@itwin/presentation-common";
11
- import { HiliteSetProvider } from "./HiliteSetProvider";
12
- import { SelectionChangeEvent, SelectionChangeType } from "./SelectionChangeEvent";
13
- import { createSelectionScopeProps } from "./SelectionScopesManager";
14
- /**
15
- * The selection manager which stores the overall selection.
16
- * @public
17
- */
18
- export class SelectionManager {
19
- /**
20
- * Creates an instance of SelectionManager.
21
- */
22
- constructor(props) {
23
- this._selectionContainerMap = new Map();
24
- this._imodelToolSelectionSyncHandlers = new Map();
25
- this._hiliteSetProviders = new Map();
26
- this.selectionChange = new SelectionChangeEvent();
27
- this.scopes = props.scopes;
28
- IModelConnection.onClose.addListener((imodel) => {
29
- this.onConnectionClose(imodel);
30
- });
31
- }
32
- onConnectionClose(imodel) {
33
- this.clearSelection("Connection Close Event", imodel);
34
- this._selectionContainerMap.delete(imodel);
35
- this._hiliteSetProviders.delete(imodel);
36
- }
37
- getContainer(imodel) {
38
- let selectionContainer = this._selectionContainerMap.get(imodel);
39
- if (!selectionContainer) {
40
- selectionContainer = new SelectionContainer();
41
- this._selectionContainerMap.set(imodel, selectionContainer);
42
- }
43
- return selectionContainer;
44
- }
45
- /** @internal */
46
- // istanbul ignore next
47
- getToolSelectionSyncHandler(imodel) { var _a; return (_a = this._imodelToolSelectionSyncHandlers.get(imodel)) === null || _a === void 0 ? void 0 : _a.handler; }
48
- /**
49
- * Request the manager to sync with imodel's tool selection (see `IModelConnection.selectionSet`).
50
- */
51
- setSyncWithIModelToolSelection(imodel, sync = true) {
52
- const registration = this._imodelToolSelectionSyncHandlers.get(imodel);
53
- if (sync) {
54
- if (!registration || registration.requestorsCount === 0) {
55
- this._imodelToolSelectionSyncHandlers.set(imodel, { requestorsCount: 1, handler: new ToolSelectionSyncHandler(imodel, this) });
56
- }
57
- else {
58
- this._imodelToolSelectionSyncHandlers.set(imodel, { ...registration, requestorsCount: registration.requestorsCount + 1 });
59
- }
60
- }
61
- else {
62
- if (registration && registration.requestorsCount > 0) {
63
- const requestorsCount = registration.requestorsCount - 1;
64
- if (requestorsCount > 0) {
65
- this._imodelToolSelectionSyncHandlers.set(imodel, { ...registration, requestorsCount });
66
- }
67
- else {
68
- this._imodelToolSelectionSyncHandlers.delete(imodel);
69
- registration.handler.dispose();
70
- }
71
- }
72
- }
73
- }
74
- /**
75
- * Temporarily suspends tool selection synchronization until the returned `IDisposable`
76
- * is disposed.
77
- */
78
- suspendIModelToolSelectionSync(imodel) {
79
- const registration = this._imodelToolSelectionSyncHandlers.get(imodel);
80
- if (!registration)
81
- return { dispose: () => { } };
82
- const wasSuspended = registration.handler.isSuspended;
83
- registration.handler.isSuspended = true;
84
- return { dispose: () => (registration.handler.isSuspended = wasSuspended) };
85
- }
86
- /** Get the selection levels currently stored in this manager for the specified imodel */
87
- getSelectionLevels(imodel) {
88
- return this.getContainer(imodel).getSelectionLevels();
89
- }
90
- /** Get the selection currently stored in this manager */
91
- getSelection(imodel, level = 0) {
92
- return this.getContainer(imodel).getSelection(level);
93
- }
94
- handleEvent(evt) {
95
- const container = this.getContainer(evt.imodel);
96
- const selectedItemsSet = container.getSelection(evt.level);
97
- const guidBefore = selectedItemsSet.guid;
98
- switch (evt.changeType) {
99
- case SelectionChangeType.Add:
100
- selectedItemsSet.add(evt.keys);
101
- break;
102
- case SelectionChangeType.Remove:
103
- selectedItemsSet.delete(evt.keys);
104
- break;
105
- case SelectionChangeType.Replace:
106
- if (selectedItemsSet.size !== evt.keys.size || !selectedItemsSet.hasAll(evt.keys)) {
107
- // note: the above check is only needed to avoid changing
108
- // guid of the keyset if we're replacing keyset with the same keys
109
- selectedItemsSet.clear().add(evt.keys);
110
- }
111
- break;
112
- case SelectionChangeType.Clear:
113
- selectedItemsSet.clear();
114
- break;
115
- }
116
- if (selectedItemsSet.guid === guidBefore)
117
- return;
118
- container.clear(evt.level + 1);
119
- this.selectionChange.raiseEvent(evt, this);
120
- }
121
- /**
122
- * Add keys to the selection
123
- * @param source Name of the selection source
124
- * @param imodel iModel associated with the selection
125
- * @param keys Keys to add
126
- * @param level Selection level (see [selection levels documentation section]($docs/presentation/unified-selection/index#selection-levels))
127
- * @param rulesetId ID of the ruleset in case the selection was changed from a rules-driven control
128
- */
129
- addToSelection(source, imodel, keys, level = 0, rulesetId) {
130
- const evt = {
131
- source,
132
- level,
133
- imodel,
134
- changeType: SelectionChangeType.Add,
135
- keys: new KeySet(keys),
136
- timestamp: new Date(),
137
- rulesetId,
138
- };
139
- this.handleEvent(evt);
140
- }
141
- /**
142
- * Remove keys from current selection
143
- * @param source Name of the selection source
144
- * @param imodel iModel associated with the selection
145
- * @param keys Keys to remove
146
- * @param level Selection level (see [selection levels documentation section]($docs/presentation/unified-selection/index#selection-levels))
147
- * @param rulesetId ID of the ruleset in case the selection was changed from a rules-driven control
148
- */
149
- removeFromSelection(source, imodel, keys, level = 0, rulesetId) {
150
- const evt = {
151
- source,
152
- level,
153
- imodel,
154
- changeType: SelectionChangeType.Remove,
155
- keys: new KeySet(keys),
156
- timestamp: new Date(),
157
- rulesetId,
158
- };
159
- this.handleEvent(evt);
160
- }
161
- /**
162
- * Replace current selection
163
- * @param source Name of the selection source
164
- * @param imodel iModel associated with the selection
165
- * @param keys Keys to add
166
- * @param level Selection level (see [selection levels documentation section]($docs/presentation/unified-selection/index#selection-levels))
167
- * @param rulesetId ID of the ruleset in case the selection was changed from a rules-driven control
168
- */
169
- replaceSelection(source, imodel, keys, level = 0, rulesetId) {
170
- const evt = {
171
- source,
172
- level,
173
- imodel,
174
- changeType: SelectionChangeType.Replace,
175
- keys: new KeySet(keys),
176
- timestamp: new Date(),
177
- rulesetId,
178
- };
179
- this.handleEvent(evt);
180
- }
181
- /**
182
- * Clear current selection
183
- * @param source Name of the selection source
184
- * @param imodel iModel associated with the selection
185
- * @param level Selection level (see [selection levels documentation section]($docs/presentation/unified-selection/index#selection-levels))
186
- * @param rulesetId ID of the ruleset in case the selection was changed from a rules-driven control
187
- */
188
- clearSelection(source, imodel, level = 0, rulesetId) {
189
- const evt = {
190
- source,
191
- level,
192
- imodel,
193
- changeType: SelectionChangeType.Clear,
194
- keys: new KeySet(),
195
- timestamp: new Date(),
196
- rulesetId,
197
- };
198
- this.handleEvent(evt);
199
- }
200
- /**
201
- * Add keys to selection after applying [selection scope]($docs/presentation/unified-selection/index#selection-scopes) on them.
202
- * @param source Name of the selection source
203
- * @param imodel iModel associated with the selection
204
- * @param ids Element IDs to add
205
- * @param scope Selection scope to apply
206
- * @param level Selection level (see [selection levels documentation section]($docs/presentation/unified-selection/index#selection-levels))
207
- * @param rulesetId ID of the ruleset in case the selection was changed from a rules-driven control
208
- */
209
- async addToSelectionWithScope(source, imodel, ids, scope, level = 0, rulesetId) {
210
- const scopedKeys = await this.scopes.computeSelection(imodel, ids, scope);
211
- this.addToSelection(source, imodel, scopedKeys, level, rulesetId);
212
- }
213
- /**
214
- * Remove keys from current selection after applying [selection scope]($docs/presentation/unified-selection/index#selection-scopes) on them.
215
- * @param source Name of the selection source
216
- * @param imodel iModel associated with the selection
217
- * @param ids Element IDs to remove
218
- * @param scope Selection scope to apply
219
- * @param level Selection level (see [selection levels documentation section]($docs/presentation/unified-selection/index#selection-levels))
220
- * @param rulesetId ID of the ruleset in case the selection was changed from a rules-driven control
221
- */
222
- async removeFromSelectionWithScope(source, imodel, ids, scope, level = 0, rulesetId) {
223
- const scopedKeys = await this.scopes.computeSelection(imodel, ids, scope);
224
- this.removeFromSelection(source, imodel, scopedKeys, level, rulesetId);
225
- }
226
- /**
227
- * Replace current selection with keys after applying [selection scope]($docs/presentation/unified-selection/index#selection-scopes) on them.
228
- * @param source Name of the selection source
229
- * @param imodel iModel associated with the selection
230
- * @param ids Element IDs to replace with
231
- * @param scope Selection scope to apply
232
- * @param level Selection level (see [selection levels documentation section]($docs/presentation/unified-selection/index#selection-levels))
233
- * @param rulesetId ID of the ruleset in case the selection was changed from a rules-driven control
234
- */
235
- async replaceSelectionWithScope(source, imodel, ids, scope, level = 0, rulesetId) {
236
- const scopedKeys = await this.scopes.computeSelection(imodel, ids, scope);
237
- this.replaceSelection(source, imodel, scopedKeys, level, rulesetId);
238
- }
239
- /**
240
- * Get the current hilite set for the specified imodel
241
- * @public
242
- */
243
- async getHiliteSet(imodel) {
244
- let provider = this._hiliteSetProviders.get(imodel);
245
- if (!provider) {
246
- provider = HiliteSetProvider.create({ imodel });
247
- this._hiliteSetProviders.set(imodel, provider);
248
- }
249
- return provider.getHiliteSet(this.getSelection(imodel));
250
- }
251
- }
252
- /** @internal */
253
- class SelectionContainer {
254
- constructor() {
255
- this._selectedItemsSetMap = new Map();
256
- }
257
- getSelection(level) {
258
- let selectedItemsSet = this._selectedItemsSetMap.get(level);
259
- if (!selectedItemsSet) {
260
- selectedItemsSet = new KeySet();
261
- this._selectedItemsSetMap.set(level, selectedItemsSet);
262
- }
263
- return selectedItemsSet;
264
- }
265
- getSelectionLevels() {
266
- const levels = new Array();
267
- for (const entry of this._selectedItemsSetMap.entries()) {
268
- if (!entry[1].isEmpty)
269
- levels.push(entry[0]);
270
- }
271
- return levels.sort();
272
- }
273
- clear(level) {
274
- const keys = this._selectedItemsSetMap.keys();
275
- for (const key of keys) {
276
- if (key >= level) {
277
- const selectedItemsSet = this._selectedItemsSetMap.get(key);
278
- selectedItemsSet.clear();
279
- }
280
- }
281
- }
282
- }
283
- /** @internal */
284
- export const TRANSIENT_ELEMENT_CLASSNAME = "/TRANSIENT";
285
- /** @internal */
286
- export class ToolSelectionSyncHandler {
287
- constructor(imodel, logicalSelection) {
288
- this._selectionSourceName = "Tool";
289
- this._asyncsTracker = new AsyncTasksTracker();
290
- // eslint-disable-next-line @typescript-eslint/naming-convention
291
- this.onToolSelectionChanged = async (ev) => {
292
- // ignore selection change event if the handler is suspended
293
- if (this.isSuspended)
294
- return;
295
- // this component only cares about its own imodel
296
- const imodel = ev.set.iModel;
297
- if (imodel !== this._imodel)
298
- return;
299
- // determine the level of selection changes
300
- // wip: may want to allow selecting at different levels?
301
- const selectionLevel = 0;
302
- let ids;
303
- switch (ev.type) {
304
- case SelectionSetEventType.Add:
305
- ids = ev.added;
306
- break;
307
- case SelectionSetEventType.Replace:
308
- ids = ev.set.elements;
309
- break;
310
- default:
311
- ids = ev.removed;
312
- break;
313
- }
314
- // we're always using scoped selection changer even if the scope is set to "element" - that
315
- // makes sure we're adding to selection keys with concrete classes and not "BisCore:Element", which
316
- // we can't because otherwise our keys compare fails (presentation components load data with
317
- // concrete classes)
318
- const changer = new ScopedSelectionChanger(this._selectionSourceName, this._imodel, this._logicalSelection, createSelectionScopeProps(this._logicalSelection.scopes.activeScope));
319
- // we know what to do immediately on `clear` events
320
- if (SelectionSetEventType.Clear === ev.type) {
321
- await changer.clear(selectionLevel);
322
- return;
323
- }
324
- const parsedIds = parseIds(ids);
325
- await using(this._asyncsTracker.trackAsyncTask(), async (_r) => {
326
- switch (ev.type) {
327
- case SelectionSetEventType.Add:
328
- await changer.add(parsedIds.transient, parsedIds.persistent, selectionLevel);
329
- break;
330
- case SelectionSetEventType.Replace:
331
- await changer.replace(parsedIds.transient, parsedIds.persistent, selectionLevel);
332
- break;
333
- case SelectionSetEventType.Remove:
334
- await changer.remove(parsedIds.transient, parsedIds.persistent, selectionLevel);
335
- break;
336
- }
337
- });
338
- };
339
- this._imodel = imodel;
340
- this._logicalSelection = logicalSelection;
341
- this._imodelToolSelectionListenerDisposeFunc = imodel.selectionSet.onChanged.addListener(this.onToolSelectionChanged);
342
- }
343
- dispose() {
344
- this._imodelToolSelectionListenerDisposeFunc();
345
- }
346
- /** note: used only it tests */
347
- get pendingAsyncs() { return this._asyncsTracker.pendingAsyncs; }
348
- }
349
- const parseIds = (ids) => {
350
- let allPersistent = true;
351
- let allTransient = true;
352
- for (const id of Id64.iterable(ids)) {
353
- if (Id64.isTransient(id))
354
- allPersistent = false;
355
- else
356
- allTransient = false;
357
- if (!allPersistent && !allTransient)
358
- break;
359
- }
360
- // avoid making a copy if ids are only persistent or only transient
361
- if (allPersistent) {
362
- return { persistent: ids, transient: [] };
363
- }
364
- else if (allTransient) {
365
- return { persistent: [], transient: ids };
366
- }
367
- // if `ids` contain mixed ids, we have to copy.. use Array instead of
368
- // a Set for performance
369
- const persistentElementIds = [];
370
- const transientElementIds = [];
371
- for (const id of Id64.iterable(ids)) {
372
- if (Id64.isTransient(id))
373
- transientElementIds.push(id);
374
- else
375
- persistentElementIds.push(id);
376
- }
377
- return { persistent: persistentElementIds, transient: transientElementIds };
378
- };
379
- function addTransientKeys(transientIds, keys) {
380
- for (const id of Id64.iterable(transientIds))
381
- keys.add({ className: TRANSIENT_ELEMENT_CLASSNAME, id });
382
- }
383
- /** @internal */
384
- class ScopedSelectionChanger {
385
- constructor(name, imodel, manager, scope) {
386
- this.name = name;
387
- this.imodel = imodel;
388
- this.manager = manager;
389
- this.scope = scope;
390
- }
391
- async clear(level) {
392
- this.manager.clearSelection(this.name, this.imodel, level);
393
- }
394
- async add(transientIds, persistentIds, level) {
395
- const keys = await this.manager.scopes.computeSelection(this.imodel, persistentIds, this.scope);
396
- addTransientKeys(transientIds, keys);
397
- this.manager.addToSelection(this.name, this.imodel, keys, level);
398
- }
399
- async remove(transientIds, persistentIds, level) {
400
- const keys = await this.manager.scopes.computeSelection(this.imodel, persistentIds, this.scope);
401
- addTransientKeys(transientIds, keys);
402
- this.manager.removeFromSelection(this.name, this.imodel, keys, level);
403
- }
404
- async replace(transientIds, persistentIds, level) {
405
- const keys = await this.manager.scopes.computeSelection(this.imodel, persistentIds, this.scope);
406
- addTransientKeys(transientIds, keys);
407
- this.manager.replaceSelection(this.name, this.imodel, keys, level);
408
- }
409
- }
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
+ /** @packageDocumentation
6
+ * @module UnifiedSelection
7
+ */
8
+ import { Id64, using } from "@itwin/core-bentley";
9
+ import { IModelConnection, SelectionSetEventType } from "@itwin/core-frontend";
10
+ import { AsyncTasksTracker, KeySet } from "@itwin/presentation-common";
11
+ import { HiliteSetProvider } from "./HiliteSetProvider";
12
+ import { SelectionChangeEvent, SelectionChangeType } from "./SelectionChangeEvent";
13
+ import { createSelectionScopeProps } from "./SelectionScopesManager";
14
+ /**
15
+ * The selection manager which stores the overall selection.
16
+ * @public
17
+ */
18
+ export class SelectionManager {
19
+ /**
20
+ * Creates an instance of SelectionManager.
21
+ */
22
+ constructor(props) {
23
+ this._selectionContainerMap = new Map();
24
+ this._imodelToolSelectionSyncHandlers = new Map();
25
+ this._hiliteSetProviders = new Map();
26
+ this.selectionChange = new SelectionChangeEvent();
27
+ this.scopes = props.scopes;
28
+ IModelConnection.onClose.addListener((imodel) => {
29
+ this.onConnectionClose(imodel);
30
+ });
31
+ }
32
+ onConnectionClose(imodel) {
33
+ this.clearSelection("Connection Close Event", imodel);
34
+ this._selectionContainerMap.delete(imodel);
35
+ this._hiliteSetProviders.delete(imodel);
36
+ }
37
+ getContainer(imodel) {
38
+ let selectionContainer = this._selectionContainerMap.get(imodel);
39
+ if (!selectionContainer) {
40
+ selectionContainer = new SelectionContainer();
41
+ this._selectionContainerMap.set(imodel, selectionContainer);
42
+ }
43
+ return selectionContainer;
44
+ }
45
+ /** @internal */
46
+ // istanbul ignore next
47
+ getToolSelectionSyncHandler(imodel) { var _a; return (_a = this._imodelToolSelectionSyncHandlers.get(imodel)) === null || _a === void 0 ? void 0 : _a.handler; }
48
+ /**
49
+ * Request the manager to sync with imodel's tool selection (see `IModelConnection.selectionSet`).
50
+ */
51
+ setSyncWithIModelToolSelection(imodel, sync = true) {
52
+ const registration = this._imodelToolSelectionSyncHandlers.get(imodel);
53
+ if (sync) {
54
+ if (!registration || registration.requestorsCount === 0) {
55
+ this._imodelToolSelectionSyncHandlers.set(imodel, { requestorsCount: 1, handler: new ToolSelectionSyncHandler(imodel, this) });
56
+ }
57
+ else {
58
+ this._imodelToolSelectionSyncHandlers.set(imodel, { ...registration, requestorsCount: registration.requestorsCount + 1 });
59
+ }
60
+ }
61
+ else {
62
+ if (registration && registration.requestorsCount > 0) {
63
+ const requestorsCount = registration.requestorsCount - 1;
64
+ if (requestorsCount > 0) {
65
+ this._imodelToolSelectionSyncHandlers.set(imodel, { ...registration, requestorsCount });
66
+ }
67
+ else {
68
+ this._imodelToolSelectionSyncHandlers.delete(imodel);
69
+ registration.handler.dispose();
70
+ }
71
+ }
72
+ }
73
+ }
74
+ /**
75
+ * Temporarily suspends tool selection synchronization until the returned `IDisposable`
76
+ * is disposed.
77
+ */
78
+ suspendIModelToolSelectionSync(imodel) {
79
+ const registration = this._imodelToolSelectionSyncHandlers.get(imodel);
80
+ if (!registration)
81
+ return { dispose: () => { } };
82
+ const wasSuspended = registration.handler.isSuspended;
83
+ registration.handler.isSuspended = true;
84
+ return { dispose: () => (registration.handler.isSuspended = wasSuspended) };
85
+ }
86
+ /** Get the selection levels currently stored in this manager for the specified imodel */
87
+ getSelectionLevels(imodel) {
88
+ return this.getContainer(imodel).getSelectionLevels();
89
+ }
90
+ /** Get the selection currently stored in this manager */
91
+ getSelection(imodel, level = 0) {
92
+ return this.getContainer(imodel).getSelection(level);
93
+ }
94
+ handleEvent(evt) {
95
+ const container = this.getContainer(evt.imodel);
96
+ const selectedItemsSet = container.getSelection(evt.level);
97
+ const guidBefore = selectedItemsSet.guid;
98
+ switch (evt.changeType) {
99
+ case SelectionChangeType.Add:
100
+ selectedItemsSet.add(evt.keys);
101
+ break;
102
+ case SelectionChangeType.Remove:
103
+ selectedItemsSet.delete(evt.keys);
104
+ break;
105
+ case SelectionChangeType.Replace:
106
+ if (selectedItemsSet.size !== evt.keys.size || !selectedItemsSet.hasAll(evt.keys)) {
107
+ // note: the above check is only needed to avoid changing
108
+ // guid of the keyset if we're replacing keyset with the same keys
109
+ selectedItemsSet.clear().add(evt.keys);
110
+ }
111
+ break;
112
+ case SelectionChangeType.Clear:
113
+ selectedItemsSet.clear();
114
+ break;
115
+ }
116
+ if (selectedItemsSet.guid === guidBefore)
117
+ return;
118
+ container.clear(evt.level + 1);
119
+ this.selectionChange.raiseEvent(evt, this);
120
+ }
121
+ /**
122
+ * Add keys to the selection
123
+ * @param source Name of the selection source
124
+ * @param imodel iModel associated with the selection
125
+ * @param keys Keys to add
126
+ * @param level Selection level (see [selection levels documentation section]($docs/presentation/unified-selection/index#selection-levels))
127
+ * @param rulesetId ID of the ruleset in case the selection was changed from a rules-driven control
128
+ */
129
+ addToSelection(source, imodel, keys, level = 0, rulesetId) {
130
+ const evt = {
131
+ source,
132
+ level,
133
+ imodel,
134
+ changeType: SelectionChangeType.Add,
135
+ keys: new KeySet(keys),
136
+ timestamp: new Date(),
137
+ rulesetId,
138
+ };
139
+ this.handleEvent(evt);
140
+ }
141
+ /**
142
+ * Remove keys from current selection
143
+ * @param source Name of the selection source
144
+ * @param imodel iModel associated with the selection
145
+ * @param keys Keys to remove
146
+ * @param level Selection level (see [selection levels documentation section]($docs/presentation/unified-selection/index#selection-levels))
147
+ * @param rulesetId ID of the ruleset in case the selection was changed from a rules-driven control
148
+ */
149
+ removeFromSelection(source, imodel, keys, level = 0, rulesetId) {
150
+ const evt = {
151
+ source,
152
+ level,
153
+ imodel,
154
+ changeType: SelectionChangeType.Remove,
155
+ keys: new KeySet(keys),
156
+ timestamp: new Date(),
157
+ rulesetId,
158
+ };
159
+ this.handleEvent(evt);
160
+ }
161
+ /**
162
+ * Replace current selection
163
+ * @param source Name of the selection source
164
+ * @param imodel iModel associated with the selection
165
+ * @param keys Keys to add
166
+ * @param level Selection level (see [selection levels documentation section]($docs/presentation/unified-selection/index#selection-levels))
167
+ * @param rulesetId ID of the ruleset in case the selection was changed from a rules-driven control
168
+ */
169
+ replaceSelection(source, imodel, keys, level = 0, rulesetId) {
170
+ const evt = {
171
+ source,
172
+ level,
173
+ imodel,
174
+ changeType: SelectionChangeType.Replace,
175
+ keys: new KeySet(keys),
176
+ timestamp: new Date(),
177
+ rulesetId,
178
+ };
179
+ this.handleEvent(evt);
180
+ }
181
+ /**
182
+ * Clear current selection
183
+ * @param source Name of the selection source
184
+ * @param imodel iModel associated with the selection
185
+ * @param level Selection level (see [selection levels documentation section]($docs/presentation/unified-selection/index#selection-levels))
186
+ * @param rulesetId ID of the ruleset in case the selection was changed from a rules-driven control
187
+ */
188
+ clearSelection(source, imodel, level = 0, rulesetId) {
189
+ const evt = {
190
+ source,
191
+ level,
192
+ imodel,
193
+ changeType: SelectionChangeType.Clear,
194
+ keys: new KeySet(),
195
+ timestamp: new Date(),
196
+ rulesetId,
197
+ };
198
+ this.handleEvent(evt);
199
+ }
200
+ /**
201
+ * Add keys to selection after applying [selection scope]($docs/presentation/unified-selection/index#selection-scopes) on them.
202
+ * @param source Name of the selection source
203
+ * @param imodel iModel associated with the selection
204
+ * @param ids Element IDs to add
205
+ * @param scope Selection scope to apply
206
+ * @param level Selection level (see [selection levels documentation section]($docs/presentation/unified-selection/index#selection-levels))
207
+ * @param rulesetId ID of the ruleset in case the selection was changed from a rules-driven control
208
+ */
209
+ async addToSelectionWithScope(source, imodel, ids, scope, level = 0, rulesetId) {
210
+ const scopedKeys = await this.scopes.computeSelection(imodel, ids, scope);
211
+ this.addToSelection(source, imodel, scopedKeys, level, rulesetId);
212
+ }
213
+ /**
214
+ * Remove keys from current selection after applying [selection scope]($docs/presentation/unified-selection/index#selection-scopes) on them.
215
+ * @param source Name of the selection source
216
+ * @param imodel iModel associated with the selection
217
+ * @param ids Element IDs to remove
218
+ * @param scope Selection scope to apply
219
+ * @param level Selection level (see [selection levels documentation section]($docs/presentation/unified-selection/index#selection-levels))
220
+ * @param rulesetId ID of the ruleset in case the selection was changed from a rules-driven control
221
+ */
222
+ async removeFromSelectionWithScope(source, imodel, ids, scope, level = 0, rulesetId) {
223
+ const scopedKeys = await this.scopes.computeSelection(imodel, ids, scope);
224
+ this.removeFromSelection(source, imodel, scopedKeys, level, rulesetId);
225
+ }
226
+ /**
227
+ * Replace current selection with keys after applying [selection scope]($docs/presentation/unified-selection/index#selection-scopes) on them.
228
+ * @param source Name of the selection source
229
+ * @param imodel iModel associated with the selection
230
+ * @param ids Element IDs to replace with
231
+ * @param scope Selection scope to apply
232
+ * @param level Selection level (see [selection levels documentation section]($docs/presentation/unified-selection/index#selection-levels))
233
+ * @param rulesetId ID of the ruleset in case the selection was changed from a rules-driven control
234
+ */
235
+ async replaceSelectionWithScope(source, imodel, ids, scope, level = 0, rulesetId) {
236
+ const scopedKeys = await this.scopes.computeSelection(imodel, ids, scope);
237
+ this.replaceSelection(source, imodel, scopedKeys, level, rulesetId);
238
+ }
239
+ /**
240
+ * Get the current hilite set for the specified imodel
241
+ * @public
242
+ */
243
+ async getHiliteSet(imodel) {
244
+ let provider = this._hiliteSetProviders.get(imodel);
245
+ if (!provider) {
246
+ provider = HiliteSetProvider.create({ imodel });
247
+ this._hiliteSetProviders.set(imodel, provider);
248
+ }
249
+ return provider.getHiliteSet(this.getSelection(imodel));
250
+ }
251
+ }
252
+ /** @internal */
253
+ class SelectionContainer {
254
+ constructor() {
255
+ this._selectedItemsSetMap = new Map();
256
+ }
257
+ getSelection(level) {
258
+ let selectedItemsSet = this._selectedItemsSetMap.get(level);
259
+ if (!selectedItemsSet) {
260
+ selectedItemsSet = new KeySet();
261
+ this._selectedItemsSetMap.set(level, selectedItemsSet);
262
+ }
263
+ return selectedItemsSet;
264
+ }
265
+ getSelectionLevels() {
266
+ const levels = new Array();
267
+ for (const entry of this._selectedItemsSetMap.entries()) {
268
+ if (!entry[1].isEmpty)
269
+ levels.push(entry[0]);
270
+ }
271
+ return levels.sort();
272
+ }
273
+ clear(level) {
274
+ const keys = this._selectedItemsSetMap.keys();
275
+ for (const key of keys) {
276
+ if (key >= level) {
277
+ const selectedItemsSet = this._selectedItemsSetMap.get(key);
278
+ selectedItemsSet.clear();
279
+ }
280
+ }
281
+ }
282
+ }
283
+ /** @internal */
284
+ export const TRANSIENT_ELEMENT_CLASSNAME = "/TRANSIENT";
285
+ /** @internal */
286
+ export class ToolSelectionSyncHandler {
287
+ constructor(imodel, logicalSelection) {
288
+ this._selectionSourceName = "Tool";
289
+ this._asyncsTracker = new AsyncTasksTracker();
290
+ // eslint-disable-next-line @typescript-eslint/naming-convention
291
+ this.onToolSelectionChanged = async (ev) => {
292
+ // ignore selection change event if the handler is suspended
293
+ if (this.isSuspended)
294
+ return;
295
+ // this component only cares about its own imodel
296
+ const imodel = ev.set.iModel;
297
+ if (imodel !== this._imodel)
298
+ return;
299
+ // determine the level of selection changes
300
+ // wip: may want to allow selecting at different levels?
301
+ const selectionLevel = 0;
302
+ let ids;
303
+ switch (ev.type) {
304
+ case SelectionSetEventType.Add:
305
+ ids = ev.added;
306
+ break;
307
+ case SelectionSetEventType.Replace:
308
+ ids = ev.set.elements;
309
+ break;
310
+ default:
311
+ ids = ev.removed;
312
+ break;
313
+ }
314
+ // we're always using scoped selection changer even if the scope is set to "element" - that
315
+ // makes sure we're adding to selection keys with concrete classes and not "BisCore:Element", which
316
+ // we can't because otherwise our keys compare fails (presentation components load data with
317
+ // concrete classes)
318
+ const changer = new ScopedSelectionChanger(this._selectionSourceName, this._imodel, this._logicalSelection, createSelectionScopeProps(this._logicalSelection.scopes.activeScope));
319
+ // we know what to do immediately on `clear` events
320
+ if (SelectionSetEventType.Clear === ev.type) {
321
+ await changer.clear(selectionLevel);
322
+ return;
323
+ }
324
+ const parsedIds = parseIds(ids);
325
+ await using(this._asyncsTracker.trackAsyncTask(), async (_r) => {
326
+ switch (ev.type) {
327
+ case SelectionSetEventType.Add:
328
+ await changer.add(parsedIds.transient, parsedIds.persistent, selectionLevel);
329
+ break;
330
+ case SelectionSetEventType.Replace:
331
+ await changer.replace(parsedIds.transient, parsedIds.persistent, selectionLevel);
332
+ break;
333
+ case SelectionSetEventType.Remove:
334
+ await changer.remove(parsedIds.transient, parsedIds.persistent, selectionLevel);
335
+ break;
336
+ }
337
+ });
338
+ };
339
+ this._imodel = imodel;
340
+ this._logicalSelection = logicalSelection;
341
+ this._imodelToolSelectionListenerDisposeFunc = imodel.selectionSet.onChanged.addListener(this.onToolSelectionChanged);
342
+ }
343
+ dispose() {
344
+ this._imodelToolSelectionListenerDisposeFunc();
345
+ }
346
+ /** note: used only it tests */
347
+ get pendingAsyncs() { return this._asyncsTracker.pendingAsyncs; }
348
+ }
349
+ const parseIds = (ids) => {
350
+ let allPersistent = true;
351
+ let allTransient = true;
352
+ for (const id of Id64.iterable(ids)) {
353
+ if (Id64.isTransient(id))
354
+ allPersistent = false;
355
+ else
356
+ allTransient = false;
357
+ if (!allPersistent && !allTransient)
358
+ break;
359
+ }
360
+ // avoid making a copy if ids are only persistent or only transient
361
+ if (allPersistent) {
362
+ return { persistent: ids, transient: [] };
363
+ }
364
+ else if (allTransient) {
365
+ return { persistent: [], transient: ids };
366
+ }
367
+ // if `ids` contain mixed ids, we have to copy.. use Array instead of
368
+ // a Set for performance
369
+ const persistentElementIds = [];
370
+ const transientElementIds = [];
371
+ for (const id of Id64.iterable(ids)) {
372
+ if (Id64.isTransient(id))
373
+ transientElementIds.push(id);
374
+ else
375
+ persistentElementIds.push(id);
376
+ }
377
+ return { persistent: persistentElementIds, transient: transientElementIds };
378
+ };
379
+ function addTransientKeys(transientIds, keys) {
380
+ for (const id of Id64.iterable(transientIds))
381
+ keys.add({ className: TRANSIENT_ELEMENT_CLASSNAME, id });
382
+ }
383
+ /** @internal */
384
+ class ScopedSelectionChanger {
385
+ constructor(name, imodel, manager, scope) {
386
+ this.name = name;
387
+ this.imodel = imodel;
388
+ this.manager = manager;
389
+ this.scope = scope;
390
+ }
391
+ async clear(level) {
392
+ this.manager.clearSelection(this.name, this.imodel, level);
393
+ }
394
+ async add(transientIds, persistentIds, level) {
395
+ const keys = await this.manager.scopes.computeSelection(this.imodel, persistentIds, this.scope);
396
+ addTransientKeys(transientIds, keys);
397
+ this.manager.addToSelection(this.name, this.imodel, keys, level);
398
+ }
399
+ async remove(transientIds, persistentIds, level) {
400
+ const keys = await this.manager.scopes.computeSelection(this.imodel, persistentIds, this.scope);
401
+ addTransientKeys(transientIds, keys);
402
+ this.manager.removeFromSelection(this.name, this.imodel, keys, level);
403
+ }
404
+ async replace(transientIds, persistentIds, level) {
405
+ const keys = await this.manager.scopes.computeSelection(this.imodel, persistentIds, this.scope);
406
+ addTransientKeys(transientIds, keys);
407
+ this.manager.replaceSelection(this.name, this.imodel, keys, level);
408
+ }
409
+ }
410
410
  //# sourceMappingURL=SelectionManager.js.map