1 /* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
2 * license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the
3 * full text of the license. */
7 * @requires OpenLayers/Handler/Point.js
8 * @requires OpenLayers/Geometry/Point.js
9 * @requires OpenLayers/Geometry/LineString.js
13 * Class: OpenLayers.Handler.Path
14 * Handler to draw a path on the map. Path is displayed on mouse down,
15 * moves on mouse move, and is finished on mouse up.
18 * - <OpenLayers.Handler.Point>
20 OpenLayers.Handler.Path = OpenLayers.Class(OpenLayers.Handler.Point, {
24 * {<OpenLayers.Feature.Vector>}
30 * {Boolean} In freehand mode, the handler starts the path on mouse down,
31 * adds a point for every mouse move, and finishes the path on mouse up.
32 * Outside of freehand mode, a point is added to the path on every mouse
33 * click and double-click finishes the path.
38 * Property: freehandToggle
39 * {String} If set, freehandToggle is checked on mouse events and will set
40 * the freehand mode to the opposite of this.freehand. To disallow
41 * toggling between freehand and non-freehand mode, set freehandToggle to
42 * null. Acceptable toggle values are 'shiftKey', 'ctrlKey', and 'altKey'.
44 freehandToggle: 'shiftKey',
47 * Constructor: OpenLayers.Handler.Path
48 * Create a new path hander
51 * control - {<OpenLayers.Control>} The control that owns this handler
52 * callbacks - {Object} An object with a properties whose values are
53 * functions. Various callbacks described below.
54 * options - {Object} An optional object with properties to be set on the
58 * create - Called when a sketch is first created. Callback called with
59 * the creation point geometry and sketch feature.
60 * modify - Called with each move of a vertex with the vertex (point)
61 * geometry and the sketch feature.
62 * point - Called as each point is added. Receives the new point geometry.
63 * done - Called when the point drawing is finished. The callback will
64 * recieve a single argument, the linestring geometry.
65 * cancel - Called when the handler is deactivated while drawing. The
66 * cancel callback will receive a geometry.
68 initialize: function(control, callbacks, options) {
69 OpenLayers.Handler.Point.prototype.initialize.apply(this, arguments);
73 * Method: createFeature
74 * Add temporary geometries
77 * pixel - {<OpenLayers.Pixel>} The initial pixel location for the new
80 createFeature: function(pixel) {
81 var lonlat = this.control.map.getLonLatFromPixel(pixel);
82 this.point = new OpenLayers.Feature.Vector(
83 new OpenLayers.Geometry.Point(lonlat.lon, lonlat.lat)
85 this.line = new OpenLayers.Feature.Vector(
86 new OpenLayers.Geometry.LineString([this.point.geometry])
88 this.callback("create", [this.point.geometry, this.getSketch()]);
89 this.point.geometry.clearBounds();
90 this.layer.addFeatures([this.line, this.point], {silent: true});
94 * Method: destroyFeature
95 * Destroy temporary geometries
97 destroyFeature: function() {
98 OpenLayers.Handler.Point.prototype.destroyFeature.apply(this);
103 * Method: removePoint
104 * Destroy the temporary point.
106 removePoint: function() {
108 this.layer.removeFeatures([this.point]);
114 * Add point to geometry. Send the point index to override
115 * the behavior of LinearRing that disregards adding duplicate points.
118 * pixel - {<OpenLayers.Pixel>} The pixel location for the new point.
120 addPoint: function(pixel) {
121 this.layer.removeFeatures([this.point]);
122 var lonlat = this.control.map.getLonLatFromPixel(pixel);
123 this.point = new OpenLayers.Feature.Vector(
124 new OpenLayers.Geometry.Point(lonlat.lon, lonlat.lat)
126 this.line.geometry.addComponent(
127 this.point.geometry, this.line.geometry.components.length
129 this.callback("point", [this.point.geometry, this.getGeometry()]);
130 this.callback("modify", [this.point.geometry, this.getSketch()]);
135 * Method: freehandMode
136 * Determine whether to behave in freehand mode or not.
141 freehandMode: function(evt) {
142 return (this.freehandToggle && evt[this.freehandToggle]) ?
143 !this.freehand : this.freehand;
147 * Method: modifyFeature
148 * Modify the existing geometry given the new point
151 * pixel - {<OpenLayers.Pixel>} The updated pixel location for the latest
154 modifyFeature: function(pixel) {
155 var lonlat = this.control.map.getLonLatFromPixel(pixel);
156 this.point.geometry.x = lonlat.lon;
157 this.point.geometry.y = lonlat.lat;
158 this.callback("modify", [this.point.geometry, this.getSketch()]);
159 this.point.geometry.clearBounds();
164 * Method: drawFeature
165 * Render geometries on the temporary layer.
167 drawFeature: function() {
168 this.layer.drawFeature(this.line, this.style);
169 this.layer.drawFeature(this.point, this.style);
174 * Return the sketch feature.
177 * {<OpenLayers.Feature.Vector>}
179 getSketch: function() {
184 * Method: getGeometry
185 * Return the sketch geometry. If <multi> is true, this will return
186 * a multi-part geometry.
189 * {<OpenLayers.Geometry.LineString>}
191 getGeometry: function() {
192 var geometry = this.line && this.line.geometry;
193 if(geometry && this.multi) {
194 geometry = new OpenLayers.Geometry.MultiLineString([geometry]);
201 * Handle mouse down. Add a new point to the geometry and
202 * render it. Return determines whether to propagate the event on the map.
205 * evt - {Event} The browser event
208 * {Boolean} Allow event propagation
210 mousedown: function(evt) {
211 // ignore double-clicks
212 if (this.lastDown && this.lastDown.equals(evt.xy)) {
215 if(this.lastDown == null) {
217 this.destroyFeature();
219 this.createFeature(evt.xy);
220 } else if((this.lastUp == null) || !this.lastUp.equals(evt.xy)) {
221 this.addPoint(evt.xy);
223 this.mouseDown = true;
224 this.lastDown = evt.xy;
231 * Handle mouse move. Adjust the geometry and redraw.
232 * Return determines whether to propagate the event on the map.
235 * evt - {Event} The browser event
238 * {Boolean} Allow event propagation
240 mousemove: function (evt) {
242 if(this.mouseDown && this.freehandMode(evt)) {
243 this.addPoint(evt.xy);
245 this.modifyFeature(evt.xy);
253 * Handle mouse up. Send the latest point in the geometry to
254 * the control. Return determines whether to propagate the event on the map.
257 * evt - {Event} The browser event
260 * {Boolean} Allow event propagation
262 mouseup: function (evt) {
263 this.mouseDown = false;
265 if(this.freehandMode(evt)) {
269 if(this.lastUp == null) {
270 this.addPoint(evt.xy);
272 this.lastUp = evt.xy;
281 * Handle double-clicks. Finish the geometry and send it back
285 * evt - {Event} The browser event
288 * {Boolean} Allow event propagation
290 dblclick: function(evt) {
291 if(!this.freehandMode(evt)) {
292 var index = this.line.geometry.components.length - 1;
293 this.line.geometry.removeComponent(this.line.geometry.components[index]);
300 CLASS_NAME: "OpenLayers.Handler.Path"