From 7b4a954c40f4c28381f87079553f9ff11e46b272 Mon Sep 17 00:00:00 2001 From: Ryan Curry Date: Tue, 30 Jun 2015 11:09:20 -0700 Subject: [PATCH 1/7] graticule.js now uses vectorContext.extent_ When creating the graticule use the extent from the vectorContext instead of the frameState to determine what parallels and meridians should be created. This will allow the graticule to be drawn correctly on views that wrap across the dateline. --- src/ol/graticule.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ol/graticule.js b/src/ol/graticule.js index 89adadad5e..9d4a1f3e69 100644 --- a/src/ol/graticule.js +++ b/src/ol/graticule.js @@ -356,7 +356,7 @@ ol.Graticule.prototype.getParallels = function() { ol.Graticule.prototype.handlePostCompose_ = function(e) { var vectorContext = e.vectorContext; var frameState = e.frameState; - var extent = frameState.extent; + var extent = vectorContext.extent_; var viewState = frameState.viewState; var center = viewState.center; var projection = viewState.projection; From de6ecb22a8e89e60d2cc1ef3190f0a6b7ab30337 Mon Sep 17 00:00:00 2001 From: Ryan Curry Date: Thu, 2 Jul 2015 12:20:05 -0700 Subject: [PATCH 2/7] graticule.js - Fixed build. No functional change. viewContext.extent_ is private, so we can't use it directly. Instead, re-calculate the corrected wrapped extent. --- src/ol/graticule.js | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/ol/graticule.js b/src/ol/graticule.js index 9d4a1f3e69..2ee6ecc1a5 100644 --- a/src/ol/graticule.js +++ b/src/ol/graticule.js @@ -356,7 +356,7 @@ ol.Graticule.prototype.getParallels = function() { ol.Graticule.prototype.handlePostCompose_ = function(e) { var vectorContext = e.vectorContext; var frameState = e.frameState; - var extent = vectorContext.extent_; + var extent = framteState.extent; var viewState = frameState.viewState; var center = viewState.center; var projection = viewState.projection; @@ -372,6 +372,21 @@ ol.Graticule.prototype.handlePostCompose_ = function(e) { this.updateProjectionInfo_(projection); } + //Fix the extent if wrapped (note: this is the same extent as vectorContext.extent_) + var offsetX = 0; + if (projection.canWrapX()) { + var projectionExtent = projection.getExtent(); + var worldWidth = ol.extent.getWidth(projectionExtent); + var x = frameState.focus[0]; + if (x < projectionExtent[0] || x > projectionExtent[2]) { + var worldsAway = Math.ceil((projectionExtent[0] - x) / worldWidth); + extent = [ + extent[0] + offsetX, extent[1], + extent[2] + offsetX, extent[3] + ]; + } + } + this.createGraticule_(extent, center, resolution, squaredTolerance); // Draw the lines From 56e871f8b59d32980bd8dba441cbee1ed6cdc0a1 Mon Sep 17 00:00:00 2001 From: Ryan Curry Date: Thu, 2 Jul 2015 12:23:05 -0700 Subject: [PATCH 3/7] Update graticule.js - fixed typo/build error Corrected reference to variable frameState - it was misspelled by the previous commit. --- src/ol/graticule.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ol/graticule.js b/src/ol/graticule.js index 2ee6ecc1a5..e3585a1ea4 100644 --- a/src/ol/graticule.js +++ b/src/ol/graticule.js @@ -356,7 +356,7 @@ ol.Graticule.prototype.getParallels = function() { ol.Graticule.prototype.handlePostCompose_ = function(e) { var vectorContext = e.vectorContext; var frameState = e.frameState; - var extent = framteState.extent; + var extent = frameState.extent; var viewState = frameState.viewState; var center = viewState.center; var projection = viewState.projection; From 9a44895d41249ab7e4dd6c75c2161f6141eb3ee0 Mon Sep 17 00:00:00 2001 From: Ryan Curry Date: Thu, 2 Jul 2015 12:35:38 -0700 Subject: [PATCH 4/7] Update graticule.js - fixed style / missing line My comment on line 375 was too long, so I broke it up into multiple lines. Also I accidentally left a line out of the commit (line 384) when transcribing my changes into the web based editor. --- src/ol/graticule.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ol/graticule.js b/src/ol/graticule.js index e3585a1ea4..57caa01537 100644 --- a/src/ol/graticule.js +++ b/src/ol/graticule.js @@ -372,7 +372,8 @@ ol.Graticule.prototype.handlePostCompose_ = function(e) { this.updateProjectionInfo_(projection); } - //Fix the extent if wrapped (note: this is the same extent as vectorContext.extent_) + //Fix the extent if wrapped. + //(note: this is the same extent as vectorContext.extent_) var offsetX = 0; if (projection.canWrapX()) { var projectionExtent = projection.getExtent(); @@ -380,6 +381,7 @@ ol.Graticule.prototype.handlePostCompose_ = function(e) { var x = frameState.focus[0]; if (x < projectionExtent[0] || x > projectionExtent[2]) { var worldsAway = Math.ceil((projectionExtent[0] - x) / worldWidth); + offsetX = worldWidth * worldsAway; extent = [ extent[0] + offsetX, extent[1], extent[2] + offsetX, extent[3] From 094f8d5391d2a0a734776f2697ceed010f39a29f Mon Sep 17 00:00:00 2001 From: jonataswalker Date: Mon, 5 Oct 2015 14:52:33 -0300 Subject: [PATCH 5/7] Add 'getLayer()' method to 'ol.interaction.Select' --- src/ol/interaction/selectinteraction.js | 75 +++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/src/ol/interaction/selectinteraction.js b/src/ol/interaction/selectinteraction.js index 6a84a8b477..6c0f000ea8 100644 --- a/src/ol/interaction/selectinteraction.js +++ b/src/ol/interaction/selectinteraction.js @@ -8,6 +8,7 @@ goog.require('goog.asserts'); goog.require('goog.events'); goog.require('goog.events.Event'); goog.require('goog.functions'); +goog.require('goog.object'); goog.require('ol.CollectionEventType'); goog.require('ol.Feature'); goog.require('ol.array'); @@ -174,6 +175,14 @@ ol.interaction.Select = function(opt_options) { */ this.layerFilter_ = layerFilter; + /** + * An association between selected feature (key) + * and layer (value) + * @private + * @type {Array.} + */ + this.featureLayerAssociation_ = []; + /** * @private * @type {ol.layer.Vector} @@ -200,6 +209,20 @@ ol.interaction.Select = function(opt_options) { goog.inherits(ol.interaction.Select, ol.interaction.Interaction); +/** + * @param {ol.Feature} feature Feature. + * @param {ol.layer.Layer} layer Layer. + * @private + */ +ol.interaction.Select.prototype.addFeatureLayerAssociation_ = + function(feature, layer) { + var key = goog.getUid(feature); + var obj = {}; + obj[key] = layer; + this.featureLayerAssociation_.push(obj); +}; + + /** * Get the selected features. * @return {ol.Collection.} Features collection. @@ -210,6 +233,27 @@ ol.interaction.Select.prototype.getFeatures = function() { }; +/** + * Returns the associated {@link ol.layer.Vector vectorlayer} of + * the (last) selected feature. + * @param {ol.Feature} feature Feature + * @return {ol.layer.Vector} Layer. + * @api + */ +ol.interaction.Select.prototype.getLayer = function(feature) { + goog.asserts.assertInstanceof(feature, ol.Feature, + 'feature should be an ol.Feature'); + var key = goog.getUid(feature).toString(); + var found = goog.array.find(this.featureLayerAssociation_, function(each) { + if (key == goog.object.getKeys(each)[0]) { + return true; + } + return false; + }); + return /** @type {ol.layer.Vector} */ (goog.object.getValues(found)[0]); +}; + + /** * Handles the {@link ol.MapBrowserEvent map browser event} and may change the * selected state of features. @@ -243,6 +287,7 @@ ol.interaction.Select.handleEvent = function(mapBrowserEvent) { function(feature, layer) { if (this.filter_(feature, layer)) { selected.push(feature); + this.addFeatureLayerAssociation_(feature, layer); return !this.multi_; } }, this, this.layerFilter_); @@ -256,6 +301,16 @@ ol.interaction.Select.handleEvent = function(mapBrowserEvent) { features.clear(); } features.extend(selected); + // Modify array featureLayerAssociation_ + if (selected.length === 0) { + this.featureLayerAssociation_.length = 0; + } else { + if (deselected.length > 0) { + deselected.forEach(function(feature) { + this.removeFeatureLayerAssociation_(feature); + }, this); + } + } } } else { // Modify the currently selected feature(s). @@ -269,11 +324,13 @@ ol.interaction.Select.handleEvent = function(mapBrowserEvent) { if (add || toggle) { if (this.filter_(feature, layer)) { selected.push(feature); + this.addFeatureLayerAssociation_(feature, layer); } } } else { if (remove || toggle) { deselected.push(feature); + this.removeFeatureLayerAssociation_(feature); } } }, this, this.layerFilter_); @@ -360,3 +417,21 @@ ol.interaction.Select.prototype.removeFeature_ = function(evt) { map.unskipFeature(feature); } }; + + +/** + * @param {ol.Feature} feature Feature. + * @private + */ +ol.interaction.Select.prototype.removeFeatureLayerAssociation_ = + function(feature) { + var key = goog.getUid(feature); + var index = goog.array.findIndex(this.featureLayerAssociation_, + function(each) { + if (key == goog.object.getKeys(each)[0]) { + return true; + } + return false; + }); + this.featureLayerAssociation_.splice(index, 1); +}; From 85163bceb6602d6504155cb6c7938b4d2e97e51e Mon Sep 17 00:00:00 2001 From: jonataswalker Date: Thu, 8 Oct 2015 06:52:01 -0300 Subject: [PATCH 6/7] Add 'getLayer()' method to 'ol.interaction.Select' --- src/ol/interaction/selectinteraction.js | 31 +++++++------------------ 1 file changed, 8 insertions(+), 23 deletions(-) diff --git a/src/ol/interaction/selectinteraction.js b/src/ol/interaction/selectinteraction.js index 6c0f000ea8..447c18634e 100644 --- a/src/ol/interaction/selectinteraction.js +++ b/src/ol/interaction/selectinteraction.js @@ -179,9 +179,9 @@ ol.interaction.Select = function(opt_options) { * An association between selected feature (key) * and layer (value) * @private - * @type {Array.} + * @type {Object.} */ - this.featureLayerAssociation_ = []; + this.featureLayerAssociation_ = {}; /** * @private @@ -217,9 +217,7 @@ goog.inherits(ol.interaction.Select, ol.interaction.Interaction); ol.interaction.Select.prototype.addFeatureLayerAssociation_ = function(feature, layer) { var key = goog.getUid(feature); - var obj = {}; - obj[key] = layer; - this.featureLayerAssociation_.push(obj); + this.featureLayerAssociation_[key] = layer; }; @@ -243,14 +241,8 @@ ol.interaction.Select.prototype.getFeatures = function() { ol.interaction.Select.prototype.getLayer = function(feature) { goog.asserts.assertInstanceof(feature, ol.Feature, 'feature should be an ol.Feature'); - var key = goog.getUid(feature).toString(); - var found = goog.array.find(this.featureLayerAssociation_, function(each) { - if (key == goog.object.getKeys(each)[0]) { - return true; - } - return false; - }); - return /** @type {ol.layer.Vector} */ (goog.object.getValues(found)[0]); + var key = goog.getUid(feature); + return /** @type {ol.layer.Vector} */ (this.featureLayerAssociation_[key]); }; @@ -301,9 +293,9 @@ ol.interaction.Select.handleEvent = function(mapBrowserEvent) { features.clear(); } features.extend(selected); - // Modify array featureLayerAssociation_ + // Modify object this.featureLayerAssociation_ if (selected.length === 0) { - this.featureLayerAssociation_.length = 0; + goog.object.clear(this.featureLayerAssociation_); } else { if (deselected.length > 0) { deselected.forEach(function(feature) { @@ -426,12 +418,5 @@ ol.interaction.Select.prototype.removeFeature_ = function(evt) { ol.interaction.Select.prototype.removeFeatureLayerAssociation_ = function(feature) { var key = goog.getUid(feature); - var index = goog.array.findIndex(this.featureLayerAssociation_, - function(each) { - if (key == goog.object.getKeys(each)[0]) { - return true; - } - return false; - }); - this.featureLayerAssociation_.splice(index, 1); + delete this.featureLayerAssociation_[key]; }; From 04c16106cde419cd73bc2139306cf3c189c1d11a Mon Sep 17 00:00:00 2001 From: jonataswalker Date: Thu, 8 Oct 2015 10:11:44 -0300 Subject: [PATCH 7/7] Add unit test to ol.interaction.Select#getLayer --- .../ol/interaction/selectinteraction.test.js | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/test/spec/ol/interaction/selectinteraction.test.js b/test/spec/ol/interaction/selectinteraction.test.js index 6e8e331e16..f1a0beb8b8 100644 --- a/test/spec/ol/interaction/selectinteraction.test.js +++ b/test/spec/ol/interaction/selectinteraction.test.js @@ -1,7 +1,7 @@ goog.provide('ol.test.interaction.Select'); describe('ol.interaction.Select', function() { - var target, map, source; + var target, map, layer, source; var width = 360; var height = 180; @@ -45,7 +45,7 @@ describe('ol.interaction.Select', function() { features: features }); - var layer = new ol.layer.Vector({source: source}); + layer = new ol.layer.Vector({source: source}); map = new ol.Map({ target: target, @@ -199,6 +199,32 @@ describe('ol.interaction.Select', function() { }); + describe('#getLayer(feature)', function() { + var interaction; + + beforeEach(function() { + interaction = new ol.interaction.Select(); + map.addInteraction(interaction); + }); + afterEach(function() { + map.removeInteraction(interaction); + }); + + it('returns a layer from a selected feature', function() { + var listenerSpy = sinon.spy(function(e) { + var feature = e.selected[0]; + var layer_ = interaction.getLayer(feature); + expect(e.selected).to.have.length(1); + expect(feature).to.be.a(ol.Feature); + expect(layer_).to.be.a(ol.layer.Vector); + expect(layer_).to.equal(layer); + }); + interaction.on('select', listenerSpy); + + simulateEvent(ol.MapBrowserEvent.EventType.SINGLECLICK, 10, -20); + }); + }); + describe('#setActive()', function() { var interaction;