UNPKG

@geoext/geoext

Version:

GeoExt is Open Source and enables building desktop-like GIS applications through the web. It is a JavaScript framework that combines the GIS functionality of OpenLayers with the user interface savvy of the ExtJS library provided by Sencha.

343 lines (320 loc) 11.1 kB
/* Copyright (c) 2015-present The Open Source Geospatial Foundation * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ /** * Provides an interface to a Mapfish or GeoServer print module. * * @class GeoExt.data.MapfishPrintProvider */ Ext.define('GeoExt.data.MapfishPrintProvider', { extend: 'Ext.Base', mixins: ['Ext.mixin.Observable', 'GeoExt.mixin.SymbolCheck'], requires: [ 'GeoExt.data.model.print.Capability', 'Ext.data.JsonStore', 'Ext.data.Store', 'Ext.data.proxy.Ajax', 'Ext.data.proxy.JsonP', ], // <debug> symbols: [ 'ol.Collection', 'ol.geom.Polygon.fromExtent', 'ol.Feature', 'ol.layer.Layer#getSource', 'ol.layer.Group', 'ol.source.Vector.prototype.addFeature', 'ol.View#calculateExtent', ], // </debug> /** * @event ready * Fires after the PrintCapability store is loaded. * * @param {GeoExt.data.MapfishPrintProvider} provider The * GeoExt.data.MapfishPrintProvider itself */ config: { capabilities: null, url: '', useJsonp: true, }, inheritableStatics: { /** * An array of objects specifying a serializer and a connected * OpenLayers class. This should not be manipulated by hand, but rather * with the method #registerSerializer. * * @private */ _serializers: [], /** * Registers the passed serializer class as an appropriate serializer * for the passed OpenLayers source class. * * @param {ol.source.Source} olSourceCls The OpenLayers source class * that the passed serializer can serialize. * @param {GeoExt.data.serializer.Base} serializerCls The serializer * that can serialize the passed source. */ registerSerializer: function (olSourceCls, serializerCls) { const staticMe = GeoExt.data.MapfishPrintProvider; staticMe._serializers.push({ olSourceCls: olSourceCls, serializerCls: serializerCls, }); }, /** * Unregisters the passed serializer class from the array of available * serializers. This may be useful if you want to register a new * serializer that is different from a serializer that we provide. * * @param {GeoExt.data.serializer.Base} serializerCls The serializer * that can serialize the passed source. * @return {boolean} Whether we could unregister the serializer. */ unregisterSerializer: function (serializerCls) { const available = GeoExt.data.MapfishPrintProvider._serializers; let index; Ext.each(available, function (candidate, idx) { if (candidate.serializerCls === serializerCls) { index = idx; return false; // break early } }); if (Ext.isDefined(index)) { Ext.Array.removeAt(available, index); return true; } return false; }, /** * Returns a GeoExt.data.serializer.Base capable of serializing the * passed source instance or undefined, if no such serializer was * previously registered. * * @param {ol.source.Source} source The source instance to find a * serializer for. * @return {GeoExt.data.serializer.Base} A serializer for the passed * source or `undefined`. */ findSerializerBySource: function (source) { const available = GeoExt.data.MapfishPrintProvider._serializers; let serializer; Ext.each(available, function (candidate) { if (source instanceof candidate.olSourceCls) { serializer = candidate.serializerCls; return false; // break early } }); if (!serializer) { Ext.log.warn( "Couldn't find a suitable serializer for source." + ' Did you require() an appropriate serializer class?', ); } return serializer; }, /** * Will return an array of ol-layers by the given collection. Layers * contained in `ol.layer.Group`s get extracted and groups get removed * from returning array * * @param {GeoExt.data.store.Layers | ol.Collection | Array<ol.layer.Base>} coll * The 'collection' of layers to get as array. If passed as * ol.Collection, all items must be `ol.layer.Base`. * @return {Array} The flat layers array. */ getLayerArray: function (coll) { const me = this; let inputLayers = []; const outputLayers = []; if (coll instanceof GeoExt.data.store.Layers) { coll.each(function (layerRec) { const layer = layerRec.getOlLayer(); inputLayers.push(layer); }); } else if (coll instanceof ol.Collection) { inputLayers = Ext.clone(coll.getArray()); } else { inputLayers = Ext.clone(coll); } inputLayers.forEach(function (layer) { if (layer instanceof ol.layer.Group) { Ext.each(me.getLayerArray(layer.getLayers()), function (subLayer) { outputLayers.push(subLayer); }); } else { outputLayers.push(layer); } }); return outputLayers; }, /** * Will return an array of serialized layers for mapfish print servlet * v3.0. * * @param {GeoExt.component.Map} mapComponent The GeoExt map component * to get the the layers from. * @param {Function} [filterFn] A function to filter the layers to be * serialized. * @param {ol.layer.Base} filterFn.item The layer to check for * inclusion. * @param {number} filterFn.index The index of the layer in the * flattened list. * @param {Array} filterFn.array The complete flattened array of layers. * @param {boolean} filterFn.return Return a truthy value to keep the * layer and serialize it. * @param {Object} [filterScope] The scope in which the filtering * function will be executed. * @return {Array<Object>} An array of serialized layers. * @static */ getSerializedLayers: function (mapComponent, filterFn, filterScope) { const layers = mapComponent.getLayers(); const viewRes = mapComponent.getView().getResolution(); const serializedLayers = []; let inputLayers = this.getLayerArray(layers); if (Ext.isDefined(filterFn)) { inputLayers = Ext.Array.filter(inputLayers, filterFn, filterScope); } Ext.each( inputLayers, function (layer) { const source = layer.getSource(); let serialized = {}; const serializer = this.findSerializerBySource(source); if (serializer) { serialized = serializer.serialize( layer, source, viewRes, mapComponent.map, ); serializedLayers.push(serialized); } }, this, ); return serializedLayers; }, /** * Renders the extent of the printout. Will ensure that the extent is * always visible and that the ratio matches the ratio that clientInfo * contains. * * @param {GeoExt.component.Map} mapComponent The map component to * render the print extent to. * @param {ol.layer.Vector} extentLayer The vector layer to render the * print extent to. * @param {Object} clientInfo Information about the desired print * dimensions. * @param {number} clientInfo.width The target width. * @param {number} clientInfo.height The target height. * @return {ol.Feature} The feature representing the print extent. */ renderPrintExtent: function (mapComponent, extentLayer, clientInfo) { const mapComponentWidth = mapComponent.getWidth(); const mapComponentHeight = mapComponent.getHeight(); const currentMapRatio = mapComponentWidth / mapComponentHeight; const scaleFactor = 0.6; const desiredPrintRatio = clientInfo.width / clientInfo.height; let targetWidth; let targetHeight; if (desiredPrintRatio >= currentMapRatio) { targetWidth = mapComponentWidth * scaleFactor; targetHeight = targetWidth / desiredPrintRatio; } else { targetHeight = mapComponentHeight * scaleFactor; targetWidth = targetHeight * desiredPrintRatio; } const geomExtent = mapComponent .getView() .calculateExtent([targetWidth, targetHeight]); const feat = new ol.Feature(ol.geom.Polygon.fromExtent(geomExtent)); extentLayer.getSource().addFeature(feat); return feat; }, }, /** * The capabiltyRec is an instance of 'GeoExt.data.model.print.Capability' * and contains the PrintCapabilities of the Printprovider. * * @property {GeoExt.data.model.print.Capability} capabilityRec PrintCapabilities record * @readonly */ capabilityRec: null, constructor: function (cfg) { this.mixins.observable.constructor.call(this, cfg); if (!cfg.capabilities && !cfg.url) { Ext.Error.raise('Print capabilities or Url required'); } this.initConfig(cfg); this.fillCapabilityRec(); }, /** * Creates the store from object or url. * * @private */ fillCapabilityRec: function () { // enhance checks let store; const capabilities = this.getCapabilities(); const url = this.getUrl(); const fillRecordAndFireEvent = function () { this.capabilityRec = store.getAt(0); if (!this.capabilityRec) { this.fireEvent('error', this); } else { this.fireEvent('ready', this); } }; if (capabilities) { // if capability object is passed store = Ext.create('Ext.data.JsonStore', { model: 'GeoExt.data.model.print.Capability', listeners: { datachanged: fillRecordAndFireEvent, scope: this, }, }); store.loadRawData(capabilities); } else if (url) { // if servlet url is passed const proxy = { url: url, }; if (this.getUseJsonp()) { proxy.type = 'jsonp'; proxy.callbackKey = 'jsonp'; } else { proxy.type = 'ajax'; proxy.reader = { type: 'json', }; } store = Ext.create('Ext.data.Store', { autoLoad: true, model: 'GeoExt.data.model.print.Capability', proxy: proxy, listeners: { load: fillRecordAndFireEvent, scope: this, }, }); } }, });