@vcmap/ui 6.1.0-rc.1 → 6.1.0-rc.3
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/config/base.config.json +6 -0
- package/config/clipping.config.json +384 -0
- package/config/cluster.config.json +106 -0
- package/config/concepts-show-case.config.json +4 -0
- package/config/projects.config.json +5 -2
- package/dist/assets/{cesium-11e5bbc6.js → cesium-87d5e72d.js} +438 -432
- package/dist/assets/cesium.js +1 -1
- package/dist/assets/{core-9d0cfec3.js → core-72f9f393.js} +4907 -4514
- package/dist/assets/core.js +1 -1
- package/dist/assets/{ol-0d0ebb27.js → ol-e468ba43.js} +23518 -22404
- package/dist/assets/ol.js +1 -1
- package/dist/assets/ui-73257b15.css +1 -0
- package/dist/assets/{ui-08446666.js → ui-73257b15.js} +13703 -12977
- package/dist/assets/ui.js +1 -1
- package/dist/assets/vue.js +1 -1
- package/dist/assets/{vuetify-67025c41.css → vuetify-2437380c.css} +2 -2
- package/dist/assets/{vuetify-67025c41.js → vuetify-2437380c.js} +8024 -7634
- package/dist/assets/vuetify.js +1 -1
- package/index.d.ts +40 -19
- package/index.js +36 -6
- package/lib/olLib.js +25 -3
- package/package.json +6 -6
- package/plugins/@vcmap-show-case/callback-tester/README.md +3 -0
- package/plugins/@vcmap-show-case/callback-tester/package.json +5 -0
- package/plugins/@vcmap-show-case/callback-tester/src/CallbackTester.vue +62 -0
- package/plugins/@vcmap-show-case/callback-tester/src/index.js +48 -0
- package/plugins/@vcmap-show-case/form-inputs-example/src/FormInputsExample.vue +1 -0
- package/src/actions/actionHelper.d.ts +1 -0
- package/src/actions/actionHelper.js +70 -19
- package/src/application/VcsApp.vue +83 -50
- package/src/application/VcsApp.vue.d.ts +28 -2
- package/src/application/VcsContainer.vue +5 -3
- package/src/application/VcsContainer.vue.d.ts +14 -0
- package/src/application/VcsNavbar.vue +10 -6
- package/src/application/VcsNavbar.vue.d.ts +2 -0
- package/src/application/VcsObliqueFooter.vue +9 -3
- package/src/application/VcsSplashScreen.vue +37 -0
- package/src/application/VcsSplashScreen.vue.d.ts +6 -0
- package/src/application/positionDisplayInteraction.js +1 -1
- package/src/callback/activateClippingPolygonCallback.d.ts +29 -0
- package/src/callback/activateClippingPolygonCallback.js +54 -0
- package/src/callback/closeSplashScreenCallback.d.ts +8 -0
- package/src/callback/closeSplashScreenCallback.js +33 -0
- package/src/callback/deactivateClippingPolygonCallback.d.ts +29 -0
- package/src/callback/deactivateClippingPolygonCallback.js +54 -0
- package/src/callback/openSplashScreenCallback.d.ts +8 -0
- package/src/callback/openSplashScreenCallback.js +35 -0
- package/src/callback/toggleNavbarButtonCallback.d.ts +36 -0
- package/src/callback/toggleNavbarButtonCallback.js +62 -0
- package/src/components/buttons/VcsActionButtonList.vue +6 -4
- package/src/components/buttons/VcsToolButton.vue +0 -1
- package/src/components/form-inputs-controls/VcsDatePicker.vue +7 -1
- package/src/components/form-inputs-controls/VcsDatePicker.vue.d.ts +9 -0
- package/src/components/form-inputs-controls/VcsSelect.vue +1 -1
- package/src/components/form-inputs-controls/VcsTextArea.vue +13 -8
- package/src/components/form-output/markdownHelper.d.ts +0 -25
- package/src/components/form-output/markdownHelper.js +1 -386
- package/src/components/import/VcsImportComponent.vue +2 -0
- package/src/components/lists/VcsGroupedList.vue +178 -0
- package/src/components/lists/VcsGroupedList.vue.d.ts +17 -0
- package/src/components/lists/VcsList.vue +144 -394
- package/src/components/lists/VcsList.vue.d.ts +38 -159
- package/src/components/lists/VcsTreeNode.vue +18 -11
- package/src/components/lists/VcsTreeview.vue +27 -20
- package/src/components/lists/VcsTreeview.vue.d.ts +18 -1
- package/src/components/lists/listHelper.d.ts +87 -0
- package/src/components/lists/listHelper.js +348 -0
- package/src/components/section/VcsFormSection.vue +7 -2
- package/src/components/section/VcsFormSection.vue.d.ts +9 -0
- package/src/components/tables/VcsDataTable.vue +14 -3
- package/src/components/tables/VcsDataTable.vue.d.ts +9 -0
- package/src/components/vector-properties/VcsVectorPropertiesComponent.vue.d.ts +1 -1
- package/src/contentTree/LayerTree.vue +2 -1
- package/src/contentTree/LayerTree.vue.d.ts +2 -0
- package/src/contentTree/contentTreeCollection.d.ts +1 -0
- package/src/contentTree/contentTreeCollection.js +7 -3
- package/src/contentTree/contentTreeItem.js +4 -2
- package/src/contentTree/groupContentTreeItem.js +5 -3
- package/src/featureInfo/ClusterFeatureComponent.vue +58 -0
- package/src/featureInfo/ClusterFeatureComponent.vue.d.ts +6 -0
- package/src/featureInfo/abstractFeatureInfoView.js +1 -2
- package/src/featureInfo/featureInfo.d.ts +87 -1
- package/src/featureInfo/featureInfo.js +342 -34
- package/src/featureInfo/featureInfoInteraction.js +18 -3
- package/src/featureInfo/iframeFeatureInfoView.js +1 -1
- package/src/featureInfo/markdownBalloonFeatureInfoView.js +2 -4
- package/src/featureInfo/markdownFeatureInfoView.js +1 -1
- package/src/i18n/de.d.ts +17 -4
- package/src/i18n/de.js +7 -0
- package/src/i18n/en.d.ts +17 -4
- package/src/i18n/en.js +7 -0
- package/src/legend/VcsLegend.vue +1 -1
- package/src/legend/legendHelper.d.ts +1 -1
- package/src/legend/legendHelper.js +52 -9
- package/src/localStorage.d.ts +21 -0
- package/src/localStorage.js +51 -0
- package/src/manager/collectionManager/CollectionComponent.vue +1 -1
- package/src/manager/collectionManager/CollectionComponentContent.vue +2 -3
- package/src/manager/collectionManager/CollectionComponentList.vue +2 -3
- package/src/manager/collectionManager/CollectionComponentStandalone.vue +1 -1
- package/src/manager/navbarManager.js +9 -4
- package/src/manager/toolbox/ToolboxManagerComponent.vue +14 -12
- package/src/manager/toolbox/ToolboxManagerComponent.vue.d.ts +13 -2
- package/src/manager/toolbox/toolboxManager.d.ts +5 -0
- package/src/manager/toolbox/toolboxManager.js +7 -1
- package/src/manager/window/WindowComponent.vue +10 -0
- package/src/manager/window/WindowComponent.vue.d.ts +1 -0
- package/src/manager/window/WindowManager.vue +14 -4
- package/src/manager/window/WindowManager.vue.d.ts +1 -0
- package/src/manager/window/windowHelper.d.ts +7 -3
- package/src/manager/window/windowHelper.js +30 -10
- package/src/navigation/MapNavigation.vue +5 -5
- package/src/navigation/MapNavigation.vue.d.ts +1 -1
- package/src/navigation/overviewMap.d.ts +7 -0
- package/src/navigation/overviewMap.js +18 -4
- package/src/pluginHelper.d.ts +7 -0
- package/src/pluginHelper.js +18 -4
- package/src/search/ResultItem.vue.d.ts +1 -1
- package/src/search/markText.d.ts +1 -1
- package/src/search/markText.js +4 -4
- package/src/search/search.js +1 -1
- package/src/state.d.ts +4 -2
- package/src/state.js +54 -31
- package/src/uiConfig.d.ts +36 -0
- package/src/uiConfig.js +17 -1
- package/src/vcsUiApp.js +7 -11
- package/dist/assets/ui-08446666.css +0 -1
- /package/dist/assets/{vue-2f81c7f8.js → vue-ff37ea23.js} +0 -0
@@ -1,3 +1,10 @@
|
|
1
|
+
/**
|
2
|
+
*
|
3
|
+
* @param {import("ol/style/Style.js").default?} style
|
4
|
+
* @param {import("@vcmap-cesium/engine").Color} fillColor
|
5
|
+
* @returns {import("ol/style/Style.js").default}
|
6
|
+
*/
|
7
|
+
export function getHighlightStyleFromStyle(style: import("ol/style/Style.js").default | null, fillColor: import("@vcmap-cesium/engine").Color): import("ol/style/Style.js").default;
|
1
8
|
/**
|
2
9
|
* @param {FeatureType} feature
|
3
10
|
* @param {import("@vcmap/core").Layer} layer
|
@@ -5,6 +12,14 @@
|
|
5
12
|
* @returns {import("ol/style/Style.js").default|import("@vcmap/core").VectorStyleItem}
|
6
13
|
*/
|
7
14
|
export function getHighlightStyle(feature: FeatureType, layer: import("@vcmap/core").Layer, defaultFillColor: string): import("ol/style/Style.js").default | import("@vcmap/core").VectorStyleItem;
|
15
|
+
/**
|
16
|
+
* @param {import("ol").Feature} clusterFeature
|
17
|
+
* @param {import("@vcmap/core").VectorClusterGroup} clusterGroup
|
18
|
+
* @param {import("ol/style/Style.js").default} clusterStyle
|
19
|
+
* @param {string} defaultFillColor
|
20
|
+
* @returns {import("ol/style/Style.js").default}
|
21
|
+
*/
|
22
|
+
export function getClusterHighlightStyle(clusterFeature: import("ol").Feature, clusterGroup: import("@vcmap/core").VectorClusterGroup, clusterStyle: import("ol/style/Style.js").default, defaultFillColor: string): import("ol/style/Style.js").default;
|
8
23
|
/**
|
9
24
|
* @param {import("../vcsUiApp.js").default} app
|
10
25
|
* @returns {FeatureInfoSession}
|
@@ -69,7 +84,12 @@ declare class FeatureInfo extends Collection<AbstractFeatureInfoView> {
|
|
69
84
|
*/
|
70
85
|
private _windowId;
|
71
86
|
/**
|
72
|
-
* @type {
|
87
|
+
* @type {string|null}
|
88
|
+
* @private
|
89
|
+
*/
|
90
|
+
private _clusterWindowId;
|
91
|
+
/**
|
92
|
+
* @type {VcsEvent<FeatureType|null>}
|
73
93
|
* @private
|
74
94
|
*/
|
75
95
|
private _featureChanged;
|
@@ -83,6 +103,21 @@ declare class FeatureInfo extends Collection<AbstractFeatureInfoView> {
|
|
83
103
|
* @private
|
84
104
|
*/
|
85
105
|
private _selectedFeatureId;
|
106
|
+
/**
|
107
|
+
* @type {VcsEvent<import("ol").Feature|null>}
|
108
|
+
* @private
|
109
|
+
*/
|
110
|
+
private _clusterFeatureChanged;
|
111
|
+
/**
|
112
|
+
* @type {import("ol").Feature|null}
|
113
|
+
* @private
|
114
|
+
*/
|
115
|
+
private _selectedClusterFeature;
|
116
|
+
/**
|
117
|
+
* @type {string|null}
|
118
|
+
* @private
|
119
|
+
*/
|
120
|
+
private _selectedClusterFeatureId;
|
86
121
|
/**
|
87
122
|
* @type {Array<function():void>}
|
88
123
|
* @private
|
@@ -96,6 +131,8 @@ declare class FeatureInfo extends Collection<AbstractFeatureInfoView> {
|
|
96
131
|
*/
|
97
132
|
private _scratchLayer;
|
98
133
|
/**
|
134
|
+
* Emitted whenever a feature is selected or cleared.
|
135
|
+
* Does not reflect cluster feature changes!
|
99
136
|
* @type {VcsEvent<null|FeatureType>}
|
100
137
|
*/
|
101
138
|
get featureChanged(): VcsEvent<FeatureType | null>;
|
@@ -107,11 +144,29 @@ declare class FeatureInfo extends Collection<AbstractFeatureInfoView> {
|
|
107
144
|
* @type {null|string}
|
108
145
|
*/
|
109
146
|
get selectedFeatureId(): string | null;
|
147
|
+
/**
|
148
|
+
* Emitted whenever a cluster feature is selected or cleared.
|
149
|
+
* @type {VcsEvent<null|import("ol").Feature>}
|
150
|
+
*/
|
151
|
+
get clusterFeatureChanged(): VcsEvent<Feature<import("ol/geom.js").Geometry> | null>;
|
152
|
+
/**
|
153
|
+
* @type {null|import("ol").Feature}
|
154
|
+
*/
|
155
|
+
get selectedClusterFeature(): Feature<import("ol/geom.js").Geometry> | null;
|
156
|
+
/**
|
157
|
+
* @type {null|string}
|
158
|
+
*/
|
159
|
+
get selectedClusterFeatureId(): string | null;
|
110
160
|
/**
|
111
161
|
* The window id of the current features FeatureInfoView window
|
112
162
|
* @type {string|null}
|
113
163
|
*/
|
114
164
|
get windowId(): string | null;
|
165
|
+
/**
|
166
|
+
* The window id of the current cluster feature window
|
167
|
+
* @type {string|null}
|
168
|
+
*/
|
169
|
+
get clusterWindowId(): string | null;
|
115
170
|
/**
|
116
171
|
* @private
|
117
172
|
*/
|
@@ -136,11 +191,42 @@ declare class FeatureInfo extends Collection<AbstractFeatureInfoView> {
|
|
136
191
|
* @returns {Promise<void>}
|
137
192
|
*/
|
138
193
|
selectFeature(feature: FeatureType, position?: import("ol/coordinate.js").Coordinate | undefined, windowPosition?: import("ol/coordinate.js").Coordinate | undefined, featureInfoView?: AbstractFeatureInfoView | undefined): Promise<void>;
|
194
|
+
/**
|
195
|
+
* Selecting a cluster feature opens a window listing the features belonging to the cluster feature.
|
196
|
+
* To be listed the feature must meet the following criteria: a) the feature must be part of a layer, b) said layer must be managed in
|
197
|
+
* the same VcsApp as provided to the FeatureInfo on construction. if not providing a feature info view, then c) said layer must have a featureInfo property set on
|
198
|
+
* its properties bag and d) said featureInfo property must provide the name of a FeatureInfoView present on this FeatureInfos
|
199
|
+
* collection.
|
200
|
+
* The cluster feature will be cloned, highlighted and added on an internal scratch layer to ensure availability until deselection.
|
201
|
+
* The original cluster feature will be hidden until deselection.
|
202
|
+
* @param {import("ol").Feature} clusterFeature
|
203
|
+
* @returns {Promise<void>}
|
204
|
+
*/
|
205
|
+
selectClusterFeature(clusterFeature: import("ol").Feature): Promise<void>;
|
139
206
|
/**
|
140
207
|
* Clears the current feature. remove window, highlighting and provided feature.
|
141
208
|
* @private
|
142
209
|
*/
|
143
210
|
private _clearInternal;
|
211
|
+
/**
|
212
|
+
* Clears the current cluster feature. remove window, highlighting and provided cluster feature.
|
213
|
+
* @private
|
214
|
+
*/
|
215
|
+
private _clearClusterInternal;
|
216
|
+
/**
|
217
|
+
* Deselecting feature clears highlighting and closes FeatureInfoView. fires feature changed with null
|
218
|
+
*/
|
219
|
+
clearFeature(): void;
|
220
|
+
/**
|
221
|
+
* Deselecting and removing cluster feature. Closing cluster window and fires cluster feature changed with null
|
222
|
+
*/
|
223
|
+
clearCluster(): void;
|
224
|
+
/**
|
225
|
+
* Clears selection by deselecting current feature and cluster and closing all related windows.
|
226
|
+
* Fires feature changed and cluster feature changed events with null.
|
227
|
+
*/
|
228
|
+
clearSelection(): void;
|
144
229
|
}
|
145
230
|
import { VcsEvent } from '@vcmap/core';
|
146
231
|
import { Collection } from '@vcmap/core';
|
232
|
+
import { Feature } from 'ol';
|
@@ -12,6 +12,11 @@ import {
|
|
12
12
|
VectorStyleItem,
|
13
13
|
markVolatile,
|
14
14
|
maxZIndex,
|
15
|
+
vectorClusterGroupName,
|
16
|
+
hidden,
|
17
|
+
isProvidedClusterFeature,
|
18
|
+
alreadyTransformedToImage,
|
19
|
+
ObliqueMap,
|
15
20
|
} from '@vcmap/core';
|
16
21
|
import { getLogger as getLoggerByName } from '@vcsuite/logger';
|
17
22
|
import {
|
@@ -24,6 +29,7 @@ import { Feature } from 'ol';
|
|
24
29
|
import { check, maybe, oneOf } from '@vcsuite/check';
|
25
30
|
|
26
31
|
import { reactive } from 'vue';
|
32
|
+
import { WindowSlot } from '../manager/window/windowManager.js';
|
27
33
|
import { vcsAppSymbol } from '../pluginHelper.js';
|
28
34
|
import FeatureInfoInteraction from './featureInfoInteraction.js';
|
29
35
|
import AbstractFeatureInfoView from './abstractFeatureInfoView.js';
|
@@ -36,6 +42,7 @@ import { getDefaultPrimaryColor } from '../vuePlugins/vuetify.js';
|
|
36
42
|
import { ToolboxType } from '../manager/toolbox/toolboxManager.js';
|
37
43
|
import MarkdownBalloonFeatureInfoView from './markdownBalloonFeatureInfoView.js';
|
38
44
|
import IframeWmsFeatureInfoView from './iframeWmsFeatureInfoView.js';
|
45
|
+
import ClusterFeatureComponent from './ClusterFeatureComponent.vue';
|
39
46
|
|
40
47
|
/** @typedef {import("ol").Feature|import("@vcmap-cesium/engine").Cesium3DTileFeature|import("@vcmap-cesium/engine").Cesium3DTilePointFeature|import("@vcmap-cesium/engine").Entity} FeatureType */
|
41
48
|
|
@@ -64,6 +71,43 @@ export const featureInfoClassRegistry = new ClassRegistry();
|
|
64
71
|
*/
|
65
72
|
export const featureInfoViewSymbol = Symbol('featureInfoView');
|
66
73
|
|
74
|
+
/**
|
75
|
+
*
|
76
|
+
* @param {import("ol/style/Style.js").default?} style
|
77
|
+
* @param {import("@vcmap-cesium/engine").Color} fillColor
|
78
|
+
* @returns {import("ol/style/Style.js").default}
|
79
|
+
*/
|
80
|
+
export function getHighlightStyleFromStyle(style, fillColor) {
|
81
|
+
const highlightStyle =
|
82
|
+
style?.clone?.() ??
|
83
|
+
new VectorStyleItem(getDefaultVectorStyleItemOptions()).style;
|
84
|
+
if (highlightStyle.getText()) {
|
85
|
+
if (highlightStyle.getText().getFill()) {
|
86
|
+
highlightStyle.getText().getFill().setColor(fillColor.toCssColorString());
|
87
|
+
}
|
88
|
+
highlightStyle
|
89
|
+
.getText()
|
90
|
+
.setScale((highlightStyle.getText().getScale() ?? 1) * 2);
|
91
|
+
}
|
92
|
+
if (highlightStyle.getImage()) {
|
93
|
+
highlightStyle
|
94
|
+
.getImage()
|
95
|
+
.setScale(highlightStyle.getImage().getScale() * 2);
|
96
|
+
}
|
97
|
+
if (highlightStyle.getStroke()) {
|
98
|
+
highlightStyle.getStroke().setColor(fillColor.toCssColorString());
|
99
|
+
highlightStyle
|
100
|
+
.getStroke()
|
101
|
+
.setWidth(highlightStyle.getStroke().getWidth() * 2);
|
102
|
+
}
|
103
|
+
if (highlightStyle.getFill()) {
|
104
|
+
const color = fillColor.toBytes();
|
105
|
+
color[3] /= 255;
|
106
|
+
highlightStyle.getFill().setColor(color);
|
107
|
+
}
|
108
|
+
return highlightStyle;
|
109
|
+
}
|
110
|
+
|
67
111
|
/**
|
68
112
|
* @param {FeatureType} feature
|
69
113
|
* @param {import("@vcmap/core").Layer} layer
|
@@ -71,7 +115,7 @@ export const featureInfoViewSymbol = Symbol('featureInfoView');
|
|
71
115
|
* @returns {import("ol/style/Style.js").default|import("@vcmap/core").VectorStyleItem}
|
72
116
|
*/
|
73
117
|
export function getHighlightStyle(feature, layer, defaultFillColor) {
|
74
|
-
if (layer
|
118
|
+
if (layer?.highlightStyle) {
|
75
119
|
return layer.highlightStyle;
|
76
120
|
}
|
77
121
|
|
@@ -81,32 +125,32 @@ export function getHighlightStyle(feature, layer, defaultFillColor) {
|
|
81
125
|
if (typeof style === 'function') {
|
82
126
|
style = style(feature, 1);
|
83
127
|
}
|
84
|
-
style
|
85
|
-
style?.clone?.() ??
|
86
|
-
new VectorStyleItem(getDefaultVectorStyleItemOptions()).style;
|
87
|
-
if (style.getText()) {
|
88
|
-
if (style.getText().getFill()) {
|
89
|
-
style.getText().getFill().setColor(fillColor.toCssColorString());
|
90
|
-
}
|
91
|
-
style.getText().setScale((style.getText().getScale() ?? 1) * 2);
|
92
|
-
}
|
93
|
-
if (style.getImage()) {
|
94
|
-
style.getImage().setScale(style.getImage().getScale() * 2);
|
95
|
-
}
|
96
|
-
if (style.getStroke()) {
|
97
|
-
style.getStroke().setColor(fillColor.toCssColorString());
|
98
|
-
style.getStroke().setWidth(style.getStroke().getWidth() * 2);
|
99
|
-
}
|
100
|
-
if (style.getFill()) {
|
101
|
-
const color = fillColor.toBytes();
|
102
|
-
color[3] /= 255;
|
103
|
-
style.getFill().setColor(color);
|
104
|
-
}
|
105
|
-
return style;
|
128
|
+
return getHighlightStyleFromStyle(style, fillColor);
|
106
129
|
}
|
107
130
|
return fromCesiumColor(fillColor);
|
108
131
|
}
|
109
132
|
|
133
|
+
/**
|
134
|
+
* @param {import("ol").Feature} clusterFeature
|
135
|
+
* @param {import("@vcmap/core").VectorClusterGroup} clusterGroup
|
136
|
+
* @param {import("ol/style/Style.js").default} clusterStyle
|
137
|
+
* @param {string} defaultFillColor
|
138
|
+
* @returns {import("ol/style/Style.js").default}
|
139
|
+
*/
|
140
|
+
export function getClusterHighlightStyle(
|
141
|
+
clusterFeature,
|
142
|
+
clusterGroup,
|
143
|
+
clusterStyle,
|
144
|
+
defaultFillColor,
|
145
|
+
) {
|
146
|
+
if (clusterGroup?.highlightStyle) {
|
147
|
+
return clusterGroup.getHighlightStyleForFeature(clusterFeature);
|
148
|
+
}
|
149
|
+
|
150
|
+
const fillColor = Color.fromCssColorString(defaultFillColor).withAlpha(0.8);
|
151
|
+
return getHighlightStyleFromStyle(clusterStyle, fillColor);
|
152
|
+
}
|
153
|
+
|
110
154
|
/**
|
111
155
|
* @param {import("../vcsUiApp.js").default} app
|
112
156
|
* @returns {FeatureInfoSession}
|
@@ -158,7 +202,7 @@ function setupFeatureInfoTool(app) {
|
|
158
202
|
session.stopped.addEventListener(() => {
|
159
203
|
action.active = false;
|
160
204
|
session = null;
|
161
|
-
app.featureInfo.
|
205
|
+
app.featureInfo.clearSelection();
|
162
206
|
action.title = 'featureInfo.activateToolTitle';
|
163
207
|
});
|
164
208
|
this.active = true;
|
@@ -266,7 +310,12 @@ class FeatureInfo extends Collection {
|
|
266
310
|
*/
|
267
311
|
this._windowId = null;
|
268
312
|
/**
|
269
|
-
* @type {
|
313
|
+
* @type {string|null}
|
314
|
+
* @private
|
315
|
+
*/
|
316
|
+
this._clusterWindowId = null;
|
317
|
+
/**
|
318
|
+
* @type {VcsEvent<FeatureType|null>}
|
270
319
|
* @private
|
271
320
|
*/
|
272
321
|
this._featureChanged = new VcsEvent();
|
@@ -280,6 +329,21 @@ class FeatureInfo extends Collection {
|
|
280
329
|
* @private
|
281
330
|
*/
|
282
331
|
this._selectedFeatureId = null;
|
332
|
+
/**
|
333
|
+
* @type {VcsEvent<import("ol").Feature|null>}
|
334
|
+
* @private
|
335
|
+
*/
|
336
|
+
this._clusterFeatureChanged = new VcsEvent();
|
337
|
+
/**
|
338
|
+
* @type {import("ol").Feature|null}
|
339
|
+
* @private
|
340
|
+
*/
|
341
|
+
this._selectedClusterFeature = null;
|
342
|
+
/**
|
343
|
+
* @type {string|null}
|
344
|
+
* @private
|
345
|
+
*/
|
346
|
+
this._selectedClusterFeatureId = null;
|
283
347
|
/**
|
284
348
|
* @type {Array<function():void>}
|
285
349
|
* @private
|
@@ -305,18 +369,39 @@ class FeatureInfo extends Collection {
|
|
305
369
|
) {
|
306
370
|
this._app.windowManager.remove(this._windowId);
|
307
371
|
}
|
372
|
+
|
373
|
+
if (
|
374
|
+
this._clusterWindowId &&
|
375
|
+
this._app.windowManager.has(this._clusterWindowId)
|
376
|
+
) {
|
377
|
+
const { props } = this._app.windowManager.get(this._clusterWindowId);
|
378
|
+
if (props.items.some((item) => item.group === layer.name)) {
|
379
|
+
props.items = props.items.filter(
|
380
|
+
(item) => item.group !== layer.name,
|
381
|
+
);
|
382
|
+
props.groups = props.groups.filter(
|
383
|
+
(group) => group.name !== layer.name,
|
384
|
+
);
|
385
|
+
if (props.items.length === 0) {
|
386
|
+
this._app.windowManager.remove(this._clusterWindowId);
|
387
|
+
}
|
388
|
+
}
|
389
|
+
}
|
308
390
|
}),
|
309
391
|
this._app.windowManager.removed.addEventListener(({ id }) => {
|
310
392
|
if (id === this._windowId) {
|
311
|
-
this.
|
393
|
+
this.clearFeature();
|
394
|
+
}
|
395
|
+
if (id === this._clusterWindowId) {
|
396
|
+
this.clearCluster();
|
312
397
|
}
|
313
398
|
}),
|
314
399
|
this._app.moduleAdded.addEventListener(() => {
|
315
|
-
this.
|
400
|
+
this.clearSelection();
|
316
401
|
this._destroyFeatureInfoTool();
|
317
402
|
this._destroyFeatureInfoTool = setupFeatureInfoTool(this._app);
|
318
403
|
}),
|
319
|
-
this._app.moduleRemoved.addEventListener(() => this.
|
404
|
+
this._app.moduleRemoved.addEventListener(() => this.clearSelection()),
|
320
405
|
];
|
321
406
|
/**
|
322
407
|
* A vector layer to render provided features on
|
@@ -332,6 +417,8 @@ class FeatureInfo extends Collection {
|
|
332
417
|
}
|
333
418
|
|
334
419
|
/**
|
420
|
+
* Emitted whenever a feature is selected or cleared.
|
421
|
+
* Does not reflect cluster feature changes!
|
335
422
|
* @type {VcsEvent<null|FeatureType>}
|
336
423
|
*/
|
337
424
|
get featureChanged() {
|
@@ -352,6 +439,28 @@ class FeatureInfo extends Collection {
|
|
352
439
|
return this._selectedFeatureId;
|
353
440
|
}
|
354
441
|
|
442
|
+
/**
|
443
|
+
* Emitted whenever a cluster feature is selected or cleared.
|
444
|
+
* @type {VcsEvent<null|import("ol").Feature>}
|
445
|
+
*/
|
446
|
+
get clusterFeatureChanged() {
|
447
|
+
return this._clusterFeatureChanged;
|
448
|
+
}
|
449
|
+
|
450
|
+
/**
|
451
|
+
* @type {null|import("ol").Feature}
|
452
|
+
*/
|
453
|
+
get selectedClusterFeature() {
|
454
|
+
return this._selectedClusterFeature;
|
455
|
+
}
|
456
|
+
|
457
|
+
/**
|
458
|
+
* @type {null|string}
|
459
|
+
*/
|
460
|
+
get selectedClusterFeatureId() {
|
461
|
+
return this._selectedClusterFeatureId;
|
462
|
+
}
|
463
|
+
|
355
464
|
/**
|
356
465
|
* The window id of the current features FeatureInfoView window
|
357
466
|
* @type {string|null}
|
@@ -360,6 +469,14 @@ class FeatureInfo extends Collection {
|
|
360
469
|
return this._windowId;
|
361
470
|
}
|
362
471
|
|
472
|
+
/**
|
473
|
+
* The window id of the current cluster feature window
|
474
|
+
* @type {string|null}
|
475
|
+
*/
|
476
|
+
get clusterWindowId() {
|
477
|
+
return this._clusterWindowId;
|
478
|
+
}
|
479
|
+
|
363
480
|
/**
|
364
481
|
* @private
|
365
482
|
*/
|
@@ -426,10 +543,19 @@ class FeatureInfo extends Collection {
|
|
426
543
|
|
427
544
|
if (usedFeatureInfoView && layer) {
|
428
545
|
this._clearInternal();
|
546
|
+
if (
|
547
|
+
this._selectedClusterFeature &&
|
548
|
+
!this._selectedClusterFeature.get('features').includes(feature)
|
549
|
+
) {
|
550
|
+
this.clearCluster();
|
551
|
+
}
|
429
552
|
if (feature[isProvidedFeature]) {
|
430
553
|
this._ensureScratchLayer();
|
431
|
-
|
432
|
-
const
|
554
|
+
// we need to clone the feature to avoid changing vcsLayerNameSymbol on the original feature
|
555
|
+
const clonedFeature = feature.clone();
|
556
|
+
clonedFeature.setId(feature.getId());
|
557
|
+
this._scratchLayer.addFeatures([clonedFeature]);
|
558
|
+
const featureId = clonedFeature.getId(); // make sure to grab ID after adding it to the layer
|
433
559
|
this._scratchLayer.featureVisibility.highlight({
|
434
560
|
[featureId]: getHighlightStyle(
|
435
561
|
feature,
|
@@ -440,6 +566,29 @@ class FeatureInfo extends Collection {
|
|
440
566
|
});
|
441
567
|
this._clearHighlightingCb = () =>
|
442
568
|
this._scratchLayer.featureVisibility.unHighlight([featureId]);
|
569
|
+
} else if (layer.vectorClusterGroup) {
|
570
|
+
this._ensureScratchLayer();
|
571
|
+
const clone = feature.clone();
|
572
|
+
const featureId = feature.getId();
|
573
|
+
this._scratchLayer.vectorProperties.setValuesForFeatures(
|
574
|
+
layer.vectorProperties.getValuesForFeatures([clone]),
|
575
|
+
[clone],
|
576
|
+
);
|
577
|
+
const eyeOffset = clone.get('olcs_eyeOffset') ?? [0, 0, 0];
|
578
|
+
eyeOffset[2] -= 10;
|
579
|
+
clone.set('olcs_eyeOffset', eyeOffset);
|
580
|
+
clone.setId(featureId);
|
581
|
+
this._scratchLayer.addFeatures([clone]);
|
582
|
+
this._scratchLayer.featureVisibility.highlight({
|
583
|
+
[featureId]: getHighlightStyle(
|
584
|
+
feature,
|
585
|
+
layer,
|
586
|
+
this._app.uiConfig.config.primaryColor ??
|
587
|
+
getDefaultPrimaryColor(this._app),
|
588
|
+
),
|
589
|
+
});
|
590
|
+
this._clearHighlightingCb = () =>
|
591
|
+
this._scratchLayer.featureVisibility.unHighlight([clone]);
|
443
592
|
} else if (layer.featureVisibility) {
|
444
593
|
const featureId = feature.getId();
|
445
594
|
layer.featureVisibility.highlight({
|
@@ -470,10 +619,117 @@ class FeatureInfo extends Collection {
|
|
470
619
|
this._selectedFeatureId = feature.getId();
|
471
620
|
this._featureChanged.raiseEvent(this._selectedFeature);
|
472
621
|
} else {
|
473
|
-
this.
|
622
|
+
this.clearSelection();
|
474
623
|
}
|
475
624
|
}
|
476
625
|
|
626
|
+
/**
|
627
|
+
* Selecting a cluster feature opens a window listing the features belonging to the cluster feature.
|
628
|
+
* To be listed the feature must meet the following criteria: a) the feature must be part of a layer, b) said layer must be managed in
|
629
|
+
* the same VcsApp as provided to the FeatureInfo on construction. if not providing a feature info view, then c) said layer must have a featureInfo property set on
|
630
|
+
* its properties bag and d) said featureInfo property must provide the name of a FeatureInfoView present on this FeatureInfos
|
631
|
+
* collection.
|
632
|
+
* The cluster feature will be cloned, highlighted and added on an internal scratch layer to ensure availability until deselection.
|
633
|
+
* The original cluster feature will be hidden until deselection.
|
634
|
+
* @param {import("ol").Feature} clusterFeature
|
635
|
+
* @returns {Promise<void>}
|
636
|
+
*/
|
637
|
+
async selectClusterFeature(clusterFeature) {
|
638
|
+
this.clearFeature();
|
639
|
+
this._clearClusterInternal();
|
640
|
+
const id = `cluster-at-${clusterFeature.getGeometry().getCoordinates().join('-')}`;
|
641
|
+
|
642
|
+
this._ensureScratchLayer();
|
643
|
+
const feature = clusterFeature.clone();
|
644
|
+
feature.setId(id);
|
645
|
+
|
646
|
+
clusterFeature[hidden] = true;
|
647
|
+
clusterFeature.changed();
|
648
|
+
|
649
|
+
const fillColor =
|
650
|
+
this._app.uiConfig.config.primaryColor ??
|
651
|
+
getDefaultPrimaryColor(this._app);
|
652
|
+
|
653
|
+
if (clusterFeature[vectorClusterGroupName]) {
|
654
|
+
const clusterGroup = this._app.vectorClusterGroups.getByKey(
|
655
|
+
clusterFeature[vectorClusterGroupName],
|
656
|
+
);
|
657
|
+
this._scratchLayer.vectorProperties.setValuesForFeatures(
|
658
|
+
clusterGroup.vectorProperties.getValuesForFeatures([feature]),
|
659
|
+
[feature],
|
660
|
+
);
|
661
|
+
const clusterStyle = clusterGroup.style.createStyleFunction((layerName) =>
|
662
|
+
this._app.layers.getByKey(layerName),
|
663
|
+
)(clusterFeature, 1);
|
664
|
+
const highlightStyle = getClusterHighlightStyle(
|
665
|
+
clusterFeature,
|
666
|
+
clusterGroup,
|
667
|
+
clusterStyle,
|
668
|
+
fillColor,
|
669
|
+
);
|
670
|
+
feature.setStyle(highlightStyle);
|
671
|
+
} else if (clusterFeature[isProvidedClusterFeature]) {
|
672
|
+
feature.setStyle(
|
673
|
+
fromCesiumColor(Color.fromCssColorString(fillColor)).style,
|
674
|
+
);
|
675
|
+
}
|
676
|
+
|
677
|
+
if (this._app.maps.activeMap instanceof ObliqueMap) {
|
678
|
+
feature.getGeometry()[alreadyTransformedToImage] = true;
|
679
|
+
}
|
680
|
+
this._scratchLayer.addFeatures([feature]);
|
681
|
+
|
682
|
+
const features = clusterFeature.get('features');
|
683
|
+
const groups = {};
|
684
|
+
const items = features.map((f) => {
|
685
|
+
const listItem = reactive({
|
686
|
+
name: f.getId(),
|
687
|
+
title: f.getAttributes()?.title || f.getAttributes()?.name || f.getId(),
|
688
|
+
disabled: !this._getFeatureInfoViewForFeature(f),
|
689
|
+
selectionChanged: (value) => {
|
690
|
+
if (value) {
|
691
|
+
this.selectFeature(f);
|
692
|
+
} else {
|
693
|
+
this.clearFeature();
|
694
|
+
}
|
695
|
+
},
|
696
|
+
});
|
697
|
+
const layerName = f[vcsLayerName];
|
698
|
+
if (layerName) {
|
699
|
+
if (!groups[layerName]) {
|
700
|
+
const title = this._app.layers.getByKey(layerName)?.properties?.title;
|
701
|
+
groups[layerName] = {
|
702
|
+
name: layerName,
|
703
|
+
title: title || layerName,
|
704
|
+
};
|
705
|
+
}
|
706
|
+
listItem.group = layerName;
|
707
|
+
}
|
708
|
+
return listItem;
|
709
|
+
});
|
710
|
+
|
711
|
+
this._clusterWindowId = id;
|
712
|
+
this._app.windowManager.add(
|
713
|
+
{
|
714
|
+
id,
|
715
|
+
component: ClusterFeatureComponent,
|
716
|
+
props: reactive({
|
717
|
+
items,
|
718
|
+
groups: Object.values(groups),
|
719
|
+
}),
|
720
|
+
state: {
|
721
|
+
headerTitle: 'featureInfo.cluster.headerTitle',
|
722
|
+
},
|
723
|
+
slot: WindowSlot.DYNAMIC_LEFT,
|
724
|
+
},
|
725
|
+
vcsAppSymbol,
|
726
|
+
);
|
727
|
+
|
728
|
+
this._selectedClusterFeature = clusterFeature;
|
729
|
+
this._selectedClusterFeatureId = id;
|
730
|
+
this._clusterFeatureChanged.raiseEvent(this._selectedClusterFeature);
|
731
|
+
}
|
732
|
+
|
477
733
|
/**
|
478
734
|
* Clears the current feature. remove window, highlighting and provided feature.
|
479
735
|
* @private
|
@@ -487,16 +743,35 @@ class FeatureInfo extends Collection {
|
|
487
743
|
this._app.windowManager.remove(this._windowId);
|
488
744
|
this._windowId = null;
|
489
745
|
}
|
746
|
+
if (this._scratchLayer && this._selectedFeatureId) {
|
747
|
+
this._scratchLayer.removeFeaturesById([this._selectedFeatureId]);
|
748
|
+
}
|
749
|
+
}
|
490
750
|
|
491
|
-
|
492
|
-
|
751
|
+
/**
|
752
|
+
* Clears the current cluster feature. remove window, highlighting and provided cluster feature.
|
753
|
+
* @private
|
754
|
+
*/
|
755
|
+
_clearClusterInternal() {
|
756
|
+
if (this._clusterWindowId) {
|
757
|
+
this._app.windowManager.remove(this._clusterWindowId);
|
758
|
+
this._clusterWindowId = null;
|
759
|
+
}
|
760
|
+
|
761
|
+
if (this._selectedClusterFeature) {
|
762
|
+
this._selectedClusterFeature[hidden] = false;
|
763
|
+
this._selectedClusterFeature.changed();
|
764
|
+
|
765
|
+
if (this._scratchLayer) {
|
766
|
+
this._scratchLayer.removeFeaturesById([this._selectedClusterFeatureId]);
|
767
|
+
}
|
493
768
|
}
|
494
769
|
}
|
495
770
|
|
496
771
|
/**
|
497
772
|
* Deselecting feature clears highlighting and closes FeatureInfoView. fires feature changed with null
|
498
773
|
*/
|
499
|
-
|
774
|
+
clearFeature() {
|
500
775
|
this._clearInternal();
|
501
776
|
if (this._selectedFeature) {
|
502
777
|
this._selectedFeature = null;
|
@@ -505,12 +780,45 @@ class FeatureInfo extends Collection {
|
|
505
780
|
}
|
506
781
|
}
|
507
782
|
|
783
|
+
/**
|
784
|
+
* Deselecting and removing cluster feature. Closing cluster window and fires cluster feature changed with null
|
785
|
+
*/
|
786
|
+
clearCluster() {
|
787
|
+
this._clearClusterInternal();
|
788
|
+
if (this._selectedClusterFeature) {
|
789
|
+
this._selectedClusterFeature[hidden] = false;
|
790
|
+
this._selectedClusterFeature = null;
|
791
|
+
this._clusterFeatureChanged.raiseEvent(this._selectedClusterFeature);
|
792
|
+
}
|
793
|
+
}
|
794
|
+
|
795
|
+
/**
|
796
|
+
* @deprecated
|
797
|
+
*/
|
798
|
+
clear() {
|
799
|
+
getLogger().deprecate(
|
800
|
+
'clear',
|
801
|
+
'Use clearSelection instead. Clear will clear the FeatureInfo collection removing all registered FeatureInfoViews in feature.',
|
802
|
+
);
|
803
|
+
this.clearSelection();
|
804
|
+
}
|
805
|
+
|
806
|
+
/**
|
807
|
+
* Clears selection by deselecting current feature and cluster and closing all related windows.
|
808
|
+
* Fires feature changed and cluster feature changed events with null.
|
809
|
+
*/
|
810
|
+
clearSelection() {
|
811
|
+
this.clearFeature();
|
812
|
+
this.clearCluster();
|
813
|
+
}
|
814
|
+
|
508
815
|
/**
|
509
816
|
* Destroys the feature info and all its events & listeners
|
510
817
|
*/
|
511
818
|
destroy() {
|
512
819
|
super.destroy();
|
513
820
|
this._clearInternal();
|
821
|
+
this._clearClusterInternal();
|
514
822
|
this._featureChanged.destroy();
|
515
823
|
this._destroyFeatureInfoTool();
|
516
824
|
if (this._scratchLayer) {
|