diff --git a/build.py b/build.py index 6d2410ae59..5dca545c20 100755 --- a/build.py +++ b/build.py @@ -85,6 +85,9 @@ virtual('precommit', 'lint', 'build-all', 'test', 'build', 'build-examples', 'do virtual('build', 'build/ol.css', 'build/ol.js') +virtual('todo', 'fixme') + + @target('build/ol.css', 'build/ol.js') def build_ol_css(t): t.touch() @@ -247,6 +250,27 @@ def hostexamples(t): def test(t): t.run('%(PHANTOMJS)s', 'test/phantom-jasmine/run_jasmine_test.coffee', 'test/ol.html') +@target('fixme', phony=True) +def find_fixme(t): + regex = re.compile(".(FIXME|TODO).") + matches = dict() + totalcount = 0 + for filename in SRC: + f = open(filename, 'r') + for lineno, line in enumerate(f): + if regex.search(line): + if (filename not in matches): + matches[filename] = list() + matches[filename].append("#" + str(lineno + 1).ljust(10) + line.strip()) + totalcount += 1 + f.close() + + for filename in matches: + print " ", filename, "has", len(matches[filename]), "matches:" + for match in matches[filename]: + print " ", match + print + print "A total number of", totalcount, "TODO/FIXME was found" if __name__ == '__main__': main() diff --git a/css/ol.css b/css/ol.css index 5e679f5ddc..eca80d969c 100644 --- a/css/ol.css +++ b/css/ol.css @@ -19,9 +19,6 @@ display: inline; list-style: none; } -.ol-attribution li { - display: inline; -} .ol-attribution li:not(:last-child):after { content: "\2003"; } diff --git a/readme.md b/readme.md index ee031aafbc..62b9f9ed5e 100644 --- a/readme.md +++ b/readme.md @@ -33,7 +33,7 @@ You can turn off compilation by appending `?mode=RAW` to the URL, for example Run the plovr web server (see above), and either open the `test/ol.html` file in the browser (e.g. ), or run `./build.py test` -on the console (headless testing with PhantomJS). +on the console (headless testing with PhantomJS, make sure to install it first from http://phantomjs.org/download.html). See also the test-specific [readme](https://github.com/openlayers/ol3/tree/master/test). @@ -45,6 +45,10 @@ Then: $ ./build.py lint +## Run the precommit hook before pushing a commit: + + $ ./build.py precommit + ## Add examples The examples are located in the `examples` directory. Adding a new example diff --git a/src/ol/browserfeature.js b/src/ol/browserfeature.js index 7335f387fd..46e40e6394 100644 --- a/src/ol/browserfeature.js +++ b/src/ol/browserfeature.js @@ -15,5 +15,6 @@ ol.BrowserFeature = { * @type {boolean} True if browser supports touch events */ HAS_TOUCH: ol.ASSUME_TOUCH || - (document && 'ontouchstart' in document.documentElement) + (document && 'ontouchstart' in document.documentElement) || + !!(window.navigator.msPointerEnabled) }; diff --git a/src/ol/control/attributioncontrol.js b/src/ol/control/attributioncontrol.js index 52e33effba..e8da8080b8 100644 --- a/src/ol/control/attributioncontrol.js +++ b/src/ol/control/attributioncontrol.js @@ -24,7 +24,7 @@ ol.control.Attribution = function(attributionOptions) { this.ulElement_ = goog.dom.createElement(goog.dom.TagName.UL); var element = goog.dom.createDom(goog.dom.TagName.DIV, { - 'class': 'ol-attribution' + 'class': 'ol-attribution ol-unselectable' }, this.ulElement_); goog.base(this, { diff --git a/src/ol/interaction/draginteraction.js b/src/ol/interaction/draginteraction.js index b41e548a6b..1d525bae7d 100644 --- a/src/ol/interaction/draginteraction.js +++ b/src/ol/interaction/draginteraction.js @@ -80,6 +80,13 @@ ol.interaction.Drag.prototype.handleDragEnd = goog.nullFunction; ol.interaction.Drag.prototype.handleDragStart = goog.functions.FALSE; +/** + * @param {ol.MapBrowserEvent} mapBrowserEvent Event. + * @protected + */ +ol.interaction.Drag.prototype.handleDown = goog.nullFunction; + + /** * @inheritDoc */ @@ -91,6 +98,10 @@ ol.interaction.Drag.prototype.handleMapBrowserEvent = } var view = map.getView(); var browserEvent = mapBrowserEvent.browserEvent; + if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.DOWN) { + goog.asserts.assert(browserEvent instanceof goog.events.BrowserEvent); + this.handleDown(mapBrowserEvent); + } if (this.dragging_) { if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.DRAG) { goog.asserts.assert(browserEvent instanceof goog.events.BrowserEvent); diff --git a/src/ol/interaction/dragpaninteraction.js b/src/ol/interaction/dragpaninteraction.js index 3fcc4d4157..5c516d62ff 100644 --- a/src/ol/interaction/dragpaninteraction.js +++ b/src/ol/interaction/dragpaninteraction.js @@ -16,8 +16,9 @@ goog.require('ol.interaction.Drag'); * @constructor * @extends {ol.interaction.Drag} * @param {ol.interaction.ConditionType} condition Condition. + * @param {ol.Kinetic=} opt_kinetic Kinetic object. */ -ol.interaction.DragPan = function(condition) { +ol.interaction.DragPan = function(condition, opt_kinetic) { goog.base(this); @@ -27,6 +28,18 @@ ol.interaction.DragPan = function(condition) { */ this.condition_ = condition; + /** + * @private + * @type {ol.Kinetic|undefined} + */ + this.kinetic_ = opt_kinetic; + + /** + * @private + * @type {?ol.PreRenderFunction} + */ + this.kineticPreRenderFn_ = null; + }; goog.inherits(ol.interaction.DragPan, ol.interaction.Drag); @@ -35,6 +48,9 @@ goog.inherits(ol.interaction.DragPan, ol.interaction.Drag); * @inheritDoc */ ol.interaction.DragPan.prototype.handleDrag = function(mapBrowserEvent) { + if (this.kinetic_) { + this.kinetic_.update(mapBrowserEvent.browserEvent); + } var map = mapBrowserEvent.map; // FIXME works for View2D only var view = map.getView(); @@ -55,9 +71,27 @@ ol.interaction.DragPan.prototype.handleDrag = function(mapBrowserEvent) { * @inheritDoc */ ol.interaction.DragPan.prototype.handleDragEnd = function(mapBrowserEvent) { + + // FIXME works for View2D only + var map = mapBrowserEvent.map; - map.requestRenderFrame(); - map.getView().setHint(ol.ViewHint.PANNING, -1); + var view = map.getView(); + view.setHint(ol.ViewHint.PANNING, -1); + + if (this.kinetic_ && this.kinetic_.end()) { + var distance = this.kinetic_.getDistance(); + var angle = this.kinetic_.getAngle(); + var center = view.getCenter(); + this.kineticPreRenderFn_ = this.kinetic_.createPanFrom(center); + map.addPreRenderFunction(this.kineticPreRenderFn_); + + var centerpx = map.getPixelFromCoordinate(center); + var destpx = new ol.Pixel( + centerpx.x - distance * Math.cos(angle), + centerpx.y - distance * Math.sin(angle)); + var dest = map.getCoordinateFromPixel(destpx); + view.setCenter(dest); + } }; @@ -67,6 +101,9 @@ ol.interaction.DragPan.prototype.handleDragEnd = function(mapBrowserEvent) { ol.interaction.DragPan.prototype.handleDragStart = function(mapBrowserEvent) { var browserEvent = mapBrowserEvent.browserEvent; if (this.condition_(browserEvent)) { + if (this.kinetic_) { + this.kinetic_.begin(browserEvent); + } var map = mapBrowserEvent.map; map.requestRenderFrame(); map.getView().setHint(ol.ViewHint.PANNING, 1); @@ -75,3 +112,21 @@ ol.interaction.DragPan.prototype.handleDragStart = function(mapBrowserEvent) { return false; } }; + + +/** + * @inheritDoc + */ +ol.interaction.DragPan.prototype.handleDown = function(mapBrowserEvent) { + var map = mapBrowserEvent.map; + // FIXME works for View2D only + var view = map.getView(); + goog.asserts.assert(view instanceof ol.View2D); + goog.asserts.assert(!goog.isNull(mapBrowserEvent.frameState)); + if (!goog.isNull(this.kineticPreRenderFn_) && + map.removePreRenderFunction(this.kineticPreRenderFn_)) { + map.requestRenderFrame(); + view.setCenter(mapBrowserEvent.frameState.view2DState.center); + this.kineticPreRenderFn_ = null; + } +}; diff --git a/src/ol/kinetic.js b/src/ol/kinetic.js new file mode 100644 index 0000000000..44aabe850b --- /dev/null +++ b/src/ol/kinetic.js @@ -0,0 +1,154 @@ + +goog.provide('ol.Kinetic'); + +goog.require('goog.array'); +goog.require('ol.Pixel'); +goog.require('ol.animation'); + + +/** + * @typedef {{x: number, + * y: number, + * t: number}} + */ +ol.KineticPoint; + + + +/** + * @constructor + * @param {number} decay Rate of decay (must be negative). + * @param {number} minVelocity Minimum velocity (pixels/millisecond). + * @param {number} delay Delay to consider to calculate the kinetic + * initial values (milliseconds). + */ +ol.Kinetic = function(decay, minVelocity, delay) { + + /** + * @private + * @type {number} + */ + this.decay_ = decay; + + /** + * @private + * @type {number} + */ + this.minVelocity_ = minVelocity; + + /** + * @private + * @type {number} + */ + this.delay_ = delay; + + /** + * @private + * @type {Array.} + */ + this.points_ = []; + + /** + * @private + * @type {number} + */ + this.angle_ = 0; + + /** + * @private + * @type {number} + */ + this.initialVelocity_ = 0; +}; + + +/** + * @param {goog.events.BrowserEvent} browserEvent Browser event. + */ +ol.Kinetic.prototype.begin = function(browserEvent) { + this.points_.length = 0; + this.angle_ = 0; + this.initialVelocity_ = 0; + this.update(browserEvent); +}; + + +/** + * @param {goog.events.BrowserEvent} browserEvent Browser event. + */ +ol.Kinetic.prototype.update = function(browserEvent) { + this.points_.push({ + x: browserEvent.clientX, + y: browserEvent.clientY, + t: goog.now() + }); +}; + + +/** + * @return {boolean} Whether we should do kinetic animation. + */ +ol.Kinetic.prototype.end = function() { + var now = goog.now(); + var lastIndex = this.points_.length - 1; + var firstIndex = lastIndex - 1; + while (firstIndex >= 0 && this.points_[firstIndex].t > now - this.delay_) { + firstIndex--; + } + if (firstIndex >= 0) { + var first = this.points_[firstIndex]; + var last = this.points_[lastIndex]; + var dx = last.x - first.x; + var dy = last.y - first.y; + this.angle_ = Math.atan2(dy, dx); + this.initialVelocity_ = Math.sqrt(dx * dx + dy * dy) / (last.t - first.t); + return this.initialVelocity_ > this.minVelocity_; + } + return false; +}; + + +/** + * @param {ol.Coordinate} source Source coordinate for the animation. + * @return {ol.PreRenderFunction} Pre-render function for kinetic animation. + */ +ol.Kinetic.prototype.createPanFrom = function(source) { + var decay = this.decay_; + var initialVelocity = this.initialVelocity_; + var minVelocity = this.minVelocity_; + var duration = this.getDuration_(); + var easingFunction = function(t) { + return initialVelocity * (Math.exp((decay * t) * duration) - 1) / + (minVelocity - initialVelocity); + }; + return ol.animation.createPanFrom({ + source: source, + duration: duration, + easing: easingFunction + }); +}; + + +/** + * @private + * @return {number} Duration of animation (milliseconds). + */ +ol.Kinetic.prototype.getDuration_ = function() { + return Math.log(this.minVelocity_ / this.initialVelocity_) / this.decay_; +}; + + +/** + * @return {number} Total distance travelled (pixels). + */ +ol.Kinetic.prototype.getDistance = function() { + return (this.minVelocity_ - this.initialVelocity_) / this.decay_; +}; + + +/** + * @return {number} Angle of the kinetic panning animation (radians). + */ +ol.Kinetic.prototype.getAngle = function() { + return this.angle_; +}; diff --git a/src/ol/map.js b/src/ol/map.js index 277ef4a172..22609eb4a6 100644 --- a/src/ol/map.js +++ b/src/ol/map.js @@ -29,6 +29,7 @@ goog.require('ol.Color'); goog.require('ol.Coordinate'); goog.require('ol.Extent'); goog.require('ol.FrameState'); +goog.require('ol.Kinetic'); goog.require('ol.MapBrowserEvent'); goog.require('ol.Object'); goog.require('ol.Pixel'); @@ -189,6 +190,8 @@ ol.Map = function(mapOptions) { this.viewport_.style.overflow = 'hidden'; this.viewport_.style.width = '100%'; this.viewport_.style.height = '100%'; + // prevent page zoom on IE >= 10 browsers + this.viewport_.style.msTouchAction = 'none'; goog.dom.appendChild(this.target_, this.viewport_); /** @@ -205,13 +208,9 @@ ol.Map = function(mapOptions) { goog.dom.appendChild(this.viewport_, this.overlayContainer_); var mapBrowserEventHandler = new ol.MapBrowserEventHandler(this); - goog.events.listen(mapBrowserEventHandler, [ - ol.MapBrowserEvent.EventType.CLICK, - ol.MapBrowserEvent.EventType.DBLCLICK, - ol.MapBrowserEvent.EventType.DRAGSTART, - ol.MapBrowserEvent.EventType.DRAG, - ol.MapBrowserEvent.EventType.DRAGEND - ], this.handleMapBrowserEvent, false, this); + goog.events.listen(mapBrowserEventHandler, + goog.object.getValues(ol.MapBrowserEvent.EventType), + this.handleMapBrowserEvent, false, this); this.registerDisposable(mapBrowserEventHandler); // FIXME we probably shouldn't listen on document... @@ -289,7 +288,7 @@ ol.Map = function(mapOptions) { this.handleSizeChanged_, false, this); goog.events.listen( this, ol.Object.getChangedEventType(ol.MapProperty.BACKGROUND_COLOR), - this.handleBackgroundColorChanged_, false, this), + this.handleBackgroundColorChanged_, false, this); this.setValues(mapOptionsInternal.values); // this gives the map an initial size @@ -327,6 +326,15 @@ ol.Map.prototype.addPreRenderFunctions = function(preRenderFunctions) { }; +/** + * @param {ol.PreRenderFunction} preRenderFunction Pre-render function. + * @return {boolean} Whether the preRenderFunction has been found and removed. + */ +ol.Map.prototype.removePreRenderFunction = function(preRenderFunction) { + return goog.array.remove(this.preRenderFunctions_, preRenderFunction); +}; + + /** * * @inheritDoc @@ -534,6 +542,7 @@ ol.Map.prototype.handleControlsRemove_ = function(collectionEvent) { * @param {ol.MapBrowserEvent} mapBrowserEvent The event to handle. */ ol.Map.prototype.handleMapBrowserEvent = function(mapBrowserEvent) { + mapBrowserEvent.frameState = this.frameState_; var interactions = this.getInteractions(); var interactionsArray = /** @type {Array.} */ (interactions.getArray()); @@ -986,7 +995,8 @@ ol.Map.createInteractions_ = function(mapOptions) { mapOptions.dragPan : true; if (dragPan) { interactions.push( - new ol.interaction.DragPan(ol.interaction.condition.noModifierKeys)); + new ol.interaction.DragPan(ol.interaction.condition.noModifierKeys, + new ol.Kinetic(-0.005, 0.05, 100))); } var keyboard = goog.isDef(mapOptions.keyboard) ? diff --git a/src/ol/mapbrowserevent.js b/src/ol/mapbrowserevent.js index 17defe5f20..a6b0f20be7 100644 --- a/src/ol/mapbrowserevent.js +++ b/src/ol/mapbrowserevent.js @@ -21,10 +21,11 @@ goog.require('ol.Pixel'); * @param {string} type Event type. * @param {ol.Map} map Map. * @param {goog.events.BrowserEvent} browserEvent Browser event. + * @param {?ol.FrameState=} opt_frameState Frame state. */ -ol.MapBrowserEvent = function(type, map, browserEvent) { +ol.MapBrowserEvent = function(type, map, browserEvent, opt_frameState) { - goog.base(this, type, map); + goog.base(this, type, map, opt_frameState); /** * @type {goog.events.BrowserEvent} @@ -117,6 +118,18 @@ ol.MapBrowserEventHandler = function(map) { */ this.timestamp_ = 0; + /** + * @type {?number} + * @private + */ + this.clickListenerKey_ = null; + + /** + * @type {?number} + * @private + */ + this.downListenerKey_ = null; + /** * @type {Array.} * @private @@ -131,11 +144,11 @@ ol.MapBrowserEventHandler = function(map) { var element = this.map_.getViewport(); if (!ol.BrowserFeature.HAS_TOUCH) { - goog.events.listen(element, + this.clickListenerKey_ = goog.events.listen(element, [goog.events.EventType.CLICK, goog.events.EventType.DBLCLICK], this.click_, false, this); } - goog.events.listen(element, + this.downListenerKey_ = goog.events.listen(element, ol.BrowserFeature.HAS_TOUCH ? goog.events.EventType.TOUCHSTART : goog.events.EventType.MOUSEDOWN, @@ -218,6 +231,9 @@ ol.MapBrowserEventHandler.prototype.handleUp_ = function(browserEvent) { * @private */ ol.MapBrowserEventHandler.prototype.handleDown_ = function(browserEvent) { + var newEvent = new ol.MapBrowserEvent( + ol.MapBrowserEvent.EventType.DOWN, this.map_, browserEvent); + this.dispatchEvent(newEvent); if (!this.previous_) { this.touchEnableBrowserEvent_(browserEvent); this.down_ = browserEvent; @@ -275,19 +291,8 @@ ol.MapBrowserEventHandler.prototype.drag_ = function(browserEvent) { * FIXME empty description for jsdoc */ ol.MapBrowserEventHandler.prototype.disposeInternal = function() { - var element = this.map_.getViewport(); - goog.events.unlisten(element, - ol.BrowserFeature.HAS_TOUCH ? - goog.events.EventType.TOUCHSTART : - goog.events.EventType.MOUSEDOWN, - this.handleDown_, false, this); - goog.events.unlisten(element, - ol.BrowserFeature.HAS_TOUCH ? - goog.events.EventType.TOUCHEND : - goog.events.EventType.MOUSEUP, - this.handleUp_, false, this); - goog.events.unlisten(element, - goog.events.EventType.CLICK, this.click_, false, this); + goog.events.unlistenByKey(this.clickListenerKey_); + goog.events.unlistenByKey(this.downListenerKey_); if (!goog.isNull(this.dragListenerKeys_)) { goog.array.forEach(this.dragListenerKeys_, goog.events.unlistenByKey); this.dragListenerKeys_ = null; @@ -305,5 +310,6 @@ ol.MapBrowserEvent.EventType = { DBLCLICK: goog.events.EventType.DBLCLICK, DRAGSTART: 'dragstart', DRAG: 'drag', - DRAGEND: 'dragend' + DRAGEND: 'dragend', + DOWN: 'down' }; diff --git a/src/ol/renderer/canvas/canvaslayerrenderer.js b/src/ol/renderer/canvas/canvaslayerrenderer.js index 78ed9d6665..f63048d8e3 100644 --- a/src/ol/renderer/canvas/canvaslayerrenderer.js +++ b/src/ol/renderer/canvas/canvaslayerrenderer.js @@ -1,7 +1,5 @@ goog.provide('ol.renderer.canvas.Layer'); -goog.require('ol.FrameState'); -goog.require('ol.layer.LayerState'); goog.require('ol.renderer.Layer'); @@ -28,10 +26,3 @@ ol.renderer.canvas.Layer.prototype.getImage = goog.abstractMethod; * @return {!goog.vec.Mat4.Number} Transform. */ ol.renderer.canvas.Layer.prototype.getTransform = goog.abstractMethod; - - -/** - * @param {ol.FrameState} frameState Frame state. - * @param {ol.layer.LayerState} layerState Layer state. - */ -ol.renderer.canvas.Layer.prototype.renderFrame = goog.abstractMethod; diff --git a/src/ol/renderer/canvas/canvasmaprenderer.js b/src/ol/renderer/canvas/canvasmaprenderer.js index 2697b07d1d..f3b05ed53e 100644 --- a/src/ol/renderer/canvas/canvasmaprenderer.js +++ b/src/ol/renderer/canvas/canvasmaprenderer.js @@ -123,17 +123,20 @@ ol.renderer.canvas.Map.prototype.renderFrame = function(frameState) { var layerRenderer = this.getLayerRenderer(layer); layerRenderer.renderFrame(frameState, layerState); - var transform = layerRenderer.getTransform(); - context.setTransform( - goog.vec.Mat4.getElement(transform, 0, 0), - goog.vec.Mat4.getElement(transform, 1, 0), - goog.vec.Mat4.getElement(transform, 0, 1), - goog.vec.Mat4.getElement(transform, 1, 1), - goog.vec.Mat4.getElement(transform, 0, 3), - goog.vec.Mat4.getElement(transform, 1, 3)); + var image = layerRenderer.getImage(); + if (!goog.isNull(image)) { + var transform = layerRenderer.getTransform(); + context.setTransform( + goog.vec.Mat4.getElement(transform, 0, 0), + goog.vec.Mat4.getElement(transform, 1, 0), + goog.vec.Mat4.getElement(transform, 0, 1), + goog.vec.Mat4.getElement(transform, 1, 1), + goog.vec.Mat4.getElement(transform, 0, 3), + goog.vec.Mat4.getElement(transform, 1, 3)); - context.globalAlpha = layerState.opacity; - context.drawImage(layerRenderer.getImage(), 0, 0); + context.globalAlpha = layerState.opacity; + context.drawImage(image, 0, 0); + } }, this); diff --git a/src/ol/renderer/dom/domlayerrenderer.js b/src/ol/renderer/dom/domlayerrenderer.js index 261c24948f..5a39813363 100644 --- a/src/ol/renderer/dom/domlayerrenderer.js +++ b/src/ol/renderer/dom/domlayerrenderer.js @@ -1,9 +1,7 @@ goog.provide('ol.renderer.dom.Layer'); goog.require('ol.Coordinate'); -goog.require('ol.FrameState'); goog.require('ol.layer.Layer'); -goog.require('ol.layer.LayerState'); goog.require('ol.renderer.Layer'); @@ -44,34 +42,3 @@ ol.renderer.dom.Layer.prototype.disposeInternal = function() { ol.renderer.dom.Layer.prototype.getTarget = function() { return this.target; }; - - -/** - * @inheritDoc - */ -ol.renderer.dom.Layer.prototype.handleLayerLoad = function() { - this.getMap().render(); -}; - - -/** - * @inheritDoc - */ -ol.renderer.dom.Layer.prototype.handleLayerOpacityChange = function() { - this.getMap().render(); -}; - - -/** - * @inheritDoc - */ -ol.renderer.dom.Layer.prototype.handleLayerVisibleChange = function() { - this.getMap().render(); -}; - - -/** - * @param {ol.FrameState} frameState Frame state. - * @param {ol.layer.LayerState} layerState Layer state. - */ -ol.renderer.dom.Layer.prototype.renderFrame = goog.abstractMethod; diff --git a/src/ol/renderer/dom/dommaprenderer.js b/src/ol/renderer/dom/dommaprenderer.js index 6f9724a746..fd6bfc75b8 100644 --- a/src/ol/renderer/dom/dommaprenderer.js +++ b/src/ol/renderer/dom/dommaprenderer.js @@ -30,7 +30,7 @@ ol.renderer.dom.Map = function(container, map) { * @private */ this.layersPane_ = goog.dom.createElement(goog.dom.TagName.DIV); - this.layersPane_.className = 'ol-layers-pane ol-unselectable'; + this.layersPane_.className = 'ol-layers ol-unselectable'; var style = this.layersPane_.style; style.position = 'absolute'; style.width = '100%'; diff --git a/src/ol/renderer/dom/domtilelayerrenderer.js b/src/ol/renderer/dom/domtilelayerrenderer.js index 27b2b6a804..5a87a865c6 100644 --- a/src/ol/renderer/dom/domtilelayerrenderer.js +++ b/src/ol/renderer/dom/domtilelayerrenderer.js @@ -30,7 +30,7 @@ goog.require('ol.tilegrid.TileGrid'); ol.renderer.dom.TileLayer = function(mapRenderer, tileLayer) { var target = goog.dom.createElement(goog.dom.TagName.DIV); - target.className = 'ol-layer'; + target.className = 'ol-layer-tile'; target.style.position = 'absolute'; goog.base(this, mapRenderer, tileLayer, target); diff --git a/src/ol/renderer/layerrenderer.js b/src/ol/renderer/layerrenderer.js index b3243519e9..e3f2b01635 100644 --- a/src/ol/renderer/layerrenderer.js +++ b/src/ol/renderer/layerrenderer.js @@ -7,6 +7,7 @@ goog.require('ol.Object'); goog.require('ol.TileRange'); goog.require('ol.layer.Layer'); goog.require('ol.layer.LayerProperty'); +goog.require('ol.layer.LayerState'); goog.require('ol.source.TileSource'); @@ -64,6 +65,14 @@ ol.renderer.Layer = function(mapRenderer, layer) { goog.inherits(ol.renderer.Layer, ol.Object); +/** + * @protected + */ +ol.renderer.Layer.prototype.dispatchChangeEvent = function() { + this.dispatchEvent(goog.events.EventType.CHANGE); +}; + + /** * @return {ol.layer.Layer} Layer. */ @@ -109,13 +118,17 @@ ol.renderer.Layer.prototype.handleLayerHueChange = goog.nullFunction; /** * @protected */ -ol.renderer.Layer.prototype.handleLayerLoad = goog.nullFunction; +ol.renderer.Layer.prototype.handleLayerLoad = function() { + this.dispatchChangeEvent(); +}; /** * @protected */ -ol.renderer.Layer.prototype.handleLayerOpacityChange = goog.nullFunction; +ol.renderer.Layer.prototype.handleLayerOpacityChange = function() { + this.dispatchChangeEvent(); +}; /** @@ -127,7 +140,16 @@ ol.renderer.Layer.prototype.handleLayerSaturationChange = goog.nullFunction; /** * @protected */ -ol.renderer.Layer.prototype.handleLayerVisibleChange = goog.nullFunction; +ol.renderer.Layer.prototype.handleLayerVisibleChange = function() { + this.dispatchChangeEvent(); +}; + + +/** + * @param {ol.FrameState} frameState Frame state. + * @param {ol.layer.LayerState} layerState Layer state. + */ +ol.renderer.Layer.prototype.renderFrame = goog.abstractMethod; /** diff --git a/src/ol/renderer/maprenderer.js b/src/ol/renderer/maprenderer.js index 01313a98b3..fbd45224bf 100644 --- a/src/ol/renderer/maprenderer.js +++ b/src/ol/renderer/maprenderer.js @@ -59,6 +59,12 @@ ol.renderer.Map = function(container, map) { */ this.layersListenerKeys_ = null; + /** + * @private + * @type {Object.} + */ + this.layerRendererChangeListenKeys_ = {}; + }; goog.inherits(ol.renderer.Map, goog.Disposable); @@ -140,8 +146,8 @@ ol.renderer.Map.prototype.getCanvas = goog.functions.NULL; * @return {ol.renderer.Layer} Layer renderer. */ ol.renderer.Map.prototype.getLayerRenderer = function(layer) { - var key = goog.getUid(layer); - var layerRenderer = this.layerRenderers[key]; + var layerKey = goog.getUid(layer); + var layerRenderer = this.layerRenderers[layerKey]; goog.asserts.assert(goog.isDef(layerRenderer)); return layerRenderer; }; @@ -155,6 +161,15 @@ ol.renderer.Map.prototype.getMap = function() { }; +/** + * @param {goog.events.Event} event Event. + * @protected + */ +ol.renderer.Map.prototype.handleLayerRendererChange = function(event) { + this.getMap().render(); +}; + + /** * @param {ol.CollectionEvent} collectionEvent Collection event. * @protected @@ -213,10 +228,12 @@ ol.renderer.Map.prototype.removeLayer = function(layer) { * @protected */ ol.renderer.Map.prototype.removeLayerRenderer = function(layer) { - var key = goog.getUid(layer); - if (key in this.layerRenderers) { - var layerRenderer = this.layerRenderers[key]; - delete this.layerRenderers[key]; + var layerKey = goog.getUid(layer); + if (layerKey in this.layerRenderers) { + var layerRenderer = this.layerRenderers[layerKey]; + delete this.layerRenderers[layerKey]; + goog.events.unlistenByKey(this.layerRendererChangeListenKeys_[layerKey]); + delete this.layerRendererChangeListenKeys_[layerKey]; return layerRenderer; } else { return null; @@ -237,7 +254,11 @@ ol.renderer.Map.prototype.renderFrame = goog.nullFunction; * @protected */ ol.renderer.Map.prototype.setLayerRenderer = function(layer, layerRenderer) { - var key = goog.getUid(layer); - goog.asserts.assert(!(key in this.layerRenderers)); - this.layerRenderers[key] = layerRenderer; + var layerKey = goog.getUid(layer); + goog.asserts.assert(!(layerKey in this.layerRenderers)); + this.layerRenderers[layerKey] = layerRenderer; + goog.asserts.assert(!(layerKey in this.layerRendererChangeListenKeys_)); + this.layerRendererChangeListenKeys_[layerKey] = goog.events.listen( + layerRenderer, goog.events.EventType.CHANGE, + this.handleLayerRendererChange, false, this); }; diff --git a/src/ol/renderer/webgl/webgllayerrenderer.js b/src/ol/renderer/webgl/webgllayerrenderer.js index 7fce8f5256..3f8f3c2d17 100644 --- a/src/ol/renderer/webgl/webgllayerrenderer.js +++ b/src/ol/renderer/webgl/webgllayerrenderer.js @@ -3,9 +3,7 @@ goog.provide('ol.renderer.webgl.Layer'); goog.require('goog.vec.Mat4'); -goog.require('ol.FrameState'); goog.require('ol.layer.Layer'); -goog.require('ol.layer.LayerState'); goog.require('ol.renderer.Layer'); goog.require('ol.vec.Mat4'); @@ -66,14 +64,6 @@ ol.renderer.webgl.Layer = function(mapRenderer, layer) { goog.inherits(ol.renderer.webgl.Layer, ol.renderer.Layer); -/** - * @protected - */ -ol.renderer.webgl.Layer.prototype.dispatchChangeEvent = function() { - this.dispatchEvent(goog.events.EventType.CHANGE); -}; - - /** * @return {!goog.vec.Mat4.Float32} Color matrix. */ @@ -140,22 +130,6 @@ ol.renderer.webgl.Layer.prototype.handleLayerHueChange = function() { }; -/** - * @inheritDoc - */ -ol.renderer.webgl.Layer.prototype.handleLayerLoad = function() { - this.dispatchChangeEvent(); -}; - - -/** - * @inheritDoc - */ -ol.renderer.webgl.Layer.prototype.handleLayerOpacityChange = function() { - this.dispatchChangeEvent(); -}; - - /** * @inheritDoc */ @@ -167,28 +141,12 @@ ol.renderer.webgl.Layer.prototype.handleLayerSaturationChange = function() { }; -/** - * @inheritDoc - */ -ol.renderer.webgl.Layer.prototype.handleLayerVisibleChange = function() { - this.dispatchChangeEvent(); -}; - - /** * Handle webglcontextlost. */ ol.renderer.webgl.Layer.prototype.handleWebGLContextLost = goog.nullFunction; -/** - * Render. - * @param {ol.FrameState} frameState Frame state. - * @param {ol.layer.LayerState} layerState Layer state. - */ -ol.renderer.webgl.Layer.prototype.renderFrame = goog.abstractMethod; - - /** * @private */ diff --git a/src/ol/renderer/webgl/webglmaprenderer.js b/src/ol/renderer/webgl/webglmaprenderer.js index 6a62129e67..6c657fb0f5 100644 --- a/src/ol/renderer/webgl/webglmaprenderer.js +++ b/src/ol/renderer/webgl/webglmaprenderer.js @@ -206,12 +206,6 @@ ol.renderer.webgl.Map = function(container, map) { */ this.vertexShader_ = ol.renderer.webgl.map.shader.Vertex.getInstance(); - /** - * @private - * @type {Object.} - */ - this.layerRendererChangeListenKeys_ = {}; - this.initializeGL_(); }; @@ -409,15 +403,6 @@ ol.renderer.webgl.Map.prototype.getShader = function(shaderObject) { }; -/** - * @param {goog.events.Event} event Event. - * @protected - */ -ol.renderer.webgl.Map.prototype.handleLayerRendererChange = function(event) { - this.getMap().render(); -}; - - /** * @param {goog.events.Event} event Event. * @protected @@ -484,20 +469,6 @@ ol.renderer.webgl.Map.prototype.removeLayer = function(layer) { }; -/** - * @inheritDoc - */ -ol.renderer.webgl.Map.prototype.removeLayerRenderer = function(layer) { - var layerRenderer = goog.base(this, 'removeLayerRenderer', layer); - if (!goog.isNull(layerRenderer)) { - var layerKey = goog.getUid(layer); - goog.events.unlistenByKey(this.layerRendererChangeListenKeys_[layerKey]); - delete this.layerRendererChangeListenKeys_[layerKey]; - } - return layerRenderer; -}; - - /** * @inheritDoc */ @@ -604,16 +575,3 @@ ol.renderer.webgl.Map.prototype.renderFrame = function(frameState) { } }; - - -/** - * @inheritDoc - */ -ol.renderer.webgl.Map.prototype.setLayerRenderer = function( - layer, layerRenderer) { - goog.base(this, 'setLayerRenderer', layer, layerRenderer); - var layerKey = goog.getUid(layer); - this.layerRendererChangeListenKeys_[layerKey] = goog.events.listen( - layerRenderer, goog.events.EventType.CHANGE, - this.handleLayerRendererChange, false, this); -};