[Commits] r1271 - in sandbox/camptocamp/geobretagne: build examples lib lib/GeoExt/data lib/GeoExt/widgets lib/GeoExt/widgets/grid lib/GeoExt/widgets/tree tests tests/lib/GeoExt/data tests/lib/GeoExt/widgets tests/lib/GeoExt/widgets/tree

commits at geoext.org commits at geoext.org
Thu Jul 16 15:55:09 CEST 2009


Author: elemoine
Date: 2009-07-16 15:55:08 +0200 (Thu, 16 Jul 2009)
New Revision: 1271

Added:
   sandbox/camptocamp/geobretagne/lib/GeoExt/data/WMSDescribeLayerReader.js
   sandbox/camptocamp/geobretagne/lib/GeoExt/data/WMSDescribeLayerStore.js
   sandbox/camptocamp/geobretagne/tests/lib/GeoExt/data/WMSDescribeLayerReader.html
   sandbox/camptocamp/geobretagne/tests/lib/GeoExt/data/WMSDescribeLayerReader.js
   sandbox/camptocamp/geobretagne/tests/lib/GeoExt/widgets/LegendWMS.html
   sandbox/camptocamp/geobretagne/tests/lib/GeoExt/widgets/tree/BaseLayerContainer.html
Modified:
   sandbox/camptocamp/geobretagne/build/Makefile
   sandbox/camptocamp/geobretagne/build/readme.txt
   sandbox/camptocamp/geobretagne/examples/feature-grid.js
   sandbox/camptocamp/geobretagne/examples/wms-capabilities.html
   sandbox/camptocamp/geobretagne/lib/GeoExt.js
   sandbox/camptocamp/geobretagne/lib/GeoExt/data/LayerReader.js
   sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/LegendImage.js
   sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/LegendPanel.js
   sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/LegendWMS.js
   sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/Popup.js
   sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/ZoomSlider.js
   sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/grid/FeatureSelectionModel.js
   sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/tree/BaseLayerContainer.js
   sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/tree/LayerContainer.js
   sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/tree/LayerNode.js
   sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/tree/OverlayLayerContainer.js
   sandbox/camptocamp/geobretagne/tests/lib/GeoExt/data/WMSCapabilitiesReader.html
   sandbox/camptocamp/geobretagne/tests/lib/GeoExt/widgets/LegendPanel.html
   sandbox/camptocamp/geobretagne/tests/lib/GeoExt/widgets/Popup.html
   sandbox/camptocamp/geobretagne/tests/lib/GeoExt/widgets/tree/LayerContainer.html
   sandbox/camptocamp/geobretagne/tests/lib/GeoExt/widgets/tree/LayerNode.html
   sandbox/camptocamp/geobretagne/tests/list-tests.html
Log:
svn merge -r1153:HEAD http://svn.geoext.org/core/trunk/geoext .


Modified: sandbox/camptocamp/geobretagne/build/Makefile
===================================================================
--- sandbox/camptocamp/geobretagne/build/Makefile	2009-07-16 06:27:44 UTC (rev 1270)
+++ sandbox/camptocamp/geobretagne/build/Makefile	2009-07-16 13:55:08 UTC (rev 1271)
@@ -1,7 +1,8 @@
-# Makefile for GeoExplorer apps
+# Makefile for GeoExt
 
+VERSION = r$(shell echo '$$Revision$$' | tr -d "[:alpha:]$$ :")
 LIB_NAME = GeoExt
-ZIP_NAME = $(LIB_NAME).zip
+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/')
@@ -23,6 +24,7 @@
 	@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)
@@ -35,7 +37,7 @@
 
 examples:
 	mkdir -p $(LIB_NAME)/examples 
-	svn export --force ../examples $(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} ; \
@@ -46,8 +48,9 @@
 	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 
 	
-	svn export --force ../resources $(LIB_NAME)/resources
+	rsync -au --exclude=.svn `pwd`/../resources `pwd`/$(LIB_NAME)
 	
 	for file in `find $(CSS_DIR) -name "*.css"`; do \
 	    csstidy $${file} --template=highest $${file} ; \
@@ -65,4 +68,4 @@
 	-rm -f $(ZIP_NAME)
 	zip $(ZIP_NAME) -r $(LIB_NAME)
 
-dist: examples zip
\ No newline at end of file
+dist: examples zip


Property changes on: sandbox/camptocamp/geobretagne/build/Makefile
___________________________________________________________________
Name: svn:keywords
   + Revision

Modified: sandbox/camptocamp/geobretagne/build/readme.txt
===================================================================
--- sandbox/camptocamp/geobretagne/build/readme.txt	2009-07-16 06:27:44 UTC (rev 1270)
+++ sandbox/camptocamp/geobretagne/build/readme.txt	2009-07-16 13:55:08 UTC (rev 1271)
@@ -9,7 +9,7 @@
 ------------------
 
 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 svn. All this
+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.
@@ -52,4 +52,4 @@
     
 The Makefile has even more targets. Invoke make help to see them all.
 
-    $ make help
\ No newline at end of file
+    $ make help

Modified: sandbox/camptocamp/geobretagne/examples/feature-grid.js
===================================================================
--- sandbox/camptocamp/geobretagne/examples/feature-grid.js	2009-07-16 06:27:44 UTC (rev 1270)
+++ sandbox/camptocamp/geobretagne/examples/feature-grid.js	2009-07-16 13:55:08 UTC (rev 1271)
@@ -6,8 +6,6 @@
  * of the license.
  */
 
-Ext.BLANK_IMAGE_URL = "../../../../ext/resources/images/default/s.gif"
-
 var mapPanel, store, gridPanel, mainPanel;
 
 Ext.onReady(function() {

Modified: sandbox/camptocamp/geobretagne/examples/wms-capabilities.html
===================================================================
--- sandbox/camptocamp/geobretagne/examples/wms-capabilities.html	2009-07-16 06:27:44 UTC (rev 1270)
+++ sandbox/camptocamp/geobretagne/examples/wms-capabilities.html	2009-07-16 13:55:08 UTC (rev 1271)
@@ -4,7 +4,6 @@
 
         <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>
         <script type="text/javascript" src="../lib/GeoExt/adapter/override-ext-ajax.js"></script>
         <script src="http://openlayers.org/api/2.8/OpenLayers.js"></script>

Modified: sandbox/camptocamp/geobretagne/lib/GeoExt/data/LayerReader.js
===================================================================
--- sandbox/camptocamp/geobretagne/lib/GeoExt/data/LayerReader.js	2009-07-16 06:27:44 UTC (rev 1270)
+++ sandbox/camptocamp/geobretagne/lib/GeoExt/data/LayerReader.js	2009-07-16 13:55:08 UTC (rev 1271)
@@ -59,7 +59,7 @@
      *  :return: ``Object``  An object with ``records`` and ``totalRecords``
      *      properties.
      *  
-     *  From an array of {OpenLayers.Layer} objects create a data block
+     *  From an array of ``OpenLayers.Layer`` objects create a data block
      *  containing :class:`GeoExt.data.LayerRecord` objects.
      */
     readRecords : function(layers) {

Copied: sandbox/camptocamp/geobretagne/lib/GeoExt/data/WMSDescribeLayerReader.js (from rev 1270, core/trunk/geoext/lib/GeoExt/data/WMSDescribeLayerReader.js)
===================================================================
--- sandbox/camptocamp/geobretagne/lib/GeoExt/data/WMSDescribeLayerReader.js	                        (rev 0)
+++ sandbox/camptocamp/geobretagne/lib/GeoExt/data/WMSDescribeLayerReader.js	2009-07-16 13:55:08 UTC (rev 1271)
@@ -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/camptocamp/geobretagne/lib/GeoExt/data/WMSDescribeLayerStore.js (from rev 1270, core/trunk/geoext/lib/GeoExt/data/WMSDescribeLayerStore.js)
===================================================================
--- sandbox/camptocamp/geobretagne/lib/GeoExt/data/WMSDescribeLayerStore.js	                        (rev 0)
+++ sandbox/camptocamp/geobretagne/lib/GeoExt/data/WMSDescribeLayerStore.js	2009-07-16 13:55:08 UTC (rev 1271)
@@ -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/camptocamp/geobretagne/lib/GeoExt/widgets/LegendImage.js
===================================================================
--- sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/LegendImage.js	2009-07-16 06:27:44 UTC (rev 1270)
+++ sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/LegendImage.js	2009-07-16 13:55:08 UTC (rev 1271)
@@ -99,5 +99,5 @@
 
 });
 
-
+/** api: xtype = gx_legendimage */
 Ext.reg('gx_legendimage', GeoExt.LegendImage);

Modified: sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/LegendPanel.js
===================================================================
--- sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/LegendPanel.js	2009-07-16 06:27:44 UTC (rev 1270)
+++ sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/LegendPanel.js	2009-07-16 13:55:08 UTC (rev 1271)
@@ -56,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.
@@ -130,7 +136,7 @@
         var layer = record.get('layer');
         var legend = this.getComponent(layer.id);
         if ((this.showTitle && !record.get('hideTitle')) && 
-            (legend.items.get(0).text !== record.get('title'))) {
+            (legend && legend.items.get(0).text !== record.get('title'))) {
                 // we need to update the title
                 legend.items.get(0).setText(record.get('title'));
         }
@@ -212,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);
                 }
             }
@@ -286,4 +295,5 @@
     
 });
 
+/** api: xtype = gx_legendpanel */
 Ext.reg('gx_legendpanel', GeoExt.LegendPanel);

Modified: sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/LegendWMS.js
===================================================================
--- sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/LegendWMS.js	2009-07-16 06:27:44 UTC (rev 1270)
+++ sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/LegendWMS.js	2009-07-16 13:55:08 UTC (rev 1271)
@@ -26,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``
@@ -48,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();
     },
 
@@ -77,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/camptocamp/geobretagne/lib/GeoExt/widgets/Popup.js
===================================================================
--- sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/Popup.js	2009-07-16 06:27:44 UTC (rev 1270)
+++ sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/Popup.js	2009-07-16 13:55:08 UTC (rev 1271)
@@ -170,7 +170,7 @@
         GeoExt.Popup.superclass.show.apply(this, arguments);
         if(this.anchored) {
             this.position();
-            if(this.panIn && !this._mapmove) {
+            if(this.panIn && !this._mapMove) {
                 this.panIntoView();
             }
         }

Modified: sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/ZoomSlider.js
===================================================================
--- sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/ZoomSlider.js	2009-07-16 06:27:44 UTC (rev 1270)
+++ sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/ZoomSlider.js	2009-07-16 13:55:08 UTC (rev 1271)
@@ -156,7 +156,7 @@
         e.stopEvent();
     },
     
-    /** private: method[removeFromMap]
+    /** private: method[removeFromMapPanel]
      *  :param panel: :class:`GeoExt.MapPanel`
      *  
      *  Called by a MapPanel if this component is one of the items in the panel.

Modified: sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/grid/FeatureSelectionModel.js
===================================================================
--- sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/grid/FeatureSelectionModel.js	2009-07-16 06:27:44 UTC (rev 1270)
+++ sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/grid/FeatureSelectionModel.js	2009-07-16 13:55:08 UTC (rev 1271)
@@ -46,13 +46,13 @@
 
 GeoExt.grid.FeatureSelectionModelMixin = {
 
-    /** api: autoActivateControl
+    /** api: config[autoActivateControl]
      *  ``Boolean`` If true the select feature control is activated and
      *  deactivated when binding and unbinding. Defaults to true.
      */
     autoActivateControl: true,
 
-    /** api: layerFromStore
+    /** 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
@@ -66,15 +66,17 @@
      *  ``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.
+     *  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,
-
+    /** 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
@@ -96,7 +98,8 @@
         config = config || {};
         if(config.selectControl instanceof OpenLayers.Control.SelectFeature) { 
             if(!config.singleSelect) {
-                config.singleSelect = !config.selectControl.multiple;
+                var ctrl = config.selectControl;
+                config.singleSelect = !(ctrl.multiple || !!ctrl.multipleKey);
             }
         } else if(config.layer instanceof OpenLayers.Layer.Vector) {
             this.selectControl = this.createSelectControl(
@@ -141,7 +144,8 @@
                            config.singleSelect : this.singleSelect;
         config = OpenLayers.Util.extend({
             toggle: true,
-            multiple: !singleSelect
+            multipleKey: singleSelect ? null :
+                (Ext.isMac ? "metaKey" : "ctrlKey")
         }, config);
         var selectControl = new OpenLayers.Control.SelectFeature(
             layer, config
@@ -162,7 +166,7 @@
      *  :return: ``OpenLayers.Control.SelectFeature`` The select feature
      *  control this selection model uses.
      *
-     *  Bind the selection model to a layer.
+     *  Bind the selection model to a layer or a SelectFeature control.
      */
     bind: function(obj, options) {
         if(!this.bound) {
@@ -195,7 +199,7 @@
      *  :return: ``OpenLayers.Control.SelectFeature`` The select feature
      *      control this selection model used.
      *
-     *  Unbind the selection model from the layer.
+     *  Unbind the selection model from the layer or SelectFeature control.
      */
     unbind: function() {
         var selectControl = this.selectControl;

Modified: sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/tree/BaseLayerContainer.js
===================================================================
--- sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/tree/BaseLayerContainer.js	2009-07-16 06:27:44 UTC (rev 1270)
+++ sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/tree/BaseLayerContainer.js	2009-07-16 13:55:08 UTC (rev 1271)
@@ -25,7 +25,10 @@
  * 
  *     A layer container that will collect all base layers of an OpenLayers
  *     map. Only layers that have displayInLayerSwitcher set to true will be
- *     included.
+ *     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 ``TreePanel`` config, set nodeType to
  *     "gx_baselayercontainer".
@@ -37,20 +40,26 @@
      */
     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);
     },
 
     /** private: method[addLayerNode]
-     *  :param layerRecord: ``Ext.data.Record`` the layer record to add a node
-     *      for
-     * 
-     *  Adds a child node representing a base layer of the map.
+     *  :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
+            );
         }
     },
     
@@ -63,8 +72,9 @@
     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/camptocamp/geobretagne/lib/GeoExt/widgets/tree/LayerContainer.js
===================================================================
--- sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/tree/LayerContainer.js	2009-07-16 06:27:44 UTC (rev 1270)
+++ sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/tree/LayerContainer.js	2009-07-16 13:55:08 UTC (rev 1271)
@@ -22,8 +22,8 @@
  * 
  *      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.
+ *      will be included. The childrens' iconCls defaults to
+ *      "gx-tree-layer-icon".
  * 
  *      To use this node type in ``TreePanel`` config, set nodeType to
  *      "gx_layercontainer".
@@ -152,8 +152,11 @@
         index = index || 0;
         var layer = layerRecord.get("layer");
         if (layer.displayInLayerSwitcher === true) {
-            var node = new GeoExt.tree.LayerNode(Ext.applyIf({
-                iconCls: layer.isBaseLayer ? '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));

Modified: sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/tree/LayerNode.js
===================================================================
--- sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/tree/LayerNode.js	2009-07-16 06:27:44 UTC (rev 1270)
+++ sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/tree/LayerNode.js	2009-07-16 13:55:08 UTC (rev 1271)
@@ -30,21 +30,36 @@
      *  :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;
+        }
     },
     
     /** 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);
         }
@@ -84,19 +99,25 @@
  *      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 ``TreePanel`` config, set ``nodeType`` to
  *      "gx_layer".
@@ -150,9 +171,6 @@
         
         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(
@@ -205,10 +223,7 @@
                 }
                 
                 ui.show();
-                ui.toggleCheck(layer.getVisibility());
                 this.addVisibilityEventHandlers();
-                // set initial checked status
-                this.attributes.checked = layer.getVisibility();
             } else {
                 ui.hide();
             }
@@ -316,8 +331,9 @@
      */
     onStoreUpdate: function(store, record, operation) {
     	var layer = record.get("layer");
-        if(this.layer == layer && this.text !== layer.name) {
-            this.setText(layer.name);
+        if(this.layer == layer && record.isModified("title") &&
+                                    record.modified["title"] == this.text) {
+            this.setText(record.get("title"));
         }
     },
 

Modified: sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/tree/OverlayLayerContainer.js
===================================================================
--- sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/tree/OverlayLayerContainer.js	2009-07-16 06:27:44 UTC (rev 1270)
+++ sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/tree/OverlayLayerContainer.js	2009-07-16 13:55:08 UTC (rev 1271)
@@ -42,16 +42,18 @@
     },
 
     /** private: method[addLayerNode]
-     *  :param layerRecord:  ``Ext.data.Record`` the layer record to add a node
-     *      for
+     *  :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
+            );
         }
     },
     
@@ -64,8 +66,9 @@
     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/camptocamp/geobretagne/lib/GeoExt.js
===================================================================
--- sandbox/camptocamp/geobretagne/lib/GeoExt.js	2009-07-16 06:27:44 UTC (rev 1270)
+++ sandbox/camptocamp/geobretagne/lib/GeoExt.js	2009-07-16 13:55:08 UTC (rev 1271)
@@ -73,6 +73,8 @@
             "GeoExt/data/ScaleStore.js",
             "GeoExt/data/WMSCapabilitiesReader.js",
             "GeoExt/data/WMSCapabilitiesStore.js",
+            "GeoExt/data/WMSDescribeLayerReader.js",
+            "GeoExt/data/WMSDescribeLayerStore.js",
             "GeoExt/data/CSWRecordsReader.js",
             "GeoExt/widgets/Action.js",
             "GeoExt/data/ProtocolProxy.js",
@@ -93,8 +95,8 @@
             "GeoExt/widgets/LegendImage.js",
             "GeoExt/widgets/LegendWMS.js",
             "GeoExt/widgets/LegendPanel.js",
-            "GeoExt/widgets/grid/FeatureSelectionModel.js",
-            "GeoExt/widgets/ZoomSlider.js"
+            "GeoExt/widgets/ZoomSlider.js",
+            "GeoExt/widgets/grid/FeatureSelectionModel.js"
         );
 
         var agent = navigator.userAgent;

Modified: sandbox/camptocamp/geobretagne/tests/lib/GeoExt/data/WMSCapabilitiesReader.html
===================================================================
--- sandbox/camptocamp/geobretagne/tests/lib/GeoExt/data/WMSCapabilitiesReader.html	2009-07-16 06:27:44 UTC (rev 1270)
+++ sandbox/camptocamp/geobretagne/tests/lib/GeoExt/data/WMSCapabilitiesReader.html	2009-07-16 13:55:08 UTC (rev 1271)
@@ -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({},[

Copied: sandbox/camptocamp/geobretagne/tests/lib/GeoExt/data/WMSDescribeLayerReader.html (from rev 1270, core/trunk/geoext/tests/lib/GeoExt/data/WMSDescribeLayerReader.html)
===================================================================
--- sandbox/camptocamp/geobretagne/tests/lib/GeoExt/data/WMSDescribeLayerReader.html	                        (rev 0)
+++ sandbox/camptocamp/geobretagne/tests/lib/GeoExt/data/WMSDescribeLayerReader.html	2009-07-16 13:55:08 UTC (rev 1271)
@@ -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/camptocamp/geobretagne/tests/lib/GeoExt/data/WMSDescribeLayerReader.js (from rev 1270, core/trunk/geoext/tests/lib/GeoExt/data/WMSDescribeLayerReader.js)
===================================================================
--- sandbox/camptocamp/geobretagne/tests/lib/GeoExt/data/WMSDescribeLayerReader.js	                        (rev 0)
+++ sandbox/camptocamp/geobretagne/tests/lib/GeoExt/data/WMSDescribeLayerReader.js	2009-07-16 13:55:08 UTC (rev 1271)
@@ -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/camptocamp/geobretagne/tests/lib/GeoExt/widgets/LegendPanel.html
===================================================================
--- sandbox/camptocamp/geobretagne/tests/lib/GeoExt/widgets/LegendPanel.html	2009-07-16 06:27:44 UTC (rev 1270)
+++ sandbox/camptocamp/geobretagne/tests/lib/GeoExt/widgets/LegendPanel.html	2009-07-16 13:55:08 UTC (rev 1271)
@@ -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.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.get(1).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");
-
             lp.destroy();
             mapPanel.destroy();
+            GeoExt.LegendWMS = LegendWMS;
         }
 
         function test_addremove(t) {

Copied: sandbox/camptocamp/geobretagne/tests/lib/GeoExt/widgets/LegendWMS.html (from rev 1270, core/trunk/geoext/tests/lib/GeoExt/widgets/LegendWMS.html)
===================================================================
--- sandbox/camptocamp/geobretagne/tests/lib/GeoExt/widgets/LegendWMS.html	                        (rev 0)
+++ sandbox/camptocamp/geobretagne/tests/lib/GeoExt/widgets/LegendWMS.html	2009-07-16 13:55:08 UTC (rev 1271)
@@ -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/camptocamp/geobretagne/tests/lib/GeoExt/widgets/Popup.html
===================================================================
--- sandbox/camptocamp/geobretagne/tests/lib/GeoExt/widgets/Popup.html	2009-07-16 06:27:44 UTC (rev 1270)
+++ sandbox/camptocamp/geobretagne/tests/lib/GeoExt/widgets/Popup.html	2009-07-16 13:55:08 UTC (rev 1271)
@@ -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);
 
@@ -70,37 +70,54 @@
             pop.show();
 
             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);
 
+            // 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);
         }
 
@@ -113,7 +130,7 @@
             var pop = popup(context.feature, context.mapPanel);
 
             pop.show();
-        
+
             pop.collapse();
 
             var origPos = pop.getPosition();

Copied: sandbox/camptocamp/geobretagne/tests/lib/GeoExt/widgets/tree/BaseLayerContainer.html (from rev 1270, core/trunk/geoext/tests/lib/GeoExt/widgets/tree/BaseLayerContainer.html)
===================================================================
--- sandbox/camptocamp/geobretagne/tests/lib/GeoExt/widgets/tree/BaseLayerContainer.html	                        (rev 0)
+++ sandbox/camptocamp/geobretagne/tests/lib/GeoExt/widgets/tree/BaseLayerContainer.html	2009-07-16 13:55:08 UTC (rev 1271)
@@ -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/camptocamp/geobretagne/tests/lib/GeoExt/widgets/tree/LayerContainer.html
===================================================================
--- sandbox/camptocamp/geobretagne/tests/lib/GeoExt/widgets/tree/LayerContainer.html	2009-07-16 06:27:44 UTC (rev 1270)
+++ sandbox/camptocamp/geobretagne/tests/lib/GeoExt/widgets/tree/LayerContainer.html	2009-07-16 13:55:08 UTC (rev 1271)
@@ -28,7 +28,7 @@
         
         function test_render(t) {
             
-            t.plan(2);
+            t.plan(3);
             
             var map = new OpenLayers.Map({
                 div: "map",
@@ -52,6 +52,7 @@
             
             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();

Modified: sandbox/camptocamp/geobretagne/tests/lib/GeoExt/widgets/tree/LayerNode.html
===================================================================
--- sandbox/camptocamp/geobretagne/tests/lib/GeoExt/widgets/tree/LayerNode.html	2009-07-16 06:27:44 UTC (rev 1270)
+++ sandbox/camptocamp/geobretagne/tests/lib/GeoExt/widgets/tree/LayerNode.html	2009-07-16 13:55:08 UTC (rev 1271)
@@ -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");
             });
@@ -70,7 +75,7 @@
         }
 
         function test_changelayername(t) {
-            t.plan(1);
+            t.plan(2);
 
             var layer = new OpenLayers.Layer("test");
 
@@ -91,6 +96,15 @@
 
             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();

Modified: sandbox/camptocamp/geobretagne/tests/list-tests.html
===================================================================
--- sandbox/camptocamp/geobretagne/tests/list-tests.html	2009-07-16 06:27:44 UTC (rev 1270)
+++ sandbox/camptocamp/geobretagne/tests/list-tests.html	2009-07-16 13:55:08 UTC (rev 1271)
@@ -9,6 +9,7 @@
   <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/data/CSWRecordsReader.html</li>
   <li>lib/GeoExt/widgets/Action.html</li>
   <li>lib/GeoExt/widgets/LayerOpacitySlider.html</li>
@@ -18,10 +19,12 @@
   <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>
-  <li>lib/GeoExt/widgets/ZoomSlider.html</li>
 </ul>



More information about the Commits mailing list