[Commits] r673 - in sandbox/bartvde/legend/geoext: examples lib/GeoExt/widgets lib/GeoExt/widgets/tree tests/lib/GeoExt/widgets tests/lib/GeoExt/widgets/tree
commits at geoext.org
commits at geoext.org
Mon May 11 09:06:23 CEST 2009
Author: bartvde
Date: 2009-05-11 09:06:22 +0200 (Mon, 11 May 2009)
New Revision: 673
Added:
sandbox/bartvde/legend/geoext/examples/tree.html
sandbox/bartvde/legend/geoext/examples/tree.js
sandbox/bartvde/legend/geoext/lib/GeoExt/widgets/tree/
sandbox/bartvde/legend/geoext/lib/GeoExt/widgets/tree/BaseLayerContainer.js
sandbox/bartvde/legend/geoext/lib/GeoExt/widgets/tree/LayerContainer.js
sandbox/bartvde/legend/geoext/lib/GeoExt/widgets/tree/LayerNode.js
sandbox/bartvde/legend/geoext/lib/GeoExt/widgets/tree/OverlayLayerContainer.js
sandbox/bartvde/legend/geoext/tests/lib/GeoExt/widgets/tree/
sandbox/bartvde/legend/geoext/tests/lib/GeoExt/widgets/tree/LayerContainer.html
sandbox/bartvde/legend/geoext/tests/lib/GeoExt/widgets/tree/LayerNode.html
Log:
applying Andreas' treenodes patch
Added: sandbox/bartvde/legend/geoext/examples/tree.html
===================================================================
--- sandbox/bartvde/legend/geoext/examples/tree.html (rev 0)
+++ sandbox/bartvde/legend/geoext/examples/tree.html 2009-05-11 07:06:22 UTC (rev 673)
@@ -0,0 +1,23 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <link rel="stylesheet" type="text/css" href="../../ext/resources/css/ext-all.css"></link>
+ <link rel="stylesheet" type="text/css" href="../../ext/examples/shared/examples.css"></link>
+ <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" src="tree.js"></script>
+ </head>
+ <body>
+ <div id="desc">
+ <h1>GeoExt.tree Components</h1>
+ <p>This example shows how to work with layer tree. The basic
+ component for building layer trees is the LayerNode, and there are
+ differnt types of containers for automatically adding a map's
+ layers to the tree. The tree configuration of this example is pure
+ JSON and can be edited live by clicking on the "Show/Edit Tree Config"
+ button below the layers panel.<p>
+ <p>The js is not minified so it is readable. See <a href="tree.js">tree.js</a>.</p>
+ </div>
+ </body>
+</html>
Added: sandbox/bartvde/legend/geoext/examples/tree.js
===================================================================
--- sandbox/bartvde/legend/geoext/examples/tree.js (rev 0)
+++ sandbox/bartvde/legend/geoext/examples/tree.js 2009-05-11 07:06:22 UTC (rev 673)
@@ -0,0 +1,175 @@
+var mapPanel;
+Ext.onReady(function() {
+ // using OpenLayers.Format.JSON to create a nice formatted string of the
+ // configuration for editing it in the UI
+ var treeConfig = new OpenLayers.Format.JSON().write([{
+ nodeType: "gx_baselayercontainer"
+ }, {
+ nodeType: "gx_overlaylayercontainer",
+ // render the nodes inside this container with a radio button,
+ // and assign them the group "foo"
+ defaults: {
+ radioGroup: "foo"
+ }
+ }, {
+ nodeType: "gx_layer",
+ layer: "Tasmania Roads"
+ }], true);
+
+ mapPanel = new GeoExt.MapPanel({
+ border: true,
+ region: "center",
+ // we do not want all overlays, to try the OverlayLayerContainer
+ map: new OpenLayers.Map({allOverlays: false}),
+ center: [146.1569825, -41.6109735],
+ zoom: 6,
+ layers: [
+ new OpenLayers.Layer.WMS("Blue Marble",
+ "http://sigma.openplans.org/geoserver/wms", {
+ layers: "bluemarble"
+ }, {
+ buffer: 0,
+ visibility: false
+ }),
+ new OpenLayers.Layer.WMS("Tasmania State Boundaries",
+ "http://demo.opengeo.org/geoserver/wms", {
+ layers: "topp:tasmania_state_boundaries"
+ }, {
+ buffer: 0
+ }),
+ new OpenLayers.Layer.WMS("Water",
+ "http://demo.opengeo.org/geoserver/wms", {
+ layers: "topp:tasmania_water_bodies",
+ transparent: true,
+ format: "image/gif"
+ }, {
+ isBaseLayer: false,
+ buffer: 0
+ }),
+ new OpenLayers.Layer.WMS("Cities",
+ "http://demo.opengeo.org/geoserver/wms", {
+ layers: "topp:tasmania_cities",
+ transparent: true,
+ format: "image/gif"
+ }, {
+ isBaseLayer: false,
+ buffer: 0
+ }),
+ new OpenLayers.Layer.WMS("Tasmania Roads",
+ "http://demo.opengeo.org/geoserver/wms", {
+ layers: "topp:tasmania_roads",
+ transparent: true,
+ format: "image/gif"
+ }, {
+ isBaseLayer: false,
+ buffer: 0,
+ // exclude this layer from layer container nodes
+ displayInLayerSwitcher: false
+ })
+ ]
+ });
+
+ // dialog for editing the tree configuration
+ var treeConfigWin = new Ext.Window({
+ layout: "fit",
+ hideBorders: true,
+ closeAction: "hide",
+ width: 300,
+ height: 400,
+ title: "Tree Configuration",
+ items: [{
+ xtype: "form",
+ layout: "fit",
+ items: [{
+ id: "treeconfig",
+ xtype: "textarea"
+ }],
+ buttons: [{
+ text: "Save",
+ handler: function() {
+ var value = Ext.getCmp("treeconfig").getValue()
+ try {
+ var root = tree.getRootNode();
+ root.attributes.children = Ext.decode(value);
+ tree.getLoader().load(root);
+ } catch(e) {
+ alert("Invalid JSON");
+ return;
+ }
+ treeConfig = value;
+ treeConfigWin.hide();
+ }
+ }, {
+ text: "Cancel",
+ handler: function() {
+ treeConfigWin.hide();
+ }
+ }]
+ }]
+ });
+
+ var toolbar = new Ext.Toolbar({
+ items: [{
+ text: "Show/Edit Tree Config",
+ handler: function() {
+ treeConfigWin.show();
+ Ext.getCmp("treeconfig").setValue(treeConfig);
+ }
+ }]
+ });
+
+ var tree = new Ext.tree.TreePanel({
+ border: true,
+ region: "west",
+ title: "Layers",
+ width: 200,
+ split: true,
+ collapsible: true,
+ collapseMode: "mini",
+ autoScroll: true,
+ loader: new Ext.tree.TreeLoader({
+ clearOnLoad: true
+ }),
+ root: {
+ nodeType: "async",
+ children: Ext.decode(treeConfig)
+ },
+ rootVisible: false,
+ lines: false,
+ bbar: toolbar
+ });
+
+ // the layer node's radio button with its radiochange event can be used
+ // to set an active layer.
+ var registerRadio = function(node){
+ if(!node.hasListener("radiochange")) {
+ node.on("radiochange", function(node){
+ alert(node.layer.name + " is now the the active layer.");
+ });
+ }
+ }
+ tree.on({
+ "insert": registerRadio,
+ "append": registerRadio,
+ scope: this
+ });
+
+ new Ext.Viewport({
+ layout: "fit",
+ hideBorders: true,
+ items: {
+ layout: "border",
+ deferredRender: false,
+ items: [mapPanel, tree, {
+ contentEl: "desc",
+ region: "east",
+ bodyStyle: {"padding": "5px"},
+ collapsible: true,
+ collapseMode: "mini",
+ split: true,
+ width: 200,
+ title: "Description"
+ }]
+ }
+ });
+});
Added: sandbox/bartvde/legend/geoext/lib/GeoExt/widgets/tree/BaseLayerContainer.js
===================================================================
--- sandbox/bartvde/legend/geoext/lib/GeoExt/widgets/tree/BaseLayerContainer.js (rev 0)
+++ sandbox/bartvde/legend/geoext/lib/GeoExt/widgets/tree/BaseLayerContainer.js 2009-05-11 07:06:22 UTC (rev 673)
@@ -0,0 +1,65 @@
+/**
+ * Copyright (c) 2008 The Open Planning Project
+ */
+Ext.namespace("GeoExt.tree");
+
+/**
+ * Class: GeoExt.tree.BaseLayerContainer
+ *
+ * A layer container that will collect all base layers of an OpenLayers map.
+ * Only layers that have displayInLayerSwitcher set to true will be included.
+ *
+ * To use this node type in JSON config, set nodeType to
+ * "olBaseLayerContainer".
+ *
+ * Inherits from:
+ * - <GeoExt.tree.LayerContainer>
+ */
+GeoExt.tree.BaseLayerContainer = Ext.extend(GeoExt.tree.LayerContainer, {
+
+ /**
+ * Constructor: GeoExt.tree.BaseLayerContainer
+ *
+ * Parameters:
+ * config - {Object}
+ */
+ constructor: function(config) {
+ config.text = config.text || "Base Layer";
+ GeoExt.tree.BaseLayerContainer.superclass.constructor.apply(this, arguments);
+ },
+
+ /**
+ * Method: addLayerNode
+ * Adds a child node representing a base layer of the map
+ *
+ * Parameters:
+ * layerRecord - {Ext.data.Record} the layer record to add a node for
+ */
+ addLayerNode: function(layerRecord) {
+ var layer = layerRecord.get("layer");
+ if (layer.isBaseLayer == true) {
+ GeoExt.tree.BaseLayerContainer.superclass.addLayerNode.call(this,
+ layerRecord);
+ }
+ },
+
+ /**
+ * Method: removeLayerNode
+ * Removes a child node representing a base layer of the map
+ *
+ * Parameters:
+ * layerRecord - {Ext.data.Record} the layer record to remove the node for
+ */
+ removeLayerNode: function(layer) {
+ var layer = layerRecord.get("layer");
+ if (layer.isBaseLayer == true) {
+ GeoExt.tree.BaseLayerContainer.superclass.removeLayerNode.call(this,
+ layerRecord);
+ }
+ }
+});
+
+/**
+ * NodeType: gx_baselayercontainer
+ */
+Ext.tree.TreePanel.nodeTypes.gx_baselayercontainer = GeoExt.tree.BaseLayerContainer;
Added: sandbox/bartvde/legend/geoext/lib/GeoExt/widgets/tree/LayerContainer.js
===================================================================
--- sandbox/bartvde/legend/geoext/lib/GeoExt/widgets/tree/LayerContainer.js (rev 0)
+++ sandbox/bartvde/legend/geoext/lib/GeoExt/widgets/tree/LayerContainer.js 2009-05-11 07:06:22 UTC (rev 673)
@@ -0,0 +1,244 @@
+/**
+ * Copyright (c) 2008 The Open Planning Project
+ */
+Ext.namespace("GeoExt.tree");
+
+/**
+ * Class: GeoExt.tree.LayerContainer
+ *
+ * A subclass of {Ext.tree.TreeNode} that will collect all layers of an
+ * OpenLayers map. Only layers that have displayInLayerSwitcher set to true
+ * will be included. The childrens' iconCls will be set to "baselayer-icon"
+ * for base layers, and to "layer-icon" for overlay layers.
+ *
+ * To use this node type in JSON config, set nodeType to "olLayerContainer".
+ *
+ * Inherits from:
+ * - <Ext.tree.TreeNode>
+ */
+GeoExt.tree.LayerContainer = Ext.extend(Ext.tree.TreeNode, {
+
+ /**
+ * APIProperty: layerStore
+ * {<GeoExt.data.LayerStore>} The layer store containing layers to be
+ * displayed in the container.
+ */
+ layerStore: null,
+
+ /**
+ * APIProperty: defaults
+ * {Object} a configuration object passed to all nodes that this
+ * LayerContainer creates.
+ */
+ defaults: null,
+
+ /**
+ * Constructor: GeoExt.tree.LayerContainer
+ *
+ * Parameters:
+ * config - {Object}
+ */
+ constructor: function(config) {
+ this.layerStore = config.layerStore;
+ this.defaults = config.defaults;
+ GeoExt.tree.LayerContainer.superclass.constructor.apply(this, arguments);
+ },
+
+ /**
+ * Method: render
+ *
+ * Parameters:
+ * 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);
+ },
+
+ /**
+ * Method: onStoreAdd
+ * Listener for the store's add event.
+ *
+ * Parameters:
+ * store - {Ext.data.Store}
+ * records - {Array(Ext.data.Record)}
+ * index - {Number}
+ */
+ onStoreAdd: function(store, records, index) {
+ if(!this._reordering) {
+ var nodeIndex = this.recordIndexToNodeIndex(index);
+ for(var i=0; i<records.length; ++i) {
+ this.addLayerNode(records[i], nodeIndex);
+ }
+ }
+ },
+
+ /**
+ * Method: onStoreRemove
+ * Listener for the store's remove event.
+ *
+ * Parameters:
+ * store - {Ext.data.Store}
+ * record - {Ext.data.Record}
+ * index - {Number}
+ */
+ onStoreRemove: function(store, record, index) {
+ if(!this._reordering) {
+ this.removeLayerNode(record);
+ }
+ },
+
+ /**
+ * Method: onDestroy
+ */
+ onDestroy: function() {
+ if(this.layerStore) {
+ this.layerStore.un("add", this.onStoreAdd, this);
+ this.layerStore.un("remove", this.onStoreRemove, this);
+ }
+ GeoExt.tree.LayerContainer.superclass.onDestroy.apply(this, arguments);
+ },
+
+ /**
+ * Method: recordIndexToNodeIndex
+ * Convert a record index into a child node index.
+ *
+ * Parameters:
+ * index - {Number} The record index in the layer store.
+ *
+ * Returns:
+ * {Number} The appropriate child node index for the record.
+ */
+ recordIndexToNodeIndex: function(index) {
+ var store = this.layerStore;
+ var count = store.getCount();
+ var nodeIndex = -1;
+ for(var i=count-1; i>=0; --i) {
+ if(store.getAt(i).get("layer").displayInLayerSwitcher) {
+ ++nodeIndex;
+ if(index === i) {
+ break;
+ }
+ }
+ };
+ return nodeIndex;
+ },
+
+ /**
+ * Method: nodeIndexToRecordIndex
+ * Convert a child node index to a record index.
+ *
+ * Parameters:
+ * index - {Number} The child node index.
+ *
+ * Returns:
+ * {Number} The appropriate record index for the node.
+ */
+ 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;
+ },
+
+ /**
+ * Method: addLayerNode
+ * Adds a child node representing a layer of the map
+ *
+ * Parameters:
+ * layerRecord - {Ext.data.Record} the layer record to add the layer for
+ * index - {Number} Optional index for the new layer. Default is 0.
+ */
+ addLayerNode: function(layerRecord, index) {
+ index = index || 0;
+ var layer = layerRecord.get("layer");
+ if (layer.displayInLayerSwitcher === true) {
+ var node = new GeoExt.tree.LayerNode(Ext.applyIf({
+ iconCls: layer.isBayeLayer ? 'baselayer-icon' : 'layer-icon',
+ 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);
+ }
+ },
+
+ /**
+ * Method: removeLayerNode
+ * Removes a child node representing a layer of the map
+ *
+ * Parameters:
+ * layerRecord - {Ext.data.Record} the layer record to remove the node for
+ */
+ 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();
+ }
+ }
+ },
+
+ /**
+ * Method: onChildMove
+ * Listener for child node "move" events. This updates the order of
+ * records in the store based on new node order if the node has not
+ * changed parents.
+ *
+ * Parameters:
+ * tree - {Ext.data.Tree}
+ * node - {Ext.tree.TreeNode}
+ * oldParent - {Ext.tree.TreeNode}
+ * newParent - {Ext.tree.TreeNode}
+ * index {Number}
+ */
+ 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;
+ }
+ }
+
+});
+
+/**
+ * NodeType: gx_layercontainer
+ */
+Ext.tree.TreePanel.nodeTypes.gx_layercontainer = GeoExt.tree.LayerContainer;
Added: sandbox/bartvde/legend/geoext/lib/GeoExt/widgets/tree/LayerNode.js
===================================================================
--- sandbox/bartvde/legend/geoext/lib/GeoExt/widgets/tree/LayerNode.js (rev 0)
+++ sandbox/bartvde/legend/geoext/lib/GeoExt/widgets/tree/LayerNode.js 2009-05-11 07:06:22 UTC (rev 673)
@@ -0,0 +1,307 @@
+/**
+ * Copyright (c) 2008 The Open Planning Project
+ */
+Ext.namespace("GeoExt.tree");
+
+/**
+ * Class: GeoExt.tree.LayerNodeUI
+ *
+ * Inherits from:
+ * - <GeoExt.tree.TristateCheckboxNodeUI>
+ */
+GeoExt.tree.LayerNodeUI = Ext.extend(Ext.tree.TreeNodeUI, {
+
+ /**
+ * Property: radio
+ * {Ext.Element}
+ */
+ radio: null,
+
+ /**
+ * Constructor: GeoExt.tree.LayerNodeUI
+ *
+ * Parameters:
+ * config - {Object}
+ */
+ constructor: function(config) {
+ GeoExt.tree.LayerNodeUI.superclass.constructor.apply(this, arguments);
+ },
+
+ /**
+ * Method: render
+ *
+ * Parameters:
+ * bulkRender - {Boolean}
+ */
+ render: function(bulkRender) {
+ GeoExt.tree.LayerNodeUI.superclass.render.call(this, bulkRender);
+ var a = this.node.attributes;
+ if (a.radioGroup && this.radio !== undefined) {
+ this.radio = Ext.DomHelper.insertAfter(this.checkbox,
+ ['<input type="radio" class="x-tree-node-radio" name="',
+ a.radioGroup, '_radio"></input>'].join(""));
+ }
+ },
+
+ /**
+ * Method: onClick
+ *
+ * Parameters:
+ * e - {Object}
+ */
+ onClick: function(e) {
+ if (e.getTarget('input[type=radio]', 1)) {
+ this.fireEvent("radiochange", this.node);
+ } else {
+ GeoExt.tree.LayerNodeUI.superclass.onClick.call(this, e);
+ }
+ },
+
+ /**
+ * Method: toggleCheck
+ *
+ * Parameters:
+ * value - {Boolean}
+ */
+ toggleCheck: function(value) {
+ GeoExt.tree.LayerNodeUI.superclass.toggleCheck.call(this, value);
+ var node = this.node;
+ var layer = this.node.layer;
+ node.visibilityChanging = true;
+ if(this.checkbox && (layer.getVisibility() != this.isChecked())) {
+ layer.setVisibility(this.isChecked());
+ }
+ node.visibilityChanging = false;
+ },
+
+ /**
+ * Method: onDestroy
+ */
+ onDestroy: function() {
+ delete this.radio;
+ GeoExt.tree.LayerNodeUI.superclass.onDestroy.call(this);
+ }
+});
+
+
+/**
+ * Class: GeoExt.tree.LayerNode
+ *
+ * A subclass of {<GeoExt.tree.TristateCheckboxNode>} 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.
+ *
+ * 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 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.
+ *
+ * To use this node type in a JSON config, set nodeType to "gx_layer".
+ *
+ * Inherits from:
+ * - Ext.tree.TreeNode
+ */
+GeoExt.tree.LayerNode = Ext.extend(Ext.tree.TreeNode, {
+
+ /**
+ * APIProperty: layer
+ * {OpenLayers.Layer|String} The layer that this layer node will
+ * be bound to, or the name of the layer (has to match the layer's
+ * name property). If a layer name is provided, <layerStore> also has
+ * to be provided.
+ */
+ layer: null,
+
+ /**
+ * APIProperty: layerStore
+ * {<GeoExt.data.LayerStore|"auto"} The layer store containing the layer
+ * that this node represents. If set to "auto", the node will query
+ * the ComponentManager for a <GeoExt.MapPanel>, take the first one it
+ * finds and take its layer store. This property is only required
+ * if <layer> is provided as a string.
+ */
+ layerStore: null,
+
+ /**
+ * APIProperty: childNodeType
+ * {Ext.tree.Node|String} node class or nodeType of childnodes for this
+ * node. A node type provided here needs to have an add method, with
+ * a scope argument. This method will be run by this node in the
+ * context of this node, to create child nodes.
+ */
+ childNodeType: null,
+
+ /**
+ * Property: visibilityChanging
+ * {Boolean} private property indicating layer visibility being changed
+ * by this node in order to prevent visibilitychanged events bouncing
+ * back and forth
+ */
+ visibilityChanging: false,
+
+ /**
+ * Constructor: GeoExt.tree.LayerNode
+ *
+ * Parameters:
+ * config - {Object}
+ */
+ constructor: function(config) {
+ config.leaf = config.leaf || !config.children;
+
+ config.iconCls = typeof config.iconCls == "undefined" &&
+ !config.children ? "layer-icon" : config.iconCls;
+ // checked status will be set by layer event, so setting it to false
+ // to always get the checkbox rendered
+ config.checked = false;
+
+ this.defaultUI = this.defaultUI || GeoExt.tree.LayerNodeUI;
+ this.addEvents(
+ /**
+ * Event: radiochange
+ * Notifies listener when a differnt radio button was selected.
+ * Will be called with the currently selected node as argument.
+ */
+ "radiochange"
+ );
+
+ Ext.apply(this, {
+ layer: config.layer,
+ layerStore: config.layerStore,
+ childNodeType: config.childNodeType
+ });
+ GeoExt.tree.LayerNode.superclass.constructor.apply(this, arguments);
+ },
+
+ /**
+ * Method: render
+ *
+ * Properties:
+ * bulkRender {Boolean} - optional
+ * layer {<OpenLayers.Layer>} - optional
+ */
+ render: function(bulkRender) {
+ var layer = this.layer instanceof OpenLayers.Layer && this.layer;
+ if(!layer) {
+ // guess the store if not provided
+ if(!this.layerStore || this.layerStore == "auto") {
+ this.layerStore = GeoExt.MapPanel.guess().layers;
+ }
+ // now we try to find the layer by its name in the layer store
+ var i = this.layerStore.findBy(function(o) {
+ return o.get("title") == this.layer;
+ }, this);
+ if(i != -1) {
+ // if we found the layer, we can assign it and everything
+ // will be fine
+ layer = this.layerStore.getAt(i).get("layer");
+ }
+ }
+ if (!this.rendered || !layer) {
+ var ui = this.getUI();
+
+ if(layer) {
+ this.layer = layer;
+ if(!this.text) {
+ this.text = layer.name;
+ }
+
+ if(this.childNodeType) {
+ this.addChildNodes();
+ }
+
+ ui.show();
+ ui.toggleCheck(layer.getVisibility());
+ this.addVisibilityEventHandlers();
+ // set initial checked status
+ this.attributes.checked = layer.getVisibility();
+ } else {
+ ui.hide();
+ }
+
+ if(this.layerStore instanceof GeoExt.data.LayerStore) {
+ this.addStoreEventHandlers(layer);
+ }
+ }
+ GeoExt.tree.LayerNode.superclass.render.call(this, bulkRender);
+ },
+
+ /**
+ * Method: addVisibilityHandlers
+ * Adds handlers that sync the checkbox state with the layer's visibility
+ * state
+ */
+ addVisibilityEventHandlers: function() {
+ this.layer.events.register("visibilitychanged", this, function() {
+ if(!this.visibilityChanging &&
+ this.attributes.checked != this.layer.getVisibility()) {
+ this.getUI().toggleCheck(this.layer.getVisibility());
+ }
+ });
+ this.on({
+ "checkchange": function(node, checked) {
+ if (checked && this.layer.isBaseLayer && this.layer.map) {
+ this.layer.map.setBaseLayer(this.layer);
+ }
+ this.layer.setVisibility(checked);
+ },
+ scope: this
+ });
+ },
+
+ /**
+ * Method: addStoreEventHandlers
+ * Adds handlers that make sure the node disappeares when the layer is
+ * removed from the store, and appears when it is re-added.
+ */
+ addStoreEventHandlers: function() {
+ this.layerStore.on({
+ "add": function(store, records, index) {
+ var l;
+ for(var i=0; i<records.length; ++i) {
+ l = records[i].get("layer");
+ if(this.layer == l) {
+ this.getUI().show();
+ } else if (this.layer == l.name) {
+ // layer is a string, which means the node has not yet
+ // been rendered because the layer was not found. But
+ // now we have the layer and can render.
+ this.render(bulkRender);
+ return;
+ }
+ }
+ },
+ "remove": function(store, record, index) {
+ if(this.layer == record.get("layer")) {
+ this.getUI().hide();
+ }
+ },
+ scope: this
+ });
+ },
+
+ /**
+ * Method: addChildNodes
+ * Calls the add method of a node type configured as <childNodeType>
+ * to add children.
+ */
+ addChildNodes: function() {
+ if(typeof this.childNodeType == "string") {
+ Ext.tree.TreePanel.nodeTypes[this.childNodeType].add(this);
+ } else if(typeof this.childNodeType.add === "function") {
+ this.childNodeType.add(this);
+ }
+ }
+});
+
+/**
+ * NodeType: gx_layer
+ */
+Ext.tree.TreePanel.nodeTypes.gx_layer = GeoExt.tree.LayerNode;
Added: sandbox/bartvde/legend/geoext/lib/GeoExt/widgets/tree/OverlayLayerContainer.js
===================================================================
--- sandbox/bartvde/legend/geoext/lib/GeoExt/widgets/tree/OverlayLayerContainer.js (rev 0)
+++ sandbox/bartvde/legend/geoext/lib/GeoExt/widgets/tree/OverlayLayerContainer.js 2009-05-11 07:06:22 UTC (rev 673)
@@ -0,0 +1,66 @@
+/**
+ * Copyright (c) 2008 The Open Planning Project
+ */
+Ext.namespace("GeoExt.tree");
+
+/**
+ * Class: GeoExt.tree.OverlayLayerContainer
+ *
+ * A layer container that will collect all overlay layers of an OpenLayers map.
+ * Only layers that have displayInLayerSwitcher set to true will be included.
+ *
+ * To use this node type in JSON config, set nodeType to
+ * "olOverlayLayerContainer".
+ *
+ * Inherits from:
+ * - <GeoExt.tree.LayerContainer>
+ */
+GeoExt.tree.OverlayLayerContainer = Ext.extend(GeoExt.tree.LayerContainer, {
+
+ /**
+ * Constructor: GeoExt.tree.OverlayLayerContainer
+ *
+ * Parameters:
+ * config - {Object}
+ */
+ constructor: function(config) {
+ config.text = config.text || "Overlays";
+ GeoExt.tree.OverlayLayerContainer.superclass.constructor.apply(this,
+ arguments);
+ },
+
+ /**
+ * Method: addLayerNode
+ * Adds a child node representing a overlay layer of the map
+ *
+ * Parameters:
+ * layerRecord - {Ext.data.Record} the layer record to add a node for
+ */
+ addLayerNode: function(layerRecord) {
+ var layer = layerRecord.get("layer");
+ if (layer.isBaseLayer == false) {
+ GeoExt.tree.OverlayLayerContainer.superclass.addLayerNode.call(this,
+ layerRecord);
+ }
+ },
+
+ /**
+ * Method: removeLayerNode
+ * Removes a child node representing an overlay layer of the map
+ *
+ * Parameters:
+ * layerRecord - {Ext.data.Record} the layer record to remove the node for
+ */
+ removeLayerNode: function(layerRecord) {
+ var layer = layerRecord.get("layer");
+ if (layer.isBaseLayer == false) {
+ GeoExt.tree.OverlayLayerContainer.superclass.removeLayerNode.call(
+ this, layerRecord);
+ }
+ }
+});
+
+/**
+ * NodeType: gx_overlaylayercontainer
+ */
+Ext.tree.TreePanel.nodeTypes.gx_overlaylayercontainer = GeoExt.tree.OverlayLayerContainer;
Added: sandbox/bartvde/legend/geoext/tests/lib/GeoExt/widgets/tree/LayerContainer.html
===================================================================
--- sandbox/bartvde/legend/geoext/tests/lib/GeoExt/widgets/tree/LayerContainer.html (rev 0)
+++ sandbox/bartvde/legend/geoext/tests/lib/GeoExt/widgets/tree/LayerContainer.html 2009-05-11 07:06:22 UTC (rev 673)
@@ -0,0 +1,65 @@
+<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 store = new GeoExt.data.LayerStore();
+ var defaults = {};
+
+ var node = new GeoExt.tree.LayerContainer({
+ layerStore: store,
+ defaults: defaults
+ });
+
+ t.ok(node.layerStore === store, "layerStore set");
+ t.ok(node.defaults === defaults, "defaults set");
+
+ node.destroy();
+
+ }
+
+ function test_render(t) {
+
+ t.plan(2);
+
+ var map = new OpenLayers.Map({
+ div: "map",
+ allOverlays: true
+ });
+ var layer = new OpenLayers.Layer();
+ map.addLayer(layer);
+
+ var store = new GeoExt.data.LayerStore({
+ map: map
+ });
+
+ var node = new GeoExt.tree.LayerContainer({
+ layerStore: store
+ });
+
+ var panel = new Ext.tree.TreePanel({
+ renderTo: document.body,
+ root: node
+ });
+
+ t.eq(node.childNodes && node.childNodes.length, 1, "container has one child");
+ t.ok(node.firstChild.layer === layer, "child layer is correct");
+
+ node.destroy();
+
+ }
+
+ </script>
+ </head>
+ <body>
+ <div id="map" style="width: 100px; height: 100px;"></div>
+ </body>
+</html>
\ No newline at end of file
Added: sandbox/bartvde/legend/geoext/tests/lib/GeoExt/widgets/tree/LayerNode.html
===================================================================
--- sandbox/bartvde/legend/geoext/tests/lib/GeoExt/widgets/tree/LayerNode.html (rev 0)
+++ sandbox/bartvde/legend/geoext/tests/lib/GeoExt/widgets/tree/LayerNode.html 2009-05-11 07:06:22 UTC (rev 673)
@@ -0,0 +1,78 @@
+<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(1);
+
+ var store = new GeoExt.data.LayerStore();
+
+ var node = new GeoExt.tree.LayerNode({
+ layer: "foo",
+ layerStore: store
+ });
+
+ t.ok(node.layerStore === store, "layerStore set");
+
+ node.destroy();
+
+ }
+
+ function test_render(t) {
+
+ t.plan(5);
+
+ var layer = new OpenLayers.Layer("foo");
+
+ var mapPanel = new GeoExt.MapPanel({
+ layers: [layer],
+ allOverlays: true
+ });
+
+ var node = new GeoExt.tree.LayerNode({
+ layer: "foo",
+ radioGroup: "group",
+ childNodeType: {
+ add: function() {
+ t.ok(true, "add function of childNodeType called");
+ }
+ }
+ });
+
+ 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(node.layer === layer, "layer found on detected map panel");
+
+ 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}});
+
+ node.ui.toggleCheck();
+ t.eq(layer.visibility, false, "unchecking node hides layer");
+ });
+
+ mapPanel.render("map");
+
+ }
+
+ </script>
+ </head>
+ <body>
+ <div id="map" style="width: 100px; height: 100px;"></div>
+ <div id="tree" style="width: 100px; height: 100px;"></div>
+ </body>
+</html>
\ No newline at end of file
More information about the Commits
mailing list