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