Adding vertexmodified, sketchmodified, and sketchcomplete events to the vector layer. These are triggered by the DrawFeature and ModifyFeature controls and let listeners know about newly drawn features and modified features. r=ahocevar (closes #1904)

git-svn-id: http://svn.openlayers.org/trunk/openlayers@8835 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
This commit is contained in:
Tim Schaub
2009-02-05 17:38:20 +00:00
parent f4bae0a011
commit 41670499b1
5 changed files with 169 additions and 16 deletions

View File

@@ -66,8 +66,17 @@ OpenLayers.Control.DrawFeature = OpenLayers.Class(OpenLayers.Control, {
); );
OpenLayers.Control.prototype.initialize.apply(this, [options]); OpenLayers.Control.prototype.initialize.apply(this, [options]);
this.callbacks = OpenLayers.Util.extend({done: this.drawFeature}, this.callbacks = OpenLayers.Util.extend(
this.callbacks); {
done: this.drawFeature,
modify: function(vertex, feature) {
this.layer.events.triggerEvent(
"sketchmodified", {vertex: vertex, feature: feature}
);
}
},
this.callbacks
);
this.layer = layer; this.layer = layer;
this.handler = new handler(this, this.callbacks, this.handlerOptions); this.handler = new handler(this, this.callbacks, this.handlerOptions);
}, },
@@ -77,10 +86,15 @@ OpenLayers.Control.DrawFeature = OpenLayers.Class(OpenLayers.Control, {
*/ */
drawFeature: function(geometry) { drawFeature: function(geometry) {
var feature = new OpenLayers.Feature.Vector(geometry); var feature = new OpenLayers.Feature.Vector(geometry);
feature.state = OpenLayers.State.INSERT; var proceed = this.layer.events.triggerEvent(
this.layer.addFeatures([feature]); "sketchcomplete", {feature: feature}
this.featureAdded(feature); );
this.events.triggerEvent("featureadded",{feature : feature}); if(proceed !== false) {
feature.state = OpenLayers.State.INSERT;
this.layer.addFeatures([feature]);
this.featureAdded(feature);
this.events.triggerEvent("featureadded",{feature : feature});
}
}, },
CLASS_NAME: "OpenLayers.Control.DrawFeature" CLASS_NAME: "OpenLayers.Control.DrawFeature"

View File

@@ -117,6 +117,12 @@ OpenLayers.Control.ModifyFeature = OpenLayers.Class(OpenLayers.Control, {
*/ */
mode: null, mode: null,
/**
* Property: modified
* {Boolean} The currently selected feature has been modified.
*/
modified: false,
/** /**
* Property: radiusHandle * Property: radiusHandle
* {<OpenLayers.Feature.Vector>} A handle for rotating/resizing a feature. * {<OpenLayers.Feature.Vector>} A handle for rotating/resizing a feature.
@@ -212,8 +218,8 @@ OpenLayers.Control.ModifyFeature = OpenLayers.Class(OpenLayers.Control, {
onStart: function(feature, pixel) { onStart: function(feature, pixel) {
control.dragStart.apply(control, [feature, pixel]); control.dragStart.apply(control, [feature, pixel]);
}, },
onDrag: function(feature) { onDrag: function(feature, pixel) {
control.dragVertex.apply(control, [feature]); control.dragVertex.apply(control, [feature, pixel]);
}, },
onComplete: function(feature) { onComplete: function(feature) {
control.dragComplete.apply(control, [feature]); control.dragComplete.apply(control, [feature]);
@@ -304,6 +310,7 @@ OpenLayers.Control.ModifyFeature = OpenLayers.Class(OpenLayers.Control, {
*/ */
selectFeature: function(feature) { selectFeature: function(feature) {
this.feature = feature; this.feature = feature;
this.modified = false;
this.resetVertices(); this.resetVertices();
this.dragControl.activate(); this.dragControl.activate();
this.onModificationStart(this.feature); this.onModificationStart(this.feature);
@@ -332,8 +339,11 @@ OpenLayers.Control.ModifyFeature = OpenLayers.Class(OpenLayers.Control, {
this.feature = null; this.feature = null;
this.dragControl.deactivate(); this.dragControl.deactivate();
this.onModificationEnd(feature); this.onModificationEnd(feature);
this.layer.events.triggerEvent("afterfeaturemodified", this.layer.events.triggerEvent("afterfeaturemodified", {
{feature: feature}); feature: feature,
modified: this.modified
});
this.modified = false;
}, },
/** /**
@@ -390,21 +400,28 @@ OpenLayers.Control.ModifyFeature = OpenLayers.Class(OpenLayers.Control, {
* *
* Parameters: * Parameters:
* vertex - {<OpenLayers.Feature.Vector>} The vertex being dragged. * vertex - {<OpenLayers.Feature.Vector>} The vertex being dragged.
* pixel - {<OpenLayers.Pixel>} Pixel location of the mouse event.
*/ */
dragVertex: function(vertex) { dragVertex: function(vertex, pixel) {
this.modified = true;
/** /**
* Five cases: * Five cases:
* 1) dragging a simple point * 1) dragging a simple point
* 2) dragging a virtual vertex * 2) dragging a virtual vertex
* 3) dragging a drag handle * 3) dragging a drag handle
* 4) dragging a radius handle * 4) dragging a real vertex
* 5) dragging a real vertex * 5) dragging a radius handle
*/ */
if(this.feature.geometry.CLASS_NAME == "OpenLayers.Geometry.Point") { if(this.feature.geometry.CLASS_NAME == "OpenLayers.Geometry.Point") {
// dragging a simple point // dragging a simple point
if(this.feature != vertex) { if(this.feature != vertex) {
this.feature = vertex; this.feature = vertex;
} }
this.layer.events.triggerEvent("vertexmodified", {
vertex: vertex.geometry,
feature: this.feature,
pixel: pixel
});
} else { } else {
if(vertex._index) { if(vertex._index) {
// dragging a virtual vertex // dragging a virtual vertex
@@ -422,9 +439,15 @@ OpenLayers.Control.ModifyFeature = OpenLayers.Class(OpenLayers.Control, {
this.layer.destroyFeatures([this.radiusHandle], {silent: true}); this.layer.destroyFeatures([this.radiusHandle], {silent: true});
this.radiusHandle = null; this.radiusHandle = null;
} }
} else if(vertex !== this.radiusHandle) {
// dragging a real vertex
this.layer.events.triggerEvent("vertexmodified", {
vertex: vertex.geometry,
feature: this.feature,
pixel: pixel
});
} }
// dragging a radius handle - no special treatment // dragging a radius handle - no special treatment
// dragging a real vertex - no special treatment
if(this.virtualVertices.length > 0) { if(this.virtualVertices.length > 0) {
this.layer.destroyFeatures(this.virtualVertices, {silent: true}); this.layer.destroyFeatures(this.virtualVertices, {silent: true});
this.virtualVertices = []; this.virtualVertices = [];
@@ -556,6 +579,7 @@ OpenLayers.Control.ModifyFeature = OpenLayers.Class(OpenLayers.Control, {
var i, vertex, component, len; var i, vertex, component, len;
if(geometry.CLASS_NAME == "OpenLayers.Geometry.Point") { if(geometry.CLASS_NAME == "OpenLayers.Geometry.Point") {
vertex = new OpenLayers.Feature.Vector(geometry); vertex = new OpenLayers.Feature.Vector(geometry);
vertex._sketch = true;
control.vertices.push(vertex); control.vertices.push(vertex);
} else { } else {
var numVert = geometry.components.length; var numVert = geometry.components.length;
@@ -566,6 +590,7 @@ OpenLayers.Control.ModifyFeature = OpenLayers.Class(OpenLayers.Control, {
component = geometry.components[i]; component = geometry.components[i];
if(component.CLASS_NAME == "OpenLayers.Geometry.Point") { if(component.CLASS_NAME == "OpenLayers.Geometry.Point") {
vertex = new OpenLayers.Feature.Vector(component); vertex = new OpenLayers.Feature.Vector(component);
vertex._sketch = true;
control.vertices.push(vertex); control.vertices.push(vertex);
} else { } else {
collectComponentVertices(component); collectComponentVertices(component);
@@ -588,6 +613,7 @@ OpenLayers.Control.ModifyFeature = OpenLayers.Class(OpenLayers.Control, {
// set the virtual parent and intended index // set the virtual parent and intended index
point.geometry.parent = geometry; point.geometry.parent = geometry;
point._index = i + 1; point._index = i + 1;
point._sketch = true;
control.virtualVertices.push(point); control.virtualVertices.push(point);
} }
} }
@@ -614,6 +640,7 @@ OpenLayers.Control.ModifyFeature = OpenLayers.Class(OpenLayers.Control, {
OpenLayers.Geometry.Point.prototype.move.call(this, x, y); OpenLayers.Geometry.Point.prototype.move.call(this, x, y);
geometry.move(x, y); geometry.move(x, y);
}; };
origin._sketch = true;
this.dragHandle = origin; this.dragHandle = origin;
this.layer.addFeatures([this.dragHandle], {silent: true}); this.layer.addFeatures([this.dragHandle], {silent: true});
}, },
@@ -654,6 +681,7 @@ OpenLayers.Control.ModifyFeature = OpenLayers.Class(OpenLayers.Control, {
geometry.resize(l1 / l0, originGeometry); geometry.resize(l1 / l0, originGeometry);
} }
}; };
radius._sketch = true;
this.radiusHandle = radius; this.radiusHandle = radius;
this.layer.addFeatures([this.radiusHandle], {silent: true}); this.layer.addFeatures([this.radiusHandle], {silent: true});
}, },

View File

@@ -74,6 +74,19 @@ OpenLayers.Layer.Vector = OpenLayers.Class(OpenLayers.Layer, {
* - *afterfeaturemodified* Triggered when a feature is finished being modified. * - *afterfeaturemodified* Triggered when a feature is finished being modified.
* Listeners will receive an object with a *feature* property referencing * Listeners will receive an object with a *feature* property referencing
* the modified feature. * the modified feature.
* - *vertexmodified* Triggered when a vertex within any feature geometry
* has been modified. Listeners will receive an object with a
* *feature* property referencing the modified feature, a *vertex*
* property referencing the vertex modified (always a point geometry),
* and a *pixel* property referencing the pixel location of the
* modification.
* - *sketchmodified* Triggered when a feature sketch bound for this layer
* is modified. Listeners will receive an object with a *vertex*
* property referencing the modified vertex.
* - *sketchcomplete* Triggered when a feature sketch bound for this layer
* is complete. Listeners will receive an object with a *feature*
* property referencing the sketch feature. By returning false, a
* listener can stop the sketch feature from being added to the layer.
* - *refresh* Triggered when something wants a strategy to ask the protocol * - *refresh* Triggered when something wants a strategy to ask the protocol
* for a new set of features. * for a new set of features.
*/ */
@@ -82,6 +95,7 @@ OpenLayers.Layer.Vector = OpenLayers.Class(OpenLayers.Layer, {
"beforefeatureremoved", "featureremoved", "featuresremoved", "beforefeatureremoved", "featureremoved", "featuresremoved",
"beforefeatureselected", "featureselected", "featureunselected", "beforefeatureselected", "featureselected", "featureunselected",
"beforefeaturemodified", "featuremodified", "afterfeaturemodified", "beforefeaturemodified", "featuremodified", "afterfeaturemodified",
"vertexmodified", "sketchmodified", "sketchcomplete",
"refresh"], "refresh"],
/** /**

View File

@@ -30,6 +30,45 @@
control.events.un({"featureadded": handlefeatureadded}); control.events.un({"featureadded": handlefeatureadded});
} }
function test_sketch_events(t) {
t.plan(4);
var map = new OpenLayers.Map("map", {
resolutions: [1]
});
var layer = new OpenLayers.Layer.Vector("foo", {
maxExtent: new OpenLayers.Bounds(-10, -10, 10, 10),
isBaseLayer: true
});
var control = new OpenLayers.Control.DrawFeature(
layer, OpenLayers.Handler.Point
);
map.addLayer(layer);
map.addControl(control);
map.zoomToMaxExtent();
control.activate();
var log = {};
layer.events.on({
sketchmodified: function(event) {
log.event = event;
},
sketchcomplete: function(event) {
log.event = event;
}
});
// mock up draw/modify of a point
map.events.triggerEvent("mousedown", {xy: new OpenLayers.Pixel(0, 0)});
map.events.triggerEvent("mousemove", {xy: new OpenLayers.Pixel(10, 10)});
t.eq(log.event.type, "sketchmodified", "[mousemove] sketchmodified triggered");
t.geom_eq(log.event.vertex, new OpenLayers.Geometry.Point(-190, 115), "[mousemove] correct vertex");
map.events.triggerEvent("mouseup", {xy: new OpenLayers.Pixel(10, 10)});
t.eq(log.event.type, "sketchcomplete", "[mouseup] sketchcomplete triggered");
t.geom_eq(log.event.feature.geometry, new OpenLayers.Geometry.Point(-190, 115), "[mouseup] correct geometry");
map.destroy();
}
</script> </script>
</head> </head>

View File

@@ -337,7 +337,64 @@
control.destroy(); control.destroy();
layer.destroy(); layer.destroy();
} }
function test_dragVertex(t) {
t.plan(8);
var map = new OpenLayers.Map("map", {
resolutions: [1]
});
var layer = new OpenLayers.Layer.Vector("foo", {
maxExtent: new OpenLayers.Bounds(-10, -10, 10, 10),
isBaseLayer: true
});
map.addLayer(layer);
var control = new OpenLayers.Control.ModifyFeature(layer);
map.addControl(control);
control.activate();
map.zoomToMaxExtent();
var log = {};
layer.events.on({
"vertexmodified": function(event) {
log.event = event;
}
});
// pretend to drag a point
var feature = new OpenLayers.Feature.Vector(
new OpenLayers.Geometry.Point(0, 0)
);
control.feature = feature;
var pixel = new OpenLayers.Pixel(-100, 100);
control.dragVertex(feature, pixel);
t.eq(log.event.type, "vertexmodified", "[drag point] vertexmodified triggered");
t.geom_eq(log.event.vertex, feature.geometry, "[drag point] listeners receive correct vertex");
t.eq(log.event.feature.id, feature.id, "[drag point] listeners receive correct feature");
t.ok(log.event.pixel === pixel, "[drag point] listeners receive correct pixel");
// pretend to drag vertex of a linestring
var vert = new OpenLayers.Feature.Vector(
new OpenLayers.Geometry.Point(0, 0)
);
var feature = new OpenLayers.Feature.Vector(
new OpenLayers.Geometry.LineString([
vert.geometry, new OpenLayers.Geometry.Point(10, 0)
])
);
control.feature = feature;
var pixel = new OpenLayers.Pixel(-100, 100);
control.dragVertex(vert, pixel);
t.eq(log.event.type, "vertexmodified", "[drag vertex] vertexmodified triggered");
t.geom_eq(log.event.vertex, vert.geometry, "[drag vertex] listeners receive correct vertex");
t.eq(log.event.feature.id, feature.id, "[drag vertex] listeners receive correct feature");
t.ok(log.event.pixel === pixel, "[drag vertex] listeners receive correct pixel");
map.destroy();
}
function test_onDrag(t) { function test_onDrag(t) {
t.plan(1); t.plan(1);
@@ -477,7 +534,7 @@
} }
function test_onModificationEnd(t) { function test_onModificationEnd(t) {
t.plan(2); t.plan(3);
var map = new OpenLayers.Map("map"); var map = new OpenLayers.Map("map");
var layer = new OpenLayers.Layer.Vector(); var layer = new OpenLayers.Layer.Vector();
map.addLayer(layer); map.addLayer(layer);
@@ -491,6 +548,7 @@
); );
layer.events.on({"afterfeaturemodified": function(event) { layer.events.on({"afterfeaturemodified": function(event) {
t.eq(event.feature.id, testFeature.id, "afterfeaturemodified triggered"); t.eq(event.feature.id, testFeature.id, "afterfeaturemodified triggered");
t.eq(event.modified, false, "afterfeaturemodified event given proper modified property (false - feature was not modified in this case)");
}}); }});
control.onModificationEnd = function(feature) { control.onModificationEnd = function(feature) {
t.eq(feature.id, testFeature.id, t.eq(feature.id, testFeature.id,