@vcmap/core 5.0.0-rc.27 → 5.0.0-rc.28

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 (37) hide show
  1. package/index.d.ts +273 -125
  2. package/index.js +6 -4
  3. package/package.json +1 -1
  4. package/src/category/category.js +16 -16
  5. package/src/category/categoryCollection.js +13 -13
  6. package/src/interaction/eventHandler.js +4 -4
  7. package/src/layer/featureVisibility.js +3 -4
  8. package/src/layer/globalHider.js +1 -1
  9. package/src/layer/layer.js +2 -1
  10. package/src/layer/vectorLayer.js +7 -0
  11. package/src/oblique/helpers.js +7 -9
  12. package/src/ol/feature.js +28 -0
  13. package/src/overrideClassRegistry.js +17 -17
  14. package/src/style/declarativeStyleItem.js +2 -3
  15. package/src/util/editor/editFeaturesSession.js +150 -166
  16. package/src/util/editor/editGeometrySession.js +69 -47
  17. package/src/util/editor/editorHelpers.js +3 -1
  18. package/src/util/editor/editorSessionHelpers.js +11 -3
  19. package/src/util/editor/editorSymbols.js +5 -0
  20. package/src/util/editor/interactions/editFeaturesMouseOverInteraction.js +15 -49
  21. package/src/util/editor/interactions/editGeometryMouseOverInteraction.js +16 -33
  22. package/src/util/editor/interactions/ensureHandlerSelectionInteraction.js +5 -5
  23. package/src/util/editor/interactions/selectFeatureMouseOverInteraction.js +143 -0
  24. package/src/util/editor/interactions/selectMultiFeatureInteraction.js +17 -11
  25. package/src/util/editor/interactions/selectSingleFeatureInteraction.js +27 -8
  26. package/src/util/editor/interactions/translateVertexInteraction.js +2 -3
  27. package/src/util/editor/selectFeaturesSession.js +287 -0
  28. package/src/util/editor/transformation/transformationHandler.js +4 -9
  29. package/src/util/editor/transformation/transformationTypes.js +1 -0
  30. package/src/util/featureconverter/convert.js +1 -1
  31. package/src/util/indexedCollection.js +19 -3
  32. package/src/util/layerCollection.js +4 -2
  33. package/src/util/overrideCollection.js +20 -20
  34. package/src/vcsApp.js +107 -85
  35. package/src/vcsModule.js +129 -0
  36. package/src/{vcsAppContextHelpers.js → vcsModuleHelpers.js} +5 -5
  37. package/src/context.js +0 -89
@@ -1,6 +1,6 @@
1
1
  import { getLogger } from '@vcsuite/logger';
2
+ import { unByKey } from 'ol/Observable.js';
2
3
  import { GeometryType, SessionType, setupInteractionChain, setupScratchLayer } from './editorSessionHelpers.js';
3
- import SelectSingleFeatureInteraction from './interactions/selectSingleFeatureInteraction.js';
4
4
  import InteractionChain from '../../interaction/interactionChain.js';
5
5
  import VcsEvent from '../../vcsEvent.js';
6
6
  import TranslateVertexInteraction from './interactions/translateVertexInteraction.js';
@@ -11,14 +11,12 @@ import EditGeometryMouseOverInteraction from './interactions/editGeometryMouseOv
11
11
  import { cartesian2DDistance, modulo } from '../math.js';
12
12
  import { createSync, obliqueGeometry } from '../../layer/vectorSymbols.js';
13
13
  import geometryIsValid from './validateGeoemetry.js';
14
- import ObliqueMap from '../../map/obliqueMap.js';
15
- import { emptyStyle } from '../../style/styleHelpers.js';
16
14
  import MapInteractionController from './interactions/mapInteractionController.js';
17
- import { originalStyle } from '../../layer/featureVisibility.js';
18
15
 
19
16
  /**
20
17
  * @typedef {EditorSession} EditGeometrySession
21
- * @property {SelectSingleFeatureInteraction} featureSelection - the feature selection for this session.
18
+ * @property {function(import("ol").Feature):void} setFeature - Sets the feature for the edit session.
19
+ * @property {import("ol").Feature | null} feature - Gets the current feature of the edit session.
22
20
  */
23
21
 
24
22
  /**
@@ -82,12 +80,15 @@ function createEditLineStringGeometryInteraction(feature, scratchLayer) {
82
80
  * @returns {EditGeometryInteraction}
83
81
  */
84
82
  function createEditCircleGeometryInteraction(feature, scratchLayer) {
83
+ /** @type {import("ol/geom").Circle} */
85
84
  const geometry = feature[obliqueGeometry] ?? feature.getGeometry();
86
85
  const vertices = geometry.getCoordinates().map(createVertex);
87
86
  scratchLayer.addFeatures(vertices);
88
87
 
89
88
  const translateVertex = new TranslateVertexInteraction();
89
+ let suspend;
90
90
  translateVertex.vertexChanged.addEventListener((vertex) => {
91
+ suspend = true;
91
92
  if (vertices.indexOf(vertex) === 1) {
92
93
  const coords = geometry.getCoordinates();
93
94
  coords[1] = vertex.getGeometry().getCoordinates();
@@ -97,6 +98,16 @@ function createEditCircleGeometryInteraction(feature, scratchLayer) {
97
98
  geometry.setCenter(vertex.getGeometry().getCoordinates());
98
99
  vertices[1].getGeometry().setCoordinates(geometry.getCoordinates()[1]);
99
100
  }
101
+ suspend = false;
102
+ });
103
+
104
+ const geometryListener = geometry.on('change', () => {
105
+ if (!suspend) {
106
+ geometry.getCoordinates()
107
+ .forEach((c, index) => {
108
+ vertices[index].getGeometry().setCoordinates(c);
109
+ });
110
+ }
100
111
  });
101
112
 
102
113
  const interactionChain = new InteractionChain([translateVertex]);
@@ -106,6 +117,7 @@ function createEditCircleGeometryInteraction(feature, scratchLayer) {
106
117
  destroy: () => {
107
118
  scratchLayer.removeFeaturesById(vertices.map(v => v.getId()));
108
119
  interactionChain.destroy();
120
+ unByKey(geometryListener);
109
121
  },
110
122
  };
111
123
  }
@@ -119,7 +131,7 @@ function createEditBBoxGeometryInteraction(feature, scratchLayer) {
119
131
  const geometry = feature[obliqueGeometry] ?? feature.getGeometry();
120
132
  const vertices = geometry.getCoordinates()[0].map(createVertex);
121
133
  scratchLayer.addFeatures(vertices);
122
-
134
+ let suspend = false;
123
135
  const translateVertex = new TranslateVertexInteraction();
124
136
  translateVertex.vertexChanged.addEventListener((vertex) => {
125
137
  const vertexIndex = vertices.indexOf(vertex);
@@ -156,9 +168,19 @@ function createEditBBoxGeometryInteraction(feature, scratchLayer) {
156
168
  updateOtherVertex(rightOfIndex);
157
169
  updateOtherVertex(leftOfIndex);
158
170
 
171
+ suspend = true;
159
172
  geometry.setCoordinates([vertices.map(f => f.getGeometry().getCoordinates())]);
173
+ suspend = false;
160
174
  });
161
175
 
176
+ const geometryListener = geometry.on('change', () => {
177
+ if (!suspend) {
178
+ geometry.getCoordinates()[0]
179
+ .forEach((c, index) => {
180
+ vertices[index].getGeometry().setCoordinates(c);
181
+ });
182
+ }
183
+ });
162
184
  const interactionChain = new InteractionChain([translateVertex]);
163
185
 
164
186
  return {
@@ -166,6 +188,7 @@ function createEditBBoxGeometryInteraction(feature, scratchLayer) {
166
188
  destroy: () => {
167
189
  scratchLayer.removeFeaturesById(vertices.map(v => v.getId()));
168
190
  interactionChain.destroy();
191
+ unByKey(geometryListener);
169
192
  },
170
193
  };
171
194
  }
@@ -224,17 +247,28 @@ function createEditSimplePolygonInteraction(feature, scratchLayer) {
224
247
  /**
225
248
  * @param {import("ol").Feature<import("ol/geom").Point>} feature
226
249
  * @param {import("@vcmap/core").VectorLayer} scratchLayer
250
+ * @param {import("@vcmap/core").VectorLayer} layer
227
251
  * @returns {EditGeometryInteraction}
228
252
  */
229
- function createEditPointInteraction(feature, scratchLayer) {
230
- const vertex = createVertex(feature.getGeometry().getCoordinates());
231
- const featureStyle = feature.getStyle();
232
- feature[originalStyle] = featureStyle;
233
- feature.setStyle(emptyStyle);
253
+ function createEditPointInteraction(feature, scratchLayer, layer) {
254
+ const geometry = feature[obliqueGeometry] ?? feature.getGeometry();
255
+ const vertex = createVertex(geometry.getCoordinates());
256
+ const featureIdArray = [feature.getId()];
257
+ layer.featureVisibility.hideObjects(featureIdArray);
258
+ vertex[createSync] = true;
234
259
  scratchLayer.addFeatures([vertex]);
235
260
  const translateVertex = new TranslateVertexInteraction();
261
+ let suspend = false;
236
262
  translateVertex.vertexChanged.addEventListener(() => {
263
+ suspend = true;
237
264
  feature.getGeometry().setCoordinates(vertex.getGeometry().getCoordinates());
265
+ suspend = false;
266
+ });
267
+
268
+ const geometryListener = geometry.on('change', () => {
269
+ if (!suspend) {
270
+ vertex.getGeometry().setCoordinates(geometry.getCoordinates());
271
+ }
238
272
  });
239
273
 
240
274
  const interactionChain = new InteractionChain([
@@ -246,7 +280,8 @@ function createEditPointInteraction(feature, scratchLayer) {
246
280
  destroy: () => {
247
281
  interactionChain.destroy();
248
282
  scratchLayer.removeFeaturesById([vertex.getId()]);
249
- feature.setStyle(featureStyle);
283
+ layer.featureVisibility.showObjects(featureIdArray);
284
+ unByKey(geometryListener);
250
285
  },
251
286
  };
252
287
  }
@@ -255,24 +290,22 @@ function createEditPointInteraction(feature, scratchLayer) {
255
290
  * Creates the edit geometry session.
256
291
  * @param {import("@vcmap/core").VcsApp} app
257
292
  * @param {import("@vcmap/core").VectorLayer} layer
293
+ * @param {string} [interactionId] id for registering mutliple exclusive interaction. Needed to run a selection session at the same time as a edit features session.
258
294
  * @returns {EditGeometrySession}
259
295
  */
260
- function startEditGeometrySession(app, layer) {
296
+ function startEditGeometrySession(app, layer, interactionId) {
261
297
  const {
262
298
  interactionChain,
263
299
  removed: interactionRemoved,
264
300
  destroy: destroyInteractionChain,
265
- } = setupInteractionChain(app.maps.eventHandler);
301
+ } = setupInteractionChain(app.maps.eventHandler, interactionId);
266
302
 
267
303
  const scratchLayer = setupScratchLayer(app.layers);
268
304
 
269
- const selectFeatureInteraction = new SelectSingleFeatureInteraction(layer);
270
- interactionChain.addInteraction(selectFeatureInteraction);
271
-
272
305
  const mapInteractionController = new MapInteractionController();
273
306
  interactionChain.addInteraction(mapInteractionController);
274
307
 
275
- const mouseOverInteraction = new EditGeometryMouseOverInteraction(layer.name);
308
+ const mouseOverInteraction = new EditGeometryMouseOverInteraction();
276
309
  interactionChain.addInteraction(mouseOverInteraction);
277
310
 
278
311
  /**
@@ -284,11 +317,12 @@ function startEditGeometrySession(app, layer) {
284
317
  * @type {EditGeometryInteraction|null}
285
318
  */
286
319
  let currentInteractionSet = null;
287
- let currentFeature = null;
288
320
  /**
289
- * @type {ObliqueMap|null}
321
+ * The feature that is set for the edit session.
322
+ * @type {import("ol").Feature}
290
323
  */
291
- let obliqueMap = null;
324
+ let currentFeature = null;
325
+
292
326
 
293
327
  const destroyCurrentInteractionSet = () => {
294
328
  if (currentInteractionSet) {
@@ -304,18 +338,15 @@ function startEditGeometrySession(app, layer) {
304
338
  }
305
339
  }
306
340
  currentFeature = null;
307
-
308
- if (obliqueMap) {
309
- obliqueMap.switchEnabled = true;
310
- }
311
341
  };
312
342
 
313
- selectFeatureInteraction.featureChanged.addEventListener((feature) => {
343
+ /**
344
+ * Creates an interaction set from an edit geometry interaction. If the geometry of the feature is not supported a message is logged.
345
+ * @param {import("ol").Feature} feature The feature to be edited.
346
+ */
347
+ function createCurrentInteractionSet(feature) {
314
348
  destroyCurrentInteractionSet();
315
349
  if (feature) {
316
- if (obliqueMap) {
317
- obliqueMap.switchEnabled = false;
318
- }
319
350
  currentFeature = feature;
320
351
  currentFeature[createSync] = true;
321
352
  const geometry = feature[obliqueGeometry] ?? feature.getGeometry();
@@ -341,6 +372,7 @@ function startEditGeometrySession(app, layer) {
341
372
  currentInteractionSet = createEditPointInteraction(
342
373
  /** @type {import("ol").Feature<import("ol/geom").Point>} */ (feature),
343
374
  scratchLayer,
375
+ layer,
344
376
  );
345
377
  } else if (geometryType === GeometryType.Circle) {
346
378
  currentInteractionSet = createEditCircleGeometryInteraction(
@@ -355,35 +387,20 @@ function startEditGeometrySession(app, layer) {
355
387
  getLogger('EditGeometrySession').warning(`Geometry of type ${geometryType} is currently not supported`);
356
388
  currentFeature[createSync] = false;
357
389
  currentFeature = null;
358
- selectFeatureInteraction.clear();
359
390
  }
360
391
  }
361
- });
392
+ }
362
393
 
363
- let obliqueImageChangedListener = () => {};
364
394
  const setupActiveMap = () => {
365
395
  mapInteractionController.reset();
366
396
  mouseOverInteraction.reset();
367
- selectFeatureInteraction.clear();
368
- obliqueImageChangedListener();
369
- const { activeMap } = app.maps;
370
- if (activeMap instanceof ObliqueMap) {
371
- obliqueMap = activeMap;
372
- obliqueImageChangedListener = /** @type {ObliqueMap} */ (activeMap).imageChanged
373
- .addEventListener(() => {
374
- selectFeatureInteraction.clear();
375
- });
376
- } else {
377
- obliqueMap = null;
378
- obliqueImageChangedListener = () => {};
379
- }
397
+ createCurrentInteractionSet(null);
380
398
  };
381
399
  const mapActivatedListener = app.maps.mapActivated.addEventListener(setupActiveMap);
382
400
  setupActiveMap();
383
401
 
384
402
  const stop = () => {
385
403
  app.layers.remove(scratchLayer);
386
- obliqueImageChangedListener();
387
404
  mapActivatedListener();
388
405
  mapInteractionController.reset();
389
406
  mouseOverInteraction.reset();
@@ -396,9 +413,14 @@ function startEditGeometrySession(app, layer) {
396
413
 
397
414
  return {
398
415
  type: SessionType.EDIT_GEOMETRY,
399
- featureSelection: selectFeatureInteraction,
400
416
  stopped,
401
417
  stop,
418
+ setFeature(feature) {
419
+ createCurrentInteractionSet(feature);
420
+ },
421
+ get feature() {
422
+ return currentFeature;
423
+ },
402
424
  };
403
425
  }
404
426
 
@@ -13,6 +13,7 @@ import { getFlatCoordinatesFromGeometry } from '../geometryHelpers.js';
13
13
  import CesiumMap from '../../map/cesiumMap.js';
14
14
  import { vertexSymbol } from './editorSymbols.js';
15
15
  import Vector from '../../layer/vectorLayer.js';
16
+ import { createSync } from '../../layer/vectorSymbols.js';
16
17
 
17
18
  /**
18
19
  * @param {import("ol/coordinate").Coordinate} coordinate
@@ -26,6 +27,7 @@ export function createVertex(coordinate) {
26
27
  });
27
28
  vertex[vertexSymbol] = true;
28
29
  vertex[Vector.doNotTransform] = true;
30
+ vertex[createSync] = true;
29
31
  return vertex;
30
32
  }
31
33
 
@@ -193,7 +195,7 @@ export async function placeGeometryOnTerrain(geometry, map) {
193
195
  * @param {import("@vcmap/core").VcsMap} cesiumMap
194
196
  * @returns {Promise<void>}
195
197
  */
196
- export async function ensureFeatureAbsolute(feature, layer, cesiumMap) {
198
+ export async function ensureFeatureAbsolute(feature, layer, cesiumMap) { // XXX this does not ensure 3D coordinates
197
199
  const layerIsClamped = layer.vectorProperties.altitudeMode === HeightReference.CLAMP_TO_GROUND;
198
200
  const altitudeMode = feature.get('olcs_altitudeMode');
199
201
  if (altitudeMode === 'clampToGround' || (!altitudeMode && layerIsClamped)) {
@@ -4,7 +4,7 @@ import InteractionChain from '../../interaction/interactionChain.js';
4
4
  import VcsEvent from '../../vcsEvent.js';
5
5
  import { EventType } from '../../interaction/interactionType.js';
6
6
  import { maxZIndex } from '../layerCollection.js';
7
- import { markVolatile } from '../../context.js';
7
+ import { markVolatile } from '../../vcsModule.js';
8
8
  import { PrimitiveOptionsType } from '../../layer/vectorProperties.js';
9
9
 
10
10
  /**
@@ -23,11 +23,13 @@ import { PrimitiveOptionsType } from '../../layer/vectorProperties.js';
23
23
  * @property {string} CREATE
24
24
  * @property {string} EDIT_GEOMETRY
25
25
  * @property {string} EDIT_FEATURES
26
+ * @property {string} SELECT
26
27
  */
27
28
  export const SessionType = {
28
29
  CREATE: 'create',
29
30
  EDIT_GEOMETRY: 'editGeometry',
30
31
  EDIT_FEATURES: 'editFeatures',
32
+ SELECT: 'selectFeatures',
31
33
  };
32
34
 
33
35
  /**
@@ -77,16 +79,22 @@ export function setupScratchLayer(layerCollection) { // IDEA pass in stopped and
77
79
  * feature interaction to be active on CLICKMOVE & DRAGSTART. Destroying the setup will reset the interaction
78
80
  * to its previous active state.
79
81
  * @param {import("@vcmap/core").EventHandler} eventHandler
82
+ * @param {string} [interactionId]
80
83
  * @returns {{ interactionChain: InteractionChain, removed: VcsEvent<void>, destroy: function():void }}
81
84
  * @private
82
85
  */
83
- export function setupInteractionChain(eventHandler) {
86
+ export function setupInteractionChain(eventHandler, interactionId) {
84
87
  const interactionChain = new InteractionChain();
85
88
  /**
86
89
  * @type {VcsEvent<void>}
87
90
  */
88
91
  const removed = new VcsEvent();
89
- const listener = eventHandler.addExclusiveInteraction(interactionChain, () => { removed.raiseEvent(); });
92
+ const listener = eventHandler.addExclusiveInteraction(
93
+ interactionChain,
94
+ () => { removed.raiseEvent(); },
95
+ undefined,
96
+ interactionId,
97
+ );
90
98
  const currentFeatureInteractionEvent = eventHandler.featureInteraction.active;
91
99
  eventHandler.featureInteraction.setActive(EventType.CLICKMOVE | EventType.DRAGSTART);
92
100
 
@@ -14,3 +14,8 @@ export const vertexIndex = Symbol('VertexIndex');
14
14
  * @type {symbol}
15
15
  */
16
16
  export const handlerSymbol = Symbol('Handler');
17
+ /**
18
+ * Symbol to identify which was the last editor mouse over handler that edited the cursor style.
19
+ * @type {symbol}
20
+ */
21
+ export const mouseOverSymbol = Symbol('MouseOver');
@@ -1,7 +1,6 @@
1
- import { handlerSymbol } from '../editorSymbols.js';
1
+ import { handlerSymbol, mouseOverSymbol } from '../editorSymbols.js';
2
2
  import AbstractInteraction from '../../../interaction/abstractInteraction.js';
3
3
  import { ModificationKeyType, EventType } from '../../../interaction/interactionType.js';
4
- import { vcsLayerName } from '../../../layer/layerSymbols.js';
5
4
  import { cursorMap } from './editGeometryMouseOverInteraction.js';
6
5
 
7
6
  /**
@@ -10,27 +9,13 @@ import { cursorMap } from './editGeometryMouseOverInteraction.js';
10
9
  * @extends {AbstractInteraction}
11
10
  */
12
11
  class EditFeaturesMouseOverInteraction extends AbstractInteraction {
13
- /**
14
- * @param {string} layerName - the layer name of the currently editing layer
15
- * @param {import("@vcmap/core").SelectMultiFeatureInteraction} selectMultiFeatureInteraction
16
- */
17
- constructor(layerName, selectMultiFeatureInteraction) {
18
- super(EventType.MOVE, ModificationKeyType.ALL);
12
+ constructor() {
13
+ super(EventType.MOVE, ModificationKeyType.NONE);
19
14
  /**
20
15
  * @type {import("ol").Feature|import("@vcmap-cesium/engine").Cesium3DTileFeature|import("@vcmap-cesium/engine").Cesium3DTilePointFeature|null}
21
16
  * @private
22
17
  */
23
- this._lastFeature = null;
24
- /**
25
- * @type {import("@vcmap/core").SelectMultiFeatureInteraction}
26
- * @private
27
- */
28
- this._selectMultiFeatureInteraction = selectMultiFeatureInteraction;
29
- /**
30
- * The layer name to react to
31
- * @type {string}
32
- */
33
- this.layerName = layerName;
18
+ this._currentHandler = null;
34
19
  /**
35
20
  * @type {CSSStyleDeclaration}
36
21
  */
@@ -46,26 +31,17 @@ class EditFeaturesMouseOverInteraction extends AbstractInteraction {
46
31
  */
47
32
  async pipe(event) {
48
33
  if (
49
- event.feature &&
50
- (event.feature[vcsLayerName] === this.layerName || event.feature[handlerSymbol])
34
+ event.feature && event.feature[handlerSymbol]
51
35
  ) {
52
- this._lastFeature = /** @type {import("ol").Feature|import("@vcmap-cesium/engine").Cesium3DTileFeature|import("@vcmap-cesium/engine").Cesium3DTilePointFeature} */
36
+ this._currentHandler = /** @type {import("ol").Feature|import("@vcmap-cesium/engine").Cesium3DTileFeature|import("@vcmap-cesium/engine").Cesium3DTilePointFeature} */
53
37
  (event.feature);
54
38
  } else {
55
- this._lastFeature = null;
39
+ this._currentHandler = null;
56
40
  }
57
- this._evaluate(event.key);
41
+ this._evaluate();
58
42
  return event;
59
43
  }
60
44
 
61
- /**
62
- * @inheritDoc
63
- * @param {ModificationKeyType} modifier
64
- */
65
- modifierChanged(modifier) {
66
- this._evaluate(modifier);
67
- }
68
-
69
45
  /**
70
46
  * @inheritDoc
71
47
  * @param {(boolean|number)=} active
@@ -85,26 +61,15 @@ class EditFeaturesMouseOverInteraction extends AbstractInteraction {
85
61
  }
86
62
 
87
63
  /**
88
- * @param {ModificationKeyType} modifier
89
64
  * @private
90
65
  */
91
- _evaluate(modifier) {
92
- if (this._lastFeature) {
93
- if (this._lastFeature[handlerSymbol]) {
94
- this.cursorStyle.cursor = cursorMap.select;
95
- } else if (modifier === ModificationKeyType.CTRL) {
96
- if (!this._selectMultiFeatureInteraction.hasFeatureId(/** @type {string} */ (this._lastFeature.getId()))) {
97
- this.cursorStyle.cursor = cursorMap.addToSelection;
98
- } else {
99
- this.cursorStyle.cursor = cursorMap.removeFromSelection;
100
- }
101
- } else if (!this._selectMultiFeatureInteraction.hasFeatureId(/** @type {string} */ (this._lastFeature.getId()))) {
102
- this.cursorStyle.cursor = cursorMap.select;
103
- } else {
104
- this.cursorStyle.cursor = cursorMap.auto;
105
- }
106
- } else {
66
+ _evaluate() {
67
+ if (this._currentHandler) {
68
+ this.cursorStyle.cursor = cursorMap.translate;
69
+ this.cursorStyle[mouseOverSymbol] = this.id;
70
+ } else if (this.cursorStyle?.[mouseOverSymbol] === this.id) {
107
71
  this.cursorStyle.cursor = cursorMap.auto;
72
+ delete this.cursorStyle[mouseOverSymbol];
108
73
  }
109
74
  }
110
75
 
@@ -112,6 +77,7 @@ class EditFeaturesMouseOverInteraction extends AbstractInteraction {
112
77
  * @inheritDoc
113
78
  */
114
79
  destroy() {
80
+ this.reset();
115
81
  this.cursorStyle = null;
116
82
  super.destroy();
117
83
  }
@@ -1,10 +1,8 @@
1
- import { vertexSymbol } from '../editorSymbols.js';
1
+ import { mouseOverSymbol, vertexSymbol } from '../editorSymbols.js';
2
2
  import AbstractInteraction from '../../../interaction/abstractInteraction.js';
3
3
  import { ModificationKeyType, EventType } from '../../../interaction/interactionType.js';
4
- import { vcsLayerName } from '../../../layer/layerSymbols.js';
5
4
 
6
5
  /**
7
- * only exported for tests
8
6
  * @type {Object}
9
7
  */
10
8
  export const cursorMap = { // TODO these can now be designed custom. IE11 no linger required
@@ -16,7 +14,7 @@ export const cursorMap = { // TODO these can now be designed custom. IE11 no lin
16
14
  select: 'pointer',
17
15
  edit: 'pointer', // fa pencil
18
16
  translateVertex: 'move', // fa-stack pointer-move
19
- removeVertex: 'pointer', // fa-stack pencil-minus
17
+ removeVertex: 'no-drop', // fa-stack pencil-minus
20
18
  insertVertex: 'cell', // fa-stack pencil-plus
21
19
  addToSelection: 'cell', // fa-stack pointer-black
22
20
  removeFromSelection: 'not-allowed',
@@ -28,21 +26,13 @@ export const cursorMap = { // TODO these can now be designed custom. IE11 no lin
28
26
  * @extends {AbstractInteraction}
29
27
  */
30
28
  class EditGeometryMouseOverInteraction extends AbstractInteraction {
31
- /**
32
- * @param {string} layerName - the layer name of the currently editing layer
33
- */
34
- constructor(layerName) {
35
- super(EventType.MOVE, ModificationKeyType.ALL);
29
+ constructor() {
30
+ super(EventType.MOVE, ModificationKeyType.NONE | ModificationKeyType.SHIFT);
36
31
  /**
37
32
  * @type {import("ol").Feature|import("@vcmap-cesium/engine").Cesium3DTileFeature|import("@vcmap-cesium/engine").Cesium3DTilePointFeature|null}
38
33
  * @private
39
34
  */
40
- this._lastFeature = null;
41
- /**
42
- * The layer name to react to
43
- * @type {string}
44
- */
45
- this.layerName = layerName;
35
+ this._currentVertex = null;
46
36
  /**
47
37
  * @type {CSSStyleDeclaration}
48
38
  */
@@ -57,17 +47,11 @@ class EditGeometryMouseOverInteraction extends AbstractInteraction {
57
47
  * @returns {Promise<InteractionEvent>}
58
48
  */
59
49
  async pipe(event) {
60
- if (
61
- event.feature &&
62
- (
63
- event.feature[vcsLayerName] === this.layerName ||
64
- event.feature[vertexSymbol]
65
- )
66
- ) {
67
- this._lastFeature = /** @type {import("ol").Feature|import("@vcmap-cesium/engine").Cesium3DTileFeature|import("@vcmap-cesium/engine").Cesium3DTilePointFeature} */
50
+ if (event.feature && event.feature[vertexSymbol]) {
51
+ this._currentVertex = /** @type {import("ol").Feature|import("@vcmap-cesium/engine").Cesium3DTileFeature|import("@vcmap-cesium/engine").Cesium3DTilePointFeature} */
68
52
  (event.feature);
69
53
  } else {
70
- this._lastFeature = null;
54
+ this._currentVertex = null;
71
55
  }
72
56
  this._evaluate(event.key);
73
57
  return event;
@@ -104,18 +88,16 @@ class EditGeometryMouseOverInteraction extends AbstractInteraction {
104
88
  * @private
105
89
  */
106
90
  _evaluate(modifier) {
107
- if (this._lastFeature) {
108
- if (this._lastFeature[vertexSymbol]) {
109
- if (modifier === ModificationKeyType.SHIFT) {
110
- this.cursorStyle.cursor = cursorMap.removeVertex;
111
- } else {
112
- this.cursorStyle.cursor = cursorMap.translateVertex;
113
- }
91
+ if (this._currentVertex) {
92
+ if (modifier === ModificationKeyType.SHIFT) {
93
+ this.cursorStyle.cursor = cursorMap.removeVertex;
114
94
  } else {
115
- this.cursorStyle.cursor = cursorMap.select;
95
+ this.cursorStyle.cursor = cursorMap.translateVertex;
116
96
  }
117
- } else {
97
+ this.cursorStyle[mouseOverSymbol] = this.id;
98
+ } else if (this.cursorStyle?.[mouseOverSymbol] === this.id) {
118
99
  this.cursorStyle.cursor = cursorMap.auto;
100
+ delete this.cursorStyle[mouseOverSymbol];
119
101
  }
120
102
  }
121
103
 
@@ -123,6 +105,7 @@ class EditGeometryMouseOverInteraction extends AbstractInteraction {
123
105
  * @inheritDoc
124
106
  */
125
107
  destroy() {
108
+ this.reset();
126
109
  this.cursorStyle = null;
127
110
  super.destroy();
128
111
  }
@@ -11,15 +11,15 @@ import CesiumMap from '../../../map/cesiumMap.js';
11
11
  */
12
12
  class EnsureHandlerSelectionInteraction extends AbstractInteraction {
13
13
  /**
14
- * @param {import("@vcmap/core").SelectMultiFeatureInteraction} selectMultiFeatureInteraction
14
+ * @param {Array<import("ol").Feature>} selectedFeatures Reference to the selected features.
15
15
  */
16
- constructor(selectMultiFeatureInteraction) {
16
+ constructor(selectedFeatures) {
17
17
  super(EventType.DRAGSTART | EventType.MOVE);
18
18
  /**
19
- * @type {import("@vcmap/core").SelectMultiFeatureInteraction}
19
+ * @type {Array<import("ol").Feature>}
20
20
  * @private
21
21
  */
22
- this._featureSelection = selectMultiFeatureInteraction;
22
+ this._featureSelection = selectedFeatures;
23
23
  }
24
24
 
25
25
  /**
@@ -29,7 +29,7 @@ class EnsureHandlerSelectionInteraction extends AbstractInteraction {
29
29
  async pipe(event) {
30
30
  if (
31
31
  event.feature &&
32
- this._featureSelection.selectedFeatures.length > 0 &&
32
+ this._featureSelection.length > 0 &&
33
33
  !event.feature[handlerSymbol] &&
34
34
  event.map instanceof CesiumMap
35
35
  ) {