Add a map property to layers

This commit is contained in:
Tim Schaub
2021-11-12 17:11:26 -07:00
parent 080fe8ca67
commit 371bb85350
7 changed files with 446 additions and 24 deletions

View File

@@ -5,7 +5,8 @@ import BaseObject from './Object.js';
import Collection from './Collection.js';
import CollectionEventType from './CollectionEventType.js';
import EventType from './events/EventType.js';
import LayerGroup from './layer/Group.js';
import Layer from './layer/Layer.js';
import LayerGroup, {GroupEvent} from './layer/Group.js';
import MapBrowserEvent from './MapBrowserEvent.js';
import MapBrowserEventHandler from './MapBrowserEventHandler.js';
import MapBrowserEventType from './MapBrowserEventType.js';
@@ -143,6 +144,36 @@ import {removeNode} from './dom.js';
* {@link module:ol/Map~Map#setView}.
*/
/**
* @param {import("./layer/Base.js").default} layer Layer.
*/
function removeLayerMapProperty(layer) {
if (layer instanceof Layer) {
layer.setMapInternal(null);
return;
}
if (layer instanceof LayerGroup) {
layer.getLayers().forEach(removeLayerMapProperty);
}
}
/**
* @param {import("./layer/Base.js").default} layer Layer.
* @param {PluggableMap} map Map.
*/
function setLayerMapProperty(layer, map) {
if (layer instanceof Layer) {
layer.setMapInternal(map);
return;
}
if (layer instanceof LayerGroup) {
const layers = layer.getLayers().getArray();
for (let i = 0, ii = layers.length; i < ii; ++i) {
setLayerMapProperty(layers[i], map);
}
}
}
/**
* @fires import("./MapBrowserEvent.js").MapBrowserEvent
* @fires import("./MapEvent.js").MapEvent
@@ -524,6 +555,14 @@ class PluggableMap extends BaseObject {
layers.push(layer);
}
/**
* @param {import("./layer/Group.js").GroupEvent} event The layer add event.
* @private
*/
handleLayerAdd_(event) {
setLayerMapProperty(event.layer, this);
}
/**
* Add the given overlay to the map.
* @param {import("./Overlay.js").default} overlay Overlay.
@@ -1287,9 +1326,12 @@ class PluggableMap extends BaseObject {
}
const layerGroup = this.getLayerGroup();
if (layerGroup) {
this.handleLayerAdd_(new GroupEvent('addlayer', layerGroup));
this.layerGroupPropertyListenerKeys_ = [
listen(layerGroup, ObjectEventType.PROPERTYCHANGE, this.render, this),
listen(layerGroup, EventType.CHANGE, this.render, this),
listen(layerGroup, 'addlayer', this.handleLayerAdd_, this),
listen(layerGroup, 'removelayer', this.handleLayerRemove_, this),
];
}
this.render();
@@ -1370,6 +1412,14 @@ class PluggableMap extends BaseObject {
return layers.remove(layer);
}
/**
* @param {import("./layer/Group.js").GroupEvent} event The layer remove event.
* @private
*/
handleLayerRemove_(event) {
removeLayerMapProperty(event.layer);
}
/**
* Remove the given overlay from the map.
* @param {import("./Overlay.js").default} overlay Overlay.
@@ -1490,6 +1540,10 @@ class PluggableMap extends BaseObject {
* @api
*/
setLayerGroup(layerGroup) {
const oldLayerGroup = this.getLayerGroup();
if (oldLayerGroup) {
this.handleLayerRemove_(new GroupEvent('removelayer', oldLayerGroup));
}
this.set(MapProperty.LAYERGROUP, layerGroup);
}

View File

@@ -4,6 +4,7 @@
import BaseLayer from './Base.js';
import Collection from '../Collection.js';
import CollectionEventType from '../CollectionEventType.js';
import Event from '../events/Event.js';
import EventType from '../events/EventType.js';
import ObjectEventType from '../ObjectEventType.js';
import SourceState from '../source/State.js';
@@ -13,6 +14,33 @@ import {getIntersection} from '../extent.js';
import {getUid} from '../util.js';
import {listen, unlistenByKey} from '../events.js';
/**
* @typedef {'addlayer'|'removelayer'} EventType
*/
/**
* @classdesc
* A layer group triggers 'addlayer' and 'removelayer' events when layers are added to or removed from
* the group or one of its child groups. When a layer group is added to or removed from another layer group,
* a single event will be triggered (instead of one per layer in the group added or removed).
*/
export class GroupEvent extends Event {
/**
* @param {EventType} type The event type.
* @param {BaseLayer} layer The layer.
*/
constructor(type, layer) {
super(type);
/**
* The added or removed layer.
* @type {BaseLayer}
* @api
*/
this.layer = layer;
}
}
/***
* @template Return
* @typedef {import("../Observable").OnSignature<import("../Observable").EventTypes, import("../events/Event.js").default, Return> &
@@ -142,18 +170,48 @@ class LayerGroup extends BaseLayer {
const layersArray = layers.getArray();
for (let i = 0, ii = layersArray.length; i < ii; i++) {
const layer = layersArray[i];
this.listenerKeys_[getUid(layer)] = [
listen(
layer,
ObjectEventType.PROPERTYCHANGE,
this.handleLayerChange_,
this
),
listen(layer, EventType.CHANGE, this.handleLayerChange_, this),
];
this.registerLayerListeners_(layer);
this.dispatchEvent(new GroupEvent('addlayer', layer));
}
this.changed();
}
/**
* @param {BaseLayer} layer The layer.
*/
registerLayerListeners_(layer) {
const listenerKeys = [
listen(
layer,
ObjectEventType.PROPERTYCHANGE,
this.handleLayerChange_,
this
),
listen(layer, EventType.CHANGE, this.handleLayerChange_, this),
];
if (layer instanceof LayerGroup) {
listenerKeys.push(
listen(layer, 'addlayer', this.handleLayerGroupAdd_, this),
listen(layer, 'removelayer', this.handleLayerGroupRemove_, this)
);
}
this.changed();
this.listenerKeys_[getUid(layer)] = listenerKeys;
}
/**
* @param {GroupEvent} event The layer group event.
*/
handleLayerGroupAdd_(event) {
this.dispatchEvent(new GroupEvent('addlayer', event.layer));
}
/**
* @param {GroupEvent} event The layer group event.
*/
handleLayerGroupRemove_(event) {
this.dispatchEvent(new GroupEvent('removelayer', event.layer));
}
/**
@@ -164,15 +222,8 @@ class LayerGroup extends BaseLayer {
const layer = /** @type {import("./Base.js").default} */ (
collectionEvent.element
);
this.listenerKeys_[getUid(layer)] = [
listen(
layer,
ObjectEventType.PROPERTYCHANGE,
this.handleLayerChange_,
this
),
listen(layer, EventType.CHANGE, this.handleLayerChange_, this),
];
this.registerLayerListeners_(layer);
this.dispatchEvent(new GroupEvent('addlayer', layer));
this.changed();
}
@@ -187,6 +238,7 @@ class LayerGroup extends BaseLayer {
const key = getUid(layer);
this.listenerKeys_[key].forEach(unlistenByKey);
delete this.listenerKeys_[key];
this.dispatchEvent(new GroupEvent('removelayer', layer));
this.changed();
}
@@ -213,6 +265,14 @@ class LayerGroup extends BaseLayer {
* @api
*/
setLayers(layers) {
const collection = this.getLayers();
if (collection) {
const currentLayers = collection.getArray();
for (let i = 0, ii = currentLayers.length; i < ii; ++i) {
this.dispatchEvent(new GroupEvent('removelayer', currentLayers[i]));
}
}
this.set(Property.LAYERS, layers);
}

View File

@@ -258,6 +258,22 @@ class Layer extends BaseLayer {
}
}
/**
* For use inside the library only.
* @param {import("../PluggableMap.js").default} map Map.
*/
setMapInternal(map) {
this.set(LayerProperty.MAP, map);
}
/**
* For use inside the library only.
* @return {import("../PluggableMap.js").default} Map.
*/
getMapInternal() {
return this.get(LayerProperty.MAP);
}
/**
* Sets the layer to be rendered on top of other layers on a map. The map will
* not manage this layer in its layers collection, and the callback in

View File

@@ -15,4 +15,5 @@ export default {
MAX_ZOOM: 'maxZoom',
MIN_ZOOM: 'minZoom',
SOURCE: 'source',
MAP: 'map',
};