diff --git a/examples/drag-feature.html b/examples/drag-feature.html new file mode 100644 index 0000000000..8dfe33958c --- /dev/null +++ b/examples/drag-feature.html @@ -0,0 +1,97 @@ + + + Drag Feature + + + + + +

OpenLayers Drag Feature Example

+
+
+ +
+ + diff --git a/lib/OpenLayers.js b/lib/OpenLayers.js index 29b4139028..b73bdf4776 100644 --- a/lib/OpenLayers.js +++ b/lib/OpenLayers.js @@ -138,6 +138,7 @@ "OpenLayers/Control/Scale.js", "OpenLayers/Control/LayerSwitcher.js", "OpenLayers/Control/DrawFeature.js", + "OpenLayers/Control/DragFeature.js", "OpenLayers/Control/Panel.js", "OpenLayers/Control/SelectFeature.js", "OpenLayers/Geometry.js", diff --git a/lib/OpenLayers/Control/DragFeature.js b/lib/OpenLayers/Control/DragFeature.js new file mode 100644 index 0000000000..fc37f04aff --- /dev/null +++ b/lib/OpenLayers/Control/DragFeature.js @@ -0,0 +1,285 @@ +/* Copyright (c) 2006 MetaCarta, Inc., published under a modified BSD license. + * See http://svn.openlayers.org/trunk/openlayers/repository-license.txt + * for the full text of the license. */ + + +/** + * @requires OpenLayers/Control.js + * @requires OpenLayers/Handler/Drag.js + * @requires OpenLayers/Handler/Feature.js + * + * Class: OpenLayers.Control.DragFeature + * Move a feature with a drag. Create a new control with the + * constructor. + * + * Inherits From: + * - + */ +OpenLayers.Control.DragFeature = OpenLayers.Class(OpenLayers.Control, { + + /** + * APIProperty: geometryTypes + * {Array(String)} To restrict dragging to a limited set of geometry types, + * send a list of strings corresponding to the geometry class names. + */ + geometryTypes: null, + + /** + * APIProperty: onDrag + * {Function} Define this function if you want to know about each move of a + * feature. The function should expect to receive two arguments: the + * feature that is being dragged and the pixel location of the mouse. + * + * Parameters: + * feature - {OpenLayers.Feature.Vector} The feature that was dragged. + * pixel - {OpenLayers.Pixel} The pixel location of the mouse. + */ + onDrag: function(feature, pixel) {}, + + /** + * APIProperty: onComplete + * {Function} Define this function if you want to know when a feature is + * done dragging. The function should expect to receive two arguments: + * the feature that is being dragged and the pixel location of the + * mouse. + * + * Parameters: + * feature - {OpenLayers.Feature.Vector} The feature that was dragged. + * pixel - {OpenLayers.Pixel} The pixel location of the mouse. + */ + onComplete: function(feature, pixel) {}, + + /** + * Property: layer + * {OpenLayers.Layer.Vector} + */ + layer: null, + + /** + * Property: feature + * {OpenLayers.Feature.Vector} + */ + feature: null, + + /** + * Property: dragHandler + * {OpenLayers.Handler.Drag} + */ + dragHandler: null, + + /** + * Property: dragCallbacks + * {Object} The functions that are sent to the drag handler for callback. + */ + dragCallbacks: {}, + + /** + * Property: featureHandler + * {OpenLayers.Handler.Feature} + */ + featureHandler: null, + + /** + * Property: featureCallbacks + * {Object} The functions that are sent to the feature handler for callback. + */ + featureCallbacks: {}, + + /** + * Property: lastPixel + * {OpenLayers.Pixel} + */ + lastPixel: null, + + /** + * Constructor: OpenLayers.Control.DragFeature + * Create a new control to drag features. + * + * Parameters: + * layer - {OpenLayers.Layer.Vector} The layer containing features to be + * dragged. + * options - {Object} Optional object whose properties will be set on the + * control. + */ + initialize: function(layer, options) { + OpenLayers.Control.prototype.initialize.apply(this, [options]); + this.layer = layer; + this.dragCallbacks = OpenLayers.Util.extend({down: this.downFeature, + move: this.moveFeature, + up: this.upFeature, + out: this.cancel, + done: this.doneDragging + }, this.dragCallbacks); + this.dragHandler = new OpenLayers.Handler.Drag(this, this.dragCallbacks); + this.featureCallbacks = OpenLayers.Util.extend({over: this.overFeature, + out: this.outFeature + }, this.featureCallbacks); + var handlerOptions = {geometryTypes: this.geometryTypes}; + this.featureHandler = new OpenLayers.Handler.Feature(this, this.layer, + this.featureCallbacks, + handlerOptions); + }, + + /** + * APIMethod: destroy + * Take care of things that are not handled in superclass + */ + destroy: function() { + this.layer = null; + this.dragHandler.destroy(); + this.featureHandler.destroy(); + OpenLayers.Control.prototype.destroy.apply(this, []); + }, + + /** + * APIMethod: activate + * Activate the control and the feature handler. + * + * Returns: + * {Boolean} Successfully activated the control and feature handler. + */ + activate: function() { + return (this.featureHandler.activate() && + OpenLayers.Control.prototype.activate.apply(this, arguments)); + }, + + /** + * APIMethod: deactivate + * Deactivate the control and all handlers. + * + * Returns: + * {Boolean} Successfully deactivated the control. + */ + deactivate: function() { + // the return from the handlers is unimportant in this case + this.dragHandler.deactivate(); + this.featureHandler.deactivate(); + return OpenLayers.Control.prototype.deactivate.apply(this, arguments); + }, + + /** + * Method: overFeature + * Called when the feature handler detects a mouse-over on a feature. + * This activates the drag handler. + * + * Parameters: + * feature - {OpenLayers.Feature.Vector} The selected feature. + */ + overFeature: function(feature) { + if(!this.dragHandler.dragging) { + this.feature = feature; + this.dragHandler.activate(); + this.over = true; + // TBD replace with CSS classes + this.map.div.style.cursor = "move"; + } else { + if(this.feature.id == feature.id) { + this.over = true; + } else { + this.over = false; + } + } + }, + + /** + * Method: downFeature + * Called when the drag handler detects a mouse-down. + * + * Parameters: + * pixel - {OpenLayers.Pixel} Location of the mouse event. + */ + downFeature: function(pixel) { + this.dragHandler.dragging = true; + this.lastPixel = pixel; + }, + + /** + * Method: moveFeature + * Called when the drag handler detects a mouse-move. Also calls the + * optional onDrag method. + * + * Parameters: + * pixel - {OpenLayers.Pixel} Location of the mouse event. + */ + moveFeature: function(pixel) { + var res = this.map.getResolution(); + this.feature.geometry.move(res * (pixel.x - this.lastPixel.x), + res * (this.lastPixel.y - pixel.y)); + this.layer.drawFeature(this.feature); + this.lastPixel = pixel; + this.onDrag(this.feature, pixel); + }, + + /** + * Method: upFeature + * Called when the drag handler detects a mouse-up. Also calls the + * optional onComplete method. + * + * Parameters: + * pixel - {OpenLayers.Pixel} Location of the mouse event. + */ + upFeature: function(pixel) { + if(!this.over) { + this.dragHandler.deactivate(); + this.feature = null; + // TBD replace with CSS classes + this.map.div.style.cursor = "default"; + } + }, + + /** + * Method: doneDragging + * Called when the drag handler is done dragging. + * + * Parameters: + * pixel - {OpenLayers.Pixel} The last event pixel location. If this event + * came from a mouseout, this may not be in the map viewport. + */ + doneDragging: function(pixel) { + this.onComplete(this.feature, pixel); + }, + + /** + * Method: outFeature + * Called when the feature handler detects a mouse-out on a feature. + * + * Parameters: + * feature - {OpenLayers.Feature.Vector} The feature that the mouse left. + */ + outFeature: function(feature) { + if(!this.dragHandler.dragging) { + this.over = false; + this.dragHandler.deactivate(); + // TBD replace with CSS classes + this.map.div.style.cursor = "default"; + } else { + if(this.feature.id == feature.id) { + this.over = false; + } + } + }, + + /** + * Method: cancel + * Called when the drag handler detects a mouse-out (from the map viewport). + */ + cancel: function() { + this.dragHandler.deactivate(); + this.over = false; + }, + + /** + * Method: setMap + * Set the map property for the control and all handlers. + * + * Parameters: + * map - {OpenLayers.Map} The control's map. + */ + setMap: function(map) { + this.dragHandler.setMap(map); + this.featureHandler.setMap(map); + OpenLayers.Control.prototype.setMap.apply(this, arguments); + }, + + CLASS_NAME: "OpenLayers.Control.DragFeature" +}); diff --git a/tests/Control/test_DragFeature.html b/tests/Control/test_DragFeature.html new file mode 100644 index 0000000000..59e64f6982 --- /dev/null +++ b/tests/Control/test_DragFeature.html @@ -0,0 +1,173 @@ + + + + + + +
+ + diff --git a/tests/list-tests.html b/tests/list-tests.html index 5ff8756d73..177ce47a97 100644 --- a/tests/list-tests.html +++ b/tests/list-tests.html @@ -58,6 +58,7 @@
  • test_Tile.html
  • Tile/test_Image.html
  • test_Control.html
  • +
  • Control/test_DragFeature.html
  • Control/test_DragPan.html
  • Control/test_OverviewMap.html
  • Control/test_NavToolbar.html