diff --git a/mapcomposer/app/static/externals/gxp/src/script/widgets/AdvancedScaleOverlay.js b/mapcomposer/app/static/externals/gxp/src/script/widgets/AdvancedScaleOverlay.js new file mode 100644 index 000000000..f50c6c3e9 --- /dev/null +++ b/mapcomposer/app/static/externals/gxp/src/script/widgets/AdvancedScaleOverlay.js @@ -0,0 +1,348 @@ +/** + * Copyright (c) 2008-2011 The Open Planning Project + * + * Published under the GPL license. + * See https://github.com/opengeo/gxp/raw/master/license.txt for the full text + * of the license. + */ + +/** api: (define) + * module = gxp + * class = ScaleOverlay + * base_link = `Ext.Panel `_ + */ +Ext.namespace("gxp"); + +/** api: constructor + * .. class:: ScaleOverlay(config) + * + * Create a panel for showing a ScaleLine control and a combobox for + * selecting the map scale. + */ +gxp.AdvancedScaleOverlay = Ext.extend(Ext.Panel, { + + /** api: config[map] + * ``OpenLayers.Map`` or :class:`GeoExt.MapPanel` + * The map for which to show the scale info. + */ + map: null, + + /** api: config[topOutUnits] + * {String} Units for zoomed out on top bar. Default is km. + */ + topOutUnits: null, + + /** api: config[topInUnits] + * {String} Units for zoomed in on top bar. Default is m. + */ + topInUnits: null, + + /** api: config[displaySystem] + * {String} Units for zoomed in on scale bar. Default is nautical. + */ + displaySystem: null, + + /** api: config[bottomInUnits] + * {String} Units for zoomed in on bottom bar. Default is ft. + */ + bottomInUnits: null, + + /** api: config[bottomOutUnits] + * {String} Units for zoomed out on bottom bar. Default is mi. + */ + bottomOutUnits: null, + + /** api: config[enableSetScaleUnits] + * {boolean} Enable or disable ComboUnits. + */ + enableSetScaleUnits: true, + + /** api: config[divisions] + * {integer} Number of Divisions. + */ + divisions: 2, + + /** api: config[subdivisions] + * {integer} Number of SubDivisions. + */ + subdivisions: 2, + + /** api: config[showMinorMeasures] + * {boolean} Enable or disable MinorMeasures. + */ + showMinorMeasures: false, + + /** api: config[singleLine] + * {boolean} Enable or disable Single Line display. + */ + singleLine: false, + + /** api: config[abbreviateLabel] + * {boolean} Enable or disable Abbreviate Labels. + */ + abbreviateLabel: false, + + /** i18n */ + zoomLevelText: "Zoom level", + + /** private: method[initComponent] + * Initialize the component. + */ + initComponent: function() { + gxp.AdvancedScaleOverlay.superclass.initComponent.call(this); + + if(!this.topOutUnits){ + this.topOutUnits = "km"; + } + if(!this.topInUnits){ + this.topInUnits = "m"; + } + if(!this.bottomInUnits){ + this.bottomInUnits = "ft"; + } + if(!this.bottomOutUnits){ + this.bottomOutUnits = "mi"; + } + if(!this.displaySystem){ + this.displaySystem = "metric"; + } + + this.cls = 'map-overlay'; + if(this.map) { + if(this.map instanceof GeoExt.MapPanel) { + this.map = this.map.map; + } + this.bind(this.map); + } + this.on("beforedestroy", this.unbind, this); + }, + + /** private: method[addToMapPanel] + * :param panel: :class:`GeoExt.MapPanel` + * + * Called by a MapPanel if this component is one of the items in the panel. + */ + addToMapPanel: function(panel) { + this.on({ + afterrender: function() { + this.bind(panel.map); + }, + scope: this + }); + }, + + /** private: method[stopMouseEvents] + * :param e: ``Object`` + */ + stopMouseEvents: function(e) { + e.stopEvent(); + }, + + /** private: method[removeFromMapPanel] + * :param panel: :class:`GeoExt.MapPanel` + * + * Called by a MapPanel if this component is one of the items in the panel. + */ + removeFromMapPanel: function(panel) { + var el = this.getEl(); + el.un("mousedown", this.stopMouseEvents, this); + el.un("click", this.stopMouseEvents, this); + this.unbind(); + }, + + /** private: method[addScaleLine] + * + * Create the scale line control and add it to the panel. + */ + addScaleLine: function(topOutUnits,topInUnits,bottomInUnits,bottomOutUnits,divisions,subdivisions,showMinorMeasures,singleLine,abbreviateLabel) { + if(topOutUnits && topInUnits && bottomInUnits && bottomOutUnits){ + Ext.getCmp("id_box").destroy(); + } + + this.scaleLinePanel = new Ext.BoxComponent({ + id: "id_box", + autoEl: { + tag: "div", + cls: "olControlScaleLine overlay-element overlay-scaleline" + } + }); + + this.on("afterlayout", function(){ + if(!topOutUnits){ + this.scaleLinePanel.getEl().dom.style.position = 'relative'; + this.scaleLinePanel.getEl().dom.style.display = 'inline'; + }else{ + Ext.get("id_box").insertBefore(Ext.get("zoom_selector")); + } + this.getEl().on("click", this.stopMouseEvents, this); + this.getEl().on("mousedown", this.stopMouseEvents, this); + }, this); + + this.scaleLinePanel.on('render', function(){ + var mousePositionControl = this.map.getControlsByClass('OpenLayers.Control.MousePosition'); + var scaleBarControl = this.map.getControlsByClass('OpenLayers.Control.ScaleBar'); + + if(topOutUnits && topInUnits && bottomInUnits && bottomOutUnits){ + this.map.removeControl(mousePositionControl[0]); + this.map.removeControl(scaleBarControl[0]); + } + + var mousePosition = new OpenLayers.Control.MousePosition({ + /*prefix: '' + + 'EPSG:4326 lon/lat: ',*/ + separator: ' : ', + numDigits: 3, + div: this.scaleLinePanel.getEl().dom + }); + + if (topOutUnits != "hide") { + var scalebar = new OpenLayers.Control.ScaleBar({ + geodesic: true, + displaySystem: topOutUnits ? (topOutUnits == "mi" || topOutUnits == "nmi" ? "nautical" : "metric") : this.displaySystem, + divisions: divisions ? divisions : this.divisions, + subdivisions: subdivisions ? subdivisions : this.subdivisions, + showMinorMeasures: showMinorMeasures ? showMinorMeasures : this.showMinorMeasures, + singleLine: singleLine ? singleLine : this.singleLine, + abbreviateLabel: abbreviateLabel ? abbreviateLabel : this.abbreviateLabel + }); + + this.map.addControl(scalebar); + scalebar.activate(); + } + + this.map.addControl(mousePosition); + mousePosition.activate(); + }, this); + + this.add(this.scaleLinePanel); + }, + + /** private: method[handleZoomEnd] + * + * Set the correct value in the scale combo box. + */ + handleZoomEnd: function() { + var scale = this.zoomStore.queryBy(function(record) { + return this.map.getZoom() == record.data.level; + }, this); + if (scale.length > 0) { + scale = scale.items[0]; + this.zoomSelector.setValue("1 : " + parseInt(scale.data.scale, 10)); + } else { + if (!this.zoomSelector.rendered) { + return; + } + this.zoomSelector.clearValue(); + } + }, + + /** private: method[addScaleCombo] + * + * Create the scale combo and add it to the panel. + */ + addScaleCombo: function() { + this.zoomStore = new GeoExt.data.ScaleStore({ + map: this.map + }); + this.zoomSelector = new Ext.form.ComboBox({ + emptyText: this.zoomLevelText, + tpl: '
1 : {[parseInt(values.scale)]}
', + editable: false, + triggerAction: 'all', + mode: 'local', + store: this.zoomStore, + width: 110 + }); + this.zoomSelector.on({ + click: this.stopMouseEvents, + mousedown: this.stopMouseEvents, + select: function(combo, record, index) { + this.map.zoomTo(record.data.level); + }, + scope: this + }); + this.map.events.register('zoomend', this, this.handleZoomEnd); + var zoomSelectorWrapper = new Ext.Panel({ + id: "zoom_selector", + items: [this.zoomSelector], + cls: 'overlay-element overlay-scalechooser', + border: false + }); + this.add(zoomSelectorWrapper); + }, + /** private: method[addComboUnits] + * + * Create the scale combo units and add it to the panel. + * deve comparire solo se lo definisco in configurazione + */ + addComboUnits: function() { + var comboUnits = this; + this.unitsSelector = new Ext.form.ComboBox({ + editable: false, + typeAhead: true, + forceSelection: true, + selectOnFocus:false, + triggerAction: 'all', + mode: 'local', + emptyText:this.topOutUnits, + displayField: 'unitsName', + valueField: 'unitsValue', + store: new Ext.data.SimpleStore({ + fields: ['unitsValue', 'unitsName'], + data: [['km;m;ft;mi','Km'],['nmi;nmi;m;km','Nmi'],['hide;hide;hide;hide','Hide']] + }), + width: 90 + }); + this.unitsSelector.on({ + click: this.stopMouseEvents, + mousedown: this.stopMouseEvents, + select: function(combo, record, index) { + var valueUnits = this.unitsSelector.getValue().split(";"); + comboUnits.updateScaleUnits(valueUnits[0],valueUnits[1],valueUnits[2],valueUnits[3]); + }, + scope: this + }); + var unitsSelectorWrapper = new Ext.Panel({ + id: "id_units", + items: [this.unitsSelector], + cls: 'overlay-element overlay-unitschooser', + border: false + }); + this.add(unitsSelectorWrapper); + }, + /** private: method[updateScaleUnits] + * :params topOutUnits,topInUnits,bottomInUnits,bottomOutUnits + */ + updateScaleUnits: function(topOutUnits,topInUnits,bottomInUnits,bottomOutUnits,divisions,subdivisions,showMinorMeasures,singleLine,abbreviateLabel) { + this.addScaleLine(topOutUnits,topInUnits,bottomInUnits,bottomOutUnits,divisions,subdivisions,showMinorMeasures,singleLine,abbreviateLabel); + this.doLayout(); + }, + /** private: method[bind] + * :param map: ``OpenLayers.Map`` + */ + bind: function(map) { + this.map = map; + this.addScaleLine(); + this.addScaleCombo(); + if(this.enableSetScaleUnits){ + this.addComboUnits(); + } + this.doLayout(); + }, + + /** private: method[unbind] + */ + unbind: function() { + if(this.map && this.map.events) { + this.map.events.unregister('zoomend', this, this.handleZoomEnd); + } + this.zoomStore = null; + this.zoomSelector = null; + this.unitsSelector = null; + } + +}); + +/** api: xtype = gxp_advancedscaleoverlay */ +Ext.reg('gxp_advancedscaleoverlay', gxp.AdvancedScaleOverlay); diff --git a/mapcomposer/app/static/externals/openlayers-ext/lib/OpenLayers/Control/ScaleBar.js b/mapcomposer/app/static/externals/openlayers-ext/lib/OpenLayers/Control/ScaleBar.js new file mode 100644 index 000000000..1bf0be80e --- /dev/null +++ b/mapcomposer/app/static/externals/openlayers-ext/lib/OpenLayers/Control/ScaleBar.js @@ -0,0 +1,681 @@ +/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD + * license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the + * full text of the license. */ + +/** + * requires OpenLayers/Control.js + */ + +/** + * Class: OpenLayers.Control.ScaleBar + * A scale bar styled with CSS. + * + * Inherits from: + * - + */ +OpenLayers.Control.ScaleBar = OpenLayers.Class(OpenLayers.Control, { + + /** + * Property: element + * {Element} + */ + element: null, + + /** + * Property: scale + * {Float} Scale denominator (1 / X) - set on update + */ + scale: 1, + + /** + * APIProperty: geodesic + * {Boolean} Use geodesic measurement. Default is false. The recommended + * setting for maps in EPSG:4326 is false, and true EPSG:900913. If set to + * true, the scale will be calculated based on the horizontal size of the + * pixel in the center of the map viewport. + */ + geodesic: false, + + /** + * APIProperty: displaySystem + * {String} Display system for scale bar - metric or english supported. + * Default is metric. + */ + displaySystem: 'metric', + + /** + * APIProperty: minWidth + * {Integer} Minimum width of the scale bar in pixels. Default is 100 px. + */ + minWidth: 100, + + /** + * APIProperty: maxWidth + * Maximum width of the scale bar in pixels. Default is 200 px. + */ + maxWidth: 200, + + /** + * APIProperty: divisions + * {Integer} Number of major divisions for the scale bar. Default is 2. + */ + divisions: 2, + + /** + * APIProperty: subdivisions + * {Integer} Number of subdivisions per major division. Default is 2. + */ + subdivisions: 2, + + /** + * APIProperty: showMinorMeasures + * {Boolean} Show measures for subdivisions. Default is false. + */ + showMinorMeasures: false, + + /** + * APIProperty: abbreviateLabel + * {Boolean} Show abbreviated measurement unit (ft, km). Default is false. + */ + abbreviateLabel: false, + + /** + * APIProperty: singleLine + * {Boolean} Display scale bar length and unit after scale bar. Default + * is false. + */ + singleLine: false, + + /** + * APIProperty: align + * {String} Determines how scale bar will be aligned within the element - + * left, center, or right supported + */ + align: 'left', + + /** + * APIProperty: div + * {Element} Optional DOM element to become the container for the scale + * bar. If not provided, one will be created. + */ + div: null, + + /** + * Property: scaleText + * Text to prefix the scale denominator used as a title for the scale bar + * element. Default is "scale 1:". + */ + scaleText: "scale 1:", + + /** + * Property: thousandsSeparator + * Thousands separator for formatted scale bar measures. The title + * attribute for the scale bar always uses + * for number formatting. To + * conserve space on measures displayed with markers, the default + * thousands separator for formatting is "" (no separator). + */ + thousandsSeparator: "", + + /** + * Property: measurementProperties + * {Object} Holds display units, abbreviations, and conversion to inches + * (since we're using dpi) per measurement sytem. + */ + measurementProperties: { + english: { + units: ['miles', 'feet', 'inches'], + abbr: ['mi', 'ft', 'in'], + inches: [63360, 12, 1] + }, + metric: { + units: ['kilometers', 'meters', 'centimeters'], + abbr: ['km', 'm', 'cm'], + inches: [39370.07874, 39.370079, 0.393701] + }, + nautical: { + units: ['nautical miles', 'nautical miles', 'nautical miles'], + abbr: ['nmi', 'nmi', 'nmi'], + inches: [72913.385826772, 72913.385826772, 72913.385826772] + } + }, + + /** + * Property: limitedStyle + * {Boolean} For browsers with limited CSS support, limitedStyle will be + * set to true. In addition, this property can be set to true in the + * options sent to the constructor. If true scale bar element offsets + * will be determined based on the object. + */ + limitedStyle: false, + + /** + * Property: customStyle + * {Object} For cases where is true, a customStyle property + * can be set on the options sent to the constructor. The + * object will be extended with this custom style + * object. + */ + customStyles: null, + + /** + * Property: defaultStyles + * {Object} For cases where is true, default scale bar + * element offsets are taken from this object. Values correspond to + * pixel dimensions given in the stylesheet. + */ + defaultStyles: { + Bar: { + height: 11, top: 12, + borderLeftWidth: 0, + borderRightWidth: 0 + }, + BarAlt: { + height: 11, top: 12, + borderLeftWidth: 0, + borderRightWidth: 0 + }, + MarkerMajor: { + height: 13, width: 13, top: 12, + borderLeftWidth: 0, + borderRightWidth: 0 + }, + MarkerMinor: { + height: 13, width: 13, top: 12, + borderLeftWidth: 0, + borderRightWidth: 0 + }, + NumbersBox: { + height: 13, width: 40, top: 24 + }, + LabelBox: { + height: 15, top: -2 + }, + LabelBoxSingleLine: { + height: 15, width: 35, top: 5, left: 10 + } + }, + + /** + * Property: appliedStyles + * For cases where is true, scale bar element offsets will + * be determined based on extended with any + * . + */ + appliedStyles: null, + + /** + * Constructor: OpenLayers.Control.ScaleBar + * Create a new scale bar instance. + * + * Parameters: + * options - {Object} Optional object whose properties will be set on this + * object. + */ + initialize: function(options) { + OpenLayers.Control.prototype.initialize.apply(this, [options]); + if(!document.styleSheets) { + this.limitedStyle = true; + } + if(this.limitedStyle) { + this.appliedStyles = OpenLayers.Util.extend({}, this.defaultStyles); + OpenLayers.Util.extend(this.appliedStyles, this.customStyles); + } + // create scalebar DOM elements + this.element = document.createElement('div'); + this.element.style.position = 'relative'; + this.element.className = this.displayClass + 'Wrapper'; + this.labelContainer = document.createElement('div'); + this.labelContainer.className = this.displayClass + 'Units'; + this.labelContainer.style.position = 'absolute'; + this.graphicsContainer = document.createElement('div'); + this.graphicsContainer.style.position = 'absolute'; + this.graphicsContainer.className = this.displayClass + 'Graphics'; + this.numbersContainer = document.createElement('div'); + this.numbersContainer.style.position = 'absolute'; + this.numbersContainer.className = this.displayClass + 'Numbers'; + this.element.appendChild(this.graphicsContainer); + this.element.appendChild(this.labelContainer); + this.element.appendChild(this.numbersContainer); + }, + + /** + * APIMethod: destroy + * Destroy the control. + */ + destroy: function() { + this.map.events.unregister('moveend', this, this.onMoveend); + this.div.innerHTML = ""; + OpenLayers.Control.prototype.destroy.apply(this); + }, + + /** + * Method: draw + */ + draw: function() { + OpenLayers.Control.prototype.draw.apply(this, arguments); + // determine offsets for graphic elements + this.dxMarkerMajor = ( + this.styleValue('MarkerMajor', 'borderLeftWidth') + + this.styleValue('MarkerMajor', 'width') + + this.styleValue('MarkerMajor', 'borderRightWidth') + ) / 2; + this.dxMarkerMinor = ( + this.styleValue('MarkerMinor', 'borderLeftWidth') + + this.styleValue('MarkerMinor', 'width') + + this.styleValue('MarkerMinor', 'borderRightWidth') + ) / 2; + this.dxBar = ( + this.styleValue('Bar', 'borderLeftWidth') + + this.styleValue('Bar', 'borderRightWidth') + ) / 2; + this.dxBarAlt = ( + this.styleValue('BarAlt', 'borderLeftWidth') + + this.styleValue('BarAlt', 'borderRightWidth') + ) / 2; + this.dxNumbersBox = this.styleValue('NumbersBox', 'width') / 2; + // set scale bar element height + var classNames = ['Bar', 'BarAlt', 'MarkerMajor', 'MarkerMinor']; + if(this.singleLine) { + classNames.push('LabelBoxSingleLine'); + } else { + classNames.push('NumbersBox', 'LabelBox'); + } + var vertDisp = 0; + for(var classIndex = 0; classIndex < classNames.length; ++classIndex) { + var cls = classNames[classIndex]; + vertDisp = Math.max( + vertDisp, + this.styleValue(cls, 'top') + this.styleValue(cls, 'height') + ); + } + this.element.style.height = vertDisp + 'px'; + this.xOffsetSingleLine = this.styleValue('LabelBoxSingleLine', 'width') + + this.styleValue('LabelBoxSingleLine', 'left'); + + this.div.appendChild(this.element); + this.map.events.register('moveend', this, this.onMoveend); + this.update(); + return this.div; + }, + + /** + * Method: onMoveend + * Registered as a listener for "moveend". + */ + onMoveend: function() { + this.update(); + }, + + /** + * APIMethod: update + * Update the scale bar after modifying properties. + * + * Parameters: + * scale - {Float} Optional scale denominator. If not specified, the + * map scale will be used. + */ + update: function(scale) { + if(this.map.baseLayer == null || !this.map.getScale()) { + return; + } + this.scale = (scale != undefined) ? scale : this.map.getScale(); + // update the element title and width + this.element.title = this.scaleText + OpenLayers.Number.format(this.scale); + this.element.style.width = this.maxWidth + 'px'; + // check each measurement unit in the display system + var comp = this.getComp(); + // get the value (subdivision length) with the lowest cumulative score + this.setSubProps(comp); + // clean out any old content from containers + this.labelContainer.innerHTML = ""; + this.graphicsContainer.innerHTML = ""; + this.numbersContainer.innerHTML = ""; + // create all divisions + var numDiv = this.divisions * this.subdivisions; + var alignmentOffset = { + left: 0 + (this.singleLine ? 0 : this.dxNumbersBox), + center: (this.maxWidth / 2) - + (numDiv * this.subProps.pixels / 2) - + (this.singleLine ? this.xOffsetSingleLine / 2 : 0), + right: this.maxWidth - + (numDiv *this.subProps.pixels) - + (this.singleLine ? this.xOffsetSingleLine : this.dxNumbersBox) + } + var xPos, measure, divNum, cls, left; + for(var di=0; di