[Commits] r1282 - in sandbox/elemoine/playground/geoext: . build examples lib lib/GeoExt lib/GeoExt/adapter lib/GeoExt/data lib/GeoExt/widgets lib/GeoExt/widgets/form lib/GeoExt/widgets/grid lib/GeoExt/widgets/tips lib/GeoExt/widgets/tree resources/css resources/images resources/images/slate tests tests/lib/GeoExt tests/lib/GeoExt/adapter tests/lib/GeoExt/data tests/lib/GeoExt/widgets tests/lib/GeoExt/widgets/grid tests/lib/GeoExt/widgets/tree

commits at geoext.org commits at geoext.org
Thu Jul 23 11:53:03 CEST 2009


Author: elemoine
Date: 2009-07-23 11:53:02 +0200 (Thu, 23 Jul 2009)
New Revision: 1282

Added:
   sandbox/elemoine/playground/geoext/build/Makefile
   sandbox/elemoine/playground/geoext/build/geoext-license.js
   sandbox/elemoine/playground/geoext/examples/layeropacityslider.html
   sandbox/elemoine/playground/geoext/examples/layeropacityslider.js
   sandbox/elemoine/playground/geoext/examples/mappanel-viewport.html
   sandbox/elemoine/playground/geoext/examples/mappanel-viewport.js
   sandbox/elemoine/playground/geoext/examples/zoomslider.html
   sandbox/elemoine/playground/geoext/examples/zoomslider.js
   sandbox/elemoine/playground/geoext/lib/GeoExt/adapter/
   sandbox/elemoine/playground/geoext/lib/GeoExt/adapter/override-ext-ajax.js
   sandbox/elemoine/playground/geoext/lib/GeoExt/data/WMSDescribeLayerReader.js
   sandbox/elemoine/playground/geoext/lib/GeoExt/data/WMSDescribeLayerStore.js
   sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/LayerOpacitySlider.js
   sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/ZoomSlider.js
   sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/grid/
   sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/grid/FeatureSelectionModel.js
   sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tips/
   sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tips/LayerOpacitySliderTip.js
   sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tips/SliderTip.js
   sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tips/ZoomSliderTip.js
   sandbox/elemoine/playground/geoext/resources/css/gxtheme-slate.css
   sandbox/elemoine/playground/geoext/resources/images/slate/
   sandbox/elemoine/playground/geoext/resources/images/slate/anchor.png
   sandbox/elemoine/playground/geoext/tests/lib/GeoExt/adapter/
   sandbox/elemoine/playground/geoext/tests/lib/GeoExt/adapter/override-ext-ajax.html
   sandbox/elemoine/playground/geoext/tests/lib/GeoExt/data/WMSDescribeLayerReader.html
   sandbox/elemoine/playground/geoext/tests/lib/GeoExt/data/WMSDescribeLayerReader.js
   sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/LayerOpacitySlider.html
   sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/LegendImage.html
   sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/LegendWMS.html
   sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/ZoomSlider.html
   sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/grid/
   sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/grid/FeatureSelectionModel.html
   sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/tree/BaseLayerContainer.html
Removed:
   sandbox/elemoine/playground/geoext/build/apidoc_config/
   sandbox/elemoine/playground/geoext/lib/GeoExt/adapter/override-ext-ajax.js
   sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/grid/FeatureSelectionModel.js
   sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tips/LayerOpacitySliderTip.js
   sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tips/SliderTip.js
   sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tips/ZoomSliderTip.js
   sandbox/elemoine/playground/geoext/resources/css/example.css
   sandbox/elemoine/playground/geoext/resources/images/slate/anchor.png
   sandbox/elemoine/playground/geoext/tests/lib/GeoExt/adapter/override-ext-ajax.html
   sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/grid/FeatureSelectionModel.html
Modified:
   sandbox/elemoine/playground/geoext/build/full.cfg
   sandbox/elemoine/playground/geoext/build/readme.txt
   sandbox/elemoine/playground/geoext/examples/feature-grid.html
   sandbox/elemoine/playground/geoext/examples/feature-grid.js
   sandbox/elemoine/playground/geoext/examples/layercontainer.html
   sandbox/elemoine/playground/geoext/examples/layercontainer.js
   sandbox/elemoine/playground/geoext/examples/legendpanel.html
   sandbox/elemoine/playground/geoext/examples/legendpanel.js
   sandbox/elemoine/playground/geoext/examples/mappanel-div.html
   sandbox/elemoine/playground/geoext/examples/mappanel-div.js
   sandbox/elemoine/playground/geoext/examples/mappanel-window.html
   sandbox/elemoine/playground/geoext/examples/mappanel-window.js
   sandbox/elemoine/playground/geoext/examples/popup.html
   sandbox/elemoine/playground/geoext/examples/popup.js
   sandbox/elemoine/playground/geoext/examples/search-form.html
   sandbox/elemoine/playground/geoext/examples/search-form.js
   sandbox/elemoine/playground/geoext/examples/toolbar.html
   sandbox/elemoine/playground/geoext/examples/toolbar.js
   sandbox/elemoine/playground/geoext/examples/tree.html
   sandbox/elemoine/playground/geoext/examples/tree.js
   sandbox/elemoine/playground/geoext/examples/wms-capabilities.html
   sandbox/elemoine/playground/geoext/examples/wms-capabilities.js
   sandbox/elemoine/playground/geoext/examples/zoom-chooser.html
   sandbox/elemoine/playground/geoext/examples/zoom-chooser.js
   sandbox/elemoine/playground/geoext/lib/GeoExt.js
   sandbox/elemoine/playground/geoext/lib/GeoExt/SingleFile.js
   sandbox/elemoine/playground/geoext/lib/GeoExt/data/FeatureReader.js
   sandbox/elemoine/playground/geoext/lib/GeoExt/data/FeatureRecord.js
   sandbox/elemoine/playground/geoext/lib/GeoExt/data/FeatureStore.js
   sandbox/elemoine/playground/geoext/lib/GeoExt/data/LayerReader.js
   sandbox/elemoine/playground/geoext/lib/GeoExt/data/LayerRecord.js
   sandbox/elemoine/playground/geoext/lib/GeoExt/data/LayerStore.js
   sandbox/elemoine/playground/geoext/lib/GeoExt/data/ProtocolProxy.js
   sandbox/elemoine/playground/geoext/lib/GeoExt/data/ScaleStore.js
   sandbox/elemoine/playground/geoext/lib/GeoExt/data/WMSCapabilitiesReader.js
   sandbox/elemoine/playground/geoext/lib/GeoExt/data/WMSCapabilitiesStore.js
   sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/Action.js
   sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/LegendImage.js
   sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/LegendPanel.js
   sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/LegendWMS.js
   sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/MapPanel.js
   sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/Popup.js
   sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/form.js
   sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/form/BasicForm.js
   sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/form/FormPanel.js
   sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/form/SearchAction.js
   sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tree/BaseLayerContainer.js
   sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tree/LayerContainer.js
   sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tree/LayerNode.js
   sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tree/OverlayLayerContainer.js
   sandbox/elemoine/playground/geoext/license.txt
   sandbox/elemoine/playground/geoext/resources/css/geoext-all-debug.css
   sandbox/elemoine/playground/geoext/resources/css/gxtheme-gray.css
   sandbox/elemoine/playground/geoext/resources/css/popup.css
   sandbox/elemoine/playground/geoext/tests/lib/GeoExt/data/LayerStore.html
   sandbox/elemoine/playground/geoext/tests/lib/GeoExt/data/ScaleStore.html
   sandbox/elemoine/playground/geoext/tests/lib/GeoExt/data/WMSCapabilitiesReader.html
   sandbox/elemoine/playground/geoext/tests/lib/GeoExt/data/WMSCapabilitiesReader.js
   sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/Action.html
   sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/LegendPanel.html
   sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/MapPanel.html
   sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/Popup.html
   sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/tree/LayerContainer.html
   sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/tree/LayerNode.html
   sandbox/elemoine/playground/geoext/tests/list-tests.html
Log:
svn merge -r876:HEAD http://svn.geoext.org/core/trunk/geoext .


Copied: sandbox/elemoine/playground/geoext/build/Makefile (from rev 1281, core/trunk/geoext/build/Makefile)
===================================================================
--- sandbox/elemoine/playground/geoext/build/Makefile	                        (rev 0)
+++ sandbox/elemoine/playground/geoext/build/Makefile	2009-07-23 09:53:02 UTC (rev 1282)
@@ -0,0 +1,71 @@
+# Makefile for GeoExt
+
+VERSION = r$(shell echo '$$Revision$$' | tr -d "[:alpha:]$$ :")
+LIB_NAME = GeoExt
+ZIP_NAME = $(LIB_NAME)-$(VERSION).zip
+
+CSS_DIR = $(LIB_NAME)/resources/css
+CSS_IMPORTS = $(shell cat ../resources/css/geoext-all-debug.css | grep '@import' | sed 's/^@import "\(.*\)";/\1/')
+ALL_CSS = $(CSS_DIR)/geoext-all.css
+
+.PHONEY: help clean ext examples lib zip dist
+
+help:
+	@echo "Please use 'make <target>' where <target> is one or more of"
+	@echo "  clean    to clean up after building"
+	@echo "  ext      to make a custom Ext JS build. See readme.txt for requirements"
+	@echo "  examples to make the examples dir"
+	@echo "  lib      to make a standalone dir of lib resources"
+	@echo "  zip      to make a zip archive of a standalone lib"
+	@echo "  dist     to make a zip archive of a standalone lib with examples"
+	@echo
+	@echo "Example use:"
+	@echo "  make lib"
+	@echo "  make lib LIB_NAME=MyLib"
+	@echo "  make zip"
+	@echo "  make zip ZIP_NAME=MyZip.zip"
+	@echo "  make dist VERSION=0.5-rc1"
+
+clean:
+	-rm -rf $(LIB_NAME)
+	-rm -f $(ZIP_NAME)
+
+ext:
+	@echo "Building ext.js."
+	mkdir -p $(LIB_NAME)/script
+	jsbuild full.cfg -v -o $(LIB_NAME)/script/ -s ext.js
+
+examples:
+	mkdir -p $(LIB_NAME)/examples 
+	rsync -au --exclude=.svn `pwd`/../examples `pwd`/$(LIB_NAME)
+	for file in `find $(LIB_NAME)/examples/ -name "*.html"`; do \
+	    sed -i "s/\.\.\/lib\/GeoExt\.js/\.\.\/script\/GeoExt\.js/g" $${file} ; \
+	    sed -i "s/geoext-all-debug\.css/geoext-all\.css/g" $${file} ; \
+	done ; 	
+
+lib:
+	@echo "Building the library."
+	mkdir -p $(LIB_NAME)/script $(LIB_NAME)/resources/css
+	
+	jsbuild full.cfg -v -o $(LIB_NAME)/script/ -s GeoExt.js
+	echo "GeoExt.VERSION_NUMBER='$(VERSION)';" >> $(LIB_NAME)/script/GeoExt.js 
+	
+	rsync -au --exclude=.svn `pwd`/../resources `pwd`/$(LIB_NAME)
+	
+	for file in `find $(CSS_DIR) -name "*.css"`; do \
+	    csstidy $${file} --template=highest $${file} ; \
+	done ;
+	echo "" > $(ALL_CSS)
+	for filename in $(CSS_IMPORTS); do \
+	    cat $(CSS_DIR)/$${filename} >> $(ALL_CSS) ; \
+	done ;
+	-rm $(CSS_DIR)/geoext-all-debug.css
+
+	cp ../license.txt $(LIB_NAME)
+
+zip: lib
+	@echo "Archiving the library."
+	-rm -f $(ZIP_NAME)
+	zip $(ZIP_NAME) -r $(LIB_NAME)
+
+dist: examples zip

Modified: sandbox/elemoine/playground/geoext/build/full.cfg
===================================================================
--- sandbox/elemoine/playground/geoext/build/full.cfg	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/build/full.cfg	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,5 +1,6 @@
 [GeoExt.js]
 root = ../lib
+license = geoext-license.js
 exclude =
     GeoExt.js
     GeoExt/SingleFile.js

Copied: sandbox/elemoine/playground/geoext/build/geoext-license.js (from rev 1281, core/trunk/geoext/build/geoext-license.js)
===================================================================
--- sandbox/elemoine/playground/geoext/build/geoext-license.js	                        (rev 0)
+++ sandbox/elemoine/playground/geoext/build/geoext-license.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -0,0 +1,30 @@
+/*
+
+Copyright (c) 2008-2009, The Open Source Geospatial Foundation
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Open Source Geospatial Foundation nor the names
+      of its contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+*/

Modified: sandbox/elemoine/playground/geoext/build/readme.txt
===================================================================
--- sandbox/elemoine/playground/geoext/build/readme.txt	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/build/readme.txt	2009-07-23 09:53:02 UTC (rev 1282)
@@ -2,23 +2,54 @@
 ===============
 
 This directory contains configuration files necessary for building GeoExt
-(and ExtJS).  The build configuration is intended for use with the jsbuild
+(and Ext JS).  The build configuration is intended for use with the jsbuild
 utility included in JSTools (http://projects.opengeo.org/jstools).
 
 Brief instructions
 ------------------
 
-Install JSTools.
+This build dir contains a Makefile, which can be used to build GeoExt. The
+build process requires a bash-like shell, make, sed, find and rsync. All this
+should be available on well equipped development *nix and OS X boxes. In
+addition, JSTools and csstidy are required. The latter is available as csstidy
+package on debian-style linux systems.
 
+    $ sudo aptitude install csstidy
+
+To install JSTools, python-setuptools is required. This is available as
+python-setuptools package on debian-style linux systems.
+
+    $ sudo aptitude install python-setuptools
+    
+Now you can easily install JSTools.
+
     $ easy_install http://svn.opengeo.org/jstools/trunk/
 
-Change into the core/trunk/build directory.
+Change into the core/trunk/build directory (the one containing the readme.txt
+file you are reading right now), if you are not already here.
 
-    $ cd core/trunk/geoext/build
+    $ cd geoext/build
 
-Run jsbuild.
+From here, you can build the library.
 
-    $ jsbuild full.cfg
+    $ make zip
     
-For more complete instructions on building GeoExt, see the documentation
-on the project website: http://www.geoext.org/trac/geoext/wiki/builds.
+Now you can take the resulting GeoExt.zip file and unpack it on your web
+server. The library itself resides in the script folder, the resources folder
+contains css files and images.
+
+For more complete instructions on building GeoExt with jsbuild, see the
+documentation on the project website:
+http://www.geoext.org/trac/geoext/wiki/builds.
+
+The Makefile also contains a target for building Ext JS. This requires Ext JS
+to be installed in ../../ext (relative to this build dir). Make sure to
+provide a license file matching your Ext JS installation and replace the
+provided ext-license.js file with it. To build the library with ext.js in the
+script folder, run make with the ext and zip targets.
+
+    $ make ext zip
+    
+The Makefile has even more targets. Invoke make help to see them all.
+
+    $ make help

Modified: sandbox/elemoine/playground/geoext/examples/feature-grid.html
===================================================================
--- sandbox/elemoine/playground/geoext/examples/feature-grid.html	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/examples/feature-grid.html	2009-07-23 09:53:02 UTC (rev 1282)
@@ -4,8 +4,8 @@
 
         <script type="text/javascript" src="http://extjs.cachefly.net/builds/ext-cdn-771.js"></script>
         <link rel="stylesheet" type="text/css" href="http://extjs.cachefly.net/ext-2.2.1/resources/css/ext-all.css" />
-        <link rel="stylesheet" type="text/css" href="http://extjs.com/deploy/dev/examples/shared/examples.css"></link>
-        <script src="http://openlayers.org/api/2.8-rc2/OpenLayers.js"></script>
+        <link rel="stylesheet" type="text/css" href="http://extjs.cachefly.net/ext-2.2.1/examples/shared/examples.css" />
+        <script src="http://openlayers.org/api/2.8/OpenLayers.js"></script>
         <script type="text/javascript" src="../lib/GeoExt.js"></script>
         
         <script type="text/javascript" src="feature-grid.js"></script>
@@ -18,8 +18,9 @@
         GeoJSON document (data/summits.json).</p>
         
         <p>Because the layer and the store are bound to each other, the
-        features loaded into the store are automatically added to the
-        layer.</p>
+        features loaded into the store are automatically added to the layer. A 
+        GeoExt feature selection model is also used so that selecting rows in 
+        the grid selects features in the layer, and vice-versa.</p> 
 
         <p>See <a href=feature-grid.js>feature-grid.js</a>.</p>
 

Modified: sandbox/elemoine/playground/geoext/examples/feature-grid.js
===================================================================
--- sandbox/elemoine/playground/geoext/examples/feature-grid.js	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/examples/feature-grid.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,4 +1,10 @@
-Ext.BLANK_IMAGE_URL = "../../../../ext/resources/images/default/s.gif"
+/**
+ * Copyright (c) 2008-2009 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.
+ */
 
 var mapPanel, store, gridPanel, mainPanel;
 
@@ -56,7 +62,8 @@
             header: "Elevation",
             width: 100,
             dataIndex: "elevation"
-        }]
+        }],
+        sm: new GeoExt.grid.FeatureSelectionModel() 
     });
 
     // create a panel and add the map panel and grid panel

Modified: sandbox/elemoine/playground/geoext/examples/layercontainer.html
===================================================================
--- sandbox/elemoine/playground/geoext/examples/layercontainer.html	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/examples/layercontainer.html	2009-07-23 09:53:02 UTC (rev 1282)
@@ -4,8 +4,8 @@
 
         <script type="text/javascript" src="http://extjs.cachefly.net/builds/ext-cdn-771.js"></script>
         <link rel="stylesheet" type="text/css" href="http://extjs.cachefly.net/ext-2.2.1/resources/css/ext-all.css" />
-        <link rel="stylesheet" type="text/css" href="http://extjs.com/deploy/dev/examples/shared/examples.css"></link>
-        <script src="http://openlayers.org/api/2.8-rc2/OpenLayers.js"></script>
+        <link rel="stylesheet" type="text/css" href="http://extjs.cachefly.net/ext-2.2.1/examples/shared/examples.css" />
+        <script src="http://openlayers.org/api/2.8/OpenLayers.js"></script>
         <script type="text/javascript" src="../lib/GeoExt.js"></script>
 
         <script type="text/javascript" src="layercontainer.js"></script>

Modified: sandbox/elemoine/playground/geoext/examples/layercontainer.js
===================================================================
--- sandbox/elemoine/playground/geoext/examples/layercontainer.js	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/examples/layercontainer.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,3 +1,11 @@
+/**
+ * Copyright (c) 2008-2009 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.
+ */
+
 var store, tree, panel;
 Ext.onReady(function() {
     

Copied: sandbox/elemoine/playground/geoext/examples/layeropacityslider.html (from rev 1281, core/trunk/geoext/examples/layeropacityslider.html)
===================================================================
--- sandbox/elemoine/playground/geoext/examples/layeropacityslider.html	                        (rev 0)
+++ sandbox/elemoine/playground/geoext/examples/layeropacityslider.html	2009-07-23 09:53:02 UTC (rev 1282)
@@ -0,0 +1,31 @@
+<html>
+    <head>
+        <title>GeoExt LayerOpacitySlider</title>
+
+        <script type="text/javascript" src="http://extjs.cachefly.net/builds/ext-cdn-771.js"></script>
+        <link rel="stylesheet" type="text/css" href="http://extjs.cachefly.net/ext-2.2.1/resources/css/ext-all.css" />
+        <link rel="stylesheet" type="text/css" href="http://extjs.com/deploy/dev/examples/shared/examples.css"></link>
+        <script src="http://openlayers.org/api/2.8/OpenLayers.js"></script>
+        <script type="text/javascript" src="../lib/GeoExt.js"></script>
+
+        <script type="text/javascript" src="layeropacityslider.js"></script>
+    </head>
+    <body>
+        <h1>GeoExt.LayerOpacitySlider</h1>
+
+        <p>The LayerOpacitySlider allows control of a layer opacity using an
+        Ext.Slider.  It is also possible to add a special tooltip plugin,
+        LayerOpacitySliderTip, which will show the opacity value while dragging
+        the slider (the content is configurable).<p>
+
+        <p>In this example, the slider below the map is in aggressive mode: the
+        opacity is changed as soon as the slider is moved. The slider into the
+        map is not aggressive: the opacity is changed when the slider is
+        released.</p>
+
+        <p>The js is not minified so it is readable. See <a
+        href="layeropacityslider.js">layeropacityslider.js</a>.</p>
+
+        <div id="map-container"></div>
+    </body>
+</html>

Copied: sandbox/elemoine/playground/geoext/examples/layeropacityslider.js (from rev 1281, core/trunk/geoext/examples/layeropacityslider.js)
===================================================================
--- sandbox/elemoine/playground/geoext/examples/layeropacityslider.js	                        (rev 0)
+++ sandbox/elemoine/playground/geoext/examples/layeropacityslider.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -0,0 +1,50 @@
+/**
+ * Copyright (c) 2008-2009 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.
+ */
+
+var panel, wms, slider;
+
+Ext.onReady(function() {
+    
+    wms = new OpenLayers.Layer.WMS(
+        "Global Imagery",
+        "http://demo.opengeo.org/geoserver/wms",
+        {layers: 'bluemarble'}
+    );
+
+    // create a map panel with an embedded slider
+    panel = new GeoExt.MapPanel({
+        title: "Map",
+        renderTo: "map-container",
+        height: 300,
+        width: 400,
+        map: {
+            controls: [new OpenLayers.Control.Navigation()]
+        },
+        layers: [wms],
+        extent: [-5, 35, 15, 55],
+        items: [{
+            xtype: "gx_opacityslider",
+            layer: wms,
+            vertical: true,
+            height: 120,
+            x: 10,
+            y: 10,
+            plugins: new GeoExt.LayerOpacitySliderTip()
+        }]
+    });
+    
+    // create a separate slider bound to the map but displayed elsewhere
+    slider = new GeoExt.LayerOpacitySlider({
+        layer: wms,
+        aggressive: true, 
+        width: 200,
+        isFormField: true,
+        fieldLabel: "opacity",
+        renderTo: document.body
+    });
+});

Modified: sandbox/elemoine/playground/geoext/examples/legendpanel.html
===================================================================
--- sandbox/elemoine/playground/geoext/examples/legendpanel.html	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/examples/legendpanel.html	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,10 +1,10 @@
 <html>
     <head>
-        <script type="text/javascript" src="http://dev.geoext.org/trunk/ext/adapter/ext/ext-base.js"></script>
-        <script type="text/javascript" src="http://dev.geoext.org/trunk/ext/ext-all.js"></script>
+        <script type="text/javascript" src="http://extjs.cachefly.net/ext-2.2.1/adapter/ext/ext-base.js"></script>
+        <script type="text/javascript" src="http://extjs.cachefly.net/ext-2.2.1/ext-all.js"></script>
         <link rel="stylesheet" type="text/css" href="http://extjs.cachefly.net/ext-2.2.1/resources/css/ext-all.css" />
-        <link rel="stylesheet" type="text/css" href="http://extjs.com/deploy/dev/examples/shared/examples.css"></link>
-        <script src="http://openlayers.org/api/2.8-rc2/OpenLayers.js"></script>
+        <link rel="stylesheet" type="text/css" href="http://extjs.cachefly.net/ext-2.2.1/examples/shared/examples.css" />
+        <script src="http://openlayers.org/api/2.8/OpenLayers.js"></script>
         <script type="text/javascript" src="../lib/GeoExt.js"></script>
 
         <script type="text/javascript" src="legendpanel.js"></script>

Modified: sandbox/elemoine/playground/geoext/examples/legendpanel.js
===================================================================
--- sandbox/elemoine/playground/geoext/examples/legendpanel.js	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/examples/legendpanel.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,3 +1,10 @@
+/**
+ * Copyright (c) 2008-2009 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.
+ */
 
 var mapPanel;
 
@@ -6,12 +13,12 @@
     map.addLayers([
         new OpenLayers.Layer.WMS(
             "Tasmania",
-            "http://publicus.opengeo.org/geoserver/wms?",
+            "http://demo.opengeo.org/geoserver/wms?",
             {layers: 'topp:tasmania_state_boundaries', format: 'image/png', transparent: true},
             {singleTile: true}),
         new OpenLayers.Layer.WMS(
             "Cities and Roads",
-            "http://publicus.opengeo.org/geoserver/wms?",
+            "http://demo.opengeo.org/geoserver/wms?",
             {layers: 'topp:tasmania_cities,topp:tasmania_roads', format: 'image/png', transparent: true},
             {singleTile: true}),
         new OpenLayers.Layer.Vector('Polygons', {styleMap: new OpenLayers.StyleMap({
@@ -26,7 +33,7 @@
 
     var addLayer = function() {
         var wmslayer = new OpenLayers.Layer.WMS("Bodies of Water",
-            "http://publicus.opengeo.org/geoserver/wms?",
+            "http://demo.opengeo.org/geoserver/wms?",
             {layers: 'topp:tasmania_water_bodies', format: 'image/png', transparent: true},
             {singleTile: true});
         mapPanel.map.addLayer(wmslayer);

Modified: sandbox/elemoine/playground/geoext/examples/mappanel-div.html
===================================================================
--- sandbox/elemoine/playground/geoext/examples/mappanel-div.html	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/examples/mappanel-div.html	2009-07-23 09:53:02 UTC (rev 1282)
@@ -4,8 +4,8 @@
 
         <script type="text/javascript" src="http://extjs.cachefly.net/builds/ext-cdn-771.js"></script>
         <link rel="stylesheet" type="text/css" href="http://extjs.cachefly.net/ext-2.2.1/resources/css/ext-all.css" />
-        <link rel="stylesheet" type="text/css" href="http://extjs.com/deploy/dev/examples/shared/examples.css"></link>
-        <script src="http://openlayers.org/api/2.8-rc2/OpenLayers.js"></script>
+        <link rel="stylesheet" type="text/css" href="http://extjs.cachefly.net/ext-2.2.1/examples/shared/examples.css" />
+        <script src="http://openlayers.org/api/2.8/OpenLayers.js"></script>
         <script type="text/javascript" src="../lib/GeoExt.js"></script>
 
         <script type="text/javascript" src="mappanel-div.js"></script>

Modified: sandbox/elemoine/playground/geoext/examples/mappanel-div.js
===================================================================
--- sandbox/elemoine/playground/geoext/examples/mappanel-div.js	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/examples/mappanel-div.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,3 +1,10 @@
+/**
+ * Copyright (c) 2008-2009 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.
+ */
 
 var mapPanel;
 
@@ -4,8 +11,8 @@
 Ext.onReady(function() {
     var map = new OpenLayers.Map();
     var layer = new OpenLayers.Layer.WMS(
-        "bluemarble",
-        "http://sigma.openplans.org/geoserver/wms?",
+        "Global Imagery",
+        "http://demo.opengeo.org/geoserver/wms",
         {layers: 'bluemarble'}
     );
     map.addLayer(layer);

Added: sandbox/elemoine/playground/geoext/examples/mappanel-viewport.html
===================================================================
--- sandbox/elemoine/playground/geoext/examples/mappanel-viewport.html	                        (rev 0)
+++ sandbox/elemoine/playground/geoext/examples/mappanel-viewport.html	2009-07-23 09:53:02 UTC (rev 1282)
@@ -0,0 +1,34 @@
+<html>
+    <head>
+        <title>GeoExt MapPanel in an Ext Viewport</title>
+
+        <script type="text/javascript" src="http://extjs.cachefly.net/builds/ext-cdn-771.js"></script>
+        <link rel="stylesheet" type="text/css" href="http://extjs.cachefly.net/ext-2.2.1/resources/css/ext-all.css" />
+        <link rel="stylesheet" type="text/css" href="http://extjs.cachefly.net/ext-2.2.1/examples/shared/examples.css" />
+        <!-- Google Maps API for "localhost" -->
+        <!--
+        <script src='http://maps.google.com/maps?file=api&amp;v=2&amp;key=ABQIAAAAjpkAC9ePGem0lIq5XcMiuhR_wWLPFku8Ix9i2SXYRVK3e45q1BQUd_beF8dtzKET_EteAjPdGDwqpQ'></script>
+        -->
+        <!-- Google Maps API for "dev.geoext.org" -->
+        <script src='http://maps.google.com/maps?file=api&amp;v=2&amp;key=ABQIAAAA_5ak-hsiH4j5bQQn7-k66xTWxvN8zH6Ta_pgIhhU0TB7bG8iAhS99ituPif4lG-2CHXoZ3qenLnK1g'></script>
+        <script src="http://openlayers.org/api/2.8/OpenLayers.js"></script>
+        <script type="text/javascript" src="../lib/GeoExt.js"></script>
+        
+        <script type="text/javascript" src="mappanel-viewport.js"></script>
+
+    </head>
+    <body>
+        <div id="title">
+            <h1>GeoExt.MapPanel in an Ext.Viewport</h1>
+        </div>
+
+        <div id="description">
+            <p>This example shows how to place a MapPanel as a region in a
+            container using a border layout, the container is a Viewport in
+            this example.</p>
+            
+            <p>The js is not minified so it is readable. See <a
+            href="mappanel-viewport.js">mappanel-viewport.js</a>.</p>
+        </div>
+    </body>
+</html>

Added: sandbox/elemoine/playground/geoext/examples/mappanel-viewport.js
===================================================================
--- sandbox/elemoine/playground/geoext/examples/mappanel-viewport.js	                        (rev 0)
+++ sandbox/elemoine/playground/geoext/examples/mappanel-viewport.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -0,0 +1,76 @@
+/**
+ * Copyright (c) 2008-2009 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.
+ */
+
+var mapPanel;
+
+Ext.onReady(function() {
+
+    // if true a google layer is used, if false
+    // the bluemarble WMS layer is used
+    var google = false;
+
+    var options, layer;
+    var extent = new OpenLayers.Bounds(-5, 35, 15, 55);
+
+    if (google) {
+
+        options = {
+            projection: new OpenLayers.Projection("EPSG:900913"),
+            units: "m",
+            numZoomLevels: 18,
+            maxResolution: 156543.0339,
+            maxExtent: new OpenLayers.Bounds(-20037508, -20037508,
+                                             20037508, 20037508.34)
+        };
+
+        layer = new OpenLayers.Layer.Google(
+            "Google Satellite",
+            {type: G_SATELLITE_MAP, sphericalMercator: true}
+        );
+
+        extent.transform(
+            new OpenLayers.Projection("EPSG:4326"), options.projection
+        );
+
+    } else {
+        layer = new OpenLayers.Layer.WMS(
+            "Global Imagery",
+            "http://demo.opengeo.org/geoserver/wms",
+            {layers: 'bluemarble'},
+            {isBaseLayer: true}
+        );
+    }
+
+    var map = new OpenLayers.Map(options);
+
+    new Ext.Viewport({
+        layout: "border",
+        items: [{
+            region: "north",
+            contentEl: "title",
+            height: 50
+        }, {
+            region: "center",
+            id: "mappanel",
+            title: "Map",
+            xtype: "gx_mappanel",
+            map: map,
+            layers: [layer],
+            extent: extent,
+            split: true
+        }, {
+            region: "east",
+            title: "Description",
+            contentEl: "description",
+            width: 200,
+            split: true
+        }]
+    });
+
+    mapPanel = Ext.getCmp("mappanel");
+});

Modified: sandbox/elemoine/playground/geoext/examples/mappanel-window.html
===================================================================
--- sandbox/elemoine/playground/geoext/examples/mappanel-window.html	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/examples/mappanel-window.html	2009-07-23 09:53:02 UTC (rev 1282)
@@ -4,8 +4,8 @@
 
         <script type="text/javascript" src="http://extjs.cachefly.net/builds/ext-cdn-771.js"></script>
         <link rel="stylesheet" type="text/css" href="http://extjs.cachefly.net/ext-2.2.1/resources/css/ext-all.css" />
-        <link rel="stylesheet" type="text/css" href="http://extjs.com/deploy/dev/examples/shared/examples.css"></link>
-        <script src="http://openlayers.org/api/2.8-rc2/OpenLayers.js"></script>
+        <link rel="stylesheet" type="text/css" href="http://extjs.cachefly.net/ext-2.2.1/examples/shared/examples.css" />
+        <script src="http://openlayers.org/api/2.8/OpenLayers.js"></script>
         <script type="text/javascript" src="../lib/GeoExt.js"></script>
         
         <script type="text/javascript" src="mappanel-window.js"></script>

Modified: sandbox/elemoine/playground/geoext/examples/mappanel-window.js
===================================================================
--- sandbox/elemoine/playground/geoext/examples/mappanel-window.js	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/examples/mappanel-window.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,3 +1,11 @@
+/**
+ * Copyright (c) 2008-2009 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.
+ */
+
 var mapPanel;
 
 Ext.onReady(function() {
@@ -10,8 +18,8 @@
             xtype: "gx_mappanel",
             id: "mappanel",
             layers: [new OpenLayers.Layer.WMS(
-                "bluemarble",
-                "http://sigma.openplans.org/geoserver/wms?",
+                "Global Imagery",
+                "http://demo.opengeo.org/geoserver/wms",
                 {layers: 'bluemarble'}
             )],
             extent: "-5,35,15,55"

Modified: sandbox/elemoine/playground/geoext/examples/popup.html
===================================================================
--- sandbox/elemoine/playground/geoext/examples/popup.html	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/examples/popup.html	2009-07-23 09:53:02 UTC (rev 1282)
@@ -4,9 +4,9 @@
 
         <script type="text/javascript" src="http://extjs.cachefly.net/builds/ext-cdn-771.js"></script>
         <link rel="stylesheet" type="text/css" href="http://extjs.cachefly.net/ext-2.2.1/resources/css/ext-all.css" />
-        <link rel="stylesheet" type="text/css" href="http://extjs.com/deploy/dev/examples/shared/examples.css"></link>
+        <link rel="stylesheet" type="text/css" href="http://extjs.cachefly.net/ext-2.2.1/examples/shared/examples.css" />
         <link rel="stylesheet" type="text/css" href="../resources/css/geoext-all-debug.css" />
-        <script src="http://openlayers.org/api/2.8-rc2/OpenLayers.js"></script>
+        <script src="http://openlayers.org/api/2.8/OpenLayers.js"></script>
         <script type="text/javascript" src="../lib/GeoExt.js"></script>
         
         <script type="text/javascript" src="popup.js"></script>

Modified: sandbox/elemoine/playground/geoext/examples/popup.js
===================================================================
--- sandbox/elemoine/playground/geoext/examples/popup.js	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/examples/popup.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,3 +1,11 @@
+/**
+ * Copyright (c) 2008-2009 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.
+ */
+
 // make the references to the map panel and the popup 
 // global, this is useful for looking at their states
 // from the console
@@ -36,7 +44,7 @@
                 }
             }
         });
-        mapPanel.add(popup);
+        popup.show();
     }
 
     // create popup on "featureselected"

Modified: sandbox/elemoine/playground/geoext/examples/search-form.html
===================================================================
--- sandbox/elemoine/playground/geoext/examples/search-form.html	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/examples/search-form.html	2009-07-23 09:53:02 UTC (rev 1282)
@@ -2,8 +2,8 @@
     <head>
         <script type="text/javascript" src="http://extjs.cachefly.net/builds/ext-cdn-771.js"></script>
         <link rel="stylesheet" type="text/css" href="http://extjs.cachefly.net/ext-2.2.1/resources/css/ext-all.css" />
-        <link rel="stylesheet" type="text/css" href="http://extjs.com/deploy/dev/examples/shared/examples.css"></link>
-        <script src="http://openlayers.org/api/2.8-rc2/OpenLayers.js"></script>
+        <link rel="stylesheet" type="text/css" href="http://extjs.cachefly.net/ext-2.2.1/examples/shared/examples.css" />
+        <script src="http://openlayers.org/api/2.8/OpenLayers.js"></script>
         <script type="text/javascript" src="../lib/GeoExt.js"></script>
 
         <script type="text/javascript" src="search-form.js"></script>

Modified: sandbox/elemoine/playground/geoext/examples/search-form.js
===================================================================
--- sandbox/elemoine/playground/geoext/examples/search-form.js	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/examples/search-form.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,3 +1,10 @@
+/**
+ * Copyright (c) 2008-2009 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.
+ */
 
 var formPanel;
 

Modified: sandbox/elemoine/playground/geoext/examples/toolbar.html
===================================================================
--- sandbox/elemoine/playground/geoext/examples/toolbar.html	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/examples/toolbar.html	2009-07-23 09:53:02 UTC (rev 1282)
@@ -3,18 +3,9 @@
         <title>GeoExt Toolbar Example</title>
 
         <script type="text/javascript" src="http://extjs.cachefly.net/builds/ext-cdn-771.js"></script>
-        <!--
-        <script type="text/javascript" src="../../ext/adapter/ext/ext-base.js"></script>
-        <script type="text/javascript" src="../../ext/ext-all-debug.js"></script>
-        <link rel="stylesheet" type="text/css" href="../../ext/resources/css/ext-all.css" />
-        <link rel="stylesheet" type="text/css" href="../../ext/examples/shared/examples.css"></link>
-        -->
         <link rel="stylesheet" type="text/css" href="http://extjs.cachefly.net/ext-2.2.1/resources/css/ext-all.css" />
-        <link rel="stylesheet" type="text/css" href="http://extjs.com/deploy/dev/examples/shared/examples.css"></link>
-        <script src="http://openlayers.org/api/2.8-rc2/OpenLayers.js"></script>
-        <!--
-        <script src="../../openlayers/lib/OpenLayers.js"></script>
-        -->
+        <link rel="stylesheet" type="text/css" href="http://extjs.cachefly.net/ext-2.2.1/examples/shared/examples.css" />
+        <script src="http://openlayers.org/api/2.8/OpenLayers.js"></script>
         <script type="text/javascript" src="../lib/GeoExt.js"></script>
 
         <script type="text/javascript" src="toolbar.js"></script>
@@ -40,9 +31,8 @@
         <h1>OpenLayers controls in an Ext toolbar</h1>
 
         <p>This example shows how to add OpenLayers controls in an Ext toolbar.
-        GeoExt provides the GeoExt.Action.fromControl method for adapating a
-        control to an object that can be inserted in a toolbar or in a
-        menu.</p>
+        GeoExt provides the GeoExt.Action class for adapating a control to an
+        object that can be inserted in a toolbar or in a menu.</p>
 
         <p>The js is not minified so it is readable. See <a
         href="toolbar.js">toolbar.js</a>.</p>

Modified: sandbox/elemoine/playground/geoext/examples/toolbar.js
===================================================================
--- sandbox/elemoine/playground/geoext/examples/toolbar.js	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/examples/toolbar.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,3 +1,10 @@
+/**
+ * Copyright (c) 2008-2009 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.
+ */
 
 Ext.onReady(function() {
     var map = new OpenLayers.Map();
@@ -2,4 +9,4 @@
     var wms = new OpenLayers.Layer.WMS(
-        "bluemarble",
-        "http://sigma.openplans.org/geoserver/wms?",
+        "Global Imagery",
+        "http://demo.opengeo.org/geoserver/wms",
         {layers: 'bluemarble'}
@@ -12,21 +19,21 @@
     var ctrl, toolbarItems = [], action, actions = {};
 
     // ZoomToMaxExtent control, a "button" control
-    ctrl = new OpenLayers.Control.ZoomToMaxExtent();
-    map.addControl(ctrl);
-    action = GeoExt.Action.fromControl(ctrl, {
+    action = new GeoExt.Action({
+        control: new OpenLayers.Control.ZoomToMaxExtent(),
+        map: map,
         text: "max extent"
-    })
+    });
     actions["max_extent"] = action;
     toolbarItems.push(action);
     toolbarItems.push("-");
 
     // Navigation control and DrawFeature controls
     // in the same toggle group
-    ctrl = new OpenLayers.Control.Navigation();
-    map.addControl(ctrl);
-    action = GeoExt.Action.fromControl(ctrl, {
+    action = new GeoExt.Action({
         text: "nav",
+        control: new OpenLayers.Control.Navigation(),
+        map: map,
         // button options
         toggleGroup: "draw",
         allowDepress: false,
@@ -37,12 +44,13 @@
     });
     actions["nav"] = action;
     toolbarItems.push(action);
-    ctrl = new OpenLayers.Control.DrawFeature(
-        vector, OpenLayers.Handler.Polygon
-    );
-    map.addControl(ctrl);
-    action = GeoExt.Action.fromControl(ctrl, {
+
+    action = new GeoExt.Action({
         text: "draw poly",
+        control: new OpenLayers.Control.DrawFeature(
+            vector, OpenLayers.Handler.Polygon
+        ),
+        map: map,
         // button options
         toggleGroup: "draw",
         allowDepress: false,
@@ -51,12 +59,13 @@
     });
     actions["draw_poly"] = action;
     toolbarItems.push(action);
-    ctrl = new OpenLayers.Control.DrawFeature(
-        vector, OpenLayers.Handler.Path
-    );
-    map.addControl(ctrl);
-    action = GeoExt.Action.fromControl(ctrl, {
+
+    action = new GeoExt.Action({
         text: "draw line",
+        control: new OpenLayers.Control.DrawFeature(
+            vector, OpenLayers.Handler.Path
+        ),
+        map: map,
         // button options
         toggleGroup: "draw",
         allowDepress: false,
@@ -68,13 +77,13 @@
     toolbarItems.push("-");
 
     // SelectFeature control, a "toggle" control
-    ctrl = new OpenLayers.Control.SelectFeature(vector, {
-        type: OpenLayers.Control.TYPE_TOGGLE,
-        hover: true
-    });
-    map.addControl(ctrl);
-    action = GeoExt.Action.fromControl(ctrl, {
+    action = new GeoExt.Action({
         text: "select",
+        control: new OpenLayers.Control.SelectFeature(vector, {
+            type: OpenLayers.Control.TYPE_TOGGLE,
+            hover: true
+        }),
+        map: map,
         // button options
         enableToggle: true
     });
@@ -85,14 +94,18 @@
     // Navigation history - two "button" controls
     ctrl = new OpenLayers.Control.NavigationHistory();
     map.addControl(ctrl);
-    action = GeoExt.Action.fromControl(ctrl.previous, {
+
+    action = new GeoExt.Action({
         text: "previous",
+        control: ctrl.previous,
         disabled: true
     });
     actions["previous"] = action;
     toolbarItems.push(action);
-    action = GeoExt.Action.fromControl(ctrl.next, {
+
+    action = new GeoExt.Action({
         text: "next",
+        control: ctrl.next,
         disabled: true
     });
     actions["next"] = action;

Modified: sandbox/elemoine/playground/geoext/examples/tree.html
===================================================================
--- sandbox/elemoine/playground/geoext/examples/tree.html	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/examples/tree.html	2009-07-23 09:53:02 UTC (rev 1282)
@@ -4,8 +4,8 @@
         
         <script type="text/javascript" src="http://extjs.cachefly.net/builds/ext-cdn-771.js"></script>
         <link rel="stylesheet" type="text/css" href="http://extjs.cachefly.net/ext-2.2.1/resources/css/ext-all.css" />
-        <link rel="stylesheet" type="text/css" href="http://extjs.com/deploy/dev/examples/shared/examples.css"></link>
-        <script src="http://openlayers.org/api/2.8-rc2/OpenLayers.js"></script>
+        <link rel="stylesheet" type="text/css" href="http://extjs.cachefly.net/ext-2.2.1/examples/shared/examples.css" />
+        <script src="http://openlayers.org/api/2.8/OpenLayers.js"></script>
         <script type="text/javascript" src="../lib/GeoExt.js"></script>
 
         <script type="text/javascript" src="tree.js"></script>

Modified: sandbox/elemoine/playground/geoext/examples/tree.js
===================================================================
--- sandbox/elemoine/playground/geoext/examples/tree.js	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/examples/tree.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,3 +1,11 @@
+/**
+ * Copyright (c) 2008-2009 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.
+ */
+
 var mapPanel;
 Ext.onReady(function() {
     // using OpenLayers.Format.JSON to create a nice formatted string of the
@@ -24,8 +32,8 @@
         center: [146.1569825, -41.6109735],
         zoom: 6,
         layers: [
-            new OpenLayers.Layer.WMS("Blue Marble",
-                "http://sigma.openplans.org/geoserver/wms", {
+            new OpenLayers.Layer.WMS("Global Imagery",
+                "http://demo.opengeo.org/geoserver/wms", {
                     layers: "bluemarble"
                 }, {
                     buffer: 0,

Modified: sandbox/elemoine/playground/geoext/examples/wms-capabilities.html
===================================================================
--- sandbox/elemoine/playground/geoext/examples/wms-capabilities.html	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/examples/wms-capabilities.html	2009-07-23 09:53:02 UTC (rev 1282)
@@ -2,10 +2,11 @@
     <head>
         <title>GeoExt WMS Capabilities Example</title>
 
+        <link rel="stylesheet" type="text/css" href="http://extjs.cachefly.net/ext-2.2.1/resources/css/ext-all.css" />
+        <link rel="stylesheet" type="text/css" href="http://extjs.cachefly.net/ext-2.2.1/examples/shared/examples.css" />
         <script type="text/javascript" src="http://extjs.cachefly.net/builds/ext-cdn-771.js"></script>
-        <link rel="stylesheet" type="text/css" href="http://extjs.cachefly.net/ext-2.2.1/resources/css/ext-all.css" />
-        <link rel="stylesheet" type="text/css" href="http://extjs.com/deploy/dev/examples/shared/examples.css"></link>
-        <script src="http://openlayers.org/api/2.8-rc2/OpenLayers.js"></script>
+        <script type="text/javascript" src="../lib/GeoExt/adapter/override-ext-ajax.js"></script>
+        <script src="http://openlayers.org/api/2.8/OpenLayers.js"></script>
         <script type="text/javascript" src="../lib/GeoExt.js"></script>
         
         <script type="text/javascript" src="wms-capabilities.js"></script>

Modified: sandbox/elemoine/playground/geoext/examples/wms-capabilities.js
===================================================================
--- sandbox/elemoine/playground/geoext/examples/wms-capabilities.js	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/examples/wms-capabilities.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,3 +1,11 @@
+/**
+ * Copyright (c) 2008-2009 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.
+ */
+
 var store;
 Ext.onReady(function() {
     
@@ -30,12 +38,12 @@
     function mapPreview(grid, index) {
         var record = grid.getStore().getAt(index);
         var layer = record.get("layer").clone();
-        layer.isBaseLayer = true; // default is false
         
         var win = new Ext.Window({
             title: "Preview: " + record.get("title"),
             width: 512,
             height: 256,
+            layout: "fit",
             items: [{
                 xtype: "gx_mappanel",
                 layers: [layer],

Modified: sandbox/elemoine/playground/geoext/examples/zoom-chooser.html
===================================================================
--- sandbox/elemoine/playground/geoext/examples/zoom-chooser.html	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/examples/zoom-chooser.html	2009-07-23 09:53:02 UTC (rev 1282)
@@ -4,8 +4,8 @@
 
         <script type="text/javascript" src="http://extjs.cachefly.net/builds/ext-cdn-771.js"></script>
         <link rel="stylesheet" type="text/css" href="http://extjs.cachefly.net/ext-2.2.1/resources/css/ext-all.css" />
-        <link rel="stylesheet" type="text/css" href="http://extjs.com/deploy/dev/examples/shared/examples.css"></link>
-        <script src="http://openlayers.org/api/2.8-rc2/OpenLayers.js"></script>
+        <link rel="stylesheet" type="text/css" href="http://extjs.cachefly.net/ext-2.2.1/examples/shared/examples.css" />
+        <script src="http://openlayers.org/api/2.8/OpenLayers.js"></script>
         <script type="text/javascript" src="../lib/GeoExt.js"></script>
         
         <script type="text/javascript" src="zoom-chooser.js"></script>

Modified: sandbox/elemoine/playground/geoext/examples/zoom-chooser.js
===================================================================
--- sandbox/elemoine/playground/geoext/examples/zoom-chooser.js	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/examples/zoom-chooser.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,3 +1,10 @@
+/**
+ * Copyright (c) 2008-2009 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.
+ */
 
 var mapPanel;
 
@@ -4,8 +11,8 @@
 Ext.onReady(function() {
     var map = new OpenLayers.Map();
     var layer = new OpenLayers.Layer.WMS(
-        "bluemarble",
-        "http://sigma.openplans.org/geoserver/wms?",
+        "Global Imagery",
+        "http://demo.opengeo.org/geoserver/wms",
         {layers: 'bluemarble'}
     );
     map.addLayer(layer);

Copied: sandbox/elemoine/playground/geoext/examples/zoomslider.html (from rev 1281, core/trunk/geoext/examples/zoomslider.html)
===================================================================
--- sandbox/elemoine/playground/geoext/examples/zoomslider.html	                        (rev 0)
+++ sandbox/elemoine/playground/geoext/examples/zoomslider.html	2009-07-23 09:53:02 UTC (rev 1282)
@@ -0,0 +1,22 @@
+<html>
+    <head>
+        <title>GeoExt ZoomSlider</title>
+
+        <script type="text/javascript" src="http://extjs.cachefly.net/builds/ext-cdn-771.js"></script>
+        <link rel="stylesheet" type="text/css" href="http://extjs.cachefly.net/ext-2.2.1/resources/css/ext-all.css" />
+        <link rel="stylesheet" type="text/css" href="http://extjs.cachefly.net/ext-2.2.1/examples/shared/examples.css" />
+        <script src="http://openlayers.org/api/2.8/OpenLayers.js"></script>
+        <script type="text/javascript" src="../lib/GeoExt.js"></script>
+
+        <script type="text/javascript" src="zoomslider.js"></script>
+    </head>
+    <body>
+        <h1>GeoExt.ZoomSlider</h1>
+        <p>The ZoomSlider allows control of the map scale using an Ext.Slider.
+        It is also possible to add a special tooltip plugin, ZoomSliderTip, which
+        will show the zoom level, scale and resolution while dragging the slider
+        (the content is configurable).<p>
+        <p>The js is not minified so it is readable. See <a href="zoomslider.js">zoomslider.js</a>.</p>
+        <div id="map-container"></div>
+    </body>
+</html>

Copied: sandbox/elemoine/playground/geoext/examples/zoomslider.js (from rev 1281, core/trunk/geoext/examples/zoomslider.js)
===================================================================
--- sandbox/elemoine/playground/geoext/examples/zoomslider.js	                        (rev 0)
+++ sandbox/elemoine/playground/geoext/examples/zoomslider.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -0,0 +1,49 @@
+/**
+ * Copyright (c) 2008-2009 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.
+ */
+
+var panel, slider;
+
+Ext.onReady(function() {
+    
+    // create a map panel with an embedded slider
+    panel = new GeoExt.MapPanel({
+        title: "Map",
+        renderTo: "map-container",
+        height: 300,
+        width: 400,
+        map: {
+            controls: [new OpenLayers.Control.Navigation()]
+        },
+        layers: [new OpenLayers.Layer.WMS(
+            "Global Imagery",
+            "http://demo.opengeo.org/geoserver/wms",
+            {layers: 'bluemarble'}
+        )],
+        extent: [-5, 35, 15, 55],
+        items: [{
+            xtype: "gx_zoomslider",
+            vertical: true,
+            height: 100,
+            x: 10,
+            y: 20,
+            plugins: new GeoExt.ZoomSliderTip()
+        }]
+    });
+    
+    // create a separate slider bound to the map but displayed elsewhere
+    slider = new GeoExt.ZoomSlider({
+        map: panel.map,
+        aggressive: true,                                                                                                                                                   
+        width: 200,
+        plugins: new GeoExt.ZoomSliderTip({
+            template: "<div>Zoom Level: {zoom}</div>"
+        }),
+        renderTo: document.body
+    });
+
+});

Modified: sandbox/elemoine/playground/geoext/lib/GeoExt/SingleFile.js
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt/SingleFile.js	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/SingleFile.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,20 +1,9 @@
-/*
- * Copyright (C) 2007-2008  Camptocamp, OpenGeo
- *
- * This file is part of GeoExt
- *
- * GeoExt 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.
- *
- * GeoExt 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 GeoExt.  If not, see <http://www.gnu.org/licenses/>.
+/**
+ * Copyright (c) 2008-2009 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.
  */
 
 Ext.namespace("GeoExt");

Copied: sandbox/elemoine/playground/geoext/lib/GeoExt/adapter (from rev 1281, core/trunk/geoext/lib/GeoExt/adapter)

Deleted: sandbox/elemoine/playground/geoext/lib/GeoExt/adapter/override-ext-ajax.js
===================================================================
--- core/trunk/geoext/lib/GeoExt/adapter/override-ext-ajax.js	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/adapter/override-ext-ajax.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,80 +0,0 @@
-/**
- * Copyright (c) 2008-2009 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.
- */
-
-/** api: (define)
- *  module = Ext.lib.Ajax
- */
-
-(function() {
-
-    /** private: function[createComplete]
-     *  ``Function``
-     */
-    var createComplete = function(fn, cb) {
-        return function(request) {
-            if(cb && cb[fn]) {
-                cb[fn].call(cb.scope || window, {
-                    responseText: request.responseText,
-                    responseXML: request.responseXML,
-                    argument: cb.argument
-                });
-            }
-        };
-    };
-
-    Ext.apply(Ext.lib.Ajax, {
-        /** private: method[request]
-         */
-        request: function(method, uri, cb, data, options) {
-            options = options || {};
-            var hs = options.headers;
-            if(options.xmlData) {
-                if(!hs || !hs["Content-Type"]) {
-                    hs = hs || {};
-                    hs["Content-Type"] = "text/xml";
-                }
-                method = (method ? method :
-                    (options.method ? options.method : "POST"));
-                data = options.xmlData;
-            } else if(options.jsonData) {
-                if(!hs || !hs["Content-Type"]) {
-                    hs = hs || {};
-                    hs["Content-Type"] = "application/json";
-                }
-                method = (method ? method :
-                    (options.method ? options.method : "POST"));
-                data = typeof options.jsonData == "object" ?
-                       Ext.encode(options.jsonData) : options.jsonData;
-            }
-            return OpenLayers.Request.issue({
-                success: createComplete("success", cb),
-                failure: createComplete("failure", cb),
-                headers: options.headers,
-                method: method,
-                headers: hs,
-                data: data,
-                url: uri
-            });
-        },
-
-        /** private: method[isCallInProgress]
-         *  :params request: ``Object`` The XHR object.
-         */
-        isCallInProgress: function(request) {
-            // do not prevent our caller from calling abort()
-            return true;
-        },
-
-        /** private: method[abort]
-         *  :params request: ``Object`` The XHR object.
-         */
-        abort: function(request) {
-            request.abort();
-        }
-    });
-})();

Copied: sandbox/elemoine/playground/geoext/lib/GeoExt/adapter/override-ext-ajax.js (from rev 1281, core/trunk/geoext/lib/GeoExt/adapter/override-ext-ajax.js)
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt/adapter/override-ext-ajax.js	                        (rev 0)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/adapter/override-ext-ajax.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -0,0 +1,80 @@
+/**
+ * Copyright (c) 2008-2009 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.
+ */
+
+/** api: (define)
+ *  module = Ext.lib.Ajax
+ */
+
+(function() {
+
+    /** private: function[createComplete]
+     *  ``Function``
+     */
+    var createComplete = function(fn, cb) {
+        return function(request) {
+            if(cb && cb[fn]) {
+                cb[fn].call(cb.scope || window, {
+                    responseText: request.responseText,
+                    responseXML: request.responseXML,
+                    argument: cb.argument
+                });
+            }
+        };
+    };
+
+    Ext.apply(Ext.lib.Ajax, {
+        /** private: method[request]
+         */
+        request: function(method, uri, cb, data, options) {
+            options = options || {};
+            var hs = options.headers;
+            if(options.xmlData) {
+                if(!hs || !hs["Content-Type"]) {
+                    hs = hs || {};
+                    hs["Content-Type"] = "text/xml";
+                }
+                method = (method ? method :
+                    (options.method ? options.method : "POST"));
+                data = options.xmlData;
+            } else if(options.jsonData) {
+                if(!hs || !hs["Content-Type"]) {
+                    hs = hs || {};
+                    hs["Content-Type"] = "application/json";
+                }
+                method = (method ? method :
+                    (options.method ? options.method : "POST"));
+                data = typeof options.jsonData == "object" ?
+                       Ext.encode(options.jsonData) : options.jsonData;
+            }
+            return OpenLayers.Request.issue({
+                success: createComplete("success", cb),
+                failure: createComplete("failure", cb),
+                headers: options.headers,
+                method: method,
+                headers: hs,
+                data: data,
+                url: uri
+            });
+        },
+
+        /** private: method[isCallInProgress]
+         *  :params request: ``Object`` The XHR object.
+         */
+        isCallInProgress: function(request) {
+            // do not prevent our caller from calling abort()
+            return true;
+        },
+
+        /** private: method[abort]
+         *  :params request: ``Object`` The XHR object.
+         */
+        abort: function(request) {
+            request.abort();
+        }
+    });
+})();

Modified: sandbox/elemoine/playground/geoext/lib/GeoExt/data/FeatureReader.js
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt/data/FeatureReader.js	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/data/FeatureReader.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,20 +1,9 @@
-/*
- * Copyright (C) 2008 Eric Lemoine, Camptocamp France SAS
- *
- * This file is part of GeoExt
- *
- * GeoExt 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.
- *
- * GeoExt 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 GeoExt.  If not, see <http://www.gnu.org/licenses/>.
+/**
+ * Copyright (c) 2008-2009 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.
  */
 
 /**

Modified: sandbox/elemoine/playground/geoext/lib/GeoExt/data/FeatureRecord.js
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt/data/FeatureRecord.js	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/data/FeatureRecord.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,9 +1,10 @@
-/* Copyright (C) 2008-2009 The Open Source Geospatial Foundation
+/**
+ * Copyright (c) 2008-2009 The Open Source Geospatial Foundation
+ * 
  * Published under the BSD license.
- * See http://geoext.org/svn/geoext/core/trunk/license.txt for the full text
+ * See http://svn.geoext.org/core/trunk/geoext/license.txt for the full text
  * of the license.
- * 
- * pending approval */
+ */
 
 /** api: (define)
  *  module = GeoExt.data
@@ -27,18 +28,14 @@
     {name: "feature"}, {name: "state"}, {name: "fid"}
 ]);
 
-/**
- * APIFunction: GeoExt.data.FeatureRecord.create
- * Creates a constructor for a FeatureRecord, optionally with additional
- * fields.
- * 
- * Parameters:
- * o - {Array} Field definition as in {Ext.data.Record.create}. Can be omitted
- *     if no additional fields are required (records will always have fields
- *     {OpenLayers.Feature} "feature", {String} "state" and {String} "fid".
- *
- * Returns:
- * {Function} A specialized {<GeoExt.data.FeatureRecord>} constructor.
+/** api: classmethod[create]
+ *  :param o: ``Array`` Field definition as in ``Ext.data.Record.create``. Can
+ *      be omitted if no additional fields are required.
+ *  :return: ``Function`` A specialized :class:`GeoExt.data.FeatureRecord`
+ *      constructor.
+ *  
+ *  Creates a constructor for a :class:`GeoExt.data.FeatureRecord`, optionally
+ *  with additional fields.
  */
 GeoExt.data.FeatureRecord.create = function(o) {
     var f = Ext.extend(GeoExt.data.FeatureRecord, {});

Modified: sandbox/elemoine/playground/geoext/lib/GeoExt/data/FeatureStore.js
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt/data/FeatureStore.js	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/data/FeatureStore.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,9 +1,10 @@
-/* Copyright (C) 2008-2009 The Open Source Geospatial Foundation ¹
+/**
+ * Copyright (c) 2008-2009 The Open Source Geospatial Foundation
+ * 
  * Published under the BSD license.
- * See http://geoext.org/svn/geoext/core/trunk/license.txt for the full text
+ * See http://svn.geoext.org/core/trunk/geoext/license.txt for the full text
  * of the license.
- * 
- * ¹ pending approval */
+ */
 
 /**
  * @include GeoExt/data/FeatureReader.js

Modified: sandbox/elemoine/playground/geoext/lib/GeoExt/data/LayerReader.js
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt/data/LayerReader.js	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/data/LayerReader.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,38 +1,40 @@
-/* Copyright (C) 2008-2009 The Open Source Geospatial Foundation
+/**
+ * Copyright (c) 2008-2009 The Open Source Geospatial Foundation
+ * 
  * Published under the BSD license.
- * See http://geoext.org/svn/geoext/core/trunk/license.txt for the full text
+ * See http://svn.geoext.org/core/trunk/geoext/license.txt for the full text
  * of the license.
- * 
- * ¹ pending approval */
+ */
 
 /**
  * @include GeoExt/data/LayerRecord.js
  */
 
+/** api: (define)
+ *  module = GeoExt.data
+ *  class = LayerReader
+ *  base_link = `Ext.data.DataReader <http://extjs.com/deploy/dev/docs/?class=Ext.data.DataReader>`_
+ */
 Ext.namespace("GeoExt", "GeoExt.data");
 
-/**
- * Class: GeoExt.data.LayerReader
- *      LayerReader is a specific Ext.data.DataReader for converting
- *      layers into layer records, i.e. {OpenLayers.Layer} objects
- *      into {GeoExt.data.LayerRecor} objects.
- *
- * Usage example:
- * (start code)
- *         var reader = new GeoExt.data.LayerReader();
- *         var layerData = reader.readRecords(map.layers);
- *         var numRecords = layerData.totalRecords;
- *         var layerRecords = layerData.records;
- * (end)
- *
- * Inherits from:
- *  - {Ext.data.DataReader}
+/** api: example
+ *  Sample using a reader to create records from an array of layers:
+ * 
+ *  .. code-block:: javascript
+ *     
+ *      var reader = new GeoExt.data.LayerReader();
+ *      var layerData = reader.readRecords(map.layers);
+ *      var numRecords = layerData.totalRecords;
+ *      var layerRecords = layerData.records;
  */
 
-/**
- * Constructor: GeoExt.data.LayerReader
- *      Create a layer reader. The arguments passed are similar to those
- *      passed to {Ext.data.DataReader} constructor.
+/** api: constructor
+ *  .. class:: LayerReader(meta, recordType)
+ *  
+ *      Data reader class to create an array of
+ *      :class:`GeoExt.data.LayerRecord` objects from an array of 
+ *      ``OpenLayers.Layer`` objects for use in a
+ *      :class:`GeoExt.data.LayerStore` object.
  */
 GeoExt.data.LayerReader = function(meta, recordType) {
     meta = meta || {};
@@ -46,24 +48,19 @@
 
 Ext.extend(GeoExt.data.LayerReader, Ext.data.DataReader, {
 
-    /**
-     * APIProperty: totalRecords
-     * {Integer}
+    /** private: property[totalRecords]
+     *  ``Integer``
      */
     totalRecords: null,
 
-    /**
-     * APIMethod: readRecords
-     *      From an array of {OpenLayers.Layer} objects create a data block
-     *      containing {<GeoExt.data.LayerRecord>} objects.
-     *
-     * Parameters:
-     * layers - {Array({OpenLayers.Layer})} Array of layers.
-     *
-     * Returns:
-     * {Object} An object with two properties. The value of the property "records"
-     *      is the array of layer records. The value of the property "totalRecords"
-     *      is the number of records in the array.
+    /** api: method[readRecords]
+     *  :param layers: ``Array(OpenLayers.Layer)`` List of layers for creating
+     *      records.
+     *  :return: ``Object``  An object with ``records`` and ``totalRecords``
+     *      properties.
+     *  
+     *  From an array of ``OpenLayers.Layer`` objects create a data block
+     *  containing :class:`GeoExt.data.LayerRecord` objects.
      */
     readRecords : function(layers) {
         var records = [];

Modified: sandbox/elemoine/playground/geoext/lib/GeoExt/data/LayerRecord.js
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt/data/LayerRecord.js	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/data/LayerRecord.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,46 +1,40 @@
-/* Copyright (C) 2008-2009 The Open Source Geospatial Foundation
+/**
+ * Copyright (c) 2008-2009 The Open Source Geospatial Foundation
+ * 
  * Published under the BSD license.
- * See http://geoext.org/svn/geoext/core/trunk/license.txt for the full text
+ * See http://svn.geoext.org/core/trunk/geoext/license.txt for the full text
  * of the license.
- * 
- * pending approval */
+ */
 
+/** api: (define)
+ *  module = GeoExt.data
+ *  class = LayerRecord
+ *  base_link = `Ext.data.Record <http://extjs.com/deploy/dev/docs/?class=Ext.data.Record>`_
+ */
 Ext.namespace("GeoExt.data");
 
-/**
- * Class: GeoExt.data.LayerRecord
- * A subclass of {Ext.data.Record} which provides a special record that
- * represents an {OpenLayers.Layer}. This record will always have at least a
- * layer and a title field in its data. The id of this record will be the same
- * as the id of the layer it represents.
- * 
- * Inherits from
- * - {Ext.data.Record}
+/** api: constructor
+ *  .. class:: LayerRecord
+ *  
+ *      A record that represents an ``OpenLayers.Layer``. This record
+ *      will always have at least the following fields:
+ *
+ *      * layer ``OpenLayers.Layer``
+ *      * title ``String``
  */
-/**
- * Constructor: GeoExt.data.LayerRecord
- * 
- * Parameters:
- * data - {Object} data object for the record
- * id - {String} id of the record
- */
 GeoExt.data.LayerRecord = Ext.data.Record.create([
     {name: "layer"},
     {name: "title", type: "string", mapping: "name"}
 ]);
 
-/**
- * APIFunction: GeoExt.data.LayerRecord.create
- * Creates a constructor for a LayerRecord, optionally with additional
- * fields.
- * 
- * Parameters:
- * o - {Array} Field definition as in {Ext.data.Record.create}. Can be omitted
- *     if no additional fields are required (records will always have a
- *     {OpenLayers.Layer} layer and a {String} title field).
- *
- * Returns:
- * {Function} A specialized {<GeoExt.data.LayerRecord>} constructor.
+/** api: classmethod[create]
+ *  :param o: ``Array`` Field definition as in ``Ext.data.Record.create``. Can
+ *      be omitted if no additional fields are required.
+ *  :return: ``Function`` A specialized :class:`GeoExt.data.LayerRecord`
+ *      constructor.
+ *  
+ *  Creates a constructor for a :class:`GeoExt.data.LayerRecord`, optionally
+ *  with additional fields.
  */
 GeoExt.data.LayerRecord.create = function(o) {
     var f = Ext.extend(GeoExt.data.LayerRecord, {});

Modified: sandbox/elemoine/playground/geoext/lib/GeoExt/data/LayerStore.js
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt/data/LayerStore.js	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/data/LayerStore.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,77 +1,91 @@
-/* Copyright (C) 2008-2009 The Open Source Geospatial Foundation ¹
+/**
+ * Copyright (c) 2008-2009 The Open Source Geospatial Foundation
+ * 
  * Published under the BSD license.
- * See http://geoext.org/svn/geoext/core/trunk/license.txt for the full text
+ * See http://svn.geoext.org/core/trunk/geoext/license.txt for the full text
  * of the license.
- * 
- * ¹ pending approval */
+ */
 
 /**
  * @include GeoExt/data/LayerReader.js
  */
 
+/** api: (define)
+ *  module = GeoExt.data
+ *  class = LayerStore
+ *  base_link = `Ext.data.DataStore <http://extjs.com/deploy/dev/docs/?class=Ext.data.DataStore>`_
+ */
 Ext.namespace("GeoExt.data");
 
-/**
- * Class: GeoExt.data.LayerStoreMixin
- * A store that synchronizes a layers array of an {OpenLayers.Map} with a
- * layer store holding {<GeoExt.data.LayerRecord>} entries.
+/** private: constructor
+ *  .. class:: LayerStoreMixin
+ *      A store that synchronizes a layers array of an {OpenLayers.Map} with a
+ *      layer store holding {<GeoExt.data.LayerRecord>} entries.
  * 
- * This class can not be instantiated directly. Instead, it is meant to extend
- * {Ext.data.Store} or a subclass of it:
- * (start code)
- * var store = new (Ext.extend(Ext.data.Store, GeoExt.data.LayerStoreMixin))({
- *     map: myMap,
- *     layers: myLayers
- * });
- * (end)
+ *      This class can not be instantiated directly. Instead, it is meant to
+ *      extend ``Ext.data.Store`` or a subclass of it.
+ */
+
+/** private: example
+ *  Sample code to extend a store with the LayerStoreMixin.
+ *
+ *  .. code-block:: javascript
+ *  
+ *      var store = new (Ext.extend(Ext.data.Store, GeoExt.data.LayerStoreMixin))({
+ *          map: myMap,
+ *          layers: myLayers
+ *      });
  * 
- * For convenience, a {<GeoExt.data.LayerStore>} class is available as a
- * shortcut to the Ext.extend sequence in the above code snippet. The above
- * is equivalent to:
- * (start code)
- * var store = new GeoExt.data.LayerStore({
- *     map: myMap,
- *     layers: myLayers
- * });
- * (end)
+ *  For convenience, a :class:`GeoExt.data.LayerStore` class is available as a
+ *  shortcut to the ``Ext.extend`` sequence in the above code snippet.
  */
+
 GeoExt.data.LayerStoreMixin = {
-    /**
-     * APIProperty: map
-     * {OpenLayers.Map} Map that this store will be in sync with.
+
+    /** api: config[map]
+     *  ``OpenLayers.Map``
+     *  Map that this store will be in sync with.
      */
+    
+    /** api: property[map]
+     *  ``OpenLayers.Map``
+     *  Map that the store is synchronized with.
+     */
     map: null,
+    
+    /** api: config[layers]
+     *  ``Array(OpenLayers.Layer)``
+     *  Layers that will be added to the store (and the map, depending on the
+     *  value of the ``initDir`` option.
+     */
+    
+    /** api: config[initDir]
+     *  ``Number``
+     *  Bitfields specifying the direction to use for the initial sync between
+     *  the map and the store, if set to 0 then no initial sync is done.
+     *  Defaults to ``GeoExt.data.LayerStore.MAP_TO_STORE|GeoExt.data.LayerStore.STORE_TO_MAP``
+     */
 
-    /**
-     * APIProperty: reader
-     * {<GeoExt.data.LayerReader>} The reader used to get
-     *     <GeoExt.data.LayerRecord> objects from {OpenLayers.Layer}
-     *     objects.
+    /** api: config[fields]
+     *  ``Array``
+     *  If provided a custom layer record type with additional fields will be
+     *  used. Default fields for every layer record are `layer`
+     *  (``OpenLayers.Layer``) `title` (``String``). The value of this option is
+     *  either a field definition objects as passed to the
+     *  :meth:`GeoExt.data.LayerRecord.create` function or a
+     *  :class:`GeoExt.data.LayerRecord` constructor created using
+     *  :meth:`GeoExt.data.LayerRecord.create`.
      */
+
+    /** api: config[reader]
+     *  ``Ext.data.DataReader`` The reader used to produce
+     *  :class:`GeoExt.data.LayerRecord` objects from ``OpenLayers.Layer``
+     *  objects.  If not provided, a :class:`GeoExt.data.LayerReader` will be
+     *  used.
+     */
     reader: null,
 
-    /**
-     * Constructor: GeoExt.data.LayerStoreMixin
-     * 
-     * Parameters:
-     * config - {Object}
-     * 
-     * Valid config options:
-     * map - {OpenLayers.Map|<GeoExt.MapPanel>} map to sync the layer store
-     *     with.
-     * layers - {Array(OpenLayers.Layer)} Layers that will be added to the
-     *     store (and the map, depending on the value of the initDir option).
-     * fields - {Array} If provided a custom layer record type with additional
-     *     fields will be used. Default fields for every layer record are
-     *     {OpenLayers.Layer} layer and {String} title. The value of this
-     *     option is either a field definition objects as passed to the
-     *     GeoExt.data.LayerRecord.create function or a
-     *     {<GeoExt.data.LayerRecord>} constructor created using
-     *     GeoExt.data.LayerRecord.create.
-     * initDir - {Number} Bitfields specifying the direction to use for the
-     *     initial sync between the map and the store, if set to 0 then no
-     *     initial sync is done. Defaults to
-     *     <GeoExt.data.LayerStore.MAP_TO_STORE>|<GeoExt.data.LayerStore.STORE_TO_MAP>.
+    /** private: method[constructor]
      */
     constructor: function(config) {
         config = config || {};
@@ -96,20 +110,12 @@
         }
     },
 
-    /**
-     * APIMethod: bind
-     * Bind this store to a map instance, once bound the store
-     * is synchronized with the map and vice-versa.
-     * 
-     * Parameters:
-     * map - {OpenLayers.Map} The map instance.
-     * options - {Object}
-     *
-     * Valid config options:
-     * initDir - {Number} Bitfields specifying the direction to use for the
-     *     initial sync between the map and the store, if set to 0 then no
-     *     initial sync is done. Defaults to
-     *     <GeoExt.data.LayerStore.MAP_TO_STORE>|<GeoExt.data.LayerStore.STORE_TO_MAP>.
+    /** private: method[bind]
+     *  :param map: ``OpenLayers.Map`` The map instance.
+     *  :param options: ``Object``
+     *  
+     *  Bind this store to a map instance, once bound the store
+     *  is synchronized with the map and vice-versa.
      */
     bind: function(map, options) {
         if(this.map) {
@@ -129,10 +135,9 @@
         var layers = map.layers.slice(0);
 
         if(initDir & GeoExt.data.LayerStore.STORE_TO_MAP) {
-            var records = this.getRange();
-            for(var i=records.length - 1; i>=0; i--) {
-                this.map.addLayer(records[i].get("layer"));
-            }
+            this.each(function(record) {
+                this.map.addLayer(record.get("layer"));
+            }, this);
         }
         if(initDir & GeoExt.data.LayerStore.MAP_TO_STORE) {
             this.loadData(layers, true);
@@ -149,6 +154,7 @@
             "clear": this.onClear,
             "add": this.onAdd,
             "remove": this.onRemove,
+            "update": this.onUpdate,
             scope: this
         });
         this.data.on({
@@ -157,9 +163,8 @@
         });
     },
 
-    /**
-     * APIMethod: unbind
-     * Unbind this store from the map it is currently bound.
+    /** private: method[unbind]
+     *  Unbind this store from the map it is currently bound.
      */
     unbind: function() {
         if(this.map) {
@@ -180,13 +185,11 @@
         }
     },
     
-    /**
-     * Method: onChangeLayer
-     * Handler for layer changes.  When layer order changes, this moves the
-     *     appropriate record within the store.
-     *
-     * Parameters:
-     * evt - {Object}
+    /** private: method[onChangeLayer]
+     *  :param evt: ``Object``
+     * 
+     *  Handler for layer changes.  When layer order changes, this moves the
+     *  appropriate record within the store.
      */
     onChangeLayer: function(evt) {
         var layer = evt.layer;
@@ -207,18 +210,18 @@
                         delete this._adding;
                     }
                 }
+            } else if(evt.property === "name") {
+                record.set("title", layer.name);
             } else {
                 this.fireEvent("update", this, record, Ext.data.Record.EDIT);
             }
         }
     },
    
-    /**
-     * Method: onAddLayer
-     * Handler for a map's addlayer event
-     * 
-     * Parameters:
-     * evt - {Object}
+    /** private: method[onAddLayer]
+     *  :param evt: ``Object``
+     *  
+     *  Handler for a map's addlayer event
      */
     onAddLayer: function(evt) {
         if(!this._adding) {
@@ -229,30 +232,33 @@
         }
     },
     
-    /**
-     * Method: onRemoveLayer
-     * Handler for a map's removelayer event
+    /** private: method[onRemoveLayer]
+     *  :param evt: ``Object``
      * 
-     * Parameters:
-     * evt - {Object}
+     *  Handler for a map's removelayer event
      */
     onRemoveLayer: function(evt){
-        if(!this._removing) {
-            var layer = evt.layer;
-            this._removing = true;
-            this.remove(this.getById(layer.id));
-            delete this._removing;
+        //TODO replace the check for undloadDestroy with a listener for the
+        // map's beforedestroy event, doing unbind(). This can be done as soon
+        // as http://trac.openlayers.org/ticket/2136 is fixed.
+        if(this.map.unloadDestroy) {
+            if(!this._removing) {
+                var layer = evt.layer;
+                this._removing = true;
+                this.remove(this.getById(layer.id));
+                delete this._removing;
+            }
+        } else {
+            this.unbind();
         }
     },
     
-    /**
-     * Method: onLoad
-     * Handler for a store's load event
+    /** private: method[onLoad]
+     *  :param store: ``Ext.data.Store``
+     *  :param records: ``Array(Ext.data.Record)``
+     *  :param options: ``Object``
      * 
-     * Parameters:
-     * store - {<Ext.data.Store>}
-     * records - {Array(Ext.data.Record)}
-     * options - {Object}
+     *  Handler for a store's load event
      */
     onLoad: function(store, records, options) {
         if (!Ext.isArray(records)) {
@@ -279,12 +285,10 @@
         }
     },
     
-    /**
-     * Method: onClear
-     * Handler for a store's clear event
+    /** private: method[onClear]
+     *  :param store: ``Ext.data.Store``
      * 
-     * Parameters:
-     * store - {<Ext.data.Store>}
+     *  Handler for a store's clear event
      */
     onClear: function(store) {
         this._removing = true;
@@ -294,14 +298,12 @@
         delete this._removing;
     },
     
-    /**
-     * Method: onAdd
-     * Handler for a store's add event
+    /** private: method[onAdd]
+     *  :param store: ``Ext.data.Store``
+     *  :param records: ``Array(Ext.data.Record)``
+     *  :param index: ``Number``
      * 
-     * Parameters:
-     * store - {<Ext.data.Store>}
-     * records - {Array(Ext.data.Record)}
-     * index - {Number}
+     *  Handler for a store's add event
      */
     onAdd: function(store, records, index) {
         if(!this._adding) {
@@ -318,14 +320,12 @@
         }
     },
     
-    /**
-     * Method: onRemove
-     * Handler for a store's remove event
+    /** private: method[onRemove]
+     *  :param store: ``Ext.data.Store``
+     *  :param record: ``Ext.data.Record``
+     *  :param index: ``Number``
      * 
-     * Parameters:
-     * store - {<Ext.data.Store>}
-     * records - {Array(Ext.data.Record)}
-     * index - {Number}
+     *  Handler for a store's remove event
      */
     onRemove: function(store, record, index){
         if(!this._removing) {
@@ -337,48 +337,71 @@
             }
         }
     },
-
-    /**
-     * Method: removeMapLayers
-     * Removes a record's layer from the bound map.
+    
+    /** private: method[onUpdate]
+     *  :param store: ``Ext.data.Store``
+     *  :param record: ``Ext.data.Record``
+     *  :param operation: ``Number``
      * 
-     * Parameters:
-     * record - {<Ext.data.Record>}
+     *  Handler for a store's update event
      */
+    onUpdate: function(store, record, operation) {
+        if(operation === Ext.data.Record.EDIT) {
+            var layer = record.get("layer");
+            var title = record.get("title");
+            if(title !== layer.name) {
+                layer.setName(title);
+            }
+        }
+    },
+
+    /** private: method[removeMapLayer]
+     *  :param record: ``Ext.data.Record``
+     *  
+     *  Removes a record's layer from the bound map.
+     */
     removeMapLayer: function(record){
         this.map.removeLayer(record.get("layer"));
     },
 
-    /**
-     * Method: onReplace
-     * Handler for a store's data collections' replace event
-     * 
-     * Parameters:
-     * key - {String}
-     * oldRecord - {Object} In this case, a record that has been replaced.
-     * newRecord - {Object} In this case, a record that is replacing oldRecord.
+    /** private: method[onReplace]
+     *  :param key: ``String``
+     *  :param oldRecord: ``Object`` In this case, a record that has been
+     *      replaced.
+     *  :param newRecord: ``Object`` In this case, a record that is replacing
+     *      oldRecord.
+
+     *  Handler for a store's data collections' replace event
      */
     onReplace: function(key, oldRecord, newRecord){
         this.removeMapLayer(oldRecord);
+    },
+    
+    /** private: method[destroy]
+     */
+    destroy: function() {
+        this.unbind();
+        GeoExt.data.LayerStore.superclass.destroy.call(this);
     }
 };
 
-/**
- * Class: GeoExt.data.LayerStore
- * Default implementation of an {Ext.data.Store} extended with
- * {<GeoExt.data.LayerStoreMixin>}
- * 
- * Inherits from:
- * - {Ext.data.Store}
- * - {<GeoExt.data.LayerStoreMixin>}
+/** api: example
+ *  Sample to create a new store containing a cache of
+ *  :class:`GeoExt.data.LayerRecord` instances derived from map layers.
+ *
+ *  .. code-block:: javascript
+ *  
+ *      var store = new GeoExt.data.LayerStore({
+ *          map: myMap,
+ *          layers: myLayers
+ *      });
  */
-/**
- * Constructor: GeoExt.data.LayerStore
- * 
- * Parameters:
- * config - {Object} See {<GeoExt.data.LayerStoreMixin>} and 
- * http://extjs.com/deploy/dev/docs/?class=Ext.data.Store for valid config
- *     options. 
+
+/** api: constructor
+ *  .. class:: LayerStore
+ *
+ *      A store that contains a cache of :class:`GeoExt.data.LayerRecord`
+ *      objects.
  */
 GeoExt.data.LayerStore = Ext.extend(
     Ext.data.Store,

Modified: sandbox/elemoine/playground/geoext/lib/GeoExt/data/ProtocolProxy.js
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt/data/ProtocolProxy.js	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/data/ProtocolProxy.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,75 +1,62 @@
-/*
- * Copyright (C) 2008 Eric Lemoine, Camptocamp France SAS
- *
- * This file is part of GeoExt
- *
- * GeoExt 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.
- *
- * GeoExt 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 GeoExt.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-Ext.namespace('GeoExt', 'GeoExt.data');
-
 /**
- * Class: GeoExt.data.ProtocolProxy
+ * Copyright (c) 2008-2009 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.
  */
 
-/**
- * Constructor: GeoExt.data.ProtocolProxy
- *
- * Parameters:
- * config - {Object} Config object
+/** api: (define)
+ *  module = GeoExt.data
+ *  class = ProtocolProxy
+ *  base_link = `Ext.data.DataProxy <http://extjs.com/deploy/dev/docs/?class=Ext.data.DataProxy>`_
  */
+Ext.namespace('GeoExt', 'GeoExt.data');
+
 GeoExt.data.ProtocolProxy = function(config) {
     GeoExt.data.ProtocolProxy.superclass.constructor.call(this);
     Ext.apply(this, config);
 };
 
+/** api: constructor
+ *  .. class:: ProtocolProxy
+ *   
+ *      A data proxy for use with ``OpenLayers.Protocol`` objects.
+ */
 Ext.extend(GeoExt.data.ProtocolProxy, Ext.data.DataProxy, {
-    /**
-     * APIProperty: protocol
-     * {<OpenLayers.Protocol>} The protocol used to fetch features.
+
+    /** api: config[protocol]
+     *  ``OpenLayers.Protocol``
+     *  The protocol used to fetch features.
      */
     protocol: null,
 
-    /**
-     * APIProperty: abortPrevious
-     * {Boolean} Whether to abort the previous request or not, defaults
-     * to true.
+    /** api: config[abortPrevious]
+     *  ``Boolean``
+     *  Abort any previous request before issuing another.  Default is ``true``.
      */
     abortPrevious: true,
 
-    /**
-     * Property: response
-     * {<OpenLayers.Protocol.Response>} The response returned by
-     * the read call on the protocol.
+    /** private: property[response]
+     *  ``OpenLayers.Protocol.Response``
+     *  The response returned by the read call on the protocol.
      */
     response: null,
 
-    /**
-     * Method: load
+    /** private: method[load]
+     *  :param params: ``Object`` An object containing properties which are to
+     *      be used as HTTP parameters for the request to the remote server.
+     *  :param reader: ``Ext.data.DataReader`` The Reader object which converts
+     *      the data object into a block of ``Ext.data.Records``.
+     *  :param callback: ``Function`` The function into which to pass the block
+     *      of ``Ext.data.Records``. The function is passed the Record block
+     *      object, the ``args`` argument passed to the load function, and a
+     *      boolean success indicator.
+     *  :param scope: ``Object`` The scope in which to call the callback.
+     *  :param arg: ``Object`` An optional argument which is passed to the
+     *      callback as its second parameter.
      *
-     * Parameters:
-     * params - {Object} An object containing properties which are to be used
-     *     as HTTP parameters for the request to the remote server.
-     * reader - {Ext.data.DataReader} The Reader object which converts the data
-     *     object into a block of Ext.data.Records.
-     * callback - {Function} The function into which to pass the block of
-     *     Ext.data.Records. The function is passed the Record block object,
-     *     the "args" argument passed to the load function, and a boolean
-     *     success indicator
-     * scope - {Object} The scope in which to call the callback
-     * arg - {Object} An optional argument which is passed to the callback
-     *     as its second parameter.
+     *  Calls ``read`` on the protocol.
      */
     load: function(params, reader, callback, scope, arg) {
         if (this.fireEvent("beforeload", this, params) !== false) {
@@ -98,9 +85,8 @@
         }
     },
 
-    /**
-     * Method: abortRequest
-     * Called to abort any ongoing request.
+    /** private: method[abortRequest]
+     *  Called to abort any ongoing request.
      */
     abortRequest: function() {
         // FIXME really we should rely on the protocol itself to
@@ -116,13 +102,11 @@
         }
     },
 
-    /**
-     * Method: loadResponse
-     * Handle response from the protocol
-     *
-     * Parameters:
-     * o - {Object} 
-     * response - {<OpenLayers.Protocol.Response>} 
+    /** private: method[loadResponse]
+     *  :param o: ``Object``
+     *  :param response: ``OpenLayers.Protocol.Response``
+     *  
+     *  Handle response from the protocol
      */
     loadResponse: function(o, response) {
         if (response.success()) {

Modified: sandbox/elemoine/playground/geoext/lib/GeoExt/data/ScaleStore.js
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt/data/ScaleStore.js	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/data/ScaleStore.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,33 +1,42 @@
-/* Copyright (C) 2008-2009 The Open Source Geospatial Foundation ¹
+/**
+ * Copyright (c) 2008-2009 The Open Source Geospatial Foundation
+ * 
  * Published under the BSD license.
- * See http://geoext.org/svn/geoext/core/trunk/license.txt for the full text
+ * See http://svn.geoext.org/core/trunk/geoext/license.txt for the full text
  * of the license.
- * 
- * ¹ pending approval */
+ */
 
+/** api: (define)
+ *  module = GeoExt.data
+ *  class = ScaleStore
+ *  base_link = `Ext.data.DataStore <http://extjs.com/deploy/dev/docs/?class=Ext.data.DataStore>`_
+ */
 Ext.namespace("GeoExt.data");
 
-/**
- *  Class: GeoExt.data.ScaleStore
- *  This store maintains a list of available zoom levels, optionally keeping it synchronized with 
- *  a Map or MapPanel instance.   The entries in the list have the following fields: 
- *  zoom - the number of the zoom level
- *  scale - the scale denominator for the zoom level
- *  resolution - the map resolution when the zoom level is active.
+/** api: constructor
+ *  .. class:: ScaleStore
+ *
+ *      A store that contains a cache of available zoom levels.  The store can
+ *      optionally be kept synchronized with an ``OpenLayers.Map`` or
+ *      :class:`GeoExt.MapPanel` object.
+ *
+ *      Records have the following fields:
+ *
+ *      * zoom - ``Number``  The zoom level.
+ *      * scale - ``Number`` The scale denominator.
+ *      * resolution - ``Number`` The map units per pixel.
  */
 GeoExt.data.ScaleStore = Ext.extend(Ext.data.Store, {
-    /**
-     * Property: map
-     * The OpenLayers.Map instance to which the store is bound, if any.
+
+    /** api: config[map]
+     *  ``OpenLayers.Map`` or :class:`GeoExt.MapPanel`
+     *  Optional map or map panel from which to derive scale values.
      */
     map: null,
 
-    /**
-     * Constructor: GeoExt.data.ScaleStore
-     * Construct a ScaleStore from a configuration.  The ScaleStore accepts some custom parameters 
-     * addition to the fields accepted by Ext.Store.
-     * Additional options:
-     * map - the GeoExt.MapPanel or OpenLayers.Map instance the store should stay sync'ed with
+    /** private: method[constructor]
+     *  Construct a ScaleStore from a configuration.  The ScaleStore accepts
+     *  some custom parameters addition to the fields accepted by Ext.Store.
      */
     constructor: function(config) {
         var map = (config.map instanceof GeoExt.MapPanel ? config.map.map : config.map);
@@ -40,18 +49,19 @@
 
         GeoExt.data.ScaleStore.superclass.constructor.call(this, config);
 
-        if (map) this.bind(map);
+        if (map) {
+            this.bind(map);
+        }
     },
 
-    /**
-     * APIMethod: bind
-     * Bind this store to a map; that is, maintain the zoom list in sync with the map's current 
-     * configuration.  If the map does not currently have a set scale list, then the store will 
-     * remain empty until the map is configured with one.
-     *
-     * Parameters: 
-     * map - the GeoExt.MapPanel or OpenLayers.Map to which we should bind
-     * options - additional parameters for the bind operation (optional, currently unused)
+    /** api: method[bind]
+     *  :param map: :class`GeoExt.MapPanel` or ``OpenLayers.Map`` Panel or map
+     *      to which we should bind.
+     *  
+     *  Bind this store to a map; that is, maintain the zoom list in sync with
+     *  the map's current configuration.  If the map does not currently have a
+     *  set scale list, then the store will remain empty until the map is
+     *  configured with one.
      */
     bind: function(map, options) {
         this.map = (map instanceof GeoExt.MapPanel ? map.map : map);
@@ -63,10 +73,10 @@
         }
     },
 
-    /**
-     * APIMethod: unbind
-     * Un-bind this store from the map to which it is currently bound.  The currently stored zoom 
-     * levels will remain, but no further changes from the map will affect it.
+    /** api: method[unbind]
+     *  Un-bind this store from the map to which it is currently bound.  The
+     *  currently stored zoom levels will remain, but no further changes from
+     *  the map will affect it.
      */
     unbind: function() {
         if (this.map) {
@@ -76,13 +86,12 @@
         }
     },
 
-    /**
-     * Method: populateOnAdd
-     * This method handles the case where we have bind() called on a not-fully-configured map so 
-     * that the zoom levels can be detected when a baselayer is finally added.
-     *
-     * Parameters:
-     * evt - the OpenLayers event
+    /** private: method[populateOnAdd]
+     *  :param evt: ``Object``
+     *  
+     *  This method handles the case where we have bind() called on a
+     *  not-fully-configured map so that the zoom levels can be detected when a
+     *  baselayer is finally added.
      */
     populateOnAdd: function(evt) {
         if (evt.layer.isBaseLayer) {
@@ -91,20 +100,22 @@
         }
     },
 
-    /**
-     * Method: populateFromMap
-     * This method actually loads the zoom level information from the OpenLayers.Map and converts 
-     * it to Ext Records.
+    /** private: method[populateFromMap]
+     *  This method actually loads the zoom level information from the
+     *  OpenLayers.Map and converts it to Ext Records.
      */
     populateFromMap: function() {
         var zooms = [];
+        var resolutions = this.map.baseLayer.resolutions;
+        var units = this.map.baseLayer.units;
 
-        for (var i = this.map.numZoomLevels-1; i > 0; i--) { 
-            var res = this.map.getResolutionForZoom(i);
-            var units = this.map.baseLayer.units;
-            var scale = OpenLayers.Util.getScaleFromResolution(res, units);
-
-            zooms.push({level: i, resolution: res, scale: scale});
+        for (var i=resolutions.length-1; i >= 0; i--) {
+            var res = resolutions[i];
+            zooms.push({
+                level: i,
+                resolution: res,
+                scale: OpenLayers.Util.getScaleFromResolution(res, units)
+            });
         }
 
         this.loadData(zooms);

Modified: sandbox/elemoine/playground/geoext/lib/GeoExt/data/WMSCapabilitiesReader.js
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt/data/WMSCapabilitiesReader.js	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/data/WMSCapabilitiesReader.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,33 +1,34 @@
 /**
- * Copyright (c) 2008 The Open Planning Project
+ * Copyright (c) 2008-2009 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.
  */
 
-Ext.namespace("GeoExt.data");
-
 /**
- * Class: GeoExt.data.WMSCapabilitiesReader
- * Data reader class to provide an array of {Ext.data.Record} objects given
- *     a WMS GetCapabilities response for use by an {Ext.data.Store}
- *     object.
- *
- * Extends:
- *  - Ext.data.DataReader
+ * @include GeoExt/data/LayerRecord.js
  */
 
-/**
- * Constructor: GeoExt.data.WMSCapabilitiesReader
- * Create a new attributes reader object.
- *
- * Parameters:
- * meta - {Object} Reader configuration.
- * recordType - {Array | Ext.data.Record} An array of field configuration
- *     objects or a record object.  Default is <GeoExt.data.LayerRecord>.
- *
- * Configuration options (meta properties):
- * format - {OpenLayers.Format} A parser for transforming the XHR response
- *     into an array of objects representing attributes.  Defaults to
- *     an {OpenLayers.Format.WMSCapabilities} parser.
+/** api: (define)
+ *  module = GeoExt.data
+ *  class = WMSCapabilitiesReader
+ *  base_link = `Ext.data.DataReader <http://extjs.com/deploy/dev/docs/?class=Ext.data.DataReader>`_
  */
+Ext.namespace("GeoExt.data");
+
+/** api: constructor
+ *  .. class:: WMSCapabilitiesReader(meta, recordType)
+ *  
+ *      :param meta: ``Object`` Reader configuration.
+ *      :param recordType: ``Array | Ext.data.Record`` An array of field
+ *          configuration objects or a record object.  Default is
+ *          :class:`GeoExt.data.LayerRecord`.
+ *   
+ *      Data reader class to create an array of
+ *      :class:`GeoExt.data.LayerRecord` objects from a WMS GetCapabilities
+ *      response.
+ */
 GeoExt.data.WMSCapabilitiesReader = function(meta, recordType) {
     meta = meta || {};
     if(!meta.format) {
@@ -44,7 +45,10 @@
                 {name: "llbbox"},
                 {name: "minScale"},
                 {name: "maxScale"},
-                {name: "prefix"}
+                {name: "prefix"},
+                {name: "attribution"},
+                {name: "keywords"},
+                {name: "metadataURLs"}
             ]
         );
     }
@@ -55,19 +59,20 @@
 
 Ext.extend(GeoExt.data.WMSCapabilitiesReader, Ext.data.DataReader, {
 
-    /**
-     * Method: read
-     * This method is only used by a DataProxy which has retrieved data from a
-     *     remote server.
-     *
-     * Parameters:
-     * request - {Object} The XHR object which contains the parsed XML
-     *     document.
-     * 
-     * Returns:
-     * {Object} A data block which is used by an {Ext.data.Store} as a cache
-     *     of Ext.data.Records.
+
+    /** api: config[attributionCls]
+     *  ``String`` CSS class name for the attribution DOM elements.
+     *  Element class names append "-link", "-image", and "-title" as
+     *  appropriate.  Default is "gx-attribution".
      */
+    attributionCls: "gx-attribution",
+
+    /** private: method[read]
+     *  :param request: ``Object`` The XHR object which contains the parsed XML
+     *      document.
+     *  :return: ``Object`` A data block which is used by an ``Ext.data.Store``
+     *      as a cache of ``Ext.data.Record`` objects.
+     */
     read: function(request) {
         var data = request.responseXML;
         if(!data || !data.documentElement) {
@@ -76,19 +81,16 @@
         return this.readRecords(data);
     },
 
-    /**
-     * Method: readRecords
-     * Create a data block containing Ext.data.Records from an XML document.
-     *
-     * Parameters:
-     * data - {DOMElement | Strint | Object} A document element or XHR response
-     *     string.  As an alternative to fetching capabilities data from a remote
-     *     source, an object representing the capabilities can be provided given
-     *     that the structure mirrors that returned from the capabilities parser.
-     *
-     * Returns:
-     * {Object} A data block which is used by an {Ext.data.Store} as a cache of
-     *     Ext.data.Records.
+    /** private: method[readRecords]
+     *  :param data: ``DOMElement | Strint | Object`` A document element or XHR
+     *      response string.  As an alternative to fetching capabilities data
+     *      from a remote source, an object representing the capabilities can
+     *      be provided given that the structure mirrors that returned from the
+     *      capabilities parser.
+     *  :return: ``Object`` A data block which is used by an ``Ext.data.Store``
+     *      as a cache of ``Ext.data.Record`` objects.
+     *  
+     *  Create a data block containing Ext.data.Records from an XML document.
      */
     readRecords: function(data) {
         
@@ -97,24 +99,68 @@
         }
         var url = data.capability.request.getmap.href;
         var records = [], layer;        
+
         for(var i=0, len=data.capability.layers.length; i<len; i++){
             layer = data.capability.layers[i];
+
             if(layer.name) {
                 records.push(new this.recordType(Ext.apply(layer, {
                     layer: new OpenLayers.Layer.WMS(
                         layer.title || layer.name,
                         url,
-                        {layers: layer.name}
+                        {layers: layer.name}, {
+                            attribution: layer.attribution ?
+                                this.attributionMarkup(layer.attribution) :
+                                undefined
+                        }
                     )
                 })));
             }
         }
-
+        
         return {
             totalRecords: records.length,
             success: true,
             records: records
         };
 
+    },
+
+    /** private: method[attributionMarkup]
+     *  :param attribution: ``Object`` The attribution property of the layer
+     *      object as parsed from a WMS Capabilities document
+     *  :return: ``String`` HTML markup to display attribution
+     *      information.
+     *  
+     *  Generates attribution markup using the Attribution metadata
+     *      from WMS Capabilities
+     */
+    attributionMarkup : function(attribution){
+        var markup = [];
+        
+        if (attribution.logo){
+            markup.push("<img class='"+this.attributionCls+"-image' "
+                        + "src='" + attribution.logo.href + "' />");
+        }
+        
+        if (attribution.title) {
+            markup.push("<span class='"+ this.attributionCls + "-title'>"
+                        + attribution.title
+                        + "</span>");
+        }
+        
+        if(attribution.href){
+            for(var i = 0; i < markup.length; i++){
+                markup[i] = "<a class='"
+              + this.attributionCls + "-link' "
+                    + "href="
+                    + attribution.href
+                    + ">"
+                    + markup[i]
+                    + "</a>";
+            }
+        }
+
+        return markup.join(" ");
     }
 });

Modified: sandbox/elemoine/playground/geoext/lib/GeoExt/data/WMSCapabilitiesStore.js
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt/data/WMSCapabilitiesStore.js	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/data/WMSCapabilitiesStore.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,42 +1,50 @@
 /**
- * Copyright (c) 2008 The Open Planning Project
+ * Copyright (c) 2008-2009 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/WMSCapabilitiesReader.js
  */
 
+/** api: (define)
+ *  module = GeoExt.data
+ *  class = WMSCapabilitiesStore
+ *  base_link = `Ext.data.DataStore <http://extjs.com/deploy/dev/docs/?class=Ext.data.DataStore>`_
+ */
 Ext.namespace("GeoExt.data");
-/**
- * Class: GeoExt.data.WMSCapabilitiesStore
- * Small helper class to make creating stores for remote WMS layer data easier.
- *     WMSCapabilitiesStore is pre-configured with a built-in
- *     {Ext.data.HttpProxy} and {GeoExt.data.WMSCapabilitiesReader}.  The
- *     HttpProxy is configured to allow caching (disableCaching: false) and uses
- *     GET.  If you require some other proxy/reader combination then you'll have
- *     to configure this with your own proxy or create a basic
- *     GeoExt.data.LayerStore and configure as needed.
- *
- * Extends:
- *  - GeoExt.data.Store
+
+/** api: constructor
+ *  .. class:: WMSCapabilitiesStore
+ *  
+ *      Small helper class to make creating stores for remote WMS layer data
+ *      easier.  The store is pre-configured with a built-in
+ *      ``Ext.data.HttpProxy`` and :class:`GeoExt.data.WMSCapabilitiesReader`.
+ *      The proxy is configured to allow caching and issues requests via GET.
+ *      If you require some other proxy/reader combination then you'll have to
+ *      configure this with your own proxy or create a basic
+ *      :class:`GeoExt.data.LayerStore` and configure as needed.
  */
 
-/**
- * Constructor: GeoExt.data.WMSCapabilitiesStore
- * Create a new WMS capabilities store object.
- *
- * Parameters:
- * config - {Object} Store configuration.
- *
- * Configuration options:
- * format - {OpenLayers.Format} A parser for transforming the XHR response into
- *     an array of objects representing attributes.  Defaults to an
- *     {OpenLayers.Format.WMSCapabilities} parser.
- * fields - {Array | Function} Either an Array of field definition objects as
- *     passed to Ext.data.Record.create, or a Record constructor created using
- *     Ext.data.Record.create.  Defaults to ["name", "type"]. 
+/** api: config[format]
+ *  ``OpenLayers.Format``
+ *  A parser for transforming the XHR response into an array of objects
+ *  representing attributes.  Defaults to an ``OpenLayers.Format.WMSCapabilities``
+ *  parser.
  */
+
+/** api: config[fields]
+ *  ``Array | Function``
+ *  Either an Array of field definition objects as passed to
+ *  ``Ext.data.Record.create``, or a record constructor created using
+ *  ``Ext.data.Record.create``.  Defaults to ``["name", "type"]``. 
+ */
+
 GeoExt.data.WMSCapabilitiesStore = function(c) {
+    c = c || {};
     GeoExt.data.WMSCapabilitiesStore.superclass.constructor.call(
         this,
         Ext.apply(c, {

Copied: sandbox/elemoine/playground/geoext/lib/GeoExt/data/WMSDescribeLayerReader.js (from rev 1281, core/trunk/geoext/lib/GeoExt/data/WMSDescribeLayerReader.js)
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt/data/WMSDescribeLayerReader.js	                        (rev 0)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/data/WMSDescribeLayerReader.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -0,0 +1,94 @@
+/**
+ * Copyright (c) 2008-2009 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.
+ */
+
+/** api: (define)
+ *  module = GeoExt.data
+ *  class = WMSDescribeLayerReader
+ *  base_link = `Ext.data.DataReader <http://extjs.com/deploy/dev/docs/?class=Ext.data.DataReader>`_
+ */
+Ext.namespace("GeoExt.data");
+
+/** api: constructor
+ *  .. class:: WMSDescribeLayerReader(meta, recordType)
+ *  
+ *      :param meta: ``Object`` Reader configuration.
+ *      :param recordType: ``Array | Ext.data.Record`` An array of field
+ *          configuration objects or a record object.  Default has
+ *          fields for owsType, owsURL, and typeName.
+ *   
+ *      Data reader class to create an array of
+ *      layer description objects from a WMS DescribeLayer
+ *      response.
+ */
+GeoExt.data.WMSDescribeLayerReader = function(meta, recordType) {
+    meta = meta || {};
+    if(!meta.format) {
+        meta.format = new OpenLayers.Format.WMSDescribeLayer();
+    }
+    if(!(typeof recordType === "function")) {
+        recordType = Ext.data.Record.create(
+            recordType || meta.fields || [
+                {name: "owsType", type: "string"},
+                {name: "owsURL", type: "string"},
+                {name: "typeName", type: "string"}
+            ]
+        );
+    }
+    GeoExt.data.WMSDescribeLayerReader.superclass.constructor.call(
+        this, meta, recordType
+    );
+};
+
+Ext.extend(GeoExt.data.WMSDescribeLayerReader, Ext.data.DataReader, {
+
+    /** private: method[read]
+     *  :param request: ``Object`` The XHR object which contains the parsed XML
+     *      document.
+     *  :return: ``Object`` A data block which is used by an ``Ext.data.Store``
+     *      as a cache of ``Ext.data.Record`` objects.
+     */
+    read: function(request) {
+        var data = request.responseXML;
+        if(!data || !data.documentElement) {
+            data = request.responseText;
+        }
+        return this.readRecords(data);
+    },
+
+    /** private: method[readRecords]
+     *  :param data: ``DOMElement | Strint | Object`` A document element or XHR
+     *      response string.  As an alternative to fetching layer description data
+     *      from a remote source, an object representing the layer descriptions can
+     *      be provided given that the structure mirrors that returned from the
+     *      layer description parser.
+     *  :return: ``Object`` A data block which is used by an ``Ext.data.Store``
+     *      as a cache of ``Ext.data.Record`` objects.
+     *  
+     *  Create a data block containing Ext.data.Records from an XML document.
+     */
+    readRecords: function(data) {
+        
+        if(typeof data === "string" || data.nodeType) {
+            data = this.meta.format.read(data);
+        }
+        var records = [], description;        
+        for(var i=0, len=data.length; i<len; i++){
+            description = data[i];
+            if(description) {
+                records.push(new this.recordType(description));
+            }
+        }
+
+        return {
+            totalRecords: records.length,
+            success: true,
+            records: records
+        };
+
+    }
+});

Copied: sandbox/elemoine/playground/geoext/lib/GeoExt/data/WMSDescribeLayerStore.js (from rev 1281, core/trunk/geoext/lib/GeoExt/data/WMSDescribeLayerStore.js)
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt/data/WMSDescribeLayerStore.js	                        (rev 0)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/data/WMSDescribeLayerStore.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -0,0 +1,61 @@
+/**x
+ * Copyright (c) 2008-2009 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/WMSDescribeLayerReader.js
+ */
+
+/** api: (define)
+ *  module = GeoExt.data
+ *  class = WMSDescribeLayerStore
+ *  base_link = `Ext.data.DataStore <http://extjs.com/deploy/dev/docs/?class=Ext.data.DataStore>`_
+ */
+Ext.namespace("GeoExt.data");
+
+/** api: constructor
+ *  .. class:: WMSDescribeLayerStore
+ *  
+ *      Small helper class to make creating stores for remote WMS layer description
+ *      easier.  The store is pre-configured with a built-in
+ *      ``Ext.data.HttpProxy`` and :class:`GeoExt.data.WMSDescribeLayerReader`.
+ *      The proxy is configured to allow caching and issues requests via GET.
+ *      If you require some other proxy/reader combination then you'll have to
+ *      configure this with your own proxy or create a basic
+ *      store and configure as needed.
+ */
+
+/** api: config[format]
+ *  ``OpenLayers.Format``
+ *  A parser for transforming the XHR response into an array of objects
+ *  representing attributes.  Defaults to an ``OpenLayers.Format.WMSCapabilities``
+ *  parser.
+ */
+
+/** api: config[fields]
+ *  ``Array | Function``
+ *  Either an Array of field definition objects as passed to
+ *  ``Ext.data.Record.create``, or a record constructor created using
+ *  ``Ext.data.Record.create``.  Defaults to ``["name", "type"]``. 
+ */
+
+GeoExt.data.WMSDescribeLayerStore = function(c) {
+    c = c || {};
+    GeoExt.data.WMSDescribeLayerStore.superclass.constructor.call(
+        this,
+        Ext.apply(c, {
+            proxy: c.proxy || (!c.data ?
+                new Ext.data.HttpProxy({url: c.url, disableCaching: false, method: "GET"}) :
+                undefined
+            ),
+            reader: new GeoExt.data.WMSDescribeLayerReader(
+                c, c.fields
+            )
+        })
+    );
+};
+Ext.extend(GeoExt.data.WMSDescribeLayerStore, Ext.data.Store);

Modified: sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/Action.js
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/Action.js	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/Action.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,9 +1,10 @@
-/* Copyright (C) 2008-2009 The Open Source Geospatial Foundation
+/**
+ * Copyright (c) 2008-2009 The Open Source Geospatial Foundation
+ * 
  * Published under the BSD license.
- * See http://geoext.org/svn/geoext/core/trunk/license.txt for the full text
+ * See http://svn.geoext.org/core/trunk/geoext/license.txt for the full text
  * of the license.
- * 
- * pending approval */
+ */
 
 /** api: (define)
  *  module = GeoExt
@@ -17,12 +18,11 @@
  * 
  *  .. code-block:: javascript
  *  
- *      var ctrl = new OpenLayers.Control.ZoomToMaxExtent();
- *      map.addControl(ctrl);
- *      var action = GeoExt.Action.fromControl(ctrl, {
- *          text: "max extent"
+ *      var action = new GeoExt.Action({
+ *          text: "max extent",
+ *          control: new OpenLayers.Control.ZoomToMaxExtent(),
+ *          map: map
  *      });
- *
  *      var toolbar = new Ext.Toolbar([action]);
  */
 
@@ -42,6 +42,13 @@
      */
     control: null,
 
+    /** api: config[map]
+     *  ``OpenLayers.Map`` The OpenLayers map that the control should be added
+     *  to.  For controls that don't need to be added to a map or have already
+     *  been added to one, this config property may be omitted.
+     */
+    map: null,
+
     /** private: property[uScope]
      *  ``Object`` The user-provided scope, used when calling uHandler,
      *  uToggleHandler, and uCheckHandler.
@@ -88,6 +95,11 @@
         // register "activate" and "deactivate" listeners
         // on the control
         if(ctrl) {
+            // If map is provided in config, add control to map.
+            if(config.map) {
+                config.map.addControl(ctrl);
+                delete config.map;
+            }
             ctrl.events.on({
                 activate: this.onCtrlActivate,
                 deactivate: this.onCtrlDeactivate,
@@ -205,12 +217,3 @@
         }
     }
 });
-
-GeoExt.Action.fromControl = function(control, cfg) {
-    cfg = cfg || {};
-    if(cfg instanceof Ext.Action) {
-        cfg = cfg.initialConfig;
-    }
-    cfg.control = control;
-    return new GeoExt.Action(cfg);
-};

Copied: sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/LayerOpacitySlider.js (from rev 1281, core/trunk/geoext/lib/GeoExt/widgets/LayerOpacitySlider.js)
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/LayerOpacitySlider.js	                        (rev 0)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/LayerOpacitySlider.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -0,0 +1,192 @@
+/* Copyright (C) 2008-2009 The Open Source Geospatial Foundation
+ * Published under the BSD license.
+ * See http://geoext.org/svn/geoext/core/trunk/license.txt for the full text
+ * of the license.
+ */
+
+/**
+ * @include GeoExt/widgets/tips/LayerOpacitySliderTip.js
+ */
+
+/** api: (define)
+ *  module = GeoExt
+ *  class = LayerOpacitySlider
+ *  base_link = `Ext.Slider <http://extjs.com/deploy/dev/docs/?class=Ext.Slider>`_
+ */
+Ext.namespace("GeoExt");
+
+/** api: example
+ *  Sample code to render a slider outside the map viewport:
+ *
+ *  .. code-block:: javascript
+ *
+ *      var slider = new GeoExt.LayerOpacitySlider({
+ *          renderTo: document.body,
+ *          width: 200,
+ *          layer: layer
+ *      });
+ *
+ *  Sample code to add a slider to a map panel:
+ *
+ *  .. code-block:: javascript
+ *
+ *      var layer = new OpenLayers.Layer.WMS(
+ *          "Global Imagery",
+ *          "http://demo.opengeo.org/geoserver/wms",
+ *          {layers: "bluemarble"}
+ *      );
+ *      var panel = new GeoExt.MapPanel({
+ *          renderTo: document.body,
+ *          height: 300,
+ *          width: 400,
+ *          map: {
+ *              controls: [new OpenLayers.Control.Navigation()]
+ *          },
+ *          layers: [layer],
+ *          extent: [-5, 35, 15, 55],
+ *          items: [{
+ *              xtype: "gx_opacityslider",
+ *              layer: layer,
+ *              aggressive: true,
+ *              vertical: true,
+ *              height: 100,
+ *              x: 10,
+ *              y: 20
+ *          }]
+ *      });
+ */
+
+/** api: constructor
+ *  .. class:: LayerOpacitySlider(config)
+ *
+ *      Create a slider for controlling a layer's opacity.
+ */
+GeoExt.LayerOpacitySlider = Ext.extend(Ext.Slider, {
+
+    /** api: config[layer]
+     *  ``OpenLayers.Layer`` or :class:`GeoExt.data.LayerRecord`
+     */
+    layer: null,
+
+    /** api: config[delay]
+     *  ``Number`` Time in milliseconds before setting the opacity value to the
+     *  layer. If the value change again within that time, the original value
+     *  is not set. Only applicable if aggressive is true.
+     */
+    delay: 5,
+
+    /** api: config[aggressive]
+     *  ``Boolean``
+     *  If set to true, the opacity is changed as soon as the thumb is moved.
+     *  Otherwise when the thumb is released (default).
+     */
+    aggressive: false,
+
+    /** private: property[minValue]
+     *  ``Number``
+     *  The minimum slider value, layer is fully transparent
+     */
+    minValue: 0,
+
+    /** private: property[maxValue]
+     *  ``Number``
+     *  The maximum slider value, layer is fully opaque.
+     */
+    maxValue: 100,
+
+    /** private: method[constructor]
+     *  Construct the component.
+     */
+    constructor: function(config) {
+        if (config.layer) {
+            if (config.layer instanceof OpenLayers.Layer) {
+                this.layer = config.layer;
+            } else if (config.layer instanceof GeoExt.data.LayerRecord) {
+                this.layer = config.layer.get('layer');
+            }
+            delete config.layer;
+        }
+        GeoExt.LayerOpacitySlider.superclass.constructor.call(this, config);
+    },
+
+    /** private: method[initComponent]
+     *  Initialize the component.
+     */
+    initComponent: function() {
+        // set the slider initial value
+        if (this.layer && this.layer.opacity !== null) {
+            this.value = parseInt(this.layer.opacity * 100);
+        } else {
+            // assume that the layer has no opacity
+            this.value = 100;
+        }
+
+        GeoExt.LayerOpacitySlider.superclass.initComponent.call(this);
+
+        if (this.aggressive === true) {
+            this.on('change', this.opacityChanged, this, {
+                buffer: this.delay
+            });
+        } else {
+            this.on('changecomplete', this.opacityChanged, this);
+        }
+    },
+
+    /** private: method[opacityChanged]
+     *  :param slider: :class:`GeoExt.LayerOpacitySlider`
+     *  :param value: ``Number`` The slider value
+     *
+     *  Updates the ``OpenLayers.Layer`` opacity value.
+     */
+    opacityChanged: function(slider, value) {
+        if (this.layer) {
+            this.layer.setOpacity(value / 100.0);
+        }
+    },
+
+    /** 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({
+            render: function() {
+                var el = this.getEl();
+                el.setStyle({
+                    position: "absolute",
+                    zIndex: panel.map.Z_INDEX_BASE.Control
+                });
+                el.on({
+                    mousedown: this.stopMouseEvents,
+                    click: this.stopMouseEvents
+                });
+            },
+            scope: this
+        });
+    },
+
+    /** 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,
+            click: this.stopMouseEvents,
+            scope: this
+        });
+    },
+
+    /** private: method[stopMouseEvents]
+     *  :param e: ``Object``
+     */
+    stopMouseEvents: function(e) {
+        e.stopEvent();
+    }
+});
+
+/** api: xtype = gx_opacityslider */
+Ext.reg('gx_opacityslider', GeoExt.LayerOpacitySlider);

Modified: sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/LegendImage.js
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/LegendImage.js	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/LegendImage.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,13 +1,15 @@
-/* Copyright (C) 2008-2009 The Open Source Geospatial Foundation
+/**
+ * Copyright (c) 2008-2009 The Open Source Geospatial Foundation
+ * 
  * Published under the BSD license.
- * See http://geoext.org/svn/geoext/core/trunk/license.txt for the full text
+ * See http://svn.geoext.org/core/trunk/geoext/license.txt for the full text
  * of the license.
- * 
- * pending approval */
+ */
 
 /** api: (define)
  *  module = GeoExt
  *  class = LegendImage
+ *  base_link = `Ext.Panel <http://extjs.com/deploy/dev/docs/?class=Ext.Panel>`_
  */
 
 Ext.namespace('GeoExt');
@@ -24,19 +26,31 @@
      *  ``String``  The url of the image to load
      */
     url: null,
+    
+    /** api: config[defaultImgSrc]
+     *  ``String`` Path to image that will be used if the legend image fails
+     *  to load.  Default is Ext.BLANK_IMAGE_URL.
+     */
+    defaultImgSrc: null,
 
     /** api: config[imgCls]
      *  ``String``  Optional css class to apply to img tag
      */
     imgCls: null,
-
+    
     /** private: method[initComponent]
      *  Initializes the legend image component. 
      */
     initComponent: function() {
         GeoExt.LegendImage.superclass.initComponent.call(this);
-        this.autoEl = {tag: 'img',
-            'class': (this.imgCls ? this.imgCls : ''), src: this.url};
+        if(this.defaultImgSrc === null) {
+            this.defaultImgSrc = Ext.BLANK_IMAGE_URL;
+        }
+        this.autoEl = {
+            tag: "img",
+            "class": (this.imgCls ? this.imgCls : ""),
+            src: this.defaultImgSrc
+        };
     },
 
     /** api: method[setUrl]
@@ -45,8 +59,11 @@
      *  Sets the url of the image.
      */
     setUrl: function(url) {
+        this.url = url;
         var el = this.getEl();
         if (el) {
+            el.un("error", this.onImageLoadError, this);
+            el.on("error", this.onImageLoadError, this, {single: true});
             el.dom.src = url;
         }
     },
@@ -57,14 +74,19 @@
      */
     onRender: function(ct, position) {
         GeoExt.LegendImage.superclass.onRender.call(this, ct, position);
-        this.getEl().on('error', this.onImageLoadError, this);
+        if(this.url) {
+            this.setUrl(this.url);
+        }
     },
 
     /** private: method[onDestroy]
      *  Private method called during the destroy sequence.
      */
     onDestroy: function() {
-        this.getEl().un('error', this.onImageLoadError, this);
+        var el = this.getEl();
+        if(el) {
+            el.un("error", this.onImageLoadError, this);
+        }
         GeoExt.LegendImage.superclass.onDestroy.apply(this, arguments);
     },
     
@@ -72,9 +94,10 @@
      *  Private method called if the legend image fails loading.
      */
     onImageLoadError: function() {
-        this.getEl().dom.src = Ext.BLANK_IMAGE_URL;
+        this.getEl().dom.src = this.defaultImgSrc;
     }
 
 });
 
+/** api: xtype = gx_legendimage */
 Ext.reg('gx_legendimage', GeoExt.LegendImage);

Modified: sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/LegendPanel.js
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/LegendPanel.js	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/LegendPanel.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,13 +1,15 @@
-/* Copyright (C) 2008-2009 The Open Source Geospatial Foundation
+/**
+ * Copyright (c) 2008-2009 The Open Source Geospatial Foundation
+ * 
  * Published under the BSD license.
- * See http://geoext.org/svn/geoext/core/trunk/license.txt for the full text
+ * See http://svn.geoext.org/core/trunk/geoext/license.txt for the full text
  * of the license.
- *
- * pending approval */
+ */
 
 /** api: (define)
  *  module = GeoExt
  *  class = LegendPanel
+ *  base_link = `Ext.Panel <http://extjs.com/deploy/dev/docs/?class=Ext.Panel>`_
  */
 
 Ext.namespace('GeoExt');
@@ -54,6 +56,12 @@
      *  container. If not provided it will be taken from the MapPanel.
      */
     layerStore: null,
+    
+    /** api: config[legendOptions]
+     *  ``Object``
+     *  Config options for the legend generator, i.e. the panel that provides
+     *  the legend image.
+     */
 
     /** private: method[initComponent]
      *  Initializes the legend panel.
@@ -96,6 +104,7 @@
         var store = this.layerStore;
         var count = store.getCount();
         var panelIndex = -1;
+        var legendCount = this.items ? this.items.length : 0;
         for(var i=count-1; i>=0; --i) {
             var layer = store.getAt(i).get("layer");
             var legendGenerator = GeoExt[
@@ -104,7 +113,7 @@
             if(layer.displayInLayerSwitcher && legendGenerator &&
                 (store.getAt(i).get("hideInLegend") !== true)) {
                     ++panelIndex;
-                    if(index === i) {
+                    if(index === i || panelIndex > legendCount-1) {
                         break;
                     }
             }
@@ -126,6 +135,11 @@
     onStoreUpdate: function(store, record, operation) {
         var layer = record.get('layer');
         var legend = this.getComponent(layer.id);
+        if ((this.showTitle && !record.get('hideTitle')) && 
+            (legend && legend.items.get(0).text !== record.get('title'))) {
+                // we need to update the title
+                legend.items.get(0).setText(record.get('title'));
+        }
         if (legend) {
             legend.setVisible(layer.getVisibility() && 
                 layer.displayInLayerSwitcher && !record.get('hideInLegend'));
@@ -148,7 +162,7 @@
      *  :param index: ``Integer`` The index of the inserted record.
      */
     onStoreAdd: function(store, records, index) {
-        var panelIndex = this.recordIndexToPanelIndex(index);
+        var panelIndex = this.recordIndexToPanelIndex(index+records.length-1);
         for (var i=0, len=records.length; i<len; i++) {
             this.addLegend(records[i], panelIndex);
         }
@@ -204,7 +218,10 @@
                     "Legend" + layer.CLASS_NAME.split(".").pop()
                 ];
                 if (legendGenerator) {
-                    legend = new legendGenerator({layer: layer});
+                    legend = new legendGenerator(Ext.applyIf({
+                        layer: layer,
+                        record: record
+                    }, this.legendOptions));
                     mainPanel.add(legend);
                 }
             }
@@ -278,4 +295,5 @@
     
 });
 
-Ext.reg('gx_legendpanel', GeoExt.LegendPanel);
\ No newline at end of file
+/** api: xtype = gx_legendpanel */
+Ext.reg('gx_legendpanel', GeoExt.LegendPanel);

Modified: sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/LegendWMS.js
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/LegendWMS.js	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/LegendWMS.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,9 +1,10 @@
-/* Copyright (C) 2008-2009 The Open Source Geospatial Foundation
+/**
+ * Copyright (c) 2008-2009 The Open Source Geospatial Foundation
+ * 
  * Published under the BSD license.
- * See http://geoext.org/svn/geoext/core/trunk/license.txt for the full text
+ * See http://svn.geoext.org/core/trunk/geoext/license.txt for the full text
  * of the license.
- *
- * pending approval */
+ */
 
 /**
  * @include GeoExt/widgets/LegendImage.js
@@ -12,6 +13,7 @@
 /** api: (define)
  *  module = GeoExt
  *  class = LegendWMS
+ *  base_link = `Ext.Panel <http://extjs.com/deploy/dev/docs/?class=Ext.Panel>`_
  */
 Ext.namespace('GeoExt');
 
@@ -24,16 +26,35 @@
 
     /** api: config[imageFormat]
      *  ``String``  
-     *  The image format to request the legend image in.
-     *  Defaults to image/png.
+     *  The image format to request the legend image in if the url cannot be
+     *  determined from the styles field of the layer record. Defaults to
+     *  image/gif.
      */
     imageFormat: "image/gif",
+    
+    /** api: config[defaultStyleIsFirst]
+     *  ``String``
+     *  The WMS spec does not say if the first style advertised for a layer in
+     *  a Capabilities document is the default style that the layer is
+     *  rendered with. We make this assumption by default. To be strictly WMS
+     *  compliant, set this to false, but make sure to configure a STYLES
+     *  param with your WMS layers, otherwise LegendURLs advertised in the
+     *  GetCapabilities document cannot be used.
+     */
+    defaultStyleIsFirst: true,
 
     /** api: config[layer]
      *  ``OpenLayers.Layer.WMS``
-     *  The WMS layer to request the legend for.
+     *  The WMS layer to request the legend for. Not required if record is
+     *  provided.
      */
-    layer: null,
+    layer: null,
+    
+    /** api: config[record]
+     *  ``Ext.data.Record``
+     *  optional record containing the layer 
+     */
+    record: null,
 
     /** api: config[bodyBorder]
      *  ``Boolean``
@@ -46,7 +67,10 @@
      *  image box components.
      */
     initComponent: function() {
-        GeoExt.LegendWMS.superclass.initComponent.call(this);
+        GeoExt.LegendWMS.superclass.initComponent.call(this);
+        if(!this.layer) {
+            this.layer = this.record.get("layer");
+        }
         this.createLegend();
     },
 
@@ -75,13 +99,29 @@
      *  Add one BoxComponent per sublayer to this panel.
      */
     createLegend: function() {
-        var layers = this.layer.params.LAYERS.split(",");
+        var layers = (this.layer.params.LAYERS instanceof Array) ? 
+            this.layer.params.LAYERS : this.layer.params.LAYERS.split(",");
+        var styleNames = this.layer.params.STYLES &&
+            this.layer.params.STYLES.split(",");
+        var styles = this.record && this.record.get("styles");
+        var url, layerName, styleName;
         for (var i = 0, len = layers.length; i < len; i++){
-            var layerName = layers[i];
+            layerName = layers[i];
+            if(styles) {
+                styleName = styleNames && styleNames[i];
+                if(styleName) {
+                    Ext.each(styles, function(s) {
+                        url = (s.name == styleName && s.legend) && s.legend.href;
+                        return !url;
+                    })
+                } else if(this.defaultStyleIsFirst === true){
+                    url = styles[0].legend && styles[0].legend.href;
+                }
+            }
             var legend = new GeoExt.LegendImage({url:
-                this.getLegendUrl(layerName)});
+                url || this.getLegendUrl(layerName)});
             this.add(legend);
         }
     }
 
-});
\ No newline at end of file
+});

Modified: sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/MapPanel.js
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/MapPanel.js	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/MapPanel.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,9 +1,10 @@
-/* Copyright (C) 2008-2009 The Open Source Geospatial Foundation ¹
+/**
+ * Copyright (c) 2008-2009 The Open Source Geospatial Foundation
+ * 
  * Published under the BSD license.
- * See http://geoext.org/svn/geoext/core/trunk/license.txt for the full text
+ * See http://svn.geoext.org/core/trunk/geoext/license.txt for the full text
  * of the license.
- * 
- * ¹ pending approval */
+ */
 
 /**
  * @include GeoExt/data/LayerStore.js
@@ -125,29 +126,38 @@
     },
     
     /** private: method[updateMapSize]
-     *  Tell the map that it needs to recaculate its size and position.
+     *  Tell the map that it needs to recalculate its size and position.
      */
     updateMapSize: function() {
         if(this.map) {
             this.map.updateSize();
         }
     },
-    
-    /** private: method[onRender]
-     *  Private method called after the panel has been
-     *  rendered.
+
+    /** private: method[renderMap]
+     *  Private method called after the panel has been rendered or after it
+     *  has been laid out by its parent's layout.
      */
-    onRender: function() {
-        GeoExt.MapPanel.superclass.onRender.apply(this, arguments);
-        this.map.render(this.body.dom);
-        if(this.map.layers.length > 0) {
-            if(this.center) {
-                // zoom does not have to be defined
-                this.map.setCenter(this.center, this.zoom);
-            }  else if(this.extent) {
-                this.map.zoomToExtent(this.extent);
+    renderMap: function() {
+        var map = this.map;
+
+        // hack: prevent map.updateSize (called from within map.render) from 
+        // zooming to the map extent. This hack is a workaround for 
+        // <http://trac.openlayers.org/ticket/2105> and must be
+        // removed once this ticket is closed.
+        var setCenter = map.setCenter;
+        map.setCenter = function() {};
+        map.render(this.body.dom);
+        map.setCenter = setCenter;
+
+        if(map.layers.length > 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 {
-                this.map.zoomToMaxExtent();
+                map.zoomToMaxExtent();
             }
         }
     },
@@ -157,10 +167,19 @@
      */
     afterRender: function() {
         GeoExt.MapPanel.superclass.afterRender.apply(this, arguments);
-        if(this.ownerCt) {
+        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.

Modified: sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/Popup.js
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/Popup.js	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/Popup.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,9 +1,9 @@
-/* Copyright (C) 2008-2009 The Open Source Geospatial Foundation [1]
+/**
+ * Copyright (c) 2008-2009 The Open Source Geospatial Foundation
+ * 
  * Published under the BSD license.
- * See http://geoext.org/svn/geoext/core/trunk/license.txt for the full text
+ * See http://svn.geoext.org/core/trunk/geoext/license.txt for the full text
  * of the license.
- * 
- * [1] pending approval
  */
 
 /** api: (define)
@@ -44,6 +44,14 @@
      */
     anchored: true,
 
+    /** api: config[map]
+     *  ``OpenLayers.Map`` or :class:`GeoExt.MapPanel`
+     *  The map this popup will be anchored to (only required if ``anchored``
+     *  is set to true and the map cannot be derived from the ``feature``'s
+     *  layer.
+     */
+    map: null,
+
     /** api: config[panIn]
      *  ``Boolean`` The popup should pan the map so that the popup is
      *  fully in view when it is rendered.  Default is ``true``.
@@ -108,10 +116,19 @@
     /** private: method[initComponent]
      *  Initializes the popup.
      */
-    initComponent: function() {        
+    initComponent: function() {
+        if(this.map instanceof GeoExt.MapPanel) {
+            this.map = this.map.map;
+        }
+        if(!this.map && this.feature && this.feature.layer) {
+            this.map = this.feature.layer.map;
+        }
         if (!this.feature && this.lonlat) {
             this.feature = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(this.lonlat.lon, this.lonlat.lat));
         }
+        if(this.anchored) {
+            this.addAnchorEvents();
+        }
 
         this.baseCls = this.popupCls + " " + this.baseCls;
 
@@ -146,38 +163,19 @@
         GeoExt.Popup.superclass.initTools.call(this);
     },
 
-    /** private: method[addToMapPanel]
-     *  :param mapPanel: :class:`MapPanel` The panel to which this popup should
-     *      be added.
-     *  
-     *  Adds this popup to a :class:`MapPanel`.  Assumes that the
-     *  MapPanel's map is already initialized and that the
-     *  Popup's feature is on the map.  This method is called by the MapPanel's
-     *  add method.
+    /** private: method[show]
+     *  Override.
      */
-    addToMapPanel: function(mapPanel) {
-        this.mapPanel = mapPanel;
-        this.map = this.mapPanel.map;
-        
-        mapPanel.on({
-            "add": {
-                fn: function() {
-                    mapPanel.doLayout();
-                    this.position();
-                    if(this.anchored) {
-                        this.anchorPopup();
-                    }
-                    this.show();
-                    if(this.panIn) {
-                        this.panIntoView();
-                    }
-                },
-                single: true,
-                scope: this
+    show: function() {
+        GeoExt.Popup.superclass.show.apply(this, arguments);
+        if(this.anchored) {
+            this.position();
+            if(this.panIn && !this._mapMove) {
+                this.panIntoView();
             }
-        });
+        }
     },
-
+    
     /** api: method[setSize]
      *  :param w: ``Integer``
      *  :param h: ``Integer``
@@ -202,21 +200,32 @@
      */
     position: function() {
         var centerLonLat = this.feature.geometry.getBounds().getCenterLonLat();
-        var centerPx = this.map.getViewPortPxFromLonLat(centerLonLat);
 
-        //This works for positioning with the anchor on the bottom.
-        
-        //Will have to functionalize this out later and allow
-        //for other positions relative to the feature.
-        var anchorSelector = "div." + this.ancCls;
+        if(this._mapMove === true) {
+            var visible = this.map.getExtent().containsLonLat(centerLonLat);
+            if(visible !== this.isVisible()) {
+                this.setVisible(visible);
+            }
+        }
 
-        var dx = this.anc.down(anchorSelector).getLeft(true) +
-                            this.anc.down(anchorSelector).getWidth() / 2;
-        var dy = this.el.getHeight();
-
-        //Assuming for now that the map viewport takes up
-        //the entire area of the MapPanel
-        this.setPosition(centerPx.x - dx, centerPx.y - dy);
+        if(this.isVisible()) {
+            var centerPx = this.map.getViewPortPxFromLonLat(centerLonLat);
+            var mapBox = Ext.fly(this.map.div).getBox(); 
+    
+            //This works for positioning with the anchor on the bottom.
+            
+            //Will have to functionalize this out later and allow
+            //for other positions relative to the feature.
+            var anchorSelector = "div." + this.ancCls;
+    
+            var dx = this.anc.down(anchorSelector).getLeft(true) +
+                                this.anc.down(anchorSelector).getWidth() / 2;
+            var dy = this.el.getHeight();
+    
+            //Assuming for now that the map viewport takes up
+            //the entire area of the MapPanel
+            this.setPosition(centerPx.x + mapBox.x - dx, centerPx.y + mapBox.y - dy);
+        }
     },
 
     /** private: method[getAnchorElement]
@@ -228,30 +237,13 @@
         return anc;
     },
 
-    /** private: method[anchorPopup]
-     *  Anchors a popup to its feature by registering listeners that reposition
-     *  the popup when the map is moved.
-     */
-    anchorPopup: function() {
-        this.map.events.on({
-            "move" : this.position,
-            scope : this            
-        });
-
-        this.on({
-            "resize": this.position,
-            "collapse": this.position,
-            "expand": this.position,
-            scope: this
-        });
-    },
-
     /** private: method[unanchorPopup]
      *  Unanchors a popup from its feature.  This removes the popup from its
      *  MapPanel and adds it to the page body.
      */
     unanchorPopup: function() {
-
+        this.removeAnchorEvents();
+        
         //make the window draggable
         this.draggable = true;
         this.header.addClass("x-window-draggable");
@@ -263,70 +255,24 @@
 
         //hide unpin tool
         this.tools.unpin.hide();
-
-        //keep track of whether the popup has been collapsed
-        var collapsed = this.collapsed;
-
-        //Steps to move this window out to the body
-        //TODO: Make 'unpinned' container configurable
-        this.mapPanel.remove(this, false);
-
-        this.container = Ext.getBody();
-        
-        var xy = this.getPosition();
-        this.hide();
-        this.el.appendTo(Ext.getBody());
-        this.setPagePosition(xy[0],xy[1]);
-        this.show();
-
-        //recollapse if it was collapsed before
-        if(collapsed) {
-            this.collapse();
-        }
     },
 
-    /** private: method[removeFromMapPanel]
-     *  Utility method for unbinding events that call for popup repositioning.
-     *  Called from the panel during panel.remove(popup).
-     */
-    removeFromMapPanel: function() {
-        if(this.map && this.map.events) {
-            //stop position with feature
-            this.map.events.un({
-                "move" : this.position,
-                scope : this
-            });
-        }
-
-        this.un("resize", this.position, this);
-        this.un("collapse", this.position, this);
-        this.un("expand", this.position, this);
-
-        delete this.mapPanel;
-        delete this.map;
-    },
-
     /** private: method[panIntoView]
      *  Pans the MapPanel's map so that an anchored popup can come entirely
      *  into view, with padding specified as per normal OpenLayers.Map popup
      *  padding.
      */ 
     panIntoView: function() {
-        if(!this.anchored) {
-            /*
-             * If it's not anchored, panning the map won't put popup into view
-             */
-            return;
-        }
-        this.position();
-        
-        var centerLonLat = this.feature.geometry.getBounds().getCenterLonLat(); 
+        var centerLonLat = this.feature.geometry.getBounds().getCenterLonLat();
         var centerPx = this.map.getViewPortPxFromLonLat(centerLonLat);
+        var mapBox = Ext.fly(this.map.div).getBox(); 
 
         //assumed viewport takes up whole body element of map panel
         var popupPos =  this.getPosition(true);
+        popupPos[0] -= mapBox.x;
+        popupPos[1] -= mapBox.y;
        
-        var panelSize = [this.mapPanel.getInnerWidth(), this.mapPanel.getInnerHeight()]; // [X,Y]
+        var panelSize = [mapBox.width, mapBox.height]; // [X,Y]
 
         var popupSize = this.getSize();
 
@@ -354,15 +300,56 @@
 
         this.map.pan(dx, dy);
     },
+    
+    /** private: method[onMapMove]
+     */
+    onMapMove: function() {
+        this._mapMove = true;
+        this.position();
+        delete this._mapMove;
+    },
+    
+    /** private: method[addAnchorEvents]
+     */
+    addAnchorEvents: function() {
+        this.map.events.on({
+            "move" : this.onMapMove,
+            scope : this            
+        });
+        
+        this.on({
+            "resize": this.position,
+            "collapse": this.position,
+            "expand": this.position,
+            scope: this
+        });
+    },
+    
+    /** private: method[removeAnchorEvents]
+     */
+    removeAnchorEvents: function() {
+        //stop position with feature
+        this.map.events.un({
+            "move" : this.onMapMove,
+            scope : this
+        });
 
+        this.un("resize", this.position, this);
+        this.un("collapse", this.position, this);
+        this.un("expand", this.position, this);
+
+    },
+
     /** private: method[beforeDestroy]
      *  Cleanup events before destroying the popup.
      */
     beforeDestroy: function() {
-        this.removeFromMapPanel();
+        if(this.anchored) {
+            this.removeAnchorEvents();
+        }
         GeoExt.Popup.superclass.beforeDestroy.call(this);
     }
 });
 
-/** api: xtype = gx_mappanel */
+/** api: xtype = gx_popup */
 Ext.reg('gx_popup', GeoExt.Popup); 

Copied: sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/ZoomSlider.js (from rev 1281, core/trunk/geoext/lib/GeoExt/widgets/ZoomSlider.js)
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/ZoomSlider.js	                        (rev 0)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/ZoomSlider.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -0,0 +1,264 @@
+/**
+ * Copyright (c) 2008-2009 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/widgets/tips/ZoomSliderTip.js
+ */
+
+/** api: (define)
+ *  module = GeoExt
+ *  class = ZoomSlider
+ *  base_link = `Ext.Slider <http://extjs.com/deploy/dev/docs/?class=Ext.Slider>`_
+ */
+Ext.namespace("GeoExt");
+
+/** api: example
+ *  Sample code to render a slider outside the map viewport:
+ * 
+ *  .. code-block:: javascript
+ *     
+ *      var slider = new GeoExt.ZoomSlider({
+ *          renderTo: document.body,
+ *          width: 200,
+ *          map: map
+ *      });
+ *     
+ *  Sample code to add a slider to a map panel:
+ * 
+ *  .. code-block:: javascript
+ * 
+ *      var panel = new GeoExt.MapPanel({
+ *          renderTo: document.body,
+ *          height: 300,
+ *          width: 400,
+ *          map: {
+ *              controls: [new OpenLayers.Control.Navigation()]
+ *          },
+ *          layers: [new OpenLayers.Layer.WMS(
+ *              "Global Imagery",
+ *              "http://demo.opengeo.org/geoserver/wms",
+ *              {layers: "bluemarble"}
+ *          )],
+ *          extent: [-5, 35, 15, 55],
+ *          items: [{
+ *              xtype: "gx_zoomslider",
+ *              aggressive: true,
+ *              vertical: true,
+ *              height: 100,
+ *              x: 10,
+ *              y: 20
+ *          }]
+ *      });
+ */
+
+/** api: constructor
+ *  .. class:: ZoomSlider(config)
+ *   
+ *      Create a slider for controlling a map's zoom level.
+ */
+GeoExt.ZoomSlider = Ext.extend(Ext.Slider, {
+    
+    /** api: config[map]
+     *  ``OpenLayers.Map`` or :class:`GeoExt.MapPanel`
+     *  The map that the slider controls.
+     */
+    map: null,
+    
+    /** api: config[baseCls]
+     *  ``String``
+     *  The CSS class name for the slider elements.  Default is "gx-zoomslider".
+     */
+    baseCls: "gx-zoomslider",
+
+    /** api: config[aggressive]
+     *  ``Boolean``
+     *  If set to true, the map is zoomed as soon as the thumb is moved. Otherwise 
+     *  the map is zoomed when the thumb is released (default).
+     */
+    aggressive: false,
+    
+    /** private: property[updating]
+     *  ``Boolean``
+     *  The slider position is being updated by itself (based on map zoomend).
+     */
+    updating: false,
+    
+    /** private: method[initComponent]
+     *  Initialize the component.
+     */
+    initComponent: function() {
+        GeoExt.ZoomSlider.superclass.initComponent.call(this);
+        
+        if(this.map) {
+            if(this.map instanceof GeoExt.MapPanel) {
+                this.map = this.map.map;
+            }
+            this.bind(this.map);
+        }
+
+        if (this.aggressive === true) {
+            this.on('change', this.changeHandler, this);
+        } else {
+            this.on('changecomplete', this.changeHandler, this);
+        }
+        this.on("beforedestroy", this.unbind, this);        
+    },
+    
+    /** private: method[onRender]
+     *  Override onRender to set base css class.
+     */
+    onRender: function() {
+        GeoExt.ZoomSlider.superclass.onRender.apply(this, arguments);
+        this.el.addClass(this.baseCls);
+    },
+
+    /** private: method[afterRender]
+     *  Override afterRender because the render event is fired too early
+     *  to call update.
+     */
+    afterRender : function(){
+        Ext.Slider.superclass.afterRender.apply(this, arguments);
+        this.update();
+    },
+    
+    /** 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({
+            render: function() {
+                var el = this.getEl();
+                el.setStyle({
+                    position: "absolute",
+                    zIndex: panel.map.Z_INDEX_BASE.Control
+                });
+                el.on({
+                    mousedown: this.stopMouseEvents,
+                    click: this.stopMouseEvents
+                });
+            },
+            scope: this
+        });
+        this.bind(panel.map);
+    },
+    
+    /** 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[bind]
+     *  :param map: ``OpenLayers.Map``
+     */
+    bind: function(map) {
+        this.map = map;
+        this.map.events.on({
+            zoomend: this.update,
+            changebaselayer: this.initZoomValues,
+            scope: this
+        });
+        if(this.map.baseLayer) {
+            this.initZoomValues();
+        }
+    },
+    
+    /** private: method[unbind]
+     */
+    unbind: function() {
+        if(this.map) {
+            this.map.events.un({
+                zoomend: this.update,
+                changebaselayer: this.initZoomValues,
+                scope: this
+            });
+        }
+    },
+    
+    /** private: method[initZoomValues]
+     *  Set the min/max values for the slider if not set in the config.
+     */
+    initZoomValues: function() {
+        var layer = this.map.baseLayer;
+        if(this.initialConfig.minValue === undefined) {
+            this.minValue = layer.minZoomLevel || 0;
+        }
+        if(this.initialConfig.maxValue === undefined) {
+            this.maxValue = layer.maxZoomLevel || layer.numZoomLevels - 1;
+        }
+    },
+    
+    /** api: method[getZoom]
+     *  :return: ``Number`` The map zoom level.
+     *  
+     *  Get the zoom level for the associated map based on the slider value.
+     */
+    getZoom: function() {
+        return this.getValue();
+    },
+    
+    /** api: method[getScale]
+     *  :return: ``Number`` The map scale denominator.
+     *  
+     *  Get the scale denominator for the associated map based on the slider value.
+     */
+    getScale: function() {
+        return OpenLayers.Util.getScaleFromResolution(
+            this.map.getResolutionForZoom(this.getValue()),
+            this.map.getUnits()
+        );
+    },
+    
+    /** api: method[getResolution]
+     *  :return: ``Number`` The map resolution.
+     *  
+     *  Get the resolution for the associated map based on the slider value.
+     */
+    getResolution: function() {
+        return this.map.getResolutionForZoom(this.getValue());
+    },
+    
+    /** private: method[changeHandler]
+     *  Registered as a listener for slider changecomplete.  Zooms the map.
+     */
+    changeHandler: function() {
+        if(this.map && !this.updating) {
+            this.map.zoomTo(this.getValue());
+        }
+    },
+    
+    /** private: method[update]
+     *  Registered as a listener for map zoomend.  Updates the value of the slider.
+     */
+    update: function() {
+        if(this.rendered && this.map) {
+            this.updating = true;
+            this.setValue(this.map.getZoom());
+            this.updating = false;
+        }
+    }
+
+});
+
+/** api: xtype = gx_zoomslider */
+Ext.reg('gx_zoomslider', GeoExt.ZoomSlider);

Modified: sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/form/BasicForm.js
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/form/BasicForm.js	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/form/BasicForm.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,9 +1,10 @@
-/* Copyright (C) 2008-2009 The Open Source Geospatial Foundation
+/**
+ * Copyright (c) 2008-2009 The Open Source Geospatial Foundation
+ * 
  * Published under the BSD license.
- * See http://geoext.org/svn/geoext/core/trunk/license.txt for the full text
+ * See http://svn.geoext.org/core/trunk/geoext/license.txt for the full text
  * of the license.
- * 
- * pending approval */
+ */
 
 /**
  * @include GeoExt/widgets/form/SearchAction.js

Modified: sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/form/FormPanel.js
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/form/FormPanel.js	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/form/FormPanel.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,9 +1,10 @@
-/* Copyright (C) 2008-2009 The Open Source Geospatial Foundation
+/**
+ * Copyright (c) 2008-2009 The Open Source Geospatial Foundation
+ * 
  * Published under the BSD license.
- * See http://geoext.org/svn/geoext/core/trunk/license.txt for the full text
+ * See http://svn.geoext.org/core/trunk/geoext/license.txt for the full text
  * of the license.
- * 
- * pending approval */
+ */
 
 /** api: (define)
  *  module = GeoExt.form

Modified: sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/form/SearchAction.js
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/form/SearchAction.js	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/form/SearchAction.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,9 +1,10 @@
-/* Copyright (C) 2008-2009 The Open Source Geospatial Foundation
+/**
+ * Copyright (c) 2008-2009 The Open Source Geospatial Foundation
+ * 
  * Published under the BSD license.
- * See http://geoext.org/svn/geoext/core/trunk/license.txt for the full text
+ * See http://svn.geoext.org/core/trunk/geoext/license.txt for the full text
  * of the license.
- * 
- * pending approval */
+ */
 
 /** api: (define)
  *  module = GeoExt.form

Modified: sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/form.js
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/form.js	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/form.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,26 +1,23 @@
-/* Copyright (C) 2008-2009 The Open Source Geospatial Foundation
+/**
+ * Copyright (c) 2008-2009 The Open Source Geospatial Foundation
+ * 
  * Published under the BSD license.
- * See http://geoext.org/svn/geoext/core/trunk/license.txt for the full text
+ * See http://svn.geoext.org/core/trunk/geoext/license.txt for the full text
  * of the license.
- * 
- * pending approval */
+ */
 
 Ext.namespace("GeoExt.form");
 
-/**
- * Function: GeoExt.form.toFilter
- * Create an {OpenLayers.Filter} object from a {Ext.form.BasicForm}
- *     or a {Ext.form.FormPanel} instance.
- *
- * Parameters:
- * form - {Ext.form.BasicForm|Ext.form.FormPanel}
- * logicalOp - {String} Either {OpenLayers.Filter.Logical.AND}
- *     or {OpenLayers.Filter.Logical.OR}, set to
- *     {OpenLayers.Filter.Logical.AND} if null or
- *     undefined.
- *
- * Returns:
- * {OpenLayers.Filter}
+/** private: function[toFilter]
+ *  :param form: ``Ext.form.BasicForm|Ext.form.FormPanel``
+ *  :param logicalOp: ``String`` Either ``OpenLayers.Filter.Logical.AND`` or
+ *      ``OpenLayers.Filter.Logical.OR``, set to
+ *      ``OpenLayers.Filter.Logical.AND`` if null or undefined
+ *      
+ *  :return: ``OpenLayers.Filter``
+ *  
+ *  Create an {OpenLayers.Filter} object from a {Ext.form.BasicForm}
+ *      or a {Ext.form.FormPanel} instance.
  */
 GeoExt.form.toFilter = function(form, logicalOp) {
     if(form instanceof Ext.form.FormPanel) {
@@ -54,10 +51,9 @@
     });
 };
 
-/**
- * Constant: GeoExt.form.omForm.FILTER_MAP
- * An object mapping operator strings as found in field names to
- *     {OpenLayers.Filter.Comparison} types.
+/** private: constant[FILTER_MAP]
+ *  An object mapping operator strings as found in field names to
+ *      ``OpenLayers.Filter.Comparison`` types.
  */
 GeoExt.form.toFilter.FILTER_MAP = {
     "eq": OpenLayers.Filter.Comparison.EQUAL_TO,

Copied: sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/grid (from rev 1281, core/trunk/geoext/lib/GeoExt/widgets/grid)

Deleted: sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/grid/FeatureSelectionModel.js
===================================================================
--- core/trunk/geoext/lib/GeoExt/widgets/grid/FeatureSelectionModel.js	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/grid/FeatureSelectionModel.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,316 +0,0 @@
-/**
- * Copyright (c) 2008-2009 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.
- */
-
-/** api: (define)
- *  module = GeoExt.grid
- *  class = FeatureSelectionModel
- *  base_link = `Ext.grid.RowSelectionModel <http://extjs.com/deploy/dev/docs/?class=Ext.grid.RowSelectionModel>`_
- */
-
-Ext.namespace('GeoExt.grid');
-
-/** api: constructor
- *  .. class:: FeatureSelectionModel
- *
- *      A row selection model which enables automatic selection of features
- *      in the map when rows are selected in the grid and vice-versa.
- */
-
-/** api: example
- *  Sample code to create a feature grid with a feature selection model:
- *  
- *  .. code-block:: javascript
- *
- *       var gridPanel = new Ext.grid.GridPanel({
- *          title: "Feature Grid",
- *          region: "east",
- *          store: store,
- *          width: 320,
- *          columns: [{
- *              header: "Name",
- *              width: 200,
- *              dataIndex: "name"
- *          }, {
- *              header: "Elevation",
- *              width: 100,
- *              dataIndex: "elevation"
- *          }],
- *          sm: new GeoExt.grid.FeatureSelectionModel() 
- *      });
- */
-
-GeoExt.grid.FeatureSelectionModelMixin = {
-
-    /** api: config[autoActivateControl]
-     *  ``Boolean`` If true the select feature control is activated and
-     *  deactivated when binding and unbinding. Defaults to true.
-     */
-    autoActivateControl: true,
-
-    /** api: config[layerFromStore]
-     *  ``Boolean`` If true, and if the constructor is passed neither a
-     *  layer nor a select feature control, a select feature control is
-     *  created using the layer found in the grid's store. Set it to
-     *  false if you want to manually bind the selection model to a
-     *  layer. Defaults to true.
-     */
-    layerFromStore: true,
-
-    /** api: config[selectControl]
-     *
-     *  ``OpenLayers.Control.SelectFeature`` A select feature control. If not
-     *  provided one will be created.  If provided any "layer" config option
-     *  will be ignored, and its "multiple" option will be used to configure
-     *  the selectionModel.  If an ``Object`` is provided here, it will be
-     *  passed as config to the SelectFeature constructor, and the "layer"
-     *  config option will be used for the layer.
-     */
-
-    /** private: property[selectControl] 
-     *  ``OpenLayers.Control.SelectFeature`` The select feature control 
-     *  instance. 
-     */ 
-    selectControl: null, 
-    
-    /** api: config[layer]
-     *  ``OpenLayers.Layer.Vector`` The vector layer used for the creation of
-     *  the select feature control, it must already be added to the map. If not
-     *  provided, the layer bound to the grid's store, if any, will be used.
-     */
-
-    /** private: property[bound]
-     *  ``Boolean`` Flag indicating if the selection model is bound.
-     */
-    bound: false,
-    
-    /** private: property[superclass]
-     *  ``Ext.grid.AbstractSelectionModel`` Our superclass.
-     */
-    superclass: null,
-
-    /** private */
-    constructor: function(config) {
-        config = config || {};
-        if(config.selectControl instanceof OpenLayers.Control.SelectFeature) { 
-            if(!config.singleSelect) {
-                var ctrl = config.selectControl;
-                config.singleSelect = !(ctrl.multiple || !!ctrl.multipleKey);
-            }
-        } else if(config.layer instanceof OpenLayers.Layer.Vector) {
-            this.selectControl = this.createSelectControl(
-                config.layer, config.selectControl
-            );
-            delete config.layer;
-            delete config.selectControl;
-        }
-        this.superclass = arguments.callee.superclass;
-        this.superclass.constructor.call(this, config);
-    },
-    
-    /** private: method[initEvents]
-     *
-     *  Called after this.grid is defined
-     */
-    initEvents: function() {
-        this.superclass.initEvents.call(this);
-        if(this.layerFromStore) {
-            var layer = this.grid.getStore() && this.grid.getStore().layer;
-            if(layer &&
-               !(this.selectControl instanceof OpenLayers.Control.SelectFeature)) {
-                this.selectControl = this.createSelectControl(
-                    layer, this.selectControl
-                );
-            }
-        }
-        if(this.selectControl) {
-            this.bind(this.selectControl);
-        }
-    },
-
-    /** private: createSelectControl
-     *  :param layer: ``OpenLayers.Layer.Vector`` The vector layer.
-     *  :param config: ``Object`` The select feature control config.
-     *
-     *  Create the select feature control.
-     */
-    createSelectControl: function(layer, config) {
-        config = config || {};
-        var singleSelect = config.singleSelect !== undefined ?
-                           config.singleSelect : this.singleSelect;
-        config = OpenLayers.Util.extend({
-            toggle: true,
-            multipleKey: singleSelect ? null :
-                (Ext.isMac ? "metaKey" : "ctrlKey")
-        }, config);
-        var selectControl = new OpenLayers.Control.SelectFeature(
-            layer, config
-        );
-        layer.map.addControl(selectControl);
-        return selectControl;
-    },
-    
-    /** api: method[bind]
-     *
-     *  :param obj: ``OpenLayers.Layer.Vector`` or
-     *  ``OpenLayers.Control.SelectFeature`` The object this selection model
-     *      should be bound to, either a vector layeer or a select feature
-     *      control.
-     *  :param options: ``Object`` An object with a "controlConfig"
-     *      property referencing the configuration object to pass to the
-     *      ``OpenLayers.Control.SelectFeature`` constructor.
-     *  :return: ``OpenLayers.Control.SelectFeature`` The select feature
-     *  control this selection model uses.
-     *
-     *  Bind the selection model to a layer or a SelectFeature control.
-     */
-    bind: function(obj, options) {
-        if(!this.bound) {
-            options = options || {};
-            this.selectControl = obj;
-            if(obj instanceof OpenLayers.Layer.Vector) {
-                this.selectControl = this.createSelectControl(
-                    obj, options.controlConfig
-                );
-            }
-            if(this.autoActivateControl) {
-                this.selectControl.activate();
-            }
-            var layers = this.getLayers();
-            for(var i = 0, len = layers.length; i < len; i++) {
-                layers[i].events.on({
-                    featureselected: this.featureSelected,
-                    featureunselected: this.featureUnselected,
-                    scope: this
-                });
-            }
-            this.on("rowselect", this.rowSelected, this);
-            this.on("rowdeselect", this.rowDeselected, this);
-            this.bound = true;
-        }
-        return this.selectControl;
-    },
-    
-    /** api: method[unbind]
-     *  :return: ``OpenLayers.Control.SelectFeature`` The select feature
-     *      control this selection model used.
-     *
-     *  Unbind the selection model from the layer or SelectFeature control.
-     */
-    unbind: function() {
-        var selectControl = this.selectControl;
-        if(this.bound) {
-            var layers = this.getLayers();
-            for(var i = 0, len = layers.length; i < len; i++) {
-                layers[i].events.un({
-                    featureselected: this.featureSelected,
-                    featureunselected: this.featureUnselected,
-                    scope: this
-                });
-            }
-            this.un("rowselect", this.rowSelected, this);
-            this.un("rowdeselect", this.rowDeselected, this);
-            if(this.autoActivateControl) {
-                selectControl.deactivate();
-            }
-            this.selectControl = null;
-            this.bound = false;
-        }
-        return selectControl;
-    },
-    
-    /** private: method[featureSelected]
-     *  :param evt: ``Object`` An object with a feature property referencing
-     *                         the selected feature.
-     */
-    featureSelected: function(evt) {
-        if(!this._selecting) {
-            var store = this.grid.store;
-            var row = store.findBy(function(record, id) {
-                return record.data.feature == evt.feature;
-            });
-            if(row != -1 && !this.isSelected(row)) {
-                this._selecting = true;
-                this.selectRow(row, !this.singleSelect);
-                this._selecting = false;
-                // focus the row in the grid to ensure it is visible
-                this.grid.getView().focusRow(row);
-            }
-        }
-    },
-    
-    /** private: method[featureUnselected]
-     *  :param evt: ``Object`` An object with a feature property referencing
-     *                         the unselected feature.
-     */
-    featureUnselected: function(evt) {
-        if(!this._selecting) {
-            var store = this.grid.store;
-            var row = store.findBy(function(record, id) {
-                return record.data.feature == evt.feature;
-            });
-            if(row != -1 && this.isSelected(row)) {
-                this._selecting = true;
-                this.deselectRow(row); 
-                this._selecting = false;
-                this.grid.getView().focusRow(row);
-            }
-        }
-    },
-    
-    /** private: method[rowSelected]
-     *  :param model: ``Ext.grid.RowSelectModel`` The row select model.
-     *  :param row: ``Integer`` The row index.
-     *  :param record: ``Ext.data.Record`` The record.
-     */
-    rowSelected: function(model, row, record) {
-        var feature = record.data.feature;
-        if(!this._selecting && feature) {
-            var layers = this.getLayers();
-            for(var i = 0, len = layers.length; i < len; i++) {
-                if(layers[i].selectedFeatures.indexOf(feature) == -1) {
-                    this._selecting = true;
-                    this.selectControl.select(feature);
-                    this._selecting = false;
-                    break;
-                }
-            }
-         }
-    },
-    
-    /** private: method[rowDeselected]
-     *  :param model: ``Ext.grid.RowSelectModel`` The row select model.
-     *  :param row: ``Integer`` The row index.
-     *  :param record: ``Ext.data.Record`` The record.
-     */
-    rowDeselected: function(model, row, record) {
-        var feature = record.data.feature;
-        if(!this._selecting && feature) {
-            var layers = this.getLayers();
-            for(var i = 0, len = layers.length; i < len; i++) {
-                if(layers[i].selectedFeatures.indexOf(feature) != -1) {
-                    this._selecting = true;
-                    this.selectControl.unselect(feature);
-                    this._selecting = false;
-                    break;
-                }
-            }
-        }
-    },
-
-    /** private: method[getLayers]
-     *  Return the layers attached to the select feature control.
-     */
-    getLayers: function() {
-        return this.selectControl.layers || [this.selectControl.layer];
-    }
-};
-
-GeoExt.grid.FeatureSelectionModel = Ext.extend(
-    Ext.grid.RowSelectionModel,
-    GeoExt.grid.FeatureSelectionModelMixin
-);

Copied: sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/grid/FeatureSelectionModel.js (from rev 1281, core/trunk/geoext/lib/GeoExt/widgets/grid/FeatureSelectionModel.js)
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/grid/FeatureSelectionModel.js	                        (rev 0)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/grid/FeatureSelectionModel.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -0,0 +1,316 @@
+/**
+ * Copyright (c) 2008-2009 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.
+ */
+
+/** api: (define)
+ *  module = GeoExt.grid
+ *  class = FeatureSelectionModel
+ *  base_link = `Ext.grid.RowSelectionModel <http://extjs.com/deploy/dev/docs/?class=Ext.grid.RowSelectionModel>`_
+ */
+
+Ext.namespace('GeoExt.grid');
+
+/** api: constructor
+ *  .. class:: FeatureSelectionModel
+ *
+ *      A row selection model which enables automatic selection of features
+ *      in the map when rows are selected in the grid and vice-versa.
+ */
+
+/** api: example
+ *  Sample code to create a feature grid with a feature selection model:
+ *  
+ *  .. code-block:: javascript
+ *
+ *       var gridPanel = new Ext.grid.GridPanel({
+ *          title: "Feature Grid",
+ *          region: "east",
+ *          store: store,
+ *          width: 320,
+ *          columns: [{
+ *              header: "Name",
+ *              width: 200,
+ *              dataIndex: "name"
+ *          }, {
+ *              header: "Elevation",
+ *              width: 100,
+ *              dataIndex: "elevation"
+ *          }],
+ *          sm: new GeoExt.grid.FeatureSelectionModel() 
+ *      });
+ */
+
+GeoExt.grid.FeatureSelectionModelMixin = {
+
+    /** api: config[autoActivateControl]
+     *  ``Boolean`` If true the select feature control is activated and
+     *  deactivated when binding and unbinding. Defaults to true.
+     */
+    autoActivateControl: true,
+
+    /** api: config[layerFromStore]
+     *  ``Boolean`` If true, and if the constructor is passed neither a
+     *  layer nor a select feature control, a select feature control is
+     *  created using the layer found in the grid's store. Set it to
+     *  false if you want to manually bind the selection model to a
+     *  layer. Defaults to true.
+     */
+    layerFromStore: true,
+
+    /** api: config[selectControl]
+     *
+     *  ``OpenLayers.Control.SelectFeature`` A select feature control. If not
+     *  provided one will be created.  If provided any "layer" config option
+     *  will be ignored, and its "multiple" option will be used to configure
+     *  the selectionModel.  If an ``Object`` is provided here, it will be
+     *  passed as config to the SelectFeature constructor, and the "layer"
+     *  config option will be used for the layer.
+     */
+
+    /** private: property[selectControl] 
+     *  ``OpenLayers.Control.SelectFeature`` The select feature control 
+     *  instance. 
+     */ 
+    selectControl: null, 
+    
+    /** api: config[layer]
+     *  ``OpenLayers.Layer.Vector`` The vector layer used for the creation of
+     *  the select feature control, it must already be added to the map. If not
+     *  provided, the layer bound to the grid's store, if any, will be used.
+     */
+
+    /** private: property[bound]
+     *  ``Boolean`` Flag indicating if the selection model is bound.
+     */
+    bound: false,
+    
+    /** private: property[superclass]
+     *  ``Ext.grid.AbstractSelectionModel`` Our superclass.
+     */
+    superclass: null,
+
+    /** private */
+    constructor: function(config) {
+        config = config || {};
+        if(config.selectControl instanceof OpenLayers.Control.SelectFeature) { 
+            if(!config.singleSelect) {
+                var ctrl = config.selectControl;
+                config.singleSelect = !(ctrl.multiple || !!ctrl.multipleKey);
+            }
+        } else if(config.layer instanceof OpenLayers.Layer.Vector) {
+            this.selectControl = this.createSelectControl(
+                config.layer, config.selectControl
+            );
+            delete config.layer;
+            delete config.selectControl;
+        }
+        this.superclass = arguments.callee.superclass;
+        this.superclass.constructor.call(this, config);
+    },
+    
+    /** private: method[initEvents]
+     *
+     *  Called after this.grid is defined
+     */
+    initEvents: function() {
+        this.superclass.initEvents.call(this);
+        if(this.layerFromStore) {
+            var layer = this.grid.getStore() && this.grid.getStore().layer;
+            if(layer &&
+               !(this.selectControl instanceof OpenLayers.Control.SelectFeature)) {
+                this.selectControl = this.createSelectControl(
+                    layer, this.selectControl
+                );
+            }
+        }
+        if(this.selectControl) {
+            this.bind(this.selectControl);
+        }
+    },
+
+    /** private: createSelectControl
+     *  :param layer: ``OpenLayers.Layer.Vector`` The vector layer.
+     *  :param config: ``Object`` The select feature control config.
+     *
+     *  Create the select feature control.
+     */
+    createSelectControl: function(layer, config) {
+        config = config || {};
+        var singleSelect = config.singleSelect !== undefined ?
+                           config.singleSelect : this.singleSelect;
+        config = OpenLayers.Util.extend({
+            toggle: true,
+            multipleKey: singleSelect ? null :
+                (Ext.isMac ? "metaKey" : "ctrlKey")
+        }, config);
+        var selectControl = new OpenLayers.Control.SelectFeature(
+            layer, config
+        );
+        layer.map.addControl(selectControl);
+        return selectControl;
+    },
+    
+    /** api: method[bind]
+     *
+     *  :param obj: ``OpenLayers.Layer.Vector`` or
+     *  ``OpenLayers.Control.SelectFeature`` The object this selection model
+     *      should be bound to, either a vector layeer or a select feature
+     *      control.
+     *  :param options: ``Object`` An object with a "controlConfig"
+     *      property referencing the configuration object to pass to the
+     *      ``OpenLayers.Control.SelectFeature`` constructor.
+     *  :return: ``OpenLayers.Control.SelectFeature`` The select feature
+     *  control this selection model uses.
+     *
+     *  Bind the selection model to a layer or a SelectFeature control.
+     */
+    bind: function(obj, options) {
+        if(!this.bound) {
+            options = options || {};
+            this.selectControl = obj;
+            if(obj instanceof OpenLayers.Layer.Vector) {
+                this.selectControl = this.createSelectControl(
+                    obj, options.controlConfig
+                );
+            }
+            if(this.autoActivateControl) {
+                this.selectControl.activate();
+            }
+            var layers = this.getLayers();
+            for(var i = 0, len = layers.length; i < len; i++) {
+                layers[i].events.on({
+                    featureselected: this.featureSelected,
+                    featureunselected: this.featureUnselected,
+                    scope: this
+                });
+            }
+            this.on("rowselect", this.rowSelected, this);
+            this.on("rowdeselect", this.rowDeselected, this);
+            this.bound = true;
+        }
+        return this.selectControl;
+    },
+    
+    /** api: method[unbind]
+     *  :return: ``OpenLayers.Control.SelectFeature`` The select feature
+     *      control this selection model used.
+     *
+     *  Unbind the selection model from the layer or SelectFeature control.
+     */
+    unbind: function() {
+        var selectControl = this.selectControl;
+        if(this.bound) {
+            var layers = this.getLayers();
+            for(var i = 0, len = layers.length; i < len; i++) {
+                layers[i].events.un({
+                    featureselected: this.featureSelected,
+                    featureunselected: this.featureUnselected,
+                    scope: this
+                });
+            }
+            this.un("rowselect", this.rowSelected, this);
+            this.un("rowdeselect", this.rowDeselected, this);
+            if(this.autoActivateControl) {
+                selectControl.deactivate();
+            }
+            this.selectControl = null;
+            this.bound = false;
+        }
+        return selectControl;
+    },
+    
+    /** private: method[featureSelected]
+     *  :param evt: ``Object`` An object with a feature property referencing
+     *                         the selected feature.
+     */
+    featureSelected: function(evt) {
+        if(!this._selecting) {
+            var store = this.grid.store;
+            var row = store.findBy(function(record, id) {
+                return record.data.feature == evt.feature;
+            });
+            if(row != -1 && !this.isSelected(row)) {
+                this._selecting = true;
+                this.selectRow(row, !this.singleSelect);
+                this._selecting = false;
+                // focus the row in the grid to ensure it is visible
+                this.grid.getView().focusRow(row);
+            }
+        }
+    },
+    
+    /** private: method[featureUnselected]
+     *  :param evt: ``Object`` An object with a feature property referencing
+     *                         the unselected feature.
+     */
+    featureUnselected: function(evt) {
+        if(!this._selecting) {
+            var store = this.grid.store;
+            var row = store.findBy(function(record, id) {
+                return record.data.feature == evt.feature;
+            });
+            if(row != -1 && this.isSelected(row)) {
+                this._selecting = true;
+                this.deselectRow(row); 
+                this._selecting = false;
+                this.grid.getView().focusRow(row);
+            }
+        }
+    },
+    
+    /** private: method[rowSelected]
+     *  :param model: ``Ext.grid.RowSelectModel`` The row select model.
+     *  :param row: ``Integer`` The row index.
+     *  :param record: ``Ext.data.Record`` The record.
+     */
+    rowSelected: function(model, row, record) {
+        var feature = record.data.feature;
+        if(!this._selecting && feature) {
+            var layers = this.getLayers();
+            for(var i = 0, len = layers.length; i < len; i++) {
+                if(layers[i].selectedFeatures.indexOf(feature) == -1) {
+                    this._selecting = true;
+                    this.selectControl.select(feature);
+                    this._selecting = false;
+                    break;
+                }
+            }
+         }
+    },
+    
+    /** private: method[rowDeselected]
+     *  :param model: ``Ext.grid.RowSelectModel`` The row select model.
+     *  :param row: ``Integer`` The row index.
+     *  :param record: ``Ext.data.Record`` The record.
+     */
+    rowDeselected: function(model, row, record) {
+        var feature = record.data.feature;
+        if(!this._selecting && feature) {
+            var layers = this.getLayers();
+            for(var i = 0, len = layers.length; i < len; i++) {
+                if(layers[i].selectedFeatures.indexOf(feature) != -1) {
+                    this._selecting = true;
+                    this.selectControl.unselect(feature);
+                    this._selecting = false;
+                    break;
+                }
+            }
+        }
+    },
+
+    /** private: method[getLayers]
+     *  Return the layers attached to the select feature control.
+     */
+    getLayers: function() {
+        return this.selectControl.layers || [this.selectControl.layer];
+    }
+};
+
+GeoExt.grid.FeatureSelectionModel = Ext.extend(
+    Ext.grid.RowSelectionModel,
+    GeoExt.grid.FeatureSelectionModelMixin
+);

Copied: sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tips (from rev 1281, core/trunk/geoext/lib/GeoExt/widgets/tips)

Deleted: sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tips/LayerOpacitySliderTip.js
===================================================================
--- core/trunk/geoext/lib/GeoExt/widgets/tips/LayerOpacitySliderTip.js	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tips/LayerOpacitySliderTip.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,78 +0,0 @@
-/**
- * Copyright (c) 2008-2009 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.
- */
-
-/**
- * @requires GeoExt/widgets/tips/SliderTip.js
- */
-
-/** api: (extends)
- *  GeoExt/widgets/tips/SliderTip.js
- */
-
-/** api: (define)
- *  module = GeoExt
- *  class = LayerOpacitySliderTip
- *  base_link = `Ext.Tip <http://extjs.com/deploy/dev/docs/?class=Ext.Tip>`_
- */
-Ext.namespace("GeoExt");
-
-/** api: example
- *  Sample code to create a slider tip to display scale and resolution:
- *
- *  .. code-block:: javascript
- *
- *      var slider = new GeoExt.LayerOpacitySlider({
- *          renderTo: document.body,
- *          width: 200,
- *          layer: layer,
- *          plugins: new GeoExt.LayerOpacitySliderTip({
- *              template: "Opacity: {opacity}%"
- *          })
- *      });
- */
-
-/** api: constructor
- *  .. class:: LayerOpacitySliderTip(config)
- *
- *      Create a slider tip displaying :class:`GeoExt.LayerOpacitySlider` values.
- */
-GeoExt.LayerOpacitySliderTip = Ext.extend(GeoExt.SliderTip, {
-
-    /** api: config[template]
-     *  ``String``
-     *  Template for the tip. Can be customized using the following keywords in
-     *  curly braces:
-     *
-     *  * ``opacity`` - the opacity value in percent.
-     */
-    template: '<div>{opacity}%</div>',
-
-    /** private: property[compiledTemplate]
-     *  ``Ext.Template``
-     *  The template compiled from the ``template`` string on init.
-     */
-    compiledTemplate: null,
-
-    /** private: method[init]
-     *  Called to initialize the plugin.
-     */
-    init: function(slider) {
-        this.compiledTemplate = new Ext.Template(this.template);
-        GeoExt.LayerOpacitySliderTip.superclass.init.call(this, slider);
-    },
-
-    /** private: method[getText]
-     *  :param slider: ``Ext.Slider`` The slider this tip is attached to.
-     */
-    getText: function(slider) {
-        var data = {
-            opacity: slider.getValue()
-        };
-        return this.compiledTemplate.apply(data);
-    }
-});

Copied: sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tips/LayerOpacitySliderTip.js (from rev 1281, core/trunk/geoext/lib/GeoExt/widgets/tips/LayerOpacitySliderTip.js)
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tips/LayerOpacitySliderTip.js	                        (rev 0)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tips/LayerOpacitySliderTip.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -0,0 +1,78 @@
+/**
+ * Copyright (c) 2008-2009 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.
+ */
+
+/**
+ * @requires GeoExt/widgets/tips/SliderTip.js
+ */
+
+/** api: (extends)
+ *  GeoExt/widgets/tips/SliderTip.js
+ */
+
+/** api: (define)
+ *  module = GeoExt
+ *  class = LayerOpacitySliderTip
+ *  base_link = `Ext.Tip <http://extjs.com/deploy/dev/docs/?class=Ext.Tip>`_
+ */
+Ext.namespace("GeoExt");
+
+/** api: example
+ *  Sample code to create a slider tip to display scale and resolution:
+ *
+ *  .. code-block:: javascript
+ *
+ *      var slider = new GeoExt.LayerOpacitySlider({
+ *          renderTo: document.body,
+ *          width: 200,
+ *          layer: layer,
+ *          plugins: new GeoExt.LayerOpacitySliderTip({
+ *              template: "Opacity: {opacity}%"
+ *          })
+ *      });
+ */
+
+/** api: constructor
+ *  .. class:: LayerOpacitySliderTip(config)
+ *
+ *      Create a slider tip displaying :class:`GeoExt.LayerOpacitySlider` values.
+ */
+GeoExt.LayerOpacitySliderTip = Ext.extend(GeoExt.SliderTip, {
+
+    /** api: config[template]
+     *  ``String``
+     *  Template for the tip. Can be customized using the following keywords in
+     *  curly braces:
+     *
+     *  * ``opacity`` - the opacity value in percent.
+     */
+    template: '<div>{opacity}%</div>',
+
+    /** private: property[compiledTemplate]
+     *  ``Ext.Template``
+     *  The template compiled from the ``template`` string on init.
+     */
+    compiledTemplate: null,
+
+    /** private: method[init]
+     *  Called to initialize the plugin.
+     */
+    init: function(slider) {
+        this.compiledTemplate = new Ext.Template(this.template);
+        GeoExt.LayerOpacitySliderTip.superclass.init.call(this, slider);
+    },
+
+    /** private: method[getText]
+     *  :param slider: ``Ext.Slider`` The slider this tip is attached to.
+     */
+    getText: function(slider) {
+        var data = {
+            opacity: slider.getValue()
+        };
+        return this.compiledTemplate.apply(data);
+    }
+});

Deleted: sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tips/SliderTip.js
===================================================================
--- core/trunk/geoext/lib/GeoExt/widgets/tips/SliderTip.js	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tips/SliderTip.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,126 +0,0 @@
-/**
- * Copyright (c) 2008-2009 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.
- */
-
-/** api: (define)
- *  module = GeoExt
- *  class = SliderTip
- *  base_link = `Ext.Tip <http://extjs.com/deploy/dev/docs/?class=Ext.Tip>`_
- */
-Ext.namespace("GeoExt");
-
-/** api: example
- *  Sample code to create a slider tip to display slider value on hover:
- * 
- *  .. code-block:: javascript
- *     
- *      var slider = new Ext.Slider({
- *          renderTo: document.body,
- *          width: 200,
- *          plugins: new GeoExt.SliderTip()
- *      });
- */
-
-/** api: constructor
- *  .. class:: SliderTip(config)
- *   
- *      Create a slider tip displaying ``Ext.Slider`` values over slider thumbs.
- */
-GeoExt.SliderTip = Ext.extend(Ext.Tip, {
-
-    /** api: config[hover]
-     *  ``Boolean``
-     *  Display the tip when hovering over the thumb.  If ``false``, tip will
-     *  only be displayed while dragging.  Default is ``true``.
-     */
-    hover: true,
-    
-    /** api: config[minWidth]
-     *  ``Number``
-     *  Minimum width of the tip.  Default is 10.
-     */
-    minWidth: 10,
-
-    /** api: config[minWidth]
-     *  ``Number``
-     *  Minimum width of the tip.  Default is 10.
-     */
-    minWidth: 10,
-    
-    /** api: config[offsets]
-     *  ``Array(Number)``
-     *  A two item list that provides x, y offsets for the tip.  Default is
-     *  [0, -10].
-     */
-    offsets : [0, -10],
-    
-    /** private: property[dragging]
-     *  ``Boolean``
-     *  The thumb is currently being dragged.
-     */
-    dragging: false,
-
-    /** private: method[init]
-     *  :param slider: ``Ext.Slider``
-     *  
-     *  Called when the plugin is initialized.
-     */
-    init: function(slider) {
-        slider.on({
-            dragstart: this.onSlide,
-            drag: this.onSlide,
-            dragend: this.hide,
-            destroy: this.destroy,
-            scope: this
-        });
-        if(this.hover) {
-            slider.on("render", this.registerThumbListeners, this);
-        }
-        this.slider = slider;
-    },
-
-    /** private: method[registerThumbListeners]
-     *  Set as a listener for 'render' if hover is true.
-     */
-    registerThumbListeners: function() {
-        this.slider.thumb.on({
-            "mouseover": function() {
-                this.onSlide(this.slider);
-                this.dragging = false;
-            },
-            "mouseout": function() {
-                if(!this.dragging) {
-                    this.hide.apply(this, arguments);
-                }
-            },
-            scope: this
-        });
-    },
-
-    /** private: method[onSlide]
-     *  :param slider: ``Ext.Slider``
-     *
-     *  Listener for dragstart and drag.
-     */
-    onSlide: function(slider) {
-        this.dragging = true;
-        this.show();
-        this.body.update(this.getText(slider));
-        this.doAutoWidth();
-        this.el.alignTo(slider.thumb, 'b-t?', this.offsets);
-    },
-
-    /** api: config[getText]
-     *  :param slider: ``Ext.Slider``
-     *  ``Function``
-     *  Function that generates the string value to be displayed in the tip.  By
-     *  default, the return from slider.getValue() is displayed.
-     */
-    getText : function(slider) {
-        return slider.getValue();
-    }
-});

Copied: sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tips/SliderTip.js (from rev 1281, core/trunk/geoext/lib/GeoExt/widgets/tips/SliderTip.js)
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tips/SliderTip.js	                        (rev 0)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tips/SliderTip.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -0,0 +1,126 @@
+/**
+ * Copyright (c) 2008-2009 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.
+ */
+
+/** api: (define)
+ *  module = GeoExt
+ *  class = SliderTip
+ *  base_link = `Ext.Tip <http://extjs.com/deploy/dev/docs/?class=Ext.Tip>`_
+ */
+Ext.namespace("GeoExt");
+
+/** api: example
+ *  Sample code to create a slider tip to display slider value on hover:
+ * 
+ *  .. code-block:: javascript
+ *     
+ *      var slider = new Ext.Slider({
+ *          renderTo: document.body,
+ *          width: 200,
+ *          plugins: new GeoExt.SliderTip()
+ *      });
+ */
+
+/** api: constructor
+ *  .. class:: SliderTip(config)
+ *   
+ *      Create a slider tip displaying ``Ext.Slider`` values over slider thumbs.
+ */
+GeoExt.SliderTip = Ext.extend(Ext.Tip, {
+
+    /** api: config[hover]
+     *  ``Boolean``
+     *  Display the tip when hovering over the thumb.  If ``false``, tip will
+     *  only be displayed while dragging.  Default is ``true``.
+     */
+    hover: true,
+    
+    /** api: config[minWidth]
+     *  ``Number``
+     *  Minimum width of the tip.  Default is 10.
+     */
+    minWidth: 10,
+
+    /** api: config[minWidth]
+     *  ``Number``
+     *  Minimum width of the tip.  Default is 10.
+     */
+    minWidth: 10,
+    
+    /** api: config[offsets]
+     *  ``Array(Number)``
+     *  A two item list that provides x, y offsets for the tip.  Default is
+     *  [0, -10].
+     */
+    offsets : [0, -10],
+    
+    /** private: property[dragging]
+     *  ``Boolean``
+     *  The thumb is currently being dragged.
+     */
+    dragging: false,
+
+    /** private: method[init]
+     *  :param slider: ``Ext.Slider``
+     *  
+     *  Called when the plugin is initialized.
+     */
+    init: function(slider) {
+        slider.on({
+            dragstart: this.onSlide,
+            drag: this.onSlide,
+            dragend: this.hide,
+            destroy: this.destroy,
+            scope: this
+        });
+        if(this.hover) {
+            slider.on("render", this.registerThumbListeners, this);
+        }
+        this.slider = slider;
+    },
+
+    /** private: method[registerThumbListeners]
+     *  Set as a listener for 'render' if hover is true.
+     */
+    registerThumbListeners: function() {
+        this.slider.thumb.on({
+            "mouseover": function() {
+                this.onSlide(this.slider);
+                this.dragging = false;
+            },
+            "mouseout": function() {
+                if(!this.dragging) {
+                    this.hide.apply(this, arguments);
+                }
+            },
+            scope: this
+        });
+    },
+
+    /** private: method[onSlide]
+     *  :param slider: ``Ext.Slider``
+     *
+     *  Listener for dragstart and drag.
+     */
+    onSlide: function(slider) {
+        this.dragging = true;
+        this.show();
+        this.body.update(this.getText(slider));
+        this.doAutoWidth();
+        this.el.alignTo(slider.thumb, 'b-t?', this.offsets);
+    },
+
+    /** api: config[getText]
+     *  :param slider: ``Ext.Slider``
+     *  ``Function``
+     *  Function that generates the string value to be displayed in the tip.  By
+     *  default, the return from slider.getValue() is displayed.
+     */
+    getText : function(slider) {
+        return slider.getValue();
+    }
+});

Deleted: sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tips/ZoomSliderTip.js
===================================================================
--- core/trunk/geoext/lib/GeoExt/widgets/tips/ZoomSliderTip.js	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tips/ZoomSliderTip.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,84 +0,0 @@
-/**
- * Copyright (c) 2008-2009 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.
- */
-
-/**
- * @requires GeoExt/widgets/tips/SliderTip.js
- */
-
-/** api: (extends)
- *  GeoExt/widgets/tips/SliderTip.js
- */
-
-/** api: (define)
- *  module = GeoExt
- *  class = ZoomSliderTip
- *  base_link = `Ext.Tip <http://extjs.com/deploy/dev/docs/?class=Ext.Tip>`_
- */
-Ext.namespace("GeoExt");
-
-/** api: example
- *  Sample code to create a slider tip to display scale and resolution:
- * 
- *  .. code-block:: javascript
- *     
- *      var slider = new GeoExt.ZoomSlider({
- *          renderTo: document.body,
- *          width: 200,
- *          map: map,
- *          plugins: new GeoExt.ZoomSliderTip({
- *              template: "Scale: 1 : {scale}<br>Resolution: {resolution}"
- *          })
- *      });
- */
-
-/** api: constructor
- *  .. class:: ZoomSliderTip(config)
- *   
- *      Create a slider tip displaying :class:`GeoExt.ZoomSlider` values.
- */
-GeoExt.ZoomSliderTip = Ext.extend(GeoExt.SliderTip, {
-    
-    /** api: config[template]
-     *  ``String``
-     *  Template for the tip. Can be customized using the following keywords in
-     *  curly braces:
-     *  
-     *  * ``zoom`` - the zoom level
-     *  * ``resolution`` - the resolution
-     *  * ``scale`` - the scale denominator
-     */
-    template: '<div>Zoom Level: {zoom}</div>' +
-        '<div>Resolution: {resolution}</div>' +
-        '<div>Scale: 1 : {scale}</div>',
-    
-    /** private: property[compiledTemplate]
-     *  ``Ext.Template``
-     *  The template compiled from the ``template`` string on init.
-     */
-    compiledTemplate: null,
-    
-    /** private: method[init]
-     *  Called to initialize the plugin.
-     */
-    init: function(slider) {
-        this.compiledTemplate = new Ext.Template(this.template);
-        GeoExt.ZoomSliderTip.superclass.init.call(this, slider);
-    },
-    
-    /** private: method[getText]
-     *  :param slider: ``Ext.Slider`` The slider this tip is attached to.
-     */
-    getText: function(slider) {
-        var data = {
-            zoom: slider.getZoom(),
-            resolution: slider.getResolution(),
-            scale: Math.round(slider.getScale()) 
-        };
-        return this.compiledTemplate.apply(data);
-    }
-});

Copied: sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tips/ZoomSliderTip.js (from rev 1281, core/trunk/geoext/lib/GeoExt/widgets/tips/ZoomSliderTip.js)
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tips/ZoomSliderTip.js	                        (rev 0)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tips/ZoomSliderTip.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -0,0 +1,84 @@
+/**
+ * Copyright (c) 2008-2009 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.
+ */
+
+/**
+ * @requires GeoExt/widgets/tips/SliderTip.js
+ */
+
+/** api: (extends)
+ *  GeoExt/widgets/tips/SliderTip.js
+ */
+
+/** api: (define)
+ *  module = GeoExt
+ *  class = ZoomSliderTip
+ *  base_link = `Ext.Tip <http://extjs.com/deploy/dev/docs/?class=Ext.Tip>`_
+ */
+Ext.namespace("GeoExt");
+
+/** api: example
+ *  Sample code to create a slider tip to display scale and resolution:
+ * 
+ *  .. code-block:: javascript
+ *     
+ *      var slider = new GeoExt.ZoomSlider({
+ *          renderTo: document.body,
+ *          width: 200,
+ *          map: map,
+ *          plugins: new GeoExt.ZoomSliderTip({
+ *              template: "Scale: 1 : {scale}<br>Resolution: {resolution}"
+ *          })
+ *      });
+ */
+
+/** api: constructor
+ *  .. class:: ZoomSliderTip(config)
+ *   
+ *      Create a slider tip displaying :class:`GeoExt.ZoomSlider` values.
+ */
+GeoExt.ZoomSliderTip = Ext.extend(GeoExt.SliderTip, {
+    
+    /** api: config[template]
+     *  ``String``
+     *  Template for the tip. Can be customized using the following keywords in
+     *  curly braces:
+     *  
+     *  * ``zoom`` - the zoom level
+     *  * ``resolution`` - the resolution
+     *  * ``scale`` - the scale denominator
+     */
+    template: '<div>Zoom Level: {zoom}</div>' +
+        '<div>Resolution: {resolution}</div>' +
+        '<div>Scale: 1 : {scale}</div>',
+    
+    /** private: property[compiledTemplate]
+     *  ``Ext.Template``
+     *  The template compiled from the ``template`` string on init.
+     */
+    compiledTemplate: null,
+    
+    /** private: method[init]
+     *  Called to initialize the plugin.
+     */
+    init: function(slider) {
+        this.compiledTemplate = new Ext.Template(this.template);
+        GeoExt.ZoomSliderTip.superclass.init.call(this, slider);
+    },
+    
+    /** private: method[getText]
+     *  :param slider: ``Ext.Slider`` The slider this tip is attached to.
+     */
+    getText: function(slider) {
+        var data = {
+            zoom: slider.getZoom(),
+            resolution: slider.getResolution(),
+            scale: Math.round(slider.getScale()) 
+        };
+        return this.compiledTemplate.apply(data);
+    }
+});

Modified: sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tree/BaseLayerContainer.js
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tree/BaseLayerContainer.js	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tree/BaseLayerContainer.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,5 +1,9 @@
 /**
- * Copyright (c) 2008 The Open Planning Project
+ * Copyright (c) 2008-2009 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.
  */
 
 /**
@@ -7,58 +11,70 @@
  */
 Ext.namespace("GeoExt.tree");
 
-/**
- * Class: GeoExt.tree.BaseLayerContainer
+/** api: (define)
+ *  module = GeoExt.tree
+ *  class = BaseLayerContainer
+ */
+
+/** api: (extends)
+ * GeoExt/widgets/tree/LayerContainer.js
+ */
+
+/** api: constructor
+ *  .. class:: BaseLayerContainer
  * 
- * A layer container that will collect all base layers of an OpenLayers map.
- * Only layers that have displayInLayerSwitcher set to true will be included.
+ *     A layer container that will collect all base layers of an OpenLayers
+ *     map. Only layers that have displayInLayerSwitcher set to true will be
+ *     included. The childrens' iconCls defaults to "gx-tree-baselayer-icon".
+ *     
+ *     Children will be rendered with a radio button instead of a checkbox,
+ *     showing the user that only one base layer can be active at a time.
  * 
- * To use this node type in JSON config, set nodeType to
- * "olBaseLayerContainer".
- * 
- * Inherits from:
- * - <GeoExt.tree.LayerContainer>
+ *     To use this node type in ``TreePanel`` config, set nodeType to
+ *     "gx_baselayercontainer".
  */
 GeoExt.tree.BaseLayerContainer = Ext.extend(GeoExt.tree.LayerContainer, {
 
-    /**
-     * Constructor: GeoExt.tree.BaseLayerContainer
-     * 
-     * Parameters:
-     * config - {Object}
+    /** private: method[constructor]
+     *  Private constructor override.
      */
     constructor: function(config) {
         config.text = config.text || "Base Layer";
+        config.defaults = Ext.apply({
+            iconCls: 'gx-tree-baselayer-icon',
+            checkedGroup: 'baselayer'
+        }, config.defaults);
         GeoExt.tree.BaseLayerContainer.superclass.constructor.apply(this, arguments);
     },
 
-    /**
-     * Method: addLayerNode
-     * Adds a child node representing a base layer of the map
-     * 
-     * Parameters:
-     * layerRecord - {Ext.data.Record} the layer record to add a node for
+    /** private: method[addLayerNode]
+     *  :param layerRecord: ``Ext.data.Record`` The layer record containing the
+     *      layer to be added.
+     *  :param index: ``Number`` Optional index for the new layer.  Default is 0.
+     *  
+     *  Adds a child node representing a base layer of the map
      */
-    addLayerNode: function(layerRecord) {
+    addLayerNode: function(layerRecord, index) {
         var layer = layerRecord.get("layer");
         if (layer.isBaseLayer == true) {
-            GeoExt.tree.BaseLayerContainer.superclass.addLayerNode.call(this,
-                layerRecord);
+            GeoExt.tree.BaseLayerContainer.superclass.addLayerNode.apply(
+                this, arguments
+            );
         }
     },
     
-    /**
-     * Method: removeLayerNode
-     * Removes a child node representing a base layer of the map
-     * 
-     * Parameters:
-     * layerRecord - {Ext.data.Record} the layer record to remove the node for
+    /** private: method[removeLayerNode]
+     *  :param layerRecord: ``Ext.data.Record`` the layer record to remove the
+     *      node for
+     *
+     *  Removes a child node representing a base layer of the map.
      */
     removeLayerNode: function(layerRecord) {
         var layer = layerRecord.get("layer");
         if (layer.isBaseLayer == true) {
-            GeoExt.tree.BaseLayerContainer.superclass.removeLayerNode.call(this,
-                layerRecord);
+            GeoExt.tree.BaseLayerContainer.superclass.removeLayerNode.apply(
+                this, arguments
+            );
     	}
     }
 });

Modified: sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tree/LayerContainer.js
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tree/LayerContainer.js	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tree/LayerContainer.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,5 +1,9 @@
 /**
- * Copyright (c) 2008 The Open Planning Project
+ * Copyright (c) 2008-2009 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.
  */
 
 /**
@@ -7,40 +11,39 @@
  */
 Ext.namespace("GeoExt.tree");
 
-/**
- * Class: GeoExt.tree.LayerContainer
+/** api: (define)
+ *  module = GeoExt.tree
+ *  class = LayerContainer
+ *  base_link = `Ext.tree.TreeNode <http://extjs.com/deploy/dev/docs/?class=Ext.tree.TreeNode>`_
+ */
+
+/** api: constructor
+ *  .. class:: LayerContainer
  * 
- * A subclass of {Ext.tree.TreeNode} that will collect all layers of an
- * OpenLayers map. Only layers that have displayInLayerSwitcher set to true
- * will be included. The childrens' iconCls will be set to "baselayer-icon"
- * for base layers, and to "layer-icon" for overlay layers.
+ *      A subclass of ``Ext.tree.TreeNode`` that will collect all layers of an
+ *      OpenLayers map. Only layers that have displayInLayerSwitcher set to true
+ *      will be included. The childrens' iconCls defaults to
+ *      "gx-tree-layer-icon".
  * 
- * To use this node type in JSON config, set nodeType to "olLayerContainer".
- * 
- * Inherits from:
- * - <Ext.tree.TreeNode>
+ *      To use this node type in ``TreePanel`` config, set nodeType to
+ *      "gx_layercontainer".
  */
 GeoExt.tree.LayerContainer = Ext.extend(Ext.tree.TreeNode, {
     
-    /**
-     * APIProperty: layerStore
-     * {<GeoExt.data.LayerStore>} The layer store containing layers to be
-     *     displayed in the container.
+    /** api: config[layerStore]
+     *  :class:`GeoExt.data.LayerStore`
+     *  The layer store containing layers to be displayed in the container.
      */
     layerStore: null,
     
-    /**
-     * APIProperty: defaults
-     * {Object} a configuration object passed to all nodes that this
-     *     LayerContainer creates.
+    /** api: config[defaults]
+     *  ``Object``
+     *  A configuration object passed to all nodes that this container creates.
      */
     defaults: null,
 
-    /**
-     * Constructor: GeoExt.tree.LayerContainer
-     * 
-     * Parameters:
-     * config - {Object}
+    /** private: method[constructor]
+     *  Private constructor override.
      */
     constructor: function(config) {
         this.layerStore = config.layerStore;
@@ -48,11 +51,8 @@
         GeoExt.tree.LayerContainer.superclass.constructor.apply(this, arguments);
     },
 
-    /**
-     * Method: render
-     * 
-     * Parameters:
-     * bulkRender - {Boolean}
+    /** private: method[render]
+     *  :param bulkRender: ``Boolean``
      */
     render: function(bulkRender) {
         if (!this.rendered) {
@@ -71,32 +71,28 @@
         GeoExt.tree.LayerContainer.superclass.render.call(this, bulkRender);
     },
     
-    /**
-     * Method: onStoreAdd
-     * Listener for the store's add event.
-     *
-     * Parameters:
-     * store - {Ext.data.Store}
-     * records - {Array(Ext.data.Record)}
-     * index - {Number}
+    /** private: method[onStoreAdd]
+     *  :param store: ``Ext.data.Store``
+     *  :param records: ``Array(Ext.data.Record)``
+     *  :param index: ``Number``
+     *  
+     *  Listener for the store's add event.
      */
     onStoreAdd: function(store, records, index) {
         if(!this._reordering) {
-            var nodeIndex = this.recordIndexToNodeIndex(index);
+            var nodeIndex = this.recordIndexToNodeIndex(index+records.length-1);
             for(var i=0; i<records.length; ++i) {
                 this.addLayerNode(records[i], nodeIndex);
             }
         }
     },
     
-    /**
-     * Method: onStoreRemove
-     * Listener for the store's remove event.
-     *
-     * Parameters:
-     * store - {Ext.data.Store}
-     * record - {Ext.data.Record}
-     * index - {Number}
+    /** private: method[onStoreRemove]
+     *  :param store: ``Ext.data.Store``
+     *  :param record: ``Ext.data.Record``
+     *  :param index: ``Number``
+     *  
+     *  Listener for the store's remove event.
      */
     onStoreRemove: function(store, record, index) {
         if(!this._reordering) {
@@ -104,35 +100,19 @@
         }
     },
 
-    /**
-     * Method: onDestroy
+    /** private: method[recordIndexToNodeIndex]
+     *  :param index: ``Number`` The record index in the layer store.
+     *  :return: ``Number`` The appropriate child node index for the record.
      */
-    onDestroy: function() {
-        if(this.layerStore) {
-            this.layerStore.un("add", this.onStoreAdd, this);
-            this.layerStore.un("remove", this.onStoreRemove, this);
-        }
-        GeoExt.tree.LayerContainer.superclass.onDestroy.apply(this, arguments);
-    },
-    
-    /**
-     * Method: recordIndexToNodeIndex
-     * Convert a record index into a child node index.
-     *
-     * Parameters:
-     * index - {Number} The record index in the layer store.
-     *
-     * Returns:
-     * {Number} The appropriate child node index for the record.
-     */
     recordIndexToNodeIndex: function(index) {
         var store = this.layerStore;
         var count = store.getCount();
+        var nodeCount = this.childNodes.length;
         var nodeIndex = -1;
         for(var i=count-1; i>=0; --i) {
             if(store.getAt(i).get("layer").displayInLayerSwitcher) {
                 ++nodeIndex;
-                if(index === i) {
+                if(index === i || nodeIndex > nodeCount-1) {
                     break;
                 }
             }
@@ -140,15 +120,11 @@
         return nodeIndex;
     },
     
-    /**
-     * Method: nodeIndexToRecordIndex
-     * Convert a child node index to a record index.
-     *
-     * Parameters:
-     * index - {Number} The child node index.
-     *
-     * Returns:
-     * {Number} The appropriate record index for the node.
+    /** private: method[nodeIndexToRecordIndex]
+     *  :param index: ``Number`` The child node index.
+     *  :return: ``Number`` The appropriate record index for the node.
+     *  
+     *  Convert a child node index to a record index.
      */
     nodeIndexToRecordIndex: function(index) {
         var store = this.layerStore;
@@ -165,20 +141,22 @@
         return i;
     },
     
-    /**
-     * Method: addLayerNode
-     * Adds a child node representing a layer of the map
-     * 
-     * Parameters:
-     * layerRecord - {Ext.data.Record} the layer record to add the layer for
-     * index - {Number} Optional index for the new layer.  Default is 0.
+    /** private: method[addLayerNode]
+     *  :param layerRecord: ``Ext.data.Record`` The layer record containing the
+     *      layer to be added.
+     *  :param index: ``Number`` Optional index for the new layer.  Default is 0.
+     *  
+     *  Adds a child node representing a layer of the map
      */
     addLayerNode: function(layerRecord, index) {
         index = index || 0;
         var layer = layerRecord.get("layer");
         if (layer.displayInLayerSwitcher === true) {
-            var node = new GeoExt.tree.LayerNode(Ext.applyIf({
-                iconCls: layer.isBayeLayer ? 'baselayer-icon' : 'layer-icon',
+            var Node = (this.defaults && this.defaults.nodeType) ?
+                Ext.tree.TreePanel.nodeTypes[this.defaults.nodeType] :
+                GeoExt.tree.LayerNode;
+            var node = new Node(Ext.apply({
+                iconCls: 'gx-tree-layer-icon',
                 layer: layer,
                 layerStore: this.layerStore
             }, this.defaults));
@@ -192,12 +170,11 @@
         }
     },
     
-    /**
-     * Method: removeLayerNode
-     * Removes a child node representing a layer of the map
+    /** private: method[removeLayerNode]
+     *  :param layerRecord: ``Ext.data.Record`` The layer record containing the
+     *      layer to be removed.
      * 
-     * Parameters:
-     * layerRecord - {Ext.data.Record} the layer record to remove the node for
+     *  Removes a child node representing a layer of the map
      */
     removeLayerNode: function(layerRecord) {
         var layer = layerRecord.get("layer");
@@ -212,18 +189,16 @@
     	}
     },
     
-    /**
-     * Method: onChildMove
-     * Listener for child node "move" events.  This updates the order of
-     *     records in the store based on new node order if the node has not
-     *     changed parents.
-     *
-     * Parameters:
-     * tree - {Ext.data.Tree}
-     * node - {Ext.tree.TreeNode}
-     * oldParent - {Ext.tree.TreeNode}
-     * newParent - {Ext.tree.TreeNode}
-     * index {Number}
+    /** private: method[onChildMove]
+     *  :param tree: ``Ext.data.Tree``
+     *  :param node: ``Ext.tree.TreeNode``
+     *  :param oldParent: ``Ext.tree.TreeNode``
+     *  :param newParent: ``Ext.tree.TreeNode``
+     *  :param index: ``Number``
+     *  
+     *  Listener for child node "move" events.  This updates the order of
+     *  records in the store based on new node order if the node has not
+     *  changed parents.
      */
     onChildMove: function(tree, node, oldParent, newParent, index) {
         if(oldParent === newParent) {
@@ -238,8 +213,17 @@
             this.layerStore.insert(newRecordIndex, [record]);
             delete this._reordering;
         }
+    },
+
+    /** private: method[destroy]
+     */
+    destroy: function() {
+        if(this.layerStore) {
+            this.layerStore.un("add", this.onStoreAdd, this);
+            this.layerStore.un("remove", this.onStoreRemove, this);
+        }
+        GeoExt.tree.LayerContainer.superclass.destroy.apply(this, arguments);
     }
-    
 });
 
 /**

Modified: sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tree/LayerNode.js
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tree/LayerNode.js	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tree/LayerNode.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,67 +1,72 @@
 /**
- * Copyright (c) 2008 The Open Planning Project
+ * Copyright (c) 2008-2009 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.
  */
+
 Ext.namespace("GeoExt.tree");
 
-/**
- * Class: GeoExt.tree.LayerNodeUI
- * 
- * Inherits from:
- * - Ext.tree.TreeNodeUI
+/** private: constructor
+ *  .. class:: LayerNodeUI
+ *
+ *      Place in a separate file if this should be documented.
  */
 GeoExt.tree.LayerNodeUI = Ext.extend(Ext.tree.TreeNodeUI, {
     
-    /**
-     * Property: radio
-     * {Ext.Element}
+    /** private: property[radio]
+     *  ``Ext.Element``
      */
     radio: null,
     
-    /**
-     * Constructor: GeoExt.tree.LayerNodeUI
-     * 
-     * Parameters:
-     * config - {Object}
+    /** private: method[constructor]
      */
     constructor: function(config) {
         GeoExt.tree.LayerNodeUI.superclass.constructor.apply(this, arguments);
     },
     
-    /**
-     * Method: render
-     * 
-     * Parameters:
-     * bulkRender - {Boolean}
+    /** private: method[render]
+     *  :param bulkRender: ``Boolean``
      */
     render: function(bulkRender) {
+        var a = this.node.attributes;
+        if (a.checked === undefined) {
+            a.checked = this.node.layer.getVisibility();
+        }
         GeoExt.tree.LayerNodeUI.superclass.render.call(this, bulkRender);
-        var a = this.node.attributes;
         if (a.radioGroup && this.radio === null) {
             this.radio = Ext.DomHelper.insertAfter(this.checkbox,
-                ['<input type="radio" class="x-tree-node-radio" name="',
+                ['<input type="radio" class="gx-tree-layer-radio" name="',
                 a.radioGroup, '_radio"></input>'].join(""));
         }
+        if(a.checkedGroup) {
+            // replace the checkbox with a radio button
+            var radio = Ext.DomHelper.insertAfter(this.checkbox,
+                ['<input type="radio" name="', a.checkedGroup,
+                '_checkbox" class="', this.checkbox.className, 
+                this.checkbox.checked ? '" checked="checked"' : '',
+                '"></input>'].join(""));
+            Ext.get(this.checkbox).remove();
+            this.checkbox = radio;
+        }
     },
     
-    /**
-     * Method: onClick
-     * 
-     * Parameters:
-     * e - {Object}
+    /** private: method[onClick]
+     *  :param e: ``Object``
      */
     onClick: function(e) {
-        if (e.getTarget('input[type=radio]', 1)) {
+        if (e.getTarget('.gx-tree-layer-radio', 1)) {
             this.fireEvent("radiochange", this.node);
+        } else if(e.getTarget('.x-tree-node-cb', 1)) {
+            GeoExt.tree.LayerNodeUI.superclass.onCheckChange.call(this);
         } else {
             GeoExt.tree.LayerNodeUI.superclass.onClick.call(this, e);
         }
     },
     
-    /**
-     * Method: toggleCheck
-     * 
-     * Parameters:
-     * value - {Boolean}
+    /** private: method[toggleCheck]
+     *  :param value: ``Boolean``
      */
     toggleCheck: function(value) {
         GeoExt.tree.LayerNodeUI.superclass.toggleCheck.call(this, value);
@@ -74,12 +79,11 @@
         node.visibilityChanging = false;
     },
     
-    /**
-     * Method: onDestroy
+    /** private: method[destroy]
      */
-    onDestroy: function() {
+    destroy: function() {
         delete this.radio;
-        GeoExt.tree.LayerNodeUI.superclass.onDestroy.call(this);
+        GeoExt.tree.LayerNodeUI.superclass.destroy.call(this);
     }
 });
 
@@ -95,21 +99,28 @@
  *      A subclass of ``Ext.tree.TreeNode`` that is connected to an
  *      ``OpenLayers.Layer`` by setting the node's layer property. Checking or
  *      unchecking the checkbox of this node will directly affect the layer and
- *      vice versa. The default iconCls for this node's icon is "layer-icon",
- *      unless it has children.
+ *      vice versa. The default iconCls for this node's icon is
+ *      "gx-tree-layer-icon", unless it has children.
  * 
  *      Setting the node's layer property to a layer name instead of an object
  *      will also work. As soon as a layer is found, it will be stored as layer
  *      property in the attributes hash.
  * 
  *      The node's text property defaults to the layer name.
+ *      
+ *      If the node has a checkedGroup attribute configured, it will be
+ *      rendered with a radio button instead of the checkbox. The value of
+ *      the checkedGroup attribute is a string, identifying the options group
+ *      for the node.
  * 
  *      If the node has a radioGroup attribute configured, the node will be
- *      rendered with a radio button. This works like the checkbox with the
- *      checked attribute, but radioGroup is a string that identifies the options
- *      group. Clicking the radio button will fire a radioChange event.
+ *      rendered with a radio button next to the checkbox. This works like the
+ *      checkbox with the checked attribute, but radioGroup is a string that
+ *      identifies the options group. Clicking the radio button will fire a
+ *      radioChange event.
  * 
- *      To use this node type in a JSON config, set nodeType to "gx_layer".
+ *      To use this node type in a ``TreePanel`` config, set ``nodeType`` to
+ *      "gx_layer".
  */
 GeoExt.tree.LayerNode = Ext.extend(Ext.tree.TreeNode, {
     
@@ -152,27 +163,20 @@
      */
     visibilityChanging: false,
     
-    /**
-     * Constructor: GeoExt.tree.LayerNode
-     * 
-     * Parameters:
-     * config - {Object}
+    /** private: method[constructor]
+     *  Private constructor override.
      */
     constructor: function(config) {
         config.leaf = config.leaf || !config.children;
         
         config.iconCls = typeof config.iconCls == "undefined" &&
             !config.children ? "layer-icon" : config.iconCls;
-        // checked status will be set by layer event, so setting it to false
-        // to always get the checkbox rendered
-        config.checked = false;
         
         this.defaultUI = this.defaultUI || GeoExt.tree.LayerNodeUI;
         this.addEvents(
-            /**
-             * Event: radiochange
-             * Notifies listener when a differnt radio button was selected.
-             * Will be called with the currently selected node as argument.
+            /** api: event[radiochange]
+             *  Notifies listener when a differnt radio button was selected.
+             *  Will be called with the currently selected node as argument.
              */
             "radiochange"
         );
@@ -185,12 +189,8 @@
         GeoExt.tree.LayerNode.superclass.constructor.apply(this, arguments);
     },
 
-    /**
-     * Method: render
-     * 
-     * Properties:
-     * bulkRender {Boolean} - optional
-     * layer {<OpenLayers.Layer>} - optional
+    /** private: method[render]
+     *  :param bulkRender: ``Boolean``
      */
     render: function(bulkRender) {
         var layer = this.layer instanceof OpenLayers.Layer && this.layer;
@@ -223,10 +223,7 @@
                 }
                 
                 ui.show();
-                ui.toggleCheck(layer.getVisibility());
                 this.addVisibilityEventHandlers();
-                // set initial checked status
-                this.attributes.checked = layer.getVisibility();
             } else {
                 ui.hide();
             }
@@ -238,71 +235,141 @@
         GeoExt.tree.LayerNode.superclass.render.call(this, bulkRender);
     },
     
-    /**
-     * Method: addVisibilityHandlers
-     * Adds handlers that sync the checkbox state with the layer's visibility
-     * state
+    /** private: method[addVisibilityHandlers]
+     *  Adds handlers that sync the checkbox state with the layer's visibility
+     *  state
      */
     addVisibilityEventHandlers: function() {
-        this.layer.events.register("visibilitychanged", this, function() {
-            if(!this.visibilityChanging &&
-                    this.attributes.checked != this.layer.getVisibility()) {
-                this.getUI().toggleCheck(this.layer.getVisibility());
-            }
-        });
+        this.layer.events.on({
+            "visibilitychanged": this.onLayerVisibilityChanged,
+            scope: this
+        }); 
         this.on({
-            "checkchange": function(node, checked) {
-                if (checked && this.layer.isBaseLayer && this.layer.map) {
-                    this.layer.map.setBaseLayer(this.layer);
-                }
-                this.layer.setVisibility(checked);
-            },
+            "checkchange": this.onCheckChange,
             scope: this
         });
     },
     
-    /**
-     * Method: addStoreEventHandlers
-     * Adds handlers that make sure the node disappeares when the layer is
-     * removed from the store, and appears when it is re-added.
+    /** private: method[onLayerVisiilityChanged
+     *  handler for visibilitychanged events on the layer
      */
+    onLayerVisibilityChanged: function() {
+        if(!this.visibilityChanging &&
+                this.attributes.checked != this.layer.getVisibility()) {
+            this.getUI().toggleCheck(this.layer.getVisibility());
+        }
+    },
+    
+    /** private: method[onCheckChange]
+     *  :param node: ``GeoExt.tree.LayerNode``
+     *  :param checked: ``Boolean``
+     *
+     *  handler for checkchange events 
+     */
+    onCheckChange: function(node, checked) {
+        if (checked && this.layer.isBaseLayer && this.layer.map) {
+            this.layer.map.setBaseLayer(this.layer);
+        }
+        this.layer.setVisibility(checked);
+    },
+    
+    /** private: method[addStoreEventHandlers]
+     *  Adds handlers that make sure the node disappeares when the layer is
+     *  removed from the store, and appears when it is re-added.
+     */
     addStoreEventHandlers: function() {
         this.layerStore.on({
-            "add": function(store, records, index) {
-                var l;
-                for(var i=0; i<records.length; ++i) {
-                    l = records[i].get("layer");
-                    if(this.layer == l) {
-                        this.getUI().show();
-                    } else if (this.layer == l.name) {
-                        // layer is a string, which means the node has not yet
-                        // been rendered because the layer was not found. But
-                        // now we have the layer and can render.
-                        this.render(bulkRender);
-                        return;
-                    }
-                }
-            },
-            "remove": function(store, record, index) {
-                if(this.layer == record.get("layer")) {
-                    this.getUI().hide();
-                }
-            },
+            "add": this.onStoreAdd,
+            "remove": this.onStoreRemove,
+            "update": this.onStoreUpdate,
             scope: this
         });
     },
     
-    /**
-     * Method: addChildNodes
-     * Calls the add method of a node type configured as <childNodeType>
-     * to add children.
+    /** private: method[onStoreAdd]
+     *  :param store: ``Ext.data.Store``
+     *  :param records: ``Array(Ext.data.Record)``
+     *  :param index: ``Number``
+     *
+     *  handler for add events on the store 
      */
+    onStoreAdd: function(store, records, index) {
+        var l;
+        for(var i=0; i<records.length; ++i) {
+            l = records[i].get("layer");
+            if(this.layer == l) {
+                this.getUI().show();
+            } else if (this.layer == l.name) {
+                // layer is a string, which means the node has not yet
+                // been rendered because the layer was not found. But
+                // now we have the layer and can render.
+                this.render(bulkRender);
+                return;
+            }
+        }
+    },
+    
+    /** private: method[onStoreRemove]
+     *  :param store: ``Ext.data.Store``
+     *  :param record: ``Ext.data.Record``
+     *  :param index: ``Number``
+     *
+     *  handler for remove events on the store 
+     */
+    onStoreRemove: function(store, record, index) {
+        if(this.layer == record.get("layer")) {
+            this.getUI().hide();
+        }
+    },
+
+    /** private: method[onStoreUpdate]
+     *  :param store: ``Ext.data.Store``
+     *  :param record: ``Ext.data.Record``
+     *  :param operation: ``String``
+     *  
+     *  Listener for the store's update event.
+     */
+    onStoreUpdate: function(store, record, operation) {
+    	var layer = record.get("layer");
+        if(this.layer == layer && record.isModified("title") &&
+                                    record.modified["title"] == this.text) {
+            this.setText(record.get("title"));
+        }
+    },
+
+    /** private: method[addChildNodes]
+     *  Calls the add method of a node type configured as ``childNodeType``
+     *  to add children.
+     */
     addChildNodes: function() {
         if(typeof this.childNodeType == "string") {
             Ext.tree.TreePanel.nodeTypes[this.childNodeType].add(this);
         } else if(typeof this.childNodeType.add === "function") {
             this.childNodeType.add(this);
         }
+    },
+    
+    /** private: method[destroy]
+     */
+    destroy: function() {
+        var layer = this.layer;
+        if (layer instanceof OpenLayers.Layer) {
+            layer.events.un({
+                "visibilitychanged": this.onLayerVisibilityChanged,
+                scope: this
+            });
+        }
+        delete this.layer;
+        var layerStore = this.layerStore;
+        if(layerStore) {
+            layerStore.un("add", this.onStoreAdd, this);
+            layerStore.un("remove", this.onStoreRemove, this);
+            layerStore.un("update", this.onStoreUpdate, this);
+        }
+        delete this.layerStore;
+        this.un("checkchange", this.onCheckChange, this);
+
+        GeoExt.tree.LayerNode.superclass.destroy.call(this);
     }
 });
 

Modified: sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tree/OverlayLayerContainer.js
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tree/OverlayLayerContainer.js	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tree/OverlayLayerContainer.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,5 +1,9 @@
 /**
- * Copyright (c) 2008 The Open Planning Project
+ * Copyright (c) 2008-2009 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.
  */
 
 /**
@@ -7,25 +11,29 @@
  */
 Ext.namespace("GeoExt.tree");
 
-/**
- * Class: GeoExt.tree.OverlayLayerContainer
+/** api: (define)
+ *  module = GeoExt.tree
+ *  class = OverlayLayerContainer
+ */
+
+/** api: (extends)
+ * GeoExt/widgets/tree/LayerContainer.js
+ */
+
+/** api: constructor
+ * .. class:: OverlayLayerContainer
  * 
- * A layer container that will collect all overlay layers of an OpenLayers map.
- * Only layers that have displayInLayerSwitcher set to true will be included.
+ *     A layer container that will collect all overlay layers of an OpenLayers
+ *     map. Only layers that have displayInLayerSwitcher set to true will be
+ *     included.
  * 
- * To use this node type in JSON config, set nodeType to
- * "olOverlayLayerContainer".
- * 
- * Inherits from:
- * - <GeoExt.tree.LayerContainer>
+ *     To use this node type in ``TreePanel`` config, set nodeType to
+ *     "gx_overlaylayerontainer".
  */
 GeoExt.tree.OverlayLayerContainer = Ext.extend(GeoExt.tree.LayerContainer, {
 
-    /**
-     * Constructor: GeoExt.tree.OverlayLayerContainer
-     * 
-     * Parameters:
-     * config - {Object}
+    /** private: method[constructor]
+     *  Private constructor override.
      */
     constructor: function(config) {
         config.text = config.text || "Overlays";
@@ -33,33 +41,34 @@
             arguments);
     },
 
-    /**
-     * Method: addLayerNode
-     * Adds a child node representing a overlay layer of the map
-     * 
-     * Parameters:
-     * layerRecord - {Ext.data.Record} the layer record to add a node for
+    /** private: method[addLayerNode]
+     *  :param layerRecord: ``Ext.data.Record`` The layer record containing the
+     *      layer to be added.
+     *  :param index: ``Number`` Optional index for the new layer.  Default is 0.
+     *  
+     *  Adds a child node representing a overlay layer of the map.
      */
-    addLayerNode: function(layerRecord) {
+    addLayerNode: function(layerRecord, index) {
         var layer = layerRecord.get("layer");
         if (layer.isBaseLayer == false) {
-            GeoExt.tree.OverlayLayerContainer.superclass.addLayerNode.call(this,
-                layerRecord);
+            GeoExt.tree.OverlayLayerContainer.superclass.addLayerNode.apply(
+                this, arguments
+            );
         }
     },
     
-    /**
-     * Method: removeLayerNode
-     * Removes a child node representing an overlay layer of the map
-     * 
-     * Parameters:
-     * layerRecord - {Ext.data.Record} the layer record to remove the node for
+    /** private: method[removeLayerNode]
+     *  :param layerRecord: ``Ext.data.Record`` the layer record to remove the
+     *      node for
+     *      
+     * Removes a child node representing an overlay layer of the map.
      */
     removeLayerNode: function(layerRecord) {
         var layer = layerRecord.get("layer");
         if (layer.isBaseLayer == false) {
-            GeoExt.tree.OverlayLayerContainer.superclass.removeLayerNode.call(
-                this, layerRecord);
+            GeoExt.tree.OverlayLayerContainer.superclass.removeLayerNode.apply(
+                this, arguments
+            );
     	}
     }
 });

Modified: sandbox/elemoine/playground/geoext/lib/GeoExt.js
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt.js	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,9 +1,10 @@
-/* Copyright (C) 2008-2009 The Open Source Geospatial Foundation ¹
+/**
+ * Copyright (c) 2008-2009 The Open Source Geospatial Foundation
+ * 
  * Published under the BSD license.
- * See http://geoext.org/svn/geoext/core/trunk/license.txt for the full text
+ * See http://svn.geoext.org/core/trunk/geoext/license.txt for the full text
  * of the license.
- * 
- * ¹ pending approval */
+ */
 
 /*
  * The code in this file is based on code taken from OpenLayers.
@@ -32,7 +33,12 @@
      */
     var getScriptLocation = function() {
         var scriptLocation = "";
-        var scripts = document.getElementsByTagName('script');
+        // If we load other scripts right before GeoExt using the same
+        // mechanism to add script resources dynamically (e.g. OpenLayers), 
+        // document.getElementsByTagName will not find the GeoExt script tag
+        // in FF2. Using document.documentElement.getElementsByTagName instead
+        // works around this issue.
+        var scripts = document.documentElement.getElementsByTagName('script');
         for(var i=0, len=scripts.length; i<len; i++) {
             var src = scripts[i].getAttribute('src');
             if(src) {
@@ -67,6 +73,8 @@
             "GeoExt/data/ScaleStore.js",
             "GeoExt/data/WMSCapabilitiesReader.js",
             "GeoExt/data/WMSCapabilitiesStore.js",
+            "GeoExt/data/WMSDescribeLayerReader.js",
+            "GeoExt/data/WMSDescribeLayerStore.js",
             "GeoExt/widgets/Action.js",
             "GeoExt/data/ProtocolProxy.js",
             "GeoExt/widgets/MapPanel.js",
@@ -75,13 +83,19 @@
             "GeoExt/widgets/form/SearchAction.js",
             "GeoExt/widgets/form/BasicForm.js",
             "GeoExt/widgets/form/FormPanel.js",
+            "GeoExt/widgets/tips/SliderTip.js",
+            "GeoExt/widgets/tips/LayerOpacitySliderTip.js",
+            "GeoExt/widgets/tips/ZoomSliderTip.js",
             "GeoExt/widgets/tree/LayerNode.js",
             "GeoExt/widgets/tree/LayerContainer.js",
             "GeoExt/widgets/tree/BaseLayerContainer.js",
             "GeoExt/widgets/tree/OverlayLayerContainer.js",
+            "GeoExt/widgets/LayerOpacitySlider.js",
             "GeoExt/widgets/LegendImage.js",
             "GeoExt/widgets/LegendWMS.js",
-            "GeoExt/widgets/LegendPanel.js"
+            "GeoExt/widgets/LegendPanel.js",
+            "GeoExt/widgets/ZoomSlider.js",
+            "GeoExt/widgets/grid/FeatureSelectionModel.js"
         );
 
         var agent = navigator.userAgent;

Modified: sandbox/elemoine/playground/geoext/license.txt
===================================================================
--- sandbox/elemoine/playground/geoext/license.txt	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/license.txt	2009-07-23 09:53:02 UTC (rev 1282)
@@ -7,7 +7,7 @@
 License
 =======
 
-Copyright (c) 2008-2009, The Open Source Geospatial Foundation ¹
+Copyright (c) 2008-2009, The Open Source Geospatial Foundation
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -34,7 +34,6 @@
 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGE.
 
-¹ pending approval
 
 
 Notice about ExtJS

Deleted: sandbox/elemoine/playground/geoext/resources/css/example.css
===================================================================
--- sandbox/elemoine/playground/geoext/resources/css/example.css	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/resources/css/example.css	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,16 +0,0 @@
-/*
- * Styles can be theme specific, as shown in the example below.
- * 
- * style for the default theme:
- * .my-style {
- *     background: transparent url(../images/default/anchor.png) no-repeat 0 0;
- *     postion: relative;
- *     top: -1px;
- *     left: 5px;
- * }
- * 
- * modifier for the gray theme:
- * .xtheme-gray .my-style {
- *     background: transparent url(../images/gray/anchor.png) no-repeat 0 0;
- * }
- */

Modified: sandbox/elemoine/playground/geoext/resources/css/geoext-all-debug.css
===================================================================
--- sandbox/elemoine/playground/geoext/resources/css/geoext-all-debug.css	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/resources/css/geoext-all-debug.css	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,2 +1,6 @@
- at import "example.css";
+/**
+ * This file combines all default css files. It will be parsed by the build
+ * processor to generate a minified geoext-all.css file. Theme specific
+ * overrides go into gxtheme-<theme>.css
+ */
 @import "popup.css";

Modified: sandbox/elemoine/playground/geoext/resources/css/gxtheme-gray.css
===================================================================
--- sandbox/elemoine/playground/geoext/resources/css/gxtheme-gray.css	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/resources/css/gxtheme-gray.css	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,9 +1,9 @@
 .gx-popup-anc {
-	background: transparent url(../images/gray/anchor.png) no-repeat 0 0;
-        position: relative;
-        top:-1px;
-        left:5px;
-        z-index:2;
-        height:16px;
-        width:31px;
+    background: transparent url(../images/gray/anchor.png) no-repeat 0 0;
+    position: relative;
+    top:-1px;
+    left:5px;
+    z-index:2;
+    height:16px;
+    width:31px;
 }
\ No newline at end of file

Copied: sandbox/elemoine/playground/geoext/resources/css/gxtheme-slate.css (from rev 1281, core/trunk/geoext/resources/css/gxtheme-slate.css)
===================================================================
--- sandbox/elemoine/playground/geoext/resources/css/gxtheme-slate.css	                        (rev 0)
+++ sandbox/elemoine/playground/geoext/resources/css/gxtheme-slate.css	2009-07-23 09:53:02 UTC (rev 1282)
@@ -0,0 +1,9 @@
+.gx-popup-anc {
+	background: transparent url(../images/slate/anchor.png) no-repeat 0 0;
+        position: relative;
+        top:-1px;
+        left:5px;
+        z-index:2;
+        height:16px;
+        width:31px;
+}

Modified: sandbox/elemoine/playground/geoext/resources/css/popup.css
===================================================================
--- sandbox/elemoine/playground/geoext/resources/css/popup.css	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/resources/css/popup.css	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,10 +1,9 @@
-
 .gx-popup-anc {
-	background: transparent url(../images/default/anchor.png) no-repeat 0 0;
-        position: relative;
-        top:-1px;
-        left:5px;
-        z-index:2;
-        height:16px;
-        width:31px;
+    background: transparent url(../images/default/anchor.png) no-repeat 0 0;
+    position: relative;
+    top:-1px;
+    left:5px;
+    z-index:2;
+    height:16px;
+    width:31px;
 }

Copied: sandbox/elemoine/playground/geoext/resources/images/slate (from rev 1281, core/trunk/geoext/resources/images/slate)

Deleted: sandbox/elemoine/playground/geoext/resources/images/slate/anchor.png
===================================================================
(Binary files differ)

Copied: sandbox/elemoine/playground/geoext/resources/images/slate/anchor.png (from rev 1281, core/trunk/geoext/resources/images/slate/anchor.png)
===================================================================
(Binary files differ)

Copied: sandbox/elemoine/playground/geoext/tests/lib/GeoExt/adapter (from rev 1281, core/trunk/geoext/tests/lib/GeoExt/adapter)

Deleted: sandbox/elemoine/playground/geoext/tests/lib/GeoExt/adapter/override-ext-ajax.html
===================================================================
--- core/trunk/geoext/tests/lib/GeoExt/adapter/override-ext-ajax.html	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/tests/lib/GeoExt/adapter/override-ext-ajax.html	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,168 +0,0 @@
-<!DOCTYPE html>
-<html debug="true">
-  <head>
-    <script type="text/javascript" src="../../../../../openlayers/lib/OpenLayers.js"></script>
-    <script type="text/javascript" src="../../../../../ext/adapter/ext/ext-base.js"></script>
-    <script type="text/javascript" src="../../../../../ext/ext-all-debug.js"></script>
-    <script type="text/javascript" src="../../../../lib/GeoExt/adapter/override-ext-ajax.js"></script>
-    <script type="text/javascript" src="../../../../lib/GeoExt.js"></script>
-
-    <script type="text/javascript">
-        function setup() {
-            window._xhr = OpenLayers.Request.XMLHttpRequest;
-            var anon = new Function();
-            OpenLayers.Request.XMLHttpRequest = function() {};
-            OpenLayers.Request.XMLHttpRequest.prototype = {
-                open: anon,
-                setRequestHeader: anon,
-                send: anon
-            };
-            OpenLayers.Request.XMLHttpRequest.DONE = 4;
-        }
-
-        function teardown() {
-            OpenLayers.Request.XMLHttpRequest = window._xhr;
-        }
-
-        function test_request(t) {
-            t.plan(7);
-
-            /*
-             * Setup
-             */
-
-            setup();
-
-            var _srh;
-            var proto = OpenLayers.Request.XMLHttpRequest.prototype;
-
-            var request, data;
-
-            var argument= {"some": "argument"};
-            var scope = {"some": "scope"};
-            var headers = {"some": "headers"}; 
-
-            var successObj, failureObj;
-            var success = function(o) {
-                successObj = {scope: this, arg: o.argument};
-            };
-            var failure = function(o) {
-                failureObj = {scope: this, arg: o.argument};
-            };
-
-            /*
-             * Test
-             */
-
-            // test "success" callback
-            // 3 tests
-            data = "some data";
-            successObj = failureObj = null;
-            _srh = proto.setRequestHeader; 
-            proto.setRequestHeader = function(k, v) {
-                t.ok(k == "some" && v == "headers",
-                     "headers properly set");
-            };
-            request = Ext.lib.Ajax.request("GET", "http://foo",
-                {
-                    success: success,
-                    failure: failure,
-                    argument: argument,
-                    scope: scope
-                },
-                data,
-                {
-                    headers: headers
-                }
-            );
-            request.readyState = OpenLayers.Request.XMLHttpRequest.DONE;
-            request.status = 200;
-            request.onreadystatechange();
-            t.eq(successObj.scope, scope,
-                 "success cb called with proper scope");
-            t.eq(successObj.arg, argument,
-                 "success cb called with proper argument");
-            proto.setRequestHeader = _srh;
-
-            // test "failure" callback
-            // 2 tests
-            data = "some data";
-            successObj = failureObj = null;
-            request = Ext.lib.Ajax.request("GET", "http://foo",
-                {
-                    success: success,
-                    failure: failure,
-                    argument: argument,
-                    scope: scope
-                },
-                data,
-                {
-                    headers: headers
-                }
-            );
-            request.readyState = OpenLayers.Request.XMLHttpRequest.DONE;
-            request.status = 400;
-            request.onreadystatechange();
-            t.eq(failureObj.scope, scope,
-                 "failure cb called with proper scope");
-            t.eq(failureObj.arg, argument,
-                 "failure cb called with proper argument");
-
-            // test xmlData
-            // 1 test
-            data = "some data";
-            _srh = proto.setRequestHeader; 
-            proto.setRequestHeader = function(k, v) {
-                t.ok(k == "Content-Type" && v == "text/xml",
-                     "Content-Type header properly set");
-            };
-            request = Ext.lib.Ajax.request("GET", "http://foo",
-                {
-                },
-                null,
-                {
-                    xmlData: data
-                }
-            );
-            proto.setRequestHeader = _srh;
-
-            // test jsonData
-            // 1 test
-            data = "some data";
-            _srh = proto.setRequestHeader; 
-            proto.setRequestHeader = function(k, v) {
-                t.ok(k == "Content-Type" && v == "application/json",
-                     "Content-Type header properly set");
-            };
-            request = Ext.lib.Ajax.request("GET", "http://foo",
-                {
-                },
-                null,
-                {
-                    jsonData: data
-                }
-            );
-            proto.setRequestHeader = _srh;
-
-            /*
-             * Teardown
-             */
-            teardown();
-        }
-
-        function test_serializeForm(t) {
-            t.plan(1);
-
-            var expect = "key1=val1&key2=val2";
-            var result = Ext.lib.Ajax.serializeForm(Ext.get("form").dom);
-            t.eq(result, expect,
-                 "serializeForm returns expected result (" + expect + ")");
-        }
-    </script>
-  <body>
-  <form id="form">
-      <input type="text" name="key1" value="val1"></input>
-      <input type="checkbox" name="key2" value="val2" checked="checked"></input>
-  </form>
-  </body>
-</html>

Copied: sandbox/elemoine/playground/geoext/tests/lib/GeoExt/adapter/override-ext-ajax.html (from rev 1281, core/trunk/geoext/tests/lib/GeoExt/adapter/override-ext-ajax.html)
===================================================================
--- sandbox/elemoine/playground/geoext/tests/lib/GeoExt/adapter/override-ext-ajax.html	                        (rev 0)
+++ sandbox/elemoine/playground/geoext/tests/lib/GeoExt/adapter/override-ext-ajax.html	2009-07-23 09:53:02 UTC (rev 1282)
@@ -0,0 +1,168 @@
+<!DOCTYPE html>
+<html debug="true">
+  <head>
+    <script type="text/javascript" src="../../../../../openlayers/lib/OpenLayers.js"></script>
+    <script type="text/javascript" src="../../../../../ext/adapter/ext/ext-base.js"></script>
+    <script type="text/javascript" src="../../../../../ext/ext-all-debug.js"></script>
+    <script type="text/javascript" src="../../../../lib/GeoExt/adapter/override-ext-ajax.js"></script>
+    <script type="text/javascript" src="../../../../lib/GeoExt.js"></script>
+
+    <script type="text/javascript">
+        function setup() {
+            window._xhr = OpenLayers.Request.XMLHttpRequest;
+            var anon = new Function();
+            OpenLayers.Request.XMLHttpRequest = function() {};
+            OpenLayers.Request.XMLHttpRequest.prototype = {
+                open: anon,
+                setRequestHeader: anon,
+                send: anon
+            };
+            OpenLayers.Request.XMLHttpRequest.DONE = 4;
+        }
+
+        function teardown() {
+            OpenLayers.Request.XMLHttpRequest = window._xhr;
+        }
+
+        function test_request(t) {
+            t.plan(7);
+
+            /*
+             * Setup
+             */
+
+            setup();
+
+            var _srh;
+            var proto = OpenLayers.Request.XMLHttpRequest.prototype;
+
+            var request, data;
+
+            var argument= {"some": "argument"};
+            var scope = {"some": "scope"};
+            var headers = {"some": "headers"}; 
+
+            var successObj, failureObj;
+            var success = function(o) {
+                successObj = {scope: this, arg: o.argument};
+            };
+            var failure = function(o) {
+                failureObj = {scope: this, arg: o.argument};
+            };
+
+            /*
+             * Test
+             */
+
+            // test "success" callback
+            // 3 tests
+            data = "some data";
+            successObj = failureObj = null;
+            _srh = proto.setRequestHeader; 
+            proto.setRequestHeader = function(k, v) {
+                t.ok(k == "some" && v == "headers",
+                     "headers properly set");
+            };
+            request = Ext.lib.Ajax.request("GET", "http://foo",
+                {
+                    success: success,
+                    failure: failure,
+                    argument: argument,
+                    scope: scope
+                },
+                data,
+                {
+                    headers: headers
+                }
+            );
+            request.readyState = OpenLayers.Request.XMLHttpRequest.DONE;
+            request.status = 200;
+            request.onreadystatechange();
+            t.eq(successObj.scope, scope,
+                 "success cb called with proper scope");
+            t.eq(successObj.arg, argument,
+                 "success cb called with proper argument");
+            proto.setRequestHeader = _srh;
+
+            // test "failure" callback
+            // 2 tests
+            data = "some data";
+            successObj = failureObj = null;
+            request = Ext.lib.Ajax.request("GET", "http://foo",
+                {
+                    success: success,
+                    failure: failure,
+                    argument: argument,
+                    scope: scope
+                },
+                data,
+                {
+                    headers: headers
+                }
+            );
+            request.readyState = OpenLayers.Request.XMLHttpRequest.DONE;
+            request.status = 400;
+            request.onreadystatechange();
+            t.eq(failureObj.scope, scope,
+                 "failure cb called with proper scope");
+            t.eq(failureObj.arg, argument,
+                 "failure cb called with proper argument");
+
+            // test xmlData
+            // 1 test
+            data = "some data";
+            _srh = proto.setRequestHeader; 
+            proto.setRequestHeader = function(k, v) {
+                t.ok(k == "Content-Type" && v == "text/xml",
+                     "Content-Type header properly set");
+            };
+            request = Ext.lib.Ajax.request("GET", "http://foo",
+                {
+                },
+                null,
+                {
+                    xmlData: data
+                }
+            );
+            proto.setRequestHeader = _srh;
+
+            // test jsonData
+            // 1 test
+            data = "some data";
+            _srh = proto.setRequestHeader; 
+            proto.setRequestHeader = function(k, v) {
+                t.ok(k == "Content-Type" && v == "application/json",
+                     "Content-Type header properly set");
+            };
+            request = Ext.lib.Ajax.request("GET", "http://foo",
+                {
+                },
+                null,
+                {
+                    jsonData: data
+                }
+            );
+            proto.setRequestHeader = _srh;
+
+            /*
+             * Teardown
+             */
+            teardown();
+        }
+
+        function test_serializeForm(t) {
+            t.plan(1);
+
+            var expect = "key1=val1&key2=val2";
+            var result = Ext.lib.Ajax.serializeForm(Ext.get("form").dom);
+            t.eq(result, expect,
+                 "serializeForm returns expected result (" + expect + ")");
+        }
+    </script>
+  <body>
+  <form id="form">
+      <input type="text" name="key1" value="val1"></input>
+      <input type="checkbox" name="key2" value="val2" checked="checked"></input>
+  </form>
+  </body>
+</html>

Modified: sandbox/elemoine/playground/geoext/tests/lib/GeoExt/data/LayerStore.html
===================================================================
--- sandbox/elemoine/playground/geoext/tests/lib/GeoExt/data/LayerStore.html	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/tests/lib/GeoExt/data/LayerStore.html	2009-07-23 09:53:02 UTC (rev 1282)
@@ -84,6 +84,35 @@
             t.eq(mapPanel.layers.getCount(),1,"Adding layers to MapPanel's LayerStore does not create duplicate layers"); 
         }
 
+        function test_store_to_map(t) {
+
+            t.plan(8);
+            
+            var map = new OpenLayers.Map("mappanel");
+            var layers = [new OpenLayers.Layer.Vector("a"),
+                          new OpenLayers.Layer.Vector("b"),
+                          new OpenLayers.Layer.Vector("c")];
+
+            var store = new GeoExt.data.LayerStore({
+                map: map,
+                layers: layers
+            });
+
+            t.eq(store.getCount(), 3, "three layers in store");
+            t.eq(map.layers.length, 3, "three layers on map");
+
+            t.eq(store.getAt(0).get("layer").name, "a", "first layer correct in store");
+            t.eq(map.layers[0].name, "a", "first layer correct on map");
+
+            t.eq(store.getAt(1).get("layer").name, "b", "second layer correct in store");
+            t.eq(map.layers[1].name, "b", "second layer correct on map");
+
+            t.eq(store.getAt(2).get("layer").name, "c", "third layer correct in store");
+            t.eq(map.layers[2].name, "c", "third layer correct on map");
+
+            map.destroy();
+        }
+
         function test_load_clear(t) {
             t.plan(2);
             
@@ -285,6 +314,26 @@
 
         }
         
+        function test_update(t) {
+            t.plan(2);
+            
+            var map = new OpenLayers.Map("mappanel");
+            var layer = new OpenLayers.Layer("foo");
+            map.addLayer(layer);
+
+            var store = new GeoExt.data.LayerStore({
+                map: map
+            });
+
+            layer.setName("newName");
+            t.eq(store.getAt(0).get("title"), "newName", "record title synced from layer name");
+            
+            store.getAt(0).set("title", "newTitle");
+            t.eq(layer.name, "newTitle", "layer name synced from record title");
+                                    
+            map.destroy();
+        }
+        
         function test_events(t) {
             t.plan(21);
             
@@ -370,7 +419,30 @@
             
         }
         
+        function test_map_destroy(t) {
+            t.plan(1);
+            
+            var map = new OpenLayers.Map({div: "mappanel", allOverlays: true});
+            var a = new OpenLayers.Layer("a");
+            var b = new OpenLayers.Layer("b");
+            map.addLayers([a, b]);
 
+            var store = new GeoExt.data.LayerStore({
+                map: map
+            });
+            
+            var count = 0;
+            store.on("remove", function() {
+                count++;
+            });
+            
+            map.removeLayer(a);
+            map.destroy();
+            
+            t.eq(count, 1, "store's remove handler called once");
+        }
+        
+
     </script>
   </head>  
   <body>

Modified: sandbox/elemoine/playground/geoext/tests/lib/GeoExt/data/ScaleStore.html
===================================================================
--- sandbox/elemoine/playground/geoext/tests/lib/GeoExt/data/ScaleStore.html	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/tests/lib/GeoExt/data/ScaleStore.html	2009-07-23 09:53:02 UTC (rev 1282)
@@ -45,6 +45,8 @@
             map = createMap();
             store = new GeoExt.data.ScaleStore({map: map});
             t.ok(store.map == map, "ctor sets the passed map in the instance");
+            
+            map.destroy();
         }
 
         function test_bind_unbind(t) {
@@ -84,15 +86,31 @@
             store.unbind();
             t.eq(map.events.listeners["changebaselayer"][0], undefined,
                  "unbind unregisters changebaselayer listener (map has a base layer)");
+            
+            map.destroy();
         }
 
         function test_scalestore(t) {
-            t.plan(1);
+            t.plan(3);
 
             var mapPanel = loadMapPanel();
             var map = mapPanel.map;
             var store = new GeoExt.data.ScaleStore({map: map});
-            t.eq(store.data.length, 15, 'Found expected number of zoomlevels');
+            var levels = map.baseLayer.resolutions.length;
+            t.eq(store.getCount(), levels,
+                 'Found expected number of zoomlevels: ' + levels);
+            
+            var low = store.getAt(0).get("resolution");
+            t.eq(low, map.baseLayer.resolutions[levels-1],
+                 'First record has lowest res value: ' + low);
+
+            var high = store.getAt(levels-1).get("resolution");
+            t.eq(high, map.baseLayer.resolutions[0],
+                 'Last record has highest res value: ' + high);
+            
+            map.destroy();
+            mapPanel.destroy();
+            
         }
         
     </script>

Modified: sandbox/elemoine/playground/geoext/tests/lib/GeoExt/data/WMSCapabilitiesReader.html
===================================================================
--- sandbox/elemoine/playground/geoext/tests/lib/GeoExt/data/WMSCapabilitiesReader.html	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/tests/lib/GeoExt/data/WMSCapabilitiesReader.html	2009-07-23 09:53:02 UTC (rev 1282)
@@ -17,7 +17,7 @@
             var fields = reader.recordType.prototype.fields;
 
             // 1 test
-            t.eq(fields.items.length, 11, 'number of default items is correct');
+            t.eq(fields.items.length, 14, 'number of default items is correct');
 
 
             var reader = new GeoExt.data.WMSCapabilitiesReader({},[
@@ -33,7 +33,7 @@
                  'field values set from configuration are correct');
         }
         function test_read(t) {
-            t.plan(13);
+            t.plan(16);
 
             var reader = new GeoExt.data.WMSCapabilitiesReader();
 
@@ -72,6 +72,12 @@
             t.eq(layer.url, "http://publicus.opengeo.org:80/geoserver/wms?SERVICE=WMS&", "[2] layer field has correct URL");
             t.eq(layer.params.LAYERS, "tiger:tiger_roads","[2] layer field has correct LAYERS parameter");
             t.eq(layer.name, "Manhattan (NY) roads","[2] layer field has correct name");
+            
+            // 3 tests -- attribution markup
+            var attribution = layer.attribution;
+            t.ok(attribution.indexOf("http://foo/logo.png") !== -1, "attribution markup has a logo");
+            t.ok(attribution.indexOf("Foo Authority") !== -1, "attribution markup has a title");
+            t.ok(attribution.indexOf("http://foo/about/") !== -1, "attribution has a link");
 
         }
     </script>

Modified: sandbox/elemoine/playground/geoext/tests/lib/GeoExt/data/WMSCapabilitiesReader.js
===================================================================
--- sandbox/elemoine/playground/geoext/tests/lib/GeoExt/data/WMSCapabilitiesReader.js	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/tests/lib/GeoExt/data/WMSCapabilitiesReader.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -4132,6 +4132,14 @@
       'AUTHORITY["EPSG","4326"]]-->' +
             '<LatLonBoundingBox minx="-74.08769307536667" miny="40.660618924633326" maxx="-73.84653192463333" maxy="40.90178007536667"/>' +
             '<BoundingBox SRS="EPSG:4326" minx="-74.02722" miny="40.684221" maxx="-73.907005" maxy="40.878178"/>' +
+            '<Attribution>' +
+              '<Title>Foo Authority</Title>' +
+              '<OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://foo/about/" />' +
+              '<LogoURL width="24" height="24">' +
+                '<Format>image/png</Format>' +
+                '<OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://foo/logo.png" />' +
+              '</LogoURL>' +
+            '</Attribution>' +
             '<Style>' +
               '<Name>tiger_roads</Name>' +
               '<Title>Default Styler</Title>' +

Copied: sandbox/elemoine/playground/geoext/tests/lib/GeoExt/data/WMSDescribeLayerReader.html (from rev 1281, core/trunk/geoext/tests/lib/GeoExt/data/WMSDescribeLayerReader.html)
===================================================================
--- sandbox/elemoine/playground/geoext/tests/lib/GeoExt/data/WMSDescribeLayerReader.html	                        (rev 0)
+++ sandbox/elemoine/playground/geoext/tests/lib/GeoExt/data/WMSDescribeLayerReader.html	2009-07-23 09:53:02 UTC (rev 1282)
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html debug="true">
+  <head>
+    <script type="text/javascript" src="../../../../../ext/adapter/ext/ext-base.js"></script>
+    <script type="text/javascript" src="../../../../../ext/ext-all-debug.js"></script>
+
+    <script type="text/javascript" src="../../../../../openlayers/lib/OpenLayers.js"></script>
+    <script type="text/javascript" src="../../../../lib/GeoExt.js"></script>
+    <script type="text/javascript" src="WMSDescribeLayerReader.js"></script>
+
+    <script type="text/javascript">
+      
+        function test_constructor(t) {
+            t.plan(2);
+            var reader = new GeoExt.data.WMSDescribeLayerReader();
+
+            var fields = reader.recordType.prototype.fields;
+
+            // 1 test
+            t.eq(fields.items.length, 3, 'number of default items is correct');
+
+
+            var reader = new GeoExt.data.WMSDescribeLayerReader({},[
+                {name: "foo"},
+                {name: "bar"}
+            ]);
+
+            var fields = reader.recordType.prototype.fields;
+
+            //1 test
+            t.ok(fields.items[0].name == 'foo' &&
+                 fields.items[1].name == 'bar',
+                 'field values set from configuration are correct');
+        }
+        function test_read(t) {
+            t.plan(4);
+
+            var reader = new GeoExt.data.WMSDescribeLayerReader();
+
+            var records = reader.read({responseXML : doc});
+
+            //1 test
+            t.eq(records.totalRecords, 2, 'readRecords returns correct number of records');
+            
+            var record = records.records[0];
+
+            //3 tests -- testing the fields of a record
+            t.eq(record.get("owsType"), "WFS", "[0] correct owsType");
+            t.eq(record.get("owsURL"), "http://demo.opengeo.org/geoserver/wfs/WfsDispatcher?", "[0] correct owsURL");
+            t.eq(record.get("typeName"),"topp:states", "[0] correct typeName");
+        }
+    </script>
+  <body>
+    <div id="map"></div>
+  </body>
+</html>

Copied: sandbox/elemoine/playground/geoext/tests/lib/GeoExt/data/WMSDescribeLayerReader.js (from rev 1281, core/trunk/geoext/tests/lib/GeoExt/data/WMSDescribeLayerReader.js)
===================================================================
--- sandbox/elemoine/playground/geoext/tests/lib/GeoExt/data/WMSDescribeLayerReader.js	                        (rev 0)
+++ sandbox/elemoine/playground/geoext/tests/lib/GeoExt/data/WMSDescribeLayerReader.js	2009-07-23 09:53:02 UTC (rev 1282)
@@ -0,0 +1,11 @@
+var doc = (new OpenLayers.Format.XML).read(
+    '<?xml version="1.0" encoding="UTF-8"?>'+
+    '<!DOCTYPE WMS_DescribeLayerResponse SYSTEM "http://demo.opengeo.org/geoserver/schemas/wms/1.1.1/WMS_DescribeLayerResponse.dtd">'+
+    '<WMS_DescribeLayerResponse version="1.1.1">'+
+        '<LayerDescription name="topp:states" wfs="http://demo.opengeo.org/geoserver/wfs/WfsDispatcher?">'+
+            '<Query typeName="topp:states"/>'+
+        '</LayerDescription>'+
+        '<LayerDescription name="topp:bluemarble" wfs="http://demo.opengeo.org/geoserver/wfs/WfsDispatcher?">'+
+        '</LayerDescription>'+
+    '</WMS_DescribeLayerResponse>'
+);

Modified: sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/Action.html
===================================================================
--- sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/Action.html	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/Action.html	2009-07-23 09:53:02 UTC (rev 1282)
@@ -7,46 +7,21 @@
     <script type="text/javascript" src="../../../../lib/GeoExt.js"></script>
 
     <script type="text/javascript">
-        function test_fromControl(t) {
-            t.plan(4);
-
-            var ctrl, action, cfg;
-            
-            ctrl = new OpenLayers.Control();
-
-            // 2 tests
-            action = GeoExt.Action.fromControl(ctrl);
-            t.ok(action instanceof Ext.Action,
-                 "fromControl return an Ext.Action instance");
-            t.ok(action.control == ctrl,
-                 "fromControl sets the control in the returned instance");
-
-            // 1 test
-            cfg = {text: "foo"};
-            action = GeoExt.Action.fromControl(ctrl, cfg);
-            t.ok(action.initialConfig == cfg,
-                 "fromControl sets the config in the instance's initial config");
-            
-            // 1 test
-            var a = new Ext.Action({text: "foo"});
-            action = GeoExt.Action.fromControl(ctrl, a);
-            t.ok(action.initialConfig == a.initialConfig,
-                 "fromControl sets the passed action's initial config in the " +
-                 "instance's initial config");
-        }
-
         function test_constructor(t) {
-            t.plan(10)
+            t.plan(12)
 
             var ctrl, scope, handler, toggleHandler, checkHandler, cfg, action;
 
             ctrl = new OpenLayers.Control();
+            
+            var map = new OpenLayers.Map();
 
             scope = {}, handler = function() {};
             toggleHandler = function() {}, checkHandler = function() {};
 
             cfg = {
                 control: ctrl,
+                map: map,
                 scope: scope,
                 handler: handler,
                 toggleHandler: toggleHandler,
@@ -57,6 +32,10 @@
 
             t.ok(action.control == ctrl,
                  "constructor sets control in the instance");
+            t.ok(action.control.map === map,
+                 "constructor adds control to map if provided");
+            t.ok(!action.initialConfig.map,
+                 "action does not have a reference to the map");
             t.ok(action.uScope == scope,
                  "constructor sets this.uScope to user-provided scope");
             t.ok(action.uHandler == handler,
@@ -76,6 +55,8 @@
                  "constructor sets toggleHandler to this.ptoggleHandler in the initial config");
             t.ok(action.initialConfig.checkHandler == action.pCheckHandler,
                  "constructor sets checkHandler to this.pCheckHandler in the initial config");
+            
+            map.destroy();
         }
 
         function test_button(t) {
@@ -111,7 +92,8 @@
             });
             ctrl.activate();
 
-            action = GeoExt.Action.fromControl(ctrl, {
+            action = new GeoExt.Action({
+                control: ctrl,
                 handler: function() {
                     handlerCnt++;
                 }
@@ -194,7 +176,8 @@
             });
             ctrl.activate();
 
-            action = GeoExt.Action.fromControl(ctrl, {
+            action = new GeoExt.Action({
+                control: ctrl,
                 enableToggle: true,
                 toggleHandler: function() {
                     toggleHandlerCnt++;
@@ -318,11 +301,13 @@
             ctrl2.activate();
 
             // the actions
-            action1 = GeoExt.Action.fromControl(ctrl1, {
+            action1 = new GeoExt.Action({
+                control: ctrl1,
                 toggleGroup: "ctrl",
                 pressed: false
             });
-            action2 = GeoExt.Action.fromControl(ctrl2, {
+            action2 = new GeoExt.Action({
+                control: ctrl2,
                 toggleGroup: "ctrl",
                 pressed: true
             });

Copied: sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/LayerOpacitySlider.html (from rev 1281, core/trunk/geoext/tests/lib/GeoExt/widgets/LayerOpacitySlider.html)
===================================================================
--- sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/LayerOpacitySlider.html	                        (rev 0)
+++ sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/LayerOpacitySlider.html	2009-07-23 09:53:02 UTC (rev 1282)
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<html debug="true">
+  <head>
+    <script type="text/javascript" src="../../../../../openlayers/lib/OpenLayers.js"></script>
+    <script type="text/javascript" src="../../../../../ext/adapter/ext/ext-base.js"></script>
+    <script type="text/javascript" src="../../../../../ext/ext-all-debug.js"></script>
+    <script type="text/javascript" src="../../../../lib/GeoExt.js"></script>
+
+    <script type="text/javascript">
+
+        function test_constructor(t) {
+            t.plan(2);
+
+            var record, store, slider;
+            var layer = new OpenLayers.Layer("a");
+
+            record = new (GeoExt.data.LayerRecord.create())(
+                {layer: layer, title: layer.name}, layer.id
+            );
+            slider = new GeoExt.LayerOpacitySlider({
+                layer: record
+            });
+            t.eq(slider.layer.id, record.id, "layer parameter is a GeoExt.data.LayerRecord");
+            slider.destroy();
+
+            var slider = new GeoExt.LayerOpacitySlider({
+                layer: layer
+            });
+            t.eq(layer.id, slider.layer.id, "layer parameter is a OpenLayers.Layer.WMS");
+            slider.destroy();
+        }
+
+        function test_initalOpacity(t) {
+            t.plan(3);
+
+            var slider = new GeoExt.LayerOpacitySlider({
+                layer: new OpenLayers.Layer('foo')
+            });
+            t.ok(slider.getValue() == 100,
+                 "set the value to 100 if the layer has no opacity");
+            slider.destroy();
+
+            slider = new GeoExt.LayerOpacitySlider({
+                layer: new OpenLayers.Layer('foo', { opacity: 0 })
+            });
+            t.ok(slider.getValue() == 0,
+                 "initial layer's opacity sets the slider value");
+            slider.destroy();
+
+            slider = new GeoExt.LayerOpacitySlider({
+                layer: new OpenLayers.Layer('foo', { opacity: 0.42 })
+            });
+            t.ok(slider.getValue() == 42,
+                 "initial layer's opacity sets the slider value");
+            slider.destroy();
+        }
+
+        function test_aggressive(t) {
+            t.plan(2);
+
+            var slider1 = new GeoExt.LayerOpacitySlider({
+                renderTo: document.body,
+                layer: new OpenLayers.Layer('foo'),
+                aggressive: false
+            });
+            slider1.on({
+                changecomplete: function() {
+                    t.ok(true, "changecomplete triggered in non-aggressive mode");
+                }
+            });
+
+            var slider2 = new GeoExt.LayerOpacitySlider({
+                renderTo: document.body,
+                layer: new OpenLayers.Layer('foo'),
+                aggressive: true
+            });
+            slider2.on({
+                change: function() {
+                    t.ok(true, "change triggered in aggressive mode");
+                }
+            });
+            slider1.setValue(42, undefined, true);
+            slider2.setValue(42, undefined, true);
+
+            slider1.destroy();
+            slider2.destroy();
+        }
+    </script>
+  <body>
+  </body>
+</html>

Copied: sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/LegendImage.html (from rev 1281, core/trunk/geoext/tests/lib/GeoExt/widgets/LegendImage.html)
===================================================================
--- sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/LegendImage.html	                        (rev 0)
+++ sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/LegendImage.html	2009-07-23 09:53:02 UTC (rev 1282)
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <script type="text/javascript" src="../../../../../openlayers/lib/OpenLayers.js"></script>
+    <script type="text/javascript" src="../../../../../ext/adapter/ext/ext-base.js"></script>
+    <script type="text/javascript" src="../../../../../ext/ext-all-debug.js"></script>
+    <script type="text/javascript" src="../../../../lib/GeoExt.js"></script>
+
+    <script type="text/javascript">
+
+        function test_constructor(t) {
+            t.plan(2);
+            
+            var legend;
+            
+            // create a legend with the default config
+            legend = new GeoExt.LegendImage();
+            t.eq(legend.defaultImgSrc, Ext.BLANK_IMAGE_URL, "defaultImgSrc defaults to Ext.BLANK_IMAGE_URL");
+            legend.destroy();
+            
+            // create a legend with a custom defaultImgSrc
+            legend = new GeoExt.LegendImage({defaultImgSrc: "foo"});
+            t.eq(legend.defaultImgSrc, "foo", "defaultImgSrc can be set in config");
+            legend.destroy();
+            
+        }
+        
+        function test_onImageLoadError(t) {
+            t.plan(2);
+            
+            var legend, calls = 0;
+
+            // create a legend with a bogus image url (one call to error handler)
+            legend = new GeoExt.LegendImage({
+                url: "bogus",
+                defaultImgSrc: "also-bogus",
+                renderTo: "legend",
+                onImageLoadError: function() {
+                    ++calls;
+                    GeoExt.LegendImage.prototype.onImageLoadError.apply(this, arguments);
+                }
+            });
+            t.delay_call(0.5, function() {
+                t.eq(calls, 1, "onImageLoadError called once for bogus image src");
+                var el = legend.getEl();
+                t.eq(el && el.dom.src.split("/").pop(), "also-bogus", "defaultImgSrc set as image src");
+                legend.destroy();
+            });            
+            
+        }
+
+
+    </script>
+  <body>
+    <div id="legend"></div>
+  </body>
+</html>

Modified: sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/LegendPanel.html
===================================================================
--- sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/LegendPanel.html	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/LegendPanel.html	2009-07-23 09:53:02 UTC (rev 1282)
@@ -8,16 +8,7 @@
 
     <script type="text/javascript">
 
-        function createMap() {
-            var map = new OpenLayers.Map({allOverlays: true});
-            var layer = new OpenLayers.Layer.WMS("test", '/ows', {layers: 'a'});
-            map.addLayer(layer);
-            return map;
-        }
-
         function loadMapPanel() {
-            var map = createMap();
-
             mapPanel = new GeoExt.MapPanel({
                 // panel options
                 id: "map-panel",
@@ -26,7 +17,9 @@
                 height: 400,
                 width: 600,
                 // map panel-specific options
-                map: map,
+                layers: [
+                    new OpenLayers.Layer.WMS("test", '/ows', {layers: 'a'})
+                ],
                 center: new OpenLayers.LonLat(5, 45),
                 zoom: 4
             });
@@ -35,19 +28,31 @@
         }
 
         function test_legendurl(t) {
-            t.plan(1);
+            t.plan(3);
             var mapPanel = loadMapPanel();
             var lp  = new GeoExt.LegendPanel({
                 renderTo: 'legendpanel'});
             lp.render();
 
-            var newUrl = "http://www.geoext.org//trac/geoext/chrome/site/img/GeoExt.png";
+            var newUrl = "http://trac.geoext.org/chrome/site/img/GeoExt.png";
             mapPanel.layers.getAt(0).set("legendURL", newUrl);
 
             var item = lp.getComponent(mapPanel.map.layers[0].id);
-            var url = item.items.items[1].items.items[0].getEl().dom.src;
+            var url = item.items.get(1).items.get(0).getEl().dom.src;
             t.eq(url, newUrl, "Update the image with the provided legendURL");
 
+            var vectorLayer = new OpenLayers.Layer.Vector("vector layer");
+            mapPanel.map.addLayer(vectorLayer);
+
+            vectorLayer.setVisibility(false);
+
+            t.eq(lp.items.length, 1, "Currently there are no legends for non WMS layers");
+
+            var wms = new OpenLayers.Layer.WMS("testArray", '/ows', {layers: ['a', 'b', 'c']});
+            mapPanel.map.addLayer(wms);
+
+            t.eq(lp.items.length, 2, "The legend panel can deal with WMS layers which have a LAYERS params which is an array");
+
             lp.destroy();
             mapPanel.destroy();
         }
@@ -104,19 +109,24 @@
         }
 
         function test_wms(t) {
-            t.plan(1);
+            t.plan(3);
             var mapPanel = loadMapPanel();
+            var LegendWMS = GeoExt.LegendWMS;
+            GeoExt.LegendWMS = function(config) {
+                t.ok(config.record == mapPanel.layers.getAt(0), "layer record passed correctly");
+                t.ok(config.layer == mapPanel.map.layers[0], "layer passed correctly");
+                t.eq(config.foo, "bar", "legendOptions passed correctly");
+                return new Ext.Panel();
+            }
             var lp  = new GeoExt.LegendPanel({
-                renderTo: 'legendpanel'});
+                renderTo: 'legendpanel',
+                legendOptions: {foo: "bar"}
+            });
             lp.render();
 
-            var item = lp.getComponent(mapPanel.map.layers[0].id);
-            var url = item.items.items[1].items.items[0].url;
-            var expectedUrl = "/ows?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetLegendGraphic&STYLES=&EXCEPTIONS=application%2Fvnd.ogc.se_xml&FORMAT=image%2Fgif&LAYER=a";
-            t.eq(url, expectedUrl, "GetLegendGraphic url is generated correctly");
-
             lp.destroy();
             mapPanel.destroy();
+            GeoExt.LegendWMS = LegendWMS;
         }
 
         function test_addremove(t) {
@@ -147,6 +157,37 @@
             mapPanel.destroy();
         }
 
+        function test_changelayername(t) {
+            t.plan(3);
+            var mapPanel = loadMapPanel();
+            var lp  = new GeoExt.LegendPanel({
+                renderTo: 'legendpanel'});
+            lp.render();
+
+            var layer = mapPanel.map.layers[0];
+            var cmp = lp.getComponent(layer.id);
+            t.eq(cmp.items.get(0).text, 'test', "Layer name is test before change");
+
+            layer.setName("My new name");
+
+            t.eq(cmp.items.get(0).text, "My new name", "Layer name was changed correctly to 'My new name'");
+
+            lp.destroy();
+
+            var lp  = new GeoExt.LegendPanel({
+                showTitle: false,
+                renderTo: 'legendpanel'});
+            lp.render();
+
+            layer.setName("My new new name");
+            var cmp = lp.getComponent(layer.id);
+            t.eq(cmp.items.get(0).text, "", "When showTitle is false, there is no label for a layer and it is not changed");
+
+            lp.destroy();
+
+            mapPanel.destroy();
+        }
+
     </script>
   <body>
     <div id="legendpanel"></div>

Copied: sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/LegendWMS.html (from rev 1281, core/trunk/geoext/tests/lib/GeoExt/widgets/LegendWMS.html)
===================================================================
--- sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/LegendWMS.html	                        (rev 0)
+++ sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/LegendWMS.html	2009-07-23 09:53:02 UTC (rev 1282)
@@ -0,0 +1,78 @@
+<!DOCTYPE html>
+<html debug="true">
+  <head>
+    <script type="text/javascript" src="../../../../../openlayers/lib/OpenLayers.js"></script>
+    <script type="text/javascript" src="../../../../../ext/adapter/ext/ext-base.js"></script>
+    <script type="text/javascript" src="../../../../../ext/ext-all.js"></script>
+    <script type="text/javascript" src="../../../../lib/GeoExt.js"></script>
+
+    <script type="text/javascript">
+
+        function loadMapPanel() {
+            var mapPanel = new GeoExt.MapPanel({
+                // panel options
+                id: "map-panel",
+                title: "GeoExt MapPanel",
+                renderTo: "mappanel",
+                height: 400,
+                width: 600,
+                // map panel-specific options
+                layers: [
+                    new OpenLayers.Layer.WMS("test", '/ows', {layers: 'a'})
+                ],
+                center: new OpenLayers.LonLat(5, 45),
+                zoom: 4
+            });
+
+            return mapPanel;
+        }
+
+        function test_legendurl(t) {
+            t.plan(3);
+            var mapPanel = loadMapPanel();
+            var l = new GeoExt.LegendWMS({
+                renderTo: 'legendwms',
+                record: mapPanel.layers.getAt(0)
+            });
+            l.render();
+
+            var url = l.items.get(0).url;
+            var expectedUrl = "/ows?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetLegendGraphic&STYLES=&EXCEPTIONS=application%2Fvnd.ogc.se_xml&FORMAT=image%2Fgif&LAYER=a";
+            t.eq(url, expectedUrl, "GetLegendGraphic url is generated correctly");
+            l.destroy()
+            
+            mapPanel.map.layers[0].params.STYLES="bar";
+            mapPanel.layers.getAt(0).set("styles", [{
+                name: "bar",
+                legend: {href: "foo"}
+            }]);
+            var l = new GeoExt.LegendWMS({
+                renderTo: 'legendwms',
+                record: mapPanel.layers.getAt(0)
+            });
+            l.render();
+            var url = l.items.get(0).url;
+            t.eq(url, "foo", "legend url from styles field of layer record used correctly.");
+            l.destroy();
+            
+            delete mapPanel.map.layers[0].params.STYLES;
+            var l = new GeoExt.LegendWMS({
+                renderTo: 'legendwms',
+                record: mapPanel.layers.getAt(0),
+                defaultStyleIsFirst: true
+            });
+            l.render();
+            var url = l.items.get(0).url;
+            t.eq(url, "foo", "legend url from styles field of layer record used correctly when defaultStyleIsFirst set to true and layer has no STYLES param.");
+
+            l.destroy();
+            mapPanel.destroy();
+        }
+
+
+    </script>
+  <body>
+    <div id="legendwms"></div>
+    <div id="mappanel"></div>
+  </body>
+</html>

Modified: sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/MapPanel.html
===================================================================
--- sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/MapPanel.html	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/MapPanel.html	2009-07-23 09:53:02 UTC (rev 1282)
@@ -12,14 +12,24 @@
             var map = new OpenLayers.Map();
             var layer = new OpenLayers.Layer("test", {isBaseLayer: true});
             map.addLayer(layer);
+            // add a vector layer, which would fail onmapresize if we render
+            // the map before the panel has a layout.
+            map.addLayer(new OpenLayers.Layer.Vector("vector layer"));
             return map;
         }
 
         function test_mappanel(t) {
-            t.plan(3)
+            t.plan(4)
 
+            var moveToCnt;
+
             var map = createMap();
-            
+            map.moveTo = function() {
+                moveToCnt++;
+                OpenLayers.Map.prototype.moveTo.apply(this, arguments);
+            };
+
+            moveToCnt = 0;
             var mapPanel = new GeoExt.MapPanel({
                 // panel options
                 id: "map-panel",
@@ -32,6 +42,7 @@
                 center: new OpenLayers.LonLat(5, 45),
                 zoom: 4
             });
+            t.eq(moveToCnt, 1, "map.moveTo called exactly once");
             t.eq(mapPanel.map.getCenter().toString(), "lon=5,lat=45", "Map center set correctly");
             t.eq(mapPanel.map.getZoom(), 4, "Zoom set correctly");
             t.eq(GeoExt.MapPanel.guess().id, mapPanel.id, "MapPanel guessed correctly");
@@ -74,6 +85,24 @@
             
         }
 
+        function test_zoom(t) {
+            
+            t.plan(1);
+            
+            var panel = new GeoExt.MapPanel({
+                title: "GeoExt MapPanel",
+                renderTo: "mappanel",
+                height: 400,
+                width: 600,
+                layers: [new OpenLayers.Layer()],
+                zoom: 4
+            });
+            
+            t.eq(panel.map.zoom, 4, "zoom correctly set");
+            
+            panel.destroy();
+        }
+
         function test_extent(t) {
             
             t.plan(3);
@@ -82,10 +111,12 @@
             map = createMap();
             map.zoomToExtent = function(extent) {
                 log.extent = extent;
-            }
+            };
             panel = new GeoExt.MapPanel({
                 renderTo: "mappanel",
                 map: map,
+                height: 400,
+                width: 600,
                 extent: [1, 2, 3, 4]
             });            
             t.eq(log.extent.toArray(), [1, 2, 3, 4], "map extent set with array");
@@ -97,10 +128,12 @@
             map = createMap();
             map.zoomToExtent = function(extent) {
                 log.extent = extent;
-            }
+            };
             panel = new GeoExt.MapPanel({
                 renderTo: "mappanel",
                 map: map,
+                height: 400,
+                width: 600,
                 extent: "1, 2, 3, 4"
             });
             t.eq(log.extent.toArray(), [1, 2, 3, 4], "map extent set with string");
@@ -111,10 +144,12 @@
             map = createMap();
             map.zoomToExtent = function(extent) {
                 log.extent = extent;
-            }
+            };
             panel = new GeoExt.MapPanel({
                 renderTo: "mappanel",
                 map: map,
+                height: 400,
+                width: 600,
                 extent: new OpenLayers.Bounds(1, 2, 3, 4)
             });
             t.eq(log.extent.toArray(), [1, 2, 3, 4], "map extent set with Bounds");
@@ -132,10 +167,12 @@
             map = createMap();
             map.setCenter = function(center) {
                 log.center = center;
-            }
+            };
             panel = new GeoExt.MapPanel({
                 renderTo: "mappanel",
                 map: map,
+                height: 400,
+                width: 600,
                 center: [1, 2]
             });            
             t.eq(log.center.toString(), "lon=1,lat=2", "map center set with array");
@@ -147,10 +184,12 @@
             map = createMap();
             map.setCenter = function(center) {
                 log.center = center;
-            }
+            };
             panel = new GeoExt.MapPanel({
                 renderTo: "mappanel",
                 map: map,
+                height: 400,
+                width: 600,
                 center: "1, 2"
             });            
             t.eq(log.center.toString(), "lon=1,lat=2", "map center set with string");
@@ -162,10 +201,12 @@
             map = createMap();
             map.setCenter = function(center) {
                 log.center = center;
-            }
+            };
             panel = new GeoExt.MapPanel({
                 renderTo: "mappanel",
                 map: map,
+                height: 400,
+                width: 600,
                 center: new OpenLayers.LonLat(1, 2)
             });            
             t.eq(log.center.toString(), "lon=1,lat=2", "map center set with LonLat");
@@ -213,7 +254,43 @@
             
         }
 
+        function test_layout(t) {
+            t.plan(1);
 
+            var map, panel, layout = 0;
+
+            map = new OpenLayers.Map({
+                render: function() {
+                    OpenLayers.Map.prototype.render.apply(this, arguments);
+                    t.ok(layout, 1,
+                         "the OpenLayers map is rendered once the container " +
+                         "has its final dimensions");
+                },
+                allOverlays: true
+            });
+            
+            panel = new Ext.Panel({
+                layout: "border",
+                renderTo: "mappanel",
+                listeners: {
+                    afterlayout: function() {
+                        layout++;
+                    }
+                },
+                items: [{
+                    region: "center",
+                    xtype: "gx_mappanel",
+                    map: map,
+                    layers: [
+                        new OpenLayers.Layer("")
+                    ]
+                }]
+            });
+
+            panel.destroy();
+        }
+
+
     </script>
   <body>
     <div id="mappanel"></div>

Modified: sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/Popup.html
===================================================================
--- sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/Popup.html	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/Popup.html	2009-07-23 09:53:02 UTC (rev 1282)
@@ -11,7 +11,7 @@
 
         function setupContext() {        
 
-            var map = new OpenLayers.Map();
+            var map = new OpenLayers.Map({panMethod: null}); // avoid tween panning for tests
             var layer = new OpenLayers.Layer("test", {isBaseLayer: true});
             map.addLayer(layer);
 
@@ -29,9 +29,13 @@
             });
 
             var feature = new OpenLayers.Feature.Vector(
-                new OpenLayers.Geometry.Point(100,50),
+                new OpenLayers.Geometry.Point(5,45),
                 {name: "My Feature"}
             );
+            feature.layer = {
+                map: map,
+                removeFeatures: function() {}
+            };
 
             return {
                 feature: feature,
@@ -63,53 +67,70 @@
 
             var pop = popup(context.feature);
 
-            context.mapPanel.add(pop);
+            pop.show();
 
-            t.ok(context.mapPanel.el.child("div." + pop.popupCls),"Map panel contains popup");
-            
+            t.ok(Ext.getBody().child("div." + pop.popupCls),"viewport contains popup");
+
             tearDown(context);
         }
 
         function test_anchorPopup(t) {
-            t.plan(4);
+            t.plan(5);
 
             var context = setupContext();
 
             var pop = popup(context.feature);
 
-            context.mapPanel.add(pop);
-
+            // show the popup and move the map to ensure popup is actually visible
+            pop.show();
+            context.map.setCenter(new OpenLayers.LonLat(5, 45));
+            
+            var moves = 0;
             pop.on({
-                'move' : function(c,x,y){
-                    t.ok(true,"Move event fired on " + action); //should happen twice, on call to position()
+                move: function() {
+                    ++moves;
                 },
                 scope : this
             });
 
             t.ok(pop.getAnchorElement(), "Popup has anchor element");
 
-            var action = "map move";
-            context.map.events.triggerEvent("move");
-            
-            action = "popup collapse";
+            // move the map and confirm that popup moves
+            context.map.setCenter(new OpenLayers.LonLat(6, 45));
+            t.eq(moves, 1, "anchored popup moves once on map.setCenter");
+            moves = 0;
+
+            // anchored popup needs to reposition on collapse, resize and
+            // expand to keep the anchor point on the feature
+
+            // collapse popup and and confirm that it moves
             pop.collapse();
+            t.eq(moves, 1, "anchored popup moves once on collapse");
+            moves = 0;
 
-            action = "popup expand"
+            // expand popup and confirm that it moves
             pop.expand();
+            t.eq(moves, 1, "anchored popup moves once on expand");
+            moves = 0;
             
+            // resize popup and confirm that it moves
+            pop.setSize(100, 100);
+            t.eq(moves, 1, "anchored popup moves once on resize");
+            moves = 0;
+
             tearDown(context);
         }
 
 
         function test_unanchorPopup(t) {
-            t.plan(6);
+            t.plan(4);
 
             var context = setupContext();
 
             var pop = popup(context.feature, context.mapPanel);
 
-            context.mapPanel.add(pop);
-        
+            pop.show();
+
             pop.collapse();
 
             var origPos = pop.getPosition();
@@ -120,8 +141,6 @@
 
             t.ok(!pop.getAnchorElement(),"Anchor element removed");
             t.ok(!this.collapsed, "Preserved collapsed state");
-            t.ok(!context.mapPanel.el.child("div." + pop.popupCls),"Map panel does not contain popup");
-            t.ok(Ext.getBody().child("div." + pop.popupCls),"Document body contains popup element");
             t.eq(origPos[0],newPos[0],"Popup remains in same position (X)");
             t.eq(origPos[1],newPos[1],"Popup remains in same position (Y)");
 
@@ -151,7 +170,7 @@
 
             var context = setupContext();
             var pop = popup(context.feature);
-            context.mapPanel.add(pop);
+            pop.show();
             
             var called = false;
             pop.on({

Copied: sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/ZoomSlider.html (from rev 1281, core/trunk/geoext/tests/lib/GeoExt/widgets/ZoomSlider.html)
===================================================================
--- sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/ZoomSlider.html	                        (rev 0)
+++ sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/ZoomSlider.html	2009-07-23 09:53:02 UTC (rev 1282)
@@ -0,0 +1,93 @@
+<!DOCTYPE html>
+<html debug="true">
+  <head>
+    <script type="text/javascript" src="../../../../../openlayers/lib/OpenLayers.js"></script>
+    <script type="text/javascript" src="../../../../../ext/adapter/ext/ext-base.js"></script>
+    <script type="text/javascript" src="../../../../../ext/ext-all-debug.js"></script>
+    <script type="text/javascript" src="../../../../lib/GeoExt.js"></script>
+
+    <script type="text/javascript">
+       
+        function test_zoomslider(t) {
+            t.plan(7);
+            
+            var map = new OpenLayers.Map({
+                div: "map",
+                allOverlays: true
+            });
+            map.addLayer(new OpenLayers.Layer());
+            map.setCenter(new OpenLayers.LonLat(0, 0), 2);
+            
+            var slider = new GeoExt.ZoomSlider({
+                map: map,
+                renderTo: document.body
+            });
+            
+            // test range of values
+            t.eq(slider.minValue, 0, "slider min is 0");
+            t.eq(slider.maxValue, 15, "slider can go to 15");
+            
+            // test initial value
+            t.eq(slider.getValue(), 2, "slider has correct value after setCenter");
+            
+            // zoom in and test that value is updated
+            map.zoomIn();
+            t.eq(slider.getValue(), 3, "slider has correct value after zoomIn");
+            
+            // test that zoomTo updates slider value
+            map.zoomTo(0);
+            t.eq(slider.getValue(), 0, "slider has correct value after zoomTo");
+            
+            // test that slider can be destroyed
+            try {
+                slider.destroy();
+                t.ok(true, "slider.destroy does not cause problems");
+            } catch(err) {
+                t.fail("slider.destroy causes problems: " + err);
+            }
+            
+            // test that map can be zoomed without trouble after slider destroy
+            try {
+                map.zoomIn();
+                t.ok(true, "map.zoomIn does not cause problems after slider.destroy");
+            } catch(err) {
+                t.fail("map.zoomIn causes problems after slider.destroy: " + err);
+            }
+            
+            map.destroy();
+
+        }
+        
+        function test_zoomslider_aggressive(t) {
+            t.plan(2);
+            var slider1 = new GeoExt.ZoomSlider({
+                renderTo: document.body
+            });
+            slider1.on({
+                "changecomplete": function() {
+                    t.ok(true, "changecomplete triggered in non-aggressive mode");
+                }
+            });
+            var slider2 = new GeoExt.ZoomSlider({
+                renderTo: document.body,
+                aggressive: true
+            });
+            slider2.on({
+                "change": function() {
+                    t.ok(true, "change triggered in aggressive mode");
+                }
+            });
+            
+            slider1.setValue(slider1.maxValue, undefined, true);
+            slider2.setValue(slider2.maxValue, undefined, true);
+            
+            slider1.destroy();
+            slider2.destroy();
+        }
+
+    </script>
+  </head>
+  <body>
+    <div id="map" style="width: 512px; height: 256px;"></div>
+  </body>
+</html>

Copied: sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/grid (from rev 1281, core/trunk/geoext/tests/lib/GeoExt/widgets/grid)

Deleted: sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/grid/FeatureSelectionModel.html
===================================================================
--- core/trunk/geoext/tests/lib/GeoExt/widgets/grid/FeatureSelectionModel.html	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/grid/FeatureSelectionModel.html	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,376 +0,0 @@
-<!DOCTYPE html>
-<html debug="true">
-  <head>
-    <script type="text/javascript" src="../../../../../../openlayers/lib/OpenLayers.js"></script>
-    <script type="text/javascript" src="../../../../../../ext/adapter/ext/ext-base.js"></script>
-    <script type="text/javascript" src="../../../../../../ext/ext-all-debug.js"></script>
-    <script type="text/javascript" src="../../../../../lib/GeoExt.js"></script>
-
-    <script type="text/javascript">
-    
-        function test_init(t) {
-            t.plan(11);
-
-            /*
-             * Set up
-             */
-            var map, layer, layers, selectControl, store, sm;
-            
-            map = new OpenLayers.Map();
-            layer = new OpenLayers.Layer.Vector("vector");
-            layers = [layer];
-            map.addLayers(layers);
-
-            store = new GeoExt.data.FeatureStore({layer: layer});
-
-            /*
-             * Test
-             */
-
-            // create a feature selection model
-            // 1 test
-            sm = new GeoExt.grid.FeatureSelectionModel();
-            t.ok(sm instanceof Ext.grid.RowSelectionModel,
-                 "a feature selection model is a row selection model");
-
-            // create a feature selection model and give it a
-            // select feature control
-            // 2 tests
-            selectControl = new OpenLayers.Control.SelectFeature(layer);
-            sm = new GeoExt.grid.FeatureSelectionModel({
-                selectControl: selectControl, multiple: false
-            });
-            t.ok(sm.selectControl == selectControl,
-                 "ctor sets the passed select feature control in the instance");
-            t.eq(sm.singleSelect, true,
-                 "ctor sets singleSelect to true in the instance");
-
-            // create a feature selection model with singleSelect true and give
-            // it a select feature control
-            // 1 test
-            selectControl = new OpenLayers.Control.SelectFeature(layer);
-            sm = new GeoExt.grid.FeatureSelectionModel({
-                singleSelect: true,
-                selectControl: selectControl
-            });
-            t.eq(sm.selectControl.multiple, false,
-                 "ctor configures the select feature control with multiple false");
-
-            // create a feature selection model and give it a layer and
-            // a select control config
-            // 3 tests
-            sm = new GeoExt.grid.FeatureSelectionModel({
-                layer: layer,
-                selectControl: {
-                    hover: true
-                }
-            });
-            t.ok(sm.selectControl instanceof OpenLayers.Control.SelectFeature,
-                 "ctor creates a select feature control when passed a layer");
-            t.ok(sm.selectControl.layer == layer,
-                 "ctor configures the select feature control with the passed layer");
-            t.eq(sm.selectControl.hover, true,
-                 "ctor configures the select feature control with the passed config");
-
-            // create a feature selection model and create a grid with it
-            // 3 tests
-            sm = new GeoExt.grid.FeatureSelectionModel({
-                selectControl: {
-                    hover: true
-                }
-            });
-            var grid = new Ext.grid.GridPanel({
-                renderTo: "grid",
-                store: store,
-                columns: [{
-                    header: "name"
-                }],
-                sm: sm,
-                deferRowRender: false
-            });
-            t.ok(sm.selectControl instanceof OpenLayers.Control.SelectFeature,
-                 "init creates a select feature control ");
-            t.ok(sm.selectControl.layer == layer,
-                 "init configures the select feature control with the store layer");
-            t.eq(sm.selectControl.hover, true,
-                 "init configures the select feature control with the passed config");
-            grid.destroy();
-
-            // 1 test
-            var CheckboxSelectionModel = Ext.extend(
-                Ext.grid.CheckboxSelectionModel,
-                GeoExt.grid.FeatureSelectionModelMixin
-            );
-            sm = new CheckboxSelectionModel();
-            t.ok(sm instanceof Ext.grid.CheckboxSelectionModel,
-                 "instance is a checkbox selection model");
-        }
-
-        function test_row_selection(t) {
-            t.plan(7);
-
-            /*
-             * Set up
-             */
-
-            var map, layer, features, store, sm, grid, e;
-
-            map = new OpenLayers.Map('map');
-
-            layer = new OpenLayers.Layer.Vector("vector");
-            map.addLayer(layer);
-
-            features = [
-                new OpenLayers.Feature.Vector(null,
-                    {foo: "foo1", bar: "bar1"}
-                ),
-                new OpenLayers.Feature.Vector(null,
-                    {foo: "foo2", bar: "bar2"}
-                )
-            ];
-            
-            store = new GeoExt.data.FeatureStore({
-                layer: layer,
-                data: features
-            });
-
-            sm = new GeoExt.grid.FeatureSelectionModel();
-
-            grid = new Ext.grid.GridPanel({
-                renderTo: "grid",
-                store: store,
-                columns: [{
-                    dataIndex: "foo"
-                }, {
-                    dataIndex: "bar"
-                }],
-                sm: sm,
-                deferRowRender: false
-            });
-
-            /*
-             * Test
-             */
-
-            // simulate a mousedown on the first row
-            // test that the first feature is selected in the layer
-            e = {
-                button: 0,
-                shiftKey: false,
-                ctrlKey: false
-            };
-            grid.fireEvent("rowmousedown", grid, 0, e);
-            t.ok(OpenLayers.Util.indexOf(layer.selectedFeatures,
-                                         features[0]) > -1,
-                 "click on row 0 selects feature 0");
-                 
-            // simulate a mousedown on the first row
-            // test that the first feature is deselected in the layer
-            e = {
-                button: 0,
-                shiftKey: false,
-                ctrlKey: true
-            };
-            grid.fireEvent("rowmousedown", grid, 0, e);
-            t.ok(OpenLayers.Util.indexOf(layer.selectedFeatures,
-                                         features[0]) < 0,
-                 "click on row 0 deselects feature 0");
-
-            // simulate a mousedown on the second row
-            grid.fireEvent("rowmousedown", grid, 1, e);
-            t.ok(OpenLayers.Util.indexOf(layer.selectedFeatures,
-                                         features[1]) > -1,
-                 "click on row 1 selects feature 1");
-
-            sm.clearSelections();
-
-            // select feature 0
-            // test that the first row is selected
-            sm.selectControl.select(features[0]);
-            t.ok(sm.isSelected(0),
-                 "selecting feature 0 selects row 0");
-
-            // select feature 1
-            // test that the second row is selected
-            sm.selectControl.select(features[1]);
-            t.ok(sm.isSelected(1),
-                 "selecting feature 1 selects row 1");
-
-            // unselect feature 0
-            // test that the first row is selected
-            sm.selectControl.unselect(features[0]);
-            t.ok(!sm.isSelected(0),
-                 "unselecting feature 0 unselects row 0");
-
-            // unselect feature 1
-            // test that the second row is unselected
-            sm.selectControl.unselect(features[1]);
-            t.ok(!sm.isSelected(1),
-                 "unselecting feature 1 unselects row 1");
-            
-            /*
-             * Tear down
-             */
-            grid.destroy();
-        }
-        
-        
-        function test_bind_unbind(t) {
-            t.plan(9);
-
-            /*
-             * Set up
-             */
-
-            var map, layer, selectControl, features, store, sm, grid, e;
-
-            map = new OpenLayers.Map('map');
-
-            layer = new OpenLayers.Layer.Vector("vector");
-            map.addLayer(layer);
-
-            selectControl = new OpenLayers.Control.SelectFeature(layer);
-            map.addControl(selectControl);
-
-            features = [
-                new OpenLayers.Feature.Vector(null,
-                    {foo: "foo1", bar: "bar1"}
-                ),
-                new OpenLayers.Feature.Vector(null,
-                    {foo: "foo2", bar: "bar2"}
-                )
-            ];
-            
-            store = new GeoExt.data.FeatureStore({
-                layer: layer,
-                data: features
-            });
-
-            sm = new GeoExt.grid.FeatureSelectionModel({
-                layerFromStore: false
-            });
-
-            grid = new Ext.grid.GridPanel({
-                renderTo: "grid",
-                store: store,
-                columns: [{
-                    dataIndex: "foo"
-                }, {
-                    dataIndex: "bar"
-                }],
-                sm: sm,
-                deferRowRender: false
-            });
- 
-            /*
-             * Test
-             */
-
-            // simulate a mousedown on the first row
-            // test that the first feature is not selected in the layer
-            e = {
-                button: 0,
-                shiftKey: false,
-                ctrlKey: false
-            };
-            grid.fireEvent("rowmousedown", grid, 0, e);
-            t.ok(OpenLayers.Util.indexOf(layer.selectedFeatures,
-                                         features[0]) < 0,
-                 "click on row 0 does not select feature 0");
-            sm.clearSelections();
-            
-            // select feature 0
-            // test that the first row is not selected
-            selectControl.select(features[0]);
-            t.ok(!sm.isSelected(0),
-                 "selecting feature 0 does not select row 0");
-            selectControl.unselect(features[0]);
-
-            // bind the select control to the selection model
-            sm.bind(selectControl);
-
-            // simulate a mousedown on the second row
-            // test that the second feature is selected in the layer
-            e = {
-                button: 0,
-                shiftKey: false,
-                ctrlKey: false
-            };
-            grid.fireEvent("rowmousedown", grid, 1, e);
-            t.ok(OpenLayers.Util.indexOf(layer.selectedFeatures,
-                                         features[1]) > -1,
-                 "click on row 1 selects feature 1");
-            sm.clearSelections();
-            
-            // select feature 1
-            // test that the second row is selected
-            selectControl.select(features[1]);
-            t.ok(sm.isSelected(1),
-                 "selecting feature 1 selects row 1");
-            selectControl.unselect(features[1]);
-            sm.clearSelections();
-            
-            // unbind row and feature selection
-            sm.unbind(); 
-            // (side effect: selectControl is deactivated)
-            
-            // simulate a mousedown on the first row
-            // test that the first feature is not selected in the layer
-            e = {
-                button: 0,
-                shiftKey: false,
-                ctrlKey: false
-            };
-            grid.fireEvent("rowmousedown", grid, 0, e);
-            t.ok(OpenLayers.Util.indexOf(layer.selectedFeatures,
-                                         features[0]) < 0,
-                 "click on row 0 does not select feature 0");
-            sm.clearSelections();
-            
-            // select feature 0
-            // test that the first row is not selected
-            selectControl.select(features[0]);
-            t.ok(!sm.isSelected(0),
-                 "selecting feature 0 does not select row 0");
-            selectControl.unselect(features[0]);
-            
-            // bind selection of features on a layer to rows
-            sm.bind(layer, {controlConfig: {hover: true}});
-            
-            // verify that controlConfig has been applied
-            t.eq(sm.selectControl.hover, true,
-                 "bind configures correctly the select feature control");
-
-            // simulate a mousedown on the second row
-            // test that the second feature is selected in the layer
-            e = {
-                button: 0,
-                shiftKey: false,
-                ctrlKey: false
-            };
-            grid.fireEvent("rowmousedown", grid, 1, e);
-            t.ok(OpenLayers.Util.indexOf(layer.selectedFeatures,
-                                         features[1]) > -1,
-                 "click on row 1 selects feature 1");
-            sm.clearSelections();
-            
-            // select feature 1
-            // test that the second row is selected
-            sm.selectControl.select(features[1]);
-            t.ok(sm.isSelected(1),
-                 "selecting feature 1 selects row 1");
-            sm.selectControl.unselect(features[1]);
-            sm.clearSelections();
-            
-            /*
-             * Tear down
-             */
-            grid.destroy();
-        }
-    </script>
-
-  <body>
-      <div id="map" style="width:100px;height:100px"></div>
-      <div id="grid"></div>
-  </body>
-</html>

Copied: sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/grid/FeatureSelectionModel.html (from rev 1281, core/trunk/geoext/tests/lib/GeoExt/widgets/grid/FeatureSelectionModel.html)
===================================================================
--- sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/grid/FeatureSelectionModel.html	                        (rev 0)
+++ sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/grid/FeatureSelectionModel.html	2009-07-23 09:53:02 UTC (rev 1282)
@@ -0,0 +1,376 @@
+<!DOCTYPE html>
+<html debug="true">
+  <head>
+    <script type="text/javascript" src="../../../../../../openlayers/lib/OpenLayers.js"></script>
+    <script type="text/javascript" src="../../../../../../ext/adapter/ext/ext-base.js"></script>
+    <script type="text/javascript" src="../../../../../../ext/ext-all-debug.js"></script>
+    <script type="text/javascript" src="../../../../../lib/GeoExt.js"></script>
+
+    <script type="text/javascript">
+    
+        function test_init(t) {
+            t.plan(11);
+
+            /*
+             * Set up
+             */
+            var map, layer, layers, selectControl, store, sm;
+            
+            map = new OpenLayers.Map();
+            layer = new OpenLayers.Layer.Vector("vector");
+            layers = [layer];
+            map.addLayers(layers);
+
+            store = new GeoExt.data.FeatureStore({layer: layer});
+
+            /*
+             * Test
+             */
+
+            // create a feature selection model
+            // 1 test
+            sm = new GeoExt.grid.FeatureSelectionModel();
+            t.ok(sm instanceof Ext.grid.RowSelectionModel,
+                 "a feature selection model is a row selection model");
+
+            // create a feature selection model and give it a
+            // select feature control
+            // 2 tests
+            selectControl = new OpenLayers.Control.SelectFeature(layer);
+            sm = new GeoExt.grid.FeatureSelectionModel({
+                selectControl: selectControl, multiple: false
+            });
+            t.ok(sm.selectControl == selectControl,
+                 "ctor sets the passed select feature control in the instance");
+            t.eq(sm.singleSelect, true,
+                 "ctor sets singleSelect to true in the instance");
+
+            // create a feature selection model with singleSelect true and give
+            // it a select feature control
+            // 1 test
+            selectControl = new OpenLayers.Control.SelectFeature(layer);
+            sm = new GeoExt.grid.FeatureSelectionModel({
+                singleSelect: true,
+                selectControl: selectControl
+            });
+            t.eq(sm.selectControl.multiple, false,
+                 "ctor configures the select feature control with multiple false");
+
+            // create a feature selection model and give it a layer and
+            // a select control config
+            // 3 tests
+            sm = new GeoExt.grid.FeatureSelectionModel({
+                layer: layer,
+                selectControl: {
+                    hover: true
+                }
+            });
+            t.ok(sm.selectControl instanceof OpenLayers.Control.SelectFeature,
+                 "ctor creates a select feature control when passed a layer");
+            t.ok(sm.selectControl.layer == layer,
+                 "ctor configures the select feature control with the passed layer");
+            t.eq(sm.selectControl.hover, true,
+                 "ctor configures the select feature control with the passed config");
+
+            // create a feature selection model and create a grid with it
+            // 3 tests
+            sm = new GeoExt.grid.FeatureSelectionModel({
+                selectControl: {
+                    hover: true
+                }
+            });
+            var grid = new Ext.grid.GridPanel({
+                renderTo: "grid",
+                store: store,
+                columns: [{
+                    header: "name"
+                }],
+                sm: sm,
+                deferRowRender: false
+            });
+            t.ok(sm.selectControl instanceof OpenLayers.Control.SelectFeature,
+                 "init creates a select feature control ");
+            t.ok(sm.selectControl.layer == layer,
+                 "init configures the select feature control with the store layer");
+            t.eq(sm.selectControl.hover, true,
+                 "init configures the select feature control with the passed config");
+            grid.destroy();
+
+            // 1 test
+            var CheckboxSelectionModel = Ext.extend(
+                Ext.grid.CheckboxSelectionModel,
+                GeoExt.grid.FeatureSelectionModelMixin
+            );
+            sm = new CheckboxSelectionModel();
+            t.ok(sm instanceof Ext.grid.CheckboxSelectionModel,
+                 "instance is a checkbox selection model");
+        }
+
+        function test_row_selection(t) {
+            t.plan(7);
+
+            /*
+             * Set up
+             */
+
+            var map, layer, features, store, sm, grid, e;
+
+            map = new OpenLayers.Map('map');
+
+            layer = new OpenLayers.Layer.Vector("vector");
+            map.addLayer(layer);
+
+            features = [
+                new OpenLayers.Feature.Vector(null,
+                    {foo: "foo1", bar: "bar1"}
+                ),
+                new OpenLayers.Feature.Vector(null,
+                    {foo: "foo2", bar: "bar2"}
+                )
+            ];
+            
+            store = new GeoExt.data.FeatureStore({
+                layer: layer,
+                data: features
+            });
+
+            sm = new GeoExt.grid.FeatureSelectionModel();
+
+            grid = new Ext.grid.GridPanel({
+                renderTo: "grid",
+                store: store,
+                columns: [{
+                    dataIndex: "foo"
+                }, {
+                    dataIndex: "bar"
+                }],
+                sm: sm,
+                deferRowRender: false
+            });
+
+            /*
+             * Test
+             */
+
+            // simulate a mousedown on the first row
+            // test that the first feature is selected in the layer
+            e = {
+                button: 0,
+                shiftKey: false,
+                ctrlKey: false
+            };
+            grid.fireEvent("rowmousedown", grid, 0, e);
+            t.ok(OpenLayers.Util.indexOf(layer.selectedFeatures,
+                                         features[0]) > -1,
+                 "click on row 0 selects feature 0");
+                 
+            // simulate a mousedown on the first row
+            // test that the first feature is deselected in the layer
+            e = {
+                button: 0,
+                shiftKey: false,
+                ctrlKey: true
+            };
+            grid.fireEvent("rowmousedown", grid, 0, e);
+            t.ok(OpenLayers.Util.indexOf(layer.selectedFeatures,
+                                         features[0]) < 0,
+                 "click on row 0 deselects feature 0");
+
+            // simulate a mousedown on the second row
+            grid.fireEvent("rowmousedown", grid, 1, e);
+            t.ok(OpenLayers.Util.indexOf(layer.selectedFeatures,
+                                         features[1]) > -1,
+                 "click on row 1 selects feature 1");
+
+            sm.clearSelections();
+
+            // select feature 0
+            // test that the first row is selected
+            sm.selectControl.select(features[0]);
+            t.ok(sm.isSelected(0),
+                 "selecting feature 0 selects row 0");
+
+            // select feature 1
+            // test that the second row is selected
+            sm.selectControl.select(features[1]);
+            t.ok(sm.isSelected(1),
+                 "selecting feature 1 selects row 1");
+
+            // unselect feature 0
+            // test that the first row is selected
+            sm.selectControl.unselect(features[0]);
+            t.ok(!sm.isSelected(0),
+                 "unselecting feature 0 unselects row 0");
+
+            // unselect feature 1
+            // test that the second row is unselected
+            sm.selectControl.unselect(features[1]);
+            t.ok(!sm.isSelected(1),
+                 "unselecting feature 1 unselects row 1");
+            
+            /*
+             * Tear down
+             */
+            grid.destroy();
+        }
+        
+        
+        function test_bind_unbind(t) {
+            t.plan(9);
+
+            /*
+             * Set up
+             */
+
+            var map, layer, selectControl, features, store, sm, grid, e;
+
+            map = new OpenLayers.Map('map');
+
+            layer = new OpenLayers.Layer.Vector("vector");
+            map.addLayer(layer);
+
+            selectControl = new OpenLayers.Control.SelectFeature(layer);
+            map.addControl(selectControl);
+
+            features = [
+                new OpenLayers.Feature.Vector(null,
+                    {foo: "foo1", bar: "bar1"}
+                ),
+                new OpenLayers.Feature.Vector(null,
+                    {foo: "foo2", bar: "bar2"}
+                )
+            ];
+            
+            store = new GeoExt.data.FeatureStore({
+                layer: layer,
+                data: features
+            });
+
+            sm = new GeoExt.grid.FeatureSelectionModel({
+                layerFromStore: false
+            });
+
+            grid = new Ext.grid.GridPanel({
+                renderTo: "grid",
+                store: store,
+                columns: [{
+                    dataIndex: "foo"
+                }, {
+                    dataIndex: "bar"
+                }],
+                sm: sm,
+                deferRowRender: false
+            });
+ 
+            /*
+             * Test
+             */
+
+            // simulate a mousedown on the first row
+            // test that the first feature is not selected in the layer
+            e = {
+                button: 0,
+                shiftKey: false,
+                ctrlKey: false
+            };
+            grid.fireEvent("rowmousedown", grid, 0, e);
+            t.ok(OpenLayers.Util.indexOf(layer.selectedFeatures,
+                                         features[0]) < 0,
+                 "click on row 0 does not select feature 0");
+            sm.clearSelections();
+            
+            // select feature 0
+            // test that the first row is not selected
+            selectControl.select(features[0]);
+            t.ok(!sm.isSelected(0),
+                 "selecting feature 0 does not select row 0");
+            selectControl.unselect(features[0]);
+
+            // bind the select control to the selection model
+            sm.bind(selectControl);
+
+            // simulate a mousedown on the second row
+            // test that the second feature is selected in the layer
+            e = {
+                button: 0,
+                shiftKey: false,
+                ctrlKey: false
+            };
+            grid.fireEvent("rowmousedown", grid, 1, e);
+            t.ok(OpenLayers.Util.indexOf(layer.selectedFeatures,
+                                         features[1]) > -1,
+                 "click on row 1 selects feature 1");
+            sm.clearSelections();
+            
+            // select feature 1
+            // test that the second row is selected
+            selectControl.select(features[1]);
+            t.ok(sm.isSelected(1),
+                 "selecting feature 1 selects row 1");
+            selectControl.unselect(features[1]);
+            sm.clearSelections();
+            
+            // unbind row and feature selection
+            sm.unbind(); 
+            // (side effect: selectControl is deactivated)
+            
+            // simulate a mousedown on the first row
+            // test that the first feature is not selected in the layer
+            e = {
+                button: 0,
+                shiftKey: false,
+                ctrlKey: false
+            };
+            grid.fireEvent("rowmousedown", grid, 0, e);
+            t.ok(OpenLayers.Util.indexOf(layer.selectedFeatures,
+                                         features[0]) < 0,
+                 "click on row 0 does not select feature 0");
+            sm.clearSelections();
+            
+            // select feature 0
+            // test that the first row is not selected
+            selectControl.select(features[0]);
+            t.ok(!sm.isSelected(0),
+                 "selecting feature 0 does not select row 0");
+            selectControl.unselect(features[0]);
+            
+            // bind selection of features on a layer to rows
+            sm.bind(layer, {controlConfig: {hover: true}});
+            
+            // verify that controlConfig has been applied
+            t.eq(sm.selectControl.hover, true,
+                 "bind configures correctly the select feature control");
+
+            // simulate a mousedown on the second row
+            // test that the second feature is selected in the layer
+            e = {
+                button: 0,
+                shiftKey: false,
+                ctrlKey: false
+            };
+            grid.fireEvent("rowmousedown", grid, 1, e);
+            t.ok(OpenLayers.Util.indexOf(layer.selectedFeatures,
+                                         features[1]) > -1,
+                 "click on row 1 selects feature 1");
+            sm.clearSelections();
+            
+            // select feature 1
+            // test that the second row is selected
+            sm.selectControl.select(features[1]);
+            t.ok(sm.isSelected(1),
+                 "selecting feature 1 selects row 1");
+            sm.selectControl.unselect(features[1]);
+            sm.clearSelections();
+            
+            /*
+             * Tear down
+             */
+            grid.destroy();
+        }
+    </script>
+
+  <body>
+      <div id="map" style="width:100px;height:100px"></div>
+      <div id="grid"></div>
+  </body>
+</html>

Copied: sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/tree/BaseLayerContainer.html (from rev 1281, core/trunk/geoext/tests/lib/GeoExt/widgets/tree/BaseLayerContainer.html)
===================================================================
--- sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/tree/BaseLayerContainer.html	                        (rev 0)
+++ sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/tree/BaseLayerContainer.html	2009-07-23 09:53:02 UTC (rev 1282)
@@ -0,0 +1,75 @@
+<html>
+    <head>
+        <script src="../../../../../../openlayers/lib/OpenLayers.js"></script>
+        <script src="../../../../../../ext/adapter/ext/ext-base.js"></script>
+        <script src="../../../../../../ext/ext-all-debug.js"></script>
+        <script src="../../../../../lib/GeoExt.js"></script>
+    
+        <script>
+        
+        function test_render(t) {
+            
+            t.plan(2);
+            
+            var map = new OpenLayers.Map({
+                div: "map"
+            });
+            // add a base layer
+            var layer = new OpenLayers.Layer("foo", {isBaseLayer: true});
+            map.addLayer(layer);
+            // add an overlay
+            map.addLayer(new OpenLayers.Layer());
+            
+            var store = new GeoExt.data.LayerStore({
+                map: map
+            });
+            
+            var node = new GeoExt.tree.BaseLayerContainer({
+                layerStore: store
+            });
+            
+            var panel = new Ext.tree.TreePanel({
+                renderTo: document.body,
+                root: node
+            });
+            
+            t.eq(node.childNodes.length, 1, "only base layers get added to the container");
+            t.eq(node.firstChild.attributes.iconCls, "gx-tree-baselayer-icon", "iconClass for child set correctly");
+
+            node.destroy();
+            map.destroy();
+            
+        }
+        
+        function test_addLayerNode(t) {
+            
+            t.plan(2);
+            
+            // setup
+            var original = GeoExt.tree.LayerContainer.prototype.addLayerNode;
+            var container = new GeoExt.tree.BaseLayerContainer({});
+            var args;
+            GeoExt.tree.LayerContainer.prototype.addLayerNode = function() {
+                args = arguments;
+            };
+            var Rec = Ext.data.Record.create([{name: "layer"}]);
+            var record = new Rec({
+                layer: new OpenLayers.Layer(null, {isBaseLayer: true})
+            });
+            
+            // call addLayerNode with two args and confirm the super got both
+            container.addLayerNode(record, 4);
+            t.eq(args.length, 2, "method called with two arguments");
+            t.eq(args[1], 4, "method called with correct second argument");
+            
+            // clean up
+            GeoExt.tree.LayerContainer.prototype.addLayerNode = original;
+            
+        }
+        
+        </script>
+    </head>
+    <body>
+        <div id="map" style="width: 100px; height: 100px;"></div>
+    </body>
+</html>
\ No newline at end of file

Modified: sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/tree/LayerContainer.html
===================================================================
--- sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/tree/LayerContainer.html	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/tree/LayerContainer.html	2009-07-23 09:53:02 UTC (rev 1282)
@@ -28,7 +28,7 @@
         
         function test_render(t) {
             
-            t.plan(2);
+            t.plan(3);
             
             var map = new OpenLayers.Map({
                 div: "map",
@@ -52,11 +52,76 @@
             
             t.eq(node.childNodes && node.childNodes.length, 1, "container has one child");
             t.ok(node.firstChild.layer === layer, "child layer is correct");
+            t.eq(node.firstChild.attributes.iconCls, "gx-tree-layer-icon", "iconClass for child set correctly");
 
             node.destroy();
+            map.destroy();
             
         }
         
+        function test_order(t) {
+            
+            t.plan(16);
+            
+            var map = new OpenLayers.Map({
+                div: "map",
+                allOverlays: true
+            });
+            
+            var store = new GeoExt.data.LayerStore({
+                map: map
+            });
+            
+            var root = new GeoExt.tree.LayerContainer({
+                layerStore: store
+            });
+            
+            var panel = new Ext.tree.TreePanel({
+                renderTo: document.body,
+                root: root
+            });
+            
+            var a = new OpenLayers.Layer("a");
+            var b = new OpenLayers.Layer("b");
+            var c = new OpenLayers.Layer("c");
+            var d = new OpenLayers.Layer("d");
+            
+            var reader = new GeoExt.data.LayerReader();
+            
+            // add two records to empty root
+            store.add(reader.readRecords([a, b]).records);
+            t.eq(root.childNodes.length, 2, "[a, b] two records added");
+            t.eq(root.childNodes[0].layer.name, "b", "[a, b] last layer drawn at top of root");
+            t.eq(root.childNodes[1].layer.name, "a", "[a, b] first layer drawn at bottom of root");
+            
+            // add two records to root with two existing child nodes
+            store.add(reader.readRecords([c, d]).records);
+            t.eq(root.childNodes.length, 4, "[a, b, c, d] four records total");
+            t.eq(root.childNodes[0].layer.name, "d", "[a, b, c, d] last layer drawn at top of root");
+            t.eq(root.childNodes[1].layer.name, "c", "[a, b, c, d] third layer drawn at correct index");
+            t.eq(root.childNodes[2].layer.name, "b", "[a, b, c, d] second layer drawn at correct index");
+            t.eq(root.childNodes[3].layer.name, "a", "[a, b, c, d] first layer drawn at bottom of root");
+            
+            // remove the first two layers in draw order
+            store.remove(store.getAt(0));
+            store.remove(store.getAt(0));
+            t.eq(root.childNodes.length, 2, "[c, d] two records total");
+            t.eq(root.childNodes[0].layer.name, "d", "[c, d] last layer drawn at top of root");
+            t.eq(root.childNodes[1].layer.name, "c", "[c, d] first layer drawn at bottom of root");
+            
+            // insert two records in the middle
+            store.insert(1, reader.readRecords([a, b]).records);
+            t.eq(root.childNodes.length, 4, "[c, a, b, d] four records total");
+            t.eq(root.childNodes[0].layer.name, "d", "[c, a, b, d] last layer drawn at top of root");
+            t.eq(root.childNodes[1].layer.name, "b", "[c, a, b, d] third layer drawn at correct index");
+            t.eq(root.childNodes[2].layer.name, "a", "[c, a, b, d] second layer drawn at correct index");
+            t.eq(root.childNodes[3].layer.name, "c", "[c, a, b, d] first layer drawn at bottom of root");
+            
+            root.destroy();
+            map.destroy();
+            
+        }
+        
         </script>
     </head>
     <body>

Modified: sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/tree/LayerNode.html
===================================================================
--- sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/tree/LayerNode.html	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/tree/LayerNode.html	2009-07-23 09:53:02 UTC (rev 1282)
@@ -26,7 +26,7 @@
         
         function test_render(t) {
             
-            t.plan(5);
+            t.plan(8);
             
             var layer = new OpenLayers.Layer("foo");
             
@@ -38,6 +38,7 @@
             var node = new GeoExt.tree.LayerNode({
                 layer: "foo",
                 radioGroup: "group",
+                checkedGroup: "check",
                 childNodeType: {
                     add: function() {
                         t.ok(true, "add function of childNodeType called");
@@ -56,11 +57,15 @@
             
             mapPanel.on("render", function() {
                 t.ok(node.layer === layer, "layer found on detected map panel");
-                
+
+                t.ok(node.ui.checkbox, "node has a checkbox");
                 t.ok(node.ui.radio, "node has a radio button");
                 // simulate a click event for testing the radiochange event
                 node.ui.onClick({getTarget: function() {return true}});
                 
+                t.eq(node.ui.checkbox.type, "radio", "checkbox rendered as radio button when checkedGroup is configured");
+                t.eq(node.ui.checkbox.name, "check_checkbox", "option group name set correclty according to checkedGroup");
+                
                 node.ui.toggleCheck();
                 t.eq(layer.visibility, false, "unchecking node hides layer");
             });
@@ -68,6 +73,42 @@
             mapPanel.render("map");
             
         }
+
+        function test_changelayername(t) {
+            t.plan(2);
+
+            var layer = new OpenLayers.Layer("test");
+
+            var mapPanel = new GeoExt.MapPanel({
+                layers: [layer],
+                allOverlays: true
+            });
+
+            var node = new GeoExt.tree.LayerNode({
+                layer: "test",
+                layerStore: mapPanel.layers
+            });
+
+            var panel = new Ext.tree.TreePanel({
+                 root: node
+            });
+            panel.render(document.body);
+
+            layer.setName("My new name");
+            t.eq(node.text, "My new name", "Node is named 'My new name' after layer setName is called");
+            
+            node = new GeoExt.tree.LayerNode({
+                layer: "My new name",
+                layerStore: mapPanel.layers,
+                text: "My custom text"
+            });
+            
+            layer.setName("test");
+            t.eq(node.text, "My custom text", "Node text does not change with layer name if custom text was provided");
+
+            node.destroy();
+            mapPanel.destroy();
+        }
         
         </script>
     </head>
@@ -75,4 +116,4 @@
         <div id="map" style="width: 100px; height: 100px;"></div>
         <div id="tree" style="width: 100px; height: 100px;"></div>
     </body>
-</html>
\ No newline at end of file
+</html>

Modified: sandbox/elemoine/playground/geoext/tests/list-tests.html
===================================================================
--- sandbox/elemoine/playground/geoext/tests/list-tests.html	2009-07-23 06:51:27 UTC (rev 1281)
+++ sandbox/elemoine/playground/geoext/tests/list-tests.html	2009-07-23 09:53:02 UTC (rev 1282)
@@ -1,4 +1,5 @@
 <ul id="testlist">
+  <li>lib/GeoExt/adapter/override-ext-ajax.html</li>
   <li>lib/GeoExt/data/FeatureRecord.html</li>
   <li>lib/GeoExt/data/FeatureReader.html</li>
   <li>lib/GeoExt/data/FeatureStore.html</li>
@@ -8,14 +9,21 @@
   <li>lib/GeoExt/data/ScaleStore.html</li>
   <li>lib/GeoExt/data/ProtocolProxy.html</li>
   <li>lib/GeoExt/data/WMSCapabilitiesReader.html</li>
+  <li>lib/GeoExt/data/WMSDescribeLayerReader.html</li>
   <li>lib/GeoExt/widgets/Action.html</li>
+  <li>lib/GeoExt/widgets/LayerOpacitySlider.html</li>
   <li>lib/GeoExt/widgets/MapPanel.html</li>
   <li>lib/GeoExt/widgets/Popup.html</li>
   <li>lib/GeoExt/widgets/form.html</li>
   <li>lib/GeoExt/widgets/form/SearchAction.html</li>
   <li>lib/GeoExt/widgets/form/BasicForm.html</li>
   <li>lib/GeoExt/widgets/form/FormPanel.html</li>
+  <li>lib/GeoExt/widgets/tree/BaseLayerContainer.html</li>
+  <li>lib/GeoExt/widgets/tree/LayerContainer.html</li>
   <li>lib/GeoExt/widgets/tree/LayerNode.html</li>
-  <li>lib/GeoExt/widgets/tree/LayerContainer.html</li>
+  <li>lib/GeoExt/widgets/LegendImage.html</li>
   <li>lib/GeoExt/widgets/LegendPanel.html</li>
+  <li>lib/GeoExt/widgets/LegendWMS.html</li>
+  <li>lib/GeoExt/widgets/ZoomSlider.html</li>
+  <li>lib/GeoExt/widgets/grid/FeatureSelectionModel.html</li>
 </ul>



More information about the Commits mailing list