/** * Copyright (c) 2008-2010 The Open Source Geospatial Foundation * * Published under the BSD license. * See http://svn.geoext.org/core/trunk/geoext/license.txt for the full text * of the license. */ /** * @include GeoExt/data/LayerStore.js */ /** api: (define) * module = GeoExt * class = MapPanel * base_link = `Ext.Panel `_ */ Ext.namespace("GeoExt"); /** api: example * Sample code to create a panel with a new map: * * .. code-block:: javascript * * var mapPanel = new GeoExt.MapPanel({ * border: false, * renderTo: "div-id", * map: { * maxExtent: new OpenLayers.Bounds(-90, -45, 90, 45) * } * }); * * Sample code to create a map panel with a bottom toolbar in a Window: * * .. code-block:: javascript * * var win = new Ext.Window({ * title: "My Map", * items: [{ * xtype: "gx_mappanel", * bbar: new Ext.Toolbar() * }] * }); */ /** api: constructor * .. class:: MapPanel(config) * * Create a panel container for a map. */ GeoExt.MapPanel = Ext.extend(Ext.Panel, { /** api: config[map] * ``OpenLayers.Map or Object`` A configured map or a configuration object * for the map constructor. A configured map will be available after * construction through the :attr:`map` property. */ /** api: property[map] * ``OpenLayers.Map`` or ``Object`` A map or map configuration. */ map: null, /** api: config[layers] * ``GeoExt.data.LayerStore or GeoExt.data.GroupingStore or Array(OpenLayers.Layer)`` * A store holding records. The layers provided here will be added to this * MapPanel's map when it is rendered. */ /** api: property[layers] * :class:`GeoExt.data.LayerStore` A store containing * :class:`GeoExt.data.LayerRecord` objects. */ layers: null, /** api: config[center] * ``OpenLayers.LonLat or Array(Number)`` A location for the map center. If * an array is provided, the first two items should represent x & y coordinates. */ center: null, /** api: config[zoom] * ``Number`` An initial zoom level for the map. */ zoom: null, /** api: config[prettyStateKeys] * ``Boolean`` Set this to true if you want pretty strings in the MapPanel's * state keys. More specifically, layer.name instead of layer.id will be used * in the state keys if this option is set to true. But in that case you have * to make sure you don't have two layers with the same name. Defaults to * false. */ prettyStateKeys: false, /** api: config[extent] * ``OpenLayers.Bounds or Array(Number)`` An initial extent for the map (used * if center and zoom are not provided. If an array, the first four items * should be minx, miny, maxx, maxy. */ extent: null, /** private: property[stateEvents] * ``Array(String)`` Array of state events */ stateEvents: ["aftermapmove", "afterlayervisibilitychange", "afterlayeropacitychange"], /** private: method[initComponent] * Initializes the map panel. Creates an OpenLayers map if * none was provided in the config options passed to the * constructor. */ initComponent: function(){ if(!(this.map instanceof OpenLayers.Map)) { this.map = new OpenLayers.Map( Ext.applyIf(this.map || {}, {allOverlays: true}) ); } var layers = this.layers; if(!layers || layers instanceof Array) { this.layers = new GeoExt.data.LayerStore({ layers: layers, map: this.map.layers.length > 0 ? this.map : null }); } if(typeof this.center == "string") { this.center = OpenLayers.LonLat.fromString(this.center); } else if(this.center instanceof Array) { this.center = new OpenLayers.LonLat(this.center[0], this.center[1]); } if(typeof this.extent == "string") { this.extent = OpenLayers.Bounds.fromString(this.extent); } else if(this.extent instanceof Array) { this.extent = OpenLayers.Bounds.fromArray(this.extent); } GeoExt.MapPanel.superclass.initComponent.call(this); this.addEvents( /** private: event[aftermapmove] * Fires after the map is moved. */ "aftermapmove", /** private: event[afterlayervisibilitychange] * Fires after a layer changed visibility. */ "afterlayervisibilitychange", /** private: event[afterlayeropacitychange] * Fires after a layer changed opacity. */ "afterlayeropacitychange" ); this.map.events.on({ "moveend": this.onMoveend, "changelayer": this.onLayerchange, scope: this }); }, /** private: method[onMoveend] * * The "moveend" listener. */ onMoveend: function() { this.fireEvent("aftermapmove"); }, /** private: method[onLayerchange] * :param e: ``Object`` * * The "changelayer" listener. */ onLayerchange: function(e) { if(e.property) { if(e.property === "visibility") { this.fireEvent("afterlayervisibilitychange"); } else if(e.property === "opacity") { this.fireEvent("afterlayeropacitychange"); } } }, /** private: method[applyState] * :param state: ``Object`` The state to apply. * * Apply the state provided as an argument. */ applyState: function(state) { // if we get strings for state.x, state.y or state.zoom // OpenLayers will take care of converting them to the // appropriate types so we don't bother with that this.center = new OpenLayers.LonLat(state.x, state.y); this.zoom = state.zoom; // set layer visibility and opacity var i, l, layer, layerId, visibility, opacity; var layers = this.map.layers; for(i=0, l=layers.length; i 0) { if(this.center || this.zoom != null) { // both do not have to be defined map.setCenter(this.center, this.zoom); } else if(this.extent) { map.zoomToExtent(this.extent); } else { map.zoomToMaxExtent(); } } }, /** private: method[afterRender] * Private method called after the panel has been rendered. */ afterRender: function() { GeoExt.MapPanel.superclass.afterRender.apply(this, arguments); if(!this.ownerCt) { this.renderMap(); } else { this.ownerCt.on("move", this.updateMapSize, this); this.ownerCt.on({ "afterlayout": { fn: this.renderMap, scope: this, single: true } }); } }, /** private: method[onResize] * Private method called after the panel has been resized. */ onResize: function() { GeoExt.MapPanel.superclass.onResize.apply(this, arguments); this.updateMapSize(); }, /** private: method[onBeforeAdd] * Private method called before a component is added to the panel. */ onBeforeAdd: function(item) { if(typeof item.addToMapPanel === "function") { item.addToMapPanel(this); } GeoExt.MapPanel.superclass.onBeforeAdd.apply(this, arguments); }, /** private: method[remove] * Private method called when a component is removed from the panel. */ remove: function(item, autoDestroy) { if(typeof item.removeFromMapPanel === "function") { item.removeFromMapPanel(this); } GeoExt.MapPanel.superclass.remove.apply(this, arguments); }, /** private: method[beforeDestroy] * Private method called during the destroy sequence. */ beforeDestroy: function() { if(this.ownerCt) { this.ownerCt.un("move", this.updateMapSize, this); } if(this.map && this.map.events) { this.map.events.un({ "moveend": this.onMoveend, "changelayer": this.onLayerchange, scope: this }); } // if the map panel was passed a map instance, this map instance // is under the user's responsibility if(!this.initialConfig.map || !(this.initialConfig.map instanceof OpenLayers.Map)) { // we created the map, we destroy it if(this.map && this.map.destroy) { this.map.destroy(); } } delete this.map; GeoExt.MapPanel.superclass.beforeDestroy.apply(this, arguments); } }); /** api: function[guess] * :return: ``GeoExt.MapPanel`` The first map panel found by the Ext * component manager. * * Convenience function for guessing the map panel of an application. This * can reliably be used for all applications that just have one map panel * in the viewport. */ GeoExt.MapPanel.guess = function() { return Ext.ComponentMgr.all.find(function(o) { return o instanceof GeoExt.MapPanel; }); }; /** api: xtype = gx_mappanel */ Ext.reg('gx_mappanel', GeoExt.MapPanel);