[Commits] r1293 - in sandbox/elemoine/playground/geoext: examples lib lib/GeoExt/data lib/GeoExt/widgets lib/GeoExt/widgets/tree tests tests/lib/GeoExt/widgets tests/lib/GeoExt/widgets/tree

commits at geoext.org commits at geoext.org
Wed Jul 29 10:52:37 CEST 2009


Author: elemoine
Date: 2009-07-29 10:52:37 +0200 (Wed, 29 Jul 2009)
New Revision: 1293

Added:
   sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tree/LayerLoader.js
   sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/tree/LayerLoader.html
Modified:
   sandbox/elemoine/playground/geoext/examples/toolbar.js
   sandbox/elemoine/playground/geoext/examples/tree.js
   sandbox/elemoine/playground/geoext/lib/GeoExt.js
   sandbox/elemoine/playground/geoext/lib/GeoExt/data/ProtocolProxy.js
   sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/Action.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/tree/BaseLayerContainer.js
   sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tree/LayerContainer.js
   sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tree/OverlayLayerContainer.js
   sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/Action.html
   sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/Popup.html
   sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/tree/BaseLayerContainer.html
   sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/tree/LayerContainer.html
   sandbox/elemoine/playground/geoext/tests/list-tests.html
Log:
svn merge -r876:HEAD http://svn.geoext.org/core/trunk/geoext .


Modified: sandbox/elemoine/playground/geoext/examples/toolbar.js
===================================================================
--- sandbox/elemoine/playground/geoext/examples/toolbar.js	2009-07-29 07:38:12 UTC (rev 1292)
+++ sandbox/elemoine/playground/geoext/examples/toolbar.js	2009-07-29 08:52:37 UTC (rev 1293)
@@ -7,6 +7,8 @@
  */
 
 Ext.onReady(function() {
+    Ext.QuickTips.init();
+
     var map = new OpenLayers.Map();
     var wms = new OpenLayers.Layer.WMS(
         "Global Imagery",
@@ -22,7 +24,8 @@
     action = new GeoExt.Action({
         control: new OpenLayers.Control.ZoomToMaxExtent(),
         map: map,
-        text: "max extent"
+        text: "max extent",
+        tooltip: "zoom to max extent"
     });
     actions["max_extent"] = action;
     toolbarItems.push(action);
@@ -38,6 +41,7 @@
         toggleGroup: "draw",
         allowDepress: false,
         pressed: true,
+        tooltip: "navigate",
         // check item options
         group: "draw",
         checked: true
@@ -54,6 +58,7 @@
         // button options
         toggleGroup: "draw",
         allowDepress: false,
+        tooltip: "draw polygon",
         // check item options
         group: "draw"
     });
@@ -69,6 +74,7 @@
         // button options
         toggleGroup: "draw",
         allowDepress: false,
+        tooltip: "draw line",
         // check item options
         group: "draw"
     });
@@ -85,7 +91,8 @@
         }),
         map: map,
         // button options
-        enableToggle: true
+        enableToggle: true,
+        tooltip: "select feature"
     });
     actions["select"] = action;
     toolbarItems.push(action);
@@ -98,7 +105,8 @@
     action = new GeoExt.Action({
         text: "previous",
         control: ctrl.previous,
-        disabled: true
+        disabled: true,
+        tooltip: "previous in history"
     });
     actions["previous"] = action;
     toolbarItems.push(action);
@@ -106,7 +114,8 @@
     action = new GeoExt.Action({
         text: "next",
         control: ctrl.next,
-        disabled: true
+        disabled: true,
+        tooltip: "next in history"
     });
     actions["next"] = action;
     toolbarItems.push(action);

Modified: sandbox/elemoine/playground/geoext/examples/tree.js
===================================================================
--- sandbox/elemoine/playground/geoext/examples/tree.js	2009-07-29 07:38:12 UTC (rev 1292)
+++ sandbox/elemoine/playground/geoext/examples/tree.js	2009-07-29 08:52:37 UTC (rev 1293)
@@ -16,8 +16,8 @@
         nodeType: "gx_overlaylayercontainer",
         // render the nodes inside this container with a radio button,
         // and assign them the group "foo"
-        defaults: {
-            radioGroup: "foo"
+        loader: {
+            baseAttrs: {radioGroup: "foo"}
         }
     }, {
         nodeType: "gx_layer",
@@ -136,7 +136,7 @@
         collapseMode: "mini",
         autoScroll: true,
         loader: new Ext.tree.TreeLoader({
-            clearOnLoad: true
+            applyLoader: false
         }),
         root: {
             nodeType: "async",

Modified: sandbox/elemoine/playground/geoext/lib/GeoExt/data/ProtocolProxy.js
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt/data/ProtocolProxy.js	2009-07-29 07:38:12 UTC (rev 1292)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/data/ProtocolProxy.js	2009-07-29 08:52:37 UTC (rev 1293)
@@ -14,8 +14,8 @@
 Ext.namespace('GeoExt', 'GeoExt.data');
 
 GeoExt.data.ProtocolProxy = function(config) {
-    GeoExt.data.ProtocolProxy.superclass.constructor.call(this);
     Ext.apply(this, config);
+    GeoExt.data.ProtocolProxy.superclass.constructor.apply(this, arguments);
 };
 
 /** api: constructor

Modified: sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/Action.js
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/Action.js	2009-07-29 07:38:12 UTC (rev 1292)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/Action.js	2009-07-29 08:52:37 UTC (rev 1293)
@@ -100,6 +100,9 @@
                 config.map.addControl(ctrl);
                 delete config.map;
             }
+            if((config.pressed || config.checked) && ctrl.map) {
+                ctrl.activate();
+            }
             ctrl.events.on({
                 activate: this.onCtrlActivate,
                 deactivate: this.onCtrlDeactivate,

Modified: sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/MapPanel.js
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/MapPanel.js	2009-07-29 07:38:12 UTC (rev 1292)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/MapPanel.js	2009-07-29 08:52:37 UTC (rev 1293)
@@ -140,16 +140,7 @@
      */
     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

Modified: sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/Popup.js
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/Popup.js	2009-07-29 07:38:12 UTC (rev 1292)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/Popup.js	2009-07-29 08:52:37 UTC (rev 1293)
@@ -145,7 +145,7 @@
         this.ancCls = this.popupCls + "-anc";
 
         //create anchor dom element.
-        this.createElement("anc", this.el);
+        this.createElement("anc", this.el.dom);
     },
 
     /** private: method[initTools]
@@ -184,7 +184,7 @@
      */
     setSize: function(w, h) {
         if(this.anc) {
-            var ancSize = this.getAnchorElement().getSize();
+            var ancSize = this.anc.getSize();
             if(typeof w == 'object') {
                 h = w.height - ancSize.height;
                 w = w.width;
@@ -214,12 +214,8 @@
     
             //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 anc = this.anc;
+            var dx = anc.getLeft(true) + anc.getWidth() / 2;
             var dy = this.el.getHeight();
     
             //Assuming for now that the map viewport takes up
@@ -228,15 +224,6 @@
         }
     },
 
-    /** private: method[getAnchorElement]
-     *  :returns: ``Ext.Element``  The anchor element of the popup.
-     */
-    getAnchorElement: function() {
-        var anchorSelector = "div." + this.ancCls;
-        var anc = Ext.get(this.el.child(anchorSelector));
-        return anc;
-    },
-
     /** private: method[unanchorPopup]
      *  Unanchors a popup from its feature.  This removes the popup from its
      *  MapPanel and adds it to the page body.
@@ -250,7 +237,7 @@
         this.dd = new Ext.Window.DD(this);
 
         //remove anchor
-        this.getAnchorElement().remove();
+        this.anc.remove();
         this.anc = null;
 
         //hide unpin tool

Modified: sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tree/BaseLayerContainer.js
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tree/BaseLayerContainer.js	2009-07-29 07:38:12 UTC (rev 1292)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tree/BaseLayerContainer.js	2009-07-29 08:52:37 UTC (rev 1293)
@@ -39,43 +39,24 @@
      *  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);
-    },
+        config = Ext.applyIf(config || {}, {
+            text: "Base Layer",
+            loader: {}
+        });
+        config.loader = Ext.applyIf(config.loader, {
+            baseAttrs: Ext.applyIf(config.loader.baseAttrs || {}, {
+                iconCls: 'gx-tree-baselayer-icon',
+                checkedGroup: 'baselayer'
+            }),
+            filter: function(record) {
+                var layer = record.get("layer");
+                return layer.displayInLayerSwitcher === true &&
+                    layer.isBaseLayer === true;
+            }
+        });
 
-    /** 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, index) {
-        var layer = layerRecord.get("layer");
-        if (layer.isBaseLayer == true) {
-            GeoExt.tree.BaseLayerContainer.superclass.addLayerNode.apply(
-                this, arguments
-            );
-        }
-    },
-    
-    /** 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.apply(
-                this, arguments
-            );
-    	}
+        GeoExt.tree.BaseLayerContainer.superclass.constructor.call(this,
+            config);
     }
 });
 

Modified: sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tree/LayerContainer.js
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tree/LayerContainer.js	2009-07-29 07:38:12 UTC (rev 1292)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tree/LayerContainer.js	2009-07-29 08:52:37 UTC (rev 1293)
@@ -7,14 +7,14 @@
  */
 
 /**
- * @include GeoExt/widgets/tree/LayerNode.js
+ * @include GeoExt/widgets/tree/LayerLoader.js
  */
 Ext.namespace("GeoExt.tree");
 
 /** api: (define)
  *  module = GeoExt.tree
  *  class = LayerContainer
- *  base_link = `Ext.tree.TreeNode <http://extjs.com/deploy/dev/docs/?class=Ext.tree.TreeNode>`_
+ *  base_link = `Ext.tree.AsyncTreeNode <http://extjs.com/deploy/dev/docs/?class=Ext.tree.AsyncTreeNode>`_
  */
 
 /** api: constructor
@@ -24,208 +24,76 @@
  *      OpenLayers map. Only layers that have displayInLayerSwitcher set to true
  *      will be included. The childrens' iconCls defaults to
  *      "gx-tree-layer-icon".
+ *      
+ *      Note: if this conatiner is loaded by an ``Ext.tree.TreeLoader``, the
+ *      ``applyLoader`` config option of that loader needs to be set to
+ *      "false". Also note that the list of available uiProviders will be
+ *      taken from the ownerTree if this container's loader is configured
+ *      without one.
  * 
  *      To use this node type in ``TreePanel`` config, set nodeType to
  *      "gx_layercontainer".
  */
-GeoExt.tree.LayerContainer = Ext.extend(Ext.tree.TreeNode, {
+GeoExt.tree.LayerContainer = Ext.extend(Ext.tree.AsyncTreeNode, {
     
-    /** api: config[layerStore]
-     *  :class:`GeoExt.data.LayerStore`
-     *  The layer store containing layers to be displayed in the container.
+    /** api: config[loader]
+     *  :class:`GeoExt.tree.LayerLoader` or ``Object`` The loader to use with
+     *  this container. If an ``Object`` is provided, a
+     *  :class:`GeoExt.tree.LayerLoader`, configured with the the properties
+     *  from the provided object, will be created. 
      */
-    layerStore: null,
     
-    /** api: config[defaults]
-     *  ``Object``
-     *  A configuration object passed to all nodes that this container creates.
+    /** api: config[layerStore]
+     *  :class:`GeoExt.data.LayerStore` The layer store containing layers to be
+     *  displayed in the container. If loader is not provided or provided as
+     *  ``Object``, this property will be set as the store option of the
+     *  loader. Otherwise it will be ignored.
      */
-    defaults: null,
-
+    
     /** private: method[constructor]
      *  Private constructor override.
      */
     constructor: function(config) {
-        this.layerStore = config.layerStore;
-        this.defaults = config.defaults;
-        GeoExt.tree.LayerContainer.superclass.constructor.apply(this, arguments);
+        config = Ext.applyIf(config || {}, {
+            text: "Layers"
+        });
+        this.loader = config.loader instanceof GeoExt.tree.LayerLoader ?
+            config.loader :
+            new GeoExt.tree.LayerLoader(Ext.applyIf(config.loader || {}, {
+                store: config.layerStore
+            }));
+        
+        GeoExt.tree.LayerContainer.superclass.constructor.call(this, config);
     },
-
-    /** private: method[render]
-     *  :param bulkRender: ``Boolean``
-     */
-    render: function(bulkRender) {
-        if (!this.rendered) {
-            if(!this.layerStore) {
-                this.layerStore = GeoExt.MapPanel.guess().layers;
-            }
-            this.layerStore.each(function(record) {
-                this.addLayerNode(record);
-            }, this);
-            this.layerStore.on({
-                "add": this.onStoreAdd,
-                "remove": this.onStoreRemove,
-                scope: this
-            });
-        }
-        GeoExt.tree.LayerContainer.superclass.render.call(this, bulkRender);
-    },
     
-    /** 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+records.length-1);
-            for(var i=0; i<records.length; ++i) {
-                this.addLayerNode(records[i], nodeIndex);
-            }
-        }
-    },
-    
-    /** 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) {
-            this.removeLayerNode(record);
-        }
-    },
-
     /** private: method[recordIndexToNodeIndex]
      *  :param index: ``Number`` The record index in the layer store.
      *  :return: ``Number`` The appropriate child node index for the record.
      */
     recordIndexToNodeIndex: function(index) {
-        var store = this.layerStore;
+        var store = this.loader.store;
         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) {
+            if(this.loader.filter(store.getAt(i)) === true) {
                 ++nodeIndex;
                 if(index === i || nodeIndex > nodeCount-1) {
                     break;
                 }
             }
-        };
+        }
         return nodeIndex;
     },
     
-    /** 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;
-        var count = store.getCount();
-        var nodeIndex = -1;
-        for(var i=count-1; i>=0; --i) {
-            if(store.getAt(i).get("layer").displayInLayerSwitcher) {
-                ++nodeIndex;
-                if(index === nodeIndex) {
-                    break;
-                }
-            }
-        }
-        return i;
-    },
-    
-    /** 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 = (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));
-            var sibling = this.item(index);
-            if(sibling) {
-                this.insertBefore(node, sibling);
-            } else {
-                this.appendChild(node);
-            }
-            node.on("move", this.onChildMove, this);
-        }
-    },
-    
-    /** private: method[removeLayerNode]
-     *  :param layerRecord: ``Ext.data.Record`` The layer record containing the
-     *      layer to be removed.
-     * 
-     *  Removes a child node representing a layer of the map
-     */
-    removeLayerNode: function(layerRecord) {
-        var layer = layerRecord.get("layer");
-        if (layer.displayInLayerSwitcher == true) {
-            var node = this.findChildBy(function(node) {
-                return node.layer == layer;
-            });
-            if(node) {
-                node.un("move", this.onChildMove, this);
-                node.remove();
-            }
-    	}
-    },
-    
-    /** 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) {
-            var newRecordIndex = this.nodeIndexToRecordIndex(index);
-            var oldRecordIndex = this.layerStore.findBy(function(record) {
-                return record.get("layer") === node.layer;
-            });
-            // remove the record and re-insert it at the correct index
-            var record = this.layerStore.getAt(oldRecordIndex);
-            this._reordering = true;
-            this.layerStore.remove(record);
-            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);
-        }
+        delete this.layerStore;
         GeoExt.tree.LayerContainer.superclass.destroy.apply(this, arguments);
     }
 });
-
+    
 /**
  * NodeType: gx_layercontainer
  */

Copied: sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tree/LayerLoader.js (from rev 1292, core/trunk/geoext/lib/GeoExt/widgets/tree/LayerLoader.js)
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tree/LayerLoader.js	                        (rev 0)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tree/LayerLoader.js	2009-07-29 08:52:37 UTC (rev 1293)
@@ -0,0 +1,317 @@
+/**
+ * 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/tree/LayerNode.js
+ */
+Ext.namespace("GeoExt.tree");
+
+/** api: (define)
+ *  module = GeoExt.tree
+ *  class = LayerLoader
+ *  base_link = `Ext.util.Observable <http://extjs.com/deploy/dev/docs/?class=Ext.util.Observable>`_
+ */
+
+/** api: constructor
+ *  .. class:: LayerLoader
+ * 
+ *      A loader that will load all layers of a :class:`GeoExt.data.LayerStore`
+ *      By default, only layers that have displayInLayerSwitcher set to true
+ *      will be included. The childrens' iconCls defaults to
+ *      "gx-tree-layer-icon".
+ */
+GeoExt.tree.LayerLoader = function(config) {
+    Ext.apply(this, config);
+    this.addEvents(
+    
+        /** api: events[beforeload]
+         *  Triggered before loading children. Return false to avoid
+         *  loading children.
+         *  
+         *  Listener arguments:
+         *  * loader - :class:`GeoExt.tree.LayerLoader` this loader
+         *  * node - ``Ex.tree.TreeNode`` the node that this loader is
+         *      configured with
+         */
+        "beforeload",
+        
+        /** api: events[load]
+         *  Triggered after children wer loaded.
+         *  
+         *  Listener arguments:
+         *  * loader - :class:`GeoExt.tree.LayerLoader` this loader
+         *  * node - ``Ex.tree.TreeNode`` the node that this loader is
+         *      configured with
+         */
+        "load"
+    );
+
+    GeoExt.tree.LayerLoader.superclass.constructor.call(this);
+};
+
+Ext.extend(GeoExt.tree.LayerLoader, Ext.util.Observable, {
+
+    /** api: config[store]
+     *  :class:`GeoExt.data.LayerStore`
+     *  The layer store containing layers to be added by this loader.
+     */
+    store: null,
+    
+    /** api: config[filter]
+     *  ``Function``
+     *  A function, called in the scope of this loader, with a layer record
+     *  as argument. Is expected to return true for layers to be loaded, false
+     *  otherwise. By default, the filter checks for displayInLayerSwitcher:
+     *  
+     *  .. code-block:: javascript
+     *  
+     *      filter: function(record) {
+     *          return record.get("layer").displayInLayerSwitcher == true
+     *      }
+     */
+    filter: function(record) {
+        return record.get("layer").displayInLayerSwitcher == true;
+    },
+    
+    /** api: config[uiProviders]
+     *  ``Object``
+     *  An optional object containing properties which specify custom
+     *  GeoExt.tree.LayerNodeUI implementations. If the optional uiProvider
+     *  attribute for child nodes is a string rather than a reference to a
+     *  TreeNodeUI implementation, then that string value is used as a
+     *  property name in the uiProviders object. If not provided, the
+     *  uiProviders object will be taken from the ownerTree.
+     */
+    uiProviders: null,
+    
+    /** private: method[load]
+     *  :param node: ``Ext.tree.TreeNode`` The node to add children to.
+     *  :param callback: ``Function``
+     */
+    load: function(node, callback) {
+        if(this.fireEvent("beforeload", this, node)) {
+            this.removeStoreHandlers();
+            while (node.firstChild) {
+                node.removeChild(node.firstChild);
+            }
+            
+            if(!this.uiProviders) {
+                this.uiProviders = node.getOwnerTree().getLoader().uiProviders;
+            }
+    
+            if(!this.store) {
+                this.store = GeoExt.MapPanel.guess().layers;
+            }
+            this.store.each(function(record) {
+                this.addLayerNode(node, record);
+            }, this);
+            this.addStoreHandlers(node);
+    
+            if(typeof callback == "function"){
+                callback();
+            }
+            
+            this.fireEvent("load", this, node);
+        }
+    },
+    
+    /** private: method[onStoreAdd]
+     *  :param store: ``Ext.data.Store``
+     *  :param records: ``Array(Ext.data.Record)``
+     *  :param index: ``Number``
+     *  :param node: ``Ext.tree.TreeNode``
+     *  
+     *  Listener for the store's add event.
+     */
+    onStoreAdd: function(store, records, index, node) {
+        if(!this._reordering) {
+            var nodeIndex = node.recordIndexToNodeIndex(index+records.length-1);
+            for(var i=0; i<records.length; ++i) {
+                this.addLayerNode(node, records[i], nodeIndex);
+            }
+        }
+    },
+    
+    /** private: method[onStoreRemove]
+     *  :param store: ``Ext.data.Store``
+     *  :param record: ``Ext.data.Record``
+     *  :param index: ``Number``
+     *  :param node: ``Ext.tree.TreeNode``
+     *  
+     *  Listener for the store's remove event.
+     */
+    onStoreRemove: function(store, record, index, node) {
+        if(!this._reordering) {
+            this.removeLayerNode(node, record);
+        }
+    },
+
+    /** private: method[addLayerNode]
+     *  :param node: ``Ext.tree.TreeNode`` The node that the layer node will
+     *      be added to as child.
+     *  :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(node, layerRecord, index) {
+        index = index || 0;
+        if (this.filter(layerRecord) === true) {
+            var child = this.createNode({
+                nodeType: 'gx_layer',
+                layer: layerRecord.get("layer"),
+                layerStore: this.store
+            });
+            var sibling = node.item(index);
+            if(sibling) {
+                node.insertBefore(child, sibling);
+            } else {
+                node.appendChild(child);
+            }
+            child.on("move", this.onChildMove, this);
+        }
+    },
+
+    /** private: method[removeLayerNode]
+     *  :param node: ``Ext.tree.TreeNode`` The node that the layer node will
+     *      be removed from as child.
+     *  :param layerRecord: ``Ext.data.Record`` The layer record containing the
+     *      layer to be removed.
+     * 
+     *  Removes a child node representing a layer of the map
+     */
+    removeLayerNode: function(node, layerRecord) {
+        if (this.filter(layerRecord) === true) {
+            var child = node.findChildBy(function(node) {
+                return node.layer == layerRecord.get("layer");
+            });
+            if(child) {
+                child.un("move", this.onChildMove, this);
+                child.remove();
+                node.reload();
+            }
+    	}
+    },
+    
+    /** 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) {
+        this._reordering = true;
+        var oldRecordIndex = this.store.findBy(function(record) {
+            return record.get("layer") === node.layer;
+        });
+        // remove the record and re-insert it at the correct index
+        var record = this.store.getAt(oldRecordIndex);
+
+        if(newParent instanceof GeoExt.tree.LayerContainer && 
+                                    this.store === newParent.loader.store) {
+            newParent.loader._reordering = true;
+            this.store.remove(record);
+            var newRecordIndex;
+            if(newParent.childNodes.length > 1) {
+                // find index by neighboring node in the same container
+                var searchIndex = (index === 0) ? index + 1 : index - 1;
+                newRecordIndex = this.store.findBy(function(r) {
+                    return newParent.childNodes[searchIndex].layer === r.get("layer");
+                });
+                index === 0 && newRecordIndex++;
+            } else if(oldParent.parentNode === newParent.parentNode){
+                // find index by last node of a container above
+                var prev = newParent;
+                do {
+                    prev = prev.previousSibling;
+                } while (prev && !(prev instanceof GeoExt.tree.LayerContainer && prev.lastChild));
+                if(prev) {
+                    newRecordIndex = this.store.findBy(function(r) {
+                        return prev.lastChild.layer === r.get("layer");
+                    });
+                } else {
+                    // find indext by first node of a container below
+                    var next = newParent;
+                    do {
+                        next = next.nextSibling;
+                    } while (next && !(next instanceof GeoExt.tree.LayerContainer && next.firstChild));
+                    if(next) {
+                        newRecordIndex = this.store.findBy(function(r) {
+                            return next.firstChild.layer === r.get("layer");
+                        });
+                    }
+                    newRecordIndex++;
+                }
+            }
+            if(newRecordIndex !== undefined) {
+                this.store.insert(newRecordIndex, [record]);
+                window.setTimeout(function() {
+                    newParent.reload();
+                    oldParent.reload();
+                });
+            } else {
+                this.store.insert(oldRecordIndex, [record]);
+            }
+            delete newParent.loader._reordering;
+        }
+        delete this._reordering;
+    },
+    
+    /** private: method[addStoreHandlers]
+     *  :param node: :class:`GeoExt.tree.LayerNode`
+     */
+    addStoreHandlers: function(node) {
+        if(!this._storeHandlers) {
+            this._storeHandlers = {
+                "add": this.onStoreAdd.createDelegate(this, [node], true),
+                "remove": this.onStoreRemove.createDelegate(this, [node], true)
+            };
+            for(evt in this._storeHandlers) {
+                this.store.on(evt, this._storeHandlers[evt], this);
+            }
+        }
+    },
+    
+    /** private: method[removeStoreHandlers]
+     */
+    removeStoreHandlers: function() {
+        if(this._storeHandlers) {
+            for(evt in this._storeHandlers) {
+                this.store.un(evt, this._storeHandlers[evt], this);
+            }
+            delete this._storeHandlers;
+        }
+    },
+
+    /** private: method[createNode]
+     *  :param attr: ``Object`` attributes for the new node
+     */
+    createNode: function(attr){
+        if(this.baseAttrs){
+            Ext.apply(attr, this.baseAttrs);
+        }
+        if(typeof attr.uiProvider == 'string'){
+           attr.uiProvider = this.uiProviders[attr.uiProvider] || eval(attr.uiProvider);
+        }
+        attr.nodeType = attr.nodeType || "gx_layer";
+
+        return new Ext.tree.TreePanel.nodeTypes[attr.nodeType](attr);
+    },
+
+    /** private: method[destroy]
+     */
+    destroy: function() {
+        this.removeStoreHandlers();
+    }
+});
\ No newline at end of file

Modified: sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tree/OverlayLayerContainer.js
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tree/OverlayLayerContainer.js	2009-07-29 07:38:12 UTC (rev 1292)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt/widgets/tree/OverlayLayerContainer.js	2009-07-29 08:52:37 UTC (rev 1293)
@@ -36,40 +36,19 @@
      *  Private constructor override.
      */
     constructor: function(config) {
-        config.text = config.text || "Overlays";
-        GeoExt.tree.OverlayLayerContainer.superclass.constructor.apply(this,
-            arguments);
-    },
-
-    /** 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, index) {
-        var layer = layerRecord.get("layer");
-        if (layer.isBaseLayer == false) {
-            GeoExt.tree.OverlayLayerContainer.superclass.addLayerNode.apply(
-                this, arguments
-            );
-        }
-    },
-    
-    /** 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.apply(
-                this, arguments
-            );
-    	}
+        config = Ext.applyIf(config || {}, {
+            text: "Overlays"
+        });
+        config.loader = Ext.applyIf(config.loader || {}, {
+            filter: function(record){
+                var layer = record.get("layer");
+                return layer.displayInLayerSwitcher === true &&
+                layer.isBaseLayer === false;
+            }
+        });
+        
+        GeoExt.tree.OverlayLayerContainer.superclass.constructor.call(this,
+            config);
     }
 });
 

Modified: sandbox/elemoine/playground/geoext/lib/GeoExt.js
===================================================================
--- sandbox/elemoine/playground/geoext/lib/GeoExt.js	2009-07-29 07:38:12 UTC (rev 1292)
+++ sandbox/elemoine/playground/geoext/lib/GeoExt.js	2009-07-29 08:52:37 UTC (rev 1293)
@@ -87,6 +87,7 @@
             "GeoExt/widgets/tips/LayerOpacitySliderTip.js",
             "GeoExt/widgets/tips/ZoomSliderTip.js",
             "GeoExt/widgets/tree/LayerNode.js",
+            "GeoExt/widgets/tree/LayerLoader.js",
             "GeoExt/widgets/tree/LayerContainer.js",
             "GeoExt/widgets/tree/BaseLayerContainer.js",
             "GeoExt/widgets/tree/OverlayLayerContainer.js",

Modified: sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/Action.html
===================================================================
--- sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/Action.html	2009-07-29 07:38:12 UTC (rev 1292)
+++ sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/Action.html	2009-07-29 08:52:37 UTC (rev 1293)
@@ -368,6 +368,71 @@
             t.eq(deactivateCtrl1Cnt, 1, "click on item2 deactivates ctrl1 once");
             t.eq(activateCtrl2Cnt, 1, "click on item2 activates ctrl2 once");
         }
+        
+        function test_pressed(t) {
+            
+            t.plan(2);
+            
+            var map = new OpenLayers.Map();
+            var ctrl1 = new OpenLayers.Control();
+            var ctrl2 = new OpenLayers.Control();
+            
+            // confirm that control is activated with pressed true
+            var act1 = new GeoExt.Action({
+                control: ctrl1,
+                map: map,
+                pressed: true,
+                enableToggle: true,
+                toggleGroup: "group"
+            });
+            t.eq(ctrl1.active, true, "ctrl1 activated with pressed true");
+            
+            // confirm that a control is not activated with pressed false
+            var act2 = new GeoExt.Action({
+                control: ctrl2,
+                map: map,
+                pressed: false,
+                enableToggle: true,
+                toggleGroup: "group"
+            });
+            t.ok(!ctrl2.active, "ctrl2 not activated with pressed false");
+            
+            map.destroy();
+            
+        }
+        
+        function test_checked(t) {
+            
+            t.plan(2);
+            
+            var map = new OpenLayers.Map();
+            var ctrl1 = new OpenLayers.Control();
+            var ctrl2 = new OpenLayers.Control();
+            
+            // confirm that control is activated with checked true
+            var act1 = new GeoExt.Action({
+                control: ctrl1,
+                map: map,
+                checked: true,
+                enableToggle: true,
+                toggleGroup: "group"
+            });
+            t.eq(ctrl1.active, true, "ctrl1 activated with checked true");
+            
+            // confirm that a control is not activated with checked false
+            var act2 = new GeoExt.Action({
+                control: ctrl2,
+                map: map,
+                checked: false,
+                enableToggle: true,
+                toggleGroup: "group"
+            });
+            t.ok(!ctrl2.active, "ctrl2 not activated with checked false");
+            
+            map.destroy();
+            
+        }
+        
     </script>
   <body>
     <div id="toolbar"></div>

Modified: sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/Popup.html
===================================================================
--- sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/Popup.html	2009-07-29 07:38:12 UTC (rev 1292)
+++ sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/Popup.html	2009-07-29 08:52:37 UTC (rev 1293)
@@ -93,7 +93,7 @@
                 scope : this
             });
 
-            t.ok(pop.getAnchorElement(), "Popup has anchor element");
+            t.ok(pop.anc, "Popup has anchor element");
 
             // move the map and confirm that popup moves
             context.map.setCenter(new OpenLayers.LonLat(6, 45));
@@ -139,7 +139,7 @@
 
             var newPos = pop.getPosition();
 
-            t.ok(!pop.getAnchorElement(),"Anchor element removed");
+            t.ok(!pop.anc,"Anchor element removed");
             t.ok(!this.collapsed, "Preserved collapsed state");
             t.eq(origPos[0],newPos[0],"Popup remains in same position (X)");
             t.eq(origPos[1],newPos[1],"Popup remains in same position (Y)");

Modified: sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/tree/BaseLayerContainer.html
===================================================================
--- sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/tree/BaseLayerContainer.html	2009-07-29 07:38:12 UTC (rev 1292)
+++ sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/tree/BaseLayerContainer.html	2009-07-29 08:52:37 UTC (rev 1293)
@@ -25,7 +25,8 @@
             });
             
             var node = new GeoExt.tree.BaseLayerContainer({
-                layerStore: store
+                layerStore: store,
+                expanded: true
             });
             
             var panel = new Ext.tree.TreePanel({

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-29 07:38:12 UTC (rev 1292)
+++ sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/tree/LayerContainer.html	2009-07-29 08:52:37 UTC (rev 1293)
@@ -12,15 +12,17 @@
             t.plan(2);
             
             var store = new GeoExt.data.LayerStore();
-            var defaults = {};
+            var defaults = {foo: "bar"};
             
             var node = new GeoExt.tree.LayerContainer({
                 layerStore: store,
-                defaults: defaults
+                loader: {
+                    baseAttrs: defaults
+                }
             });
             
-            t.ok(node.layerStore === store, "layerStore set");
-            t.ok(node.defaults === defaults, "defaults set");
+            t.ok(node.loader.store === store, "layerStore set");
+            t.eq(node.loader.baseAttrs.foo, "bar", "baseAttrs set");
             
             node.destroy();
             
@@ -42,7 +44,8 @@
             });
             
             var node = new GeoExt.tree.LayerContainer({
-                layerStore: store
+                layerStore: store,
+                expanded: true
             });
             
             var panel = new Ext.tree.TreePanel({
@@ -73,7 +76,8 @@
             });
             
             var root = new GeoExt.tree.LayerContainer({
-                layerStore: store
+                layerStore: store,
+                expanded: true
             });
             
             var panel = new Ext.tree.TreePanel({
@@ -122,6 +126,96 @@
             
         }
         
+        function test_group_move(t) {
+            t.plan(8);
+            
+            var map = new OpenLayers.Map({
+                div: "map",
+                allOverlays: true
+            });
+            
+            map.addLayers([
+                new OpenLayers.Layer("a"),
+                new OpenLayers.Layer("b"),
+                new OpenLayers.Layer("c", {displayInLayerSwitcher: false}),
+                new OpenLayers.Layer("d", {displayInLayerSwitcher: false})
+            ]);
+
+            var store = new GeoExt.data.LayerStore({
+                map: map
+            });
+
+            var root = new Ext.tree.TreeNode({
+                expanded: true
+            });
+            
+            var panel = new Ext.tree.TreePanel({
+                renderTo: document.body,
+                root: root,
+                listeners: {
+                    beforemovenode: function(tree, node, oldParent, newParent, index){
+                        // change the group when moving to a new container
+                        if (oldParent !== newParent) {
+                            var index = store.findBy(function(r){
+                                return r.get("layer") === node.layer;
+                            });
+                            var layer = store.getAt(index).get("layer");
+                            layer.displayInLayerSwitcher = !layer.displayInLayerSwitcher;
+                        }
+                    },
+                    scope: this
+                }
+            });
+
+            var container1 = new GeoExt.tree.LayerContainer({
+                loader: {
+                    store: store,
+                    filter: function(record) {
+                        return !record.get("layer").displayInLayerSwitcher
+                    }
+                },
+                expanded: true
+            });
+            root.appendChild(container1);
+            var container2 = new GeoExt.tree.LayerContainer({
+                loader: {
+                    store: store,
+                    filter: function(record) {
+                        return record.get("layer").displayInLayerSwitcher
+                    }
+                },
+                expanded: true
+            });
+            root.appendChild(container2);
+            
+            // testing if layers get grouped by filter properly
+            t.eq(container1.childNodes[0].text, "d", "d is 1st node on container1");
+            t.eq(container1.childNodes[1].text, "c", "c is 2nd node on container1");
+            t.eq(container2.childNodes[0].text, "b", "b is 1st node on container2");
+            t.eq(container2.childNodes[1].text, "a", "a is 2nd node on container2");
+            
+            // testing if indices are determined correctly from previous node in container
+            container2.appendChild(container1.childNodes[0]);
+            t.eq(map.getLayerIndex(container2.childNodes[2].layer), 0, "[c, b, a, d] d moved to the bottom");
+            
+            // testing if indices are determined correctly from next layer in container
+            container2.insertBefore(container1.childNodes[0], container2.childNodes[1]);
+            t.eq(map.getLayerIndex(container2.childNodes[0].layer), 3, "[b, a, d, c] c is now the 4th layer on the map");
+            
+            // testing if indices are determined correctly from container below
+            container1.appendChild(container2.childNodes[0]);
+            t.eq(map.getLayerIndex(container1.childNodes[0].layer), 3, "[b, a, d, c] c is still the 4th layer on the map");
+
+            for(var i=0; i<3; ++i) {
+                container1.appendChild(container2.childNodes[0]);
+            }
+            
+            // testing if indices are determined correctly from container above
+            container2.appendChild(container1.childNodes[0]);
+            t.eq(map.getLayerIndex(container2.childNodes[0].layer), 0, "[a,d,c,b] b moved to the bottom");
+            
+        }
+        
         </script>
     </head>
     <body>

Copied: sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/tree/LayerLoader.html (from rev 1292, core/trunk/geoext/tests/lib/GeoExt/widgets/tree/LayerLoader.html)
===================================================================
--- sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/tree/LayerLoader.html	                        (rev 0)
+++ sandbox/elemoine/playground/geoext/tests/lib/GeoExt/widgets/tree/LayerLoader.html	2009-07-29 08:52:37 UTC (rev 1293)
@@ -0,0 +1,76 @@
+<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_constructor(t) {
+            
+            t.plan(2);
+            
+            var loader = new GeoExt.tree.LayerLoader({
+                store: "foo",
+                filter: "bar"
+            });
+            
+            t.eq(loader.store, "foo", "store set");
+            t.eq(loader.filter, "bar", "filter set");
+        }
+        
+        function test_load(t) {
+            
+            t.plan(3);
+            
+            var args;
+            
+            var loader = new GeoExt.tree.LayerLoader({
+                store: new GeoExt.data.LayerStore(),
+                listeners: {
+                    "beforeload": function(loader, node) {
+                        return node.attributes.load;
+                    },
+                    "load": function(loader, node) {
+                        args = {
+                            loader: loader,
+                            node: node
+                        };
+                    }
+                }
+            });
+            
+            var node = new Ext.tree.AsyncTreeNode({
+                loader: loader,
+                load: false,
+                expanded: true
+            });
+            var tree = new Ext.tree.TreePanel({root: node});
+            tree.render("tree");
+            t.ok(!args, "loading aborted by beforeload event");
+            
+            tree.destroy();
+            node.destroy();
+            
+            node = new Ext.tree.AsyncTreeNode({
+                loader: loader,
+                load: true,
+                expanded: true
+            });
+            tree = new Ext.tree.TreePanel({root: node});
+            tree.render("tree");
+            t.ok(args.loader == loader, "loader passed correctly to 'load' handler");
+            t.ok(args.node == node, "node passed correctly to 'node' handler");
+            
+            tree.destroy();
+            node.destroy();
+            loader.destroy();
+        }
+        
+        </script>
+    </head>
+    <body>
+        <div id="tree" style="width: 100px; height: 100px;"></div>
+    </body>
+</html>

Modified: sandbox/elemoine/playground/geoext/tests/list-tests.html
===================================================================
--- sandbox/elemoine/playground/geoext/tests/list-tests.html	2009-07-29 07:38:12 UTC (rev 1292)
+++ sandbox/elemoine/playground/geoext/tests/list-tests.html	2009-07-29 08:52:37 UTC (rev 1293)
@@ -20,6 +20,7 @@
   <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/LayerLoader.html</li>
   <li>lib/GeoExt/widgets/tree/LayerNode.html</li>
   <li>lib/GeoExt/widgets/LegendImage.html</li>
   <li>lib/GeoExt/widgets/LegendPanel.html</li>



More information about the Commits mailing list