[Commits] r1240 - sandbox/bartvde/layernodes/trunk/geoext/lib/GeoExt/widgets/tree
commits at geoext.org
commits at geoext.org
Thu Jul 9 14:22:45 CEST 2009
Author: bartvde
Date: 2009-07-09 14:22:45 +0200 (Thu, 09 Jul 2009)
New Revision: 1240
Added:
sandbox/bartvde/layernodes/trunk/geoext/lib/GeoExt/widgets/tree/LayerNode.js
Log:
putting in LayerNode from trunk
Copied: sandbox/bartvde/layernodes/trunk/geoext/lib/GeoExt/widgets/tree/LayerNode.js (from rev 1239, core/trunk/geoext/lib/GeoExt/widgets/tree/LayerNode.js)
===================================================================
--- sandbox/bartvde/layernodes/trunk/geoext/lib/GeoExt/widgets/tree/LayerNode.js (rev 0)
+++ sandbox/bartvde/layernodes/trunk/geoext/lib/GeoExt/widgets/tree/LayerNode.js 2009-07-09 12:22:45 UTC (rev 1240)
@@ -0,0 +1,382 @@
+/**
+ * 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");
+
+/** private: constructor
+ * .. class:: LayerNodeUI
+ *
+ * Place in a separate file if this should be documented.
+ */
+GeoExt.tree.LayerNodeUI = Ext.extend(Ext.tree.TreeNodeUI, {
+
+ /** private: property[radio]
+ * ``Ext.Element``
+ */
+ radio: null,
+
+ /** private: method[constructor]
+ */
+ constructor: function(config) {
+ GeoExt.tree.LayerNodeUI.superclass.constructor.apply(this, arguments);
+ },
+
+ /** private: method[render]
+ * :param bulkRender: ``Boolean``
+ */
+ render: function(bulkRender) {
+ GeoExt.tree.LayerNodeUI.superclass.render.call(this, bulkRender);
+ var a = this.node.attributes;
+ if (a.radioGroup && this.radio === null) {
+ this.radio = Ext.DomHelper.insertAfter(this.checkbox,
+ ['<input type="radio" class="gx-tree-layer-radio" name="',
+ a.radioGroup, '_radio"></input>'].join(""));
+ }
+ if(a.checkedGroup) {
+ // replace the checkbox with a radio button
+ var radio = Ext.DomHelper.insertAfter(this.checkbox,
+ ['<input type="radio" name="', a.checkedGroup,
+ '_checkbox" class="', this.checkbox.className,
+ this.checkbox.checked ? '" checked="checked"' : '',
+ '"></input>'].join(""));
+ Ext.get(this.checkbox).remove();
+ this.checkbox = radio;
+ }
+ },
+
+ /** private: method[onClick]
+ * :param e: ``Object``
+ */
+ onClick: function(e) {
+ if (e.getTarget('.gx-tree-layer-radio', 1)) {
+ this.fireEvent("radiochange", this.node);
+ } else if(e.getTarget('.x-tree-node-cb', 1)) {
+ GeoExt.tree.LayerNodeUI.superclass.onCheckChange.call(this);
+ } else {
+ GeoExt.tree.LayerNodeUI.superclass.onClick.call(this, e);
+ }
+ },
+
+ /** private: method[toggleCheck]
+ * :param 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;
+ },
+
+ /** private: method[destroy]
+ */
+ destroy: function() {
+ delete this.radio;
+ GeoExt.tree.LayerNodeUI.superclass.destroy.call(this);
+ }
+});
+
+/** api: (define)
+ * module = GeoExt.tree
+ * class = LayerNode
+ * base_link = `Ext.tree.TreeNode <http://extjs.com/deploy/dev/docs/?class=Ext.tree.TreeNode>`_
+ */
+
+/** api: constructor
+ * .. class:: LayerNode(config)
+ *
+ * A subclass of ``Ext.tree.TreeNode`` that is connected to an
+ * ``OpenLayers.Layer`` by setting the node's layer property. Checking or
+ * unchecking the checkbox of this node will directly affect the layer and
+ * vice versa. The default iconCls for this node's icon is
+ * "gx-tree-layer-icon", unless it has children.
+ *
+ * Setting the node's layer property to a layer name instead of an object
+ * will also work. As soon as a layer is found, it will be stored as layer
+ * property in the attributes hash.
+ *
+ * The node's text property defaults to the layer name.
+ *
+ * If the node has a checkedGroup attribute configured, it will be
+ * rendered with a radio button instead of the checkbox. The value of
+ * the checkedGroup attribute is a string, identifying the options group
+ * for the node.
+ *
+ * If the node has a radioGroup attribute configured, the node will be
+ * rendered with a radio button next to the checkbox. This works like the
+ * checkbox with the checked attribute, but radioGroup is a string that
+ * identifies the options group. Clicking the radio button will fire a
+ * radioChange event.
+ *
+ * To use this node type in a ``TreePanel`` config, set ``nodeType`` to
+ * "gx_layer".
+ */
+GeoExt.tree.LayerNode = Ext.extend(Ext.tree.TreeNode, {
+
+ /** api: config[layer]
+ * ``OpenLayers.Layer or 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.
+ */
+
+ /** api: property[layer]
+ * ``OpenLayers.Layer``
+ * The layer this node is bound to.
+ */
+ layer: null,
+
+ /** api: config[layerStore]
+ * :class:`GeoExt.data.LayerStore` ``or "auto"``
+ * The layer store containing the layer that this node represents. If set
+ * to "auto", the node will query the ComponentManager for a
+ * :class:`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,
+
+ /** api: config[childNodeType]
+ * ``Ext.tree.Node or 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,
+
+ /** private: 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,
+
+ /** private: method[constructor]
+ * Private constructor override.
+ */
+ constructor: function(config) {
+ config.leaf = config.leaf || !config.children;
+
+ config.iconCls = typeof config.iconCls == "undefined" &&
+ !config.children ? "layer-icon" : config.iconCls;
+ // checked status will be set by layer event, so setting it to false
+ // to always get the checkbox rendered
+ config.checked = false;
+
+ this.defaultUI = this.defaultUI || GeoExt.tree.LayerNodeUI;
+ this.addEvents(
+ /** api: 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);
+ },
+
+ /** private: method[render]
+ * :param bulkRender: ``Boolean``
+ */
+ 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);
+ },
+
+ /** private: method[addVisibilityHandlers]
+ * Adds handlers that sync the checkbox state with the layer's visibility
+ * state
+ */
+ addVisibilityEventHandlers: function() {
+ this.layer.events.on({
+ "visibilitychanged": this.onLayerVisibilityChanged,
+ scope: this
+ });
+ this.on({
+ "checkchange": this.onCheckChange,
+ scope: this
+ });
+ },
+
+ /** private: method[onLayerVisiilityChanged
+ * handler for visibilitychanged events on the layer
+ */
+ onLayerVisibilityChanged: function() {
+ if(!this.visibilityChanging &&
+ this.attributes.checked != this.layer.getVisibility()) {
+ this.getUI().toggleCheck(this.layer.getVisibility());
+ }
+ },
+
+ /** private: method[onCheckChange]
+ * :param node: ``GeoExt.tree.LayerNode``
+ * :param checked: ``Boolean``
+ *
+ * handler for checkchange events
+ */
+ onCheckChange: function(node, checked) {
+ if (checked && this.layer.isBaseLayer && this.layer.map) {
+ this.layer.map.setBaseLayer(this.layer);
+ }
+ this.layer.setVisibility(checked);
+ },
+
+ /** private: method[addStoreEventHandlers]
+ * Adds handlers that make sure the node disappeares when the layer is
+ * removed from the store, and appears when it is re-added.
+ */
+ addStoreEventHandlers: function() {
+ this.layerStore.on({
+ "add": this.onStoreAdd,
+ "remove": this.onStoreRemove,
+ "update": this.onStoreUpdate,
+ scope: this
+ });
+ },
+
+ /** private: method[onStoreAdd]
+ * :param store: ``Ext.data.Store``
+ * :param records: ``Array(Ext.data.Record)``
+ * :param index: ``Number``
+ *
+ * handler for add events on the store
+ */
+ onStoreAdd: function(store, records, index) {
+ var l;
+ for(var i=0; i<records.length; ++i) {
+ l = records[i].get("layer");
+ if(this.layer == l) {
+ this.getUI().show();
+ } else if (this.layer == l.name) {
+ // layer is a string, which means the node has not yet
+ // been rendered because the layer was not found. But
+ // now we have the layer and can render.
+ this.render(bulkRender);
+ return;
+ }
+ }
+ },
+
+ /** private: method[onStoreRemove]
+ * :param store: ``Ext.data.Store``
+ * :param record: ``Ext.data.Record``
+ * :param index: ``Number``
+ *
+ * handler for remove events on the store
+ */
+ onStoreRemove: function(store, record, index) {
+ if(this.layer == record.get("layer")) {
+ this.getUI().hide();
+ }
+ },
+
+ /** private: method[onStoreUpdate]
+ * :param store: ``Ext.data.Store``
+ * :param record: ``Ext.data.Record``
+ * :param operation: ``String``
+ *
+ * Listener for the store's update event.
+ */
+ onStoreUpdate: function(store, record, operation) {
+ var layer = record.get("layer");
+ if(this.layer == layer && record.isModified("title") &&
+ record.modified["title"] == this.text) {
+ this.setText(record.get("title"));
+ }
+ },
+
+ /** private: method[addChildNodes]
+ * Calls the add method of a node type configured as ``childNodeType``
+ * to add children.
+ */
+ addChildNodes: function() {
+ if(typeof this.childNodeType == "string") {
+ Ext.tree.TreePanel.nodeTypes[this.childNodeType].add(this);
+ } else if(typeof this.childNodeType.add === "function") {
+ this.childNodeType.add(this);
+ }
+ },
+
+ /** private: method[destroy]
+ */
+ destroy: function() {
+ var layer = this.layer;
+ if (layer instanceof OpenLayers.Layer) {
+ layer.events.un({
+ "visibilitychanged": this.onLayerVisibilityChanged,
+ scope: this
+ });
+ }
+ delete this.layer;
+ var layerStore = this.layerStore;
+ if(layerStore) {
+ layerStore.un("add", this.onStoreAdd, this);
+ layerStore.un("remove", this.onStoreRemove, this);
+ layerStore.un("update", this.onStoreUpdate, this);
+ }
+ delete this.layerStore;
+ this.un("checkchange", this.onCheckChange, this);
+
+ GeoExt.tree.LayerNode.superclass.destroy.call(this);
+ }
+});
+
+/**
+ * NodeType: gx_layer
+ */
+Ext.tree.TreePanel.nodeTypes.gx_layer = GeoExt.tree.LayerNode;
More information about the Commits
mailing list