[Commits] r1970 - in core/trunk/geoext: examples lib/GeoExt/widgets tests/lib/GeoExt/widgets
commits at geoext.org
commits at geoext.org
Tue Mar 16 14:56:40 CET 2010
Author: elemoine
Date: 2010-03-16 14:56:39 +0100 (Tue, 16 Mar 2010)
New Revision: 1970
Modified:
core/trunk/geoext/examples/mappanel-div.html
core/trunk/geoext/examples/mappanel-div.js
core/trunk/geoext/lib/GeoExt/widgets/MapPanel.js
core/trunk/geoext/tests/lib/GeoExt/widgets/MapPanel.html
Log:
make the MapPanel stateful, so map position, layer visibility, and layer opacity can be stored and restored through an Ext.state.Provider, r=bartvde (closes #94)
Modified: core/trunk/geoext/examples/mappanel-div.html
===================================================================
--- core/trunk/geoext/examples/mappanel-div.html 2010-03-16 13:46:09 UTC (rev 1969)
+++ core/trunk/geoext/examples/mappanel-div.html 2010-03-16 13:56:39 UTC (rev 1970)
@@ -16,6 +16,11 @@
<p>This example shows the how to create a MapPanel with a map that has
already been created. See <a href="mappanel-window.html">mappanel-window.html</a>
for an example that creates the MapPanel without creating the map first.<p>
+ <p>This example makes use of a <code>CookieProvider</code>. The <code>MapPanel</code>
+ being a stateful component, if you reload the page the map should be
+ at the same location as previously. Also the <code>getState</code> and
+ <code>applyState</code> methods are overloaded so the size of the map
+ panel is also restored when refreshing the page.</p>
<p>The js is not minified so it is readable. See <a href="mappanel-div.js">mappanel-div.js</a>.</p>
<div id="mappanel"></div>
<input type="button" onclick="mapSizeUp()" value="bigger"></input>
Modified: core/trunk/geoext/examples/mappanel-div.js
===================================================================
--- core/trunk/geoext/examples/mappanel-div.js 2010-03-16 13:46:09 UTC (rev 1969)
+++ core/trunk/geoext/examples/mappanel-div.js 2010-03-16 13:56:39 UTC (rev 1970)
@@ -15,6 +15,7 @@
var mapPanel;
Ext.onReady(function() {
+ Ext.state.Manager.setProvider(new Ext.state.CookieProvider());
var map = new OpenLayers.Map();
var layer = new OpenLayers.Layer.WMS(
"Global Imagery",
@@ -26,11 +27,25 @@
mapPanel = new GeoExt.MapPanel({
title: "GeoExt MapPanel",
renderTo: "mappanel",
+ stateId: "mappanel",
height: 400,
width: 600,
map: map,
center: new OpenLayers.LonLat(5, 45),
- zoom: 4
+ zoom: 4,
+ // getState and applyState are overloaded so panel size
+ // can be stored and restored
+ getState: function() {
+ var state = GeoExt.MapPanel.prototype.getState.apply(this);
+ state.width = this.getSize().width;
+ state.height = this.getSize().height;
+ return state;
+ },
+ applyState: function(state) {
+ GeoExt.MapPanel.prototype.applyState.apply(this, arguments);
+ this.width = state.width;
+ this.height = state.height;
+ }
});
});
Modified: core/trunk/geoext/lib/GeoExt/widgets/MapPanel.js
===================================================================
--- core/trunk/geoext/lib/GeoExt/widgets/MapPanel.js 2010-03-16 13:46:09 UTC (rev 1969)
+++ core/trunk/geoext/lib/GeoExt/widgets/MapPanel.js 2010-03-16 13:56:39 UTC (rev 1970)
@@ -85,13 +85,29 @@
*/
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
@@ -122,9 +138,129 @@
this.extent = OpenLayers.Bounds.fromArray(this.extent);
}
- GeoExt.MapPanel.superclass.initComponent.call(this);
+ 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<l; i++) {
+ layer = layers[i];
+ layerId = this.prettyStateKeys ? layer.name : layer.id;
+ visibility = state["visibility_" + layerId];
+ if(visibility !== undefined) {
+ // convert to boolean
+ visibility = (/^true$/i).test(visibility);
+ if(layer.isBaseLayer) {
+ if(visibility) {
+ this.map.setBaseLayer(layer);
+ }
+ } else {
+ layer.setVisibility(visibility);
+ }
+ }
+ opacity = state["opacity_" + layerId];
+ if(opacity !== undefined) {
+ layer.setOpacity(opacity);
+ }
+ }
+ },
+
+ /** private: method[getState]
+ * :return: ``Object`` The state.
+ *
+ * Returns the current state for the map panel.
+ */
+ getState: function() {
+ var state;
+
+ // Ext delays the call to getState when a state event
+ // occurs, so the MapPanel may have been destroyed
+ // between the time the event occurred and the time
+ // getState is called
+ if(!this.map) {
+ return;
+ }
+
+ // record location and zoom level
+ var center = this.map.getCenter();
+ state = {
+ x: center.lon,
+ y: center.lat,
+ zoom: this.map.getZoom()
+ };
+
+ // record layer visibility and opacity
+ var i, l, layer, layerId, layers = this.map.layers;
+ for(i=0, l=layers.length; i<l; i++) {
+ layer = layers[i];
+ layerId = this.prettyStateKeys ? layer.name : layer.id;
+ state["visibility_" + layerId] = layer.getVisibility();
+ state["opacity_" + layerId] = layer.opacity == null ?
+ 1 : layer.opacity;
+ }
+
+ return state;
+ },
+
/** private: method[updateMapSize]
* Tell the map that it needs to recalculate its size and position.
*/
@@ -208,10 +344,15 @@
this.ownerCt.un("move", this.updateMapSize, this);
}
GeoExt.MapPanel.superclass.beforeDestroy.apply(this, arguments);
- /**
- * If this container was passed a map instance, it is the
- * responsibility of the creator to destroy it.
- */
+ // if the map panel was passed a map instance, this map instance
+ // is under the user's responsibility
+ if(this.map && this.map.events) {
+ this.map.events.un({
+ "moveend": this.onMoveend,
+ "changelayer": this.onLayerchange,
+ scope: this
+ });
+ }
if(!this.initialConfig.map ||
!(this.initialConfig.map instanceof OpenLayers.Map)) {
// we created the map, we destroy it
Modified: core/trunk/geoext/tests/lib/GeoExt/widgets/MapPanel.html
===================================================================
--- core/trunk/geoext/tests/lib/GeoExt/widgets/MapPanel.html 2010-03-16 13:46:09 UTC (rev 1969)
+++ core/trunk/geoext/tests/lib/GeoExt/widgets/MapPanel.html 2010-03-16 13:56:39 UTC (rev 1970)
@@ -291,7 +291,288 @@
panel.destroy();
}
+ function test_applyState_called(t) {
+ t.plan(1);
+ // set up
+
+ var provider, applyState, mapPanel, log;
+
+ provider = new Ext.state.Provider();
+ provider.state["map"] = {};
+ Ext.state.Manager.setProvider(provider);
+
+ applyState = GeoExt.MapPanel.prototype.applyState;
+ GeoExt.MapPanel.prototype.applyState = function(state) {
+ log = true;
+ };
+
+ // test
+
+ // test that applyState gets called when the MapPanel is created
+ // 1 test
+ log = false;
+ mapPanel = new GeoExt.MapPanel({
+ renderTo: "mappanel",
+ stateId: "map",
+ height: 400,
+ width: 600
+ });
+ t.eq(log, true, "applyState called when creating the MapPanel");
+
+ // tear down
+
+ GeoExt.MapPanel.prototype.applyState = applyState;
+ mapPanel.destroy();
+ }
+
+ function test_applyState(t) {
+ t.plan(21);
+
+ // set up
+
+ var state;
+
+ var layers = [
+ new OpenLayers.Layer("foo", {visibility: false}),
+ new OpenLayers.Layer("bar", {visibility: false})
+ ];
+ layers[0].id = "fooid";
+ layers[1].id = "barid";
+ var mapPanel = new GeoExt.MapPanel({
+ renderTo: "mappanel",
+ stateId: "map",
+ prettyStateKeys: true,
+ height: 400,
+ width: 600,
+ layers: layers
+ });
+
+ // test
+
+ // test with numeric and boolean state values
+ state = {
+ x: 5,
+ y: 45,
+ zoom: 10,
+ visibility_foo: true,
+ visibility_bar: true,
+ opacity_foo: 0.2,
+ opacity_bar: 0.5
+ };
+ mapPanel.applyState(state);
+ t.eq(mapPanel.center.lon, 5,
+ "mapPanel.center.lon correctly set [0]");
+ t.eq(mapPanel.center.lat, 45,
+ "mapPanel.center.lat correctly set [0]");
+ t.eq(mapPanel.zoom, 10,
+ "mapPanel.zoom correctly set [0]");
+ t.eq(layers[0].getVisibility(), true,
+ "layer foo visibility is correct [0]");
+ t.eq(layers[1].getVisibility(), true,
+ "layer bar visibility is correct [0]");
+ t.eq(layers[0].opacity, 0.2,
+ "layer foo opacity is correct [0]");
+ t.eq(layers[1].opacity, 0.5,
+ "layer bar opacity is correct [0]");
+
+ layers[0].visibility = false;
+ layers[1].visibility = false;
+ layers[0].opacity = null;
+ layers[1].opacity = null;
+
+ // test with string state values
+ state = {
+ x: "5",
+ y: "45",
+ zoom: "10",
+ visibility_foo: "true",
+ visibility_bar: "true",
+ opacity_foo: "0.2",
+ opacity_bar: "0.5"
+ };
+ mapPanel.applyState(state);
+ t.eq(mapPanel.center.lon, 5,
+ "mapPanel.center.lon correctly set [1]");
+ t.eq(mapPanel.center.lat, 45,
+ "mapPanel.center.lat correctly set [1]");
+ t.eq(mapPanel.zoom, "10",
+ "mapPanel.zoom correctly set [1]");
+ t.eq(layers[0].getVisibility(), true,
+ "layer foo visibility is correct [1]");
+ t.eq(layers[1].getVisibility(), true,
+ "layer bar visibility is correct [1]");
+ t.eq(layers[0].opacity, "0.2",
+ "layer foo opacity is correct [1]");
+ t.eq(layers[1].opacity, "0.5",
+ "layer bar opacity is correct [1]");
+
+ layers[0].visibility = false;
+ layers[1].visibility = false;
+ layers[0].opacity = null;
+ layers[1].opacity = null;
+
+ // test with prettyStateKeys set to false
+ mapPanel.prettyStateKeys = false;
+ state = {
+ x: "5",
+ y: "45",
+ zoom: "10",
+ visibility_fooid: "true",
+ visibility_barid: "true",
+ opacity_fooid: "0.2",
+ opacity_barid: "0.5"
+ };
+ mapPanel.applyState(state);
+ t.eq(mapPanel.center.lon, 5,
+ "mapPanel.center.lon correctly set [1]");
+ t.eq(mapPanel.center.lat, 45,
+ "mapPanel.center.lat correctly set [1]");
+ t.eq(mapPanel.zoom, "10",
+ "mapPanel.zoom correctly set [1]");
+ t.eq(layers[0].getVisibility(), true,
+ "layer foo visibility is correct [1]");
+ t.eq(layers[1].getVisibility(), true,
+ "layer bar visibility is correct [1]");
+ t.eq(layers[0].opacity, "0.2",
+ "layer foo opacity is correct [1]");
+ t.eq(layers[1].opacity, "0.5",
+ "layer bar opacity is correct [1]");
+
+ // tear down
+
+ mapPanel.destroy();
+ }
+
+ function test_getState_called(t) {
+ t.plan(2);
+
+ // set up
+
+ var getState, mapPanel, log;
+
+ getState = GeoExt.MapPanel.prototype.getState;
+ GeoExt.MapPanel.prototype.getState = function(state) {
+ log = true;
+ };
+
+ mapPanel = new GeoExt.MapPanel({
+ renderTo: "mappanel",
+ layers: [
+ new OpenLayers.Layer("foo")
+ ],
+ stateId: "map",
+ height: 400,
+ width: 600
+ });
+
+ // test
+
+ // test that getState gets called when the map is moved
+ // 1 test
+ log = false;
+ mapPanel.map.setCenter(new OpenLayers.LonLat(5, 45), 5);
+ t.delay_call(1, function() {
+ t.eq(log, true, "getState called when map is moved");
+ });
+
+ // test that getState gets called when layer visibility
+ // is changed
+ // 1 test
+ log = false;
+ mapPanel.map.layers[0].setVisibility(false);
+ t.delay_call(1, function() {
+ t.eq(log, true, "getState called when layer visibility is changed");
+
+ // tear down
+
+ GeoExt.MapPanel.prototype.getState = getState;
+ mapPanel.destroy();
+ });
+ }
+
+ function test_getState(t) {
+ t.plan(14);
+
+ // set up
+
+ var state;
+
+ // test
+
+ // test with prettyStateKeys set to true
+ var layers = [
+ new OpenLayers.Layer("foo", {visibility: true}),
+ new OpenLayers.Layer("bar", {visibility: false})
+ ];
+ layers[0].id = "fooid";
+ layers[1].id = "barid";
+ var mapPanel = new GeoExt.MapPanel({
+ renderTo: "mappanel",
+ prettyStateKeys: true,
+ stateId: "map",
+ height: 400,
+ width: 600,
+ layers: layers,
+ center: [5, 45],
+ zoom: 6
+ });
+ layers[0].setOpacity(0.5);
+
+ state = mapPanel.getState();
+ t.eq(state.x, 5,
+ "state.x correctly set");
+ t.eq(state.y, 45,
+ "state.y correctly set");
+ t.eq(state.zoom, 6,
+ "state.zoom correctly set");
+ t.eq(state.visibility_foo, true,
+ "state.visibility_foo correctly set");
+ t.eq(state.visibility_bar, false,
+ "state.visibility_bar correctly set");
+ t.eq(state.opacity_foo, 0.5,
+ "state.opacity_foo correctly set");
+ t.eq(state.opacity_bar, 1,
+ "state.opacity_bar correctly set");
+ mapPanel.destroy();
+
+ // test with prettyStateKeys set to false
+ var layers = [
+ new OpenLayers.Layer("foo", {visibility: true}),
+ new OpenLayers.Layer("bar", {visibility: false})
+ ];
+ layers[0].id = "fooid";
+ layers[1].id = "barid";
+ var mapPanel = new GeoExt.MapPanel({
+ renderTo: "mappanel",
+ prettyStateKeys: false,
+ stateId: "map",
+ height: 400,
+ width: 600,
+ layers: layers,
+ center: [5, 45],
+ zoom: 6
+ });
+ layers[0].setOpacity(0.5);
+
+ mapPanel.prettyStateKeys = false;
+ state = mapPanel.getState();
+ t.eq(state.x, 5,
+ "state.x correctly set");
+ t.eq(state.y, 45,
+ "state.y correctly set");
+ t.eq(state.zoom, 6,
+ "state.zoom correctly set");
+ t.eq(state.visibility_fooid, true,
+ "state.visibility_fooid correctly set");
+ t.eq(state.visibility_barid, false,
+ "state.visibility_barid correctly set");
+ t.eq(state.opacity_fooid, 0.5,
+ "state.opacity_fooid correctly set");
+ t.eq(state.opacity_barid, 1,
+ "state.opacity_barid correctly set");
+ mapPanel.destroy();
+ }
</script>
</head>
<body>
More information about the Commits
mailing list