Do not use a temporary layer for selected features

This commit is contained in:
ahocevar
2013-11-09 14:07:08 +01:00
parent 9fca2c407d
commit d9fd459654
2 changed files with 30 additions and 92 deletions

View File

@@ -1,14 +1,12 @@
goog.provide('ol.interaction.Select');
goog.require('goog.array');
goog.require('goog.object');
goog.require('ol.Feature');
goog.require('ol.events.ConditionType');
goog.require('ol.events.condition');
goog.require('ol.interaction.Interaction');
goog.require('ol.layer.Vector');
goog.require('ol.layer.VectorLayerRenderIntent');
goog.require('ol.source.Vector');
@@ -36,20 +34,6 @@ ol.interaction.Select = function(opt_options) {
this.addCondition_ = goog.isDef(options.addCondition) ?
options.addCondition : ol.events.condition.shiftKeyOnly;
/**
* Mapping between original features and cloned features on selection layers.
* @type {Object.<*,Object.<*,ol.Feature>>}
* @private
*/
this.featureMap_ = {};
/**
* Mapping between original layers and selection layers, by map.
* @type {Object.<*,{map:ol.Map,layers:Object.<*,ol.layer.Vector>}>}
* @protected
*/
this.selectionLayers = {};
/**
* @type {null|function(ol.layer.Layer):boolean}
* @private
@@ -99,77 +83,34 @@ ol.interaction.Select.prototype.handleMapBrowserEvent =
*/
ol.interaction.Select.prototype.select =
function(map, featuresByLayer, layers, clear) {
var mapId = goog.getUid(map);
if (!(mapId in this.selectionLayers)) {
this.selectionLayers[mapId] = {map: map, layers: {}};
}
for (var i = 0, ii = featuresByLayer.length; i < ii; ++i) {
var layer = layers[i];
var layerId = goog.getUid(layer);
var selectionLayer = this.selectionLayers[mapId].layers[layerId];
if (!goog.isDef(selectionLayer)) {
selectionLayer = new ol.layer.Vector({
source: new ol.source.Vector({parser: null}),
style: layer instanceof ol.layer.Vector ? layer.getStyle() : null
});
selectionLayer.setTemporary(true);
map.addLayer(selectionLayer);
this.selectionLayers[mapId].layers[layerId] = selectionLayer;
this.featureMap_[layerId] = {};
}
var selectedFeatures, unselectedFeatures;
selectedFeatures = [];
unselectedFeatures = [];
var features = featuresByLayer[i];
var numFeatures = features.length;
var featuresToAdd = [];
var featuresToRemove = [];
var featureMap = this.featureMap_[layerId];
var oldFeatureMap = featureMap;
var featuresToSelect = featuresByLayer[i];
var selectedFeatures = layer.getFeatures(this.selectedFeaturesFilter);
if (clear) {
for (var f in featureMap) {
unselectedFeatures.push(layer.getFeatureWithUid(f));
featuresToRemove.push(featureMap[f]);
}
featureMap = {};
this.featureMap_[layerId] = featureMap;
}
for (var j = 0; j < numFeatures; ++j) {
var feature = features[j];
var featureId = goog.getUid(feature);
var clone = featureMap[featureId];
if (clone) {
// TODO: make toggle configurable
unselectedFeatures.push(feature);
delete featureMap[featureId];
featuresToRemove.push(clone);
} else if (!(featureId in oldFeatureMap)) {
clone = new ol.Feature(feature.getAttributes());
clone.setGeometry(feature.getGeometry().clone());
clone.setId(feature.getId());
clone.setSymbolizers(feature.getSymbolizers());
clone.renderIntent = ol.layer.VectorLayerRenderIntent.SELECTED;
featureMap[featureId] = clone;
selectedFeatures.push(feature);
featuresToAdd.push(clone);
for (var j = selectedFeatures.length - 1; j >= 0; --j) {
selectedFeatures[j].setRenderIntent(
ol.layer.VectorLayerRenderIntent.DEFAULT);
}
}
for (var j = selectedFeatures.length - 1; j >= 0; --j) {
selectedFeatures[j].setRenderIntent(
ol.layer.VectorLayerRenderIntent.HIDDEN);
}
for (var j = unselectedFeatures.length - 1; j >= 0; --j) {
unselectedFeatures[j].setRenderIntent(
ol.layer.VectorLayerRenderIntent.DEFAULT);
}
selectionLayer.removeFeatures(featuresToRemove);
selectionLayer.addFeatures(featuresToAdd);
if (goog.object.getCount(featureMap) == 0) {
map.removeLayer(selectionLayer);
delete this.selectionLayers[mapId].layers[layerId];
delete this.featureMap_[layerId];
for (var j = featuresToSelect.length - 1; j >= 0; --j) {
var feature = featuresToSelect[j];
// TODO: Make toggle configurable
feature.setRenderIntent(
feature.renderIntent == ol.layer.VectorLayerRenderIntent.SELECTED ?
ol.layer.VectorLayerRenderIntent.DEFAULT :
ol.layer.VectorLayerRenderIntent.SELECTED);
}
// TODO: Dispatch an event with selectedFeatures and unselectedFeatures
}
};
/**
* @param {ol.Feature} feature Feature.
* @return {boolean} Whether the feature is selected.
*/
ol.interaction.Select.prototype.selectedFeaturesFilter = function(feature) {
return feature.renderIntent == ol.layer.VectorLayerRenderIntent.SELECTED;
};

View File

@@ -46,29 +46,27 @@ describe('ol.interaction.Select', function() {
describe('#select', function() {
var selectedFeaturesFilter = function(feature) {
return feature.renderIntent == 'selected';
};
it('toggles selection of features', function() {
select.select(map, [features], [vector]);
var layer = select.selectionLayers[goog.getUid(map)]
.layers[goog.getUid(vector)];
expect(goog.object.getCount(layer.featureCache_.idLookup_)).to.be(2);
expect(vector.getFeatures(selectedFeaturesFilter).length).to.be(2);
select.select(map, [features], [vector]);
expect(goog.object.getCount(layer.featureCache_.idLookup_)).to.be(0);
expect(vector.getFeatures(selectedFeaturesFilter).length).to.be(0);
});
it('can append features to an existing selection', function() {
select.select(map, [[features[0]]], [vector]);
select.select(map, [[features[0]]], [vector], true);
select.select(map, [[features[1]]], [vector]);
var layer = select.selectionLayers[goog.getUid(map)]
.layers[goog.getUid(vector)];
expect(goog.object.getCount(layer.featureCache_.idLookup_)).to.be(2);
expect(vector.getFeatures(selectedFeaturesFilter).length).to.be(2);
});
it('can clear a selection before selecting new features', function() {
select.select(map, [[features[0]]], [vector], true);
select.select(map, [[features[1]]], [vector], true);
var layer = select.selectionLayers[goog.getUid(map)]
.layers[goog.getUid(vector)];
expect(goog.object.getCount(layer.featureCache_.idLookup_)).to.be(1);
expect(vector.getFeatures(selectedFeaturesFilter).length).to.be(1);
});
});
@@ -76,7 +74,6 @@ describe('ol.interaction.Select', function() {
});
goog.require('goog.dispose');
goog.require('goog.object');
goog.require('ol.Map');
goog.require('ol.interaction.Select');
goog.require('ol.layer.Vector');