/** * 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. */ /** * @include GeoExt/widgets/tree/LayerNode.js * @include GeoExt/widgets/tree/LayerContainer.js */ Ext.namespace("GeoExt.tree"); /** api: (define) * module = GeoExt.tree * class = LayerLoader * base_link = `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: event[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: event[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.getLayer().displayInLayerSwitcher == true * } */ filter: function(record) { return record.getLayer().displayInLayerSwitcher == true; }, /** api: config[baseAttrs] * An object containing attributes to be added to all nodes created by * this loader. */ baseAttrs: null, /** 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's loader. */ 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 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.getLayer(); }); 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.getLayer(); }); } 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.getLayer(); }); } 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(var evt in this._storeHandlers) { this.store.on(evt, this._storeHandlers[evt], this); } } }, /** private: method[removeStoreHandlers] */ removeStoreHandlers: function() { if(this._storeHandlers) { for(var evt in this._storeHandlers) { this.store.un(evt, this._storeHandlers[evt], this); } delete this._storeHandlers; } }, /** api: method[createNode] * :param attr: ``Object`` attributes for the new node * * Override this function for custom TreeNode node implementation, or to * modify the attributes at creation time. */ 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(); } });