# HG changeset patch # User cin # Date 1503326820 -10800 # Node ID f0035923ff3e23ce7582cf56a3bbae9e530896f2 # Parent 9c0943c68a90bfb9f93dbe8d02eef009e17322b6 добавлена библиотека для работы с openlayers 3+ diff -r 9c0943c68a90 -r f0035923ff3e src/djol/BaseLayer.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/djol/BaseLayer.js Mon Aug 21 17:47:00 2017 +0300 @@ -0,0 +1,44 @@ +define([ + "implab/text/template-compile", + "dojo/_base/declare", + "dojo/_base/lang", + "ol"], + function (compile, declare, lang, ol) { + return declare([ol.layer.Layer], { + + name: null, + + displayName: null, + + identifyResultTemplate: null, + + searchResultTemplate: null, + + constructor: function () { + lang.mixin(this, arguments[0]); + var identifyCompiledTemplate = null, searchCompiledTemplate = null; + if (this.identifyResultTemplate) { + identifyCompiledTemplate = compile(this.identifyResultTemplate); + } + if (this.searchResultTemplate) { + searchCompiledTemplate = compile(this.searchResultTemplate); + } + }, + + /** Возвращает массив строк, каждая строка - результат поиска приведенный к шаблонному виду + @options {Object} + @str {String} поисковая строка + @bbox {Object} bound box, в рамках которого осуществлять поиск + */ + getSearchResult: function (options) { + console.warn("Метод необходимо переопределить для для слоя конкретного типа!"); + }, + /** Возвращает массив строк, каждая строка - результат идентификации приведенный к шаблонному виду + @options {Object} + @coordinates {Array} массив описывающий координаты точки идентификации + */ + getItentifyResult: function (coordinates) { + console.warn("Метод необходимо переопределить для для слоя конкретного типа!"); + } + }); + }) \ No newline at end of file diff -r 9c0943c68a90 -r f0035923ff3e src/djol/ClearTool.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/djol/ClearTool.js Mon Aug 21 17:47:00 2017 +0300 @@ -0,0 +1,19 @@ +define (["dojo/_base/declare", "./_OneshotTool", "implab/safe"] , function(declare, _OneshotTool, safe) { + return declare([_OneshotTool], { + tools : null, + + constructor : function(opts) { + safe.mixin(this,opts, ["tools"]); + }, + + invoke : function() { + if (this.tools) { + this.log("Clear {0} tools", this.tools.length); + safe.each(this.tools, function(tool) { + if (tool.clear) + tool.clear(); + }); + } + } + }); +}); \ No newline at end of file diff -r 9c0943c68a90 -r f0035923ff3e src/djol/DeactivationTool.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/djol/DeactivationTool.js Mon Aug 21 17:47:00 2017 +0300 @@ -0,0 +1,14 @@ +define(["dojo/_base/declare", "./_ToolBase"],function(declare, _ToolBase) { + + // Инструмент, выключает текущий активный инструмент + // Данный инструмент ничго не делает, но при его активации будет + // деактивирован предыдущий инструмент + return declare([_ToolBase], { + + // данный инструмент не может быть активным, поэтому данный метод + // переопределяется и возвращает всегда false + onActivating : function() { + return false; + } + }); +}); \ No newline at end of file diff -r 9c0943c68a90 -r f0035923ff3e src/djol/DistanceMeasureTool.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/djol/DistanceMeasureTool.js Mon Aug 21 17:47:00 2017 +0300 @@ -0,0 +1,63 @@ +define([ + "dojo/_base/declare", + "implab/safe", + "./MeasureToolBase", + "implab/text/format", + "dojo/i18n!./format/nls/units", + "ol" ], + +function(declare, safe, MeasureToolBase, format, units, ol) { + return declare([ MeasureToolBase ], { + + isGeodesic : true, + + units : 'metric', + + constructor : function(opts) { + if (opts) + safe.mixin(this,opts,["isGeodesic", "units"]); + }, + + _createDraw : function(source) { + return new ol.interaction.Draw( + { + source : source, + type : "LineString", + style : this.drawStyle + }); + }, + + _formatTooltip : function(sketch, proj) { + var length = 0; + if (this.isGeodesic) { + var points = sketch.getGeometry().getCoordinates(); + var t = ol.proj.getTransform(proj, "EPSG:4326"); + for (var i = 0; i < points.length - 1; i++) { + length += this.wgs84Sphere.haversineDistance( + t(points[i]), + t(points[i + 1])); + } + } else { + length = sketch.getGeometry().getLength(); + } + + var mpu, unitName; + switch (this.units) { + case "nautical": + mpu = 1852; + unitName = units.nmiles; + break; + default: + mpu = 1000; + unitName = units.kilometers; + } + + if (length >= mpu) { + return format("{0:#.0#}{1}", length / mpu, unitName); + } else { + return format("{0:#0.0#}{1}", length, units.meters); + } + } + + }); +}); \ No newline at end of file diff -r 9c0943c68a90 -r f0035923ff3e src/djol/DynamicStyle.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/djol/DynamicStyle.js Mon Aug 21 17:47:00 2017 +0300 @@ -0,0 +1,119 @@ +define([ "./declare-style", "dojo/_base/declare", "ol", "implab/safe" ], + +function(declare, dojoDeclare, ol, safe) { + return declare([], { + _cache : null, + _getKey : null, + _getZoom : null, + + defaultStyle : null, + + style : null, + + styleFunction : null, + + filter : null, + + constructor : function(opts) { + if (opts) + dojoDeclare.safeMixin(this, opts); + + this._cache = {}; + + if (this.zoom) { + if (this.zoom instanceof Function) { + this._getZoom = this.zoom; + } else { + var levels = [], max = "max"; + for ( var p in this.zoom) { + if (safe.isNumber(this.zoom[p])) + levels.push({ + name : p, + zoom : Number(this.zoom[p]) + }); + else if (this.zoom[p] == "max") + max = p; + } + + levels.sort(function(x, y) { + return x.zoom - y.zoom; + }); + + this.zoomMax = max; + this.zoomLevels = levels; + + this._getZoom = function(z) { + for (var i = 0; i < levels.length; i++) { + if (z <= levels[i].zoom) + return levels[i].name; + } + return max; + }; + } + } else { + this._getZoom = function(z) { + return "max"; + }; + } + + if (this.key) { + if (this.key instanceof Function) { + this._getKey = this.key; + } else if (typeof this.key === "string") { + this._getKey = function(ft) { + return ft.get(this.key); + }; + } else { + this._getKey = function(ft, z) { + var k = this.key[z]; + if (k instanceof Function) + return k.call(this, ft, z); + else if (typeof k == "string") + return ft.get(k); + else + return this.defaultStyle; + }; + } + } else { + this._getKey = function() { + return this.defaultStyle; + }; + } + + if (this.style) { + if (this.style instanceof Function) { + this._style = this.style; + } else { + this._style = function(ft, res, key, zoom) { + var s = this.style[zoom]; + return s && (s instanceof Function) ? s.apply( + this, + arguments) : s; + }; + } + } + }, + + getFeatureStyle : function(ft, res) { + safe.argumentNotNull(ft, "ft"); + + if (this.filter && this.filter(ft) === false) + return null; + + var z = this._getZoom(res); + var k = this._getKey(ft, z); + + var cid = [ k, z ].join('-'); + + var style = this._cache[cid]; + if (!style) { + style = this._style ? this._style(ft, res, k, z) : null; + this._cache[cid] = style; + } + + + return safe.isNull(style) || style instanceof Array ? style : [ style ]; + } + + }); +}); \ No newline at end of file diff -r 9c0943c68a90 -r f0035923ff3e src/djol/IdentificationTool.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/djol/IdentificationTool.js Mon Aug 21 17:47:00 2017 +0300 @@ -0,0 +1,246 @@ +define([ + "dijit/layout/ContentPane", + "dojo/_base/declare", + "dojo/Deferred", + "dojo/dom-construct", + "dojo/dom-class", + "dojo/on", + "dojo/promise/all", + "dojo/when", + "implab/safe", + "ol", + "./listen", + "./IdentifyGroup", + "./_ToolBase", + "./PopupContainer" + ], + + function ( + ContentPane, + declare, + Deffered, + domConstruct, + domClass, + on, + promiseAll, + when, + safe, + ol, + listen, + IdentifyGroup, + _ToolBase, + PopupContainer) { + return declare([_ToolBase], { + /** + * массив обработчиков openLayers, которые необходимо удалить при + * деактивации + */ + _handlers: null, + /** + * widget карты + */ + _map: null, + /** + * openLayers map + */ + _olMap: null, + /** + * Массив overlays содержащих popupContainers + */ + _popupOverlays: null, + /** + * Массив popups контейнеров + */ + _popupContainers: null, + /** + * Режим работы инструмента идентификации + * + * @value {String} "single"||"multiple" + */ + mode: null, + /** + * Режимы + */ + appManager: null, + + constructor: function (options) { + safe.argumentNotNull(options, "options"); + safe.argumentNotNull(options.map, "options.map"); + safe.argumentNotNull(options.appManager, "options.appManager"); + + this._map = options.map; + this._olMap = options.map.olMap; + this._popupContainers = []; + this._popupOverlays = []; + this._handlers = []; + + this.appManager = options.appManager; + this.mode = options.mode || "single"; + }, + /** + */ + createPopupContent: function (groupWidgets) { + var contentWidget = new ContentPane(); + groupWidgets.forEach(function (groupWidget) { + if (groupWidget && !groupWidget.isEmpty()) { + contentWidget.addChild(groupWidget); + } + }); + return contentWidget; + }, + + /** + * Возвращает обещание на получение объекта с результатом идентификации + * по всем видимым режимам и информационным слоям @ options {Object} @ pixel + * {Object} - информация о точке идентификации @ coordinate {Array} - + * координаты точки иденификации + */ + getGroupsFromVisibleModules: function (options) { + var promises = []; + var modules = this.appManager.getVisibleModules(); + modules.forEach(function (module) { + promises.push.apply(promises, module + .getIdentifyResult(options)); + }); + + return promiseAll(promises).then( + function (results) { + console.log("promise all groups = ", results); + return results; + }); + }, + + identifyPosition: function (position) { + var me = this, i; + var popupContainer = null, + popupOverlay = null; + if (me.mode == "multiple") { + // TODO: создать popupContainer и popupOverlay + popupContainer = new PopupContainer({ + map: me._olMap + }); + on(popupContainer, "close", function () { + var index = me._popupContainers.indexOf(me); + me._popupContainers.splice(index, 1); + + }); + me._popupContainers.push(popupContainer); + + popupOverlay = new ol.Overlay({ + element: popupContainer.domNode, + autoPan: true, + autoPanAnimation: { + duration: 250 + } + }); + me._popupOverlays.push(popupOverlay); + me._olMap.addOverlay(popupOverlay); + + } else { + if (me._popupContainers.length > 0) { + // Берем первый + popupContainer = me._popupContainers[0]; + // Все остальные удалить + if (me._popupContainers.length > 1) { + for (i = 1; i < me._popupContainers.length; i++) { + me._popupContainers[i].destroyRecursive(); + } + me._popupContainers.splice( + 1, + me._popupContainers.length - 1); + } + } else { + // Создаем новый + popupContainer = new PopupContainer({ + map: me._olMap + }); + on(popupContainer, "close", function () { + var index = me._popupContainers.indexOf(me); + me._popupContainers.splice(index, 1); + + }); + me._popupContainers.push(popupContainer); + } + if (me._popupOverlays.length > 0) { + // Берем первый и помещаем в него popup + popupOverlay = me._popupOverlays[0]; + popupOverlay.setElement(popupContainer.domNode); + // Все остальные удалить + if (me._popupOverlays.length > 1) { + for (i = 1; i < me._popupOverlays.length; i++) { + me._olMap.removeOverlay(me._popupOverlays[i]); + } + me._popupOverlays.splice( + 1, + me._popupOverlays.length - 1) + } + } else { + // Создаем новый и помещаем в него popup + popupOverlay = new ol.Overlay({ + element: popupContainer.domNode, + autoPan: true, + autoPanAnimation: { + duration: 250 + } + }); + me._popupOverlays.push(popupOverlay); + me._olMap.addOverlay(popupOverlay); + } + } + + popupContainer.destroyDescendants(); + + popupOverlay.setPosition(position.coordinate); + + popupContainer.showOverlay(); + + when(me.getGroupsFromVisibleModules(position), function (data) { + var contentWidget = me.createPopupContent(data); + popupContainer.show(contentWidget, "only"); + popupContainer.hideOverlay(); + }); + }, + /** + * Скрыть все popups + */ + hideAllPopups: function () { + var me = this, i; + for (i = 0; i < this._popupContainers.length; i++) { + this._popupContainers[i].destroyRecursive(); + } + this._popupContainers.splice(0, this._popupContainers.length); + + for (i = 0; i < this._popupOverlays.length; i++) { + this._olMap.removeOverlay(this._popupOverlays[i]); + } + this._popupOverlays.splice(0, this._popupOverlays.length) + }, + + onActivating: function () { + var me = this; + // Обработчик для события "singleclick" по карте + var handler = listen(this._olMap, 'singleclick', function (evt) { + if (evt.originalEvent.ctrlKey) { + me.mode = "multiple"; + } else { + me.mode = "single"; + } + me.identifyPosition({ + pixel: evt.pixel, + coordinate: evt.coordinate + }); + }); + this._handlers.push(handler); + }, + + onDeactivating: function () { + var me = this; + me._handlers.forEach(function (handler) { + if (handler.remove) + handler.remove(); + + }); + this.hideAllPopups(); + }, + }) + }); \ No newline at end of file diff -r 9c0943c68a90 -r f0035923ff3e src/djol/IdentifyGroup.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/djol/IdentifyGroup.js Mon Aug 21 17:47:00 2017 +0300 @@ -0,0 +1,89 @@ +define( + [ + "implab/safe", + 'dijit/_WidgetBase', + 'dijit/_TemplatedMixin', + "dijit/_WidgetsInTemplateMixin", + "dijit/layout/_LayoutWidget", + "dijit/layout/ContentPane", + "dojo/_base/declare", + "dojo/dom-construct", + "dojo/on", + "ol3/IdentifyItem" ], + function( + safe, + _WidgetBase, + _TemplatedMixin, + _WidgetsInTemplateMixin, + _LayoutWidget, + ContentPane, + declare, + domConstruct, + on, + IdentifyItem) { + + return declare( + [ _LayoutWidget, _TemplatedMixin, _WidgetsInTemplateMixin ], + { + + /** + */ + _empty : true, + /** + */ + layerName : null, + /** + * Шаблон всего widget + */ + templateString : "
+ * {
+ * extent : ol3.Extent,
+ * }
+ *
+ */
+ query: function (q, options) {
+ var me = this;
+ var filter = this.queryEngine(q, options);
+
+ if (this.notify && !this.hasOwnProperty("_subscriptions")) {
+ me._subscriptions = [];
+
+ var sc = function (evt, handler) {
+ me._subscriptions.push(listen(me._source, evt, safe.delegate(me, handler)));
+ }
+
+ sc("addfeature", "_onAdd");
+ sc("changefeature", "_onUpdate");
+ sc("removefeature", "_onRemove");
+ }
+
+ var predicate, data, extent = filter.matches &&
+ filter.matches.extent;
+ // если это запрос с указанием области
+ if (extent) {
+ predicate = filter.matches.predicate;
+
+ data = this._source.getFeaturesInExtent(extent);
+
+ if (predicate)
+ data = array.filter(data, predicate);
+
+ if (filter.sort)
+ filter.sort(data);
+
+ if (filter.paginate)
+ data = filter.paginate(data);
+ } else {
+ // любой другой запрос
+ data = filter(this._source.getFeatures());
+ }
+
+ return new QueryResults(data);
+ },
+
+ put: function (obj, options) {
+ safe.argumentOfType(obj, ol.Feature, "obj");
+ if (!options)
+ options = {};
+
+ if (options.id)
+ obj.setId(options.id);
+
+ var id = obj.getId() || new UUID();
+
+ var prev = this.get(id);
+
+ if ('overwrite' in options) {
+ // overwrite=true указан, но перезаписывать нечего
+ if (!prev && options.overwrite)
+ throw new Error("The specified feature with id '" +
+ id + "' doesn't exist in the store");
+
+ // overwrite=false указан, но объект уже существует
+ if (prev && !options.overwrite)
+ throw new Error("The specified feature with id '" +
+ id + "' already exists in the store");
+ }
+
+ // ok
+ if (prev) {
+ var data = obj.getProperties();
+ prev.setProperties(data);
+ } else {
+ this._source.addFeature(obj);
+ }
+
+ return id;
+ },
+
+ add: function (obj, options) {
+ safe.argumentOfType(obj, ol.Feature, "obj");
+
+ if (!options)
+ options = {};
+
+ if (options.id)
+ obj.setId(options.id);
+
+ var id = obj.getId() || new UUID();
+
+ var prev = this.get(id);
+
+ if (prev)
+ throw new Error("The specified feature with id '" + id +
+ "' already exists in the store");
+
+ this._source.addFeature(obj);
+ },
+
+ remove: function (id) {
+ var me = this;
+
+ var ft = me.get(id);
+ if (ft)
+ me._source.removeFeature(ft);
+ },
+
+ getIdentity: function (obj) {
+ if (safe.isNull(obj))
+ return undefined;
+ if (!(obj instanceof ol.Feature))
+ throw new Error("A feature is expected");
+
+ return obj.getId();
+ },
+
+ _onAdd: function (ev) {
+ this.notify(ev.feature);
+ },
+
+ _onRemove: function (ev) {
+ var id = ev.feature.getId();
+ if (!safe.isNull(id))
+ this.notify(undefined, id);
+ },
+
+ _onUpdate: function (ev) {
+ var id = ev.feature.getId();
+ if (!safe.isNull(id))
+ this.notify(ev.feature, id);
+ },
+
+ dispose: function () {
+ var me = this;
+ if (me._subscriptions)
+ me._subscriptions.forEach(function (sc) {
+ sc.remove();
+ });
+
+ me._source = null;
+ me._subscriptions = null;
+ }
+ });
+ });
\ No newline at end of file
diff -r 9c0943c68a90 -r f0035923ff3e src/djol/VectorStoreQuery.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/djol/VectorStoreQuery.js Mon Aug 21 17:47:00 2017 +0300
@@ -0,0 +1,67 @@
+define([ "ol" ], function(ol) {
+
+ function buildFilter(filter) {
+ if (filter instanceof Function)
+ return filter;
+ if (filter) {
+ var match = function(str) {
+ return {
+ test : function(x) {
+ if (x === null || x === undefined)
+ return false;
+ return x.toString().startsWith(str);
+ }
+ };
+ };
+
+ for ( var p in filter) {
+ if (typeof (filter[p]) == "string" && filter[p].endsWith("*"))
+ filter[p] = match(filter[p].substr(0, filter[p].length));
+ }
+ return function(ft) {
+ for ( var p in filter) {
+ if (filter[p] && filter[p].test ? !filter[p]
+ .test(ft.get(p)) : ft.get(p) != filter[p])
+ return false;
+ }
+ return true;
+ };
+ }
+ throw new Error("Unsupported filter");
+ }
+
+ /**
+ * @constructor
+ * @example
+ *
+ *
+ * var store = new VectorStore({
+ * source : vectorSource
+ * });
+ *
+ * var req = new VectorStoreQuery({
+ * city : "Moscow"
+ * }, [ 30, 50, 40, 60 ]);
+ *
+ * store.query(req).then(showResults);
+ *
+ */
+ return function(filter, extent) {
+ var match = filter && buildFilter(filter);
+
+ var query = function(ft) {
+ if (extent) {
+ var g = gt.getGeometry();
+ if (!g || !ol.extent.intersects(extent, g.getExtent()))
+ return false;
+ }
+
+ return !match || match(ft);
+ };
+
+ query.extent = extent;
+ query.predicate = match;
+
+ return query;
+ };
+});
\ No newline at end of file
diff -r 9c0943c68a90 -r f0035923ff3e src/djol/WFSSource.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/djol/WFSSource.js Mon Aug 21 17:47:00 2017 +0300
@@ -0,0 +1,112 @@
+define([ "ol", "dojo/request", "dojo/_base/array", "implab/safe"],
+
+function(ol, request, array, safe) {
+ return function(wfs, featurePrefix, featureType, featureNS, queryArgs) {
+ if (arguments.length == 1) {
+ featurePrefix = wfs.featurePrefix;
+ featureType = wfs.featureType;
+ featureNS = wfs.featureNS;
+ wfs = wfs.wfsURL;
+ queryArgs = wfs.queryArgs;
+ }
+
+ safe.argumentNotNull(wfs, "wfsURL");
+ safe.argumentNotEmpty(featurePrefix, "featurePrefix");
+ safe.argumentNotEmpty(featureNS, "featureNS");
+ safe.argumentNotEmpty(featureType, "featureType");
+
+ var format = new ol.format.WFS({
+ featureNS : featureNS,
+ featureType : featureType
+ });
+
+ var layerName = featurePrefix + ":" + featureType;
+
+ function loader(extent, resolution, projection) {
+ var query = {
+ service : 'WFS',
+ version : '1.1.0',
+ request : 'GetFeature',
+ typename : layerName,
+ srsname : projection.getCode()
+ };
+ safe.mixin(query, queryArgs);
+
+ if (extent && isFinite(extent[0]))
+ query.bbox = extent.join(',') + "," + projection.getCode();
+
+ return request(wfs, {
+ query : query,
+ handleAs : 'xml'
+ }).then(function(data) {
+ // в загрузчике нельзя вызывать метод source.clear() поскольку
+ // это приводит к рекурсии
+ var features = format.readFeatures(data);
+
+ var map = {}, del = [], add = [];
+
+ array.forEach(features, function(x) {
+ // HACK исправляем идентификаторы, чтобы они совпадали с
+ // реальными
+
+ var id = x.get("id");
+ if (id)
+ x.setId(id);
+ else
+ id = x.getId();
+
+ map[id] = x;
+
+ // нужно проверить, была ли фича на карте
+ var prev = source.getFeatureById(id);
+ if (prev) {
+ // если да, то обновить ее.
+ var data = x.getProperties();
+ prev.setProperties(data);
+ } else {
+ // иначе добавить
+ add.push(x);
+ }
+ });
+
+ source.forEachFeatureInExtent(extent, function(x) {
+ if (!(x.getId() in map))
+ del.push(x);
+ });
+
+ source.addFeatures(add);
+
+ array.forEach(del, function(x) {
+ source.removeFeature(x);
+ });
+
+ //revision = revision + 1;
+
+ source.set("revision", ++revision);
+
+ });
+ }
+
+ var cls = ol.source.ServerVector || ol.source.Vector;
+ var revision = 0;
+ var source = new cls({
+ loader : loader,
+ //revision: revision
+ wrapX : false
+ // ,
+ // strategy : options.strategy || ol.loadingstrategy.all,
+ // projection : options.projection
+ });
+ source.set("revision", revision);
+ source.reload = function(extent,resolution, projection, q) {
+ if (arguments.length >= 4)
+ queryArgs = q;
+ if (!extent)
+ extent = [-Infinity, -Infinity, Infinity, Infinity];
+ return loader(extent,resolution,projection);
+ };
+
+ console.log(wfs, layerName);
+ return source;
+ };
+});
\ No newline at end of file
diff -r 9c0943c68a90 -r f0035923ff3e src/djol/_OneshotTool.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/djol/_OneshotTool.js Mon Aug 21 17:47:00 2017 +0300
@@ -0,0 +1,65 @@
+define([ "dojo/_base/declare", "implab/safe", "implab/guard", "ol3/_ToolBase", "ol3/ToolType" ],
+
+function(declare, safe, guard, _ToolBase, ToolType) {
+ return declare([ _ToolBase ], {
+ _pending : null,
+
+ _lastResult : null,
+
+ toolType : ToolType.Oneshot,
+
+ invoke : function() {
+ },
+
+ onActivating : function() {
+ var me = this;
+
+ // start the operation
+ me._lastResult = me._pending = guard(me,"invoke");
+
+ return this.inherited(arguments);
+ },
+
+ onActivated : function() {
+ var me = this;
+
+ // fire the activate event
+ this.inherited(arguments);
+
+ me._pending.then(function() {
+ if (me._pending) {
+ me.log("Operation finished, deactivating.");
+ me._pending = null;
+ me.deactivate();
+ }
+ }, function(ex) {
+ if (me._pending) {
+ me.error("Operation failed, deactivating: {0}", ex);
+ me._pending = null;
+ me.deactivate();
+ }
+ });
+ },
+
+ onDeactivated : function() {
+ var d = this._pending;
+ if (d) {
+ this.log("Cancelling pending operation");
+ this._pending = null;
+ d.cancel();
+ }
+
+ return this.inherited(arguments);
+ },
+
+ run : function() {
+ var me = this;
+
+ return me.activate().then(function(success) {
+ if (success)
+ return me._lastResult;
+ throw new Error("Operation declined");
+ });
+ }
+ });
+});
\ No newline at end of file
diff -r 9c0943c68a90 -r f0035923ff3e src/djol/_ToolBase.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/djol/_ToolBase.js Mon Aug 21 17:47:00 2017 +0300
@@ -0,0 +1,46 @@
+define([
+ "dojo/_base/declare",
+ "dojo/when",
+ "implab/safe",
+ "implab/guard",
+ "implab/components/_ActivatableMixin",
+ "implab/log/_LogMixin",
+ "dojo/Evented",
+ "./ToolType" ],
+
+function(declare, when, safe, guard, _ActivatableMixin, _LogMixin, Evented, ToolType) {
+ return declare([ _ActivatableMixin, Evented ], {
+ toolType : ToolType.Activatable,
+
+ module : null,
+
+ constructor : function(opts) {
+ if (opts) {
+ if (opts.controller)
+ this.setController(opts.controller);
+ }
+ },
+
+ onActivating : function() {
+ var me = this, inherited = this.getInherited(arguments);
+ if (me.module && !me.module.isActive())
+ return me.module.activate().then(function(active) {
+ return active ? inherited.apply(me) : false;
+ });
+ else
+ return inherited.apply(me);
+ },
+
+ onActivated : function() {
+ this.emit("active", true);
+ },
+
+ onDeactivated : function() {
+ this.emit("active", false);
+ },
+
+ destroy : function() {
+
+ }
+ });
+});
\ No newline at end of file
diff -r 9c0943c68a90 -r f0035923ff3e src/djol/declare-style.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/djol/declare-style.js Mon Aug 21 17:47:00 2017 +0300
@@ -0,0 +1,20 @@
+define(["dojo/_base/declare","implab/safe"],function(declare, safe){
+ return function(base, proto){
+ var cls = declare(base,proto);
+
+ var factory = function() {
+ var me = this;
+ cls.apply(me,arguments);
+ var fn = function() {
+ return me.getFeatureStyle.apply(me,arguments);
+ };
+ fn.style = me;
+ fn.styleFunction = fn;
+ return fn;
+ };
+
+ factory.styleClass = cls;
+ factory.prototype = cls.prototype;
+ return factory;
+ };
+});
\ No newline at end of file
diff -r 9c0943c68a90 -r f0035923ff3e src/djol/format/coords.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/djol/format/coords.js Mon Aug 21 17:47:00 2017 +0300
@@ -0,0 +1,71 @@
+define(
+ [ "dojo/i18n!./nls/coords", "implab/text/format", "implab/safe" ],
+
+ function(nls, format, safe) {
+
+ var formatDMS = function(coord) {
+ return formatSD(coord, nls.dmsPattern);
+ };
+
+ var formatDM = function(coord) {
+ return formatSD(coord, nls.dmPattern);
+ };
+
+ var formatD = function(coord) {
+ return formatSD(coord, nls.dPattern);
+ };
+
+ /**
+ * pattern:
+ *
+ * {0} - signed floating point number - latitude
+ *
+ * {1} - positive floating point number - minutes part of latitude
+ *
+ * {2} - positive floating point number - seconds part of latitude
+ *
+ * {3} - localized hemisphere sign: north or south
+ *
+ * {4} - signed floating point number - longitude
+ *
+ * {5} - positive floating point number - minutes part of longitude
+ *
+ * {6} - positive floating point number - seconds part of longitude
+ *
+ * {7} - localized hemisphere sign: east or west
+ */
+ var formatSD = function(coord, pattern) {
+ safe.argumentNotNull(coord, "coord");
+ if (!pattern)
+ pattern = nls.sdPattern;
+ var x = (coord[0] % 360 + 540) % 360 - 180, y = (coord[1] % 180 + 270) % 180 - 90;
+
+ return format(pattern, y, Math.abs((y * 60) % 60), Math
+ .abs((y * 3600) % 60), y >= 0 ? nls.north : nls.south, x, Math
+ .abs((x * 60) % 60), Math.abs((x * 3600) % 60), x >= 0
+ ? nls.east
+ : nls.west);
+ };
+
+ var cls = function(fmt) {
+ switch (fmt) {
+ case "DMS":
+ return formatDMS;
+ case "DM":
+ return formatDM;
+ case "D":
+ return formatD;
+ case "SD":
+ return formatSD;
+ default:
+ if (!fmt)
+ return formatSD;
+ else
+ return function(coord) {
+ return formatSD(coord, fmt);
+ }
+ }
+ };
+
+ return cls;
+ });
\ No newline at end of file
diff -r 9c0943c68a90 -r f0035923ff3e src/djol/format/nls/coords.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/djol/format/nls/coords.js Mon Aug 21 17:47:00 2017 +0300
@@ -0,0 +1,14 @@
+define({
+ root : {
+ // lat lon
+ dmsPattern : "{0:!00;00}\u00b0{1:!00}\u2032{2:00}\u2033{3} {4:!000;000}\u00b0{5:!00}\u2032{6:00}\u2033{7}",
+ dmPattern : "{0:!00;00}\u00b0{1:00.0000}\u2032{3} {4:000;000}\u00b0{5:!00.0000}\u2032{7}",
+ dPattern : "{0:00.000000;00.000000}\u00b0{3} {4:000.000000;000.000000}\u00b0{7}",
+ sdPattern : "{0:#0.000000}, {4:#0.000000}",
+ north : "N",
+ south : "S",
+ west : "W",
+ east : "E"
+ },
+ ru : true
+});
\ No newline at end of file
diff -r 9c0943c68a90 -r f0035923ff3e src/djol/format/nls/ru/coords.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/djol/format/nls/ru/coords.js Mon Aug 21 17:47:00 2017 +0300
@@ -0,0 +1,6 @@
+define({
+ north : "С",
+ south : "Ю",
+ west : "З",
+ east : "В"
+});
\ No newline at end of file
diff -r 9c0943c68a90 -r f0035923ff3e src/djol/format/nls/ru/units.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/djol/format/nls/ru/units.js Mon Aug 21 17:47:00 2017 +0300
@@ -0,0 +1,11 @@
+define({
+ kmph : "км/ч",
+ mps : "м/с",
+ knots : "уз",
+ meters : "м",
+ kilometers : "км",
+ meters2 : "м2",
+ kilometers2 : "км2",
+ nmiles : "миль",
+ nmiles2 : "миль2"
+});
\ No newline at end of file
diff -r 9c0943c68a90 -r f0035923ff3e src/djol/format/nls/units.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/djol/format/nls/units.js Mon Aug 21 17:47:00 2017 +0300
@@ -0,0 +1,14 @@
+define({
+ root : {
+ kmph: "km/h",
+ mps: "m/s",
+ knots : "kn",
+ meters : "m",
+ kilometers : "km",
+ meters2 : "m2",
+ kilometers2 : "m2",
+ nmiles : "nmi",
+ nmiles2 : "nmi2"
+ },
+ ru : true
+});
\ No newline at end of file
diff -r 9c0943c68a90 -r f0035923ff3e src/djol/interaction/FeatureDrag.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/djol/interaction/FeatureDrag.js Mon Aug 21 17:47:00 2017 +0300
@@ -0,0 +1,123 @@
+define([ "dojo/_base/declare", "ol", "dojo/Evented" ], function(declare, ol,
+ Evented) {
+
+ var peekFirstFeature = function(map, coordinate, pixel) {
+ return map.forEachFeatureAtPixel(function(ft, layer) {
+ return ft;
+ });
+ };
+
+ var cls = declare([ ol.interaction.Pointer ], {
+ "-chains-" : {
+ constructor : "manual"
+ },
+
+ _peek : null,
+
+ _feature : null,
+
+ _coordinate : null,
+
+ cursor : "pointer",
+
+ _oldCursor : undefined,
+
+ /**
+ * Создает новый объект
+ *
+ * @param {Object}
+ * opts опции
+ * @param {Function}
+ * opts.peek Функция выбора фичи для перетаскивания
+ * function(map,coordinate,pixel), возвращает фичу
+ * @param {String}
+ * opts.cursor css курсор который будет использован при
+ * наведении и перетаскивании фичи
+ *
+ */
+ constructor : function(opts) {
+
+ ol.interaction.Pointer.apply(this, [{
+ handleDownEvent : this.handleDownEvent,
+ handleDragEvent : this.handleDragEvent,
+ handleMoveEvent : this.handleMoveEvent,
+ handleUpEvent : this.handleUpEvent
+ }]);
+ Evented.apply(this);
+
+ if (opts) {
+ if (opts.peek) {
+ this._peek = opts.peek;
+ } else {
+ this._peek = peekFirstFeature;
+ }
+ if ("cursor" in opts)
+ this.cursor = opts.cursor;
+ }
+ },
+
+ handleDownEvent : function(evt) {
+ var c = evt.coordinate;
+
+ var ft = this._peek(evt.map, c, evt.pixel);
+
+ if (ft) {
+ this._feature = ft;
+ this._coordinate = c;
+ this._emit("dragbegin", { feature : ft });
+ return true;
+ }
+
+ return false;
+ },
+
+ handleDragEvent : function(evt) {
+ var c1 = this._coordinate, c2 = evt.coordinate;
+
+ var dx = c2[0] - c1[0];
+ var dy = c2[1] - c1[1];
+
+ this._emit("dragging", { feature : this._feature, fromCoord : c1, toCoord : c2 });
+
+ this._feature.getGeometry().translate(dx, dy);
+
+ this._coordinate = c2;
+ },
+
+ handleUpEvent : function(evt) {
+ if (this._feature)
+ this._emit("dragend", { feature : this._feature });
+
+ this._feature = null;
+ this._coordinate = null;
+ return false;
+ },
+
+ handleMoveEvent : function(evt) {
+ if (this.cursor) {
+ var ft = this._feature || this._peek(evt.map, evt.coordinate , evt.pixel);
+
+ var element = evt.map.getTargetElement();
+ if (ft) {
+ if (element.style.cursor != this.cursor) {
+ this._oldCursor = element.style.cursor;
+ element.style.cursor = this.cursor;
+ }
+ } else if (this._oldCursor !== undefined) {
+ element.style.cursor = this._oldCursor;
+ this._oldCursor = undefined;
+ }
+ }
+ },
+
+ _emit : function(name, data) {
+ var evt = new ol.source.VectorEvent(name,this);
+
+ for(var p in data)
+ evt[p] = data[p];
+ this.dispatchEvent(evt);
+ }
+ });
+
+ return cls;
+});
\ No newline at end of file
diff -r 9c0943c68a90 -r f0035923ff3e src/djol/listen.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/djol/listen.js Mon Aug 21 17:47:00 2017 +0300
@@ -0,0 +1,22 @@
+define(["ol"], function(ol) {
+
+ var listen = function(target, event, callback) {
+ var key = target.on(event, callback);
+ return {
+ remove : function() {
+ ol.Observable.unByKey(key);
+ }
+ };
+ };
+
+ listen.once = function(target, event, callback) {
+ var key = target.once(event, callback);
+ return {
+ remove : function() {
+ ol.Observable.unByKey(key);
+ }
+ };
+ };
+
+ return listen;
+});
\ No newline at end of file
diff -r 9c0943c68a90 -r f0035923ff3e src/djol/main.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/djol/main.js Mon Aug 21 17:47:00 2017 +0300
@@ -0,0 +1,6 @@
+define([ "ol" ], function(ol) {
+ // вспомогательный класс для получения ol в виде зависимости
+ return function() {
+ return ol;
+ };
+});
\ No newline at end of file
diff -r 9c0943c68a90 -r f0035923ff3e src/djol/ol-stub.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/djol/ol-stub.js Mon Aug 21 17:47:00 2017 +0300
@@ -0,0 +1,4 @@
+var ol;
+define([], function() {
+ return ol;
+});
\ No newline at end of file
diff -r 9c0943c68a90 -r f0035923ff3e src/djol/resources/LayerCheckBoxTemplate.html
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/djol/resources/LayerCheckBoxTemplate.html Mon Aug 21 17:47:00 2017 +0300
@@ -0,0 +1,4 @@
+