diff --git a/src/ol/events/condition.js b/src/ol/events/condition.js index de8c3d20fe..c2ead5189f 100644 --- a/src/ol/events/condition.js +++ b/src/ol/events/condition.js @@ -111,6 +111,18 @@ ol.events.condition.singleClick = function(mapBrowserEvent) { }; +/** + * Return `true` if the event is a map `dblclick` event, `false` otherwise. + * + * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event. + * @return {boolean} True if the event is a map `dblclick` event. + * @api stable + */ +ol.events.condition.doubleClick = function(mapBrowserEvent) { + return mapBrowserEvent.type == ol.MapBrowserEvent.EventType.DBLCLICK; +}; + + /** * Return `true` if no modifier key (alt-, shift- or platform-modifier-key) is * pressed. diff --git a/src/ol/interaction/modifyinteraction.js b/src/ol/interaction/modifyinteraction.js index e206af9053..91009a09a3 100644 --- a/src/ol/interaction/modifyinteraction.js +++ b/src/ol/interaction/modifyinteraction.js @@ -142,12 +142,12 @@ ol.interaction.Modify = function(options) { this.lastPixel_ = [0, 0]; /** - * Keep track of the last inserted pixel location to avoid - * unintentional deletion. - * @type {ol.Pixel} + * Tracks if the next `singleclick` event should be ignored to prevent + * accidental deletion right after vertex creation. + * @type {boolean} * @private */ - this.lastNewVertexPixel_ = [NaN, NaN]; + this.ignoreNextSingleClick_ = false; /** * Segment RTree for each layer @@ -543,6 +543,8 @@ ol.interaction.Modify.handleDownEvent_ = function(evt) { * @private */ ol.interaction.Modify.handleDragEvent_ = function(evt) { + this.ignoreNextSingleClick_ = false; + var vertex = evt.coordinate; for (var i = 0, ii = this.dragSegments_.length; i < ii; ++i) { var dragSegment = this.dragSegments_[i]; @@ -626,8 +628,8 @@ ol.interaction.Modify.handleEvent = function(mapBrowserEvent) { } if (!goog.isNull(this.vertexFeature_) && this.deleteCondition_(mapBrowserEvent)) { - if (!(this.lastNewVertexPixel_[0] === this.lastPixel_[0] && - this.lastNewVertexPixel_[1] === this.lastPixel_[1])) { + if (mapBrowserEvent.type != ol.MapBrowserEvent.EventType.SINGLECLICK || + !this.ignoreNextSingleClick_) { var geometry = this.vertexFeature_.getGeometry(); goog.asserts.assertInstanceof(geometry, ol.geom.Point, 'geometry should be an ol.geom.Point'); @@ -636,6 +638,11 @@ ol.interaction.Modify.handleEvent = function(mapBrowserEvent) { handled = true; } } + + if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.SINGLECLICK) { + this.ignoreNextSingleClick_ = false; + } + return ol.interaction.Pointer.handleEvent.call(this, mapBrowserEvent) && !handled; }; @@ -789,7 +796,7 @@ ol.interaction.Modify.prototype.insertVertex_ = function(segmentData, vertex) { rTree.insert(ol.extent.boundingExtent(newSegmentData2.segment), newSegmentData2); this.dragSegments_.push([newSegmentData2, 0]); - this.lastNewVertexPixel_ = this.lastPixel_; + this.ignoreNextSingleClick_ = true; }; diff --git a/test/spec/ol/interaction/modifyinteraction.test.js b/test/spec/ol/interaction/modifyinteraction.test.js index 7ef55b719b..48a64022a7 100644 --- a/test/spec/ol/interaction/modifyinteraction.test.js +++ b/test/spec/ol/interaction/modifyinteraction.test.js @@ -89,7 +89,7 @@ describe('ol.interaction.Modify', function() { }); var rbushEntries = modify.rBush_.getAll(); expect(rbushEntries.length).to.be(1); - expect(rbushEntries[0].feature === feature).to.be.ok(); + expect(rbushEntries[0].feature).to.be(feature); }); }); @@ -106,7 +106,6 @@ describe('ol.interaction.Modify', function() { expect(feature.getGeometry().getRevision()).to.equal(1); expect(feature.getGeometry().getCoordinates()[0]).to.have.length(5); - simulateEvent('pointermove', 10, -20, false, 0); simulateEvent('pointerdown', 10, -20, false, 0); simulateEvent('pointerup', 10, -20, false, 0); simulateEvent('click', 10, -20, false, 0); @@ -127,7 +126,6 @@ describe('ol.interaction.Modify', function() { expect(feature.getGeometry().getRevision()).to.equal(1); expect(feature.getGeometry().getCoordinates()[0]).to.have.length(5); - simulateEvent('pointermove', 40, -20, false, 0); simulateEvent('pointerdown', 40, -20, false, 0); simulateEvent('pointerup', 40, -20, false, 0); simulateEvent('click', 40, -20, false, 0); @@ -137,6 +135,34 @@ describe('ol.interaction.Modify', function() { expect(feature.getGeometry().getCoordinates()[0]).to.have.length(6); }); + it('single clicking on created vertex should delete it again', function() { + var modify = new ol.interaction.Modify({ + features: new ol.Collection(features) + }); + map.addInteraction(modify); + + var feature = features[0]; + + expect(feature.getGeometry().getRevision()).to.equal(1); + expect(feature.getGeometry().getCoordinates()[0]).to.have.length(5); + + simulateEvent('pointerdown', 40, -20, false, 0); + simulateEvent('pointerup', 40, -20, false, 0); + simulateEvent('click', 40, -20, false, 0); + simulateEvent('singleclick', 40, -20, false, 0); + + expect(feature.getGeometry().getRevision()).to.equal(2); + expect(feature.getGeometry().getCoordinates()[0]).to.have.length(6); + + simulateEvent('pointerdown', 40, -20, false, 0); + simulateEvent('pointerup', 40, -20, false, 0); + simulateEvent('click', 40, -20, false, 0); + simulateEvent('singleclick', 40, -20, false, 0); + + expect(feature.getGeometry().getRevision()).to.equal(3); + expect(feature.getGeometry().getCoordinates()[0]).to.have.length(5); + }); + it('clicking with drag should add vertex and +r3', function() { var modify = new ol.interaction.Modify({ features: new ol.Collection(features) @@ -150,6 +176,7 @@ describe('ol.interaction.Modify', function() { simulateEvent('pointermove', 40, -20, false, 0); simulateEvent('pointerdown', 40, -20, false, 0); + simulateEvent('pointermove', 30, -20, false, 0); simulateEvent('pointerdrag', 30, -20, false, 0); simulateEvent('pointerup', 30, -20, false, 0); @@ -158,6 +185,53 @@ describe('ol.interaction.Modify', function() { }); }); + describe('double click deleteCondition', function() { + + it('should delete vertex on double click', function() { + var modify = new ol.interaction.Modify({ + features: new ol.Collection(features), + deleteCondition: ol.events.condition.doubleClick + }); + map.addInteraction(modify); + + var feature = features[0]; + + expect(feature.getGeometry().getRevision()).to.equal(1); + expect(feature.getGeometry().getCoordinates()[0]).to.have.length(5); + + simulateEvent('pointerdown', 10, -20, false, 0); + simulateEvent('pointerup', 10, -20, false, 0); + simulateEvent('click', 10, -20, false, 0); + simulateEvent('pointerdown', 10, -20, false, 0); + simulateEvent('pointerup', 10, -20, false, 0); + simulateEvent('click', 10, -20, false, 0); + simulateEvent('dblclick', 10, -20, false, 0); + + expect(feature.getGeometry().getRevision()).to.equal(2); + expect(feature.getGeometry().getCoordinates()[0]).to.have.length(4); + }); + + it('should do nothing on single click', function() { + var modify = new ol.interaction.Modify({ + features: new ol.Collection(features), + deleteCondition: ol.events.condition.doubleClick + }); + map.addInteraction(modify); + + var feature = features[0]; + + expect(feature.getGeometry().getRevision()).to.equal(1); + expect(feature.getGeometry().getCoordinates()[0]).to.have.length(5); + + simulateEvent('pointerdown', 10, -20, false, 0); + simulateEvent('pointerup', 10, -20, false, 0); + simulateEvent('click', 10, -20, false, 0); + simulateEvent('singleclick', 10, -20, false, 0); + + expect(feature.getGeometry().getRevision()).to.equal(1); + expect(feature.getGeometry().getCoordinates()[0]).to.have.length(5); + }); + }); }); goog.require('goog.dispose'); @@ -169,6 +243,7 @@ goog.require('ol.Feature'); goog.require('ol.Map'); goog.require('ol.MapBrowserPointerEvent'); goog.require('ol.View'); +goog.require('ol.events.condition'); goog.require('ol.geom.Point'); goog.require('ol.geom.Polygon'); goog.require('ol.interaction.Modify');