@open-pioneer/map 0.7.0 → 0.8.0-dev.20241120115147

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 (53) hide show
  1. package/CHANGELOG.md +133 -0
  2. package/README.md +116 -12
  3. package/api/MapModel.d.ts +48 -15
  4. package/api/layers/GroupLayer.d.ts +50 -0
  5. package/api/layers/GroupLayer.js +6 -0
  6. package/api/layers/GroupLayer.js.map +1 -0
  7. package/api/layers/SimpleLayer.d.ts +1 -0
  8. package/api/layers/SimpleLayer.js.map +1 -1
  9. package/api/layers/WMSLayer.d.ts +1 -0
  10. package/api/layers/WMSLayer.js.map +1 -1
  11. package/api/layers/WMTSLayer.d.ts +1 -0
  12. package/api/layers/WMTSLayer.js.map +1 -1
  13. package/api/layers/base.d.ts +35 -14
  14. package/api/layers/base.js.map +1 -1
  15. package/api/layers/index.d.ts +1 -0
  16. package/index.js +1 -0
  17. package/index.js.map +1 -1
  18. package/model/AbstractLayer.d.ts +2 -2
  19. package/model/AbstractLayer.js +16 -23
  20. package/model/AbstractLayer.js.map +1 -1
  21. package/model/AbstractLayerBase.d.ts +19 -4
  22. package/model/AbstractLayerBase.js +48 -35
  23. package/model/AbstractLayerBase.js.map +1 -1
  24. package/model/Highlights.d.ts +2 -1
  25. package/model/Highlights.js +2 -0
  26. package/model/Highlights.js.map +1 -1
  27. package/model/LayerCollectionImpl.d.ts +5 -3
  28. package/model/LayerCollectionImpl.js +27 -29
  29. package/model/LayerCollectionImpl.js.map +1 -1
  30. package/model/MapModelImpl.d.ts +12 -2
  31. package/model/MapModelImpl.js +94 -25
  32. package/model/MapModelImpl.js.map +1 -1
  33. package/model/SublayersCollectionImpl.d.ts +6 -3
  34. package/model/SublayersCollectionImpl.js +6 -4
  35. package/model/SublayersCollectionImpl.js.map +1 -1
  36. package/model/layers/GroupLayerImpl.d.ts +39 -0
  37. package/model/layers/GroupLayerImpl.js +88 -0
  38. package/model/layers/GroupLayerImpl.js.map +1 -0
  39. package/model/layers/SimpleLayerImpl.d.ts +1 -0
  40. package/model/layers/SimpleLayerImpl.js +3 -0
  41. package/model/layers/SimpleLayerImpl.js.map +1 -1
  42. package/model/layers/WMSLayerImpl.d.ts +9 -7
  43. package/model/layers/WMSLayerImpl.js +58 -51
  44. package/model/layers/WMSLayerImpl.js.map +1 -1
  45. package/model/layers/WMTSLayerImpl.d.ts +3 -5
  46. package/model/layers/WMTSLayerImpl.js +13 -13
  47. package/model/layers/WMTSLayerImpl.js.map +1 -1
  48. package/package.json +9 -8
  49. package/ui/hooks.d.ts +10 -0
  50. package/ui/hooks.js.map +1 -1
  51. package/util/defer.d.ts +0 -18
  52. package/util/defer.js +0 -21
  53. package/util/defer.js.map +0 -1
@@ -1,24 +1,24 @@
1
- import { createLogger, EventEmitter } from '@open-pioneer/core';
1
+ import { reactiveSet, reactive, batch } from '@conterra/reactivity-core';
2
+ import { createLogger } from '@open-pioneer/core';
2
3
  import { AbstractLayer } from './AbstractLayer.js';
3
4
 
4
5
  const LOG = createLogger("map:LayerCollection");
5
6
  const BASE_LAYER_Z = 0;
6
7
  const OPERATION_LAYER_INITIAL_Z = 1;
7
8
  const TOPMOST_LAYER_Z = 9999999;
8
- class LayerCollectionImpl extends EventEmitter {
9
+ class LayerCollectionImpl {
9
10
  #map;
10
11
  /** Top level layers (base layers, operational layers). No sublayers. */
11
- #topLevelLayers = /* @__PURE__ */ new Set();
12
+ #topLevelLayers = reactiveSet();
12
13
  /** Index of _all_ layer instances, including sublayers. */
13
14
  #layersById = /* @__PURE__ */ new Map();
14
15
  /** Reverse index of _all_ layers that have an associated OpenLayers layer. */
15
16
  #layersByOlLayer = /* @__PURE__ */ new WeakMap();
16
17
  /** Currently active base layer. */
17
- #activeBaseLayer;
18
+ #activeBaseLayer = reactive();
18
19
  /** next z-index for operational layer. currently just auto-increments. */
19
20
  #nextIndex = OPERATION_LAYER_INITIAL_Z;
20
21
  constructor(map) {
21
- super();
22
22
  this.#map = map;
23
23
  }
24
24
  destroy() {
@@ -27,18 +27,18 @@ class LayerCollectionImpl extends EventEmitter {
27
27
  }
28
28
  this.#topLevelLayers.clear();
29
29
  this.#layersById.clear();
30
- this.#activeBaseLayer = void 0;
30
+ this.#activeBaseLayer.value = void 0;
31
31
  }
32
32
  addLayer(layer) {
33
33
  checkLayerInstance(layer);
34
- layer.__attach(this.#map);
34
+ layer.__attachToMap(this.#map);
35
35
  this.#addLayer(layer);
36
36
  }
37
37
  getBaseLayers() {
38
38
  return this.getAllLayers().filter((layer) => layer.isBaseLayer);
39
39
  }
40
40
  getActiveBaseLayer() {
41
- return this.#activeBaseLayer;
41
+ return this.#activeBaseLayer.value;
42
42
  }
43
43
  activateBaseLayer(id) {
44
44
  let newBaseLayer = void 0;
@@ -57,10 +57,7 @@ class LayerCollectionImpl extends EventEmitter {
57
57
  return false;
58
58
  }
59
59
  }
60
- if (newBaseLayer !== this.#activeBaseLayer) {
61
- this.#updateBaseLayer(newBaseLayer);
62
- this.emit("changed");
63
- }
60
+ this.#updateBaseLayer(newBaseLayer);
64
61
  return true;
65
62
  }
66
63
  getOperationalLayers(options) {
@@ -95,7 +92,7 @@ class LayerCollectionImpl extends EventEmitter {
95
92
  const olLayer = model.olLayer;
96
93
  if (model.isBaseLayer) {
97
94
  olLayer.setZIndex(BASE_LAYER_Z);
98
- if (!this.#activeBaseLayer && model.visible) {
95
+ if (!this.#activeBaseLayer.value && model.visible) {
99
96
  this.#updateBaseLayer(model);
100
97
  } else {
101
98
  model.__setVisible(false);
@@ -106,7 +103,6 @@ class LayerCollectionImpl extends EventEmitter {
106
103
  }
107
104
  this.#topLevelLayers.add(model);
108
105
  this.#map.olMap.addLayer(olLayer);
109
- this.emit("changed");
110
106
  }
111
107
  /**
112
108
  * Removes the given layer from the map and all relevant indices.
@@ -127,7 +123,7 @@ class LayerCollectionImpl extends EventEmitter {
127
123
  this.#map.olMap.removeLayer(model.olLayer);
128
124
  this.#topLevelLayers.delete(model);
129
125
  this.#unIndexLayer(model);
130
- if (this.#activeBaseLayer === model) {
126
+ if (this.#activeBaseLayer.value === model) {
131
127
  const newBaselayer = this.getBaseLayers()[0];
132
128
  if (newBaselayer) {
133
129
  checkLayerInstance(newBaselayer);
@@ -135,10 +131,9 @@ class LayerCollectionImpl extends EventEmitter {
135
131
  this.#updateBaseLayer(newBaselayer);
136
132
  }
137
133
  model.destroy();
138
- this.emit("changed");
139
134
  }
140
135
  #updateBaseLayer(model) {
141
- if (this.#activeBaseLayer === model) {
136
+ if (this.#activeBaseLayer.value === model) {
142
137
  return;
143
138
  }
144
139
  if (LOG.isDebug()) {
@@ -146,14 +141,14 @@ class LayerCollectionImpl extends EventEmitter {
146
141
  return model2 ? `'${model2.id}'` : void 0;
147
142
  };
148
143
  LOG.debug(
149
- `Switching active base layer from ${getId(this.#activeBaseLayer)} to ${getId(
150
- model
151
- )}`
144
+ `Switching active base layer from ${getId(this.#activeBaseLayer.value)} to ${getId(model)}`
152
145
  );
153
146
  }
154
- this.#activeBaseLayer?.__setVisible(false);
155
- this.#activeBaseLayer = model;
156
- this.#activeBaseLayer?.__setVisible(true);
147
+ batch(() => {
148
+ this.#activeBaseLayer.value?.__setVisible(false);
149
+ this.#activeBaseLayer.value = model;
150
+ model?.__setVisible(true);
151
+ });
157
152
  }
158
153
  /**
159
154
  * Index the layer and all its children.
@@ -169,13 +164,16 @@ class LayerCollectionImpl extends EventEmitter {
169
164
  );
170
165
  }
171
166
  if (olLayer && this.#layersByOlLayer.has(olLayer)) {
172
- throw new Error(`OlLayer has already been used in this or another layer.`);
167
+ throw new Error(`OlLayer used by layer '${id}' has already been used in map.`);
173
168
  }
174
169
  this.#layersById.set(id, model2);
175
170
  if (olLayer) {
176
171
  this.#layersByOlLayer.set(olLayer, model2);
177
172
  }
178
173
  registrations.push([id, olLayer]);
174
+ for (const layer of model2.layers?.__getRawLayers() ?? []) {
175
+ visit(layer);
176
+ }
179
177
  for (const sublayer of model2.sublayers?.__getRawSublayers() ?? []) {
180
178
  visit(sublayer);
181
179
  }
@@ -193,7 +191,7 @@ class LayerCollectionImpl extends EventEmitter {
193
191
  }
194
192
  }
195
193
  /**
196
- * Removes index entries for the given layer and all its sublayers.
194
+ * Removes index entries for the given layer and all its children.
197
195
  */
198
196
  #unIndexLayer(model) {
199
197
  const visit = (model2) => {
@@ -201,6 +199,9 @@ class LayerCollectionImpl extends EventEmitter {
201
199
  this.#layersByOlLayer.delete(model2.olLayer);
202
200
  }
203
201
  this.#layersById.delete(model2.id);
202
+ for (const layer of model2.layers?.__getRawLayers() ?? []) {
203
+ visit(layer);
204
+ }
204
205
  for (const sublayer of model2.sublayers?.__getRawSublayers() ?? []) {
205
206
  visit(sublayer);
206
207
  }
@@ -212,10 +213,7 @@ function sortLayersByDisplayOrder(layers) {
212
213
  layers.sort((left, right) => {
213
214
  const leftZ = left.olLayer.getZIndex() ?? 1;
214
215
  const rightZ = right.olLayer.getZIndex() ?? 1;
215
- if (leftZ !== rightZ) {
216
- return leftZ - rightZ;
217
- }
218
- return left.id.localeCompare(right.id, "en");
216
+ return leftZ - rightZ;
219
217
  });
220
218
  }
221
219
  function checkLayerInstance(object) {
@@ -1 +1 @@
1
- {"version":3,"file":"LayerCollectionImpl.js","sources":["LayerCollectionImpl.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { EventEmitter, createLogger } from \"@open-pioneer/core\";\nimport OlBaseLayer from \"ol/layer/Base\";\nimport {\n LayerCollection,\n LayerCollectionEvents,\n Layer,\n LayerRetrievalOptions,\n AnyLayer,\n Sublayer\n} from \"../api\";\nimport { AbstractLayer } from \"./AbstractLayer\";\nimport { AbstractLayerBase } from \"./AbstractLayerBase\";\nimport { MapModelImpl } from \"./MapModelImpl\";\n\nconst LOG = createLogger(\"map:LayerCollection\");\n\nconst BASE_LAYER_Z = 0;\nconst OPERATION_LAYER_INITIAL_Z = 1;\n\ntype LayerType = AbstractLayer & Layer;\ntype LayerBaseType = (AbstractLayerBase & Layer) | (AbstractLayerBase & Sublayer);\n\n/**\n * Z index for layers that should always be rendered on top of all other layers.\n * Note that this is an internal, unstable property!\n *\n * @internal\n */\nexport const TOPMOST_LAYER_Z = 9999999;\n\nexport class LayerCollectionImpl\n extends EventEmitter<LayerCollectionEvents>\n implements LayerCollection\n{\n #map: MapModelImpl;\n\n /** Top level layers (base layers, operational layers). No sublayers. */\n #topLevelLayers = new Set<LayerType>();\n\n /** Index of _all_ layer instances, including sublayers. */\n #layersById = new Map<string, LayerBaseType>();\n\n /** Reverse index of _all_ layers that have an associated OpenLayers layer. */\n #layersByOlLayer: WeakMap<OlBaseLayer, LayerType> = new WeakMap();\n\n /** Currently active base layer. */\n #activeBaseLayer: LayerType | undefined;\n\n /** next z-index for operational layer. currently just auto-increments. */\n #nextIndex = OPERATION_LAYER_INITIAL_Z;\n\n constructor(map: MapModelImpl) {\n super();\n this.#map = map;\n }\n\n destroy() {\n // Collection is destroyed together with the map, there is no need to clean up the olMap\n for (const layer of this.#layersById.values()) {\n layer.destroy();\n }\n this.#topLevelLayers.clear();\n this.#layersById.clear();\n this.#activeBaseLayer = undefined;\n }\n\n addLayer(layer: Layer): void {\n checkLayerInstance(layer);\n\n layer.__attach(this.#map);\n this.#addLayer(layer);\n }\n\n getBaseLayers(): Layer[] {\n return this.getAllLayers().filter((layer) => layer.isBaseLayer);\n }\n\n getActiveBaseLayer(): Layer | undefined {\n return this.#activeBaseLayer;\n }\n\n activateBaseLayer(id: string | undefined): boolean {\n let newBaseLayer = undefined;\n if (id != null) {\n newBaseLayer = this.#layersById.get(id);\n if (!(newBaseLayer instanceof AbstractLayer)) {\n LOG.warn(`Cannot activate base layer '${id}: layer has an invalid type.'`);\n return false;\n }\n if (!newBaseLayer) {\n LOG.warn(`Cannot activate base layer '${id}': layer is unknown.`);\n return false;\n }\n if (!newBaseLayer.isBaseLayer) {\n LOG.warn(`Cannot activate base layer '${id}': layer is not a base layer.`);\n return false;\n }\n }\n\n if (newBaseLayer !== this.#activeBaseLayer) {\n this.#updateBaseLayer(newBaseLayer);\n this.emit(\"changed\");\n }\n return true;\n }\n\n getOperationalLayers(options?: LayerRetrievalOptions): Layer[] {\n return this.getAllLayers(options).filter((layer) => !layer.isBaseLayer);\n }\n\n getAllLayers(options?: LayerRetrievalOptions): Layer[] {\n const layers = Array.from(this.#topLevelLayers.values());\n if (options?.sortByDisplayOrder) {\n sortLayersByDisplayOrder(layers);\n }\n return layers;\n }\n\n getLayerById(id: string): AnyLayer | undefined {\n return this.#layersById.get(id);\n }\n\n removeLayerById(id: string): void {\n const model = this.#layersById.get(id);\n if (!model) {\n LOG.isDebug() && LOG.debug(`Cannot remove layer '${id}': layer is unknown.`);\n return;\n }\n\n this.#removeLayer(model);\n }\n\n getLayerByRawInstance(layer: OlBaseLayer): Layer | undefined {\n return this.#layersByOlLayer?.get(layer);\n }\n\n /**\n * Adds the given layer to the map and all relevant indices.\n */\n #addLayer(model: LayerType) {\n this.#indexLayer(model);\n\n const olLayer = model.olLayer;\n if (model.isBaseLayer) {\n olLayer.setZIndex(BASE_LAYER_Z);\n if (!this.#activeBaseLayer && model.visible) {\n this.#updateBaseLayer(model);\n } else {\n model.__setVisible(false);\n }\n } else {\n olLayer.setZIndex(this.#nextIndex++);\n model.__setVisible(model.visible);\n }\n\n this.#topLevelLayers.add(model);\n this.#map.olMap.addLayer(olLayer);\n this.emit(\"changed\");\n }\n\n /**\n * Removes the given layer from the map and all relevant indices.\n * The layer will be destroyed.\n */\n #removeLayer(model: LayerType | LayerBaseType) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n if (!this.#topLevelLayers.has(model as any)) {\n LOG.warn(\n `Cannot remove layer '${model.id}': only top level layers can be removed at this time.`\n );\n return;\n }\n\n if (!(model instanceof AbstractLayer)) {\n throw new Error(\n `Internal error: expected top level layer to be an instance of AbstractLayer.`\n );\n }\n\n this.#map.olMap.removeLayer(model.olLayer);\n this.#topLevelLayers.delete(model);\n this.#unIndexLayer(model);\n if (this.#activeBaseLayer === model) {\n const newBaselayer = this.getBaseLayers()[0];\n if (newBaselayer) {\n checkLayerInstance(newBaselayer);\n }\n this.#updateBaseLayer(newBaselayer);\n }\n model.destroy();\n this.emit(\"changed\");\n }\n\n #updateBaseLayer(model: LayerType | undefined) {\n if (this.#activeBaseLayer === model) {\n return;\n }\n\n if (LOG.isDebug()) {\n const getId = (model: AbstractLayer | undefined) => {\n return model ? `'${model.id}'` : undefined;\n };\n\n LOG.debug(\n `Switching active base layer from ${getId(this.#activeBaseLayer)} to ${getId(\n model\n )}`\n );\n }\n this.#activeBaseLayer?.__setVisible(false);\n this.#activeBaseLayer = model;\n this.#activeBaseLayer?.__setVisible(true);\n }\n\n /**\n * Index the layer and all its children.\n */\n #indexLayer(model: LayerType) {\n // layer id -> layer (or sublayer)\n const registrations: [string, OlBaseLayer | undefined][] = [];\n const visit = (model: LayerType | (AbstractLayerBase & Sublayer)) => {\n const id = model.id;\n const olLayer = \"olLayer\" in model ? model.olLayer : undefined;\n if (this.#layersById.has(id)) {\n throw new Error(\n `Layer id '${id}' is not unique. Either assign a unique id yourself ` +\n `or skip configuring 'id' for an automatically generated id.`\n );\n }\n if (olLayer && this.#layersByOlLayer.has(olLayer)) {\n throw new Error(`OlLayer has already been used in this or another layer.`);\n }\n\n // Register this layer with the maps.\n this.#layersById.set(id, model);\n if (olLayer) {\n this.#layersByOlLayer.set(olLayer, model as LayerType); // ol is present --> not a sublayer\n }\n registrations.push([id, olLayer]);\n\n // Recurse into nested sublayers.\n for (const sublayer of model.sublayers?.__getRawSublayers() ?? []) {\n visit(sublayer);\n }\n };\n\n try {\n visit(model);\n } catch (e) {\n for (const [id, olLayer] of registrations) {\n this.#layersById.delete(id);\n if (olLayer) {\n this.#layersByOlLayer.delete(olLayer);\n }\n }\n throw e;\n }\n }\n\n /**\n * Removes index entries for the given layer and all its sublayers.\n */\n #unIndexLayer(model: AbstractLayer) {\n const visit = (model: AbstractLayer | AbstractLayerBase) => {\n if (\"olLayer\" in model) {\n this.#layersByOlLayer.delete(model.olLayer);\n }\n this.#layersById.delete(model.id);\n for (const sublayer of model.sublayers?.__getRawSublayers() ?? []) {\n visit(sublayer);\n }\n };\n visit(model);\n }\n}\n\nfunction sortLayersByDisplayOrder(layers: Layer[]) {\n layers.sort((left, right) => {\n // currently layers are added with increasing z-index (base layers: 0), so\n // ordering by z-index is automatically the correct display order.\n // we use the id as the tie breaker for equal z-indices.\n const leftZ = left.olLayer.getZIndex() ?? 1;\n const rightZ = right.olLayer.getZIndex() ?? 1;\n if (leftZ !== rightZ) {\n return leftZ - rightZ;\n }\n return left.id.localeCompare(right.id, \"en\");\n });\n}\n\nfunction checkLayerInstance(object: Layer): asserts object is Layer & AbstractLayer {\n if (!(object instanceof AbstractLayer)) {\n throw new Error(\n `Layer is not a valid layer instance. Use one of the classes provided by the map package instead.`\n );\n }\n}\n"],"names":["model"],"mappings":"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"}
1
+ {"version":3,"file":"LayerCollectionImpl.js","sources":["LayerCollectionImpl.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { batch, reactive, reactiveSet } from \"@conterra/reactivity-core\";\nimport { createLogger } from \"@open-pioneer/core\";\nimport OlBaseLayer from \"ol/layer/Base\";\nimport { Layer, LayerCollection, LayerRetrievalOptions, AnyLayer, Sublayer } from \"../api\";\nimport { AbstractLayer } from \"./AbstractLayer\";\nimport { AbstractLayerBase } from \"./AbstractLayerBase\";\nimport { MapModelImpl } from \"./MapModelImpl\";\n\nconst LOG = createLogger(\"map:LayerCollection\");\n\nconst BASE_LAYER_Z = 0;\nconst OPERATION_LAYER_INITIAL_Z = 1;\n\ntype LayerType = AbstractLayer & Layer;\ntype LayerBaseType = (AbstractLayerBase & Layer) | (AbstractLayerBase & Sublayer);\n\n/**\n * Z index for layers that should always be rendered on top of all other layers.\n * Note that this is an internal, unstable property!\n *\n * @internal\n */\nexport const TOPMOST_LAYER_Z = 9999999;\n\n/**\n * Manages the (top-level) content of the map.\n */\nexport class LayerCollectionImpl implements LayerCollection {\n #map: MapModelImpl;\n\n /** Top level layers (base layers, operational layers). No sublayers. */\n #topLevelLayers = reactiveSet<LayerType>();\n\n /** Index of _all_ layer instances, including sublayers. */\n #layersById = new Map<string, LayerBaseType>();\n\n /** Reverse index of _all_ layers that have an associated OpenLayers layer. */\n #layersByOlLayer: WeakMap<OlBaseLayer, LayerType> = new WeakMap();\n\n /** Currently active base layer. */\n #activeBaseLayer = reactive<LayerType>();\n\n /** next z-index for operational layer. currently just auto-increments. */\n #nextIndex = OPERATION_LAYER_INITIAL_Z;\n\n constructor(map: MapModelImpl) {\n this.#map = map;\n }\n\n destroy() {\n // Collection is destroyed together with the map, there is no need to clean up the olMap\n for (const layer of this.#layersById.values()) {\n layer.destroy();\n }\n this.#topLevelLayers.clear();\n this.#layersById.clear();\n this.#activeBaseLayer.value = undefined;\n }\n\n addLayer(layer: Layer): void {\n checkLayerInstance(layer);\n\n layer.__attachToMap(this.#map);\n this.#addLayer(layer);\n }\n\n getBaseLayers(): Layer[] {\n return this.getAllLayers().filter((layer) => layer.isBaseLayer);\n }\n\n getActiveBaseLayer(): Layer | undefined {\n return this.#activeBaseLayer.value;\n }\n\n activateBaseLayer(id: string | undefined): boolean {\n let newBaseLayer = undefined;\n if (id != null) {\n newBaseLayer = this.#layersById.get(id);\n if (!(newBaseLayer instanceof AbstractLayer)) {\n LOG.warn(`Cannot activate base layer '${id}: layer has an invalid type.'`);\n return false;\n }\n if (!newBaseLayer) {\n LOG.warn(`Cannot activate base layer '${id}': layer is unknown.`);\n return false;\n }\n if (!newBaseLayer.isBaseLayer) {\n LOG.warn(`Cannot activate base layer '${id}': layer is not a base layer.`);\n return false;\n }\n }\n\n this.#updateBaseLayer(newBaseLayer);\n return true;\n }\n\n getOperationalLayers(options?: LayerRetrievalOptions): Layer[] {\n return this.getAllLayers(options).filter((layer) => !layer.isBaseLayer);\n }\n\n getAllLayers(options?: LayerRetrievalOptions): Layer[] {\n const layers = Array.from(this.#topLevelLayers.values());\n if (options?.sortByDisplayOrder) {\n sortLayersByDisplayOrder(layers);\n }\n return layers;\n }\n\n getLayerById(id: string): AnyLayer | undefined {\n return this.#layersById.get(id);\n }\n\n removeLayerById(id: string): void {\n const model = this.#layersById.get(id);\n if (!model) {\n LOG.isDebug() && LOG.debug(`Cannot remove layer '${id}': layer is unknown.`);\n return;\n }\n\n this.#removeLayer(model);\n }\n\n getLayerByRawInstance(layer: OlBaseLayer): Layer | undefined {\n return this.#layersByOlLayer?.get(layer);\n }\n\n /**\n * Adds the given layer to the map and all relevant indices.\n */\n #addLayer(model: LayerType) {\n this.#indexLayer(model);\n\n const olLayer = model.olLayer;\n if (model.isBaseLayer) {\n olLayer.setZIndex(BASE_LAYER_Z);\n if (!this.#activeBaseLayer.value && model.visible) {\n this.#updateBaseLayer(model);\n } else {\n model.__setVisible(false);\n }\n } else {\n olLayer.setZIndex(this.#nextIndex++);\n model.__setVisible(model.visible);\n }\n\n this.#topLevelLayers.add(model);\n this.#map.olMap.addLayer(olLayer);\n }\n\n /**\n * Removes the given layer from the map and all relevant indices.\n * The layer will be destroyed.\n */\n #removeLayer(model: LayerType | LayerBaseType) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n if (!this.#topLevelLayers.has(model as any)) {\n LOG.warn(\n `Cannot remove layer '${model.id}': only top level layers can be removed at this time.`\n );\n return;\n }\n\n if (!(model instanceof AbstractLayer)) {\n throw new Error(\n `Internal error: expected top level layer to be an instance of AbstractLayer.`\n );\n }\n\n this.#map.olMap.removeLayer(model.olLayer);\n this.#topLevelLayers.delete(model);\n this.#unIndexLayer(model);\n if (this.#activeBaseLayer.value === model) {\n const newBaselayer = this.getBaseLayers()[0];\n if (newBaselayer) {\n checkLayerInstance(newBaselayer);\n }\n this.#updateBaseLayer(newBaselayer);\n }\n model.destroy();\n }\n\n #updateBaseLayer(model: LayerType | undefined) {\n if (this.#activeBaseLayer.value === model) {\n return;\n }\n\n if (LOG.isDebug()) {\n const getId = (model: AbstractLayer | undefined) => {\n return model ? `'${model.id}'` : undefined;\n };\n\n LOG.debug(\n `Switching active base layer from ${getId(this.#activeBaseLayer.value)} to ${getId(model)}`\n );\n }\n\n batch(() => {\n this.#activeBaseLayer.value?.__setVisible(false);\n this.#activeBaseLayer.value = model;\n model?.__setVisible(true);\n });\n }\n\n /**\n * Index the layer and all its children.\n */\n #indexLayer(model: LayerType) {\n // layer id -> layer (or sublayer)\n const registrations: [string, OlBaseLayer | undefined][] = [];\n const visit = (model: LayerType | (AbstractLayerBase & Sublayer)) => {\n const id = model.id;\n const olLayer = \"olLayer\" in model ? model.olLayer : undefined;\n if (this.#layersById.has(id)) {\n throw new Error(\n `Layer id '${id}' is not unique. Either assign a unique id yourself ` +\n `or skip configuring 'id' for an automatically generated id.`\n );\n }\n if (olLayer && this.#layersByOlLayer.has(olLayer)) {\n throw new Error(`OlLayer used by layer '${id}' has already been used in map.`);\n }\n\n // Register this layer with the maps.\n this.#layersById.set(id, model);\n if (olLayer) {\n this.#layersByOlLayer.set(olLayer, model as LayerType); // ol is present --> not a sublayer\n }\n registrations.push([id, olLayer]);\n\n // Recurse into nested children.\n for (const layer of model.layers?.__getRawLayers() ?? []) {\n visit(layer);\n }\n for (const sublayer of model.sublayers?.__getRawSublayers() ?? []) {\n visit(sublayer);\n }\n };\n\n try {\n visit(model);\n } catch (e) {\n // If any error happens, undo the indexing.\n // This way we don't leave a partially indexed layer tree behind.\n for (const [id, olLayer] of registrations) {\n this.#layersById.delete(id);\n if (olLayer) {\n this.#layersByOlLayer.delete(olLayer);\n }\n }\n throw e;\n }\n }\n\n /**\n * Removes index entries for the given layer and all its children.\n */\n #unIndexLayer(model: AbstractLayer) {\n const visit = (model: AbstractLayer | AbstractLayerBase) => {\n if (\"olLayer\" in model) {\n this.#layersByOlLayer.delete(model.olLayer);\n }\n this.#layersById.delete(model.id);\n\n for (const layer of model.layers?.__getRawLayers() ?? []) {\n visit(layer);\n }\n\n for (const sublayer of model.sublayers?.__getRawSublayers() ?? []) {\n visit(sublayer);\n }\n };\n visit(model);\n }\n}\n\nfunction sortLayersByDisplayOrder(layers: Layer[]) {\n layers.sort((left, right) => {\n // currently layers are added with increasing z-index (base layers: 0), so\n // ordering by z-index is automatically the correct display order.\n const leftZ = left.olLayer.getZIndex() ?? 1;\n const rightZ = right.olLayer.getZIndex() ?? 1;\n return leftZ - rightZ;\n });\n}\n\nfunction checkLayerInstance(object: Layer): asserts object is Layer & AbstractLayer {\n if (!(object instanceof AbstractLayer)) {\n throw new Error(\n `Layer is not a valid layer instance. Use one of the classes provided by the map package instead.`\n );\n }\n}\n"],"names":["model"],"mappings":"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"}
@@ -1,9 +1,12 @@
1
1
  import { EventEmitter } from "@open-pioneer/core";
2
+ import { HttpService } from "@open-pioneer/http";
2
3
  import OlMap from "ol/Map";
4
+ import OlView from "ol/View";
5
+ import { Coordinate } from "ol/coordinate";
6
+ import { Geometry } from "ol/geom";
7
+ import { Projection } from "ol/proj";
3
8
  import { ExtentConfig, Highlight, HighlightOptions, HighlightZoomOptions, MapModel, MapModelEvents } from "../api";
4
9
  import { LayerCollectionImpl } from "./LayerCollectionImpl";
5
- import { Geometry } from "ol/geom";
6
- import { HttpService } from "@open-pioneer/http";
7
10
  /**
8
11
  * Shared services or other entities propagated from the map model to all layer instances.
9
12
  */
@@ -21,10 +24,17 @@ export declare class MapModelImpl extends EventEmitter<MapModelEvents> implement
21
24
  destroy(): void;
22
25
  get id(): string;
23
26
  get olMap(): OlMap;
27
+ get olView(): OlView;
28
+ get projection(): Projection;
29
+ get center(): Coordinate | undefined;
30
+ get resolution(): number | undefined;
31
+ get zoomLevel(): number | undefined;
32
+ get scale(): number | undefined;
24
33
  get layers(): LayerCollectionImpl;
25
34
  get container(): HTMLElement | undefined;
26
35
  get initialExtent(): ExtentConfig | undefined;
27
36
  get __sharedDependencies(): SharedDependencies;
37
+ setScale(newScale: number): void;
28
38
  highlight(geometries: Geometry[], options?: HighlightOptions | undefined): Highlight;
29
39
  zoom(geometries: Geometry[], options?: HighlightZoomOptions | undefined): void;
30
40
  highlightAndZoom(geometries: Geometry[], options?: HighlightZoomOptions): {
@@ -1,20 +1,26 @@
1
+ import { reactive, synchronized, computed } from '@conterra/reactivity-core';
1
2
  import { createLogger, EventEmitter, isAbortError, createManualPromise, createAbortError } from '@open-pioneer/core';
2
3
  import { unByKey } from 'ol/Observable.js';
3
4
  import { getCenter } from 'ol/extent.js';
4
- import { LayerCollectionImpl } from './LayerCollectionImpl.js';
5
+ import { getPointResolution } from 'ol/proj.js';
5
6
  import { Highlights } from './Highlights.js';
7
+ import { LayerCollectionImpl } from './LayerCollectionImpl.js';
6
8
 
7
9
  const LOG = createLogger("map:MapModel");
10
+ const DEFAULT_DPI = 25.4 / 0.28;
11
+ const INCHES_PER_METRE = 39.37;
8
12
  class MapModelImpl extends EventEmitter {
9
13
  #id;
10
14
  #olMap;
15
+ #olView;
11
16
  #layers = new LayerCollectionImpl(this);
12
17
  #highlights;
13
18
  #sharedDeps;
14
19
  #destroyed = false;
15
20
  #container;
16
- #initialExtent;
17
- #targetWatchKey;
21
+ #initialExtent = reactive();
22
+ #viewBindings;
23
+ #scale;
18
24
  #abortController = new AbortController();
19
25
  #displayStatus;
20
26
  #displayWaiter;
@@ -22,7 +28,14 @@ class MapModelImpl extends EventEmitter {
22
28
  super();
23
29
  this.#id = properties.id;
24
30
  this.#olMap = properties.olMap;
25
- this.#initialExtent = properties.initialExtent;
31
+ this.#olView = synchronized(
32
+ () => this.#olMap.getView(),
33
+ (cb) => {
34
+ const key = this.#olMap.on("change:view", cb);
35
+ return () => unByKey(key);
36
+ }
37
+ );
38
+ this.#initialExtent.value = properties.initialExtent;
26
39
  this.#sharedDeps = {
27
40
  httpService: properties.httpService
28
41
  };
@@ -43,8 +56,22 @@ class MapModelImpl extends EventEmitter {
43
56
  this.#displayWaiter = void 0;
44
57
  }
45
58
  );
46
- this.#targetWatchKey = this.#olMap.on("change:target", () => {
47
- this.#onTargetChanged();
59
+ this.#container = synchronized(
60
+ () => this.#olMap.getTargetElement() ?? void 0,
61
+ (cb) => {
62
+ const key = this.#olMap.on("change:target", cb);
63
+ return () => unByKey(key);
64
+ }
65
+ );
66
+ this.#viewBindings = computed(() => createViewBindings(this.#olView.value));
67
+ this.#scale = computed(() => {
68
+ const { projection, resolution, center } = this;
69
+ if (projection == null || resolution == null || center == null) {
70
+ return void 0;
71
+ }
72
+ const pointResolution = getPointResolution(projection, resolution, center);
73
+ const scale = Math.round(pointResolution * INCHES_PER_METRE * DEFAULT_DPI);
74
+ return scale;
48
75
  });
49
76
  }
50
77
  destroy() {
@@ -57,10 +84,6 @@ class MapModelImpl extends EventEmitter {
57
84
  } catch (e) {
58
85
  LOG.warn(`Unexpected error from event listener during map model destruction:`, e);
59
86
  }
60
- if (this.#targetWatchKey) {
61
- unByKey(this.#targetWatchKey);
62
- }
63
- this.#targetWatchKey = void 0;
64
87
  this.#abortController.abort();
65
88
  this.#displayWaiter?.reject(new Error("Map model was destroyed."));
66
89
  this.#layers.destroy();
@@ -73,18 +96,48 @@ class MapModelImpl extends EventEmitter {
73
96
  get olMap() {
74
97
  return this.#olMap;
75
98
  }
99
+ get olView() {
100
+ return this.#olView.value;
101
+ }
102
+ get projection() {
103
+ return this.#viewBindings.value.projection;
104
+ }
105
+ get center() {
106
+ return this.#viewBindings.value.center.value;
107
+ }
108
+ get resolution() {
109
+ return this.#viewBindings.value.resolution.value;
110
+ }
111
+ get zoomLevel() {
112
+ return this.#viewBindings.value.zoom.value;
113
+ }
114
+ get scale() {
115
+ return this.#scale.value;
116
+ }
76
117
  get layers() {
77
118
  return this.#layers;
78
119
  }
79
120
  get container() {
80
- return this.#container;
121
+ return this.#container.value;
81
122
  }
82
123
  get initialExtent() {
83
- return this.#initialExtent;
124
+ return this.#initialExtent.value;
84
125
  }
85
126
  get __sharedDependencies() {
86
127
  return this.#sharedDeps;
87
128
  }
129
+ setScale(newScale) {
130
+ const view = this.olView;
131
+ const projection = this.projection;
132
+ const center = this.center;
133
+ if (!center) {
134
+ return;
135
+ }
136
+ const mpu = projection.getMetersPerUnit() ?? 1;
137
+ const resolution = INCHES_PER_METRE * DEFAULT_DPI * mpu;
138
+ const pointResolution = newScale / getPointResolution(projection, resolution, center);
139
+ view.setResolution(pointResolution);
140
+ }
88
141
  highlight(geometries, options) {
89
142
  return this.#highlights.addHighlight(geometries, options);
90
143
  }
@@ -128,8 +181,8 @@ class MapModelImpl extends EventEmitter {
128
181
  try {
129
182
  const olMap = this.#olMap;
130
183
  const view = olMap.getView();
131
- if (this.#initialExtent) {
132
- const extent = this.#initialExtent;
184
+ if (this.#initialExtent.value) {
185
+ const extent = this.#initialExtent.value;
133
186
  const olExtent = [extent.xMin, extent.yMin, extent.xMax, extent.yMax];
134
187
  const olCenter = getCenter(olExtent);
135
188
  const resolution = view.getResolutionForExtent(olExtent);
@@ -143,22 +196,38 @@ class MapModelImpl extends EventEmitter {
143
196
  const [xMin = 0, yMin = 0, xMax = 0, yMax = 0] = olExtent;
144
197
  const extent = { xMin, yMin, xMax, yMax };
145
198
  LOG.debug(`Detected initial extent`, extent);
146
- this.#initialExtent = extent;
147
- this.emit("changed:initialExtent");
148
- this.emit("changed");
199
+ this.#initialExtent.value = extent;
149
200
  }
150
201
  } catch (e) {
151
202
  throw new Error(`Failed to apply the initial extent.`, { cause: e });
152
203
  }
153
204
  }
154
- #onTargetChanged() {
155
- const newContainer = this.#olMap.getTargetElement() ?? void 0;
156
- if (this.#container !== newContainer) {
157
- this.#container = newContainer;
158
- this.emit("changed:container");
159
- this.emit("changed");
160
- }
161
- }
205
+ }
206
+ function createViewBindings(view) {
207
+ return {
208
+ resolution: synchronized(
209
+ () => view.getResolution(),
210
+ (cb) => {
211
+ const key = view.on("change:resolution", cb);
212
+ return () => unByKey(key);
213
+ }
214
+ ),
215
+ center: synchronized(
216
+ () => view.getCenter(),
217
+ (cb) => {
218
+ const key = view.on("change:center", cb);
219
+ return () => unByKey(key);
220
+ }
221
+ ),
222
+ zoom: synchronized(
223
+ () => view.getZoom(),
224
+ (cb) => {
225
+ const key = view.on("change:resolution", cb);
226
+ return () => unByKey(key);
227
+ }
228
+ ),
229
+ projection: view.getProjection()
230
+ };
162
231
  }
163
232
  function waitForMapSize(olMap, signal) {
164
233
  const promise = new Promise((resolve, reject) => {
@@ -1 +1 @@
1
- {"version":3,"file":"MapModelImpl.js","sources":["MapModelImpl.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport {\n EventEmitter,\n ManualPromise,\n createAbortError,\n createLogger,\n createManualPromise,\n isAbortError\n} from \"@open-pioneer/core\";\nimport OlMap from \"ol/Map\";\nimport { unByKey } from \"ol/Observable\";\nimport { EventsKey } from \"ol/events\";\nimport { getCenter } from \"ol/extent\";\nimport {\n ExtentConfig,\n Highlight,\n HighlightOptions,\n HighlightZoomOptions,\n MapModel,\n MapModelEvents\n} from \"../api\";\nimport { LayerCollectionImpl } from \"./LayerCollectionImpl\";\nimport { Geometry } from \"ol/geom\";\nimport { Highlights } from \"./Highlights\";\nimport { HttpService } from \"@open-pioneer/http\";\n\nconst LOG = createLogger(\"map:MapModel\");\n\n/**\n * Shared services or other entities propagated from the map model to all layer instances.\n */\nexport interface SharedDependencies {\n httpService: HttpService;\n}\n\nexport class MapModelImpl extends EventEmitter<MapModelEvents> implements MapModel {\n readonly #id: string;\n readonly #olMap: OlMap;\n readonly #layers = new LayerCollectionImpl(this);\n readonly #highlights: Highlights;\n readonly #sharedDeps: SharedDependencies;\n\n #destroyed = false;\n #container: HTMLElement | undefined;\n #initialExtent: ExtentConfig | undefined;\n #targetWatchKey: EventsKey | undefined;\n\n readonly #abortController = new AbortController();\n #displayStatus: \"waiting\" | \"ready\" | \"error\";\n #displayWaiter: ManualPromise<void> | undefined;\n\n constructor(properties: {\n id: string;\n olMap: OlMap;\n initialExtent: ExtentConfig | undefined;\n httpService: HttpService;\n }) {\n super();\n this.#id = properties.id;\n this.#olMap = properties.olMap;\n this.#initialExtent = properties.initialExtent;\n this.#sharedDeps = {\n httpService: properties.httpService\n };\n this.#highlights = new Highlights(this.#olMap);\n\n this.#displayStatus = \"waiting\";\n this.#initializeView().then(\n () => {\n this.#displayStatus = \"ready\";\n this.#displayWaiter?.resolve();\n this.#displayWaiter = undefined;\n },\n (error) => {\n if (!isAbortError(error)) {\n LOG.error(`Failed to initialize map`, error);\n }\n\n this.#displayStatus = \"error\";\n this.#displayWaiter?.reject(new Error(`Failed to initialize map.`));\n this.#displayWaiter = undefined;\n }\n );\n this.#targetWatchKey = this.#olMap.on(\"change:target\", () => {\n this.#onTargetChanged();\n });\n }\n\n destroy() {\n if (this.#destroyed) {\n return;\n }\n\n this.#destroyed = true;\n try {\n this.emit(\"destroy\");\n } catch (e) {\n LOG.warn(`Unexpected error from event listener during map model destruction:`, e);\n }\n\n if (this.#targetWatchKey) {\n unByKey(this.#targetWatchKey);\n }\n this.#targetWatchKey = undefined;\n this.#abortController.abort();\n this.#displayWaiter?.reject(new Error(\"Map model was destroyed.\"));\n this.#layers.destroy();\n this.#highlights.destroy();\n this.#olMap.dispose();\n }\n\n get id(): string {\n return this.#id;\n }\n\n get olMap(): OlMap {\n return this.#olMap;\n }\n\n get layers(): LayerCollectionImpl {\n return this.#layers;\n }\n\n get container(): HTMLElement | undefined {\n return this.#container;\n }\n\n get initialExtent(): ExtentConfig | undefined {\n return this.#initialExtent;\n }\n\n get __sharedDependencies(): SharedDependencies {\n return this.#sharedDeps;\n }\n\n highlight(geometries: Geometry[], options?: HighlightOptions | undefined): Highlight {\n return this.#highlights.addHighlight(geometries, options);\n }\n zoom(geometries: Geometry[], options?: HighlightZoomOptions | undefined): void {\n this.#highlights.zoomToHighlight(geometries, options);\n }\n\n highlightAndZoom(geometries: Geometry[], options?: HighlightZoomOptions) {\n return this.#highlights.addHighlightAndZoom(geometries, options ?? {});\n }\n\n removeHighlights() {\n this.#highlights.clearHighlight();\n }\n\n whenDisplayed(): Promise<void> {\n if (this.#destroyed) {\n return Promise.reject(new Error(\"Map model was destroyed.\"));\n }\n if (this.#displayStatus === \"error\") {\n return Promise.reject(new Error(`Failed to initialize map.`));\n }\n if (this.#displayStatus === \"ready\") {\n return Promise.resolve();\n }\n return (this.#displayWaiter ??= createManualPromise()).promise;\n }\n\n /**\n * Waits for the map to be displayed and then initializes the view (if necessary).\n *\n * May simply resolve when done, or throw an error when a problem occurs.\n * AbortError is thrown when cancelled via `this.#abortController`, for example\n * when the map model is destroyed before it has ever been displayed.\n */\n async #initializeView(): Promise<void> {\n try {\n await waitForMapSize(this.olMap, this.#abortController.signal); // may throw on cancel\n } catch (e) {\n if (isAbortError(e)) {\n throw e;\n }\n throw new Error(`Failed to wait for the map to be displayed.`, { cause: e });\n }\n\n try {\n const olMap = this.#olMap;\n const view = olMap.getView();\n\n if (this.#initialExtent) {\n // Initial extent was set from the outside. We simply ensure that it gets displayed by the map.\n const extent = this.#initialExtent;\n const olExtent = [extent.xMin, extent.yMin, extent.xMax, extent.yMax];\n\n const olCenter = getCenter(olExtent);\n const resolution = view.getResolutionForExtent(olExtent);\n LOG.debug(`Applying initial extent`, extent);\n LOG.debug(` Computed center:`, olCenter);\n LOG.debug(` Computed resolution:`, resolution);\n\n view.setCenter(olCenter);\n view.setResolution(resolution);\n } else {\n // Initial extent was NOT set from the outside.\n // We detect whatever the view is displaying and consider it to be the initial extent.\n const olExtent = view.calculateExtent();\n const [xMin = 0, yMin = 0, xMax = 0, yMax = 0] = olExtent;\n const extent: ExtentConfig = { xMin, yMin, xMax, yMax };\n LOG.debug(`Detected initial extent`, extent);\n\n this.#initialExtent = extent;\n this.emit(\"changed:initialExtent\");\n this.emit(\"changed\");\n }\n } catch (e) {\n throw new Error(`Failed to apply the initial extent.`, { cause: e });\n }\n }\n\n #onTargetChanged() {\n const newContainer: HTMLElement | undefined = this.#olMap.getTargetElement() ?? undefined;\n if (this.#container !== newContainer) {\n this.#container = newContainer;\n this.emit(\"changed:container\");\n this.emit(\"changed\");\n }\n }\n}\n\nfunction waitForMapSize(olMap: OlMap, signal: AbortSignal): Promise<void> {\n const promise = new Promise<void>((resolve, reject) => {\n let eventKey: EventsKey | undefined;\n\n function checkSize() {\n const currentSize = olMap.getSize() ?? [];\n const [width = 0, height = 0] = currentSize;\n if (currentSize && width > 0 && height > 0) {\n finish();\n }\n }\n\n function onAbort() {\n finish(createAbortError());\n }\n\n function finish(error?: Error | undefined) {\n if (eventKey) {\n unByKey(eventKey);\n eventKey = undefined;\n }\n signal.removeEventListener(\"abort\", onAbort);\n\n if (error) {\n reject(error);\n } else {\n resolve(wait(25)); // Give the map some time to render\n }\n }\n\n if (signal.aborted) {\n finish(createAbortError());\n return;\n }\n\n signal.addEventListener(\"abort\", onAbort);\n eventKey = olMap.on(\"change:size\", checkSize);\n });\n return promise;\n}\n\nfunction wait(milliseconds: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, milliseconds));\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"MapModelImpl.js","sources":["MapModelImpl.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { computed, reactive, ReadonlyReactive, synchronized } from \"@conterra/reactivity-core\";\nimport {\n createAbortError,\n createLogger,\n createManualPromise,\n EventEmitter,\n isAbortError,\n ManualPromise\n} from \"@open-pioneer/core\";\nimport { HttpService } from \"@open-pioneer/http\";\nimport OlMap from \"ol/Map\";\nimport { unByKey } from \"ol/Observable\";\nimport OlView from \"ol/View\";\nimport { Coordinate } from \"ol/coordinate\";\nimport { EventsKey } from \"ol/events\";\nimport { getCenter } from \"ol/extent\";\nimport { Geometry } from \"ol/geom\";\nimport { getPointResolution, Projection } from \"ol/proj\";\nimport {\n ExtentConfig,\n Highlight,\n HighlightOptions,\n HighlightZoomOptions,\n MapModel,\n MapModelEvents\n} from \"../api\";\nimport { Highlights } from \"./Highlights\";\nimport { LayerCollectionImpl } from \"./LayerCollectionImpl\";\n\nconst LOG = createLogger(\"map:MapModel\");\n\nconst DEFAULT_DPI = 25.4 / 0.28;\nconst INCHES_PER_METRE = 39.37;\n\n/**\n * Shared services or other entities propagated from the map model to all layer instances.\n */\nexport interface SharedDependencies {\n httpService: HttpService;\n}\n\nexport class MapModelImpl extends EventEmitter<MapModelEvents> implements MapModel {\n readonly #id: string;\n readonly #olMap: OlMap;\n readonly #olView: ReadonlyReactive<OlView>;\n readonly #layers = new LayerCollectionImpl(this);\n readonly #highlights: Highlights;\n readonly #sharedDeps: SharedDependencies;\n\n #destroyed = false;\n #container: ReadonlyReactive<HTMLElement | undefined>;\n #initialExtent = reactive<ExtentConfig>();\n #viewBindings: ReadonlyReactive<ViewBindings>;\n #scale: ReadonlyReactive<number | undefined>;\n\n readonly #abortController = new AbortController();\n #displayStatus: \"waiting\" | \"ready\" | \"error\";\n #displayWaiter: ManualPromise<void> | undefined;\n\n constructor(properties: {\n id: string;\n olMap: OlMap;\n initialExtent: ExtentConfig | undefined;\n httpService: HttpService;\n }) {\n super();\n this.#id = properties.id;\n this.#olMap = properties.olMap;\n this.#olView = synchronized(\n () => this.#olMap.getView(),\n (cb) => {\n const key = this.#olMap.on(\"change:view\", cb);\n return () => unByKey(key);\n }\n );\n this.#initialExtent.value = properties.initialExtent;\n this.#sharedDeps = {\n httpService: properties.httpService\n };\n this.#highlights = new Highlights(this.#olMap);\n\n this.#displayStatus = \"waiting\";\n this.#initializeView().then(\n () => {\n this.#displayStatus = \"ready\";\n this.#displayWaiter?.resolve();\n this.#displayWaiter = undefined;\n },\n (error) => {\n if (!isAbortError(error)) {\n LOG.error(`Failed to initialize map`, error);\n }\n\n this.#displayStatus = \"error\";\n this.#displayWaiter?.reject(new Error(`Failed to initialize map.`));\n this.#displayWaiter = undefined;\n }\n );\n\n this.#container = synchronized(\n () => this.#olMap.getTargetElement() ?? undefined,\n (cb) => {\n const key = this.#olMap.on(\"change:target\", cb);\n return () => unByKey(key);\n }\n );\n\n this.#viewBindings = computed(() => createViewBindings(this.#olView.value));\n this.#scale = computed(() => {\n const { projection, resolution, center } = this;\n if (projection == null || resolution == null || center == null) {\n return undefined;\n }\n\n /**\n * Returns the appropriate scale for the given resolution and units, see OpenLayers function getScaleForResolution()\n * https://github.com/openlayers/openlayers/blob/7fa9df03431e9e1bc517e6c414565d9f848a3132/src/ol/control/ScaleLine.js#L454C3-L454C24\n */\n const pointResolution = getPointResolution(projection, resolution, center);\n const scale = Math.round(pointResolution * INCHES_PER_METRE * DEFAULT_DPI);\n return scale;\n });\n }\n\n destroy() {\n if (this.#destroyed) {\n return;\n }\n\n this.#destroyed = true;\n try {\n this.emit(\"destroy\");\n } catch (e) {\n LOG.warn(`Unexpected error from event listener during map model destruction:`, e);\n }\n\n this.#abortController.abort();\n this.#displayWaiter?.reject(new Error(\"Map model was destroyed.\"));\n this.#layers.destroy();\n this.#highlights.destroy();\n this.#olMap.dispose();\n }\n\n get id(): string {\n return this.#id;\n }\n\n get olMap(): OlMap {\n return this.#olMap;\n }\n\n get olView(): OlView {\n return this.#olView.value;\n }\n\n get projection(): Projection {\n return this.#viewBindings.value.projection;\n }\n\n get center(): Coordinate | undefined {\n return this.#viewBindings.value.center.value;\n }\n\n get resolution(): number | undefined {\n return this.#viewBindings.value.resolution.value;\n }\n\n get zoomLevel(): number | undefined {\n return this.#viewBindings.value.zoom.value;\n }\n\n get scale(): number | undefined {\n return this.#scale.value;\n }\n\n get layers(): LayerCollectionImpl {\n return this.#layers;\n }\n\n get container(): HTMLElement | undefined {\n return this.#container.value;\n }\n\n get initialExtent(): ExtentConfig | undefined {\n return this.#initialExtent.value;\n }\n\n get __sharedDependencies(): SharedDependencies {\n return this.#sharedDeps;\n }\n\n setScale(newScale: number): void {\n const view = this.olView;\n const projection = this.projection;\n const center = this.center;\n if (!center) {\n return;\n }\n\n const mpu = projection.getMetersPerUnit() ?? 1;\n const resolution = INCHES_PER_METRE * DEFAULT_DPI * mpu;\n const pointResolution = newScale / getPointResolution(projection, resolution, center);\n view.setResolution(pointResolution);\n }\n\n highlight(geometries: Geometry[], options?: HighlightOptions | undefined): Highlight {\n return this.#highlights.addHighlight(geometries, options);\n }\n\n zoom(geometries: Geometry[], options?: HighlightZoomOptions | undefined): void {\n this.#highlights.zoomToHighlight(geometries, options);\n }\n\n highlightAndZoom(geometries: Geometry[], options?: HighlightZoomOptions) {\n return this.#highlights.addHighlightAndZoom(geometries, options ?? {});\n }\n\n removeHighlights() {\n this.#highlights.clearHighlight();\n }\n\n whenDisplayed(): Promise<void> {\n if (this.#destroyed) {\n return Promise.reject(new Error(\"Map model was destroyed.\"));\n }\n if (this.#displayStatus === \"error\") {\n return Promise.reject(new Error(`Failed to initialize map.`));\n }\n if (this.#displayStatus === \"ready\") {\n return Promise.resolve();\n }\n return (this.#displayWaiter ??= createManualPromise()).promise;\n }\n\n /**\n * Waits for the map to be displayed and then initializes the view (if necessary).\n *\n * May simply resolve when done, or throw an error when a problem occurs.\n * AbortError is thrown when cancelled via `this.#abortController`, for example\n * when the map model is destroyed before it has ever been displayed.\n */\n async #initializeView(): Promise<void> {\n try {\n await waitForMapSize(this.olMap, this.#abortController.signal); // may throw on cancel\n } catch (e) {\n if (isAbortError(e)) {\n throw e;\n }\n throw new Error(`Failed to wait for the map to be displayed.`, { cause: e });\n }\n\n try {\n const olMap = this.#olMap;\n const view = olMap.getView();\n\n if (this.#initialExtent.value) {\n // Initial extent was set from the outside. We simply ensure that it gets displayed by the map.\n const extent = this.#initialExtent.value;\n const olExtent = [extent.xMin, extent.yMin, extent.xMax, extent.yMax];\n\n const olCenter = getCenter(olExtent);\n const resolution = view.getResolutionForExtent(olExtent);\n LOG.debug(`Applying initial extent`, extent);\n LOG.debug(` Computed center:`, olCenter);\n LOG.debug(` Computed resolution:`, resolution);\n\n view.setCenter(olCenter);\n view.setResolution(resolution);\n } else {\n // Initial extent was NOT set from the outside.\n // We detect whatever the view is displaying and consider it to be the initial extent.\n const olExtent = view.calculateExtent();\n const [xMin = 0, yMin = 0, xMax = 0, yMax = 0] = olExtent;\n const extent: ExtentConfig = { xMin, yMin, xMax, yMax };\n LOG.debug(`Detected initial extent`, extent);\n\n this.#initialExtent.value = extent;\n }\n } catch (e) {\n throw new Error(`Failed to apply the initial extent.`, { cause: e });\n }\n }\n}\n\ninterface ViewBindings {\n resolution: ReadonlyReactive<number | undefined>;\n center: ReadonlyReactive<Coordinate | undefined>;\n zoom: ReadonlyReactive<number | undefined>;\n projection: Projection; // not reactive (change view to change projection)\n}\n\nfunction createViewBindings(view: OlView): ViewBindings {\n return {\n resolution: synchronized(\n () => view.getResolution(),\n (cb) => {\n const key = view.on(\"change:resolution\", cb);\n return () => unByKey(key);\n }\n ),\n center: synchronized(\n () => view.getCenter(),\n (cb) => {\n const key = view.on(\"change:center\", cb);\n return () => unByKey(key);\n }\n ),\n zoom: synchronized(\n () => view.getZoom(),\n (cb) => {\n const key = view.on(\"change:resolution\", cb);\n return () => unByKey(key);\n }\n ),\n projection: view.getProjection()\n };\n}\n\nfunction waitForMapSize(olMap: OlMap, signal: AbortSignal): Promise<void> {\n const promise = new Promise<void>((resolve, reject) => {\n let eventKey: EventsKey | undefined;\n\n function checkSize() {\n const currentSize = olMap.getSize() ?? [];\n const [width = 0, height = 0] = currentSize;\n if (currentSize && width > 0 && height > 0) {\n finish();\n }\n }\n\n function onAbort() {\n finish(createAbortError());\n }\n\n function finish(error?: Error | undefined) {\n if (eventKey) {\n unByKey(eventKey);\n eventKey = undefined;\n }\n signal.removeEventListener(\"abort\", onAbort);\n\n if (error) {\n reject(error);\n } else {\n resolve(wait(25)); // Give the map some time to render\n }\n }\n\n if (signal.aborted) {\n finish(createAbortError());\n return;\n }\n\n signal.addEventListener(\"abort\", onAbort);\n eventKey = olMap.on(\"change:size\", checkSize);\n });\n return promise;\n}\n\nfunction wait(milliseconds: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, milliseconds));\n}\n"],"names":[],"mappings":"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"}
@@ -1,10 +1,13 @@
1
- import { EventEmitter } from "@open-pioneer/core";
2
- import { LayerRetrievalOptions, SublayerBaseType, SublayersCollection, SublayersCollectionEvents } from "../api";
1
+ import { LayerRetrievalOptions, SublayerBaseType, SublayersCollection } from "../api";
3
2
  import { AbstractLayerBase } from "./AbstractLayerBase";
4
- export declare class SublayersCollectionImpl<Sublayer extends SublayerBaseType & AbstractLayerBase> extends EventEmitter<SublayersCollectionEvents> implements SublayersCollection<Sublayer> {
3
+ /**
4
+ * Manages the sublayers of a layer.
5
+ */
6
+ export declare class SublayersCollectionImpl<Sublayer extends SublayerBaseType & AbstractLayerBase> implements SublayersCollection<Sublayer> {
5
7
  #private;
6
8
  constructor(sublayers: Sublayer[]);
7
9
  destroy(): void;
10
+ getItems(options?: LayerRetrievalOptions): Sublayer[];
8
11
  getSublayers(_options?: LayerRetrievalOptions | undefined): Sublayer[];
9
12
  /**
10
13
  * Returns a reference to the internal sublayers array.
@@ -1,9 +1,7 @@
1
- import { EventEmitter } from '@open-pioneer/core';
2
-
3
- class SublayersCollectionImpl extends EventEmitter {
1
+ class SublayersCollectionImpl {
2
+ /* eslint-enable indent */
4
3
  #sublayers;
5
4
  constructor(sublayers) {
6
- super();
7
5
  this.#sublayers = sublayers;
8
6
  }
9
7
  destroy() {
@@ -12,6 +10,10 @@ class SublayersCollectionImpl extends EventEmitter {
12
10
  }
13
11
  this.#sublayers = [];
14
12
  }
13
+ // Generic method name for consistent interface
14
+ getItems(options) {
15
+ return this.getSublayers(options);
16
+ }
15
17
  getSublayers(_options) {
16
18
  return this.#sublayers.slice();
17
19
  }
@@ -1 +1 @@
1
- {"version":3,"file":"SublayersCollectionImpl.js","sources":["SublayersCollectionImpl.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { EventEmitter } from \"@open-pioneer/core\";\nimport {\n LayerRetrievalOptions,\n SublayerBaseType,\n SublayersCollection,\n SublayersCollectionEvents\n} from \"../api\";\nimport { AbstractLayerBase } from \"./AbstractLayerBase\";\n\n// NOTE: adding / removing sublayers currently not supported\nexport class SublayersCollectionImpl<Sublayer extends SublayerBaseType & AbstractLayerBase>\n extends EventEmitter<SublayersCollectionEvents>\n implements SublayersCollection<Sublayer>\n{\n #sublayers: Sublayer[];\n\n constructor(sublayers: Sublayer[]) {\n super();\n this.#sublayers = sublayers;\n }\n\n destroy() {\n for (const layer of this.#sublayers) {\n layer.destroy();\n }\n this.#sublayers = [];\n }\n\n getSublayers(_options?: LayerRetrievalOptions | undefined): Sublayer[] {\n // NOTE: options are ignored because layers are always ordered at this time.\n return this.#sublayers.slice();\n }\n\n /**\n * Returns a reference to the internal sublayers array.\n *\n * NOTE: Do not modify directly!\n */\n __getRawSublayers(): Sublayer[] {\n return this.#sublayers;\n }\n}\n"],"names":[],"mappings":";;AAYO,MAAM,gCACD,YAEZ,CAAA;AAAA,EACI,UAAA,CAAA;AAAA,EAEA,YAAY,SAAuB,EAAA;AAC/B,IAAM,KAAA,EAAA,CAAA;AACN,IAAA,IAAA,CAAK,UAAa,GAAA,SAAA,CAAA;AAAA,GACtB;AAAA,EAEA,OAAU,GAAA;AACN,IAAW,KAAA,MAAA,KAAA,IAAS,KAAK,UAAY,EAAA;AACjC,MAAA,KAAA,CAAM,OAAQ,EAAA,CAAA;AAAA,KAClB;AACA,IAAA,IAAA,CAAK,aAAa,EAAC,CAAA;AAAA,GACvB;AAAA,EAEA,aAAa,QAA0D,EAAA;AAEnE,IAAO,OAAA,IAAA,CAAK,WAAW,KAAM,EAAA,CAAA;AAAA,GACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,iBAAgC,GAAA;AAC5B,IAAA,OAAO,IAAK,CAAA,UAAA,CAAA;AAAA,GAChB;AACJ;;;;"}
1
+ {"version":3,"file":"SublayersCollectionImpl.js","sources":["SublayersCollectionImpl.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { LayerRetrievalOptions, SublayerBaseType, SublayersCollection } from \"../api\";\nimport { AbstractLayerBase } from \"./AbstractLayerBase\";\n\n/**\n * Manages the sublayers of a layer.\n */\n// NOTE: adding / removing sublayers currently not supported\n/* eslint-disable indent */\nexport class SublayersCollectionImpl<Sublayer extends SublayerBaseType & AbstractLayerBase>\n implements SublayersCollection<Sublayer>\n{\n /* eslint-enable indent */\n #sublayers: Sublayer[];\n\n constructor(sublayers: Sublayer[]) {\n this.#sublayers = sublayers;\n }\n\n destroy() {\n for (const layer of this.#sublayers) {\n layer.destroy();\n }\n this.#sublayers = [];\n }\n\n // Generic method name for consistent interface\n getItems(options?: LayerRetrievalOptions): Sublayer[] {\n return this.getSublayers(options);\n }\n\n getSublayers(_options?: LayerRetrievalOptions | undefined): Sublayer[] {\n // NOTE: options are ignored because layers are always ordered at this time.\n return this.#sublayers.slice();\n }\n\n /**\n * Returns a reference to the internal sublayers array.\n *\n * NOTE: Do not modify directly!\n */\n __getRawSublayers(): Sublayer[] {\n return this.#sublayers;\n }\n}\n"],"names":[],"mappings":"AAUO,MAAM,uBAEb,CAAA;AAAA;AAAA,EAEI,UAAA,CAAA;AAAA,EAEA,YAAY,SAAuB,EAAA;AAC/B,IAAA,IAAA,CAAK,UAAa,GAAA,SAAA,CAAA;AAAA,GACtB;AAAA,EAEA,OAAU,GAAA;AACN,IAAW,KAAA,MAAA,KAAA,IAAS,KAAK,UAAY,EAAA;AACjC,MAAA,KAAA,CAAM,OAAQ,EAAA,CAAA;AAAA,KAClB;AACA,IAAA,IAAA,CAAK,aAAa,EAAC,CAAA;AAAA,GACvB;AAAA;AAAA,EAGA,SAAS,OAA6C,EAAA;AAClD,IAAO,OAAA,IAAA,CAAK,aAAa,OAAO,CAAA,CAAA;AAAA,GACpC;AAAA,EAEA,aAAa,QAA0D,EAAA;AAEnE,IAAO,OAAA,IAAA,CAAK,WAAW,KAAM,EAAA,CAAA;AAAA,GACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,iBAAgC,GAAA;AAC5B,IAAA,OAAO,IAAK,CAAA,UAAA,CAAA;AAAA,GAChB;AACJ;;;;"}