]> dev.renevier.net Git - syp.git/blob - openlayers/lib/OpenLayers/Handler/Point.js
initial commit
[syp.git] / openlayers / lib / OpenLayers / Handler / Point.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.js
8  * @requires OpenLayers/Geometry/Point.js
9  */
10
11 /**
12  * Class: OpenLayers.Handler.Point
13  * Handler to draw a point on the map.  Point is displayed on mouse down,
14  *     moves on mouse move, and is finished on mouse up.  The handler triggers
15  *     callbacks for 'done', 'cancel', and 'modify'.  The modify callback is
16  *     called with each change in the sketch and will receive the latest point
17  *     drawn.  Create a new instance with the <OpenLayers.Handler.Point>
18  *     constructor.
19  * 
20  * Inherits from:
21  *  - <OpenLayers.Handler>
22  */
23 OpenLayers.Handler.Point = OpenLayers.Class(OpenLayers.Handler, {
24     
25     /**
26      * Property: point
27      * {<OpenLayers.Feature.Vector>} The currently drawn point
28      */
29     point: null,
30
31     /**
32      * Property: layer
33      * {<OpenLayers.Layer.Vector>} The temporary drawing layer
34      */
35     layer: null,
36     
37     /**
38      * Property: multi
39      * {Boolean} Cast features to multi-part geometries before passing to the
40      *     layer.  Default is false.
41      */
42     multi: false,
43     
44     /**
45      * Property: drawing 
46      * {Boolean} A point is being drawn
47      */
48     drawing: false,
49     
50     /**
51      * Property: mouseDown
52      * {Boolean} The mouse is down
53      */
54     mouseDown: false,
55
56     /**
57      * Property: lastDown
58      * {<OpenLayers.Pixel>} Location of the last mouse down
59      */
60     lastDown: null,
61
62     /**
63      * Property: lastUp
64      * {<OpenLayers.Pixel>}
65      */
66     lastUp: null,
67
68     /**
69      * APIProperty: persist
70      * {Boolean} Leave the feature rendered until destroyFeature is called.
71      *     Default is false.  If set to true, the feature remains rendered until
72      *     destroyFeature is called, typically by deactivating the handler or
73      *     starting another drawing.
74      */
75     persist: false,
76
77     /**
78      * Property: layerOptions
79      * {Object} Any optional properties to be set on the sketch layer.
80      */
81     layerOptions: null,
82
83     /**
84      * Constructor: OpenLayers.Handler.Point
85      * Create a new point handler.
86      *
87      * Parameters:
88      * control - {<OpenLayers.Control>} The control that owns this handler
89      * callbacks - {Object} An object with a properties whose values are
90      *     functions.  Various callbacks described below.
91      * options - {Object} An optional object with properties to be set on the
92      *           handler
93      *
94      * Named callbacks:
95      * create - Called when a sketch is first created.  Callback called with
96      *     the creation point geometry and sketch feature.
97      * modify - Called with each move of a vertex with the vertex (point)
98      *     geometry and the sketch feature.
99      * done - Called when the point drawing is finished.  The callback will
100      *     recieve a single argument, the point geometry.
101      * cancel - Called when the handler is deactivated while drawing.  The
102      *     cancel callback will receive a geometry.
103      */
104     initialize: function(control, callbacks, options) {
105         if(!(options && options.layerOptions && options.layerOptions.styleMap)) {
106             this.style = OpenLayers.Util.extend(OpenLayers.Feature.Vector.style['default'], {});
107         }
108
109         OpenLayers.Handler.prototype.initialize.apply(this, arguments);
110     },
111     
112     /**
113      * APIMethod: activate
114      * turn on the handler
115      */
116     activate: function() {
117         if(!OpenLayers.Handler.prototype.activate.apply(this, arguments)) {
118             return false;
119         }
120         // create temporary vector layer for rendering geometry sketch
121         // TBD: this could be moved to initialize/destroy - setting visibility here
122         var options = OpenLayers.Util.extend({
123             displayInLayerSwitcher: false,
124             // indicate that the temp vector layer will never be out of range
125             // without this, resolution properties must be specified at the
126             // map-level for this temporary layer to init its resolutions
127             // correctly
128             calculateInRange: function() { return true; }
129         }, this.layerOptions);
130         this.layer = new OpenLayers.Layer.Vector(this.CLASS_NAME, options);
131         this.map.addLayer(this.layer);
132         return true;
133     },
134     
135     /**
136      * Method: createFeature
137      * Add temporary features
138      *
139      * Parameters:
140      * pixel - {<OpenLayers.Pixel>} A pixel location on the map.
141      */
142     createFeature: function(pixel) {
143         var lonlat = this.map.getLonLatFromPixel(pixel);
144         this.point = new OpenLayers.Feature.Vector(
145             new OpenLayers.Geometry.Point(lonlat.lon, lonlat.lat)
146         );
147         this.callback("create", [this.point.geometry, this.point]);
148         this.point.geometry.clearBounds();
149         this.layer.addFeatures([this.point], {silent: true});
150     },
151
152     /**
153      * APIMethod: deactivate
154      * turn off the handler
155      */
156     deactivate: function() {
157         if(!OpenLayers.Handler.prototype.deactivate.apply(this, arguments)) {
158             return false;
159         }
160         // call the cancel callback if mid-drawing
161         if(this.drawing) {
162             this.cancel();
163         }
164         this.destroyFeature();
165         // If a layer's map property is set to null, it means that that layer
166         // isn't added to the map. Since we ourself added the layer to the map
167         // in activate(), we can assume that if this.layer.map is null it means
168         // that the layer has been destroyed (as a result of map.destroy() for
169         // example.
170         if (this.layer.map != null) {
171             this.layer.destroy(false);
172         }
173         this.layer = null;
174         return true;
175     },
176     
177     /**
178      * Method: destroyFeature
179      * Destroy the temporary geometries
180      */
181     destroyFeature: function() {
182         if(this.layer) {
183             this.layer.destroyFeatures();
184         }
185         this.point = null;
186     },
187
188     /**
189      * Method: finalize
190      * Finish the geometry and call the "done" callback.
191      *
192      * Parameters:
193      * cancel - {Boolean} Call cancel instead of done callback.  Default is
194      *     false.
195      */
196     finalize: function(cancel) {
197         var key = cancel ? "cancel" : "done";
198         this.drawing = false;
199         this.mouseDown = false;
200         this.lastDown = null;
201         this.lastUp = null;
202         this.callback(key, [this.geometryClone()]);
203         if(cancel || !this.persist) {
204             this.destroyFeature();
205         }
206     },
207
208     /**
209      * APIMethod: cancel
210      * Finish the geometry and call the "cancel" callback.
211      */
212     cancel: function() {
213         this.finalize(true);
214     },
215
216     /**
217      * Method: click
218      * Handle clicks.  Clicks are stopped from propagating to other listeners
219      *     on map.events or other dom elements.
220      * 
221      * Parameters:
222      * evt - {Event} The browser event
223      *
224      * Returns: 
225      * {Boolean} Allow event propagation
226      */
227     click: function(evt) {
228         OpenLayers.Event.stop(evt);
229         return false;
230     },
231
232     /**
233      * Method: dblclick
234      * Handle double-clicks.  Double-clicks are stopped from propagating to other
235      *     listeners on map.events or other dom elements.
236      * 
237      * Parameters:
238      * evt - {Event} The browser event
239      *
240      * Returns: 
241      * {Boolean} Allow event propagation
242      */
243     dblclick: function(evt) {
244         OpenLayers.Event.stop(evt);
245         return false;
246     },
247     
248     /**
249      * Method: modifyFeature
250      * Modify the existing geometry given a pixel location.
251      *
252      * Parameters:
253      * pixel - {<OpenLayers.Pixel>} A pixel location on the map.
254      */
255     modifyFeature: function(pixel) {
256         var lonlat = this.map.getLonLatFromPixel(pixel);
257         this.point.geometry.x = lonlat.lon;
258         this.point.geometry.y = lonlat.lat;
259         this.callback("modify", [this.point.geometry, this.point]);
260         this.point.geometry.clearBounds();
261         this.drawFeature();
262     },
263
264     /**
265      * Method: drawFeature
266      * Render features on the temporary layer.
267      */
268     drawFeature: function() {
269         this.layer.drawFeature(this.point, this.style);
270     },
271     
272     /**
273      * Method: getGeometry
274      * Return the sketch geometry.  If <multi> is true, this will return
275      *     a multi-part geometry.
276      *
277      * Returns:
278      * {<OpenLayers.Geometry.Point>}
279      */
280     getGeometry: function() {
281         var geometry = this.point && this.point.geometry;
282         if(geometry && this.multi) {
283             geometry = new OpenLayers.Geometry.MultiPoint([geometry]);
284         }
285         return geometry;
286     },
287
288     /**
289      * Method: geometryClone
290      * Return a clone of the relevant geometry.
291      *
292      * Returns:
293      * {<OpenLayers.Geometry>}
294      */
295     geometryClone: function() {
296         var geom = this.getGeometry();
297         return geom && geom.clone();
298     },
299   
300     /**
301      * Method: mousedown
302      * Handle mouse down.  Adjust the geometry and redraw.
303      * Return determines whether to propagate the event on the map.
304      * 
305      * Parameters:
306      * evt - {Event} The browser event
307      *
308      * Returns: 
309      * {Boolean} Allow event propagation
310      */
311     mousedown: function(evt) {
312         // check keyboard modifiers
313         if(!this.checkModifiers(evt)) {
314             return true;
315         }
316         // ignore double-clicks
317         if(this.lastDown && this.lastDown.equals(evt.xy)) {
318             return true;
319         }
320         this.drawing = true;
321         if(this.lastDown == null) {
322             if(this.persist) {
323                 this.destroyFeature();
324             }
325             this.createFeature(evt.xy);
326         } else {
327             this.modifyFeature(evt.xy);
328         }
329         this.lastDown = evt.xy;
330         return false;
331     },
332
333     /**
334      * Method: mousemove
335      * Handle mouse move.  Adjust the geometry and redraw.
336      * Return determines whether to propagate the event on the map.
337      * 
338      * Parameters:
339      * evt - {Event} The browser event
340      *
341      * Returns: 
342      * {Boolean} Allow event propagation
343      */
344     mousemove: function (evt) {
345         if(this.drawing) {
346             this.modifyFeature(evt.xy);
347         }
348         return true;
349     },
350
351     /**
352      * Method: mouseup
353      * Handle mouse up.  Send the latest point in the geometry to the control.
354      * Return determines whether to propagate the event on the map.
355      *
356      * Parameters:
357      * evt - {Event} The browser event
358      *
359      * Returns: 
360      * {Boolean} Allow event propagation
361      */
362     mouseup: function (evt) {
363         if(this.drawing) {
364             this.finalize();
365             return false;
366         } else {
367             return true;
368         }
369     },
370
371     CLASS_NAME: "OpenLayers.Handler.Point"
372 });