From 4f7cadd17dcad91f25265d8cd6ed7253b4979eec Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Tue, 21 Dec 2021 08:23:56 +0100 Subject: [PATCH] Add layer also for programmatically selected features --- src/ol/PluggableMap.js | 19 ++++++++++++ src/ol/interaction/Select.js | 29 +++++++++++++++---- test/browser/spec/ol/Map.test.js | 13 +++++++++ .../spec/ol/interaction/select.test.js | 7 +++++ 4 files changed, 62 insertions(+), 6 deletions(-) diff --git a/src/ol/PluggableMap.js b/src/ol/PluggableMap.js index d671e9cad8..a880582890 100644 --- a/src/ol/PluggableMap.js +++ b/src/ol/PluggableMap.js @@ -664,6 +664,25 @@ class PluggableMap extends BaseObject { return features; } + /** + * Get all layers from all layer groups. + * @return {Array} Layers. + */ + getAllLayers() { + const layers = []; + function addLayersFrom(layerGroup) { + layerGroup.forEach(function (layer) { + if (layer instanceof LayerGroup) { + addLayersFrom(layer.getLayers()); + } else { + layers.push(layer); + } + }); + } + addLayersFrom(this.getLayers()); + return layers; + } + /** * Detect layers that have a color value at a pixel on the viewport, and * execute a callback with each matching layer. Layers included in the diff --git a/src/ol/interaction/Select.js b/src/ol/interaction/Select.js index 6376207034..8436cd1ff5 100644 --- a/src/ol/interaction/Select.js +++ b/src/ol/interaction/Select.js @@ -6,6 +6,7 @@ import CollectionEventType from '../CollectionEventType.js'; import Event from '../events/Event.js'; import GeometryType from '../geom/GeometryType.js'; import Interaction from './Interaction.js'; +import VectorLayer from '../layer/Vector.js'; import {TRUE} from '../functions.js'; import {clear} from '../obj.js'; import {createEditingStyle} from '../style/Style.js'; @@ -308,10 +309,8 @@ class Select extends Interaction { } /** - * Returns the associated {@link module:ol/layer/Vector~Vector vectorlayer} of - * the (last) selected feature. Note that this will not work with any - * programmatic method like pushing features to - * {@link module:ol/interaction/Select~Select#getFeatures collection}. + * Returns the associated {@link module:ol/layer/Vector~Vector vector layer} of + * a selected feature. * @param {import("../Feature.js").FeatureLike} feature Feature * @return {import('../layer/Vector.js').default} Layer. * @api @@ -378,6 +377,24 @@ class Select extends Interaction { if (this.style_) { this.applySelectedStyle_(feature); } + if (!this.getLayer(feature)) { + const layer = /** @type {VectorLayer} */ ( + this.getMap() + .getAllLayers() + .find(function (layer) { + if ( + layer instanceof VectorLayer && + layer.getSource() && + layer.getSource().hasFeature(feature) + ) { + return layer; + } + }) + ); + if (layer) { + this.addFeatureLayerAssociation_(feature, layer); + } + } } /** @@ -475,8 +492,8 @@ class Select extends Interaction { */ function (feature, layer) { if (this.filter_(feature, layer)) { - selected.push(feature); this.addFeatureLayerAssociation_(feature, layer); + selected.push(feature); return !this.multi_; } }.bind(this), @@ -511,8 +528,8 @@ class Select extends Interaction { function (feature, layer) { if (this.filter_(feature, layer)) { if ((add || toggle) && !includes(features.getArray(), feature)) { - selected.push(feature); this.addFeatureLayerAssociation_(feature, layer); + selected.push(feature); } else if ( (remove || toggle) && includes(features.getArray(), feature) diff --git a/test/browser/spec/ol/Map.test.js b/test/browser/spec/ol/Map.test.js index 04c3595a3b..505d12570d 100644 --- a/test/browser/spec/ol/Map.test.js +++ b/test/browser/spec/ol/Map.test.js @@ -233,6 +233,19 @@ describe('ol/Map', function () { }); }); + describe('#getAllLayers()', function () { + it('returns all layers, also from inside groups', function () { + const map = new Map({}); + const layer = new TileLayer(); + const group = new LayerGroup({layers: [layer]}); + map.addLayer(group); + + const allLayers = map.getAllLayers(); + expect(allLayers.length).to.be(1); + expect(allLayers[0]).to.be(layer); + }); + }); + describe('#setLayers()', function () { it('adds an array of layers to the map', function () { const map = new Map({}); diff --git a/test/browser/spec/ol/interaction/select.test.js b/test/browser/spec/ol/interaction/select.test.js index a9fc7b310f..4d56fd069f 100644 --- a/test/browser/spec/ol/interaction/select.test.js +++ b/test/browser/spec/ol/interaction/select.test.js @@ -375,6 +375,13 @@ describe('ol.interaction.Select', function () { // Select again to make sure the style change does not break selection simulateEvent('singleclick', 10, -20); }); + + it('returns a layer from a programmatically selected feature', function () { + const feature = source.getFeatures()[0]; + interaction.getFeatures().push(feature); + const layerWithSelectedFeature = interaction.getLayer(feature); + expect(layerWithSelectedFeature).to.equal(layer); + }); }); describe('#setActive()', function () {