diff --git a/src/ol/interaction/modifyinteraction.js b/src/ol/interaction/modifyinteraction.js
index 463e4da8da..5471601651 100644
--- a/src/ol/interaction/modifyinteraction.js
+++ b/src/ol/interaction/modifyinteraction.js
@@ -4,6 +4,7 @@ goog.require('goog.array');
goog.require('goog.asserts');
goog.require('goog.events');
goog.require('goog.events.Event');
+goog.require('goog.events.EventType');
goog.require('goog.functions');
goog.require('ol.Collection');
goog.require('ol.CollectionEventType');
@@ -168,6 +169,14 @@ ol.interaction.Modify = function(options) {
*/
this.snappedToVertex_ = false;
+ /**
+ * Indicate whether the interaction is currently changing a feature's
+ * coordinates.
+ * @type {boolean}
+ * @private
+ */
+ this.changingFeature_ = false;
+
/**
* @type {Array}
* @private
@@ -235,6 +244,48 @@ ol.interaction.Modify.prototype.addFeature_ = function(feature) {
if (!goog.isNull(map)) {
this.handlePointerAtPixel_(this.lastPixel_, map);
}
+ goog.events.listen(feature, goog.events.EventType.CHANGE,
+ this.handleFeatureChange_, false, this);
+};
+
+
+/**
+ * @param {ol.Feature} feature Feature.
+ * @private
+ */
+ol.interaction.Modify.prototype.removeFeature_ = function(feature) {
+ this.removeFeatureSegmentData_(feature);
+ // Remove the vertex feature if the collection of canditate features
+ // is empty.
+ if (!goog.isNull(this.vertexFeature_) &&
+ this.features_.getLength() === 0) {
+ this.overlay_.getSource().removeFeature(this.vertexFeature_);
+ this.vertexFeature_ = null;
+ }
+ goog.events.unlisten(feature, goog.events.EventType.CHANGE,
+ this.handleFeatureChange_, false, this);
+};
+
+
+/**
+ * @param {ol.Feature} feature Feature.
+ * @private
+ */
+ol.interaction.Modify.prototype.removeFeatureSegmentData_ = function(feature) {
+ var rBush = this.rBush_;
+ var /** @type {Array.
} */ nodesToRemove = [];
+ rBush.forEach(
+ /**
+ * @param {ol.interaction.SegmentDataType} node RTree node.
+ */
+ function(node) {
+ if (feature === node.feature) {
+ nodesToRemove.push(node);
+ }
+ });
+ for (var i = nodesToRemove.length - 1; i >= 0; --i) {
+ rBush.remove(nodesToRemove[i]);
+ }
};
@@ -259,28 +310,26 @@ ol.interaction.Modify.prototype.handleFeatureAdd_ = function(evt) {
};
+/**
+ * @param {goog.events.Event} evt Event.
+ * @private
+ */
+ol.interaction.Modify.prototype.handleFeatureChange_ = function(evt) {
+ if (!this.changingFeature_) {
+ var feature = /** @type {ol.Feature} */ (evt.target);
+ this.removeFeature_(feature);
+ this.addFeature_(feature);
+ }
+};
+
+
/**
* @param {ol.CollectionEvent} evt Event.
* @private
*/
ol.interaction.Modify.prototype.handleFeatureRemove_ = function(evt) {
- var feature = evt.element;
- var rBush = this.rBush_;
- var i, nodesToRemove = [];
- rBush.forEachInExtent(feature.getGeometry().getExtent(), function(node) {
- if (feature === node.feature) {
- nodesToRemove.push(node);
- }
- });
- for (i = nodesToRemove.length - 1; i >= 0; --i) {
- rBush.remove(nodesToRemove[i]);
- }
- // There remains only vertexFeature…
- if (!goog.isNull(this.vertexFeature_) &&
- this.features_.getLength() === 0) {
- this.overlay_.getSource().removeFeature(this.vertexFeature_);
- this.vertexFeature_ = null;
- }
+ var feature = /** @type {ol.Feature} */ (evt.element);
+ this.removeFeature_(feature);
};
@@ -585,7 +634,7 @@ ol.interaction.Modify.handleDragEvent_ = function(evt) {
break;
}
- geometry.setCoordinates(coordinates);
+ this.setGeometryCoordinates_(geometry, coordinates);
}
this.createOrUpdateVertexFeature_(vertex);
};
@@ -768,7 +817,7 @@ ol.interaction.Modify.prototype.insertVertex_ = function(segmentData, vertex) {
return;
}
- geometry.setCoordinates(coordinates);
+ this.setGeometryCoordinates_(geometry, coordinates);
var rTree = this.rBush_;
goog.asserts.assert(goog.isDef(segment), 'segment should be defined');
rTree.remove(segmentData);
@@ -874,7 +923,7 @@ ol.interaction.Modify.prototype.removeVertex_ = function() {
if (deleted) {
this.rBush_.remove(newSegment[0]);
this.rBush_.remove(newSegment[1]);
- geometry.setCoordinates(coordinates);
+ this.setGeometryCoordinates_(geometry, coordinates);
goog.asserts.assert(newIndex >= 0, 'newIndex should be larger than 0');
var newSegmentData = /** @type {ol.interaction.SegmentDataType} */ ({
depth: segmentData.depth,
@@ -898,6 +947,19 @@ ol.interaction.Modify.prototype.removeVertex_ = function() {
};
+/**
+ * @param {ol.geom.SimpleGeometry} geometry Geometry.
+ * @param {Array} coordinates Coordinates.
+ * @private
+ */
+ol.interaction.Modify.prototype.setGeometryCoordinates_ =
+ function(geometry, coordinates) {
+ this.changingFeature_ = true;
+ geometry.setCoordinates(coordinates);
+ this.changingFeature_ = false;
+};
+
+
/**
* @param {ol.geom.SimpleGeometry} geometry Geometry.
* @param {number} index Index.
diff --git a/test/spec/ol/interaction/modifyinteraction.test.js b/test/spec/ol/interaction/modifyinteraction.test.js
index 418b98a3f4..7fff57b64f 100644
--- a/test/spec/ol/interaction/modifyinteraction.test.js
+++ b/test/spec/ol/interaction/modifyinteraction.test.js
@@ -262,10 +262,65 @@ describe('ol.interaction.Modify', function() {
expect(feature.getGeometry().getCoordinates()[0]).to.have.length(5);
});
});
+
+ describe('handle feature change', function() {
+ var getListeners;
+
+ beforeEach(function() {
+ getListeners = function(feature, modify) {
+ var listeners = goog.events.getListeners(
+ feature, goog.events.EventType.CHANGE, false);
+ return goog.array.filter(listeners, function(listener) {
+ return listener.handler == modify;
+ });
+ };
+ });
+
+ it('updates the segment data', function() {
+ var modify = new ol.interaction.Modify({
+ features: new ol.Collection(features)
+ });
+ map.addInteraction(modify);
+
+ var feature = features[0];
+ var listeners, listener;
+
+ listeners = getListeners(feature, modify);
+ expect(listeners).to.have.length(1);
+
+ var firstSegmentData;
+
+ firstSegmentData = modify.rBush_.forEachInExtent([0, 0, 5, 5],
+ function(node) {
+ return node;
+ });
+ expect(firstSegmentData.segment[0]).to.eql([0, 0]);
+ expect(firstSegmentData.segment[1]).to.eql([10, 20]);
+
+ var coordinates = feature.getGeometry().getCoordinates();
+ var firstVertex = coordinates[0][0];
+ firstVertex[0] = 1;
+ firstVertex[1] = 1;
+ feature.getGeometry().setCoordinates(coordinates);
+
+ firstSegmentData = modify.rBush_.forEachInExtent([0, 0, 5, 5],
+ function(node) {
+ return node;
+ });
+ expect(firstSegmentData.segment[0]).to.eql([1, 1]);
+ expect(firstSegmentData.segment[1]).to.eql([10, 20]);
+
+ listeners = getListeners(feature, modify);
+ expect(listeners).to.have.length(1);
+ });
+ });
+
});
+goog.require('goog.array');
goog.require('goog.dispose');
goog.require('goog.events');
+goog.require('goog.events.EventType');
goog.require('goog.events.BrowserEvent');
goog.require('goog.style');
goog.require('ol.Collection');