From 6ddda53a701ea5b23d4e67173a0292e9eafd2d3f Mon Sep 17 00:00:00 2001 From: ahocevar Date: Wed, 20 Jun 2012 23:21:44 +0200 Subject: [PATCH] Initial port of Control.js and Navigation.js. This also adds an Events instance to the map, so the Navigation control can register events on the map. Tests still missing. --- lib/OpenLayers/Control.js | 371 --------------------------- lib/OpenLayers/Control/Navigation.js | 348 ------------------------- src/api/map.js | 20 ++ src/ol.js | 2 + src/ol/Map.js | 67 ++++- src/ol/control/Control.js | 66 +++++ src/ol/control/Navigation.js | 49 ++++ 7 files changed, 203 insertions(+), 720 deletions(-) delete mode 100644 lib/OpenLayers/Control.js delete mode 100644 lib/OpenLayers/Control/Navigation.js create mode 100644 src/ol/control/Control.js create mode 100644 src/ol/control/Navigation.js diff --git a/lib/OpenLayers/Control.js b/lib/OpenLayers/Control.js deleted file mode 100644 index a91d8f2e73..0000000000 --- a/lib/OpenLayers/Control.js +++ /dev/null @@ -1,371 +0,0 @@ -/* Copyright (c) 2006-2012 by OpenLayers Contributors (see authors.txt for - * full list of contributors). Published under the 2-clause BSD license. - * See license.txt in the OpenLayers distribution or repository for the - * full text of the license. */ - -/** - * @requires OpenLayers/BaseTypes/Class.js - */ - -/** - * Class: OpenLayers.Control - * Controls affect the display or behavior of the map. They allow everything - * from panning and zooming to displaying a scale indicator. Controls by - * default are added to the map they are contained within however it is - * possible to add a control to an external div by passing the div in the - * options parameter. - * - * Example: - * The following example shows how to add many of the common controls - * to a map. - * - * > var map = new OpenLayers.Map('map', { controls: [] }); - * > - * > map.addControl(new OpenLayers.Control.PanZoomBar()); - * > map.addControl(new OpenLayers.Control.LayerSwitcher({'ascending':false})); - * > map.addControl(new OpenLayers.Control.Permalink()); - * > map.addControl(new OpenLayers.Control.Permalink('permalink')); - * > map.addControl(new OpenLayers.Control.MousePosition()); - * > map.addControl(new OpenLayers.Control.OverviewMap()); - * > map.addControl(new OpenLayers.Control.KeyboardDefaults()); - * - * The next code fragment is a quick example of how to intercept - * shift-mouse click to display the extent of the bounding box - * dragged out by the user. Usually controls are not created - * in exactly this manner. See the source for a more complete - * example: - * - * > var control = new OpenLayers.Control(); - * > OpenLayers.Util.extend(control, { - * > draw: function () { - * > // this Handler.Box will intercept the shift-mousedown - * > // before Control.MouseDefault gets to see it - * > this.box = new OpenLayers.Handler.Box( control, - * > {"done": this.notice}, - * > {keyMask: OpenLayers.Handler.MOD_SHIFT}); - * > this.box.activate(); - * > }, - * > - * > notice: function (bounds) { - * > OpenLayers.Console.userError(bounds); - * > } - * > }); - * > map.addControl(control); - * - */ -OpenLayers.Control = OpenLayers.Class({ - - /** - * Property: id - * {String} - */ - id: null, - - /** - * Property: map - * {} this gets set in the addControl() function in - * OpenLayers.Map - */ - map: null, - - /** - * APIProperty: div - * {DOMElement} The element that contains the control, if not present the - * control is placed inside the map. - */ - div: null, - - /** - * APIProperty: type - * {Number} Controls can have a 'type'. The type determines the type of - * interactions which are possible with them when they are placed in an - * . - */ - type: null, - - /** - * Property: allowSelection - * {Boolean} By default, controls do not allow selection, because - * it may interfere with map dragging. If this is true, OpenLayers - * will not prevent selection of the control. - * Default is false. - */ - allowSelection: false, - - /** - * Property: displayClass - * {string} This property is used for CSS related to the drawing of the - * Control. - */ - displayClass: "", - - /** - * APIProperty: title - * {string} This property is used for showing a tooltip over the - * Control. - */ - title: "", - - /** - * APIProperty: autoActivate - * {Boolean} Activate the control when it is added to a map. Default is - * false. - */ - autoActivate: false, - - /** - * APIProperty: active - * {Boolean} The control is active (read-only). Use and - * to change control state. - */ - active: null, - - /** - * Property: handlerOptions - * {Object} Used to set non-default properties on the control's handler - */ - handlerOptions: null, - - /** - * Property: handler - * {} null - */ - handler: null, - - /** - * APIProperty: eventListeners - * {Object} If set as an option at construction, the eventListeners - * object will be registered with . Object - * structure must be a listeners object as shown in the example for - * the events.on method. - */ - eventListeners: null, - - /** - * APIProperty: events - * {} Events instance for listeners and triggering - * control specific events. - * - * Register a listener for a particular event with the following syntax: - * (code) - * control.events.register(type, obj, listener); - * (end) - * - * Listeners will be called with a reference to an event object. The - * properties of this event depends on exactly what happened. - * - * All event objects have at least the following properties: - * object - {Object} A reference to control.events.object (a reference - * to the control). - * element - {DOMElement} A reference to control.events.element (which - * will be null unless documented otherwise). - * - * Supported map event types: - * activate - Triggered when activated. - * deactivate - Triggered when deactivated. - */ - events: null, - - /** - * Constructor: OpenLayers.Control - * Create an OpenLayers Control. The options passed as a parameter - * directly extend the control. For example passing the following: - * - * > var control = new OpenLayers.Control({div: myDiv}); - * - * Overrides the default div attribute value of null. - * - * Parameters: - * options - {Object} - */ - initialize: function (options) { - // We do this before the extend so that instances can override - // className in options. - this.displayClass = - this.CLASS_NAME.replace("OpenLayers.", "ol").replace(/\./g, ""); - - OpenLayers.Util.extend(this, options); - - this.events = new OpenLayers.Events(this); - if(this.eventListeners instanceof Object) { - this.events.on(this.eventListeners); - } - if (this.id == null) { - this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_"); - } - }, - - /** - * Method: destroy - * The destroy method is used to perform any clean up before the control - * is dereferenced. Typically this is where event listeners are removed - * to prevent memory leaks. - */ - destroy: function () { - if(this.events) { - if(this.eventListeners) { - this.events.un(this.eventListeners); - } - this.events.destroy(); - this.events = null; - } - this.eventListeners = null; - - // eliminate circular references - if (this.handler) { - this.handler.destroy(); - this.handler = null; - } - if(this.handlers) { - for(var key in this.handlers) { - if(this.handlers.hasOwnProperty(key) && - typeof this.handlers[key].destroy == "function") { - this.handlers[key].destroy(); - } - } - this.handlers = null; - } - if (this.map) { - this.map.removeControl(this); - this.map = null; - } - this.div = null; - }, - - /** - * Method: setMap - * Set the map property for the control. This is done through an accessor - * so that subclasses can override this and take special action once - * they have their map variable set. - * - * Parameters: - * map - {} - */ - setMap: function(map) { - this.map = map; - if (this.handler) { - this.handler.setMap(map); - } - }, - - /** - * Method: draw - * The draw method is called when the control is ready to be displayed - * on the page. If a div has not been created one is created. Controls - * with a visual component will almost always want to override this method - * to customize the look of control. - * - * Parameters: - * px - {} The top-left pixel position of the control - * or null. - * - * Returns: - * {DOMElement} A reference to the DIV DOMElement containing the control - */ - draw: function (px) { - if (this.div == null) { - this.div = OpenLayers.Util.createDiv(this.id); - this.div.className = this.displayClass; - if (!this.allowSelection) { - this.div.className += " olControlNoSelect"; - this.div.setAttribute("unselectable", "on", 0); - this.div.onselectstart = OpenLayers.Function.False; - } - if (this.title != "") { - this.div.title = this.title; - } - } - if (px != null) { - this.position = px.clone(); - } - this.moveTo(this.position); - return this.div; - }, - - /** - * Method: moveTo - * Sets the left and top style attributes to the passed in pixel - * coordinates. - * - * Parameters: - * px - {} - */ - moveTo: function (px) { - if ((px != null) && (this.div != null)) { - this.div.style.left = px.x + "px"; - this.div.style.top = px.y + "px"; - } - }, - - /** - * APIMethod: activate - * Explicitly activates a control and it's associated - * handler if one has been set. Controls can be - * deactivated by calling the deactivate() method. - * - * Returns: - * {Boolean} True if the control was successfully activated or - * false if the control was already active. - */ - activate: function () { - if (this.active) { - return false; - } - if (this.handler) { - this.handler.activate(); - } - this.active = true; - if(this.map) { - OpenLayers.Element.addClass( - this.map.viewPortDiv, - this.displayClass.replace(/ /g, "") + "Active" - ); - } - this.events.triggerEvent("activate"); - return true; - }, - - /** - * APIMethod: deactivate - * Deactivates a control and it's associated handler if any. The exact - * effect of this depends on the control itself. - * - * Returns: - * {Boolean} True if the control was effectively deactivated or false - * if the control was already inactive. - */ - deactivate: function () { - if (this.active) { - if (this.handler) { - this.handler.deactivate(); - } - this.active = false; - if(this.map) { - OpenLayers.Element.removeClass( - this.map.viewPortDiv, - this.displayClass.replace(/ /g, "") + "Active" - ); - } - this.events.triggerEvent("deactivate"); - return true; - } - return false; - }, - - CLASS_NAME: "OpenLayers.Control" -}); - -/** - * Constant: OpenLayers.Control.TYPE_BUTTON - */ -OpenLayers.Control.TYPE_BUTTON = 1; - -/** - * Constant: OpenLayers.Control.TYPE_TOGGLE - */ -OpenLayers.Control.TYPE_TOGGLE = 2; - -/** - * Constant: OpenLayers.Control.TYPE_TOOL - */ -OpenLayers.Control.TYPE_TOOL = 3; diff --git a/lib/OpenLayers/Control/Navigation.js b/lib/OpenLayers/Control/Navigation.js deleted file mode 100644 index 17d2bf0aaa..0000000000 --- a/lib/OpenLayers/Control/Navigation.js +++ /dev/null @@ -1,348 +0,0 @@ -/* Copyright (c) 2006-2012 by OpenLayers Contributors (see authors.txt for - * full list of contributors). Published under the 2-clause BSD license. - * See license.txt in the OpenLayers distribution or repository for the - * full text of the license. */ - -/** - * @requires OpenLayers/Control/ZoomBox.js - * @requires OpenLayers/Control/DragPan.js - * @requires OpenLayers/Handler/MouseWheel.js - * @requires OpenLayers/Handler/Click.js - */ - -/** - * Class: OpenLayers.Control.Navigation - * The navigation control handles map browsing with mouse events (dragging, - * double-clicking, and scrolling the wheel). Create a new navigation - * control with the control. - * - * Note that this control is added to the map by default (if no controls - * array is sent in the options object to the - * constructor). - * - * Inherits: - * - - */ -OpenLayers.Control.Navigation = OpenLayers.Class(OpenLayers.Control, { - - /** - * Property: dragPan - * {} - */ - dragPan: null, - - /** - * APIProperty: dragPanOptions - * {Object} Options passed to the DragPan control. - */ - dragPanOptions: null, - - /** - * Property: pinchZoom - * {} - */ - pinchZoom: null, - - /** - * APIProperty: pinchZoomOptions - * {Object} Options passed to the PinchZoom control. - */ - pinchZoomOptions: null, - - /** - * APIProperty: documentDrag - * {Boolean} Allow panning of the map by dragging outside map viewport. - * Default is false. - */ - documentDrag: false, - - /** - * Property: zoomBox - * {} - */ - zoomBox: null, - - /** - * APIProperty: zoomBoxEnabled - * {Boolean} Whether the user can draw a box to zoom - */ - zoomBoxEnabled: true, - - /** - * APIProperty: zoomWheelEnabled - * {Boolean} Whether the mousewheel should zoom the map - */ - zoomWheelEnabled: true, - - /** - * Property: mouseWheelOptions - * {Object} Options passed to the MouseWheel control (only useful if - * is set to true) - */ - mouseWheelOptions: null, - - /** - * APIProperty: handleRightClicks - * {Boolean} Whether or not to handle right clicks. Default is false. - */ - handleRightClicks: false, - - /** - * APIProperty: zoomBoxKeyMask - * {Integer} key code of the key, which has to be - * pressed, while drawing the zoom box with the mouse on the screen. - * You should probably set handleRightClicks to true if you use this - * with MOD_CTRL, to disable the context menu for machines which use - * CTRL-Click as a right click. - * Default: - */ - zoomBoxKeyMask: OpenLayers.Handler.MOD_SHIFT, - - /** - * APIProperty: autoActivate - * {Boolean} Activate the control when it is added to a map. Default is - * true. - */ - autoActivate: true, - - /** - * Constructor: OpenLayers.Control.Navigation - * Create a new navigation control - * - * Parameters: - * options - {Object} An optional object whose properties will be set on - * the control - */ - initialize: function(options) { - this.handlers = {}; - OpenLayers.Control.prototype.initialize.apply(this, arguments); - }, - - /** - * Method: destroy - * The destroy method is used to perform any clean up before the control - * is dereferenced. Typically this is where event listeners are removed - * to prevent memory leaks. - */ - destroy: function() { - this.deactivate(); - - if (this.dragPan) { - this.dragPan.destroy(); - } - this.dragPan = null; - - if (this.zoomBox) { - this.zoomBox.destroy(); - } - this.zoomBox = null; - - if (this.pinchZoom) { - this.pinchZoom.destroy(); - } - this.pinchZoom = null; - - OpenLayers.Control.prototype.destroy.apply(this,arguments); - }, - - /** - * Method: activate - */ - activate: function() { - this.dragPan.activate(); - if (this.zoomWheelEnabled) { - this.handlers.wheel.activate(); - } - this.handlers.click.activate(); - if (this.zoomBoxEnabled) { - this.zoomBox.activate(); - } - if (this.pinchZoom) { - this.pinchZoom.activate(); - } - return OpenLayers.Control.prototype.activate.apply(this,arguments); - }, - - /** - * Method: deactivate - */ - deactivate: function() { - if (this.pinchZoom) { - this.pinchZoom.deactivate(); - } - this.zoomBox.deactivate(); - this.dragPan.deactivate(); - this.handlers.click.deactivate(); - this.handlers.wheel.deactivate(); - return OpenLayers.Control.prototype.deactivate.apply(this,arguments); - }, - - /** - * Method: draw - */ - draw: function() { - // disable right mouse context menu for support of right click events - if (this.handleRightClicks) { - this.map.viewPortDiv.oncontextmenu = OpenLayers.Function.False; - } - - var clickCallbacks = { - 'click': this.defaultClick, - 'dblclick': this.defaultDblClick, - 'dblrightclick': this.defaultDblRightClick - }; - var clickOptions = { - 'double': true, - 'stopDouble': true - }; - this.handlers.click = new OpenLayers.Handler.Click( - this, clickCallbacks, clickOptions - ); - this.dragPan = new OpenLayers.Control.DragPan( - OpenLayers.Util.extend({ - map: this.map, - documentDrag: this.documentDrag - }, this.dragPanOptions) - ); - this.zoomBox = new OpenLayers.Control.ZoomBox( - {map: this.map, keyMask: this.zoomBoxKeyMask}); - this.dragPan.draw(); - this.zoomBox.draw(); - this.handlers.wheel = new OpenLayers.Handler.MouseWheel( - this, {"up" : this.wheelUp, - "down": this.wheelDown}, - this.mouseWheelOptions ); - if (OpenLayers.Control.PinchZoom) { - this.pinchZoom = new OpenLayers.Control.PinchZoom( - OpenLayers.Util.extend( - {map: this.map}, this.pinchZoomOptions)); - } - }, - - /** - * Method: defaultClick - * - * Parameters: - * evt - {Event} - */ - defaultClick: function (evt) { - if (evt.lastTouches && evt.lastTouches.length == 2) { - this.map.zoomOut(); - } - }, - - /** - * Method: defaultDblClick - * - * Parameters: - * evt - {Event} - */ - defaultDblClick: function (evt) { - var newCenter = this.map.getLonLatFromViewPortPx( evt.xy ); - this.map.setCenter(newCenter, this.map.zoom + 1); - }, - - /** - * Method: defaultDblRightClick - * - * Parameters: - * evt - {Event} - */ - defaultDblRightClick: function (evt) { - var newCenter = this.map.getLonLatFromViewPortPx( evt.xy ); - this.map.setCenter(newCenter, this.map.zoom - 1); - }, - - /** - * Method: wheelChange - * - * Parameters: - * evt - {Event} - * deltaZ - {Integer} - */ - wheelChange: function(evt, deltaZ) { - if (!this.map.fractionalZoom) { - deltaZ = Math.round(deltaZ); - } - var currentZoom = this.map.getZoom(); - var newZoom = this.map.getZoom() + deltaZ; - newZoom = Math.max(newZoom, 0); - newZoom = Math.min(newZoom, this.map.getNumZoomLevels()); - if (newZoom === currentZoom) { - return; - } - var size = this.map.getSize(); - var deltaX = size.w/2 - evt.xy.x; - var deltaY = evt.xy.y - size.h/2; - var newRes = this.map.baseLayer.getResolutionForZoom(newZoom); - var zoomPoint = this.map.getLonLatFromPixel(evt.xy); - var newCenter = new OpenLayers.LonLat( - zoomPoint.lon + deltaX * newRes, - zoomPoint.lat + deltaY * newRes ); - this.map.setCenter( newCenter, newZoom ); - }, - - /** - * Method: wheelUp - * User spun scroll wheel up - * - * Parameters: - * evt - {Event} - * delta - {Integer} - */ - wheelUp: function(evt, delta) { - this.wheelChange(evt, delta || 1); - }, - - /** - * Method: wheelDown - * User spun scroll wheel down - * - * Parameters: - * evt - {Event} - * delta - {Integer} - */ - wheelDown: function(evt, delta) { - this.wheelChange(evt, delta || -1); - }, - - /** - * Method: disableZoomBox - */ - disableZoomBox : function() { - this.zoomBoxEnabled = false; - this.zoomBox.deactivate(); - }, - - /** - * Method: enableZoomBox - */ - enableZoomBox : function() { - this.zoomBoxEnabled = true; - if (this.active) { - this.zoomBox.activate(); - } - }, - - /** - * Method: disableZoomWheel - */ - - disableZoomWheel : function() { - this.zoomWheelEnabled = false; - this.handlers.wheel.deactivate(); - }, - - /** - * Method: enableZoomWheel - */ - - enableZoomWheel : function() { - this.zoomWheelEnabled = true; - if (this.active) { - this.handlers.wheel.activate(); - } - }, - - CLASS_NAME: "OpenLayers.Control.Navigation" -}); diff --git a/src/api/map.js b/src/api/map.js index be84b7e9bb..70932941d8 100644 --- a/src/api/map.js +++ b/src/api/map.js @@ -38,6 +38,8 @@ ol.map = function(opt_arg){ var resolutions; /** @type {Array|undefined} */ var layers; + /** @type {Array|undefined} */ + var controls; if (arguments.length == 1) { if (opt_arg instanceof ol.Map) { @@ -53,6 +55,7 @@ ol.map = function(opt_arg){ maxRes = opt_arg['maxRes']; resolutions = opt_arg['resolutions']; layers = opt_arg['layers']; + controls = opt_arg['controls']; } else { throw new Error('ol.map'); @@ -87,6 +90,9 @@ ol.map = function(opt_arg){ if (goog.isDef(layers)) { map.setLayers(layers); } + if (goog.isDef(controls)) { + map.setControls(controls); + } return map; }; @@ -189,6 +195,20 @@ ol.Map.prototype.layers = function(opt_arg) { } }; +/** + * @export + * @param {Array=} opt_arg + * @returns {ol.Map|Array|undefined} Map center. + */ +ol.Map.prototype.controls = function(opt_arg) { + if (arguments.length == 1 && goog.isDef(opt_arg)) { + this.setControls(opt_arg); + return this; + } else { + return this.getControls(); + } +}; + /** * @export * @param {Array=} opt_arg diff --git a/src/ol.js b/src/ol.js index a108bd3f3e..8abbd43446 100644 --- a/src/ol.js +++ b/src/ol.js @@ -1,5 +1,7 @@ goog.provide("ol"); goog.require('ol.bounds'); +goog.require('ol.control.Control'); +goog.require('ol.control.Navigation'); goog.require('ol.event'); goog.require('ol.event.Events'); goog.require('ol.event.drag'); diff --git a/src/ol/Map.js b/src/ol/Map.js index 0f51c7cdb5..faf7f488db 100644 --- a/src/ol/Map.js +++ b/src/ol/Map.js @@ -2,6 +2,8 @@ goog.provide('ol.Map'); goog.require('ol.Loc'); goog.require('ol.Projection'); +goog.require('ol.event'); +goog.require('ol.event.Events'); @@ -53,6 +55,12 @@ ol.Map = function() { */ this.layers_ = null; + /** + * @private + * @type {Array} + */ + this.controls_ = null; + /** * @private * @type {ol.UnreferencedBounds} @@ -64,7 +72,21 @@ ol.Map = function() { * @type {number|undefined} */ this.maxRes_ = undefined; - + + /** + * @private + * @type {ol.event.Events} + */ + this.events_ = new ol.event.Events( + this, undefined, true, [ol.event.drag()] + ); + + /** + * @private + * @type {Element} + */ + this.container_ = null; + }; /** @@ -151,6 +173,14 @@ ol.Map.prototype.getLayers = function() { }; +/** + * @return {Array.} + */ +ol.Map.prototype.getControls = function() { + return this.controls_; +}; + + /** * @return {ol.UnreferencedBounds} the maxExtent for the map */ @@ -257,6 +287,18 @@ ol.Map.prototype.setLayers = function(layers) { this.layers_ = layers; }; +/** + * @param {Array.} controls + */ +ol.Map.prototype.setControls = function(controls) { + if (!this.controls_) { + for (var i=0, ii=controls.length; i