Add experimental controls infrastructure, thanks @elemoine

This commit is contained in:
Tom Payne
2012-07-18 13:32:22 +02:00
parent 1af79ede29
commit c6343ed2bc
11 changed files with 214 additions and 381 deletions

View File

@@ -1,103 +0,0 @@
goog.provide('ol.control.Attribution');
goog.require('ol.event');
goog.require('ol.control.Control');
goog.require('goog.dom');
/**
* @constructor
* @extends {ol.control.Control}
* @param {boolean|undefined} opt_autoActivate
*/
ol.control.Attribution = function(opt_autoActivate) {
goog.base(this, opt_autoActivate);
/**
* @type {Node}
*/
this.container_ = null;
/**
* Activate this control when it is added to a map. Default is true.
*
* @type {boolean} autoActivate
*/
this.autoActivate_ =
goog.isDef(opt_autoActivate) ? opt_autoActivate : true;
};
goog.inherits(ol.control.Attribution, ol.control.Control);
/**
* @const {string}
*/
ol.control.Attribution.prototype.CLS = 'ol-control-attribution';
/**
* @param {ol.Map} map
*/
ol.control.Attribution.prototype.setMap = function(map) {
var staticOverlay = map.getStaticOverlay();
if (goog.isNull(this.container_)) {
this.container_ = goog.dom.createDom('div', this.CLS);
// This is not registered as priority listener, so priority listeners
// can still get the click event.
map.getEvents().register('click', this.stopLinkClick, this);
}
if (!goog.isNull(staticOverlay)) {
goog.dom.append(staticOverlay, this.container_);
}
goog.base(this, 'setMap', map);
};
/**
* Prevent clicks on links in the attribution from getting through to
* listeners.
*/
ol.control.Attribution.prototype.stopLinkClick = function(evt) {
var node = evt.target;
return node.nodeName !== 'A' ||
!goog.dom.getAncestorByClass(node, this.CLS);
};
/** @inheritDoc */
ol.control.Attribution.prototype.activate = function() {
var active = goog.base(this, 'activate');
if (active) {
this.map_.getEvents().register('layeradd', this.update, this);
this.update();
}
return active;
};
/** @inheritDoc */
ol.control.Attribution.prototype.deactivate = function() {
var inactive = goog.base(this, 'deactivate');
if (inactive) {
this.map_.getEvents().unregister('layeradd', this.update, this);
}
return inactive;
};
ol.control.Attribution.prototype.update = function() {
var attribution = [],
layers = this.map_.getLayers(), layerAttribution;
for (var i=0, ii=layers.length; i<ii; ++i) {
layerAttribution = layers[i].getAttribution();
if (layerAttribution &&
!~goog.array.indexOf(attribution, layerAttribution)) {
attribution.push(layerAttribution);
}
}
this.container_.innerHTML = attribution.join(', ');
};
ol.control.Attribution.prototype.destroy = function() {
goog.dom.removeNode(this.container_);
goog.base(this, 'destroy');
};
ol.control.addControl('attribution', ol.control.Attribution);

View File

@@ -1,85 +0,0 @@
goog.provide('ol.control');
goog.provide('ol.control.Control');
goog.require('goog.object');
/**
* @enum {Object}
*/
ol.control.CONTROL_MAP = {};
/**
* @param {string} name
* @param {Function} Control
*/
ol.control.addControl = function(name, Control) {
ol.control.CONTROL_MAP[name] = Control;
};
/**
* @constructor
* @param {boolean|undefined} opt_autoActivate
*/
ol.control.Control = function(opt_autoActivate) {
/**
* @type {ol.Map} map
* @protected
*/
this.map_ = null;
/**
* @type {boolean} active
* @private
*/
this.active_ = false;
/**
* Activate this control when it is added to a map. Default is false.
*
* @type {boolean} autoActivate
*/
this.autoActivate_ =
goog.isDef(opt_autoActivate) ? opt_autoActivate : false;
};
/**
* @return {ol.Map} getMap
*/
ol.control.Control.prototype.getMap = function() {
return this.map_;
};
/**
* @param {ol.Map} map
*/
ol.control.Control.prototype.setMap = function(map) {
this.map_ = map;
if (this.autoActivate_) {
this.activate();
}
};
/**
* @return {boolean}
*/
ol.control.Control.prototype.activate = function() {
var returnValue = !this.active_;
this.active_ = true;
return returnValue;
};
/**
* @return {boolean}
*/
ol.control.Control.prototype.deactivate = function() {
var returnValue = this.active_;
this.active_ = false;
return returnValue;
};
ol.control.Control.prototype.destroy = function() {
this.deactivate();
goog.object.clear(this);
};

View File

@@ -1,71 +0,0 @@
goog.provide('ol.control.Navigation');
goog.require('ol.control.Control');
/**
* @constructor
* @extends {ol.control.Control}
* @param {boolean|undefined} opt_autoActivate
*/
ol.control.Navigation = function(opt_autoActivate) {
goog.base(this, opt_autoActivate);
/**
* Activate this control when it is added to a map. Default is true.
*
* @type {boolean} autoActivate
*/
this.autoActivate_ =
goog.isDef(opt_autoActivate) ? opt_autoActivate : true;
};
goog.inherits(ol.control.Navigation, ol.control.Control);
/** @inheritDoc */
ol.control.Navigation.prototype.activate = function() {
var active = goog.base(this, 'activate');
if (active) {
var events = this.map_.getEvents();
events.register("drag", this.moveMap, this);
events.register("scroll", this.zoomMap, this);
}
return active;
};
/** @inheritDoc */
ol.control.Navigation.prototype.deactivate = function() {
var inactive = goog.base(this, 'deactivate');
if (inactive) {
var events = this.map_.getEvents();
events.unregister("drag", this.moveMap, this);
events.unregister("scroll", this.zoomMap, this);
}
return inactive;
};
/**
* @param {Object} evt
*/
ol.control.Navigation.prototype.moveMap = function(evt) {
this.map_.moveByPx(evt.deltaX, evt.deltaY);
return false;
};
/**
* @param {Event} evt
*/
ol.control.Navigation.prototype.zoomMap = function(evt) {
var map = this.map_,
delta = ((evt.deltaY / 3) | 0);
if (Math.abs(delta) === 0) {
return;
}
map.setZoom(map.getZoom()-delta, map.getEvents().getPointerPosition(evt));
// We don't want the page to scroll.
evt.preventDefault();
return false;
};
ol.control.addControl('navigation', ol.control.Navigation);

View File

@@ -1,122 +0,0 @@
goog.provide('ol.control.Zoom');
goog.require('ol.event');
goog.require('ol.control.Control');
goog.require('goog.dom');
/**
* @constructor
* @extends {ol.control.Control}
* @param {boolean|undefined} opt_autoActivate
*/
ol.control.Zoom = function(opt_autoActivate) {
goog.base(this, opt_autoActivate);
/**
* Activate this control when it is added to a map. Default is true.
*
* @type {boolean} autoActivate
*/
this.autoActivate_ =
goog.isDef(opt_autoActivate) ? opt_autoActivate : true;
};
goog.inherits(ol.control.Zoom, ol.control.Control);
/**
* @param {ol.Map} map
*/
ol.control.Zoom.prototype.setMap = function(map) {
goog.base(this, 'setMap', map);
var container = goog.dom.createDom('div', ol.control.Zoom.RES.CLS);
var inButton = goog.dom.createDom(
'div', ol.control.Zoom.RES.IN_CLS,
goog.dom.createDom('a', {'href': '#zoomIn'})
);
goog.dom.setTextContent(
/** @type {Element} */ (inButton.firstChild),
ol.control.Zoom.RES.IN_TEXT
);
var outButton = goog.dom.createDom(
'div', ol.control.Zoom.RES.OUT_CLS,
goog.dom.createDom('a', {'href': '#zoomOut'})
);
goog.dom.setTextContent(
/** @type {Element} */ (outButton.firstChild),
ol.control.Zoom.RES.OUT_TEXT
);
goog.dom.append(container, inButton, outButton);
var overlay = map.getStaticOverlay();
if (goog.isDefAndNotNull(overlay)) {
goog.dom.append(overlay, container);
}
};
/** @inheritDoc */
ol.control.Zoom.prototype.activate = function() {
var active = goog.base(this, 'activate');
if (active) {
this.map_.getEvents().register('click', this.handle, this);
this.map_.getEvents().register('keypress', this.handle, this);
}
return active;
};
/** @inheritDoc */
ol.control.Zoom.prototype.deactivate = function() {
var inactive = goog.base(this, 'deactivate');
if (inactive) {
this.map_.getEvents().unregister('click', this.handle, this);
this.map_.getEvents().unregister('keypress', this.handle, this);
}
return inactive;
};
/**
* @param {Event} evt
* @return {boolean}
*/
ol.control.Zoom.prototype.handle = function(evt) {
var target = /** @type {Node} */ (evt.target),
handled = false;
if (evt.type === 'click' || ol.event.isEnterOrSpace(evt)) {
if (goog.dom.getAncestorByClass(target, ol.control.Zoom.RES.IN_CLS)) {
this.map_.zoomIn();
handled = true;
} else
if (goog.dom.getAncestorByClass(target, ol.control.Zoom.RES.OUT_CLS)) {
this.map_.zoomOut();
handled = true;
}
if (handled) {
// Stop default behavior (i.e. don't follow link to anchor)
evt.preventDefault();
// On Android 2.3, the above does not prevent the link from being
// followed, but stopPropagation does.
evt.stopPropagation();
}
}
return !handled;
};
ol.control.Zoom.prototype.destroy = function() {
goog.dom.removeNode(goog.dom.getElementByClass(
ol.control.Zoom.RES.CLS,
/** @type {Element} */ (this.map_.getStaticOverlay())
));
goog.base(this, 'destroy');
};
ol.control.addControl('zoom', ol.control.Zoom);
ol.control.Zoom.RES = {
CLS: 'ol-control-zoom',
IN_CLS: 'ol-control-zoom-in',
OUT_CLS: 'ol-control-zoom-out',
IN_TEXT: '+',
OUT_TEXT: '\u2013'
};

17
src/ol/control/control.js Normal file
View File

@@ -0,0 +1,17 @@
goog.provide('ol.Control');
goog.require('ol.MapBrowserEvent');
/**
* @constructor
*/
ol.Control = function() {
};
/**
* @param {ol.MapBrowserEvent} event Map browser event.
*/
ol.Control.prototype.handleMapBrowserEvent = goog.abstractMethod;

View File

@@ -0,0 +1,34 @@
goog.provide('ol.control.DblClickZoom');
goog.require('goog.events.EventType');
goog.require('ol.Control');
goog.require('ol.MapBrowserEvent');
/**
* @constructor
* @extends {ol.Control}
*/
ol.control.DblClickZoom = function() {
goog.base(this);
};
goog.inherits(ol.control.DblClickZoom, ol.Control);
/**
* @inheritDoc
*/
ol.control.DblClickZoom.prototype.handleMapBrowserEvent = function(event) {
if (event.type == goog.events.EventType.DBLCLICK) {
var map = event.map;
map.whileFrozen(function() {
// FIXME compute correct center for zoom
map.setCenter(event.getCoordinate());
var browserEventObject = event.getBrowserEventObject();
var scale = browserEventObject.shiftKey ? 2 : 0.5;
map.setResolution(scale * map.getResolution());
});
event.preventDefault();
}
};

View File

@@ -6,6 +6,7 @@ goog.require('ol.Array');
goog.require('ol.Map');
goog.require('ol.MapProperty');
goog.require('ol.Projection');
goog.require('ol.control.DblClickZoom');
goog.require('ol.dom');
goog.require('ol.dom.Map');
goog.require('ol.webgl');
@@ -62,6 +63,12 @@ ol.createMap = function(target, opt_values, opt_rendererHints) {
goog.object.extend(values, opt_values);
}
if (!goog.object.containsKey(values, ol.MapProperty.CONTROLS)) {
var controls = new ol.Array();
controls.push(new ol.control.DblClickZoom());
values[ol.MapProperty.CONTROLS] = controls;
}
if (!goog.object.containsKey(values, ol.MapProperty.LAYERS)) {
values[ol.MapProperty.LAYERS] = new ol.Array();
}

View File

@@ -4,6 +4,7 @@ goog.provide('ol.MapProperty');
goog.require('goog.array');
goog.require('goog.dom.ViewportSizeMonitor');
goog.require('goog.events');
goog.require('goog.events.BrowserEvent');
goog.require('goog.events.Event');
goog.require('goog.events.EventType');
goog.require('goog.fx.anim');
@@ -12,6 +13,7 @@ goog.require('goog.math.Coordinate');
goog.require('goog.math.Size');
goog.require('goog.object');
goog.require('ol.Array');
goog.require('ol.Control');
goog.require('ol.Extent');
goog.require('ol.LayerRenderer');
goog.require('ol.Object');
@@ -23,6 +25,7 @@ goog.require('ol.Projection');
*/
ol.MapProperty = {
CENTER: 'center',
CONTROLS: 'controls',
EXTENT: 'extent',
LAYERS: 'layers',
PROJECTION: 'projection',
@@ -31,6 +34,14 @@ ol.MapProperty = {
};
/**
* @enum {number}
*/
ol.MapPaneZIndex = {
EVENTS: 1000
};
/**
* @constructor
@@ -44,6 +55,24 @@ ol.Map = function(target, opt_values, opt_viewportSizeMonitor) {
goog.base(this);
/**
* @private
* @type {HTMLDivElement}
*/
this.eventsPane_ = /** @type {HTMLDivElement} */ (
goog.dom.createElement(goog.dom.TagName.DIV));
this.eventsPane_.className = 'ol-pane-events';
this.eventsPane_.style.position = 'absolute';
this.eventsPane_.style.width = '100%';
this.eventsPane_.style.height = '100%';
this.eventsPane_.style.zIndex = ol.MapPaneZIndex.EVENTS;
target.appendChild(this.eventsPane_);
goog.events.listen(this.eventsPane_, [
goog.events.EventType.DBLCLICK,
goog.events.EventType.CLICK
], this.handleBrowserEvent, false, this);
/**
* @private
* @type {goog.fx.anim.Animated}
@@ -183,6 +212,14 @@ ol.Map.prototype.getCenter = function() {
};
/**
* @return {ol.Array} Controls.
*/
ol.Map.prototype.getControls = function() {
return /** @type {ol.Array} */ this.get(ol.MapProperty.CONTROLS);
};
/**
* @param {goog.math.Coordinate} pixel Pixel.
* @return {goog.math.Coordinate} Coordinate.
@@ -293,6 +330,20 @@ ol.Map.prototype.getTarget = function() {
};
/**
* @param {goog.events.BrowserEvent} event Event.
*/
ol.Map.prototype.handleBrowserEvent = function(event) {
var mapBrowserEvent = new ol.MapBrowserEvent(event.type, this, event);
var controls = this.getControls();
var controlsArray = /** @type {Array.<ol.Control>} */ controls.getArray();
goog.array.every(controlsArray, function(control) {
control.handleMapBrowserEvent(mapBrowserEvent);
return !mapBrowserEvent.defaultPrevented;
});
};
/**
* @protected
*/
@@ -485,6 +536,14 @@ ol.Map.prototype.setCenter = function(center) {
};
/**
* @param {ol.Array} controls Controls.
*/
ol.Map.prototype.setControls = function(controls) {
this.set(ol.MapProperty.CONTROLS, controls);
};
/**
* @param {ol.Layer} layer Layer.
* @param {ol.LayerRenderer} layerRenderer Layer renderer.

59
src/ol/mapbrowserevent.js Normal file
View File

@@ -0,0 +1,59 @@
goog.provide('ol.MapBrowserEvent');
goog.require('goog.events.BrowserEvent');
goog.require('goog.math.Coordinate');
goog.require('ol.MapEvent');
/**
* @constructor
* @extends {ol.MapEvent}
* @param {string} type Event type.
* @param {ol.Map} map Map.
* @param {goog.events.BrowserEvent} browserEventObject Browser event object.
*/
ol.MapBrowserEvent = function(type, map, browserEventObject) {
goog.base(this, type, map);
/**
* @private
* @type {goog.events.BrowserEvent}
*/
this.browserEventObject_ = browserEventObject;
};
goog.inherits(ol.MapBrowserEvent, ol.MapEvent);
/**
* @private
* @type {goog.math.Coordinate}
*/
ol.MapBrowserEvent.prototype.coordinate_;
/**
* @return {goog.math.Coordinate} Coordinate.
*/
ol.MapBrowserEvent.prototype.getCoordinate = function() {
if (goog.isDef(this.coordinate_)) {
return this.coordinate_;
} else {
var browserEventObject = this.getBrowserEventObject();
var pixel = new goog.math.Coordinate(
browserEventObject.offsetX, browserEventObject.offsetY);
var coordinate = this.map.getCoordinateFromPixel(pixel);
this.coordinate_ = coordinate;
return coordinate;
}
};
/**
* @return {goog.events.BrowserEvent} Browser event object.
*/
ol.MapBrowserEvent.prototype.getBrowserEventObject = function() {
return this.browserEventObject_;
};

35
src/ol/mapevent.js Normal file
View File

@@ -0,0 +1,35 @@
goog.provide('ol.MapEvent');
goog.require('goog.events.Event');
/**
* @constructor
* @extends {goog.events.Event}
* @param {string} type Event type.
* @param {ol.Map} map Map.
*/
ol.MapEvent = function(type, map) {
goog.base(this, type);
/**
* @type {ol.Map}
*/
this.map = map;
/**
* @type {boolean}
*/
this.defaultPrevented = false;
};
goog.inherits(ol.MapEvent, goog.events.Event);
/**
*/
ol.MapEvent.prototype.preventDefault = function() {
this.defaultPrevented = true;
};

View File

@@ -3,11 +3,13 @@ goog.provide('ol');
goog.require('ol.Array');
goog.require('ol.ArrayEvent');
goog.require('ol.ArrayEventType');
goog.require('ol.Control');
goog.require('ol.Extent');
goog.require('ol.Layer');
goog.require('ol.LayerProperty');
goog.require('ol.LayerRenderer');
goog.require('ol.Map');
goog.require('ol.MapBrowserEvent');
goog.require('ol.MapProperty');
goog.require('ol.Object');
goog.require('ol.Projection');
@@ -22,6 +24,7 @@ goog.require('ol.TileStore');
goog.require('ol.TileUrlFunction');
goog.require('ol.TileUrlFunctionType');
goog.require('ol.TransformFunction');
goog.require('ol.control.DblClickZoom');
goog.require('ol.createMap');
goog.require('ol.dom');
goog.require('ol.dom.LayerRenderer');