@itwin/unified-selection 0.1.0 → 0.3.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.
Files changed (82) hide show
  1. package/CHANGELOG.md +129 -0
  2. package/README.md +104 -6
  3. package/lib/cjs/unified-selection/CachingHiliteSetProvider.d.ts +33 -0
  4. package/lib/cjs/unified-selection/CachingHiliteSetProvider.d.ts.map +1 -0
  5. package/lib/cjs/unified-selection/CachingHiliteSetProvider.js +62 -0
  6. package/lib/cjs/unified-selection/CachingHiliteSetProvider.js.map +1 -0
  7. package/lib/cjs/unified-selection/EnableUnifiedSelectionSyncWithIModel.d.ts +90 -0
  8. package/lib/cjs/unified-selection/EnableUnifiedSelectionSyncWithIModel.d.ts.map +1 -0
  9. package/lib/cjs/unified-selection/EnableUnifiedSelectionSyncWithIModel.js +205 -0
  10. package/lib/cjs/unified-selection/EnableUnifiedSelectionSyncWithIModel.js.map +1 -0
  11. package/lib/cjs/unified-selection/HiliteSetProvider.d.ts +37 -0
  12. package/lib/cjs/unified-selection/HiliteSetProvider.d.ts.map +1 -0
  13. package/lib/cjs/unified-selection/HiliteSetProvider.js +344 -0
  14. package/lib/cjs/unified-selection/HiliteSetProvider.js.map +1 -0
  15. package/lib/cjs/unified-selection/Selectable.d.ts +0 -3
  16. package/lib/cjs/unified-selection/Selectable.d.ts.map +1 -1
  17. package/lib/cjs/unified-selection/Selectable.js +2 -2
  18. package/lib/cjs/unified-selection/Selectable.js.map +1 -1
  19. package/lib/cjs/unified-selection/SelectionChangeEvent.d.ts +11 -7
  20. package/lib/cjs/unified-selection/SelectionChangeEvent.d.ts.map +1 -1
  21. package/lib/cjs/unified-selection/SelectionChangeEvent.js +1 -1
  22. package/lib/cjs/unified-selection/SelectionChangeEvent.js.map +1 -1
  23. package/lib/cjs/unified-selection/SelectionScope.d.ts +44 -0
  24. package/lib/cjs/unified-selection/SelectionScope.d.ts.map +1 -0
  25. package/lib/cjs/unified-selection/SelectionScope.js +193 -0
  26. package/lib/cjs/unified-selection/SelectionScope.js.map +1 -0
  27. package/lib/cjs/unified-selection/SelectionStorage.d.ts +34 -29
  28. package/lib/cjs/unified-selection/SelectionStorage.d.ts.map +1 -1
  29. package/lib/cjs/unified-selection/SelectionStorage.js +32 -18
  30. package/lib/cjs/unified-selection/SelectionStorage.js.map +1 -1
  31. package/lib/cjs/unified-selection/Utils.d.ts +7 -0
  32. package/lib/cjs/unified-selection/Utils.d.ts.map +1 -0
  33. package/lib/cjs/unified-selection/Utils.js +24 -0
  34. package/lib/cjs/unified-selection/Utils.js.map +1 -0
  35. package/lib/cjs/unified-selection/types/IModel.d.ts +84 -0
  36. package/lib/cjs/unified-selection/types/IModel.d.ts.map +1 -0
  37. package/lib/cjs/unified-selection/types/IModel.js +24 -0
  38. package/lib/cjs/unified-selection/types/IModel.js.map +1 -0
  39. package/lib/cjs/unified-selection.d.ts +5 -7
  40. package/lib/cjs/unified-selection.d.ts.map +1 -1
  41. package/lib/cjs/unified-selection.js +11 -7
  42. package/lib/cjs/unified-selection.js.map +1 -1
  43. package/lib/esm/unified-selection/CachingHiliteSetProvider.d.ts +33 -0
  44. package/lib/esm/unified-selection/CachingHiliteSetProvider.d.ts.map +1 -0
  45. package/lib/esm/unified-selection/CachingHiliteSetProvider.js +58 -0
  46. package/lib/esm/unified-selection/CachingHiliteSetProvider.js.map +1 -0
  47. package/lib/esm/unified-selection/EnableUnifiedSelectionSyncWithIModel.d.ts +90 -0
  48. package/lib/esm/unified-selection/EnableUnifiedSelectionSyncWithIModel.d.ts.map +1 -0
  49. package/lib/esm/unified-selection/EnableUnifiedSelectionSyncWithIModel.js +200 -0
  50. package/lib/esm/unified-selection/EnableUnifiedSelectionSyncWithIModel.js.map +1 -0
  51. package/lib/esm/unified-selection/HiliteSetProvider.d.ts +37 -0
  52. package/lib/esm/unified-selection/HiliteSetProvider.d.ts.map +1 -0
  53. package/lib/esm/unified-selection/HiliteSetProvider.js +340 -0
  54. package/lib/esm/unified-selection/HiliteSetProvider.js.map +1 -0
  55. package/lib/esm/unified-selection/Selectable.d.ts +0 -3
  56. package/lib/esm/unified-selection/Selectable.d.ts.map +1 -1
  57. package/lib/esm/unified-selection/Selectable.js.map +1 -1
  58. package/lib/esm/unified-selection/SelectionChangeEvent.d.ts +11 -7
  59. package/lib/esm/unified-selection/SelectionChangeEvent.d.ts.map +1 -1
  60. package/lib/esm/unified-selection/SelectionChangeEvent.js +1 -1
  61. package/lib/esm/unified-selection/SelectionChangeEvent.js.map +1 -1
  62. package/lib/esm/unified-selection/SelectionScope.d.ts +44 -0
  63. package/lib/esm/unified-selection/SelectionScope.d.ts.map +1 -0
  64. package/lib/esm/unified-selection/SelectionScope.js +189 -0
  65. package/lib/esm/unified-selection/SelectionScope.js.map +1 -0
  66. package/lib/esm/unified-selection/SelectionStorage.d.ts +34 -29
  67. package/lib/esm/unified-selection/SelectionStorage.d.ts.map +1 -1
  68. package/lib/esm/unified-selection/SelectionStorage.js +31 -17
  69. package/lib/esm/unified-selection/SelectionStorage.js.map +1 -1
  70. package/lib/esm/unified-selection/Utils.d.ts +7 -0
  71. package/lib/esm/unified-selection/Utils.d.ts.map +1 -0
  72. package/lib/esm/unified-selection/Utils.js +20 -0
  73. package/lib/esm/unified-selection/Utils.js.map +1 -0
  74. package/lib/esm/unified-selection/types/IModel.d.ts +84 -0
  75. package/lib/esm/unified-selection/types/IModel.d.ts.map +1 -0
  76. package/lib/esm/unified-selection/types/IModel.js +21 -0
  77. package/lib/esm/unified-selection/types/IModel.js.map +1 -0
  78. package/lib/esm/unified-selection.d.ts +5 -7
  79. package/lib/esm/unified-selection.d.ts.map +1 -1
  80. package/lib/esm/unified-selection.js +5 -7
  81. package/lib/esm/unified-selection.js.map +1 -1
  82. package/package.json +28 -15
@@ -0,0 +1,189 @@
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 { Id64 } from "@itwin/core-bentley";
6
+ import { formIdBindings } from "./Utils";
7
+ /**
8
+ * Computes selection from given element ID's.
9
+ * @param queryExecutor iModel query executor.
10
+ * @param elementIds ID's of elements to compute selection for.
11
+ * @param scope Selection scope to compute selection with.
12
+ * @beta
13
+ */
14
+ export async function* computeSelection(props) {
15
+ const { queryExecutor, elementIds, scope } = props;
16
+ if (typeof scope === "string") {
17
+ yield* computeSelection({ queryExecutor, elementIds, scope: { id: scope } });
18
+ return;
19
+ }
20
+ const nonTransientKeys = elementIds.filter((key) => !Id64.isTransient(key));
21
+ switch (scope.id) {
22
+ case "element":
23
+ yield* computeElementSelection(queryExecutor, nonTransientKeys, scope.ancestorLevel ?? 0);
24
+ return;
25
+ case "category":
26
+ yield* computeCategorySelection(queryExecutor, nonTransientKeys);
27
+ return;
28
+ case "model":
29
+ yield* computeModelSelection(queryExecutor, nonTransientKeys);
30
+ return;
31
+ case "functional":
32
+ yield* computeFunctionalElementSelection(queryExecutor, nonTransientKeys, scope.ancestorLevel ?? 0);
33
+ return;
34
+ }
35
+ }
36
+ async function* computeElementSelection(queryExecutor, elementIds, ancestorLevel) {
37
+ const bindings = [];
38
+ const recurseUntilRoot = ancestorLevel < 0;
39
+ const ctes = [
40
+ `
41
+ AncestorElements(ECInstanceId, ECClassId, Depth, ParentId) AS (
42
+ SELECT ECInstanceId, ECClassId, ${formAncestorLevelBinding(ancestorLevel, bindings)}, Parent.Id
43
+ FROM BisCore.Element
44
+ WHERE ${formIdBindings("ECInstanceId", elementIds, bindings)}
45
+ UNION ALL
46
+ SELECT pe.ECInstanceId, pe.ECClassId, a.Depth - 1, pe.Parent.Id
47
+ FROM AncestorElements a
48
+ JOIN BisCore.Element pe ON pe.ECInstanceId = a.ParentId
49
+ WHERE ${recurseUntilRoot ? "" : "Depth > 0 AND"} ParentId IS NOT NULL
50
+ )
51
+ `,
52
+ ];
53
+ const ecsql = `
54
+ SELECT DISTINCT ECInstanceId, ec_classname(ECClassId, 's.c') AS ClassName
55
+ FROM AncestorElements
56
+ WHERE ${recurseUntilRoot ? "" : "Depth = 0 OR"} ParentId IS NULL
57
+ `;
58
+ yield* executeQuery(queryExecutor, { ctes, ecsql, bindings });
59
+ }
60
+ async function* computeCategorySelection(queryExecutor, ids) {
61
+ const bindings = [];
62
+ const ecsql = [
63
+ `
64
+ SELECT DISTINCT c.ECInstanceId, ec_classname(c.ECClassId, 's.c') AS ClassName
65
+ FROM BisCore.Category c
66
+ JOIN BisCore.GeometricElement2d ge ON ge.Category.Id = c.ECInstanceId
67
+ WHERE ${formIdBindings("ge.ECInstanceId", ids, bindings)}
68
+ `,
69
+ `
70
+ SELECT DISTINCT c.ECInstanceId, ec_classname(c.ECClassId, 's.c') AS ClassName
71
+ FROM BisCore.Category c
72
+ JOIN BisCore.GeometricElement3d ge ON ge.Category.Id = c.ECInstanceId
73
+ WHERE ${formIdBindings("ge.ECInstanceId", ids, bindings)}
74
+ `,
75
+ ].join(" UNION ALL ");
76
+ yield* executeQuery(queryExecutor, { ecsql, bindings });
77
+ }
78
+ async function* computeModelSelection(queryExecutor, ids) {
79
+ const bindings = [];
80
+ const ecsql = `
81
+ SELECT DISTINCT m.ECInstanceId, ec_classname(m.ECClassId, 's.c') AS ClassName
82
+ FROM BisCore.Model m
83
+ JOIN BisCore.Element e ON e.Model.Id = m.ECInstanceId
84
+ WHERE ${formIdBindings("e.ECInstanceId", ids, bindings)}
85
+ `;
86
+ yield* executeQuery(queryExecutor, { ecsql, bindings });
87
+ }
88
+ async function* computeFunctionalElementSelection(queryExecutor, ids, ancestorLevel) {
89
+ const bindings = [];
90
+ const recurseUntilRoot = ancestorLevel < 0;
91
+ const ctes = [
92
+ `
93
+ Elements2dOrNearestFunctionalElements(OriginalECInstanceId, OriginalECClassId, ECInstanceId, ECClassId, ParentId) AS (
94
+ SELECT ECInstanceId, ECClassId, ECInstanceId, ECClassId, Parent.Id
95
+ FROM BisCore.Element
96
+ WHERE ${formIdBindings("ECInstanceId", ids, bindings)} AND ECClassId IS NOT (BisCore.GeometricElement3d)
97
+ UNION ALL
98
+ SELECT
99
+ e2onfe.OriginalECInstanceId,
100
+ e2onfe.OriginalECClassId,
101
+ COALESCE(dgrfe.TargetECInstanceId, pe.ECInstanceId),
102
+ COALESCE(dgrfe.TargetECClassId, pe.ECClassId),
103
+ pe.Parent.Id
104
+ FROM Elements2dOrNearestFunctionalElements e2onfe
105
+ LEFT JOIN BisCore.Element pe ON pe.ECInstanceId = e2onfe.ParentId
106
+ LEFT JOIN Functional.DrawingGraphicRepresentsFunctionalElement dgrfe ON dgrfe.SourceECInstanceId = e2onfe.ECInstanceId
107
+ WHERE e2onfe.ECClassId IS NOT (Functional.FunctionalElement) AND (e2onfe.ParentId IS NOT NULL OR dgrfe.TargetECInstanceId IS NOT NULL)
108
+ )
109
+ `,
110
+ `
111
+ Element2dNearestFunctionalElements(OriginalECInstanceId, ECInstanceId, ECClassId) AS (
112
+ SELECT OriginalECInstanceId, ECInstanceId, ECClassId
113
+ FROM Elements2dOrNearestFunctionalElements
114
+ WHERE ECClassId IS (Functional.FunctionalElement)
115
+ )
116
+ `,
117
+ `
118
+ Elements2dWithoutFunctionalElement(ECInstanceId, ECClassId) AS (
119
+ SELECT e2wfe.OriginalECInstanceId, OriginalECClassId
120
+ FROM Elements2dOrNearestFunctionalElements e2wfe
121
+ LEFT JOIN Element2dNearestFunctionalElements e2nfe ON e2nfe.OriginalECInstanceId = e2wfe.OriginalECInstanceId
122
+ WHERE e2wfe.ParentId IS NULL AND e2nfe.ECInstanceId IS NULL
123
+ )
124
+ `,
125
+ `
126
+ Elements2d(ECInstanceId, ECClassId) AS (
127
+ SELECT ECInstanceId, ECClassId FROM Element2dNearestFunctionalElements
128
+ UNION
129
+ SELECT ECInstanceId, ECClassId FROM Elements2dWithoutFunctionalElement
130
+ )
131
+ `,
132
+ `
133
+ Element2dAncestorElements(ECInstanceId, ECClassId, Depth, ParentId) AS (
134
+ SELECT e.ECInstanceId, e.ECClassId, ${formAncestorLevelBinding(ancestorLevel, bindings)}, e.Parent.Id
135
+ FROM BisCore.Element e
136
+ JOIN Elements2d e2d ON e2d.ECInstanceId = e.ECInstanceId
137
+ UNION ALL
138
+ SELECT pe.ECInstanceId, pe.ECClassId, e2ae.Depth - 1, pe.Parent.Id
139
+ FROM Element2dAncestorElements e2ae
140
+ JOIN BisCore.Element pe ON pe.ECInstanceId = e2ae.ParentId
141
+ WHERE ${recurseUntilRoot ? "" : "Depth > 0 AND"} ParentId IS NOT NULL
142
+ )
143
+ `,
144
+ `
145
+ Element3dAncestorElements(ECInstanceId, ECClassId, Depth, ParentId) AS (
146
+ SELECT ge.ECInstanceId, ge.ECClassId, ${formAncestorLevelBinding(ancestorLevel, bindings)}, ge.Parent.Id
147
+ FROM BisCore.GeometricElement3d ge
148
+ WHERE ${formIdBindings("ge.ECInstanceId", ids, bindings)}
149
+ UNION ALL
150
+ SELECT pe.ECInstanceId, pe.ECClassId, e3ae.Depth - 1, pe.Parent.Id
151
+ FROM Element3dAncestorElements e3ae
152
+ JOIN BisCore.Element pe ON pe.ECInstanceId = e3ae.ParentId
153
+ WHERE ${recurseUntilRoot ? "" : "Depth > 0 AND"} ParentId IS NOT NULL
154
+ )
155
+ `,
156
+ `
157
+ Element3dAncestorRelatedFunctionalElement(ECInstanceId, ClassName) AS (
158
+ SELECT
159
+ COALESCE(peff.TargetECInstanceId, e3ae.ECInstanceId),
160
+ ec_classname(COALESCE(peff.TargetECClassId, e3ae.ECClassId), 's.c')
161
+ FROM Element3dAncestorElements e3ae
162
+ LEFT JOIN Functional.PhysicalElementFulfillsFunction peff ON peff.SourceECInstanceId = e3ae.ECInstanceId
163
+ WHERE ${recurseUntilRoot ? "" : "e3ae.Depth = 0 OR"} e3ae.ParentId IS NULL
164
+ )
165
+ `,
166
+ ];
167
+ const ecsql = [
168
+ `
169
+ SELECT DISTINCT ECInstanceId, ec_classname(ECClassId, 's.c') AS ClassName
170
+ FROM Element2dAncestorElements
171
+ WHERE ${recurseUntilRoot ? "" : "Depth = 0 OR"} ParentId IS NULL
172
+ `,
173
+ `
174
+ SELECT DISTINCT ECInstanceId, ClassName FROM Element3dAncestorRelatedFunctionalElement
175
+ `,
176
+ ].join(" UNION ALL ");
177
+ yield* executeQuery(queryExecutor, { ctes, ecsql, bindings });
178
+ }
179
+ function formAncestorLevelBinding(ancestorLevel, bindings) {
180
+ bindings.push({ type: "int", value: ancestorLevel });
181
+ return "?";
182
+ }
183
+ async function* executeQuery(queryExecutor, query) {
184
+ const reader = queryExecutor.createQueryReader(query);
185
+ for await (const row of reader) {
186
+ yield { className: row.ClassName, id: row.ECInstanceId };
187
+ }
188
+ }
189
+ //# sourceMappingURL=SelectionScope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SelectionScope.js","sourceRoot":"","sources":["../../../src/unified-selection/SelectionScope.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Id64 } from \"@itwin/core-bentley\";\nimport { ECSqlBinding, ECSqlQueryDef, ECSqlQueryExecutor } from \"@itwin/presentation-shared\";\nimport { SelectableInstanceKey } from \"./Selectable\";\nimport { formIdBindings } from \"./Utils\";\n\n/**\n * Available selection scopes.\n * @internal Not exported through barrel, but used in public API as an argument. May be supplemented with additional items in the union at any time.\n */\nexport type SelectionScope = \"element\" | \"model\" | \"category\" | \"functional\";\n\n/**\n * Props for computing element selection.\n * @internal Not exported through barrel, but used in public API as an argument. May be supplemented with optional attributes any time.\n */\nexport interface ElementSelectionScopeProps {\n /** Identifies this as either \"element\" or \"functional\" selection scope */\n id: \"element\" | \"functional\";\n /**\n * Specifies how far \"up\" we should walk to find the target element. When not specified or `0`,\n * the target element matches the request element. When set to `1`, the target element matches the direct parent element.\n * When set to `2`, the target element is parent of the parent element and so on. In all situations when this is `> 0`,\n * we're not walking further than the last existing element, for example when `ancestorLevel = 1` (direct parent\n * element is requested), but the request element doesn't have a parent, the request element is returned as the result.\n * A negative value would result in the top-most element to be returned.\n */\n ancestorLevel?: number;\n}\n\n/**\n * Props for `computeSelection`.\n * @internal Not exported through barrel, but used in public API as an argument. May be supplemented with optional attributes any time.\n */\nexport interface ComputeSelectionProps {\n queryExecutor: ECSqlQueryExecutor;\n elementIds: string[];\n scope: ElementSelectionScopeProps | { id: SelectionScope } | SelectionScope;\n}\n\n/**\n * Computes selection from given element ID's.\n * @param queryExecutor iModel query executor.\n * @param elementIds ID's of elements to compute selection for.\n * @param scope Selection scope to compute selection with.\n * @beta\n */\nexport async function* computeSelection(props: ComputeSelectionProps): AsyncIterableIterator<SelectableInstanceKey> {\n const { queryExecutor, elementIds, scope } = props;\n\n if (typeof scope === \"string\") {\n yield* computeSelection({ queryExecutor, elementIds, scope: { id: scope } });\n return;\n }\n\n const nonTransientKeys = elementIds.filter((key) => !Id64.isTransient(key));\n\n switch (scope.id) {\n case \"element\":\n yield* computeElementSelection(queryExecutor, nonTransientKeys, (scope as ElementSelectionScopeProps).ancestorLevel ?? 0);\n return;\n case \"category\":\n yield* computeCategorySelection(queryExecutor, nonTransientKeys);\n return;\n case \"model\":\n yield* computeModelSelection(queryExecutor, nonTransientKeys);\n return;\n case \"functional\":\n yield* computeFunctionalElementSelection(queryExecutor, nonTransientKeys, (scope as ElementSelectionScopeProps).ancestorLevel ?? 0);\n return;\n }\n}\n\nasync function* computeElementSelection(\n queryExecutor: ECSqlQueryExecutor,\n elementIds: string[],\n ancestorLevel: number,\n): AsyncIterableIterator<SelectableInstanceKey> {\n const bindings: ECSqlBinding[] = [];\n const recurseUntilRoot = ancestorLevel < 0;\n const ctes = [\n `\n AncestorElements(ECInstanceId, ECClassId, Depth, ParentId) AS (\n SELECT ECInstanceId, ECClassId, ${formAncestorLevelBinding(ancestorLevel, bindings)}, Parent.Id\n FROM BisCore.Element\n WHERE ${formIdBindings(\"ECInstanceId\", elementIds, bindings)}\n UNION ALL\n SELECT pe.ECInstanceId, pe.ECClassId, a.Depth - 1, pe.Parent.Id\n FROM AncestorElements a\n JOIN BisCore.Element pe ON pe.ECInstanceId = a.ParentId\n WHERE ${recurseUntilRoot ? \"\" : \"Depth > 0 AND\"} ParentId IS NOT NULL\n )\n `,\n ];\n const ecsql = `\n SELECT DISTINCT ECInstanceId, ec_classname(ECClassId, 's.c') AS ClassName\n FROM AncestorElements\n WHERE ${recurseUntilRoot ? \"\" : \"Depth = 0 OR\"} ParentId IS NULL\n `;\n yield* executeQuery(queryExecutor, { ctes, ecsql, bindings });\n}\n\nasync function* computeCategorySelection(queryExecutor: ECSqlQueryExecutor, ids: string[]): AsyncIterableIterator<SelectableInstanceKey> {\n const bindings: ECSqlBinding[] = [];\n const ecsql = [\n `\n SELECT DISTINCT c.ECInstanceId, ec_classname(c.ECClassId, 's.c') AS ClassName\n FROM BisCore.Category c\n JOIN BisCore.GeometricElement2d ge ON ge.Category.Id = c.ECInstanceId\n WHERE ${formIdBindings(\"ge.ECInstanceId\", ids, bindings)}\n `,\n `\n SELECT DISTINCT c.ECInstanceId, ec_classname(c.ECClassId, 's.c') AS ClassName\n FROM BisCore.Category c\n JOIN BisCore.GeometricElement3d ge ON ge.Category.Id = c.ECInstanceId\n WHERE ${formIdBindings(\"ge.ECInstanceId\", ids, bindings)}\n `,\n ].join(\" UNION ALL \");\n yield* executeQuery(queryExecutor, { ecsql, bindings });\n}\n\nasync function* computeModelSelection(queryExecutor: ECSqlQueryExecutor, ids: string[]): AsyncIterableIterator<SelectableInstanceKey> {\n const bindings: ECSqlBinding[] = [];\n const ecsql = `\n SELECT DISTINCT m.ECInstanceId, ec_classname(m.ECClassId, 's.c') AS ClassName\n FROM BisCore.Model m\n JOIN BisCore.Element e ON e.Model.Id = m.ECInstanceId\n WHERE ${formIdBindings(\"e.ECInstanceId\", ids, bindings)}\n `;\n yield* executeQuery(queryExecutor, { ecsql, bindings });\n}\n\nasync function* computeFunctionalElementSelection(\n queryExecutor: ECSqlQueryExecutor,\n ids: string[],\n ancestorLevel: number,\n): AsyncIterableIterator<SelectableInstanceKey> {\n const bindings: ECSqlBinding[] = [];\n const recurseUntilRoot = ancestorLevel < 0;\n const ctes = [\n `\n Elements2dOrNearestFunctionalElements(OriginalECInstanceId, OriginalECClassId, ECInstanceId, ECClassId, ParentId) AS (\n SELECT ECInstanceId, ECClassId, ECInstanceId, ECClassId, Parent.Id\n FROM BisCore.Element\n WHERE ${formIdBindings(\"ECInstanceId\", ids, bindings)} AND ECClassId IS NOT (BisCore.GeometricElement3d)\n UNION ALL\n SELECT\n e2onfe.OriginalECInstanceId,\n e2onfe.OriginalECClassId,\n COALESCE(dgrfe.TargetECInstanceId, pe.ECInstanceId),\n COALESCE(dgrfe.TargetECClassId, pe.ECClassId),\n pe.Parent.Id\n FROM Elements2dOrNearestFunctionalElements e2onfe\n LEFT JOIN BisCore.Element pe ON pe.ECInstanceId = e2onfe.ParentId\n LEFT JOIN Functional.DrawingGraphicRepresentsFunctionalElement dgrfe ON dgrfe.SourceECInstanceId = e2onfe.ECInstanceId\n WHERE e2onfe.ECClassId IS NOT (Functional.FunctionalElement) AND (e2onfe.ParentId IS NOT NULL OR dgrfe.TargetECInstanceId IS NOT NULL)\n )\n `,\n `\n Element2dNearestFunctionalElements(OriginalECInstanceId, ECInstanceId, ECClassId) AS (\n SELECT OriginalECInstanceId, ECInstanceId, ECClassId\n FROM Elements2dOrNearestFunctionalElements\n WHERE ECClassId IS (Functional.FunctionalElement)\n )\n `,\n `\n Elements2dWithoutFunctionalElement(ECInstanceId, ECClassId) AS (\n SELECT e2wfe.OriginalECInstanceId, OriginalECClassId\n FROM Elements2dOrNearestFunctionalElements e2wfe\n LEFT JOIN Element2dNearestFunctionalElements e2nfe ON e2nfe.OriginalECInstanceId = e2wfe.OriginalECInstanceId\n WHERE e2wfe.ParentId IS NULL AND e2nfe.ECInstanceId IS NULL\n )\n `,\n `\n Elements2d(ECInstanceId, ECClassId) AS (\n SELECT ECInstanceId, ECClassId FROM Element2dNearestFunctionalElements\n UNION\n SELECT ECInstanceId, ECClassId FROM Elements2dWithoutFunctionalElement\n )\n `,\n `\n Element2dAncestorElements(ECInstanceId, ECClassId, Depth, ParentId) AS (\n SELECT e.ECInstanceId, e.ECClassId, ${formAncestorLevelBinding(ancestorLevel, bindings)}, e.Parent.Id\n FROM BisCore.Element e\n JOIN Elements2d e2d ON e2d.ECInstanceId = e.ECInstanceId\n UNION ALL\n SELECT pe.ECInstanceId, pe.ECClassId, e2ae.Depth - 1, pe.Parent.Id\n FROM Element2dAncestorElements e2ae\n JOIN BisCore.Element pe ON pe.ECInstanceId = e2ae.ParentId\n WHERE ${recurseUntilRoot ? \"\" : \"Depth > 0 AND\"} ParentId IS NOT NULL\n )\n `,\n `\n Element3dAncestorElements(ECInstanceId, ECClassId, Depth, ParentId) AS (\n SELECT ge.ECInstanceId, ge.ECClassId, ${formAncestorLevelBinding(ancestorLevel, bindings)}, ge.Parent.Id\n FROM BisCore.GeometricElement3d ge\n WHERE ${formIdBindings(\"ge.ECInstanceId\", ids, bindings)}\n UNION ALL\n SELECT pe.ECInstanceId, pe.ECClassId, e3ae.Depth - 1, pe.Parent.Id\n FROM Element3dAncestorElements e3ae\n JOIN BisCore.Element pe ON pe.ECInstanceId = e3ae.ParentId\n WHERE ${recurseUntilRoot ? \"\" : \"Depth > 0 AND\"} ParentId IS NOT NULL\n )\n `,\n `\n Element3dAncestorRelatedFunctionalElement(ECInstanceId, ClassName) AS (\n SELECT\n COALESCE(peff.TargetECInstanceId, e3ae.ECInstanceId),\n ec_classname(COALESCE(peff.TargetECClassId, e3ae.ECClassId), 's.c')\n FROM Element3dAncestorElements e3ae\n LEFT JOIN Functional.PhysicalElementFulfillsFunction peff ON peff.SourceECInstanceId = e3ae.ECInstanceId\n WHERE ${recurseUntilRoot ? \"\" : \"e3ae.Depth = 0 OR\"} e3ae.ParentId IS NULL\n )\n `,\n ];\n const ecsql = [\n `\n SELECT DISTINCT ECInstanceId, ec_classname(ECClassId, 's.c') AS ClassName\n FROM Element2dAncestorElements\n WHERE ${recurseUntilRoot ? \"\" : \"Depth = 0 OR\"} ParentId IS NULL\n `,\n `\n SELECT DISTINCT ECInstanceId, ClassName FROM Element3dAncestorRelatedFunctionalElement\n `,\n ].join(\" UNION ALL \");\n yield* executeQuery(queryExecutor, { ctes, ecsql, bindings });\n}\n\nfunction formAncestorLevelBinding(ancestorLevel: number, bindings: ECSqlBinding[]) {\n bindings.push({ type: \"int\", value: ancestorLevel });\n return \"?\";\n}\n\nasync function* executeQuery(queryExecutor: ECSqlQueryExecutor, query: ECSqlQueryDef): AsyncIterableIterator<SelectableInstanceKey> {\n const reader = queryExecutor.createQueryReader(query);\n for await (const row of reader) {\n yield { className: row.ClassName, id: row.ECInstanceId };\n }\n}\n"]}
@@ -1,31 +1,33 @@
1
- /** @packageDocumentation
2
- * @module UnifiedSelection
3
- */
4
1
  import { Selectable, Selectables } from "./Selectable";
5
2
  import { SelectionChangeEvent } from "./SelectionChangeEvent";
3
+ type IModelKeyProp = {
4
+ /** Key of the iModel to get selection levels for. */
5
+ imodelKey: string;
6
+ } | {
7
+ /**
8
+ * Key of the iModel to get selection levels for.
9
+ * @deprecated in 0.2. Use `imodelKey` instead.
10
+ */
11
+ iModelKey: string;
12
+ };
6
13
  /**
7
- * Selection storage interface which provides main selection and sub-selection.
8
- * @beta
14
+ * Defines return value of `createStorage`.
15
+ *
16
+ * @beta Used in public API as a return value. Not expected to be created / extended by package
17
+ * consumers, may be supplemented with required attributes any time.
9
18
  */
10
19
  export interface SelectionStorage {
11
20
  /** An event that is raised when selection changes. */
12
21
  selectionChangeEvent: SelectionChangeEvent;
13
22
  /** Get the selection levels currently stored for the specified iModel. */
14
- getSelectionLevels(props: {
15
- /** Key of the iModel to get selection levels for. */
16
- iModelKey: string;
17
- }): number[];
23
+ getSelectionLevels(props: IModelKeyProp): number[];
18
24
  /** Get the selection stored in the storage. */
19
- getSelection(props: {
20
- /** Key of the iModel to get selection for. */
21
- iModelKey: string;
25
+ getSelection(props: IModelKeyProp & {
22
26
  /** Level of the selection. Defaults to `0`. */
23
27
  level?: number;
24
28
  }): Selectables;
25
29
  /** Add keys to the selection. */
26
- addToSelection(props: {
27
- /** Key of the iModel to change selection for. */
28
- iModelKey: string;
30
+ addToSelection(props: IModelKeyProp & {
29
31
  /** Name of the selection source. Generally, this identifies the component that makes the selection change. */
30
32
  source: string;
31
33
  /** The selectables to add to selection. */
@@ -34,9 +36,7 @@ export interface SelectionStorage {
34
36
  level?: number;
35
37
  }): void;
36
38
  /** Remove keys from current selection. */
37
- removeFromSelection(props: {
38
- /** Key of the iModel to change selection for. */
39
- iModelKey: string;
39
+ removeFromSelection(props: IModelKeyProp & {
40
40
  /** Name of the selection source. Generally, this identifies the component that makes the selection change. */
41
41
  source: string;
42
42
  /** The selectables to remove from selection. */
@@ -45,9 +45,7 @@ export interface SelectionStorage {
45
45
  level?: number;
46
46
  }): void;
47
47
  /** Replace current selection. */
48
- replaceSelection(props: {
49
- /** Key of the iModel to change selection for. */
50
- iModelKey: string;
48
+ replaceSelection(props: IModelKeyProp & {
51
49
  /** Name of the selection source. Generally, this identifies the component that makes the selection change. */
52
50
  source: string;
53
51
  /** The selectables to add to selection. */
@@ -56,23 +54,30 @@ export interface SelectionStorage {
56
54
  level?: number;
57
55
  }): void;
58
56
  /** Clear current selection. */
59
- clearSelection(props: {
60
- /** Key of the iModel to change selection for. */
61
- iModelKey: string;
57
+ clearSelection(props: IModelKeyProp & {
62
58
  /** Name of the selection source. Generally, this identifies the component that makes the selection change. */
63
59
  source: string;
64
60
  /** Level of the selection. Defaults to `0`. */
65
61
  level?: number;
66
62
  }): void;
67
63
  /** Clear storage for an iModel. This function should be called when iModel is closed. */
68
- clearStorage(props: {
69
- /** Key of the iModel to change selection for. */
70
- iModelKey: string;
71
- }): void;
64
+ clearStorage(props: IModelKeyProp): void;
72
65
  }
73
66
  /**
74
- * Creates a selection storage. When an iModel is closed `SelectionStorage.clearSelection` function should be called.
67
+ * Creates a selection storage which stores and allows managing application-level selection.
68
+ *
69
+ * **Note:** `clearSelection` should be called upon iModel close to free-up memory:
70
+ * ```ts
71
+ * import { IModelConnection } from "@itwin/core-frontend";
72
+ * IModelConnection.onClose.addListener((imodel) => {
73
+ * storage.clearStorage(imodel.key);
74
+ * });
75
+ * ```
76
+ *
75
77
  * @beta
76
78
  */
77
79
  export declare function createStorage(): SelectionStorage;
80
+ /** @internal */
81
+ export declare const IMODEL_CLOSE_SELECTION_CLEAR_SOURCE = "Unified selection storage: clear";
82
+ export {};
78
83
  //# sourceMappingURL=SelectionStorage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SelectionStorage.d.ts","sourceRoot":"","sources":["../../../src/unified-selection/SelectionStorage.ts"],"names":[],"mappings":"AAKA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAyF,MAAM,wBAAwB,CAAC;AAErJ;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,sDAAsD;IACtD,oBAAoB,EAAE,oBAAoB,CAAC;IAE3C,0EAA0E;IAC1E,kBAAkB,CAAC,KAAK,EAAE;QACxB,qDAAqD;QACrD,SAAS,EAAE,MAAM,CAAC;KACnB,GAAG,MAAM,EAAE,CAAC;IAEb,+CAA+C;IAC/C,YAAY,CAAC,KAAK,EAAE;QAClB,8CAA8C;QAC9C,SAAS,EAAE,MAAM,CAAC;QAClB,+CAA+C;QAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GAAG,WAAW,CAAC;IAEhB,iCAAiC;IACjC,cAAc,CAAC,KAAK,EAAE;QACpB,iDAAiD;QACjD,SAAS,EAAE,MAAM,CAAC;QAClB,8GAA8G;QAC9G,MAAM,EAAE,MAAM,CAAC;QACf,2CAA2C;QAC3C,WAAW,EAAE,UAAU,EAAE,CAAC;QAC1B,+CAA+C;QAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GAAG,IAAI,CAAC;IAET,0CAA0C;IAC1C,mBAAmB,CAAC,KAAK,EAAE;QACzB,iDAAiD;QACjD,SAAS,EAAE,MAAM,CAAC;QAClB,8GAA8G;QAC9G,MAAM,EAAE,MAAM,CAAC;QACf,gDAAgD;QAChD,WAAW,EAAE,UAAU,EAAE,CAAC;QAC1B,+CAA+C;QAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GAAG,IAAI,CAAC;IAET,iCAAiC;IACjC,gBAAgB,CAAC,KAAK,EAAE;QACtB,iDAAiD;QACjD,SAAS,EAAE,MAAM,CAAC;QAClB,8GAA8G;QAC9G,MAAM,EAAE,MAAM,CAAC;QACf,2CAA2C;QAC3C,WAAW,EAAE,UAAU,EAAE,CAAC;QAC1B,+CAA+C;QAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GAAG,IAAI,CAAC;IAET,+BAA+B;IAC/B,cAAc,CAAC,KAAK,EAAE;QACpB,iDAAiD;QACjD,SAAS,EAAE,MAAM,CAAC;QAClB,8GAA8G;QAC9G,MAAM,EAAE,MAAM,CAAC;QACf,+CAA+C;QAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GAAG,IAAI,CAAC;IAET,yFAAyF;IACzF,YAAY,CAAC,KAAK,EAAE;QAClB,iDAAiD;QACjD,SAAS,EAAE,MAAM,CAAC;KACnB,GAAG,IAAI,CAAC;CACV;AAED;;;GAGG;AACH,wBAAgB,aAAa,IAAI,gBAAgB,CAEhD"}
1
+ {"version":3,"file":"SelectionStorage.d.ts","sourceRoot":"","sources":["../../../src/unified-selection/SelectionStorage.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAyF,MAAM,wBAAwB,CAAC;AAErJ,KAAK,aAAa,GACd;IACE,qDAAqD;IACrD,SAAS,EAAE,MAAM,CAAC;CACnB,GACD;IACE;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEN;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,sDAAsD;IACtD,oBAAoB,EAAE,oBAAoB,CAAC;IAE3C,0EAA0E;IAC1E,kBAAkB,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,EAAE,CAAC;IAEnD,+CAA+C;IAC/C,YAAY,CACV,KAAK,EAAE,aAAa,GAAG;QACrB,+CAA+C;QAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GACA,WAAW,CAAC;IAEf,iCAAiC;IACjC,cAAc,CACZ,KAAK,EAAE,aAAa,GAAG;QACrB,8GAA8G;QAC9G,MAAM,EAAE,MAAM,CAAC;QACf,2CAA2C;QAC3C,WAAW,EAAE,UAAU,EAAE,CAAC;QAC1B,+CAA+C;QAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GACA,IAAI,CAAC;IAER,0CAA0C;IAC1C,mBAAmB,CACjB,KAAK,EAAE,aAAa,GAAG;QACrB,8GAA8G;QAC9G,MAAM,EAAE,MAAM,CAAC;QACf,gDAAgD;QAChD,WAAW,EAAE,UAAU,EAAE,CAAC;QAC1B,+CAA+C;QAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GACA,IAAI,CAAC;IAER,iCAAiC;IACjC,gBAAgB,CACd,KAAK,EAAE,aAAa,GAAG;QACrB,8GAA8G;QAC9G,MAAM,EAAE,MAAM,CAAC;QACf,2CAA2C;QAC3C,WAAW,EAAE,UAAU,EAAE,CAAC;QAC1B,+CAA+C;QAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GACA,IAAI,CAAC;IAER,+BAA+B;IAC/B,cAAc,CACZ,KAAK,EAAE,aAAa,GAAG;QACrB,8GAA8G;QAC9G,MAAM,EAAE,MAAM,CAAC;QACf,+CAA+C;QAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GACA,IAAI,CAAC;IAER,yFAAyF;IACzF,YAAY,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAAC;CAC1C;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,IAAI,gBAAgB,CAEhD;AAED,gBAAgB;AAChB,eAAO,MAAM,mCAAmC,qCAAqC,CAAC"}
@@ -2,30 +2,37 @@
2
2
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
3
3
  * See LICENSE.md in the project root for license terms and full copyright notice.
4
4
  *--------------------------------------------------------------------------------------------*/
5
- /** @packageDocumentation
6
- * @module UnifiedSelection
7
- */
8
5
  import { Selectables } from "./Selectable";
9
6
  import { SelectionChangeEventImpl } from "./SelectionChangeEvent";
10
7
  /**
11
- * Creates a selection storage. When an iModel is closed `SelectionStorage.clearSelection` function should be called.
8
+ * Creates a selection storage which stores and allows managing application-level selection.
9
+ *
10
+ * **Note:** `clearSelection` should be called upon iModel close to free-up memory:
11
+ * ```ts
12
+ * import { IModelConnection } from "@itwin/core-frontend";
13
+ * IModelConnection.onClose.addListener((imodel) => {
14
+ * storage.clearStorage(imodel.key);
15
+ * });
16
+ * ```
17
+ *
12
18
  * @beta
13
19
  */
14
20
  export function createStorage() {
15
21
  return new SelectionStorageImpl();
16
22
  }
23
+ /** @internal */
24
+ export const IMODEL_CLOSE_SELECTION_CLEAR_SOURCE = "Unified selection storage: clear";
17
25
  class SelectionStorageImpl {
18
26
  _storage = new Map();
19
27
  selectionChangeEvent;
20
28
  constructor() {
21
29
  this.selectionChangeEvent = new SelectionChangeEventImpl();
22
30
  }
23
- getSelectionLevels({ iModelKey }) {
24
- return this.getContainer(iModelKey).getSelectionLevels();
31
+ getSelectionLevels(props) {
32
+ return this.getContainer(getIModelKey(props)).getSelectionLevels();
25
33
  }
26
34
  getSelection(props) {
27
- const { iModelKey, level } = props;
28
- return this.getContainer(iModelKey).getSelection(level ?? 0);
35
+ return this.getContainer(getIModelKey(props)).getSelection(props.level ?? 0);
29
36
  }
30
37
  addToSelection(props) {
31
38
  this.handleChange({ ...props, changeType: "add" });
@@ -39,21 +46,23 @@ class SelectionStorageImpl {
39
46
  clearSelection(props) {
40
47
  this.handleChange({ ...props, changeType: "clear", selectables: [] });
41
48
  }
42
- clearStorage({ iModelKey }) {
43
- this.clearSelection({ source: "Clear iModel storage", iModelKey });
44
- this._storage.delete(iModelKey);
49
+ clearStorage(props) {
50
+ const imodelKey = getIModelKey(props);
51
+ this.clearSelection({ source: IMODEL_CLOSE_SELECTION_CLEAR_SOURCE, imodelKey });
52
+ this._storage.delete(imodelKey);
45
53
  }
46
- getContainer(iModelKey) {
47
- let selectionContainer = this._storage.get(iModelKey);
54
+ getContainer(imodelKey) {
55
+ let selectionContainer = this._storage.get(imodelKey);
48
56
  if (!selectionContainer) {
49
57
  selectionContainer = new MultiLevelSelectablesContainer();
50
- this._storage.set(iModelKey, selectionContainer);
58
+ this._storage.set(imodelKey, selectionContainer);
51
59
  }
52
60
  return selectionContainer;
53
61
  }
54
62
  handleChange(props) {
55
- const { iModelKey, source, level: inLevel, changeType, selectables: change } = props;
56
- const container = this.getContainer(iModelKey);
63
+ const { source, level: inLevel, changeType, selectables: change } = props;
64
+ const imodelKey = getIModelKey(props);
65
+ const container = this.getContainer(imodelKey);
57
66
  const level = inLevel ?? 0;
58
67
  const selectables = container.getSelection(level);
59
68
  const selected = Selectables.create(change);
@@ -85,7 +94,8 @@ class SelectionStorageImpl {
85
94
  const event = {
86
95
  source,
87
96
  level,
88
- iModelKey,
97
+ imodelKey,
98
+ iModelKey: imodelKey,
89
99
  changeType,
90
100
  selectables: selected,
91
101
  timestamp: new Date(),
@@ -93,6 +103,10 @@ class SelectionStorageImpl {
93
103
  this.selectionChangeEvent.raiseEvent(event, this);
94
104
  }
95
105
  }
106
+ function getIModelKey(props) {
107
+ // eslint-disable-next-line deprecation/deprecation
108
+ return "imodelKey" in props ? props.imodelKey : props.iModelKey;
109
+ }
96
110
  class MultiLevelSelectablesContainer {
97
111
  _selectablesContainers;
98
112
  constructor() {
@@ -1 +1 @@
1
- {"version":3,"file":"SelectionStorage.js","sourceRoot":"","sources":["../../../src/unified-selection/SelectionStorage.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\n/** @packageDocumentation\n * @module UnifiedSelection\n */\n\nimport { Selectable, Selectables } from \"./Selectable\";\nimport { SelectionChangeEvent, SelectionChangeEventImpl, StorageSelectionChangeEventArgs, StorageSelectionChangeType } from \"./SelectionChangeEvent\";\n\n/**\n * Selection storage interface which provides main selection and sub-selection.\n * @beta\n */\nexport interface SelectionStorage {\n /** An event that is raised when selection changes. */\n selectionChangeEvent: SelectionChangeEvent;\n\n /** Get the selection levels currently stored for the specified iModel. */\n getSelectionLevels(props: {\n /** Key of the iModel to get selection levels for. */\n iModelKey: string;\n }): number[];\n\n /** Get the selection stored in the storage. */\n getSelection(props: {\n /** Key of the iModel to get selection for. */\n iModelKey: string;\n /** Level of the selection. Defaults to `0`. */\n level?: number;\n }): Selectables;\n\n /** Add keys to the selection. */\n addToSelection(props: {\n /** Key of the iModel to change selection for. */\n iModelKey: string;\n /** Name of the selection source. Generally, this identifies the component that makes the selection change. */\n source: string;\n /** The selectables to add to selection. */\n selectables: Selectable[];\n /** Level of the selection. Defaults to `0`. */\n level?: number;\n }): void;\n\n /** Remove keys from current selection. */\n removeFromSelection(props: {\n /** Key of the iModel to change selection for. */\n iModelKey: string;\n /** Name of the selection source. Generally, this identifies the component that makes the selection change. */\n source: string;\n /** The selectables to remove from selection. */\n selectables: Selectable[];\n /** Level of the selection. Defaults to `0`. */\n level?: number;\n }): void;\n\n /** Replace current selection. */\n replaceSelection(props: {\n /** Key of the iModel to change selection for. */\n iModelKey: string;\n /** Name of the selection source. Generally, this identifies the component that makes the selection change. */\n source: string;\n /** The selectables to add to selection. */\n selectables: Selectable[];\n /** Level of the selection. Defaults to `0`. */\n level?: number;\n }): void;\n\n /** Clear current selection. */\n clearSelection(props: {\n /** Key of the iModel to change selection for. */\n iModelKey: string;\n /** Name of the selection source. Generally, this identifies the component that makes the selection change. */\n source: string;\n /** Level of the selection. Defaults to `0`. */\n level?: number;\n }): void;\n\n /** Clear storage for an iModel. This function should be called when iModel is closed. */\n clearStorage(props: {\n /** Key of the iModel to change selection for. */\n iModelKey: string;\n }): void;\n}\n\n/**\n * Creates a selection storage. When an iModel is closed `SelectionStorage.clearSelection` function should be called.\n * @beta\n */\nexport function createStorage(): SelectionStorage {\n return new SelectionStorageImpl();\n}\n\nclass SelectionStorageImpl implements SelectionStorage {\n private _storage = new Map<string, MultiLevelSelectablesContainer>();\n public selectionChangeEvent: SelectionChangeEventImpl;\n\n constructor() {\n this.selectionChangeEvent = new SelectionChangeEventImpl();\n }\n\n public getSelectionLevels({ iModelKey }: { iModelKey: string }): number[] {\n return this.getContainer(iModelKey).getSelectionLevels();\n }\n\n public getSelection(props: { iModelKey: string; level?: number }): Selectables {\n const { iModelKey, level } = props;\n return this.getContainer(iModelKey).getSelection(level ?? 0);\n }\n\n public addToSelection(props: { source: string; iModelKey: string; selectables: Selectable[]; level?: number }): void {\n this.handleChange({ ...props, changeType: \"add\" });\n }\n\n public removeFromSelection(props: { source: string; iModelKey: string; selectables: Selectable[]; level?: number }): void {\n this.handleChange({ ...props, changeType: \"remove\" });\n }\n\n public replaceSelection(props: { source: string; iModelKey: string; selectables: Selectable[]; level?: number }): void {\n this.handleChange({ ...props, changeType: \"replace\" });\n }\n\n public clearSelection(props: { source: string; iModelKey: string; level?: number }): void {\n this.handleChange({ ...props, changeType: \"clear\", selectables: [] });\n }\n\n public clearStorage({ iModelKey }: { iModelKey: string }): void {\n this.clearSelection({ source: \"Clear iModel storage\", iModelKey });\n this._storage.delete(iModelKey);\n }\n\n private getContainer(iModelKey: string): MultiLevelSelectablesContainer {\n let selectionContainer = this._storage.get(iModelKey);\n if (!selectionContainer) {\n selectionContainer = new MultiLevelSelectablesContainer();\n this._storage.set(iModelKey, selectionContainer);\n }\n return selectionContainer;\n }\n\n private handleChange(props: { source: string; iModelKey: string; level?: number; changeType: StorageSelectionChangeType; selectables: Selectable[] }) {\n const { iModelKey, source, level: inLevel, changeType, selectables: change } = props;\n const container = this.getContainer(iModelKey);\n const level = inLevel ?? 0;\n const selectables = container.getSelection(level);\n const selected = Selectables.create(change);\n switch (changeType) {\n case \"add\":\n if (!Selectables.add(selectables, change)) {\n return;\n }\n break;\n case \"remove\":\n if (!Selectables.remove(selectables, change)) {\n return;\n }\n break;\n case \"replace\":\n if (Selectables.size(selectables) === Selectables.size(selected) && Selectables.hasAll(selectables, change)) {\n return;\n }\n Selectables.clear(selectables);\n Selectables.add(selectables, change);\n break;\n case \"clear\":\n if (!Selectables.clear(selectables)) {\n return;\n }\n break;\n }\n container.clear(level + 1);\n const event: StorageSelectionChangeEventArgs = {\n source,\n level,\n iModelKey,\n changeType,\n selectables: selected,\n timestamp: new Date(),\n };\n this.selectionChangeEvent.raiseEvent(event, this);\n }\n}\n\nclass MultiLevelSelectablesContainer {\n private readonly _selectablesContainers: Map<number, Selectables>;\n\n constructor() {\n this._selectablesContainers = new Map<number, Selectables>();\n }\n\n public getSelection(level: number): Selectables {\n let selectables = this._selectablesContainers.get(level);\n if (!selectables) {\n selectables = Selectables.create([]);\n this._selectablesContainers.set(level, selectables);\n }\n return selectables;\n }\n\n public getSelectionLevels(): number[] {\n const levels = new Array<number>();\n for (const entry of this._selectablesContainers.entries()) {\n if (!Selectables.isEmpty(entry[1])) {\n levels.push(entry[0]);\n }\n }\n return levels.sort();\n }\n\n public clear(level: number) {\n const storedLevels = this._selectablesContainers.keys();\n for (const storedLevel of storedLevels) {\n if (storedLevel >= level) {\n const selectables = this._selectablesContainers.get(storedLevel)!;\n Selectables.clear(selectables);\n }\n }\n }\n}\n"]}
1
+ {"version":3,"file":"SelectionStorage.js","sourceRoot":"","sources":["../../../src/unified-selection/SelectionStorage.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Selectable, Selectables } from \"./Selectable\";\nimport { SelectionChangeEvent, SelectionChangeEventImpl, StorageSelectionChangeEventArgs, StorageSelectionChangeType } from \"./SelectionChangeEvent\";\n\ntype IModelKeyProp =\n | {\n /** Key of the iModel to get selection levels for. */\n imodelKey: string;\n }\n | {\n /**\n * Key of the iModel to get selection levels for.\n * @deprecated in 0.2. Use `imodelKey` instead.\n */\n iModelKey: string;\n };\n\n/**\n * Defines return value of `createStorage`.\n *\n * @beta Used in public API as a return value. Not expected to be created / extended by package\n * consumers, may be supplemented with required attributes any time.\n */\nexport interface SelectionStorage {\n /** An event that is raised when selection changes. */\n selectionChangeEvent: SelectionChangeEvent;\n\n /** Get the selection levels currently stored for the specified iModel. */\n getSelectionLevels(props: IModelKeyProp): number[];\n\n /** Get the selection stored in the storage. */\n getSelection(\n props: IModelKeyProp & {\n /** Level of the selection. Defaults to `0`. */\n level?: number;\n },\n ): Selectables;\n\n /** Add keys to the selection. */\n addToSelection(\n props: IModelKeyProp & {\n /** Name of the selection source. Generally, this identifies the component that makes the selection change. */\n source: string;\n /** The selectables to add to selection. */\n selectables: Selectable[];\n /** Level of the selection. Defaults to `0`. */\n level?: number;\n },\n ): void;\n\n /** Remove keys from current selection. */\n removeFromSelection(\n props: IModelKeyProp & {\n /** Name of the selection source. Generally, this identifies the component that makes the selection change. */\n source: string;\n /** The selectables to remove from selection. */\n selectables: Selectable[];\n /** Level of the selection. Defaults to `0`. */\n level?: number;\n },\n ): void;\n\n /** Replace current selection. */\n replaceSelection(\n props: IModelKeyProp & {\n /** Name of the selection source. Generally, this identifies the component that makes the selection change. */\n source: string;\n /** The selectables to add to selection. */\n selectables: Selectable[];\n /** Level of the selection. Defaults to `0`. */\n level?: number;\n },\n ): void;\n\n /** Clear current selection. */\n clearSelection(\n props: IModelKeyProp & {\n /** Name of the selection source. Generally, this identifies the component that makes the selection change. */\n source: string;\n /** Level of the selection. Defaults to `0`. */\n level?: number;\n },\n ): void;\n\n /** Clear storage for an iModel. This function should be called when iModel is closed. */\n clearStorage(props: IModelKeyProp): void;\n}\n\n/**\n * Creates a selection storage which stores and allows managing application-level selection.\n *\n * **Note:** `clearSelection` should be called upon iModel close to free-up memory:\n * ```ts\n * import { IModelConnection } from \"@itwin/core-frontend\";\n * IModelConnection.onClose.addListener((imodel) => {\n * storage.clearStorage(imodel.key);\n * });\n * ```\n *\n * @beta\n */\nexport function createStorage(): SelectionStorage {\n return new SelectionStorageImpl();\n}\n\n/** @internal */\nexport const IMODEL_CLOSE_SELECTION_CLEAR_SOURCE = \"Unified selection storage: clear\";\n\nclass SelectionStorageImpl implements SelectionStorage {\n private _storage = new Map<string, MultiLevelSelectablesContainer>();\n public selectionChangeEvent: SelectionChangeEventImpl;\n\n constructor() {\n this.selectionChangeEvent = new SelectionChangeEventImpl();\n }\n\n public getSelectionLevels(props: IModelKeyProp): number[] {\n return this.getContainer(getIModelKey(props)).getSelectionLevels();\n }\n\n public getSelection(props: IModelKeyProp & { level?: number }): Selectables {\n return this.getContainer(getIModelKey(props)).getSelection(props.level ?? 0);\n }\n\n public addToSelection(props: IModelKeyProp & { source: string; selectables: Selectable[]; level?: number }): void {\n this.handleChange({ ...props, changeType: \"add\" });\n }\n\n public removeFromSelection(props: IModelKeyProp & { source: string; selectables: Selectable[]; level?: number }): void {\n this.handleChange({ ...props, changeType: \"remove\" });\n }\n\n public replaceSelection(props: IModelKeyProp & { source: string; selectables: Selectable[]; level?: number }): void {\n this.handleChange({ ...props, changeType: \"replace\" });\n }\n\n public clearSelection(props: IModelKeyProp & { source: string; level?: number }): void {\n this.handleChange({ ...props, changeType: \"clear\", selectables: [] });\n }\n\n public clearStorage(props: IModelKeyProp): void {\n const imodelKey = getIModelKey(props);\n this.clearSelection({ source: IMODEL_CLOSE_SELECTION_CLEAR_SOURCE, imodelKey });\n this._storage.delete(imodelKey);\n }\n\n private getContainer(imodelKey: string): MultiLevelSelectablesContainer {\n let selectionContainer = this._storage.get(imodelKey);\n if (!selectionContainer) {\n selectionContainer = new MultiLevelSelectablesContainer();\n this._storage.set(imodelKey, selectionContainer);\n }\n return selectionContainer;\n }\n\n private handleChange(props: IModelKeyProp & { source: string; level?: number; changeType: StorageSelectionChangeType; selectables: Selectable[] }) {\n const { source, level: inLevel, changeType, selectables: change } = props;\n const imodelKey = getIModelKey(props);\n const container = this.getContainer(imodelKey);\n const level = inLevel ?? 0;\n const selectables = container.getSelection(level);\n const selected = Selectables.create(change);\n switch (changeType) {\n case \"add\":\n if (!Selectables.add(selectables, change)) {\n return;\n }\n break;\n case \"remove\":\n if (!Selectables.remove(selectables, change)) {\n return;\n }\n break;\n case \"replace\":\n if (Selectables.size(selectables) === Selectables.size(selected) && Selectables.hasAll(selectables, change)) {\n return;\n }\n Selectables.clear(selectables);\n Selectables.add(selectables, change);\n break;\n case \"clear\":\n if (!Selectables.clear(selectables)) {\n return;\n }\n break;\n }\n container.clear(level + 1);\n const event: StorageSelectionChangeEventArgs = {\n source,\n level,\n imodelKey,\n iModelKey: imodelKey,\n changeType,\n selectables: selected,\n timestamp: new Date(),\n };\n this.selectionChangeEvent.raiseEvent(event, this);\n }\n}\n\nfunction getIModelKey(props: IModelKeyProp): string {\n // eslint-disable-next-line deprecation/deprecation\n return \"imodelKey\" in props ? props.imodelKey : props.iModelKey;\n}\n\nclass MultiLevelSelectablesContainer {\n private readonly _selectablesContainers: Map<number, Selectables>;\n\n constructor() {\n this._selectablesContainers = new Map<number, Selectables>();\n }\n\n public getSelection(level: number): Selectables {\n let selectables = this._selectablesContainers.get(level);\n if (!selectables) {\n selectables = Selectables.create([]);\n this._selectablesContainers.set(level, selectables);\n }\n return selectables;\n }\n\n public getSelectionLevels(): number[] {\n const levels = new Array<number>();\n for (const entry of this._selectablesContainers.entries()) {\n if (!Selectables.isEmpty(entry[1])) {\n levels.push(entry[0]);\n }\n }\n return levels.sort();\n }\n\n public clear(level: number) {\n const storedLevels = this._selectablesContainers.keys();\n for (const storedLevel of storedLevels) {\n if (storedLevel >= level) {\n const selectables = this._selectablesContainers.get(storedLevel)!;\n Selectables.clear(selectables);\n }\n }\n }\n}\n"]}
@@ -0,0 +1,7 @@
1
+ import { ECSqlBinding } from "@itwin/presentation-shared";
2
+ /**
3
+ * Forms ECSql bindings from given ID's.
4
+ * @internal
5
+ */
6
+ export declare function formIdBindings(property: string, ids: string[], bindings: ECSqlBinding[]): string;
7
+ //# sourceMappingURL=Utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Utils.d.ts","sourceRoot":"","sources":["../../../src/unified-selection/Utils.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE1D;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,MAAM,CAYhG"}
@@ -0,0 +1,20 @@
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
+ /**
6
+ * Forms ECSql bindings from given ID's.
7
+ * @internal
8
+ */
9
+ export function formIdBindings(property, ids, bindings) {
10
+ if (ids.length > 1000) {
11
+ bindings.push({ type: "idset", value: ids });
12
+ return `InVirtualSet(?, ${property})`;
13
+ }
14
+ if (ids.length === 0) {
15
+ return `FALSE`;
16
+ }
17
+ ids.forEach((id) => bindings.push({ type: "id", value: id }));
18
+ return `${property} IN (${ids.map(() => "?").join(",")})`;
19
+ }
20
+ //# sourceMappingURL=Utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Utils.js","sourceRoot":"","sources":["../../../src/unified-selection/Utils.ts"],"names":[],"mappings":"AAAA;;;gGAGgG;AAIhG;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,QAAgB,EAAE,GAAa,EAAE,QAAwB;IACtF,IAAI,GAAG,CAAC,MAAM,GAAG,IAAI,EAAE,CAAC;QACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QAC7C,OAAO,mBAAmB,QAAQ,GAAG,CAAC;IACxC,CAAC;IAED,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;IAC9D,OAAO,GAAG,QAAQ,QAAQ,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;AAC5D,CAAC","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\nimport { ECSqlBinding } from \"@itwin/presentation-shared\";\n\n/**\n * Forms ECSql bindings from given ID's.\n * @internal\n */\nexport function formIdBindings(property: string, ids: string[], bindings: ECSqlBinding[]): string {\n if (ids.length > 1000) {\n bindings.push({ type: \"idset\", value: ids });\n return `InVirtualSet(?, ${property})`;\n }\n\n if (ids.length === 0) {\n return `FALSE`;\n }\n\n ids.forEach((id) => bindings.push({ type: \"id\", value: id }));\n return `${property} IN (${ids.map(() => \"?\").join(\",\")})`;\n}\n"]}
@@ -0,0 +1,84 @@
1
+ import { Id64Arg } from "@itwin/core-bentley";
2
+ import { Event } from "@itwin/presentation-shared";
3
+ /**
4
+ * Identifies the type of changes made to the `CoreIModelSelectionSet` to produce a `CoreSelectionSetEvent`.
5
+ * @see https://www.itwinjs.org/reference/core-frontend/selectionset/selectionseteventtype/
6
+ * @internal
7
+ */
8
+ export declare enum CoreSelectionSetEventType {
9
+ /** Elements have been added to the set. */
10
+ Add = 0,
11
+ /** Elements have been removed from the set. */
12
+ Remove = 1,
13
+ /** Some elements have been added to the set and others have been removed. */
14
+ Replace = 2,
15
+ /** All elements are about to be removed from the set. */
16
+ Clear = 3
17
+ }
18
+ /**
19
+ * Payload sent to `CoreIModelSelectionSet.onChanged` event listeners to describe how the contents of the set have changed.
20
+ * @see https://www.itwinjs.org/reference/core-frontend/selectionset/selectionsetevent/
21
+ * @internal
22
+ */
23
+ export interface CoreSelectionSetEventUnsafe {
24
+ /**
25
+ * The type of operation that produced this event.
26
+ *
27
+ * Actually, this should be `CoreSelectionSetEventType`, however we can't use it here because in TS two identical enums with
28
+ * different names aren't equal, so [`SelectionSetEventType `](https://www.itwinjs.org/reference/core-frontend/selectionset/selectionseteventtype/)
29
+ * doesn't map to `CoreSelectionSetEventType` as far as TS is concerned. Due to this reason, this interface is marked as `unsafe`.
30
+ */
31
+ type: number;
32
+ /** The element Ids added to the set. */
33
+ added?: Id64Arg;
34
+ /** The element Ids removed from the set. */
35
+ removed?: Id64Arg;
36
+ /** The affected `CoreIModelSelectionSet`. */
37
+ set: CoreIModelSelectionSet;
38
+ }
39
+ /**
40
+ * A set of *currently selected* elements in an iModel.
41
+ * @see https://www.itwinjs.org/reference/core-frontend/selectionset/
42
+ * @internal
43
+ */
44
+ export interface CoreIModelSelectionSet {
45
+ /** Event called whenever elements are added or removed from this SelectionSet. */
46
+ onChanged: Event<(ev: CoreSelectionSetEventUnsafe) => void>;
47
+ /** The IDs of the selected elements. */
48
+ readonly elements: Set<string>;
49
+ /** Clear current selection set. */
50
+ emptyAll(): void;
51
+ /** Add one or more Ids to the current selection set. */
52
+ add(elem: Id64Arg): boolean;
53
+ /** Remove one or more Ids from the current selection set. */
54
+ remove(elem: Id64Arg): boolean;
55
+ }
56
+ /**
57
+ * A set if ID's optimized for performance-critical code which represents large sets of ID's as pairs of 32-bit integers.
58
+ * @see https://www.itwinjs.org/reference/core-bentley/ids/id64/id64.uint32set/
59
+ */
60
+ interface Uint32Set {
61
+ /** Add any number of Ids to the set. */
62
+ addIds(ids: Id64Arg): void;
63
+ /** Remove any number of Ids from the set. */
64
+ deleteIds(ids: Id64Arg): void;
65
+ }
66
+ /**
67
+ * A set of *hilited* elements in an iModel, by element id.
68
+ * @see https://www.itwinjs.org/reference/core-frontend/selectionset/hiliteset/
69
+ * @internal
70
+ */
71
+ export interface CoreIModelHiliteSet {
72
+ /** Control whether the hilited elements should be synchronized with the contents of `CoreIModelSelectionSet`.*/
73
+ wantSyncWithSelectionSet: boolean;
74
+ /** The set of hilited elements. */
75
+ readonly elements: Uint32Set;
76
+ /** The set of hilited subcategories. */
77
+ readonly subcategories: Uint32Set;
78
+ /** The set of hilited models. */
79
+ readonly models: Uint32Set;
80
+ /** Remove all elements from the hilited set. */
81
+ clear(): void;
82
+ }
83
+ export {};
84
+ //# sourceMappingURL=IModel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IModel.d.ts","sourceRoot":"","sources":["../../../../src/unified-selection/types/IModel.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAC;AAEnD;;;;GAIG;AACH,oBAAY,yBAAyB;IACnC,2CAA2C;IAC3C,GAAG,IAAA;IACH,+CAA+C;IAC/C,MAAM,IAAA;IACN,6EAA6E;IAC7E,OAAO,IAAA;IACP,yDAAyD;IACzD,KAAK,IAAA;CACN;AAED;;;;GAIG;AACH,MAAM,WAAW,2BAA2B;IAC1C;;;;;;OAMG;IACH,IAAI,EAAE,MAAM,CAAC;IACb,wCAAwC;IACxC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,4CAA4C;IAC5C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,6CAA6C;IAC7C,GAAG,EAAE,sBAAsB,CAAC;CAC7B;AAED;;;;GAIG;AACH,MAAM,WAAW,sBAAsB;IACrC,kFAAkF;IAClF,SAAS,EAAE,KAAK,CAAC,CAAC,EAAE,EAAE,2BAA2B,KAAK,IAAI,CAAC,CAAC;IAC5D,wCAAwC;IACxC,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC/B,mCAAmC;IACnC,QAAQ,IAAI,IAAI,CAAC;IACjB,wDAAwD;IACxD,GAAG,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;IAC5B,6DAA6D;IAC7D,MAAM,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;CAChC;AAED;;;GAGG;AACH,UAAU,SAAS;IACjB,wCAAwC;IACxC,MAAM,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAAC;IAC3B,6CAA6C;IAC7C,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAAC;CAC/B;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,gHAAgH;IAChH,wBAAwB,EAAE,OAAO,CAAC;IAClC,mCAAmC;IACnC,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC;IAC7B,wCAAwC;IACxC,QAAQ,CAAC,aAAa,EAAE,SAAS,CAAC;IAClC,iCAAiC;IACjC,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,gDAAgD;IAChD,KAAK,IAAI,IAAI,CAAC;CACf"}