@vcmap/ui 6.1.0-rc.7 → 6.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/config/base.config.json +7 -3
- package/config/cluster.config.json +1 -1
- package/config/dev.config.json +172 -56
- package/config/projects.config.json +2 -1
- package/config/vectorTile.config.json +42 -1
- package/dist/assets/cesium.js +1 -1
- package/dist/assets/{core-52c2ef11.js → core-841b71a4.js} +7544 -5485
- package/dist/assets/core.js +1 -1
- package/dist/assets/ol.js +1 -1
- package/dist/assets/{ui-dccb9009.css → ui-2fd6f47d.css} +1 -1
- package/dist/assets/{ui-dccb9009.js → ui-2fd6f47d.js} +21402 -20661
- package/dist/assets/ui.js +1 -1
- package/dist/assets/vue.js +1 -1
- package/dist/assets/{vuetify-43a20e18.css → vuetify-4bc77ff7.css} +2 -2
- package/dist/assets/{vuetify-43a20e18.js → vuetify-4bc77ff7.js} +6694 -6593
- package/dist/assets/vuetify.js +1 -1
- package/index.d.ts +13 -5
- package/index.js +13 -5
- package/package.json +9 -8
- package/plugins/@vcmap-show-case/vector-properties-example/src/LayerSettings.vue +39 -0
- package/plugins/@vcmap-show-case/vector-properties-example/src/VectorPropertiesExample.vue +3 -0
- package/plugins/@vcmap-show-case/vector-properties-example/src/lib.js +13 -0
- package/plugins/@vcmap-show-case/window-tester/src/WindowExample.vue +9 -0
- package/plugins/package.json +7 -5
- package/src/actions/actionHelper.d.ts +6 -0
- package/src/actions/actionHelper.js +22 -0
- package/src/actions/deepPickingAction.d.ts +23 -0
- package/src/actions/deepPickingAction.js +399 -0
- package/src/application/VcsApp.vue +3 -0
- package/src/application/VcsApp.vue.d.ts +4 -0
- package/src/application/VcsAttributionsFooter.vue +1 -0
- package/src/application/VcsContainer.vue +1 -0
- package/src/application/VcsContainer.vue.d.ts +4 -0
- package/src/application/VcsMobileMenuList.vue +34 -41
- package/src/application/VcsNavbar.vue +3 -0
- package/src/application/VcsNavbarMobile.vue +6 -18
- package/src/application/VcsNavbarMobile.vue.d.ts +0 -1
- package/src/application/VcsPositionDisplay.vue +1 -0
- package/src/components/buttons/VcsActionButtonList.vue +1 -0
- package/src/components/form-inputs-controls/VcsSelect.vue +8 -6
- package/src/components/icons/+all.d.ts +5 -0
- package/src/components/icons/+all.js +14 -0
- package/src/components/lists/VcsActionList.vue +1 -0
- package/src/components/lists/VcsGroupedList.vue +2 -1
- package/src/components/lists/VcsListItemComponent.vue +1 -0
- package/src/components/lists/VcsTreeNode.vue +5 -1
- package/src/components/lists/VcsTreeview.vue +4 -1
- package/src/components/style/{MenuWrapper.vue → StyleMenuWrapper.vue} +2 -1
- package/src/components/style/VcsFillMenu.vue +4 -4
- package/src/components/style/VcsImageMenu.vue +4 -4
- package/src/components/style/VcsStrokeMenu.vue +4 -4
- package/src/components/style/VcsTextMenu.vue +4 -4
- package/src/contentTree/LayerTree.vue +8 -46
- package/src/contentTree/LayerTree.vue.d.ts +1 -3
- package/src/contentTree/contentTreeCollection.d.ts +7 -0
- package/src/contentTree/contentTreeCollection.js +30 -10
- package/src/contentTree/contentTreeItem.d.ts +4 -4
- package/src/contentTree/contentTreeItem.js +2 -2
- package/src/contentTree/groupContentTreeItem.d.ts +5 -0
- package/src/contentTree/groupContentTreeItem.js +1 -1
- package/src/contentTree/layerContentTreeItem.js +1 -1
- package/src/contentTree/nodeContentTreeItem.d.ts +21 -0
- package/src/contentTree/nodeContentTreeItem.js +31 -2
- package/src/contentTree/wmsChildContentTreeItem.d.ts +56 -0
- package/src/contentTree/wmsChildContentTreeItem.js +159 -0
- package/src/contentTree/wmsGroupContentTreeItem.d.ts +171 -0
- package/src/contentTree/wmsGroupContentTreeItem.js +619 -0
- package/src/featureInfo/ClusterFeatureComponent.vue +47 -11
- package/src/featureInfo/ClusterFeatureComponent.vue.d.ts +1 -0
- package/src/featureInfo/balloonFeatureInfoView.d.ts +3 -0
- package/src/featureInfo/balloonFeatureInfoView.js +78 -11
- package/src/featureInfo/balloonHelper.js +8 -12
- package/src/featureInfo/featureInfo.d.ts +32 -7
- package/src/featureInfo/featureInfo.js +190 -90
- package/src/i18n/de.d.ts +22 -16
- package/src/i18n/de.js +4 -0
- package/src/i18n/en.d.ts +22 -16
- package/src/i18n/en.js +4 -0
- package/src/manager/toolbox/GroupToolboxComponent.vue +1 -0
- package/src/manager/toolbox/SelectToolboxComponent.vue +2 -0
- package/src/manager/toolbox/ToolboxManagerComponent.vue +1 -0
- package/src/manager/window/windowManager.d.ts +2 -2
- package/src/manager/window/windowManager.js +12 -10
- package/src/navigation/MapNavigation.vue +3 -1
- package/src/notifier/NotifierComponent.vue +1 -0
- package/src/search/search.js +3 -16
- package/src/state.d.ts +2 -1
- package/src/state.js +2 -1
- package/src/uiConfig.d.ts +9 -0
- package/src/uiConfig.js +1 -0
- /package/dist/assets/{cesium-6c6aa853.js → cesium-664ad022.js} +0 -0
- /package/dist/assets/{ol-b0589b0c.js → ol-2e095c08.js} +0 -0
- /package/dist/assets/{vue-f7a0b088.js → vue-71fd14e8.js} +0 -0
- /package/src/components/style/{MenuWrapper.vue.d.ts → StyleMenuWrapper.vue.d.ts} +0 -0
@@ -0,0 +1,399 @@
|
|
1
|
+
import {
|
2
|
+
cartesianToMercator,
|
3
|
+
FeatureProviderInteraction,
|
4
|
+
getFeatureFromPickObject,
|
5
|
+
isProvidedClusterFeature,
|
6
|
+
isProvidedFeature,
|
7
|
+
markVolatile,
|
8
|
+
maxZIndex,
|
9
|
+
mercatorProjection,
|
10
|
+
mercatorToCartesian,
|
11
|
+
moduleIdSymbol,
|
12
|
+
originalFeatureSymbol,
|
13
|
+
vcsLayerName,
|
14
|
+
vectorClusterGroupName,
|
15
|
+
VectorLayer,
|
16
|
+
VectorStyleItem,
|
17
|
+
volatileModuleId,
|
18
|
+
} from '@vcmap/core';
|
19
|
+
import { Feature } from 'ol';
|
20
|
+
import { Point, LineString } from 'ol/geom.js';
|
21
|
+
import { Icon } from 'ol/style.js';
|
22
|
+
import { Cartesian3, Ray } from '@vcmap-cesium/engine';
|
23
|
+
import { watch } from 'vue';
|
24
|
+
import { getColorByKey } from '../vuePlugins/vuetify.js';
|
25
|
+
import ClusterFeatureComponent from '../featureInfo/ClusterFeatureComponent.vue';
|
26
|
+
import { WindowSlot } from '../manager/window/windowManager.js';
|
27
|
+
import { vcsAppSymbol } from '../pluginHelper.js';
|
28
|
+
import {
|
29
|
+
featureInfoViewSymbol,
|
30
|
+
getFeatureInfoViewForFeature,
|
31
|
+
getGroupedFeatureList,
|
32
|
+
} from '../featureInfo/featureInfo.js';
|
33
|
+
import { getColoredMapIcon } from '../components/icons/+all.js';
|
34
|
+
|
35
|
+
const scratchCartesian = new Cartesian3();
|
36
|
+
const pickingZOffset = 10.0;
|
37
|
+
const iconScale = 1.5;
|
38
|
+
|
39
|
+
export const deepPickingWindowId = 'deep-picking-window';
|
40
|
+
|
41
|
+
/**
|
42
|
+
* @param {import("@vcmap/ui").VcsUiApp} app
|
43
|
+
* @returns {{ layer: import("@vcmap/core").VectorLayer, destroy: () => void }}
|
44
|
+
*/
|
45
|
+
export function setupDeepPickingLayer(app) {
|
46
|
+
const layer = new VectorLayer({
|
47
|
+
zIndex: maxZIndex,
|
48
|
+
projection: mercatorProjection.toJSON(),
|
49
|
+
vectorProperties: {
|
50
|
+
altitudeMode: 'absolute',
|
51
|
+
eyeOffset: [0, 0, -200],
|
52
|
+
},
|
53
|
+
allowPicking: false,
|
54
|
+
});
|
55
|
+
markVolatile(layer);
|
56
|
+
app.layers.add(layer);
|
57
|
+
layer.activate();
|
58
|
+
|
59
|
+
const style = new VectorStyleItem({
|
60
|
+
image: {
|
61
|
+
...getColoredMapIcon(getColorByKey(app, 'primary')),
|
62
|
+
scale: iconScale,
|
63
|
+
},
|
64
|
+
fill: {
|
65
|
+
color: 'rgba(237, 237, 237, 0.1)',
|
66
|
+
},
|
67
|
+
stroke: {
|
68
|
+
color: getColorByKey(app, 'primary'),
|
69
|
+
width: 5,
|
70
|
+
},
|
71
|
+
});
|
72
|
+
layer.setStyle(style);
|
73
|
+
|
74
|
+
function setIconColor() {
|
75
|
+
const color = getColorByKey(app, 'primary');
|
76
|
+
style.stroke?.setColor(color);
|
77
|
+
style.image = new Icon({ ...getColoredMapIcon(color), scale: iconScale });
|
78
|
+
layer.forceRedraw();
|
79
|
+
}
|
80
|
+
|
81
|
+
const themChangedListener = app.themeChanged.addEventListener(setIconColor);
|
82
|
+
|
83
|
+
const destroy = () => {
|
84
|
+
layer.deactivate();
|
85
|
+
app.layers.remove(layer);
|
86
|
+
layer.destroy();
|
87
|
+
themChangedListener();
|
88
|
+
};
|
89
|
+
|
90
|
+
return { layer, destroy };
|
91
|
+
}
|
92
|
+
|
93
|
+
/**
|
94
|
+
* Retrieves features from an OpenLayers map at a given pixel.
|
95
|
+
* @param {import("ol/Map.js").OLMap} map
|
96
|
+
* @param {[number, number]} pixel
|
97
|
+
* @param {number} hitTolerance
|
98
|
+
* @param {number} drill
|
99
|
+
* @returns {import("ol").Feature[]}
|
100
|
+
*/
|
101
|
+
function getFeaturesFromOlMap(map, pixel, hitTolerance, drill) {
|
102
|
+
const features = [];
|
103
|
+
let i = 0;
|
104
|
+
map.forEachFeatureAtPixel(
|
105
|
+
pixel,
|
106
|
+
(feat) => {
|
107
|
+
if (
|
108
|
+
feat &&
|
109
|
+
(feat.get('olcs_allowPicking') == null ||
|
110
|
+
feat.get('olcs_allowPicking') === true)
|
111
|
+
) {
|
112
|
+
const feature = feat[originalFeatureSymbol] || feat;
|
113
|
+
if (!feature[vectorClusterGroupName]) {
|
114
|
+
features.push(feature);
|
115
|
+
}
|
116
|
+
}
|
117
|
+
i += 1;
|
118
|
+
return i >= drill;
|
119
|
+
},
|
120
|
+
{ hitTolerance },
|
121
|
+
);
|
122
|
+
|
123
|
+
return features;
|
124
|
+
}
|
125
|
+
|
126
|
+
/**
|
127
|
+
* Retrieves features from a Cesium scene at a given window position.
|
128
|
+
* @param {import("@vcmap-cesium/engine").Scene} scene
|
129
|
+
* @param {import("@vcmap-cesium/engine").Ray} ray
|
130
|
+
* @param {number} hitTolerance
|
131
|
+
* @param {number} drill
|
132
|
+
* @returns {Promise<{ features: import("@vcmap/core").EventFeature[], minZ: number }>}
|
133
|
+
*/
|
134
|
+
async function getFeaturesFromScene(scene, ray, hitTolerance, drill) {
|
135
|
+
const { depthTestAgainstTerrain } = scene.globe;
|
136
|
+
scene.globe.depthTestAgainstTerrain = false;
|
137
|
+
|
138
|
+
let minZ = 0;
|
139
|
+
const objects = await scene.drillPickFromRay(
|
140
|
+
ray,
|
141
|
+
drill,
|
142
|
+
undefined,
|
143
|
+
hitTolerance,
|
144
|
+
);
|
145
|
+
|
146
|
+
scene.globe.depthTestAgainstTerrain = depthTestAgainstTerrain;
|
147
|
+
|
148
|
+
const features = objects
|
149
|
+
.map(({ object, position }) => {
|
150
|
+
let feature;
|
151
|
+
if (object) {
|
152
|
+
if (position) {
|
153
|
+
const z = cartesianToMercator(position)[2];
|
154
|
+
minZ = Math.min(minZ, z);
|
155
|
+
}
|
156
|
+
feature = getFeatureFromPickObject(object);
|
157
|
+
if (feature?.[vectorClusterGroupName]) {
|
158
|
+
const clusterFeatures = feature.get('features');
|
159
|
+
return [...clusterFeatures];
|
160
|
+
}
|
161
|
+
}
|
162
|
+
return feature;
|
163
|
+
})
|
164
|
+
.filter((f, i, a) => !!f && a.indexOf(f) === i);
|
165
|
+
return { features, minZ };
|
166
|
+
}
|
167
|
+
|
168
|
+
/**
|
169
|
+
* @param {import("@vcmap/core").InteractionEvent} event
|
170
|
+
* @param {number} [hitTolerance=10]
|
171
|
+
* @param {number} [drillLimit]
|
172
|
+
* @returns {Promise<{ features: import("@vcmap/core").EventFeature[], minZ: number }>}
|
173
|
+
*/
|
174
|
+
async function getDeepPickingFeatures(
|
175
|
+
event,
|
176
|
+
hitTolerance = 10,
|
177
|
+
drillLimit = undefined,
|
178
|
+
) {
|
179
|
+
let features = [];
|
180
|
+
let minZ = 0;
|
181
|
+
if (
|
182
|
+
event.map.className === 'OpenlayersMap' ||
|
183
|
+
event.map.className === 'ObliqueMap'
|
184
|
+
) {
|
185
|
+
features = getFeaturesFromOlMap(
|
186
|
+
event.map.olMap,
|
187
|
+
[event.windowPosition.x, event.windowPosition.y],
|
188
|
+
hitTolerance,
|
189
|
+
drillLimit,
|
190
|
+
);
|
191
|
+
} else if (event.map.className === 'CesiumMap') {
|
192
|
+
const cesiumMap = event.map;
|
193
|
+
const scene = cesiumMap.getScene();
|
194
|
+
|
195
|
+
if (!scene) {
|
196
|
+
return features;
|
197
|
+
}
|
198
|
+
|
199
|
+
const [x, y, z] = event.position;
|
200
|
+
const origin = mercatorToCartesian([
|
201
|
+
x,
|
202
|
+
y,
|
203
|
+
Number.isNaN(z) ? pickingZOffset : z + pickingZOffset,
|
204
|
+
]);
|
205
|
+
const direction = Cartesian3.normalize(
|
206
|
+
Cartesian3.negate(origin, scratchCartesian),
|
207
|
+
scratchCartesian,
|
208
|
+
);
|
209
|
+
const ray = new Ray(origin, direction);
|
210
|
+
|
211
|
+
({ features, minZ } = await getFeaturesFromScene(
|
212
|
+
scene,
|
213
|
+
ray,
|
214
|
+
hitTolerance,
|
215
|
+
drillLimit,
|
216
|
+
));
|
217
|
+
}
|
218
|
+
|
219
|
+
if (
|
220
|
+
event.feature &&
|
221
|
+
!event.feature[isProvidedFeature] && // provided features will be provided again.
|
222
|
+
!features.includes(event.feature)
|
223
|
+
) {
|
224
|
+
features.unshift(event.feature);
|
225
|
+
}
|
226
|
+
|
227
|
+
return { features, minZ };
|
228
|
+
}
|
229
|
+
|
230
|
+
/**
|
231
|
+
* @param {import("@vcmap/core").AbstractInteraction} interaction
|
232
|
+
* @param {import("@vcmap/core").InteractionEvent} event
|
233
|
+
* @returns {Promise<import("@vcmap/core").EventFeature[]>}
|
234
|
+
*/
|
235
|
+
async function getInteractionFeatures(interaction, event) {
|
236
|
+
const pipedEvent = await interaction.pipe({
|
237
|
+
...event,
|
238
|
+
feature: undefined,
|
239
|
+
});
|
240
|
+
const { feature } = pipedEvent;
|
241
|
+
if (feature) {
|
242
|
+
if (feature[isProvidedClusterFeature]) {
|
243
|
+
return feature.get('features');
|
244
|
+
}
|
245
|
+
return [feature];
|
246
|
+
}
|
247
|
+
return [];
|
248
|
+
}
|
249
|
+
|
250
|
+
/**
|
251
|
+
* @returns {{ collectFeatures: (event: import("@vcmap/core").InteractionEvent) => Promise<{ features: import("@vcmap/core").EventFeature[], minZ: number }>, destroy: () => void}}
|
252
|
+
*/
|
253
|
+
function createCollectFeatures() {
|
254
|
+
const featureProviderInteraction = new FeatureProviderInteraction();
|
255
|
+
return {
|
256
|
+
async collectFeatures(event) {
|
257
|
+
const { features: deepPickingFeatures, minZ } =
|
258
|
+
await getDeepPickingFeatures(event);
|
259
|
+
return {
|
260
|
+
features: [
|
261
|
+
...deepPickingFeatures,
|
262
|
+
...(await getInteractionFeatures(featureProviderInteraction, event)),
|
263
|
+
],
|
264
|
+
minZ,
|
265
|
+
};
|
266
|
+
},
|
267
|
+
destroy() {
|
268
|
+
featureProviderInteraction.destroy();
|
269
|
+
},
|
270
|
+
};
|
271
|
+
}
|
272
|
+
|
273
|
+
/**
|
274
|
+
* @param {import("../vcsUiApp.js").default} app
|
275
|
+
* @param {import("ol/Feature").default} f
|
276
|
+
* @returns {boolean}
|
277
|
+
*/
|
278
|
+
function featurePredicate(app, f) {
|
279
|
+
if (f[featureInfoViewSymbol]) {
|
280
|
+
return true;
|
281
|
+
}
|
282
|
+
|
283
|
+
const l = app.layers.getByKey(f[vcsLayerName]);
|
284
|
+
if (l?.[moduleIdSymbol] === volatileModuleId) {
|
285
|
+
return !!getFeatureInfoViewForFeature(app, f);
|
286
|
+
}
|
287
|
+
|
288
|
+
return !!l;
|
289
|
+
}
|
290
|
+
|
291
|
+
/**
|
292
|
+
* @param {import("../vcsUiApp.js").default} app
|
293
|
+
* @param {import("@vcmap/core").VectorLayer} layer
|
294
|
+
* @param {(event: import("@vcmap/core").InteractionEvent) => Promise<import("@vcmap/core").EventFeature[]>} collectFeatures
|
295
|
+
* @param {import("@vcmap/core").InteractionEvent} event
|
296
|
+
* @returns {import("./actionHelper.js").VcsAction}
|
297
|
+
*/
|
298
|
+
export function createDeepPickingAction(app, layer, collectFeatures, event) {
|
299
|
+
return {
|
300
|
+
name: 'featureInfo.deepPicking.title',
|
301
|
+
icon: '$vcsInfo',
|
302
|
+
async callback() {
|
303
|
+
const { features, minZ } = await collectFeatures(event);
|
304
|
+
const { items, groups } = getGroupedFeatureList(
|
305
|
+
app,
|
306
|
+
features.filter((f) => featurePredicate(app, f)),
|
307
|
+
event.position,
|
308
|
+
);
|
309
|
+
|
310
|
+
if (app.windowManager.has(deepPickingWindowId)) {
|
311
|
+
app.windowManager.remove(deepPickingWindowId);
|
312
|
+
}
|
313
|
+
|
314
|
+
app.windowManager.add(
|
315
|
+
{
|
316
|
+
id: deepPickingWindowId,
|
317
|
+
component: ClusterFeatureComponent,
|
318
|
+
props: {
|
319
|
+
items,
|
320
|
+
groups,
|
321
|
+
},
|
322
|
+
state: {
|
323
|
+
headerTitle: 'featureInfo.deepPicking.headerTitle',
|
324
|
+
headerIcon: '$vcsInfo',
|
325
|
+
},
|
326
|
+
slot: WindowSlot.DYNAMIC_LEFT,
|
327
|
+
},
|
328
|
+
vcsAppSymbol,
|
329
|
+
);
|
330
|
+
|
331
|
+
const windowListener = app.windowManager.removed.addEventListener(
|
332
|
+
({ id: windowId }) => {
|
333
|
+
if (windowId === deepPickingWindowId) {
|
334
|
+
layer.removeAllFeatures();
|
335
|
+
windowListener();
|
336
|
+
}
|
337
|
+
},
|
338
|
+
);
|
339
|
+
|
340
|
+
const [x, y, z] = event.position;
|
341
|
+
const coordinate = [
|
342
|
+
x,
|
343
|
+
y,
|
344
|
+
Number.isNaN(z) ? pickingZOffset : z + pickingZOffset,
|
345
|
+
];
|
346
|
+
const pickFeature = new Feature({
|
347
|
+
geometry: new Point(coordinate),
|
348
|
+
});
|
349
|
+
const rayFeature = new Feature({
|
350
|
+
geometry: new LineString([coordinate, [x, y, minZ]]),
|
351
|
+
});
|
352
|
+
layer.addFeatures([pickFeature, rayFeature]);
|
353
|
+
},
|
354
|
+
};
|
355
|
+
}
|
356
|
+
|
357
|
+
/**
|
358
|
+
* This adds deep picking action to the context menu, if not disabled in uiConfig
|
359
|
+
* @param {import("../vcsUiApp.js").default} app
|
360
|
+
* @returns {() => void}
|
361
|
+
*/
|
362
|
+
export function setupDeepPicking(app) {
|
363
|
+
const { layer, destroy: destroyLayer } = setupDeepPickingLayer(app);
|
364
|
+
const { collectFeatures, destroy: destroyCollectFeatures } =
|
365
|
+
createCollectFeatures();
|
366
|
+
|
367
|
+
const handler = async (event) => {
|
368
|
+
if (event.windowPosition) {
|
369
|
+
return [createDeepPickingAction(app, layer, collectFeatures, event)];
|
370
|
+
}
|
371
|
+
return [];
|
372
|
+
};
|
373
|
+
|
374
|
+
if (app.uiConfig.enableDeepPicking !== false) {
|
375
|
+
app.contextMenuManager.addEventHandler(handler, vcsAppSymbol);
|
376
|
+
}
|
377
|
+
|
378
|
+
const stopWatching = watch(
|
379
|
+
() => app.uiConfig.config.enableDeepPicking,
|
380
|
+
(value, oldValue) => {
|
381
|
+
if (value !== false) {
|
382
|
+
if (!(oldValue !== false)) {
|
383
|
+
app.contextMenuManager.addEventHandler(handler, vcsAppSymbol);
|
384
|
+
}
|
385
|
+
} else {
|
386
|
+
app.contextMenuManager.removeHandler(handler);
|
387
|
+
}
|
388
|
+
},
|
389
|
+
);
|
390
|
+
|
391
|
+
return () => {
|
392
|
+
stopWatching();
|
393
|
+
destroyLayer();
|
394
|
+
destroyCollectFeatures();
|
395
|
+
layer.deactivate();
|
396
|
+
layer.destroy();
|
397
|
+
app.layers.remove(layer);
|
398
|
+
};
|
399
|
+
}
|
@@ -79,6 +79,7 @@
|
|
79
79
|
createMapButtonAction,
|
80
80
|
createToggleAction,
|
81
81
|
} from '../actions/actionHelper.js';
|
82
|
+
import { setupDeepPicking } from '../actions/deepPickingAction.js';
|
82
83
|
import VcsSettings from './VcsSettings.vue';
|
83
84
|
import { WindowSlot } from '../manager/window/windowManager.js';
|
84
85
|
import CollectionManager from '../manager/collectionManager/CollectionManager.vue';
|
@@ -814,6 +815,7 @@
|
|
814
815
|
const destroyDisplayQualityListener = setupUiConfigDisplayQuality(app);
|
815
816
|
const { attributionEntries, attributionAction, destroyAttributions } =
|
816
817
|
setupAttributions(app);
|
818
|
+
const destroyDeepPicking = setupDeepPicking(app);
|
817
819
|
|
818
820
|
let pluginMountedListener;
|
819
821
|
onMounted(() => {
|
@@ -853,6 +855,7 @@
|
|
853
855
|
destroyThemingListener();
|
854
856
|
destroyDisplayQualityListener();
|
855
857
|
destroyAttributions();
|
858
|
+
destroyDeepPicking();
|
856
859
|
});
|
857
860
|
|
858
861
|
const { smAndUp, xs } = useDisplay();
|
@@ -112,6 +112,10 @@ declare const _default: import("vue").DefineComponent<{
|
|
112
112
|
* - an optional flag whether to activate feature info on startup (default active)
|
113
113
|
*/
|
114
114
|
readonly startingFeatureInfo?: boolean | undefined;
|
115
|
+
/**
|
116
|
+
* - an optional flag whether to enable deep picking via right click context menu (default active)
|
117
|
+
*/
|
118
|
+
readonly enableDeepPicking?: boolean | undefined;
|
115
119
|
/**
|
116
120
|
* - mouse event, when position display is updated. Either 'click' (default) or 'move'.
|
117
121
|
*/
|
@@ -26,6 +26,10 @@ declare const _default: import("vue").DefineComponent<{
|
|
26
26
|
* - an optional flag whether to activate feature info on startup (default active)
|
27
27
|
*/
|
28
28
|
readonly startingFeatureInfo?: boolean | undefined;
|
29
|
+
/**
|
30
|
+
* - an optional flag whether to enable deep picking via right click context menu (default active)
|
31
|
+
*/
|
32
|
+
readonly enableDeepPicking?: boolean | undefined;
|
29
33
|
/**
|
30
34
|
* - mouse event, when position display is updated. Either 'click' (default) or 'move'.
|
31
35
|
*/
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<script setup>
|
2
|
-
import {
|
2
|
+
import { inject } from 'vue';
|
3
3
|
import { VDivider, VList, VListItem } from 'vuetify/components';
|
4
4
|
import {
|
5
5
|
ButtonLocation,
|
@@ -9,56 +9,48 @@
|
|
9
9
|
import VcsTextPageFooter from './VcsTextPageFooter.vue';
|
10
10
|
import { getDataProtection, getImprint } from './uiConfigHelper.js';
|
11
11
|
import { toolboxComponentId } from '../manager/toolbox/ToolboxManagerComponent.vue';
|
12
|
-
import { defaultContentTreeComponentId } from '../contentTree/contentTreeCollection.js';
|
13
|
-
import { legendComponentId } from './VcsApp.vue';
|
14
12
|
|
15
13
|
const app = inject('vcsApp');
|
16
14
|
|
17
|
-
const mobileButtonComponents =
|
18
|
-
app.navbarManager.
|
19
|
-
|
20
|
-
.
|
21
|
-
|
22
|
-
}),
|
23
|
-
);
|
24
|
-
|
25
|
-
const getActions = (location) =>
|
26
|
-
computed(() =>
|
27
|
-
getActionsByLocation(
|
28
|
-
mobileButtonComponents.value,
|
29
|
-
location,
|
30
|
-
[...app.plugins].map((p) => p.name),
|
31
|
-
),
|
32
|
-
);
|
15
|
+
const mobileButtonComponents = app.navbarManager.componentIds
|
16
|
+
.map((id) => app.navbarManager.get(id))
|
17
|
+
.filter((buttonComponent) => {
|
18
|
+
return buttonComponent[deviceSymbol].mobile;
|
19
|
+
});
|
33
20
|
|
34
21
|
// Actions from the content overflow are put in Menu
|
35
|
-
const
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
const contentOverflowActions = computed(() => {
|
41
|
-
return getActions(ButtonLocation.CONTENT).value.filter(
|
42
|
-
(action) =>
|
43
|
-
action.name !== defaultContentTreeComponentIdAction.name &&
|
44
|
-
action.name !== legendComponentIdAction.name,
|
45
|
-
);
|
46
|
-
});
|
22
|
+
const contentOverflowActions = getActionsByLocation(
|
23
|
+
mobileButtonComponents,
|
24
|
+
ButtonLocation.CONTENT,
|
25
|
+
[...app.plugins].map((p) => p.name),
|
26
|
+
)?.slice(2);
|
47
27
|
|
48
28
|
const toolboxToggleAction = app.navbarManager.get(toolboxComponentId).action;
|
49
29
|
|
50
|
-
const toolboxOverflowActions =
|
51
|
-
|
52
|
-
|
53
|
-
),
|
54
|
-
);
|
30
|
+
const toolboxOverflowActions = getActionsByLocation(
|
31
|
+
mobileButtonComponents,
|
32
|
+
ButtonLocation.TOOL,
|
33
|
+
[...app.plugins].map((p) => p.name),
|
34
|
+
)?.filter((action) => action.name !== toolboxToggleAction.name);
|
55
35
|
|
56
36
|
const mobileMenuActions = [
|
57
|
-
...
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
37
|
+
...getActionsByLocation(
|
38
|
+
mobileButtonComponents,
|
39
|
+
ButtonLocation.MENU,
|
40
|
+
[...app.plugins].map((p) => p.name),
|
41
|
+
),
|
42
|
+
...getActionsByLocation(
|
43
|
+
mobileButtonComponents,
|
44
|
+
ButtonLocation.SHARE,
|
45
|
+
[...app.plugins].map((p) => p.name),
|
46
|
+
),
|
47
|
+
...getActionsByLocation(
|
48
|
+
mobileButtonComponents,
|
49
|
+
ButtonLocation.PROJECT,
|
50
|
+
[...app.plugins].map((p) => p.name),
|
51
|
+
),
|
52
|
+
...toolboxOverflowActions,
|
53
|
+
...contentOverflowActions,
|
62
54
|
];
|
63
55
|
|
64
56
|
const dataProtection = getDataProtection(app.uiConfig?.config);
|
@@ -70,6 +62,7 @@
|
|
70
62
|
<div v-for="action in mobileMenuActions" :key="action.name">
|
71
63
|
<v-list-item
|
72
64
|
@click="action.callback()"
|
65
|
+
:data-action-name="action.name"
|
73
66
|
:title="$t(action.name)"
|
74
67
|
:prepend-icon="action.icon"
|
75
68
|
>
|
@@ -85,6 +85,7 @@
|
|
85
85
|
v-bind="props"
|
86
86
|
tooltip="navbar.share.tooltip"
|
87
87
|
icon="$vcsShare"
|
88
|
+
id="vcs-navbar-share-menu-activator"
|
88
89
|
/>
|
89
90
|
</template>
|
90
91
|
<VcsActionList
|
@@ -96,6 +97,7 @@
|
|
96
97
|
<VcsToolButton
|
97
98
|
class="d-flex"
|
98
99
|
v-if="searchAction"
|
100
|
+
:data-action-name="searchAction.name"
|
99
101
|
:key="searchAction.name"
|
100
102
|
:tooltip="searchAction.title"
|
101
103
|
:icon="searchAction.icon"
|
@@ -108,6 +110,7 @@
|
|
108
110
|
<VcsToolButton
|
109
111
|
v-bind="props"
|
110
112
|
tooltip="navbar.menu.tooltip"
|
113
|
+
id="vcs-navbar-burger-menu-activator"
|
111
114
|
icon="$vcsMenu"
|
112
115
|
/>
|
113
116
|
</template>
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<template>
|
2
2
|
<v-toolbar
|
3
3
|
absolute
|
4
|
-
|
4
|
+
density="comfortable"
|
5
5
|
elevation="0"
|
6
6
|
class="px-4 vcs-navbar-mobile"
|
7
7
|
:height="toolbarHeight"
|
@@ -14,6 +14,7 @@
|
|
14
14
|
<VcsToolButton
|
15
15
|
v-if="mobileMenuAction"
|
16
16
|
:key="mobileMenuAction.name"
|
17
|
+
:data-action-name="mobileMenuAction.name"
|
17
18
|
:tooltip="mobileMenuAction.title"
|
18
19
|
:icon="mobileMenuAction.icon"
|
19
20
|
:active="mobileMenuAction.active"
|
@@ -22,6 +23,7 @@
|
|
22
23
|
/>
|
23
24
|
<VcsToolButton
|
24
25
|
v-if="searchAction"
|
26
|
+
:data-action-name="searchAction.name"
|
25
27
|
:key="searchAction.name"
|
26
28
|
:tooltip="searchAction.title"
|
27
29
|
:icon="searchAction.icon"
|
@@ -76,7 +78,7 @@
|
|
76
78
|
</style>
|
77
79
|
|
78
80
|
<script>
|
79
|
-
import {
|
81
|
+
import { computed, inject, onUnmounted, shallowRef } from 'vue';
|
80
82
|
import {
|
81
83
|
VCol,
|
82
84
|
VContainer,
|
@@ -100,8 +102,6 @@
|
|
100
102
|
import { WindowSlot } from '../manager/window/windowManager.js';
|
101
103
|
import MapsGroupMobileMenu from './MapsGroupMobileMenu.vue';
|
102
104
|
import { toolboxComponentId } from '../manager/toolbox/ToolboxManagerComponent.vue';
|
103
|
-
import { defaultContentTreeComponentId } from '../contentTree/contentTreeCollection.js';
|
104
|
-
import { legendComponentId } from './VcsApp.vue';
|
105
105
|
|
106
106
|
export const mobileMenuListId = 'mobileMenuList';
|
107
107
|
|
@@ -148,10 +148,6 @@
|
|
148
148
|
destroySearchAction();
|
149
149
|
});
|
150
150
|
|
151
|
-
const density = computed(() => {
|
152
|
-
return 'comfortable';
|
153
|
-
});
|
154
|
-
|
155
151
|
const fontSize = useFontSize();
|
156
152
|
const toolbarHeight = computed(() => {
|
157
153
|
return fontSize.value * 3 + 1;
|
@@ -178,16 +174,9 @@
|
|
178
174
|
vcsAppSymbol,
|
179
175
|
);
|
180
176
|
|
181
|
-
// only show the
|
177
|
+
// only show the first two actions, rest handled in VcsMobileMenuList
|
182
178
|
const contentActions = computed(() => {
|
183
|
-
return getActions(ButtonLocation.CONTENT)
|
184
|
-
(action) =>
|
185
|
-
action.name ===
|
186
|
-
app.navbarManager.get(defaultContentTreeComponentId).action
|
187
|
-
.name ||
|
188
|
-
action.name ===
|
189
|
-
app.navbarManager.get(legendComponentId).action.name,
|
190
|
-
);
|
179
|
+
return getActions(ButtonLocation.CONTENT)?.value?.slice(0, 2);
|
191
180
|
});
|
192
181
|
|
193
182
|
const toolboxToggleAction = shallowRef(
|
@@ -210,7 +199,6 @@
|
|
210
199
|
contentActions,
|
211
200
|
toolboxToggleAction,
|
212
201
|
searchAction,
|
213
|
-
density,
|
214
202
|
toolbarHeight,
|
215
203
|
};
|
216
204
|
},
|
@@ -37,7 +37,6 @@ declare const _default: import("vue").DefineComponent<{}, {
|
|
37
37
|
*/
|
38
38
|
disabled?: boolean | undefined;
|
39
39
|
} | null>;
|
40
|
-
density: import("vue").ComputedRef<string>;
|
41
40
|
toolbarHeight: import("vue").ComputedRef<number>;
|
42
41
|
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{}>>, {}, {}>;
|
43
42
|
export default _default;
|