]> dev.renevier.net Git - syp.git/blob - openlayers/lib/OpenLayers/Handler/Path.js
fixes notices
[syp.git] / openlayers / lib / OpenLayers / Handler / Path.js
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. */
4
5
6 /**
7  * @requires OpenLayers/Handler/Point.js
8  * @requires OpenLayers/Geometry/Point.js
9  * @requires OpenLayers/Geometry/LineString.js
10  */
11
12 /**
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.
16  *
17  * Inherits from:
18  *  - <OpenLayers.Handler.Point>
19  */
20 OpenLayers.Handler.Path = OpenLayers.Class(OpenLayers.Handler.Point, {
21     
22     /**
23      * Property: line
24      * {<OpenLayers.Feature.Vector>}
25      */
26     line: null,
27     
28     /**
29      * Property: freehand
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.
34      */
35     freehand: false,
36     
37     /**
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'.
43      */
44     freehandToggle: 'shiftKey',
45
46     /**
47      * Constructor: OpenLayers.Handler.Path
48      * Create a new path hander
49      *
50      * Parameters:
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
55      *           handler
56      *
57      * Named callbacks:
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.
67      */
68     initialize: function(control, callbacks, options) {
69         OpenLayers.Handler.Point.prototype.initialize.apply(this, arguments);
70     },
71         
72     /**
73      * Method: createFeature
74      * Add temporary geometries
75      *
76      * Parameters:
77      * pixel - {<OpenLayers.Pixel>} The initial pixel location for the new
78      *     feature.
79      */
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)
84         );
85         this.line = new OpenLayers.Feature.Vector(
86             new OpenLayers.Geometry.LineString([this.point.geometry])
87         );
88         this.callback("create", [this.point.geometry, this.getSketch()]);
89         this.point.geometry.clearBounds();
90         this.layer.addFeatures([this.line, this.point], {silent: true});
91     },
92         
93     /**
94      * Method: destroyFeature
95      * Destroy temporary geometries
96      */
97     destroyFeature: function() {
98         OpenLayers.Handler.Point.prototype.destroyFeature.apply(this);
99         this.line = null;
100     },
101
102     /**
103      * Method: removePoint
104      * Destroy the temporary point.
105      */
106     removePoint: function() {
107         if(this.point) {
108             this.layer.removeFeatures([this.point]);
109         }
110     },
111     
112     /**
113      * Method: addPoint
114      * Add point to geometry.  Send the point index to override
115      * the behavior of LinearRing that disregards adding duplicate points.
116      *
117      * Parameters:
118      * pixel - {<OpenLayers.Pixel>} The pixel location for the new point.
119      */
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)
125         );
126         this.line.geometry.addComponent(
127             this.point.geometry, this.line.geometry.components.length
128         );
129         this.callback("point", [this.point.geometry, this.getGeometry()]);
130         this.callback("modify", [this.point.geometry, this.getSketch()]);
131         this.drawFeature();
132     },
133     
134     /**
135      * Method: freehandMode
136      * Determine whether to behave in freehand mode or not.
137      *
138      * Returns:
139      * {Boolean}
140      */
141     freehandMode: function(evt) {
142         return (this.freehandToggle && evt[this.freehandToggle]) ?
143                     !this.freehand : this.freehand;
144     },
145
146     /**
147      * Method: modifyFeature
148      * Modify the existing geometry given the new point
149      *
150      * Parameters:
151      * pixel - {<OpenLayers.Pixel>} The updated pixel location for the latest
152      *     point.
153      */
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();
160         this.drawFeature();
161     },
162
163     /**
164      * Method: drawFeature
165      * Render geometries on the temporary layer.
166      */
167     drawFeature: function() {
168         this.layer.drawFeature(this.line, this.style);
169         this.layer.drawFeature(this.point, this.style);
170     },
171
172     /**
173      * Method: getSketch
174      * Return the sketch feature.
175      *
176      * Returns:
177      * {<OpenLayers.Feature.Vector>}
178      */
179     getSketch: function() {
180         return this.line;
181     },
182
183     /**
184      * Method: getGeometry
185      * Return the sketch geometry.  If <multi> is true, this will return
186      *     a multi-part geometry.
187      *
188      * Returns:
189      * {<OpenLayers.Geometry.LineString>}
190      */
191     getGeometry: function() {
192         var geometry = this.line && this.line.geometry;
193         if(geometry && this.multi) {
194             geometry = new OpenLayers.Geometry.MultiLineString([geometry]);
195         }
196         return geometry;
197     },
198
199     /**
200      * Method: mousedown
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.
203      * 
204      * Parameters:
205      * evt - {Event} The browser event
206      *
207      * Returns: 
208      * {Boolean} Allow event propagation
209      */
210     mousedown: function(evt) {
211         // ignore double-clicks
212         if (this.lastDown && this.lastDown.equals(evt.xy)) {
213             return false;
214         }
215         if(this.lastDown == null) {
216             if(this.persist) {
217                 this.destroyFeature();
218             }
219             this.createFeature(evt.xy);
220         } else if((this.lastUp == null) || !this.lastUp.equals(evt.xy)) {
221             this.addPoint(evt.xy);
222         }
223         this.mouseDown = true;
224         this.lastDown = evt.xy;
225         this.drawing = true;
226         return false;
227     },
228
229     /**
230      * Method: mousemove
231      * Handle mouse move.  Adjust the geometry and redraw.
232      * Return determines whether to propagate the event on the map.
233      * 
234      * Parameters:
235      * evt - {Event} The browser event
236      *
237      * Returns: 
238      * {Boolean} Allow event propagation
239      */
240     mousemove: function (evt) {
241         if(this.drawing) { 
242             if(this.mouseDown && this.freehandMode(evt)) {
243                 this.addPoint(evt.xy);
244             } else {
245                 this.modifyFeature(evt.xy);
246             }
247         }
248         return true;
249     },
250     
251     /**
252      * Method: mouseup
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.
255      * 
256      * Parameters:
257      * evt - {Event} The browser event
258      *
259      * Returns: 
260      * {Boolean} Allow event propagation
261      */
262     mouseup: function (evt) {
263         this.mouseDown = false;
264         if(this.drawing) {
265             if(this.freehandMode(evt)) {
266                 this.removePoint();
267                 this.finalize();
268             } else {
269                 if(this.lastUp == null) {
270                    this.addPoint(evt.xy);
271                 }
272                 this.lastUp = evt.xy;
273             }
274             return false;
275         }
276         return true;
277     },
278   
279     /**
280      * Method: dblclick 
281      * Handle double-clicks.  Finish the geometry and send it back
282      * to the control.
283      * 
284      * Parameters:
285      * evt - {Event} The browser event
286      *
287      * Returns: 
288      * {Boolean} Allow event propagation
289      */
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]);
294             this.removePoint();
295             this.finalize();
296         }
297         return false;
298     },
299
300     CLASS_NAME: "OpenLayers.Handler.Path"
301 });