@itwin/presentation-frontend 4.5.0-dev.9 → 4.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +63 -1
- package/LICENSE.md +1 -1
- package/README.md +1 -1
- package/lib/cjs/presentation-frontend/ConnectivityInformationProvider.d.ts.map +1 -1
- package/lib/cjs/presentation-frontend/ConnectivityInformationProvider.js +10 -6
- package/lib/cjs/presentation-frontend/ConnectivityInformationProvider.js.map +1 -1
- package/lib/cjs/presentation-frontend/Diagnostics.d.ts.map +1 -1
- package/lib/cjs/presentation-frontend/Diagnostics.js +18 -13
- package/lib/cjs/presentation-frontend/Diagnostics.js.map +1 -1
- package/lib/cjs/presentation-frontend/FrontendLoggerCategory.js +3 -3
- package/lib/cjs/presentation-frontend/FrontendLoggerCategory.js.map +1 -1
- package/lib/cjs/presentation-frontend/IpcRequestsHandler.d.ts.map +1 -1
- package/lib/cjs/presentation-frontend/IpcRequestsHandler.js +3 -3
- package/lib/cjs/presentation-frontend/IpcRequestsHandler.js.map +1 -1
- package/lib/cjs/presentation-frontend/LocalizationHelper.js +3 -3
- package/lib/cjs/presentation-frontend/LocalizationHelper.js.map +1 -1
- package/lib/cjs/presentation-frontend/Presentation.d.ts +1 -1
- package/lib/cjs/presentation-frontend/Presentation.d.ts.map +1 -1
- package/lib/cjs/presentation-frontend/Presentation.js +36 -21
- package/lib/cjs/presentation-frontend/Presentation.js.map +1 -1
- package/lib/cjs/presentation-frontend/PresentationManager.d.ts +84 -21
- package/lib/cjs/presentation-frontend/PresentationManager.d.ts.map +1 -1
- package/lib/cjs/presentation-frontend/PresentationManager.js +245 -154
- package/lib/cjs/presentation-frontend/PresentationManager.js.map +1 -1
- package/lib/cjs/presentation-frontend/RulesetManager.d.ts.map +1 -1
- package/lib/cjs/presentation-frontend/RulesetManager.js +11 -7
- package/lib/cjs/presentation-frontend/RulesetManager.js.map +1 -1
- package/lib/cjs/presentation-frontend/RulesetVariablesManager.d.ts.map +1 -1
- package/lib/cjs/presentation-frontend/RulesetVariablesManager.js +53 -31
- package/lib/cjs/presentation-frontend/RulesetVariablesManager.js.map +1 -1
- package/lib/cjs/presentation-frontend/StreamedResponseGenerator.d.ts +30 -0
- package/lib/cjs/presentation-frontend/StreamedResponseGenerator.d.ts.map +1 -0
- package/lib/cjs/presentation-frontend/StreamedResponseGenerator.js +117 -0
- package/lib/cjs/presentation-frontend/StreamedResponseGenerator.js.map +1 -0
- package/lib/cjs/presentation-frontend/favorite-properties/FavoritePropertiesManager.d.ts +33 -4
- package/lib/cjs/presentation-frontend/favorite-properties/FavoritePropertiesManager.d.ts.map +1 -1
- package/lib/cjs/presentation-frontend/favorite-properties/FavoritePropertiesManager.js +172 -67
- package/lib/cjs/presentation-frontend/favorite-properties/FavoritePropertiesManager.js.map +1 -1
- package/lib/cjs/presentation-frontend/favorite-properties/FavoritePropertiesStorage.d.ts.map +1 -1
- package/lib/cjs/presentation-frontend/favorite-properties/FavoritePropertiesStorage.js +54 -25
- package/lib/cjs/presentation-frontend/favorite-properties/FavoritePropertiesStorage.js.map +1 -1
- package/lib/cjs/presentation-frontend/selection/HiliteSetProvider.d.ts.map +1 -1
- package/lib/cjs/presentation-frontend/selection/HiliteSetProvider.js +23 -13
- package/lib/cjs/presentation-frontend/selection/HiliteSetProvider.js.map +1 -1
- package/lib/cjs/presentation-frontend/selection/ISelectionProvider.js +3 -3
- package/lib/cjs/presentation-frontend/selection/ISelectionProvider.js.map +1 -1
- package/lib/cjs/presentation-frontend/selection/SelectionChangeEvent.d.ts.map +1 -1
- package/lib/cjs/presentation-frontend/selection/SelectionChangeEvent.js +3 -3
- package/lib/cjs/presentation-frontend/selection/SelectionChangeEvent.js.map +1 -1
- package/lib/cjs/presentation-frontend/selection/SelectionHandler.d.ts.map +1 -1
- package/lib/cjs/presentation-frontend/selection/SelectionHandler.js +15 -9
- package/lib/cjs/presentation-frontend/selection/SelectionHandler.js.map +1 -1
- package/lib/cjs/presentation-frontend/selection/SelectionHelper.d.ts.map +1 -1
- package/lib/cjs/presentation-frontend/selection/SelectionHelper.js +7 -5
- package/lib/cjs/presentation-frontend/selection/SelectionHelper.js.map +1 -1
- package/lib/cjs/presentation-frontend/selection/SelectionManager.d.ts +22 -3
- package/lib/cjs/presentation-frontend/selection/SelectionManager.d.ts.map +1 -1
- package/lib/cjs/presentation-frontend/selection/SelectionManager.js +295 -75
- package/lib/cjs/presentation-frontend/selection/SelectionManager.js.map +1 -1
- package/lib/cjs/presentation-frontend/selection/SelectionScopesManager.d.ts.map +1 -1
- package/lib/cjs/presentation-frontend/selection/SelectionScopesManager.js +25 -14
- package/lib/cjs/presentation-frontend/selection/SelectionScopesManager.js.map +1 -1
- package/lib/cjs/presentation-frontend.js +3 -3
- package/lib/cjs/presentation-frontend.js.map +1 -1
- package/lib/esm/presentation-frontend/ConnectivityInformationProvider.d.ts.map +1 -1
- package/lib/esm/presentation-frontend/ConnectivityInformationProvider.js +10 -6
- package/lib/esm/presentation-frontend/ConnectivityInformationProvider.js.map +1 -1
- package/lib/esm/presentation-frontend/Diagnostics.d.ts.map +1 -1
- package/lib/esm/presentation-frontend/Diagnostics.js +18 -13
- package/lib/esm/presentation-frontend/Diagnostics.js.map +1 -1
- package/lib/esm/presentation-frontend/FrontendLoggerCategory.js +3 -3
- package/lib/esm/presentation-frontend/FrontendLoggerCategory.js.map +1 -1
- package/lib/esm/presentation-frontend/IpcRequestsHandler.d.ts.map +1 -1
- package/lib/esm/presentation-frontend/IpcRequestsHandler.js +3 -3
- package/lib/esm/presentation-frontend/IpcRequestsHandler.js.map +1 -1
- package/lib/esm/presentation-frontend/LocalizationHelper.js +3 -3
- package/lib/esm/presentation-frontend/LocalizationHelper.js.map +1 -1
- package/lib/esm/presentation-frontend/Presentation.d.ts +1 -1
- package/lib/esm/presentation-frontend/Presentation.d.ts.map +1 -1
- package/lib/esm/presentation-frontend/Presentation.js +36 -21
- package/lib/esm/presentation-frontend/Presentation.js.map +1 -1
- package/lib/esm/presentation-frontend/PresentationManager.d.ts +84 -21
- package/lib/esm/presentation-frontend/PresentationManager.d.ts.map +1 -1
- package/lib/esm/presentation-frontend/PresentationManager.js +244 -152
- package/lib/esm/presentation-frontend/PresentationManager.js.map +1 -1
- package/lib/esm/presentation-frontend/RulesetManager.d.ts.map +1 -1
- package/lib/esm/presentation-frontend/RulesetManager.js +11 -7
- package/lib/esm/presentation-frontend/RulesetManager.js.map +1 -1
- package/lib/esm/presentation-frontend/RulesetVariablesManager.d.ts.map +1 -1
- package/lib/esm/presentation-frontend/RulesetVariablesManager.js +53 -31
- package/lib/esm/presentation-frontend/RulesetVariablesManager.js.map +1 -1
- package/lib/esm/presentation-frontend/StreamedResponseGenerator.d.ts +30 -0
- package/lib/esm/presentation-frontend/StreamedResponseGenerator.d.ts.map +1 -0
- package/lib/esm/presentation-frontend/StreamedResponseGenerator.js +113 -0
- package/lib/esm/presentation-frontend/StreamedResponseGenerator.js.map +1 -0
- package/lib/esm/presentation-frontend/favorite-properties/FavoritePropertiesManager.d.ts +33 -4
- package/lib/esm/presentation-frontend/favorite-properties/FavoritePropertiesManager.d.ts.map +1 -1
- package/lib/esm/presentation-frontend/favorite-properties/FavoritePropertiesManager.js +172 -67
- package/lib/esm/presentation-frontend/favorite-properties/FavoritePropertiesManager.js.map +1 -1
- package/lib/esm/presentation-frontend/favorite-properties/FavoritePropertiesStorage.d.ts.map +1 -1
- package/lib/esm/presentation-frontend/favorite-properties/FavoritePropertiesStorage.js +54 -25
- package/lib/esm/presentation-frontend/favorite-properties/FavoritePropertiesStorage.js.map +1 -1
- package/lib/esm/presentation-frontend/selection/HiliteSetProvider.d.ts.map +1 -1
- package/lib/esm/presentation-frontend/selection/HiliteSetProvider.js +24 -14
- package/lib/esm/presentation-frontend/selection/HiliteSetProvider.js.map +1 -1
- package/lib/esm/presentation-frontend/selection/ISelectionProvider.js +3 -3
- package/lib/esm/presentation-frontend/selection/ISelectionProvider.js.map +1 -1
- package/lib/esm/presentation-frontend/selection/SelectionChangeEvent.d.ts.map +1 -1
- package/lib/esm/presentation-frontend/selection/SelectionChangeEvent.js +3 -3
- package/lib/esm/presentation-frontend/selection/SelectionChangeEvent.js.map +1 -1
- package/lib/esm/presentation-frontend/selection/SelectionHandler.d.ts.map +1 -1
- package/lib/esm/presentation-frontend/selection/SelectionHandler.js +15 -9
- package/lib/esm/presentation-frontend/selection/SelectionHandler.js.map +1 -1
- package/lib/esm/presentation-frontend/selection/SelectionHelper.d.ts.map +1 -1
- package/lib/esm/presentation-frontend/selection/SelectionHelper.js +7 -5
- package/lib/esm/presentation-frontend/selection/SelectionHelper.js.map +1 -1
- package/lib/esm/presentation-frontend/selection/SelectionManager.d.ts +22 -3
- package/lib/esm/presentation-frontend/selection/SelectionManager.d.ts.map +1 -1
- package/lib/esm/presentation-frontend/selection/SelectionManager.js +295 -75
- package/lib/esm/presentation-frontend/selection/SelectionManager.js.map +1 -1
- package/lib/esm/presentation-frontend/selection/SelectionScopesManager.d.ts.map +1 -1
- package/lib/esm/presentation-frontend/selection/SelectionScopesManager.js +25 -14
- package/lib/esm/presentation-frontend/selection/SelectionScopesManager.js.map +1 -1
- package/lib/esm/presentation-frontend.js +3 -3
- package/lib/esm/presentation-frontend.js.map +1 -1
- package/package.json +20 -16
|
@@ -1,13 +1,16 @@
|
|
|
1
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
|
-
*--------------------------------------------------------------------------------------------*/
|
|
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
5
|
/** @packageDocumentation
|
|
6
6
|
* @module UnifiedSelection
|
|
7
7
|
*/
|
|
8
|
+
import { defer, EMPTY, mergeMap, of, Subject, takeUntil, tap } from "rxjs";
|
|
8
9
|
import { Id64, using } from "@itwin/core-bentley";
|
|
9
10
|
import { IModelConnection, SelectionSetEventType } from "@itwin/core-frontend";
|
|
10
|
-
import { AsyncTasksTracker, KeySet } from "@itwin/presentation-common";
|
|
11
|
+
import { AsyncTasksTracker, KeySet, NodeKey } from "@itwin/presentation-common";
|
|
12
|
+
import { createStorage, } from "@itwin/unified-selection";
|
|
13
|
+
import { Presentation } from "../Presentation";
|
|
11
14
|
import { HiliteSetProvider } from "./HiliteSetProvider";
|
|
12
15
|
import { SelectionChangeEvent, SelectionChangeType } from "./SelectionChangeEvent";
|
|
13
16
|
import { createSelectionScopeProps } from "./SelectionScopesManager";
|
|
@@ -20,31 +23,43 @@ export class SelectionManager {
|
|
|
20
23
|
* Creates an instance of SelectionManager.
|
|
21
24
|
*/
|
|
22
25
|
constructor(props) {
|
|
23
|
-
this._selectionContainerMap = new Map();
|
|
24
26
|
this._imodelToolSelectionSyncHandlers = new Map();
|
|
25
27
|
this._hiliteSetProviders = new Map();
|
|
28
|
+
this._knownIModels = new Map();
|
|
29
|
+
this._currentSelection = new CurrentSelectionStorage();
|
|
30
|
+
this._selectionChanges = new Subject();
|
|
31
|
+
this._listeners = [];
|
|
26
32
|
this.selectionChange = new SelectionChangeEvent();
|
|
27
33
|
this.scopes = props.scopes;
|
|
28
|
-
|
|
34
|
+
this._selectionStorage = props.selectionStorage ?? createStorage();
|
|
35
|
+
this._ownsStorage = props.selectionStorage === undefined;
|
|
36
|
+
this._selectionStorage.selectionChangeEvent.addListener((args) => this._selectionChanges.next(args));
|
|
37
|
+
this._selectionEventsSubscription = this.streamSelectionEvents();
|
|
38
|
+
this._listeners.push(IModelConnection.onOpen.addListener((imodel) => {
|
|
39
|
+
this._knownIModels.set(imodel.key, imodel);
|
|
40
|
+
}));
|
|
41
|
+
this._listeners.push(IModelConnection.onClose.addListener((imodel) => {
|
|
29
42
|
this.onConnectionClose(imodel);
|
|
30
|
-
});
|
|
43
|
+
}));
|
|
44
|
+
}
|
|
45
|
+
dispose() {
|
|
46
|
+
this._selectionEventsSubscription.unsubscribe();
|
|
47
|
+
this._listeners.forEach((dispose) => dispose());
|
|
31
48
|
}
|
|
32
49
|
onConnectionClose(imodel) {
|
|
33
|
-
this.clearSelection("Connection Close Event", imodel);
|
|
34
|
-
this._selectionContainerMap.delete(imodel);
|
|
35
50
|
this._hiliteSetProviders.delete(imodel);
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
this._selectionContainerMap.set(imodel, selectionContainer);
|
|
51
|
+
this._knownIModels.delete(imodel.key);
|
|
52
|
+
this._currentSelection.clear(imodel.key);
|
|
53
|
+
if (this._ownsStorage) {
|
|
54
|
+
this.clearSelection("Connection Close Event", imodel);
|
|
55
|
+
this._selectionStorage.clearStorage({ iModelKey: imodel.key });
|
|
42
56
|
}
|
|
43
|
-
return selectionContainer;
|
|
44
57
|
}
|
|
45
58
|
/** @internal */
|
|
46
59
|
// istanbul ignore next
|
|
47
|
-
getToolSelectionSyncHandler(imodel) {
|
|
60
|
+
getToolSelectionSyncHandler(imodel) {
|
|
61
|
+
return this._imodelToolSelectionSyncHandlers.get(imodel)?.handler;
|
|
62
|
+
}
|
|
48
63
|
/**
|
|
49
64
|
* Request the manager to sync with imodel's tool selection (see `IModelConnection.selectionSet`).
|
|
50
65
|
*/
|
|
@@ -77,46 +92,57 @@ export class SelectionManager {
|
|
|
77
92
|
*/
|
|
78
93
|
suspendIModelToolSelectionSync(imodel) {
|
|
79
94
|
const registration = this._imodelToolSelectionSyncHandlers.get(imodel);
|
|
80
|
-
if (!registration)
|
|
95
|
+
if (!registration) {
|
|
81
96
|
return { dispose: () => { } };
|
|
97
|
+
}
|
|
82
98
|
const wasSuspended = registration.handler.isSuspended;
|
|
83
99
|
registration.handler.isSuspended = true;
|
|
84
100
|
return { dispose: () => (registration.handler.isSuspended = wasSuspended) };
|
|
85
101
|
}
|
|
86
102
|
/** Get the selection levels currently stored in this manager for the specified imodel */
|
|
87
103
|
getSelectionLevels(imodel) {
|
|
88
|
-
return this.
|
|
104
|
+
return this._selectionStorage.getSelectionLevels({ iModelKey: imodel.key });
|
|
89
105
|
}
|
|
90
|
-
/**
|
|
106
|
+
/**
|
|
107
|
+
* Get the selection currently stored in this manager
|
|
108
|
+
*
|
|
109
|
+
* @note Calling immediately after `add*`|`replace*`|`remove*`|`clear*` method call does not guarantee
|
|
110
|
+
* that returned `KeySet` will include latest changes. Listen for `selectionChange` event to get the
|
|
111
|
+
* latest selection after changes.
|
|
112
|
+
*/
|
|
91
113
|
getSelection(imodel, level = 0) {
|
|
92
|
-
return this.
|
|
114
|
+
return this._currentSelection.getSelection(imodel.key, level);
|
|
93
115
|
}
|
|
94
116
|
handleEvent(evt) {
|
|
95
|
-
const container = this.getContainer(evt.imodel);
|
|
96
|
-
const selectedItemsSet = container.getSelection(evt.level);
|
|
97
|
-
const guidBefore = selectedItemsSet.guid;
|
|
98
117
|
switch (evt.changeType) {
|
|
99
118
|
case SelectionChangeType.Add:
|
|
100
|
-
|
|
119
|
+
this._selectionStorage.addToSelection({
|
|
120
|
+
iModelKey: evt.imodel.key,
|
|
121
|
+
source: evt.source,
|
|
122
|
+
level: evt.level,
|
|
123
|
+
selectables: keysToSelectable(evt.imodel, evt.keys),
|
|
124
|
+
});
|
|
101
125
|
break;
|
|
102
126
|
case SelectionChangeType.Remove:
|
|
103
|
-
|
|
127
|
+
this._selectionStorage.removeFromSelection({
|
|
128
|
+
iModelKey: evt.imodel.key,
|
|
129
|
+
source: evt.source,
|
|
130
|
+
level: evt.level,
|
|
131
|
+
selectables: keysToSelectable(evt.imodel, evt.keys),
|
|
132
|
+
});
|
|
104
133
|
break;
|
|
105
134
|
case SelectionChangeType.Replace:
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
135
|
+
this._selectionStorage.replaceSelection({
|
|
136
|
+
iModelKey: evt.imodel.key,
|
|
137
|
+
source: evt.source,
|
|
138
|
+
level: evt.level,
|
|
139
|
+
selectables: keysToSelectable(evt.imodel, evt.keys),
|
|
140
|
+
});
|
|
111
141
|
break;
|
|
112
142
|
case SelectionChangeType.Clear:
|
|
113
|
-
|
|
143
|
+
this._selectionStorage.clearSelection({ iModelKey: evt.imodel.key, source: evt.source, level: evt.level });
|
|
114
144
|
break;
|
|
115
145
|
}
|
|
116
|
-
if (selectedItemsSet.guid === guidBefore)
|
|
117
|
-
return;
|
|
118
|
-
container.clear(evt.level + 1);
|
|
119
|
-
this.selectionChange.raiseEvent(evt, this);
|
|
120
146
|
}
|
|
121
147
|
/**
|
|
122
148
|
* Add keys to the selection
|
|
@@ -258,36 +284,30 @@ export class SelectionManager {
|
|
|
258
284
|
}
|
|
259
285
|
return provider;
|
|
260
286
|
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
for (const key of keys) {
|
|
286
|
-
if (key >= level) {
|
|
287
|
-
const selectedItemsSet = this._selectedItemsSetMap.get(key);
|
|
288
|
-
selectedItemsSet.clear();
|
|
289
|
-
}
|
|
290
|
-
}
|
|
287
|
+
streamSelectionEvents() {
|
|
288
|
+
return this._selectionChanges
|
|
289
|
+
.pipe(mergeMap((args) => {
|
|
290
|
+
const currentSelectables = this._selectionStorage.getSelection({ iModelKey: args.iModelKey, level: args.level });
|
|
291
|
+
return this._currentSelection.computeSelection(args.iModelKey, args.level, currentSelectables, args.selectables).pipe(mergeMap(({ level, changedSelection }) => {
|
|
292
|
+
const imodel = this._knownIModels.get(args.iModelKey);
|
|
293
|
+
if (!imodel) {
|
|
294
|
+
return EMPTY;
|
|
295
|
+
}
|
|
296
|
+
return of({
|
|
297
|
+
imodel,
|
|
298
|
+
keys: changedSelection,
|
|
299
|
+
level,
|
|
300
|
+
source: args.source,
|
|
301
|
+
timestamp: args.timestamp,
|
|
302
|
+
changeType: getChangeType(args.changeType),
|
|
303
|
+
});
|
|
304
|
+
}));
|
|
305
|
+
}))
|
|
306
|
+
.subscribe({
|
|
307
|
+
next: (args) => {
|
|
308
|
+
this.selectionChange.raiseEvent(args, this);
|
|
309
|
+
},
|
|
310
|
+
});
|
|
291
311
|
}
|
|
292
312
|
}
|
|
293
313
|
/** @internal */
|
|
@@ -300,12 +320,14 @@ export class ToolSelectionSyncHandler {
|
|
|
300
320
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
301
321
|
this.onToolSelectionChanged = async (ev) => {
|
|
302
322
|
// ignore selection change event if the handler is suspended
|
|
303
|
-
if (this.isSuspended)
|
|
323
|
+
if (this.isSuspended) {
|
|
304
324
|
return;
|
|
325
|
+
}
|
|
305
326
|
// this component only cares about its own imodel
|
|
306
327
|
const imodel = ev.set.iModel;
|
|
307
|
-
if (imodel !== this._imodel)
|
|
328
|
+
if (imodel !== this._imodel) {
|
|
308
329
|
return;
|
|
330
|
+
}
|
|
309
331
|
// determine the level of selection changes
|
|
310
332
|
// wip: may want to allow selecting at different levels?
|
|
311
333
|
const selectionLevel = 0;
|
|
@@ -354,18 +376,23 @@ export class ToolSelectionSyncHandler {
|
|
|
354
376
|
this._imodelToolSelectionListenerDisposeFunc();
|
|
355
377
|
}
|
|
356
378
|
/** note: used only it tests */
|
|
357
|
-
get pendingAsyncs() {
|
|
379
|
+
get pendingAsyncs() {
|
|
380
|
+
return this._asyncsTracker.pendingAsyncs;
|
|
381
|
+
}
|
|
358
382
|
}
|
|
359
383
|
const parseIds = (ids) => {
|
|
360
384
|
let allPersistent = true;
|
|
361
385
|
let allTransient = true;
|
|
362
386
|
for (const id of Id64.iterable(ids)) {
|
|
363
|
-
if (Id64.isTransient(id))
|
|
387
|
+
if (Id64.isTransient(id)) {
|
|
364
388
|
allPersistent = false;
|
|
365
|
-
|
|
389
|
+
}
|
|
390
|
+
else {
|
|
366
391
|
allTransient = false;
|
|
367
|
-
|
|
392
|
+
}
|
|
393
|
+
if (!allPersistent && !allTransient) {
|
|
368
394
|
break;
|
|
395
|
+
}
|
|
369
396
|
}
|
|
370
397
|
// avoid making a copy if ids are only persistent or only transient
|
|
371
398
|
if (allPersistent) {
|
|
@@ -379,16 +406,19 @@ const parseIds = (ids) => {
|
|
|
379
406
|
const persistentElementIds = [];
|
|
380
407
|
const transientElementIds = [];
|
|
381
408
|
for (const id of Id64.iterable(ids)) {
|
|
382
|
-
if (Id64.isTransient(id))
|
|
409
|
+
if (Id64.isTransient(id)) {
|
|
383
410
|
transientElementIds.push(id);
|
|
384
|
-
|
|
411
|
+
}
|
|
412
|
+
else {
|
|
385
413
|
persistentElementIds.push(id);
|
|
414
|
+
}
|
|
386
415
|
}
|
|
387
416
|
return { persistent: persistentElementIds, transient: transientElementIds };
|
|
388
417
|
};
|
|
389
418
|
function addTransientKeys(transientIds, keys) {
|
|
390
|
-
for (const id of Id64.iterable(transientIds))
|
|
419
|
+
for (const id of Id64.iterable(transientIds)) {
|
|
391
420
|
keys.add({ className: TRANSIENT_ELEMENT_CLASSNAME, id });
|
|
421
|
+
}
|
|
392
422
|
}
|
|
393
423
|
/** @internal */
|
|
394
424
|
class ScopedSelectionChanger {
|
|
@@ -417,4 +447,194 @@ class ScopedSelectionChanger {
|
|
|
417
447
|
this.manager.replaceSelection(this.name, this.imodel, keys, level);
|
|
418
448
|
}
|
|
419
449
|
}
|
|
450
|
+
/** Stores current selection in `KeySet` format per iModel. */
|
|
451
|
+
class CurrentSelectionStorage {
|
|
452
|
+
constructor() {
|
|
453
|
+
this._currentSelection = new Map();
|
|
454
|
+
}
|
|
455
|
+
getCurrentSelectionStorage(imodelKey) {
|
|
456
|
+
let storage = this._currentSelection.get(imodelKey);
|
|
457
|
+
if (!storage) {
|
|
458
|
+
storage = new IModelSelectionStorage();
|
|
459
|
+
this._currentSelection.set(imodelKey, storage);
|
|
460
|
+
}
|
|
461
|
+
return storage;
|
|
462
|
+
}
|
|
463
|
+
getSelection(imodelKey, level) {
|
|
464
|
+
return this.getCurrentSelectionStorage(imodelKey).getSelection(level);
|
|
465
|
+
}
|
|
466
|
+
clear(imodelKey) {
|
|
467
|
+
this._currentSelection.delete(imodelKey);
|
|
468
|
+
}
|
|
469
|
+
computeSelection(imodelKey, level, currSelectables, changedSelectables) {
|
|
470
|
+
return this.getCurrentSelectionStorage(imodelKey).computeSelection(level, currSelectables, changedSelectables);
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
/**
|
|
474
|
+
* Computes and stores current selection in `KeySet` format.
|
|
475
|
+
* It always stores result of latest resolved call to `computeSelection`.
|
|
476
|
+
*/
|
|
477
|
+
class IModelSelectionStorage {
|
|
478
|
+
constructor() {
|
|
479
|
+
this._currentSelection = new Map();
|
|
480
|
+
}
|
|
481
|
+
getSelection(level) {
|
|
482
|
+
let entry = this._currentSelection.get(level);
|
|
483
|
+
if (!entry) {
|
|
484
|
+
entry = { value: new KeySet(), ongoingComputationDisposers: new Set() };
|
|
485
|
+
this._currentSelection.set(level, entry);
|
|
486
|
+
}
|
|
487
|
+
return entry.value;
|
|
488
|
+
}
|
|
489
|
+
clearSelections(level) {
|
|
490
|
+
const clearedLevels = [];
|
|
491
|
+
for (const [storedLevel] of this._currentSelection.entries()) {
|
|
492
|
+
if (storedLevel > level) {
|
|
493
|
+
clearedLevels.push(storedLevel);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
clearedLevels.forEach((storedLevel) => {
|
|
497
|
+
const entry = this._currentSelection.get(storedLevel);
|
|
498
|
+
// istanbul ignore if
|
|
499
|
+
if (!entry) {
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
502
|
+
for (const disposer of entry.ongoingComputationDisposers) {
|
|
503
|
+
disposer.next();
|
|
504
|
+
}
|
|
505
|
+
this._currentSelection.delete(storedLevel);
|
|
506
|
+
});
|
|
507
|
+
}
|
|
508
|
+
addDisposer(level, disposer) {
|
|
509
|
+
const entry = this._currentSelection.get(level);
|
|
510
|
+
if (!entry) {
|
|
511
|
+
this._currentSelection.set(level, { value: new KeySet(), ongoingComputationDisposers: new Set([disposer]) });
|
|
512
|
+
return;
|
|
513
|
+
}
|
|
514
|
+
entry.ongoingComputationDisposers.add(disposer);
|
|
515
|
+
}
|
|
516
|
+
setSelection(level, keys, disposer) {
|
|
517
|
+
const currEntry = this._currentSelection.get(level);
|
|
518
|
+
// istanbul ignore else
|
|
519
|
+
if (currEntry) {
|
|
520
|
+
currEntry.ongoingComputationDisposers.delete(disposer);
|
|
521
|
+
}
|
|
522
|
+
this._currentSelection.set(level, {
|
|
523
|
+
value: keys,
|
|
524
|
+
ongoingComputationDisposers: currEntry?.ongoingComputationDisposers ?? /* istanbul ignore next */ new Set(),
|
|
525
|
+
});
|
|
526
|
+
}
|
|
527
|
+
computeSelection(level, currSelectables, changedSelectables) {
|
|
528
|
+
this.clearSelections(level);
|
|
529
|
+
const prevComputationsDisposers = [...(this._currentSelection.get(level)?.ongoingComputationDisposers ?? [])];
|
|
530
|
+
const currDisposer = new Subject();
|
|
531
|
+
this.addDisposer(level, currDisposer);
|
|
532
|
+
return defer(async () => {
|
|
533
|
+
const convertedSelectables = [];
|
|
534
|
+
const [current, changed] = await Promise.all([
|
|
535
|
+
selectablesToKeys(currSelectables, convertedSelectables),
|
|
536
|
+
selectablesToKeys(changedSelectables, convertedSelectables),
|
|
537
|
+
]);
|
|
538
|
+
const currentSelection = new KeySet([...current.keys, ...current.selectableKeys.flatMap((selectable) => selectable.keys)]);
|
|
539
|
+
const changedSelection = new KeySet([...changed.keys, ...changed.selectableKeys.flatMap((selectable) => selectable.keys)]);
|
|
540
|
+
return {
|
|
541
|
+
level,
|
|
542
|
+
currentSelection,
|
|
543
|
+
changedSelection,
|
|
544
|
+
};
|
|
545
|
+
}).pipe(takeUntil(currDisposer), tap({
|
|
546
|
+
next: (val) => {
|
|
547
|
+
prevComputationsDisposers.forEach((disposer) => disposer.next());
|
|
548
|
+
this.setSelection(val.level, val.currentSelection, currDisposer);
|
|
549
|
+
},
|
|
550
|
+
}));
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
function keysToSelectable(imodel, keys) {
|
|
554
|
+
const selectables = [];
|
|
555
|
+
keys.forEach((key) => {
|
|
556
|
+
if ("id" in key) {
|
|
557
|
+
selectables.push(key);
|
|
558
|
+
return;
|
|
559
|
+
}
|
|
560
|
+
const customSelectable = {
|
|
561
|
+
identifier: key.pathFromRoot.join("/"),
|
|
562
|
+
data: key,
|
|
563
|
+
loadInstanceKeys: () => createInstanceKeysIterator(imodel, key),
|
|
564
|
+
};
|
|
565
|
+
selectables.push(customSelectable);
|
|
566
|
+
});
|
|
567
|
+
return selectables;
|
|
568
|
+
}
|
|
569
|
+
async function selectablesToKeys(selectables, convertedList) {
|
|
570
|
+
const keys = [];
|
|
571
|
+
const selectableKeys = [];
|
|
572
|
+
for (const [className, ids] of selectables.instanceKeys) {
|
|
573
|
+
for (const id of ids) {
|
|
574
|
+
keys.push({ id, className });
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
for (const [_, selectable] of selectables.custom) {
|
|
578
|
+
if (isNodeKey(selectable.data)) {
|
|
579
|
+
selectableKeys.push({ identifier: selectable.identifier, keys: [selectable.data] });
|
|
580
|
+
continue;
|
|
581
|
+
}
|
|
582
|
+
const converted = convertedList.find((con) => con.identifier === selectable.identifier);
|
|
583
|
+
if (converted) {
|
|
584
|
+
selectableKeys.push(converted);
|
|
585
|
+
continue;
|
|
586
|
+
}
|
|
587
|
+
const newConverted = { identifier: selectable.identifier, keys: [] };
|
|
588
|
+
convertedList.push(newConverted);
|
|
589
|
+
for await (const instanceKey of selectable.loadInstanceKeys()) {
|
|
590
|
+
newConverted.keys.push(instanceKey);
|
|
591
|
+
}
|
|
592
|
+
selectableKeys.push(newConverted);
|
|
593
|
+
}
|
|
594
|
+
return { keys, selectableKeys };
|
|
595
|
+
}
|
|
596
|
+
async function* createInstanceKeysIterator(imodel, nodeKey) {
|
|
597
|
+
if (NodeKey.isInstancesNodeKey(nodeKey)) {
|
|
598
|
+
for (const key of nodeKey.instanceKeys) {
|
|
599
|
+
yield key;
|
|
600
|
+
}
|
|
601
|
+
return;
|
|
602
|
+
}
|
|
603
|
+
const content = await Presentation.presentation.getContentInstanceKeys({
|
|
604
|
+
imodel,
|
|
605
|
+
keys: new KeySet([nodeKey]),
|
|
606
|
+
rulesetOrId: {
|
|
607
|
+
id: "grouped-instances",
|
|
608
|
+
rules: [
|
|
609
|
+
{
|
|
610
|
+
ruleType: "Content",
|
|
611
|
+
specifications: [
|
|
612
|
+
{
|
|
613
|
+
specType: "SelectedNodeInstances",
|
|
614
|
+
},
|
|
615
|
+
],
|
|
616
|
+
},
|
|
617
|
+
],
|
|
618
|
+
},
|
|
619
|
+
});
|
|
620
|
+
for await (const key of content.items()) {
|
|
621
|
+
yield key;
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
function isNodeKey(data) {
|
|
625
|
+
const key = data;
|
|
626
|
+
return key.pathFromRoot !== undefined && key.type !== undefined;
|
|
627
|
+
}
|
|
628
|
+
function getChangeType(type) {
|
|
629
|
+
switch (type) {
|
|
630
|
+
case "add":
|
|
631
|
+
return SelectionChangeType.Add;
|
|
632
|
+
case "remove":
|
|
633
|
+
return SelectionChangeType.Remove;
|
|
634
|
+
case "replace":
|
|
635
|
+
return SelectionChangeType.Replace;
|
|
636
|
+
case "clear":
|
|
637
|
+
return SelectionChangeType.Clear;
|
|
638
|
+
}
|
|
639
|
+
}
|
|
420
640
|
//# sourceMappingURL=SelectionManager.js.map
|