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.js
8 * @requires OpenLayers/Geometry/Point.js
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>
21 * - <OpenLayers.Handler>
23 OpenLayers.Handler.Point = OpenLayers.Class(OpenLayers.Handler, {
27 * {<OpenLayers.Feature.Vector>} The currently drawn point
33 * {<OpenLayers.Layer.Vector>} The temporary drawing layer
39 * {Boolean} Cast features to multi-part geometries before passing to the
40 * layer. Default is false.
46 * {Boolean} A point is being drawn
52 * {Boolean} The mouse is down
58 * {<OpenLayers.Pixel>} Location of the last mouse down
64 * {<OpenLayers.Pixel>}
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.
78 * Property: layerOptions
79 * {Object} Any optional properties to be set on the sketch layer.
84 * Constructor: OpenLayers.Handler.Point
85 * Create a new point handler.
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
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.
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'], {});
109 OpenLayers.Handler.prototype.initialize.apply(this, arguments);
113 * APIMethod: activate
114 * turn on the handler
116 activate: function() {
117 if(!OpenLayers.Handler.prototype.activate.apply(this, arguments)) {
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
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);
136 * Method: createFeature
137 * Add temporary features
140 * pixel - {<OpenLayers.Pixel>} A pixel location on the map.
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)
147 this.callback("create", [this.point.geometry, this.point]);
148 this.point.geometry.clearBounds();
149 this.layer.addFeatures([this.point], {silent: true});
153 * APIMethod: deactivate
154 * turn off the handler
156 deactivate: function() {
157 if(!OpenLayers.Handler.prototype.deactivate.apply(this, arguments)) {
160 // call the cancel callback if mid-drawing
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
170 if (this.layer.map != null) {
171 this.layer.destroy(false);
178 * Method: destroyFeature
179 * Destroy the temporary geometries
181 destroyFeature: function() {
183 this.layer.destroyFeatures();
190 * Finish the geometry and call the "done" callback.
193 * cancel - {Boolean} Call cancel instead of done callback. Default is
196 finalize: function(cancel) {
197 var key = cancel ? "cancel" : "done";
198 this.drawing = false;
199 this.mouseDown = false;
200 this.lastDown = null;
202 this.callback(key, [this.geometryClone()]);
203 if(cancel || !this.persist) {
204 this.destroyFeature();
210 * Finish the geometry and call the "cancel" callback.
218 * Handle clicks. Clicks are stopped from propagating to other listeners
219 * on map.events or other dom elements.
222 * evt - {Event} The browser event
225 * {Boolean} Allow event propagation
227 click: function(evt) {
228 OpenLayers.Event.stop(evt);
234 * Handle double-clicks. Double-clicks are stopped from propagating to other
235 * listeners on map.events or other dom elements.
238 * evt - {Event} The browser event
241 * {Boolean} Allow event propagation
243 dblclick: function(evt) {
244 OpenLayers.Event.stop(evt);
249 * Method: modifyFeature
250 * Modify the existing geometry given a pixel location.
253 * pixel - {<OpenLayers.Pixel>} A pixel location on the map.
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();
265 * Method: drawFeature
266 * Render features on the temporary layer.
268 drawFeature: function() {
269 this.layer.drawFeature(this.point, this.style);
273 * Method: getGeometry
274 * Return the sketch geometry. If <multi> is true, this will return
275 * a multi-part geometry.
278 * {<OpenLayers.Geometry.Point>}
280 getGeometry: function() {
281 var geometry = this.point && this.point.geometry;
282 if(geometry && this.multi) {
283 geometry = new OpenLayers.Geometry.MultiPoint([geometry]);
289 * Method: geometryClone
290 * Return a clone of the relevant geometry.
293 * {<OpenLayers.Geometry>}
295 geometryClone: function() {
296 var geom = this.getGeometry();
297 return geom && geom.clone();
302 * Handle mouse down. Adjust the geometry and redraw.
303 * Return determines whether to propagate the event on the map.
306 * evt - {Event} The browser event
309 * {Boolean} Allow event propagation
311 mousedown: function(evt) {
312 // check keyboard modifiers
313 if(!this.checkModifiers(evt)) {
316 // ignore double-clicks
317 if(this.lastDown && this.lastDown.equals(evt.xy)) {
321 if(this.lastDown == null) {
323 this.destroyFeature();
325 this.createFeature(evt.xy);
327 this.modifyFeature(evt.xy);
329 this.lastDown = evt.xy;
335 * Handle mouse move. Adjust the geometry and redraw.
336 * Return determines whether to propagate the event on the map.
339 * evt - {Event} The browser event
342 * {Boolean} Allow event propagation
344 mousemove: function (evt) {
346 this.modifyFeature(evt.xy);
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.
357 * evt - {Event} The browser event
360 * {Boolean} Allow event propagation
362 mouseup: function (evt) {
371 CLASS_NAME: "OpenLayers.Handler.Point"