From 32a67801e5e4921ca91d84c526ee3fc382516ed3 Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Sun, 7 Dec 2014 16:27:31 -0800 Subject: [PATCH 01/29] Include correct path in error message --- tasks/generate-info.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/generate-info.js b/tasks/generate-info.js index bf3ef4357e..acad5e65f2 100644 --- a/tasks/generate-info.js +++ b/tasks/generate-info.js @@ -58,7 +58,7 @@ function getNewerExterns(date, callback) { next(); }); walker.on('errors', function() { - callback(new Error('Trouble walking ' + sourceDir)); + callback(new Error('Trouble walking ' + externsDir)); }); walker.on('end', function() { callback(null, date, newer); From 4c504ede74b8b92337fd2fec527f1fa1d106931b Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Sun, 7 Dec 2014 16:35:58 -0800 Subject: [PATCH 02/29] Doc fix regarding externs --- tasks/generate-info.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tasks/generate-info.js b/tasks/generate-info.js index acad5e65f2..d79bb67eee 100644 --- a/tasks/generate-info.js +++ b/tasks/generate-info.js @@ -39,11 +39,11 @@ function getInfoTime(callback) { /** - * Test whether externs/olx.js is newer than the provided date. + * Test whether any externs are newer than the provided date. * @param {Date} date Modification time of info file. * @param {function(Error, Date, boolen)} callback Called with any * error, the mtime of the info file (zero date if it doesn't exist), and - * whether externs/olx.js is newer than that date. + * whether any externs are newer than that date. */ function getNewerExterns(date, callback) { var newer = false; @@ -70,7 +70,7 @@ function getNewerExterns(date, callback) { * Generate a list of all .js paths in the source directory if any are newer * than the provided date. * @param {Date} date Modification time of info file. - * @param {boolean} newer Whether externs/olx.js is newer than date. + * @param {boolean} newer Whether any externs are newer than date. * @param {function(Error, Array.)} callback Called with any * error and the array of source paths (empty if none newer). */ From e7db23761cac8e39e39ae7962b45371525aed467 Mon Sep 17 00:00:00 2001 From: Antoine Abt Date: Fri, 12 Dec 2014 11:22:15 +0100 Subject: [PATCH 03/29] Respect geometry stride in modify interaction --- src/ol/interaction/modifyinteraction.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/ol/interaction/modifyinteraction.js b/src/ol/interaction/modifyinteraction.js index 210bff3f68..a78ad7f22b 100644 --- a/src/ol/interaction/modifyinteraction.js +++ b/src/ol/interaction/modifyinteraction.js @@ -433,6 +433,10 @@ ol.interaction.Modify.prototype.handlePointerDrag = function(evt) { var segment = segmentData.segment; var index = dragSegment[1]; + while (vertex.length < geometry.getStride()) { + vertex.push(0); + } + switch (geometry.getType()) { case ol.geom.GeometryType.POINT: coordinates = vertex; @@ -588,6 +592,10 @@ ol.interaction.Modify.prototype.insertVertex_ = function(segmentData, vertex) { var index = segmentData.index; var coordinates; + while (vertex.length < geometry.getStride()) { + vertex.push(0); + } + switch (geometry.getType()) { case ol.geom.GeometryType.MULTI_LINE_STRING: goog.asserts.assertInstanceof(geometry, ol.geom.MultiLineString); From df170859cc51eda6759271c9ea77c2b26a0891f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Mon, 8 Dec 2014 17:03:44 +0100 Subject: [PATCH 04/29] Add a "render" control option --- externs/olx.js | 75 +++++++++++++++++++++++++- src/ol/control/attributioncontrol.js | 10 +++- src/ol/control/control.js | 18 +++---- src/ol/control/mousepositioncontrol.js | 10 +++- src/ol/control/overviewmapcontrol.js | 13 +++-- src/ol/control/rotatecontrol.js | 10 +++- src/ol/control/scalelinecontrol.js | 10 +++- src/ol/control/zoomslidercontrol.js | 12 +++-- 8 files changed, 129 insertions(+), 29 deletions(-) diff --git a/externs/olx.js b/externs/olx.js index d58a126bb3..7decb05bfa 100644 --- a/externs/olx.js +++ b/externs/olx.js @@ -802,6 +802,7 @@ olx.control; * tipLabel: (string|undefined), * label: (string|undefined), * collapseLabel: (string|undefined), + * render: (function(ol.MapEvent)|undefined), * target: (Element|undefined)}} * @api */ @@ -865,8 +866,19 @@ olx.control.AttributionOptions.prototype.label; */ olx.control.AttributionOptions.prototype.collapseLabel; + +/** + * Function called when the control should be re-rendered. This is called + * in a requestAnimationFrame callback. + * @type {function(ol.MapEvent)|undefined} + * @api + */ +olx.control.AttributionOptions.prototype.render; + + /** * @typedef {{element: (Element|undefined), + * render: (function(ol.MapEvent)|undefined), * target: (Element|string|undefined)}} * @api stable */ @@ -882,6 +894,15 @@ olx.control.ControlOptions; olx.control.ControlOptions.prototype.element; +/** + * Function called when the control should be re-rendered. This is called + * in a requestAnimationFrame callback. + * @type {function(ol.MapEvent)|undefined} + * @api + */ +olx.control.ControlOptions.prototype.render; + + /** * Specify a target if you want the control to be rendered outside of the map's * viewport. @@ -997,6 +1018,7 @@ olx.control.FullScreenOptions.prototype.target; * @typedef {{className: (string|undefined), * coordinateFormat: (ol.CoordinateFormatType|undefined), * projection: ol.proj.ProjectionLike, + * render: (function(ol.MapEvent)|undefined), * target: (Element|undefined), * undefinedHTML: (string|undefined)}} * @api stable @@ -1028,6 +1050,15 @@ olx.control.MousePositionOptions.prototype.coordinateFormat; olx.control.MousePositionOptions.prototype.projection; +/** + * Function called when the control should be re-rendered. This is called + * in a requestAnimationFrame callback. + * @type {function(ol.MapEvent)|undefined} + * @api + */ +olx.control.MousePositionOptions.prototype.render; + + /** * Target. * @type {Element|undefined} @@ -1050,6 +1081,7 @@ olx.control.MousePositionOptions.prototype.undefinedHTML; * collapsible: (boolean|undefined), * label: (string|undefined), * layers: (Array.|ol.Collection|undefined), + * render: (function(ol.MapEvent)|undefined), * target: (Element|undefined), * tipLabel: (string|undefined)}} * @api @@ -1099,6 +1131,15 @@ olx.control.OverviewMapOptions.prototype.label; olx.control.OverviewMapOptions.prototype.layers; +/** + * Function called when the control should be re-rendered. This is called + * in a requestAnimationFrame callback. + * @type {function(ol.MapEvent)|undefined} + * @api + */ +olx.control.OverviewMapOptions.prototype.render; + + /** * Specify a target if you want the control to be rendered outside of the map's * viewport. @@ -1119,6 +1160,7 @@ olx.control.OverviewMapOptions.prototype.tipLabel; /** * @typedef {{className: (string|undefined), * minWidth: (number|undefined), + * render: (function(ol.MapEvent)|undefined), * target: (Element|undefined), * units: (ol.control.ScaleLineUnits|string|undefined)}} * @api stable @@ -1142,6 +1184,15 @@ olx.control.ScaleLineOptions.prototype.className; olx.control.ScaleLineOptions.prototype.minWidth; +/** + * Function called when the control should be re-rendered. This is called + * in a requestAnimationFrame callback. + * @type {function(ol.MapEvent)|undefined} + * @api + */ +olx.control.ScaleLineOptions.prototype.render; + + /** * Target. * @type {Element|undefined} @@ -1164,6 +1215,7 @@ olx.control.ScaleLineOptions.prototype.units; * label: (string|undefined), * tipLabel: (string|undefined), * target: (Element|undefined), + * render: (function(ol.MapEvent)|undefined), * autoHide: (boolean|undefined)}} * @api stable */ @@ -1210,6 +1262,15 @@ olx.control.RotateOptions.prototype.duration; olx.control.RotateOptions.prototype.autoHide; +/** + * Function called when the control should be re-rendered. This is called + * in a requestAnimationFrame callback. + * @type {function(ol.MapEvent)|undefined} + * @api + */ +olx.control.RotateOptions.prototype.render; + + /** * Target. * @type {Element|undefined} @@ -1299,8 +1360,9 @@ olx.control.ZoomOptions.prototype.target; /** * @typedef {{className: (string|undefined), * maxResolution: (number|undefined), - * minResolution: (number|undefined)}} - * @api stable + * minResolution: (number|undefined), + * render: (function(ol.MapEvent)|undefined)}} + * @api */ olx.control.ZoomSliderOptions; @@ -1329,6 +1391,15 @@ olx.control.ZoomSliderOptions.prototype.maxResolution; olx.control.ZoomSliderOptions.prototype.minResolution; +/** + * Function called when the control should be re-rendered. This is called + * in a requestAnimationFrame callback. + * @type {function(ol.MapEvent)|undefined} + * @api + */ +olx.control.ZoomSliderOptions.prototype.render; + + /** * @typedef {{className: (string|undefined), * target: (Element|undefined), diff --git a/src/ol/control/attributioncontrol.js b/src/ol/control/attributioncontrol.js index 6953af7843..224f4dc167 100644 --- a/src/ol/control/attributioncontrol.js +++ b/src/ol/control/attributioncontrol.js @@ -113,8 +113,12 @@ ol.control.Attribution = function(opt_options) { var element = goog.dom.createDom(goog.dom.TagName.DIV, cssClasses, this.ulElement_, button); + var render = goog.isDef(options.render) ? + options.render : ol.control.Attribution.render; + goog.base(this, { element: element, + render: render, target: options.target }); @@ -192,9 +196,11 @@ ol.control.Attribution.prototype.getSourceAttributions = function(frameState) { /** - * @inheritDoc + * @param {ol.MapEvent} mapEvent Map event. + * @this {ol.control.Attribution} + * @api */ -ol.control.Attribution.prototype.handleMapPostrender = function(mapEvent) { +ol.control.Attribution.render = function(mapEvent) { this.updateElement_(mapEvent.frameState); }; diff --git a/src/ol/control/control.js b/src/ol/control/control.js index 1695780971..73ce0e112e 100644 --- a/src/ol/control/control.js +++ b/src/ol/control/control.js @@ -66,6 +66,11 @@ ol.control.Control = function(options) { */ this.listenerKeys = []; + /** + * @type {function(ol.MapEvent)} + */ + this.render = goog.isDef(options.render) ? options.render : goog.nullFunction; + }; goog.inherits(ol.control.Control, ol.Object); @@ -89,15 +94,6 @@ ol.control.Control.prototype.getMap = function() { }; -/** - * Function called on each map render. Executes in a requestAnimationFrame - * callback. Can be implemented in sub-classes to re-render the control's - * UI. - * @param {ol.MapEvent} mapEvent Map event. - */ -ol.control.Control.prototype.handleMapPostrender = goog.nullFunction; - - /** * Remove the control from its current map and attach it to the new map. * Subclasses may set up event handlers to get notified about changes to @@ -118,9 +114,9 @@ ol.control.Control.prototype.setMap = function(map) { var target = !goog.isNull(this.target_) ? this.target_ : map.getOverlayContainerStopEvent(); goog.dom.appendChild(target, this.element); - if (this.handleMapPostrender !== goog.nullFunction) { + if (this.render !== goog.nullFunction) { this.listenerKeys.push(goog.events.listen(map, - ol.MapEventType.POSTRENDER, this.handleMapPostrender, false, this)); + ol.MapEventType.POSTRENDER, this.render, false, this)); } map.render(); } diff --git a/src/ol/control/mousepositioncontrol.js b/src/ol/control/mousepositioncontrol.js index 110f59a58e..ef558344aa 100644 --- a/src/ol/control/mousepositioncontrol.js +++ b/src/ol/control/mousepositioncontrol.js @@ -47,8 +47,12 @@ ol.control.MousePosition = function(opt_options) { var element = goog.dom.createDom(goog.dom.TagName.DIV, className); + var render = goog.isDef(options.render) ? + options.render : ol.control.MousePosition.render; + goog.base(this, { element: element, + render: render, target: options.target }); @@ -99,9 +103,11 @@ goog.inherits(ol.control.MousePosition, ol.control.Control); /** - * @inheritDoc + * @param {ol.MapEvent} mapEvent Map event. + * @this {ol.control.MousePosition} + * @api */ -ol.control.MousePosition.prototype.handleMapPostrender = function(mapEvent) { +ol.control.MousePosition.render = function(mapEvent) { var frameState = mapEvent.frameState; if (goog.isNull(frameState)) { this.mapProjection_ = null; diff --git a/src/ol/control/overviewmapcontrol.js b/src/ol/control/overviewmapcontrol.js index a7b5abcdae..628bdc77a1 100644 --- a/src/ol/control/overviewmapcontrol.js +++ b/src/ol/control/overviewmapcontrol.js @@ -136,8 +136,12 @@ ol.control.OverviewMap = function(opt_options) { var element = goog.dom.createDom(goog.dom.TagName.DIV, cssClasses, ovmapDiv, button); + var render = goog.isDef(options.render) ? + options.render : ol.control.OverviewMap.render; + goog.base(this, { element: element, + render: render, target: options.target }); }; @@ -201,12 +205,11 @@ ol.control.OverviewMap.prototype.bindView_ = function() { /** - * Function called on each map render. Executes in a requestAnimationFrame - * callback. Manage the extent of the overview map accordingly, - * then update the overview map box. - * @param {goog.events.Event} event Event. + * @param {ol.MapEvent} mapEvent Map event. + * @this {ol.control.OverviewMap} + * @api */ -ol.control.OverviewMap.prototype.handleMapPostrender = function(event) { +ol.control.OverviewMap.render = function(mapEvent) { this.validateExtent_(); this.updateBox_(); }; diff --git a/src/ol/control/rotatecontrol.js b/src/ol/control/rotatecontrol.js index 8f70495f83..4073063fe7 100644 --- a/src/ol/control/rotatecontrol.js +++ b/src/ol/control/rotatecontrol.js @@ -62,8 +62,12 @@ ol.control.Rotate = function(opt_options) { ol.css.CLASS_CONTROL; var element = goog.dom.createDom(goog.dom.TagName.DIV, cssClasses, button); + var render = goog.isDef(options.render) ? + options.render : ol.control.Rotate.render; + goog.base(this, { element: element, + render: render, target: options.target }); @@ -135,9 +139,11 @@ ol.control.Rotate.prototype.resetNorth_ = function() { /** - * @inheritDoc + * @param {ol.MapEvent} mapEvent Map event. + * @this {ol.control.Rotate} + * @api */ -ol.control.Rotate.prototype.handleMapPostrender = function(mapEvent) { +ol.control.Rotate.render = function(mapEvent) { var frameState = mapEvent.frameState; if (goog.isNull(frameState)) { return; diff --git a/src/ol/control/scalelinecontrol.js b/src/ol/control/scalelinecontrol.js index cf2777df2b..6ef6e4cc28 100644 --- a/src/ol/control/scalelinecontrol.js +++ b/src/ol/control/scalelinecontrol.js @@ -112,8 +112,12 @@ ol.control.ScaleLine = function(opt_options) { */ this.toEPSG4326_ = null; + var render = goog.isDef(options.render) ? + options.render : ol.control.ScaleLine.render; + goog.base(this, { element: this.element_, + render: render, target: options.target }); @@ -152,9 +156,11 @@ goog.exportProperty( /** - * @inheritDoc + * @param {ol.MapEvent} mapEvent Map event. + * @this {ol.control.ScaleLine} + * @api */ -ol.control.ScaleLine.prototype.handleMapPostrender = function(mapEvent) { +ol.control.ScaleLine.render = function(mapEvent) { var frameState = mapEvent.frameState; if (goog.isNull(frameState)) { this.viewState_ = null; diff --git a/src/ol/control/zoomslidercontrol.js b/src/ol/control/zoomslidercontrol.js index 2bac8ca4c0..a2fb2162f5 100644 --- a/src/ol/control/zoomslidercontrol.js +++ b/src/ol/control/zoomslidercontrol.js @@ -100,8 +100,12 @@ ol.control.ZoomSlider = function(opt_options) { goog.events.listen(thumbElement, goog.events.EventType.CLICK, goog.events.Event.stopPropagation); + var render = goog.isDef(options.render) ? + options.render : ol.control.ZoomSlider.render; + goog.base(this, { - element: containerElement + element: containerElement, + render: render }); }; goog.inherits(ol.control.ZoomSlider, ol.control.Control); @@ -166,9 +170,11 @@ ol.control.ZoomSlider.prototype.initSlider_ = function() { /** - * @inheritDoc + * @param {ol.MapEvent} mapEvent Map event. + * @this {ol.control.ZoomSlider} + * @api */ -ol.control.ZoomSlider.prototype.handleMapPostrender = function(mapEvent) { +ol.control.ZoomSlider.render = function(mapEvent) { if (goog.isNull(mapEvent.frameState)) { return; } From d07185e8f2b4cf3dba4e17da38c81703a50aeee0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Mon, 8 Dec 2014 17:52:34 +0100 Subject: [PATCH 05/29] Add an "handleEvent" interaction option --- externs/oli.js | 16 -------- externs/olx.js | 37 +++++++++++++++++++ .../interaction/doubleclickzoominteraction.js | 12 ++++-- src/ol/interaction/draganddropinteraction.js | 12 ++++-- src/ol/interaction/drawinteraction.js | 21 +++++++---- src/ol/interaction/interaction.js | 25 ++++--------- src/ol/interaction/keyboardpaninteraction.js | 12 ++++-- src/ol/interaction/keyboardzoominteraction.js | 12 ++++-- src/ol/interaction/modifyinteraction.js | 16 +++++--- .../interaction/mousewheelzoominteraction.js | 14 ++++--- src/ol/interaction/pointerinteraction.js | 20 +++++++--- src/ol/interaction/selectinteraction.js | 12 ++++-- src/ol/map.js | 2 +- test/spec/ol/interaction/interaction.test.js | 10 ++--- test/spec/ol/map.test.js | 4 +- 15 files changed, 139 insertions(+), 86 deletions(-) diff --git a/externs/oli.js b/externs/oli.js index 16f5a8a201..903fd6e893 100644 --- a/externs/oli.js +++ b/externs/oli.js @@ -137,22 +137,6 @@ oli.control.Control.prototype.setMap = function(map) {}; oli.interaction; - -/** - * @interface - */ -oli.interaction.Interaction = function() {}; - -/** - * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event. - * @return {boolean} Whether the map browser event should continue - * through the chain of interactions. `false` means stop, `true` - * means continue. - */ -oli.interaction.Interaction.prototype.handleMapBrowserEvent = - function(mapBrowserEvent) {}; - - /** * @interface */ diff --git a/externs/olx.js b/externs/olx.js index 7decb05bfa..4370a7602f 100644 --- a/externs/olx.js +++ b/externs/olx.js @@ -172,6 +172,25 @@ olx.GraticuleOptions.prototype.strokeStyle; olx.GraticuleOptions.prototype.targetSize; +/** + * Object literal with config options for interactions. + * @typedef {{handleEvent: function(ol.MapBrowserEvent):boolean}} + * @api + */ +olx.interaction.InteractionOptions; + + +/** + * Method called by the map to notify the interaction that a browser event was + * dispatched to the map. The function may return `false` to prevent the + * propagation of the event to other interactions in the map's interactions + * chain. Required. + * @type {function(ol.MapBrowserEvent):boolean} + * @api + */ +olx.interaction.InteractionOptions.prototype.handleEvent; + + /** * Object literal with config options for the map. * @typedef {{controls: (ol.Collection.|Array.|undefined), @@ -2410,6 +2429,24 @@ olx.interaction.PinchZoomOptions; olx.interaction.PinchZoomOptions.prototype.duration; +/** + * @typedef {{handleEvent: function(ol.MapBrowserEvent):boolean}} + * @api + */ +olx.interaction.PointerOptions; + + +/** + * Method called by the map to notify the interaction that a browser event was + * dispatched to the map. The function may return `false` to prevent the + * propagation of the event to other interactions in the map's interactions + * chain. + * @type {function(ol.MapBrowserEvent):boolean} + * @api + */ +olx.interaction.PointerOptions.prototype.handleEvent; + + /** * @typedef {{addCondition: (ol.events.ConditionType|undefined), * condition: (ol.events.ConditionType|undefined), diff --git a/src/ol/interaction/doubleclickzoominteraction.js b/src/ol/interaction/doubleclickzoominteraction.js index e840045e8d..a01d7ba25c 100644 --- a/src/ol/interaction/doubleclickzoominteraction.js +++ b/src/ol/interaction/doubleclickzoominteraction.js @@ -26,7 +26,9 @@ ol.interaction.DoubleClickZoom = function(opt_options) { */ this.delta_ = goog.isDef(options.delta) ? options.delta : 1; - goog.base(this); + goog.base(this, { + handleEvent: ol.interaction.DoubleClickZoom.handleEvent + }); /** * @private @@ -39,10 +41,12 @@ goog.inherits(ol.interaction.DoubleClickZoom, ol.interaction.Interaction); /** - * @inheritDoc + * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event. + * @return {boolean} `false` to stop event propagation. + * @this {ol.interaction.DoubleClickZoom} + * @api */ -ol.interaction.DoubleClickZoom.prototype.handleMapBrowserEvent = - function(mapBrowserEvent) { +ol.interaction.DoubleClickZoom.handleEvent = function(mapBrowserEvent) { var stopEvent = false; var browserEvent = mapBrowserEvent.browserEvent; if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.DBLCLICK) { diff --git a/src/ol/interaction/draganddropinteraction.js b/src/ol/interaction/draganddropinteraction.js index 382e27d8ea..3769fa094b 100644 --- a/src/ol/interaction/draganddropinteraction.js +++ b/src/ol/interaction/draganddropinteraction.js @@ -29,7 +29,9 @@ ol.interaction.DragAndDrop = function(opt_options) { var options = goog.isDef(opt_options) ? opt_options : {}; - goog.base(this); + goog.base(this, { + handleEvent: ol.interaction.DragAndDrop.handleEvent + }); /** * @private @@ -133,10 +135,12 @@ ol.interaction.DragAndDrop.prototype.handleResult_ = function(file, result) { /** - * @inheritDoc + * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event. + * @return {boolean} `false` to stop event propagation. + * @this {ol.interaction.DragAndDrop} + * @api */ -ol.interaction.DragAndDrop.prototype.handleMapBrowserEvent = - goog.functions.TRUE; +ol.interaction.DragAndDrop.handleEvent = goog.functions.TRUE; /** diff --git a/src/ol/interaction/drawinteraction.js b/src/ol/interaction/drawinteraction.js index 5ce00a70d0..94354c66bc 100644 --- a/src/ol/interaction/drawinteraction.js +++ b/src/ol/interaction/drawinteraction.js @@ -85,7 +85,9 @@ goog.inherits(ol.DrawEvent, goog.events.Event); */ ol.interaction.Draw = function(options) { - goog.base(this); + goog.base(this, { + handleEvent: ol.interaction.Draw.handleEvent + }); /** * @type {ol.Pixel} @@ -236,20 +238,23 @@ ol.interaction.Draw.prototype.setMap = function(map) { /** - * @inheritDoc + * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event. + * @return {boolean} `false` to stop event propagation. + * @this {ol.interaction.Draw} + * @api */ -ol.interaction.Draw.prototype.handleMapBrowserEvent = function(event) { - var map = event.map; +ol.interaction.Draw.handleEvent = function(mapBrowserEvent) { + var map = mapBrowserEvent.map; if (!map.isDef()) { return true; } var pass = true; - if (event.type === ol.MapBrowserEvent.EventType.POINTERMOVE) { - pass = this.handlePointerMove_(event); - } else if (event.type === ol.MapBrowserEvent.EventType.DBLCLICK) { + if (mapBrowserEvent.type === ol.MapBrowserEvent.EventType.POINTERMOVE) { + pass = this.handlePointerMove_(mapBrowserEvent); + } else if (mapBrowserEvent.type === ol.MapBrowserEvent.EventType.DBLCLICK) { pass = false; } - return (goog.base(this, 'handleMapBrowserEvent', event) && pass); + return ol.interaction.Pointer.handleEvent.call(this, mapBrowserEvent) && pass; }; diff --git a/src/ol/interaction/interaction.js b/src/ol/interaction/interaction.js index 76b15d261b..3db0a9c405 100644 --- a/src/ol/interaction/interaction.js +++ b/src/ol/interaction/interaction.js @@ -32,11 +32,11 @@ ol.interaction.InteractionProperty = { * vectors and so are visible on the screen. * * @constructor + * @param {olx.interaction.InteractionOptions} options Options. * @extends {ol.Object} - * @implements {oli.interaction.Interaction} * @api */ -ol.interaction.Interaction = function() { +ol.interaction.Interaction = function(options) { goog.base(this); @@ -48,6 +48,11 @@ ol.interaction.Interaction = function() { this.setActive(true); + /** + * @type {function(ol.MapBrowserEvent):boolean} + */ + this.handleEvent = options.handleEvent; + }; goog.inherits(ol.interaction.Interaction, ol.Object); @@ -76,22 +81,6 @@ ol.interaction.Interaction.prototype.getMap = function() { }; -/** - * Method called by the map to notify the interaction that a browser - * event was dispatched on the map. If the interaction wants to handle - * that event it can return `false` to prevent the propagation of the - * event to other interactions in the map's interactions chain. - * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event. - * @return {boolean} Whether the map browser event should continue - * through the chain of interactions. `false` means stop, `true` - * means continue. - * @function - * @api - */ -ol.interaction.Interaction.prototype.handleMapBrowserEvent = - goog.abstractMethod; - - /** * Activate or deactivate the interaction. * @param {boolean} active Active. diff --git a/src/ol/interaction/keyboardpaninteraction.js b/src/ol/interaction/keyboardpaninteraction.js index 62dab76038..9cfee2d707 100644 --- a/src/ol/interaction/keyboardpaninteraction.js +++ b/src/ol/interaction/keyboardpaninteraction.js @@ -31,7 +31,9 @@ goog.require('ol.interaction.Interaction'); */ ol.interaction.KeyboardPan = function(opt_options) { - goog.base(this); + goog.base(this, { + handleEvent: ol.interaction.KeyboardPan.handleEvent + }); var options = goog.isDef(opt_options) ? opt_options : {}; @@ -54,10 +56,12 @@ goog.inherits(ol.interaction.KeyboardPan, ol.interaction.Interaction); /** - * @inheritDoc + * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event. + * @return {boolean} `false` to stop event propagation. + * @this {ol.interaction.KeyboardPan} + * @api */ -ol.interaction.KeyboardPan.prototype.handleMapBrowserEvent = - function(mapBrowserEvent) { +ol.interaction.KeyboardPan.handleEvent = function(mapBrowserEvent) { var stopEvent = false; if (mapBrowserEvent.type == goog.events.KeyHandler.EventType.KEY) { var keyEvent = /** @type {goog.events.KeyEvent} */ diff --git a/src/ol/interaction/keyboardzoominteraction.js b/src/ol/interaction/keyboardzoominteraction.js index a629ae8ff8..b76f8a0587 100644 --- a/src/ol/interaction/keyboardzoominteraction.js +++ b/src/ol/interaction/keyboardzoominteraction.js @@ -27,7 +27,9 @@ goog.require('ol.interaction.Interaction'); */ ol.interaction.KeyboardZoom = function(opt_options) { - goog.base(this); + goog.base(this, { + handleEvent: ol.interaction.KeyboardZoom.handleEvent + }); var options = goog.isDef(opt_options) ? opt_options : {}; @@ -55,10 +57,12 @@ goog.inherits(ol.interaction.KeyboardZoom, ol.interaction.Interaction); /** - * @inheritDoc + * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event. + * @return {boolean} `false` to stop event propagation. + * @this {ol.interaction.KeyboardZoom} + * @api */ -ol.interaction.KeyboardZoom.prototype.handleMapBrowserEvent = - function(mapBrowserEvent) { +ol.interaction.KeyboardZoom.handleEvent = function(mapBrowserEvent) { var stopEvent = false; if (mapBrowserEvent.type == goog.events.KeyHandler.EventType.KEY) { var keyEvent = /** @type {goog.events.KeyEvent} */ diff --git a/src/ol/interaction/modifyinteraction.js b/src/ol/interaction/modifyinteraction.js index 210bff3f68..c8a41d91e9 100644 --- a/src/ol/interaction/modifyinteraction.js +++ b/src/ol/interaction/modifyinteraction.js @@ -47,8 +47,9 @@ ol.interaction.SegmentDataType; */ ol.interaction.Modify = function(options) { - goog.base(this); - + goog.base(this, { + handleEvent: ol.interaction.Modify.handleEvent + }); /** * @type {ol.events.ConditionType} @@ -481,10 +482,12 @@ ol.interaction.Modify.prototype.handlePointerUp = function(evt) { /** - * @inheritDoc + * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event. + * @return {boolean} `false` to stop event propagation. + * @this {ol.interaction.Modify} + * @api */ -ol.interaction.Modify.prototype.handleMapBrowserEvent = - function(mapBrowserEvent) { +ol.interaction.Modify.handleEvent = function(mapBrowserEvent) { var handled; if (!mapBrowserEvent.map.getView().getHints()[ol.ViewHint.INTERACTING] && mapBrowserEvent.type == ol.MapBrowserEvent.EventType.POINTERMOVE) { @@ -496,7 +499,8 @@ ol.interaction.Modify.prototype.handleMapBrowserEvent = goog.asserts.assertInstanceof(geometry, ol.geom.Point); handled = this.removeVertex_(); } - return goog.base(this, 'handleMapBrowserEvent', mapBrowserEvent) && !handled; + return ol.interaction.Pointer.handleEvent.call(this, mapBrowserEvent) && + !handled; }; diff --git a/src/ol/interaction/mousewheelzoominteraction.js b/src/ol/interaction/mousewheelzoominteraction.js index 0e0f713d18..547ccb577f 100644 --- a/src/ol/interaction/mousewheelzoominteraction.js +++ b/src/ol/interaction/mousewheelzoominteraction.js @@ -21,9 +21,11 @@ goog.require('ol.interaction.Interaction'); */ ol.interaction.MouseWheelZoom = function(opt_options) { - var options = goog.isDef(opt_options) ? opt_options : {}; + goog.base(this, { + handleEvent: ol.interaction.MouseWheelZoom.handleEvent + }); - goog.base(this); + var options = goog.isDef(opt_options) ? opt_options : {}; /** * @private @@ -60,10 +62,12 @@ goog.inherits(ol.interaction.MouseWheelZoom, ol.interaction.Interaction); /** - * @inheritDoc + * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event. + * @return {boolean} `false` to stop event propagation. + * @this {ol.interaction.MouseWheelZoom} + * @api */ -ol.interaction.MouseWheelZoom.prototype.handleMapBrowserEvent = - function(mapBrowserEvent) { +ol.interaction.MouseWheelZoom.handleEvent = function(mapBrowserEvent) { var stopEvent = false; if (mapBrowserEvent.type == goog.events.MouseWheelHandler.EventType.MOUSEWHEEL) { diff --git a/src/ol/interaction/pointerinteraction.js b/src/ol/interaction/pointerinteraction.js index 13123412e5..38ed96fdd6 100644 --- a/src/ol/interaction/pointerinteraction.js +++ b/src/ol/interaction/pointerinteraction.js @@ -17,11 +17,19 @@ goog.require('ol.interaction.Interaction'); * instantiated in apps. * * @constructor + * @param {olx.interaction.PointerOptions=} opt_options Options. * @extends {ol.interaction.Interaction} */ -ol.interaction.Pointer = function() { +ol.interaction.Pointer = function(opt_options) { - goog.base(this); + var options = goog.isDef(opt_options) ? opt_options : {}; + + var handleEvent = goog.isDef(options.handleEvent) ? + options.handleEvent : ol.interaction.Pointer.handleEvent; + + goog.base(this, { + handleEvent: handleEvent + }); /** * @type {boolean} @@ -124,10 +132,12 @@ ol.interaction.Pointer.prototype.handlePointerDown = goog.functions.FALSE; /** - * @inheritDoc + * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event. + * @return {boolean} `false` to stop event propagation. + * @this {ol.interaction.Pointer} + * @api */ -ol.interaction.Pointer.prototype.handleMapBrowserEvent = - function(mapBrowserEvent) { +ol.interaction.Pointer.handleEvent = function(mapBrowserEvent) { if (!(mapBrowserEvent instanceof ol.MapBrowserPointerEvent)) { return true; } diff --git a/src/ol/interaction/selectinteraction.js b/src/ol/interaction/selectinteraction.js index 86f322f1ef..240d262aea 100644 --- a/src/ol/interaction/selectinteraction.js +++ b/src/ol/interaction/selectinteraction.js @@ -28,7 +28,9 @@ goog.require('ol.style.Style'); */ ol.interaction.Select = function(opt_options) { - goog.base(this); + goog.base(this, { + handleEvent: ol.interaction.Select.handleEvent + }); var options = goog.isDef(opt_options) ? opt_options : {}; @@ -115,10 +117,12 @@ ol.interaction.Select.prototype.getFeatures = function() { /** - * @inheritDoc + * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event. + * @return {boolean} `false` to stop event propagation. + * @this {ol.interaction.Select} + * @api */ -ol.interaction.Select.prototype.handleMapBrowserEvent = - function(mapBrowserEvent) { +ol.interaction.Select.handleEvent = function(mapBrowserEvent) { if (!this.condition_(mapBrowserEvent)) { return true; } diff --git a/src/ol/map.js b/src/ol/map.js index 6905e65eae..4ee6642c5f 100644 --- a/src/ol/map.js +++ b/src/ol/map.js @@ -870,7 +870,7 @@ ol.Map.prototype.handleMapBrowserEvent = function(mapBrowserEvent) { if (!interaction.getActive()) { continue; } - var cont = interaction.handleMapBrowserEvent(mapBrowserEvent); + var cont = interaction.handleEvent(mapBrowserEvent); if (!cont) { break; } diff --git a/test/spec/ol/interaction/interaction.test.js b/test/spec/ol/interaction/interaction.test.js index 1de7d915bf..bff9c9ee13 100644 --- a/test/spec/ol/interaction/interaction.test.js +++ b/test/spec/ol/interaction/interaction.test.js @@ -6,7 +6,7 @@ describe('ol.interaction.Interaction', function() { var interaction; beforeEach(function() { - interaction = new ol.interaction.Interaction(); + interaction = new ol.interaction.Interaction({}); }); it('creates a new interaction', function() { @@ -24,13 +24,13 @@ describe('ol.interaction.Interaction', function() { it('retrieves the associated map', function() { var map = new ol.Map({}); - var interaction = new ol.interaction.Interaction(); + var interaction = new ol.interaction.Interaction({}); interaction.setMap(map); expect(interaction.getMap()).to.be(map); }); it('returns null if no map', function() { - var interaction = new ol.interaction.Interaction(); + var interaction = new ol.interaction.Interaction({}); expect(interaction.getMap()).to.be(null); }); @@ -40,13 +40,13 @@ describe('ol.interaction.Interaction', function() { it('allows a map to be set', function() { var map = new ol.Map({}); - var interaction = new ol.interaction.Interaction(); + var interaction = new ol.interaction.Interaction({}); interaction.setMap(map); expect(interaction.getMap()).to.be(map); }); it('accepts null', function() { - var interaction = new ol.interaction.Interaction(); + var interaction = new ol.interaction.Interaction({}); interaction.setMap(null); expect(interaction.getMap()).to.be(null); }); diff --git a/test/spec/ol/map.test.js b/test/spec/ol/map.test.js index 4aedaf1464..ef6a658606 100644 --- a/test/spec/ol/map.test.js +++ b/test/spec/ol/map.test.js @@ -23,7 +23,7 @@ describe('ol.Map', function() { describe('#addInteraction()', function() { it('adds an interaction to the map', function() { var map = new ol.Map({}); - var interaction = new ol.interaction.Interaction(); + var interaction = new ol.interaction.Interaction({}); var before = map.getInteractions().getLength(); map.addInteraction(interaction); @@ -36,7 +36,7 @@ describe('ol.Map', function() { describe('#removeInteraction()', function() { it('removes an interaction from the map', function() { var map = new ol.Map({}); - var interaction = new ol.interaction.Interaction(); + var interaction = new ol.interaction.Interaction({}); var before = map.getInteractions().getLength(); map.addInteraction(interaction); From a9f3367310680a935dfa4e7e19f65dc272d55724 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Mon, 8 Dec 2014 17:04:32 +0100 Subject: [PATCH 06/29] Rename handleMapPostrender to render (overlay) --- src/ol/overlay.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ol/overlay.js b/src/ol/overlay.js index 9f569b6e97..cec759b9aa 100644 --- a/src/ol/overlay.js +++ b/src/ol/overlay.js @@ -256,7 +256,7 @@ ol.Overlay.prototype.handleMapChanged = function() { var map = this.getMap(); if (goog.isDefAndNotNull(map)) { this.mapPostrenderListenerKey_ = goog.events.listen(map, - ol.MapEventType.POSTRENDER, this.handleMapPostrender, false, this); + ol.MapEventType.POSTRENDER, this.render, false, this); this.updatePixelPosition_(); var container = this.stopEvent_ ? map.getOverlayContainerStopEvent() : map.getOverlayContainer(); @@ -273,7 +273,7 @@ ol.Overlay.prototype.handleMapChanged = function() { /** * @protected */ -ol.Overlay.prototype.handleMapPostrender = function() { +ol.Overlay.prototype.render = function() { this.updatePixelPosition_(); }; From c167b2b49d54b3af5b1032e5cd0be23d14780129 Mon Sep 17 00:00:00 2001 From: Frederic Junod Date: Mon, 15 Dec 2014 09:30:37 +0100 Subject: [PATCH 07/29] Transform the coordinates in place --- src/ol/render/canvas/canvasreplay.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ol/render/canvas/canvasreplay.js b/src/ol/render/canvas/canvasreplay.js index b33ee08d6c..fe3f31258a 100644 --- a/src/ol/render/canvas/canvasreplay.js +++ b/src/ol/render/canvas/canvasreplay.js @@ -1957,9 +1957,9 @@ ol.render.canvas.ReplayGroup.prototype.replay = function( var minY = maxExtent[1]; var maxX = maxExtent[2]; var maxY = maxExtent[3]; - var flatClipCoords = ol.geom.flat.transform.transform2D( - [minX, minY, minX, maxY, maxX, maxY, maxX, minY], - 0, 8, 2, transform); + var flatClipCoords = [minX, minY, minX, maxY, maxX, maxY, maxX, minY]; + ol.geom.flat.transform.transform2D( + flatClipCoords, 0, 8, 2, transform, flatClipCoords); context.save(); context.beginPath(); context.moveTo(flatClipCoords[0], flatClipCoords[1]); From 9b0b1543e03ed6884d57159e8928365fa5a5b76c Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Mon, 15 Dec 2014 11:19:22 +0100 Subject: [PATCH 08/29] Allow custom mousemove conditions When configuring a Select interaction with a custom condition that includes mousemove, panning the map will not work any more. This is because the return value of handleMapBrowserEvent is determined by checking for a default condition function. By checking for the underlying event type instead, we gain flexibility with custom condition functions. --- src/ol/interaction/selectinteraction.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ol/interaction/selectinteraction.js b/src/ol/interaction/selectinteraction.js index 86f322f1ef..fff8ffeae2 100644 --- a/src/ol/interaction/selectinteraction.js +++ b/src/ol/interaction/selectinteraction.js @@ -179,7 +179,7 @@ ol.interaction.Select.prototype.handleMapBrowserEvent = } features.extend(selected); } - return this.condition_ == ol.events.condition.mouseMove; + return ol.events.condition.mouseMove(mapBrowserEvent); }; From ae998a75858082f04ab972d2b85ec5c673ed9ea2 Mon Sep 17 00:00:00 2001 From: Guillaume Beraudo Date: Mon, 15 Dec 2014 14:41:35 +0100 Subject: [PATCH 09/29] Mark Image style constructor properties `@api` --- src/ol/style/imagestyle.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ol/style/imagestyle.js b/src/ol/style/imagestyle.js index be7c270788..d34d74ce3b 100644 --- a/src/ol/style/imagestyle.js +++ b/src/ol/style/imagestyle.js @@ -70,6 +70,7 @@ ol.style.Image = function(options) { /** * @return {number} Opacity. + * @api */ ol.style.Image.prototype.getOpacity = function() { return this.opacity_; @@ -78,6 +79,7 @@ ol.style.Image.prototype.getOpacity = function() { /** * @return {boolean} Rotate with map. + * @api */ ol.style.Image.prototype.getRotateWithView = function() { return this.rotateWithView_; @@ -104,6 +106,7 @@ ol.style.Image.prototype.getScale = function() { /** * @return {boolean} Snap to pixel? + * @api */ ol.style.Image.prototype.getSnapToPixel = function() { return this.snapToPixel_; From 3c00c7cf4c962ee142de629da6825b66b8b9fac4 Mon Sep 17 00:00:00 2001 From: Guillaume Beraudo Date: Mon, 15 Dec 2014 15:21:55 +0100 Subject: [PATCH 10/29] Print example name in check-examples exception --- build.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build.py b/build.py index abcda2669d..9b5348459d 100755 --- a/build.py +++ b/build.py @@ -32,7 +32,11 @@ class ThreadPool: try: function(*args, **kargs) except: + print("ERROR") + for count, thing in enumerate(args): + print '{0}. {1}'.format(count, thing) print(sys.exc_info()[0]) + print("ERROR") self.tasks.errors = True self.tasks.task_done() From 7a09b11da558d60d80b24ed63c3aec6dacb47751 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Mon, 15 Dec 2014 15:24:28 +0100 Subject: [PATCH 11/29] Use // NOCOMPILE for vector-wfs This is temporary solution until the demo.boundless.com WFS works again. --- examples/vector-wfs.js | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/vector-wfs.js b/examples/vector-wfs.js index 30c2b9d2ef..96f3d7e318 100644 --- a/examples/vector-wfs.js +++ b/examples/vector-wfs.js @@ -1,3 +1,4 @@ +// NOCOMPILE goog.require('ol.Map'); goog.require('ol.View'); goog.require('ol.format.GeoJSON'); From 5eb1537f483ad95598fecdf0be1babc2bff9df44 Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Mon, 15 Dec 2014 16:15:30 +0100 Subject: [PATCH 12/29] Need exportable constructor for constructor options in olx When a constructor options object is created in the olx namespace, the constructor that uses it must be exportable as well. --- src/ol/interaction/pointerinteraction.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ol/interaction/pointerinteraction.js b/src/ol/interaction/pointerinteraction.js index 38ed96fdd6..8b90261450 100644 --- a/src/ol/interaction/pointerinteraction.js +++ b/src/ol/interaction/pointerinteraction.js @@ -19,6 +19,7 @@ goog.require('ol.interaction.Interaction'); * @constructor * @param {olx.interaction.PointerOptions=} opt_options Options. * @extends {ol.interaction.Interaction} + * @api */ ol.interaction.Pointer = function(opt_options) { From abdae6248162a8aeb4e60bed8c8735a569cf889f Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Mon, 15 Dec 2014 07:50:48 -0800 Subject: [PATCH 13/29] Move description above annotation to avoid JSDoc warnings --- externs/geojson.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/externs/geojson.js b/externs/geojson.js index 984d0728e4..4d6584539a 100644 --- a/externs/geojson.js +++ b/externs/geojson.js @@ -34,9 +34,9 @@ var GeoJSONCRS = function() {}; /** - * @type {!GeoJSONCRSCode|!GeoJSONCRSName|!GeoJSONLink} * TODO: remove GeoJSONCRSCode when http://jira.codehaus.org/browse/GEOS-5996 * is fixed and widely deployed. + * @type {!GeoJSONCRSCode|!GeoJSONCRSName|!GeoJSONLink} */ GeoJSONCRS.prototype.properties; @@ -60,9 +60,9 @@ var GeoJSONCRSName = function() {}; /** - * @type {string} * TODO: remove this when http://jira.codehaus.org/browse/GEOS-5996 is fixed * and widely deployed. + * @type {string} */ GeoJSONCRSName.prototype.code; From babc33fcb0d52cd694cbc2e3481b3c8d69a1dfd5 Mon Sep 17 00:00:00 2001 From: Bart van den Eijnden Date: Wed, 3 Dec 2014 13:28:39 +0100 Subject: [PATCH 14/29] Add getter functions for points and angle in ol.style.RegularShape --- src/ol/style/regularshapestyle.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/ol/style/regularshapestyle.js b/src/ol/style/regularshapestyle.js index bf50f3bad3..cde61ff429 100644 --- a/src/ol/style/regularshapestyle.js +++ b/src/ol/style/regularshapestyle.js @@ -151,6 +151,15 @@ ol.style.RegularShape.prototype.getAnchor = function() { }; +/** + * @return {number} Shape's rotation in radians. + * @api + */ +ol.style.RegularShape.prototype.getAngle = function() { + return this.angle_; +}; + + /** * @return {ol.style.Fill} Fill style. * @api @@ -218,6 +227,15 @@ ol.style.RegularShape.prototype.getHitDetectionOrigin = function() { }; +/** + * @return {number} Number of points for stars and regular polygons. + * @api + */ +ol.style.RegularShape.prototype.getPoints = function() { + return this.points_; +}; + + /** * @return {number} Radius. * @api From a1c6662812684c6be5289b17eac2972cd01be67a Mon Sep 17 00:00:00 2001 From: Bart van den Eijnden Date: Mon, 15 Dec 2014 20:28:13 +0100 Subject: [PATCH 15/29] Do not quote featureNS and featureType in options --- src/ol/format/gml/gmlbaseformat.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ol/format/gml/gmlbaseformat.js b/src/ol/format/gml/gmlbaseformat.js index 6baa27b61f..415fe1c29c 100644 --- a/src/ol/format/gml/gmlbaseformat.js +++ b/src/ol/format/gml/gmlbaseformat.js @@ -544,8 +544,8 @@ ol.format.GMLBase.prototype.readFeatures; ol.format.GMLBase.prototype.readFeaturesFromNode = function(node, opt_options) { var options = { - 'featureType': this.featureType, - 'featureNS': this.featureNS + featureType: this.featureType, + featureNS: this.featureNS }; if (goog.isDef(opt_options)) { goog.object.extend(options, this.getReadOptions(node, opt_options)); From 2d12531105d3a2c8d0b5456d669b030e669ece1e Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Fri, 5 Dec 2014 13:33:44 +0100 Subject: [PATCH 16/29] Allow styles to override feature geometries With this change, application developers are able to define styles that render a different geometry than the feature geometry. This can e.g. be used to render an interior point of a polygon instead of the polygon, or to render symbols like arrows along lines. --- externs/olx.js | 12 +++++++- src/ol/render/vector.js | 4 +-- src/ol/style/style.js | 61 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 3 deletions(-) diff --git a/externs/olx.js b/externs/olx.js index 4370a7602f..fbbac87ba0 100644 --- a/externs/olx.js +++ b/externs/olx.js @@ -6075,7 +6075,8 @@ olx.style.TextOptions.prototype.stroke; /** - * @typedef {{fill: (ol.style.Fill|undefined), + * @typedef {{geometry: (undefined|string|ol.geom.Geometry|function(ol.Feature): ol.geom.Geometry), + * fill: (ol.style.Fill|undefined), * image: (ol.style.Image|undefined), * stroke: (ol.style.Stroke|undefined), * text: (ol.style.Text|undefined), @@ -6085,6 +6086,15 @@ olx.style.TextOptions.prototype.stroke; olx.style.StyleOptions; +/** + * Feature property or geometry or function returning a geometry to render + * for this style. + * @type {undefined|string|ol.geom.Geometry|function(ol.Feature): ol.geom.Geometry} + * @api + */ +olx.style.StyleOptions.prototype.geometry; + + /** * Fill style. * @type {ol.style.Fill|undefined} diff --git a/src/ol/render/vector.js b/src/ol/render/vector.js index c4481e958d..a1f3a3d832 100644 --- a/src/ol/render/vector.js +++ b/src/ol/render/vector.js @@ -123,8 +123,8 @@ ol.renderer.vector.renderFeature = function( */ ol.renderer.vector.renderFeature_ = function( replayGroup, feature, style, squaredTolerance) { - var geometry = feature.getGeometry(); - if (!goog.isDefAndNotNull(geometry)) { + var geometry = style.getGeometryFunction()(feature); + if (goog.isNull(geometry)) { return; } var simplifiedGeometry = geometry.getSimplifiedGeometry(squaredTolerance); diff --git a/src/ol/style/style.js b/src/ol/style/style.js index ad45b198c4..df2c619f85 100644 --- a/src/ol/style/style.js +++ b/src/ol/style/style.js @@ -1,7 +1,9 @@ goog.provide('ol.style.Style'); +goog.provide('ol.style.defaultGeometryFunction'); goog.require('goog.asserts'); goog.require('goog.functions'); +goog.require('ol.geom.Geometry'); goog.require('ol.geom.GeometryType'); goog.require('ol.style.Circle'); goog.require('ol.style.Fill'); @@ -24,6 +26,18 @@ ol.style.Style = function(opt_options) { var options = goog.isDef(opt_options) ? opt_options : {}; + /** + * Function that is called with a feature and returns the geometry to render + * for this style. + * @private + * @type {!function(ol.Feature): ol.geom.Geometry} + */ + this.geometryFunction_ = ol.style.defaultGeometryFunction; + + if (goog.isDef(options.geometry)) { + this.setGeometry(options.geometry); + } + /** * @private * @type {ol.style.Fill} @@ -57,6 +71,16 @@ ol.style.Style = function(opt_options) { }; +/** + * @return {!function(ol.Feature): ol.geom.Geometry} Function that is called + * with a feature and returns the geometry to render instead of the feature's + * geometry. + */ +ol.style.Style.prototype.getGeometryFunction = function() { + return this.geometryFunction_; +}; + + /** * @return {ol.style.Fill} Fill style. * @api @@ -102,6 +126,32 @@ ol.style.Style.prototype.getZIndex = function() { }; +/** + * Set a geometry that is rendered instead of the feature's geometry. + * + * @param {string|ol.geom.Geometry|function(ol.Feature): ol.geom.Geometry} geometry + * Feature property or geometry or function returning a geometry to render + * for this style. + * @api + */ +ol.style.Style.prototype.setGeometry = function(geometry) { + if (goog.isFunction(geometry)) { + this.geometryFunction_ = geometry; + } else if (goog.isString(geometry)) { + this.geometryFunction_ = function(feature) { + return feature.get(geometry); + }; + } else if (goog.isDef(geometry)) { + goog.asserts.assertInstanceof(geometry, ol.geom.Geometry); + this.geometryFunction_ = function() { + return geometry; + }; + } else { + this.geometryFunction_ = ol.style.defaultGeometryFunction; + } +}; + + /** * Set the zIndex. * @@ -264,3 +314,14 @@ ol.style.createDefaultEditingStyles = function() { return styles; }; + + +/** + * @param {ol.Feature} feature Feature to get the geometry for. + * @return {ol.geom.Geometry} Geometry to render. + */ +ol.style.defaultGeometryFunction = function(feature) { + goog.asserts.assert(!goog.isNull(feature)); + var geometry = feature.getGeometry(); + return goog.isDef(geometry) ? geometry : null; +}; From 8d9acb8f4825ab5b8bcb5f9c2f8e645e68e324cd Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Tue, 9 Dec 2014 20:07:53 +0100 Subject: [PATCH 17/29] Add an example showing the use of ol.style.Style#geometry --- examples/earthquake-clusters.html | 75 +++++++++++++++ examples/earthquake-clusters.js | 155 ++++++++++++++++++++++++++++++ 2 files changed, 230 insertions(+) create mode 100644 examples/earthquake-clusters.html create mode 100644 examples/earthquake-clusters.js diff --git a/examples/earthquake-clusters.html b/examples/earthquake-clusters.html new file mode 100644 index 0000000000..d3f630e066 --- /dev/null +++ b/examples/earthquake-clusters.html @@ -0,0 +1,75 @@ + + + + + + + + + + + Earthquake Clusters + + + + + + +
+ +
+
+
+
+
+ +
+ +
+

Earthquake Clusters

+

Demonstrates the use of style geometries to render source features of a cluster.

+
+

+ This example parses a KML file and renders the features as clusters on a vector layer. The styling in this example is quite involved. Single earthquake locations (rendered as stars) have a size relative to their magnitude. Clusters have an opacity relative to the number of features in the cluster, and a size that represents the extent of the features that make up the cluster. When clicking or hovering on a cluster, the individual features that make up the cluster will be shown. +

+

To achieve this, we make heavy use of style functions and ol.style.Style#geometry. See the earthquake-clusters.js source to see how this is done.

+
+
KML, vector, style, geometry, cluster
+
+
+ +
+ + + + + + + + diff --git a/examples/earthquake-clusters.js b/examples/earthquake-clusters.js new file mode 100644 index 0000000000..862963d5cc --- /dev/null +++ b/examples/earthquake-clusters.js @@ -0,0 +1,155 @@ +goog.require('ol.Map'); +goog.require('ol.View'); +goog.require('ol.extent'); +goog.require('ol.interaction'); +goog.require('ol.interaction.Select'); +goog.require('ol.layer.Tile'); +goog.require('ol.layer.Vector'); +goog.require('ol.source.Cluster'); +goog.require('ol.source.KML'); +goog.require('ol.source.Stamen'); +goog.require('ol.style.Circle'); +goog.require('ol.style.Fill'); +goog.require('ol.style.RegularShape'); +goog.require('ol.style.Stroke'); +goog.require('ol.style.Style'); +goog.require('ol.style.Text'); + + +var earthquakeFill = new ol.style.Fill({ + color: 'rgba(255, 153, 0, 0.8)' +}); +var earthquakeStroke = new ol.style.Stroke({ + color: 'rgba(255, 204, 0, 0.2)', + width: 1 +}); +var textFill = new ol.style.Fill({ + color: '#fff' +}); +var textStroke = new ol.style.Stroke({ + color: 'rgba(0, 0, 0, 0.6)', + width: 3 +}); +var invisibleFill = new ol.style.Fill({ + color: 'rgba(255, 255, 255, 0.01)' +}); + +function createEarthquakeStyle(feature) { + // 2012_Earthquakes_Mag5.kml stores the magnitude of each earthquake in a + // standards-violating tag in each Placemark. We extract it + // from the Placemark's name instead. + var name = feature.get('name'); + var magnitude = parseFloat(name.substr(2)); + var radius = 5 + 20 * (magnitude - 5); + + return new ol.style.Style({ + geometry: feature.getGeometry(), + image: new ol.style.RegularShape({ + radius1: radius, + radius2: 3, + points: 5, + angle: Math.PI, + fill: earthquakeFill, + stroke: earthquakeStroke + }) + }); +} + +var maxFeatureCount; +function calculateClusterInfo(resolution) { + maxFeatureCount = 0; + var features = vector.getSource().getFeatures(); + var feature, radius; + for (var i = features.length - 1; i >= 0; --i) { + feature = features[i]; + var originalFeatures = feature.get('features'); + var extent = ol.extent.createEmpty(); + for (var j = 0, jj = originalFeatures.length; j < jj; ++j) { + ol.extent.extendCoordinate(extent, + originalFeatures[j].getGeometry().getCoordinates()); + } + maxFeatureCount = Math.max(maxFeatureCount, jj); + radius = 0.25 * (ol.extent.getWidth(extent) + ol.extent.getHeight(extent)) / + resolution; + feature.set('radius', radius); + } +} + +var currentResolution; +function styleFunction(feature, resolution) { + if (resolution != currentResolution) { + calculateClusterInfo(resolution); + currentResolution = resolution; + } + var style; + var size = feature.get('features').length; + if (size > 1) { + style = [new ol.style.Style({ + image: new ol.style.Circle({ + radius: feature.get('radius'), + fill: new ol.style.Fill({ + color: [255, 153, 0, Math.min(0.8, 0.4 + (size / maxFeatureCount))] + }) + }), + text: new ol.style.Text({ + text: size.toString(), + fill: textFill, + stroke: textStroke + }) + })]; + } else { + var originalFeature = feature.get('features')[0]; + style = [createEarthquakeStyle(originalFeature)]; + } + return style; +} + +function selectStyleFunction(feature, resolution) { + var styles = [new ol.style.Style({ + image: new ol.style.Circle({ + radius: feature.get('radius'), + fill: invisibleFill + }) + })]; + var originalFeatures = feature.get('features'); + var originalFeature; + for (var i = originalFeatures.length - 1; i >= 0; --i) { + originalFeature = originalFeatures[i]; + styles.push(createEarthquakeStyle(originalFeature)); + } + return styles; +} + +var vector = new ol.layer.Vector({ + source: new ol.source.Cluster({ + distance: 40, + source: new ol.source.KML({ + extractStyles: false, + projection: 'EPSG:3857', + url: 'data/kml/2012_Earthquakes_Mag5.kml' + }) + }), + style: styleFunction +}); + +var raster = new ol.layer.Tile({ + source: new ol.source.Stamen({ + layer: 'toner' + }) +}); + +var map = new ol.Map({ + layers: [raster, vector], + interactions: ol.interaction.defaults().extend([new ol.interaction.Select({ + condition: function(evt) { + return evt.originalEvent.type == 'mousemove' || + evt.type == 'singleclick'; + }, + style: selectStyleFunction + })]), + target: 'map', + view: new ol.View({ + center: [0, 0], + zoom: 2 + }) +}); From 49f9690786e7b5c118d89f547d0e7b774b77d477 Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Wed, 10 Dec 2014 10:43:59 +0100 Subject: [PATCH 18/29] Add tests for setGeometry --- test/spec/ol/style.test.js | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/test/spec/ol/style.test.js b/test/spec/ol/style.test.js index 8c64cb0497..7e4d712e4b 100644 --- a/test/spec/ol/style.test.js +++ b/test/spec/ol/style.test.js @@ -11,6 +11,35 @@ describe('ol.style.Style', function() { expect(style.getZIndex()).to.be(0.7); }); }); + + describe('#setGeometry', function() { + var style = new ol.style.Style(); + + it('creates a geometry function from a string', function() { + var feature = new ol.Feature(); + feature.set('myGeom', new ol.geom.Point([0, 0])); + style.setGeometry('myGeom'); + expect(style.getGeometryFunction()(feature)) + .to.eql(feature.get('myGeom')); + }); + + it('creates a geometry function from a geometry', function() { + var geom = new ol.geom.Point([0, 0]); + style.setGeometry(geom); + expect(style.getGeometryFunction()()) + .to.eql(geom); + }); + + it('returns the configured geometry function', function() { + var geom = new ol.geom.Point([0, 0]); + style.setGeometry(function() { + return geom; + }); + expect(style.getGeometryFunction()()) + .to.eql(geom); + }); + }); + }); describe('ol.style.createStyleFunction()', function() { @@ -42,4 +71,6 @@ describe('ol.style.createStyleFunction()', function() { }); +goog.require('ol.Feature'); +goog.require('ol.geom.Point'); goog.require('ol.style.Style'); From 6478454a937f0efe1d433f37909d14ffb86f7b30 Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Mon, 15 Dec 2014 23:22:26 +0100 Subject: [PATCH 19/29] Use getGeometryFunction() in immediate API --- src/ol/render/canvas/canvasimmediate.js | 4 ++-- src/ol/render/webgl/webglimmediate.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ol/render/canvas/canvasimmediate.js b/src/ol/render/canvas/canvasimmediate.js index 15bcef6896..2e19342f64 100644 --- a/src/ol/render/canvas/canvasimmediate.js +++ b/src/ol/render/canvas/canvasimmediate.js @@ -477,8 +477,8 @@ ol.render.canvas.Immediate.prototype.drawCircleGeometry = * @api */ ol.render.canvas.Immediate.prototype.drawFeature = function(feature, style) { - var geometry = feature.getGeometry(); - if (!goog.isDefAndNotNull(geometry) || + var geometry = style.getGeometryFunction()(feature); + if (goog.isNull(geometry) || !ol.extent.intersects(this.extent_, geometry.getExtent())) { return; } diff --git a/src/ol/render/webgl/webglimmediate.js b/src/ol/render/webgl/webglimmediate.js index 5095504b7a..2a388b37fa 100644 --- a/src/ol/render/webgl/webglimmediate.js +++ b/src/ol/render/webgl/webglimmediate.js @@ -118,8 +118,8 @@ ol.render.webgl.Immediate.prototype.drawCircleGeometry = * @api */ ol.render.webgl.Immediate.prototype.drawFeature = function(feature, style) { - var geometry = feature.getGeometry(); - if (!goog.isDefAndNotNull(geometry) || + var geometry = style.getGeometryFunction()(feature); + if (goog.isNull(geometry) || !ol.extent.intersects(this.extent_, geometry.getExtent())) { return; } From af30b88413b0c11b54fee54e53446bace3216cbc Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Tue, 16 Dec 2014 01:12:08 +0100 Subject: [PATCH 20/29] Allow geometryFunction to return undefined --- externs/olx.js | 4 ++-- src/ol/render/canvas/canvasimmediate.js | 2 +- src/ol/render/vector.js | 2 +- src/ol/render/webgl/webglimmediate.js | 2 +- src/ol/style/style.js | 15 +++++++-------- 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/externs/olx.js b/externs/olx.js index fbbac87ba0..f80a1c0467 100644 --- a/externs/olx.js +++ b/externs/olx.js @@ -6075,7 +6075,7 @@ olx.style.TextOptions.prototype.stroke; /** - * @typedef {{geometry: (undefined|string|ol.geom.Geometry|function(ol.Feature): ol.geom.Geometry), + * @typedef {{geometry: (undefined|string|ol.geom.Geometry|function(ol.Feature): (ol.geom.Geometry|undefined)), * fill: (ol.style.Fill|undefined), * image: (ol.style.Image|undefined), * stroke: (ol.style.Stroke|undefined), @@ -6089,7 +6089,7 @@ olx.style.StyleOptions; /** * Feature property or geometry or function returning a geometry to render * for this style. - * @type {undefined|string|ol.geom.Geometry|function(ol.Feature): ol.geom.Geometry} + * @type {undefined|string|ol.geom.Geometry|function(ol.Feature): (ol.geom.Geometry|undefined)} * @api */ olx.style.StyleOptions.prototype.geometry; diff --git a/src/ol/render/canvas/canvasimmediate.js b/src/ol/render/canvas/canvasimmediate.js index 2e19342f64..efaaac5893 100644 --- a/src/ol/render/canvas/canvasimmediate.js +++ b/src/ol/render/canvas/canvasimmediate.js @@ -478,7 +478,7 @@ ol.render.canvas.Immediate.prototype.drawCircleGeometry = */ ol.render.canvas.Immediate.prototype.drawFeature = function(feature, style) { var geometry = style.getGeometryFunction()(feature); - if (goog.isNull(geometry) || + if (!goog.isDefAndNotNull(geometry) || !ol.extent.intersects(this.extent_, geometry.getExtent())) { return; } diff --git a/src/ol/render/vector.js b/src/ol/render/vector.js index a1f3a3d832..e02c7ada18 100644 --- a/src/ol/render/vector.js +++ b/src/ol/render/vector.js @@ -124,7 +124,7 @@ ol.renderer.vector.renderFeature = function( ol.renderer.vector.renderFeature_ = function( replayGroup, feature, style, squaredTolerance) { var geometry = style.getGeometryFunction()(feature); - if (goog.isNull(geometry)) { + if (!goog.isDefAndNotNull(geometry)) { return; } var simplifiedGeometry = geometry.getSimplifiedGeometry(squaredTolerance); diff --git a/src/ol/render/webgl/webglimmediate.js b/src/ol/render/webgl/webglimmediate.js index 2a388b37fa..4c07223ade 100644 --- a/src/ol/render/webgl/webglimmediate.js +++ b/src/ol/render/webgl/webglimmediate.js @@ -119,7 +119,7 @@ ol.render.webgl.Immediate.prototype.drawCircleGeometry = */ ol.render.webgl.Immediate.prototype.drawFeature = function(feature, style) { var geometry = style.getGeometryFunction()(feature); - if (goog.isNull(geometry) || + if (!goog.isDefAndNotNull(geometry) || !ol.extent.intersects(this.extent_, geometry.getExtent())) { return; } diff --git a/src/ol/style/style.js b/src/ol/style/style.js index df2c619f85..6b1f33f6db 100644 --- a/src/ol/style/style.js +++ b/src/ol/style/style.js @@ -30,7 +30,7 @@ ol.style.Style = function(opt_options) { * Function that is called with a feature and returns the geometry to render * for this style. * @private - * @type {!function(ol.Feature): ol.geom.Geometry} + * @type {!function(ol.Feature): (ol.geom.Geometry|undefined)} */ this.geometryFunction_ = ol.style.defaultGeometryFunction; @@ -72,9 +72,9 @@ ol.style.Style = function(opt_options) { /** - * @return {!function(ol.Feature): ol.geom.Geometry} Function that is called - * with a feature and returns the geometry to render instead of the feature's - * geometry. + * @return {!function(ol.Feature): (ol.geom.Geometry|undefined)} Function that + * is called with a feature and returns the geometry to render instead of the + * feature's geometry. */ ol.style.Style.prototype.getGeometryFunction = function() { return this.geometryFunction_; @@ -129,7 +129,7 @@ ol.style.Style.prototype.getZIndex = function() { /** * Set a geometry that is rendered instead of the feature's geometry. * - * @param {string|ol.geom.Geometry|function(ol.Feature): ol.geom.Geometry} geometry + * @param {string|ol.geom.Geometry|function(ol.Feature): (ol.geom.Geometry|undefined)} geometry * Feature property or geometry or function returning a geometry to render * for this style. * @api @@ -318,10 +318,9 @@ ol.style.createDefaultEditingStyles = function() { /** * @param {ol.Feature} feature Feature to get the geometry for. - * @return {ol.geom.Geometry} Geometry to render. + * @return {ol.geom.Geometry|undefined} Geometry to render. */ ol.style.defaultGeometryFunction = function(feature) { goog.asserts.assert(!goog.isNull(feature)); - var geometry = feature.getGeometry(); - return goog.isDef(geometry) ? geometry : null; + return feature.getGeometry(); }; From d3365fb3a55341a4f961abace78d6c25727d7845 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Tue, 16 Dec 2014 09:43:34 +0100 Subject: [PATCH 21/29] Remove // NOCOMPILE from vector-wfs --- examples/vector-wfs.js | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/vector-wfs.js b/examples/vector-wfs.js index 96f3d7e318..30c2b9d2ef 100644 --- a/examples/vector-wfs.js +++ b/examples/vector-wfs.js @@ -1,4 +1,3 @@ -// NOCOMPILE goog.require('ol.Map'); goog.require('ol.View'); goog.require('ol.format.GeoJSON'); From 1bf4ddac6dcf5ad9bc9cb0077bc45c08421625c9 Mon Sep 17 00:00:00 2001 From: Bart van den Eijnden Date: Tue, 16 Dec 2014 10:22:37 +0100 Subject: [PATCH 22/29] Add a testcase for parsing GML feature with only boundedBy --- test/spec/ol/format/gml/only-boundedby.xml | 41 ++++++++++++++++++++++ test/spec/ol/format/gmlformat.test.js | 21 +++++++++++ 2 files changed, 62 insertions(+) create mode 100644 test/spec/ol/format/gml/only-boundedby.xml diff --git a/test/spec/ol/format/gml/only-boundedby.xml b/test/spec/ol/format/gml/only-boundedby.xml new file mode 100644 index 0000000000..1459a13a88 --- /dev/null +++ b/test/spec/ol/format/gml/only-boundedby.xml @@ -0,0 +1,41 @@ + + + + + + + 36.986 -91.516 + 42.509 -87.507 + + + Illinois + 17 + E N Cen + IL + 143986.61 + 1993.335 + 1.143E7 + 2924880.0 + 4202240.0 + 5552233.0 + 5878369.0 + 4199206.0 + 3741715.0 + 652603.0 + 538071.0 + 5417967.0 + 385040.0 + 1360159.0 + 828906.0 + 0.486 + 0.514 + 1747776.0 + + + diff --git a/test/spec/ol/format/gmlformat.test.js b/test/spec/ol/format/gmlformat.test.js index 93630d5010..2ec050b3cb 100644 --- a/test/spec/ol/format/gmlformat.test.js +++ b/test/spec/ol/format/gmlformat.test.js @@ -1066,6 +1066,27 @@ describe('ol.format.GML3', function() { }); + describe('when parsing only a boundedBy element and no geometry', function() { + + var features; + before(function(done) { + afterLoadText('spec/ol/format/gml/only-boundedby.xml', function(xml) { + try { + features = new ol.format.GML().readFeatures(xml); + } catch (e) { + done(e); + } + done(); + }); + }); + + it('creates a feature without a geometry', function() { + var feature = features[0]; + expect(feature.getGeometry()).to.be(undefined); + }); + + }); + }); From 2ea685e18f79704fa6f9fdd204f1a79dd491c2a4 Mon Sep 17 00:00:00 2001 From: Frederic Junod Date: Wed, 17 Dec 2014 10:21:53 +0100 Subject: [PATCH 23/29] Add 'opt_' prefix to optional param --- src/ol/tilecoord.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/ol/tilecoord.js b/src/ol/tilecoord.js index 4464b7e4e4..25fcaeeba2 100644 --- a/src/ol/tilecoord.js +++ b/src/ol/tilecoord.js @@ -71,15 +71,15 @@ ol.tilecoord.createFromString = function(str) { * @param {number} z Z. * @param {number} x X. * @param {number} y Y. - * @param {ol.TileCoord|undefined} tileCoord Tile coordinate. + * @param {ol.TileCoord=} opt_tileCoord Tile coordinate. * @return {ol.TileCoord} Tile coordinate. */ -ol.tilecoord.createOrUpdate = function(z, x, y, tileCoord) { - if (goog.isDef(tileCoord)) { - tileCoord[0] = z; - tileCoord[1] = x; - tileCoord[2] = y; - return tileCoord; +ol.tilecoord.createOrUpdate = function(z, x, y, opt_tileCoord) { + if (goog.isDef(opt_tileCoord)) { + opt_tileCoord[0] = z; + opt_tileCoord[1] = x; + opt_tileCoord[2] = y; + return opt_tileCoord; } else { return [z, x, y]; } From 7c6ccca57289acedfe579d2bc32998e5752f0815 Mon Sep 17 00:00:00 2001 From: Frederic Junod Date: Wed, 17 Dec 2014 10:35:07 +0100 Subject: [PATCH 24/29] Reuse previousExtent_ local variable --- src/ol/map.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/ol/map.js b/src/ol/map.js index 4ee6642c5f..ba42b80d8b 100644 --- a/src/ol/map.js +++ b/src/ol/map.js @@ -215,7 +215,7 @@ ol.Map = function(options) { * @private * @type {ol.Extent} */ - this.previousExtent_ = null; + this.previousExtent_ = ol.extent.createEmpty(); /** * @private @@ -1261,13 +1261,12 @@ ol.Map.prototype.renderFrame_ = function(time) { var idle = this.preRenderFunctions_.length === 0 && !frameState.viewHints[ol.ViewHint.ANIMATING] && !frameState.viewHints[ol.ViewHint.INTERACTING] && - (!this.previousExtent_ || - !ol.extent.equals(frameState.extent, this.previousExtent_)); + !ol.extent.equals(frameState.extent, this.previousExtent_); if (idle) { this.dispatchEvent( new ol.MapEvent(ol.MapEventType.MOVEEND, this, frameState)); - this.previousExtent_ = ol.extent.clone(frameState.extent); + ol.extent.clone(frameState.extent, this.previousExtent_); } } From 19015d2ca9bc3749d2e9a7e16413262a3f30cb2e Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Thu, 18 Dec 2014 10:07:57 +0100 Subject: [PATCH 25/29] Create typedef --- externs/olx.js | 8 ++++---- src/ol/style/style.js | 24 ++++++++++++++++++------ 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/externs/olx.js b/externs/olx.js index f80a1c0467..83c1e2f418 100644 --- a/externs/olx.js +++ b/externs/olx.js @@ -6075,7 +6075,7 @@ olx.style.TextOptions.prototype.stroke; /** - * @typedef {{geometry: (undefined|string|ol.geom.Geometry|function(ol.Feature): (ol.geom.Geometry|undefined)), + * @typedef {{geometry: (undefined|string|ol.geom.Geometry|ol.style.GeometryFunction), * fill: (ol.style.Fill|undefined), * image: (ol.style.Image|undefined), * stroke: (ol.style.Stroke|undefined), @@ -6087,9 +6087,9 @@ olx.style.StyleOptions; /** - * Feature property or geometry or function returning a geometry to render - * for this style. - * @type {undefined|string|ol.geom.Geometry|function(ol.Feature): (ol.geom.Geometry|undefined)} + * Feature property or geometry or function returning a geometry to render for + * this style. + * @type {undefined|string|ol.geom.Geometry|ol.style.GeometryFunction} * @api */ olx.style.StyleOptions.prototype.geometry; diff --git a/src/ol/style/style.js b/src/ol/style/style.js index 6b1f33f6db..8ea5cdc272 100644 --- a/src/ol/style/style.js +++ b/src/ol/style/style.js @@ -27,10 +27,8 @@ ol.style.Style = function(opt_options) { var options = goog.isDef(opt_options) ? opt_options : {}; /** - * Function that is called with a feature and returns the geometry to render - * for this style. * @private - * @type {!function(ol.Feature): (ol.geom.Geometry|undefined)} + * @type {!ol.style.GeometryFunction} */ this.geometryFunction_ = ol.style.defaultGeometryFunction; @@ -72,7 +70,7 @@ ol.style.Style = function(opt_options) { /** - * @return {!function(ol.Feature): (ol.geom.Geometry|undefined)} Function that + * @return {!ol.style.GeometryFunction} Function that * is called with a feature and returns the geometry to render instead of the * feature's geometry. */ @@ -129,7 +127,7 @@ ol.style.Style.prototype.getZIndex = function() { /** * Set a geometry that is rendered instead of the feature's geometry. * - * @param {string|ol.geom.Geometry|function(ol.Feature): (ol.geom.Geometry|undefined)} geometry + * @param {string|ol.geom.Geometry|ol.style.GeometryFunction} geometry * Feature property or geometry or function returning a geometry to render * for this style. * @api @@ -139,7 +137,10 @@ ol.style.Style.prototype.setGeometry = function(geometry) { this.geometryFunction_ = geometry; } else if (goog.isString(geometry)) { this.geometryFunction_ = function(feature) { - return feature.get(geometry); + var result = feature.get(geometry); + goog.asserts.assert(!goog.isDefAndNotNull(result) || + goog.asserts.assertInstanceof(result, ol.geom.Geometry)); + return result; }; } else if (goog.isDef(geometry)) { goog.asserts.assertInstanceof(geometry, ol.geom.Geometry); @@ -317,6 +318,17 @@ ol.style.createDefaultEditingStyles = function() { /** + * A function that takes an `{ol.Feature}` as argument and returns a geometry + * that will be rendered and styled for the feature. + * + * @typedef {function(ol.Feature): (ol.geom.Geometry|undefined)} + * @api + */ +ol.style.GeometryFunction; + + +/** + * Function that is called with a feature and returns its default geometry. * @param {ol.Feature} feature Feature to get the geometry for. * @return {ol.geom.Geometry|undefined} Geometry to render. */ From 2bf191b5e3804b5362ee775ee04cc79807c0692f Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Thu, 18 Dec 2014 10:08:35 +0100 Subject: [PATCH 26/29] Assert that feature.get('foo') returns a geometry --- src/ol/style/style.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ol/style/style.js b/src/ol/style/style.js index 8ea5cdc272..5aa4421765 100644 --- a/src/ol/style/style.js +++ b/src/ol/style/style.js @@ -138,8 +138,9 @@ ol.style.Style.prototype.setGeometry = function(geometry) { } else if (goog.isString(geometry)) { this.geometryFunction_ = function(feature) { var result = feature.get(geometry); - goog.asserts.assert(!goog.isDefAndNotNull(result) || - goog.asserts.assertInstanceof(result, ol.geom.Geometry)); + if (goog.isDefAndNotNull(result)) { + goog.asserts.assertInstanceof(result, ol.geom.Geometry); + } return result; }; } else if (goog.isDef(geometry)) { From 784701641d7614da430cb08e345155e58b68618f Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Thu, 18 Dec 2014 10:28:21 +0100 Subject: [PATCH 27/29] Add a getGeometry method --- src/ol/style/style.js | 32 +++++++++++++++++++++++++------- test/spec/ol/style.test.js | 18 ++++++++++++++++++ 2 files changed, 43 insertions(+), 7 deletions(-) diff --git a/src/ol/style/style.js b/src/ol/style/style.js index 5aa4421765..e010186eac 100644 --- a/src/ol/style/style.js +++ b/src/ol/style/style.js @@ -26,6 +26,12 @@ ol.style.Style = function(opt_options) { var options = goog.isDef(opt_options) ? opt_options : {}; + /** + * @private + * @type {string|ol.geom.Geometry|ol.style.GeometryFunction} + */ + this.geometry_ = null; + /** * @private * @type {!ol.style.GeometryFunction} @@ -70,9 +76,20 @@ ol.style.Style = function(opt_options) { /** - * @return {!ol.style.GeometryFunction} Function that - * is called with a feature and returns the geometry to render instead of the - * feature's geometry. + * @return {string|ol.geom.Geometry|ol.style.GeometryFunction} + * Feature property or geometry or function that returns the geometry that will + * be rendered with this style. + * @api + */ +ol.style.Style.prototype.getGeometry = function() { + return this.geometry_; +}; + + +/** + * @return {!ol.style.GeometryFunction} Function that is called with a feature + * and returns the geometry to render instead of the feature's geometry. + * @api */ ol.style.Style.prototype.getGeometryFunction = function() { return this.geometryFunction_; @@ -143,14 +160,15 @@ ol.style.Style.prototype.setGeometry = function(geometry) { } return result; }; + } else if (goog.isNull(geometry)) { + this.geometryFunction_ = ol.style.defaultGeometryFunction; } else if (goog.isDef(geometry)) { goog.asserts.assertInstanceof(geometry, ol.geom.Geometry); this.geometryFunction_ = function() { return geometry; }; - } else { - this.geometryFunction_ = ol.style.defaultGeometryFunction; } + this.geometry_ = geometry; }; @@ -319,8 +337,8 @@ ol.style.createDefaultEditingStyles = function() { /** - * A function that takes an `{ol.Feature}` as argument and returns a geometry - * that will be rendered and styled for the feature. + * A function that takes an {@link ol.Feature} as argument and returns an + * {@link ol.geom.Geometry} that will be rendered and styled for the feature. * * @typedef {function(ol.Feature): (ol.geom.Geometry|undefined)} * @api diff --git a/test/spec/ol/style.test.js b/test/spec/ol/style.test.js index 7e4d712e4b..2a42d4ac02 100644 --- a/test/spec/ol/style.test.js +++ b/test/spec/ol/style.test.js @@ -40,6 +40,24 @@ describe('ol.style.Style', function() { }); }); + describe('#getGeometry', function() { + + it('returns whatever was passed to setGeometry', function() { + var style = new ol.style.Style(); + style.setGeometry('foo'); + expect(style.getGeometry()).to.eql('foo'); + var geom = new ol.geom.Point([1, 2]); + style.setGeometry(geom); + expect(style.getGeometry()).to.eql(geom); + var fn = function() { return geom; }; + style.setGeometry(fn); + expect(style.getGeometry()).to.eql(fn); + style.setGeometry(null); + expect(style.getGeometry()).to.eql(null); + }); + + }); + }); describe('ol.style.createStyleFunction()', function() { From 5ca6b5dd81032a98f041491e4286235d881f062e Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Thu, 18 Dec 2014 11:02:41 +0100 Subject: [PATCH 28/29] Use an API function to extend the extent --- examples/earthquake-clusters.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/earthquake-clusters.js b/examples/earthquake-clusters.js index 862963d5cc..0850960250 100644 --- a/examples/earthquake-clusters.js +++ b/examples/earthquake-clusters.js @@ -65,8 +65,7 @@ function calculateClusterInfo(resolution) { var originalFeatures = feature.get('features'); var extent = ol.extent.createEmpty(); for (var j = 0, jj = originalFeatures.length; j < jj; ++j) { - ol.extent.extendCoordinate(extent, - originalFeatures[j].getGeometry().getCoordinates()); + ol.extent.extend(extent, originalFeatures[j].getGeometry().getExtent()); } maxFeatureCount = Math.max(maxFeatureCount, jj); radius = 0.25 * (ol.extent.getWidth(extent) + ol.extent.getHeight(extent)) / From 440a85c6f4a83d949d58f92bcab1b043d964259d Mon Sep 17 00:00:00 2001 From: Frederic Junod Date: Thu, 18 Dec 2014 11:18:35 +0100 Subject: [PATCH 29/29] Update closure-library version fixes #3034 --- closure-util.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/closure-util.json b/closure-util.json index 88e5b109ac..153e451bb2 100644 --- a/closure-util.json +++ b/closure-util.json @@ -1,3 +1,3 @@ { - "library_url": "https://github.com/google/closure-library/archive/5b7a6ce1974c230dc169cb93ed5f9689e880aa50.zip" + "library_url": "https://github.com/google/closure-library/archive/ad5e66c1e7d7829b0d77feae49aaf5f011265715.zip" }