Make Modify interaction listen to feature changes
This commit makes the Modify interaction modify its segment data when the candidate features change.
This commit is contained in:
@@ -4,6 +4,7 @@ goog.require('goog.array');
|
|||||||
goog.require('goog.asserts');
|
goog.require('goog.asserts');
|
||||||
goog.require('goog.events');
|
goog.require('goog.events');
|
||||||
goog.require('goog.events.Event');
|
goog.require('goog.events.Event');
|
||||||
|
goog.require('goog.events.EventType');
|
||||||
goog.require('goog.functions');
|
goog.require('goog.functions');
|
||||||
goog.require('ol.Collection');
|
goog.require('ol.Collection');
|
||||||
goog.require('ol.CollectionEventType');
|
goog.require('ol.CollectionEventType');
|
||||||
@@ -168,6 +169,14 @@ ol.interaction.Modify = function(options) {
|
|||||||
*/
|
*/
|
||||||
this.snappedToVertex_ = false;
|
this.snappedToVertex_ = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate whether the interaction is currently changing a feature's
|
||||||
|
* coordinates.
|
||||||
|
* @type {boolean}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.changingFeature_ = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {Array}
|
* @type {Array}
|
||||||
* @private
|
* @private
|
||||||
@@ -235,6 +244,48 @@ ol.interaction.Modify.prototype.addFeature_ = function(feature) {
|
|||||||
if (!goog.isNull(map)) {
|
if (!goog.isNull(map)) {
|
||||||
this.handlePointerAtPixel_(this.lastPixel_, 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.<ol.interaction.SegmentDataType>} */ 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.
|
* @param {ol.CollectionEvent} evt Event.
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
ol.interaction.Modify.prototype.handleFeatureRemove_ = function(evt) {
|
ol.interaction.Modify.prototype.handleFeatureRemove_ = function(evt) {
|
||||||
var feature = evt.element;
|
var feature = /** @type {ol.Feature} */ (evt.element);
|
||||||
var rBush = this.rBush_;
|
this.removeFeature_(feature);
|
||||||
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;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -585,7 +634,7 @@ ol.interaction.Modify.handleDragEvent_ = function(evt) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
geometry.setCoordinates(coordinates);
|
this.setGeometryCoordinates_(geometry, coordinates);
|
||||||
}
|
}
|
||||||
this.createOrUpdateVertexFeature_(vertex);
|
this.createOrUpdateVertexFeature_(vertex);
|
||||||
};
|
};
|
||||||
@@ -768,7 +817,7 @@ ol.interaction.Modify.prototype.insertVertex_ = function(segmentData, vertex) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
geometry.setCoordinates(coordinates);
|
this.setGeometryCoordinates_(geometry, coordinates);
|
||||||
var rTree = this.rBush_;
|
var rTree = this.rBush_;
|
||||||
goog.asserts.assert(goog.isDef(segment), 'segment should be defined');
|
goog.asserts.assert(goog.isDef(segment), 'segment should be defined');
|
||||||
rTree.remove(segmentData);
|
rTree.remove(segmentData);
|
||||||
@@ -874,7 +923,7 @@ ol.interaction.Modify.prototype.removeVertex_ = function() {
|
|||||||
if (deleted) {
|
if (deleted) {
|
||||||
this.rBush_.remove(newSegment[0]);
|
this.rBush_.remove(newSegment[0]);
|
||||||
this.rBush_.remove(newSegment[1]);
|
this.rBush_.remove(newSegment[1]);
|
||||||
geometry.setCoordinates(coordinates);
|
this.setGeometryCoordinates_(geometry, coordinates);
|
||||||
goog.asserts.assert(newIndex >= 0, 'newIndex should be larger than 0');
|
goog.asserts.assert(newIndex >= 0, 'newIndex should be larger than 0');
|
||||||
var newSegmentData = /** @type {ol.interaction.SegmentDataType} */ ({
|
var newSegmentData = /** @type {ol.interaction.SegmentDataType} */ ({
|
||||||
depth: segmentData.depth,
|
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 {ol.geom.SimpleGeometry} geometry Geometry.
|
||||||
* @param {number} index Index.
|
* @param {number} index Index.
|
||||||
|
|||||||
@@ -262,10 +262,65 @@ describe('ol.interaction.Modify', function() {
|
|||||||
expect(feature.getGeometry().getCoordinates()[0]).to.have.length(5);
|
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.dispose');
|
||||||
goog.require('goog.events');
|
goog.require('goog.events');
|
||||||
|
goog.require('goog.events.EventType');
|
||||||
goog.require('goog.events.BrowserEvent');
|
goog.require('goog.events.BrowserEvent');
|
||||||
goog.require('goog.style');
|
goog.require('goog.style');
|
||||||
goog.require('ol.Collection');
|
goog.require('ol.Collection');
|
||||||
|
|||||||
Reference in New Issue
Block a user