[Commits] r2367 - in core/trunk/geoext: examples lib lib/GeoExt/plugins lib/GeoExt/widgets/tree tests tests/lib/GeoExt/plugins tests/lib/GeoExt/widgets/tree

commits at geoext.org commits at geoext.org
Fri Sep 17 13:57:01 CEST 2010


Author: ahocevar
Date: 2010-09-17 13:57:01 +0200 (Fri, 17 Sep 2010)
New Revision: 2367

Added:
   core/trunk/geoext/lib/GeoExt/plugins/TreeNodeRadioButton.js
   core/trunk/geoext/lib/GeoExt/widgets/tree/TreeNodeUIEventMixin.js
   core/trunk/geoext/tests/lib/GeoExt/plugins/TreeNodeRadioButton.html
   core/trunk/geoext/tests/lib/GeoExt/widgets/tree/TreeNodeUIEventMixin.html
Removed:
   core/trunk/geoext/lib/GeoExt/widgets/tree/RadioButtonMixin.js
   core/trunk/geoext/tests/lib/GeoExt/widgets/tree/RadioButtonMixin.html
Modified:
   core/trunk/geoext/examples/tree.js
   core/trunk/geoext/lib/GeoExt.js
   core/trunk/geoext/tests/list-tests.html
Log:
New TreeNodeUIEventMixin which allows us to get rid of tree node mixins. This deprecates GeoExt.tree.RadioButtonMixin. r=fredj (closes #185)


Modified: core/trunk/geoext/examples/tree.js
===================================================================
--- core/trunk/geoext/examples/tree.js	2010-09-17 11:26:59 UTC (rev 2366)
+++ core/trunk/geoext/examples/tree.js	2010-09-17 11:57:01 UTC (rev 2367)
@@ -12,7 +12,7 @@
  *  Create all kinds of tree nodes.
  */
 
-var mapPanel;
+var mapPanel, tree;
 Ext.onReady(function() {
     // create a map panel with some layers that we will show in our layer tree
     // below.
@@ -92,10 +92,8 @@
         ]
     });
 
-    // create our own layer node UI class, using the RadioButtonMixin
-    var LayerNodeUI = Ext.extend(
-        GeoExt.tree.LayerNodeUI, new GeoExt.tree.RadioButtonMixin()
-    );
+    // create our own layer node UI class, using the TreeNodeUIEventMixin
+    var LayerNodeUI = Ext.extend(GeoExt.tree.LayerNodeUI, new GeoExt.tree.TreeNodeUIEventMixin());
         
     // using OpenLayers.Format.JSON to create a nice formatted string of the
     // configuration for editing it in the UI
@@ -109,7 +107,8 @@
         loader: {
             baseAttrs: {
                 radioGroup: "foo",
-                uiProvider: "use_radio"
+                allowDelete: true,
+                uiProvider: "layernodeui"
             }
         }
     }, {
@@ -125,7 +124,7 @@
     }], true);
 
     // create the tree with the configuration from above
-    var tree = new Ext.tree.TreePanel({
+    tree = new Ext.tree.TreePanel({
         border: true,
         region: "west",
         title: "Layers",
@@ -134,12 +133,21 @@
         collapsible: true,
         collapseMode: "mini",
         autoScroll: true,
+        plugins: [
+            new GeoExt.plugins.TreeNodeRadioButton({
+                listeners: {
+                    "radiochange": function(node) {
+                        alert(node.text + " is now the active layer.");
+                    }
+                }
+            })
+        ],
         loader: new Ext.tree.TreeLoader({
             // applyLoader has to be set to false to not interfer with loaders
             // of nodes further down the tree hierarchy
             applyLoader: false,
             uiProviders: {
-                "use_radio": LayerNodeUI
+                "layernodeui": LayerNodeUI
             }
         }),
         root: {

Added: core/trunk/geoext/lib/GeoExt/plugins/TreeNodeRadioButton.js
===================================================================
--- core/trunk/geoext/lib/GeoExt/plugins/TreeNodeRadioButton.js	                        (rev 0)
+++ core/trunk/geoext/lib/GeoExt/plugins/TreeNodeRadioButton.js	2010-09-17 11:57:01 UTC (rev 2367)
@@ -0,0 +1,135 @@
+/**
+ * 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/TreeNodeUIEventMixin.js
+  */
+Ext.namespace("GeoExt.plugins");
+
+/** api: (define)
+ *  module = GeoExt.plugins
+ *  class = TreeNodeRadioButton
+ */
+
+/** api: constructor
+ *  A plugin to create tree node UIs with radio buttons. Can be plugged into
+ *  any ``Ext.tree.TreePanel`` and will be applied to nodes that are extended
+ *  with the :class:`GeoExt.Tree.TreeNodeUIEventMixin`, in particular
+ *  :class:`GeoExt.tree.LayerNodeUI` nodes.
+ *
+ *  A tree with a ``GeoExt.plugins.TreeNodeRadioButton`` fires the additional
+ *  ``radiochange`` event when a node's radio button is clicked.
+ *
+ *  Only if a node is configured ``radioGroup`` attribute, it will be rendered
+ *  with a radio button next to its icon. The ``radioGroup`` works like a
+ *  HTML checkbox with its ``name`` attribute, and ``radioGroup`` is a string
+ *  that identifies the options group.
+ * 
+ */
+
+/** api: example
+ *  Sample code to create a tree with a node that has a radio button:
+ *
+ *  .. code-block:: javascript
+ *
+ *      var UIClass = Ext.extend(
+ *          Ext.tree.TreeNodeUI,
+ *          GeoExt.tree.TreeNodeUIEventMixin
+ *      );
+ *      var tree = new Ext.tree.TreePanel({
+ *          plugins: [
+ *              new GeoExt.plugins.TreeNodeRadioButton({
+ *                  listeners: {
+ *                      "radiochange": function(node) {
+ *                          alert(node.text + "'s radio button was clicked.");
+ *                      }
+ *                  }
+ *              })
+ *          ],
+ *          root: {
+ *              nodeType: "node",
+ *              uiProvider: UIClass,
+ *              text: "My Node",
+ *              radioGroup: "myGroupId"
+ *          }
+ *      }
+ */
+
+GeoExt.plugins.TreeNodeRadioButton = Ext.extend(Ext.util.Observable, {
+    
+    /** private: method[constructor]
+     *  :param config: ``Object``
+     */
+    constructor: function(config) {
+        Ext.apply(this.initialConfig, Ext.apply({}, config));
+        Ext.apply(this, config);
+
+        this.addEvents(
+
+            /** api: event[radiochange]
+             *  Fires when a radio button is clicked.
+             *
+             *  Listener arguments:
+             *  
+             *  * node - ``Ext.TreeNode`` The node of the clicked radio button.
+             */
+            "radiochange"
+        );
+
+        GeoExt.plugins.TreeNodeRadioButton.superclass.constructor.apply(this, arguments);
+    },
+
+    /** private: method[init]
+     *  :param tree: ``Ext.tree.TreePanel`` The tree.
+     */
+    init: function(tree) {
+        tree.on({
+            "rendernode": this.onRenderNode,
+            "rawclicknode": this.onRawClickNode,
+            "beforedestroy": this.onBeforeDestroy,
+            scope: this
+        });
+    },
+    
+    /** private: method[onRenderNode]
+     *  :param node: ``Ext.tree.TreeNode``
+     */
+    onRenderNode: function(node) {
+        var a = node.attributes;
+        if(a.radioGroup && !a.radio) {
+            a.radio = Ext.DomHelper.insertBefore(node.ui.anchor,
+                ['<input type="radio" class="gx-tree-radio" name="',
+                a.radioGroup, '_radio"></input>'].join(""));
+        }
+    },
+    
+    /** private: method[onRawClickNode]
+     *  :param node: ``Ext.tree.TreeNode``
+     *  :param e: ``Ext.EventObject``
+     */
+    onRawClickNode: function(node, e) {
+        var el = e.getTarget('.gx-tree-radio', 1); 
+        if(el) {
+            el.defaultChecked = el.checked;
+            this.fireEvent("radiochange", node);
+            return false;
+        }
+    },
+    
+    /** private: method[onBeforeDestroy]
+     */
+    onBeforeDestroy: function(tree) {
+        tree.un("rendernode", this.onRenderNode, this);
+        tree.un("rawclicknode", this.onRenderNode, this);
+        tree.un("beforedestroy", this.onBeforeDestroy, this);
+    }
+
+});
+
+/** api: ptype = gx_treenoderadiobutton */
+Ext.preg("gx_treenoderadiobutton", GeoExt.plugins.TreeNodeRadioButton);

Deleted: core/trunk/geoext/lib/GeoExt/widgets/tree/RadioButtonMixin.js
===================================================================
--- core/trunk/geoext/lib/GeoExt/widgets/tree/RadioButtonMixin.js	2010-09-17 11:26:59 UTC (rev 2366)
+++ core/trunk/geoext/lib/GeoExt/widgets/tree/RadioButtonMixin.js	2010-09-17 11:57:01 UTC (rev 2367)
@@ -1,103 +0,0 @@
-/**
- * Copyright (c) 2008-2010 The Open Source Geospatial Foundation
- * 
- * Published under the BSD license.
- * See http://svn.geoext.org/core/trunk/geoext/license.txt for the full text
- * of the license.
- */
-
-Ext.namespace("GeoExt.tree");
-
-/** api: (define)
- *  module = GeoExt.tree
- *  class = RadioButtonMixin
- */
-
-/** api: constructor
- *  A mixin to create tree node UIs with radio buttons. Can be mixed in
- *  any ``Ext.tree.TreeNodeUI`` class, and in particular in
- *  :class:`GeoExt.tree.LayerNodeUI`.
- *
- *  A tree node using an ``Ext.tree.TreeNodeUI`` with a
- *  ``GeoExt.tree.RadioButtonMixin`` mixed into it generates a ``radiochange``
- *  event when the radio button is clicked. A ``radiochange`` listener
- *  receives the tree node whose radio button was clicked as its first
- *  argument.
- *
- *  If the node has a radioGroup attribute configured, the node will be
- *  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.
- * 
- */
-
-/** api: example
- *  Sample code to create a layer node UI with a radio button:
- *
- *  .. code-block:: javascript
- *
- *      var uiClass = Ext.extend(
- *          GeoExt.tree.LayerNodeUI,
- *          GeoExt.tree.RadioButtonMixin
- *      );
- *
- *  Sample code to create a tree node UI with a radio button:
- *
- *  .. code-block:: javascript
- *
- *      var uiClass = Ext.extend(
- *          Ext.tree.TreeNodeUI,
- *          new GeoExt.tree.RadioButtonMixin
- *      );
- */
-
-GeoExt.tree.RadioButtonMixin = function() {
-    return (function() {
-        /** private: property[superclass]
-         *  ``Ext.tree.TreeNodeUI`` A reference to the superclass that is
-         *  extended with this mixin object.
-         */
-        var superclass;
-
-        return {
-            /** private: method[constructor]
-             *  :param node: ``Ext.tree.TreeNode`` The tree node.
-             */
-            constructor: function(node) {
-                node.addEvents(
-                    "radiochange"
-                );
-                superclass = arguments.callee.superclass;
-                superclass.constructor.apply(this, arguments);
-            },
-
-            /** private: method[render]
-             *  :param bulkRender: ``Boolean``
-             */
-            render: function(bulkRender) {
-                if(!this.rendered) {
-                    superclass.render.apply(this, arguments);
-                    var a = this.node.attributes;
-                    if(a.radioGroup) {
-                        Ext.DomHelper.insertBefore(this.anchor,
-                            ['<input type="radio" class="gx-tree-radio" name="',
-                            a.radioGroup, '_radio"></input>'].join(""));
-                    }
-                }
-            },
-
-            /** private: method[onClick]
-             *  :param e: ``Object``
-             */
-            onClick: function(e) {
-                var el = e.getTarget('.gx-tree-radio', 1); 
-                if(el) {
-                    el.defaultChecked = el.checked;
-                    this.fireEvent("radiochange", this.node);
-                } else {
-                    superclass.onClick.apply(this, arguments);
-                }
-            }
-        };
-    })();
-};

Added: core/trunk/geoext/lib/GeoExt/widgets/tree/TreeNodeUIEventMixin.js
===================================================================
--- core/trunk/geoext/lib/GeoExt/widgets/tree/TreeNodeUIEventMixin.js	                        (rev 0)
+++ core/trunk/geoext/lib/GeoExt/widgets/tree/TreeNodeUIEventMixin.js	2010-09-17 11:57:01 UTC (rev 2367)
@@ -0,0 +1,91 @@
+/**
+ * Copyright (c) 2008-2009 The Open Source Geospatial Foundation
+ * 
+ * Published under the BSD license.
+ * See http://svn.geoext.org/core/trunk/geoext/license.txt for the full text
+ * of the license.
+ */
+
+Ext.namespace("GeoExt.tree");
+
+/** api: (define)
+ *  module = GeoExt.tree
+ *  class = TreeNodeUIEventMixin
+ */
+
+/** api: constructor
+ *  A mixin that adds events to TreeNodeUIs. With these events, tree plugins
+ *  can modify the node ui's DOM when it is rendered, and react to raw click
+ *  events on tree nodes.
+ */
+
+ /** api: example
+  *  Sample code to create a tree with a node that uses the
+  *  :class:`GeoExt.tree.TreeNodeUIEventMixin`:
+  *
+  *  .. code-block:: javascript
+  *
+  *      var UIClass = Ext.extend(
+  *          Ext.tree.TreeNodeUI,
+  *          GeoExt.tree.TreeNodeUIEventMixin
+  *      );
+  *      var tree = new Ext.tree.TreePanel({
+  *          root: {
+  *              nodeType: "node",
+  *              uiProvider: UIClass,
+  *              text: "My Node"
+  *          }
+  *      }
+  */
+
+GeoExt.tree.TreeNodeUIEventMixin = function(){
+    return {
+        
+        constructor: function(node) {
+            
+            node.addEvents(
+
+                /** api: event[rendernode]
+                 *  Fires on the tree when a node is rendered.
+                 *
+                 *  Listener arguments:
+                 *  
+                 *  * node - ``Ext.TreeNode`` The rendered node.
+                 */
+                "rendernode",
+
+                /** api: event[rawclicknode]
+                 *  Fires on the tree when a node is clicked.
+                 *
+                 *  Listener arguments:
+                 *  
+                 *  * node - ``Ext.TreeNode`` The clicked node.
+                 *  * event - ``Ext.EventObject`` The click event.
+                 */
+                "rawclicknode"
+            );
+            this.superclass = arguments.callee.superclass;
+            this.superclass.constructor.apply(this, arguments);
+            
+        },
+        
+        /** private: method[render]
+         *  :param bulkRender: ``Boolean``
+         */
+        render: function(bulkRender) {
+            if(!this.rendered) {
+                this.superclass.render.apply(this, arguments);
+                this.fireEvent("rendernode", this.node);
+            }
+        },
+        
+        /** private: method[onClick]
+         *  :param e: ``Ext.EventObject``
+         */
+        onClick: function(e) {
+            if(this.fireEvent("rawclicknode", this.node, e) !== false) {
+                this.superclass.onClick.apply(this, arguments);
+            }
+        }
+    }
+};
\ No newline at end of file

Modified: core/trunk/geoext/lib/GeoExt.js
===================================================================
--- core/trunk/geoext/lib/GeoExt.js	2010-09-17 11:26:59 UTC (rev 2366)
+++ core/trunk/geoext/lib/GeoExt.js	2010-09-17 11:57:01 UTC (rev 2367)
@@ -93,7 +93,8 @@
             "GeoExt/widgets/tips/LayerOpacitySliderTip.js",
             "GeoExt/widgets/tips/ZoomSliderTip.js",
             "GeoExt/widgets/tree/LayerNode.js",
-            "GeoExt/widgets/tree/RadioButtonMixin.js",
+            "GeoExt/widgets/tree/TreeNodeUIEventMixin.js",
+            "GeoExt/plugins/TreeNodeRadioButton.js",
             "GeoExt/widgets/tree/LayerLoader.js",
             "GeoExt/widgets/tree/LayerContainer.js",
             "GeoExt/widgets/tree/BaseLayerContainer.js",

Added: core/trunk/geoext/tests/lib/GeoExt/plugins/TreeNodeRadioButton.html
===================================================================
--- core/trunk/geoext/tests/lib/GeoExt/plugins/TreeNodeRadioButton.html	                        (rev 0)
+++ core/trunk/geoext/tests/lib/GeoExt/plugins/TreeNodeRadioButton.html	2010-09-17 11:57:01 UTC (rev 2367)
@@ -0,0 +1,60 @@
+<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 layer = new OpenLayers.Layer("foo");
+            
+            var mapPanel = new GeoExt.MapPanel({
+                layers: [layer],
+                allOverlays: true
+            });
+
+            var ui = Ext.extend(
+                GeoExt.tree.LayerNodeUI,
+                new GeoExt.tree.TreeNodeUIEventMixin()
+            );
+            
+            var node = new GeoExt.tree.LayerNode({
+                layer: "foo",
+                radioGroup: "group",
+                uiProvider: ui
+            });
+            
+            var panel = new Ext.tree.TreePanel({
+                renderTo: "tree",
+                root: node,
+                plugins: new GeoExt.plugins.TreeNodeRadioButton({
+                    listeners: {
+                        "radiochange": function() {
+                            t.ok(arguments[0] === node, "radiochange event triggered with the selected node as first argument");
+                        }
+                    }
+                })
+            });
+            
+            mapPanel.on("render", function() {
+                t.ok(Ext.fly(node.ui.getEl()).child(".gx-tree-radio"), "node has a radio button");
+                // simulate a click event for testing the radiochange event
+                node.ui.onClick({getTarget: function() {return true}});
+            });
+
+            mapPanel.render("map");
+            
+            mapPanel.destroy();
+        }
+        </script>
+    </head>
+    <body>
+        <div id="map" style="width: 100px; height: 100px;"></div>
+        <div id="tree" style="width: 100px; height: 100px;"></div>
+    </body>
+</html>

Deleted: core/trunk/geoext/tests/lib/GeoExt/widgets/tree/RadioButtonMixin.html
===================================================================
--- core/trunk/geoext/tests/lib/GeoExt/widgets/tree/RadioButtonMixin.html	2010-09-17 11:26:59 UTC (rev 2366)
+++ core/trunk/geoext/tests/lib/GeoExt/widgets/tree/RadioButtonMixin.html	2010-09-17 11:57:01 UTC (rev 2367)
@@ -1,57 +0,0 @@
-<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 layer = new OpenLayers.Layer("foo");
-            
-            var mapPanel = new GeoExt.MapPanel({
-                layers: [layer],
-                allOverlays: true
-            });
-
-            var ui = Ext.extend(
-                GeoExt.tree.LayerNodeUI,
-                new GeoExt.tree.RadioButtonMixin()
-            );
-            
-            var node = new GeoExt.tree.LayerNode({
-                layer: "foo",
-                radioGroup: "group",
-                uiProvider: ui
-            });
-            
-            node.on("radiochange", function() {
-                t.ok(arguments[0] === node, "radiochange event triggered with the selected node as first argument");
-            });
-                        
-            var panel = new Ext.tree.TreePanel({
-                renderTo: "tree",
-                root: node
-            });
-            
-            mapPanel.on("render", function() {
-                t.ok(Ext.fly(node.ui.getEl()).child(".gx-tree-radio"), "node has a radio button");
-                // simulate a click event for testing the radiochange event
-                node.ui.onClick({getTarget: function() {return true}});
-            });
-
-            mapPanel.render("map");
-            
-            mapPanel.destroy();
-        }
-        </script>
-    </head>
-    <body>
-        <div id="map" style="width: 100px; height: 100px;"></div>
-        <div id="tree" style="width: 100px; height: 100px;"></div>
-    </body>
-</html>

Added: core/trunk/geoext/tests/lib/GeoExt/widgets/tree/TreeNodeUIEventMixin.html
===================================================================
--- core/trunk/geoext/tests/lib/GeoExt/widgets/tree/TreeNodeUIEventMixin.html	                        (rev 0)
+++ core/trunk/geoext/tests/lib/GeoExt/widgets/tree/TreeNodeUIEventMixin.html	2010-09-17 11:57:01 UTC (rev 2367)
@@ -0,0 +1,59 @@
+<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 layer = new OpenLayers.Layer("foo");
+            
+            var mapPanel = new GeoExt.MapPanel({
+                layers: [layer],
+                allOverlays: true
+            });
+
+            var ui = Ext.extend(
+                GeoExt.tree.LayerNodeUI,
+                new GeoExt.tree.TreeNodeUIEventMixin()
+            );
+            
+            var node = new GeoExt.tree.LayerNode({
+                layer: "foo",
+                uiProvider: ui
+            });
+            
+            var panel = new Ext.tree.TreePanel({
+                renderTo: "tree",
+                root: node,
+                listeners: {
+                    "rendernode": function() {
+                        t.ok(arguments[0] === node, "rendernode event triggered with the rendered node as first argument");
+                    },
+                    "rawclicknode": function() {
+                        t.ok(arguments[0] == node, "rawnodeclick event triggered with the clicked node as first argument");
+                    }
+                }
+            });
+            
+            mapPanel.on("render", function() {
+                // simulate a click event for testing the rawnodeclick event
+                node.ui.onClick({getTarget: function() {return true}});
+            });
+
+            mapPanel.render("map");
+            
+            mapPanel.destroy();
+        }
+        </script>
+    </head>
+    <body>
+        <div id="map" style="width: 100px; height: 100px;"></div>
+        <div id="tree" style="width: 100px; height: 100px;"></div>
+    </body>
+</html>

Modified: core/trunk/geoext/tests/list-tests.html
===================================================================
--- core/trunk/geoext/tests/list-tests.html	2010-09-17 11:26:59 UTC (rev 2366)
+++ core/trunk/geoext/tests/list-tests.html	2010-09-17 11:57:01 UTC (rev 2367)
@@ -20,6 +20,7 @@
   <li>lib/GeoExt/plugins/PrintProviderField.html</li>
   <li>lib/GeoExt/plugins/PrintExtent.html</li>
   <li>lib/GeoExt/plugins/AttributeForm.html</li>
+  <li>lib/GeoExt/plugins/TreeNodeRadioButton.html</li>
   <li>lib/GeoExt/widgets/Action.html</li>
   <li>lib/GeoExt/widgets/FeatureRenderer.html</li>
   <li>lib/GeoExt/widgets/LayerOpacitySlider.html</li>
@@ -34,9 +35,9 @@
   <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/tree/RadioButtonMixin.html</li>
   <li>lib/GeoExt/widgets/tree/LayerParamLoader.html</li>
   <li>lib/GeoExt/widgets/tree/LayerParamNode.html</li>
+  <li>lib/GeoExt/widgets/tree/TreeNodeUIEventMixin.html</li>
   <li>lib/GeoExt/widgets/tree/WMSCapabilitiesLoader.html</li>
   <li>lib/GeoExt/widgets/LegendImage.html</li>
   <li>lib/GeoExt/widgets/LegendPanel.html</li>



More information about the Commits mailing list