Ext.grid.TableGrid = function(table, config) {
    config = config || {};
    var cf = config.fields || [], ch = config.columns || [];
    table = Ext.get(table);

    var ct = table.insertSibling();

    var fields = [], cols = [];
    var headers = table.query("thead th");
	for (var i = 0, h; h = headers[i]; i++) {
		var text = h.innerHTML;
		var name = 'tcol-'+i;

        fields.push(Ext.applyIf(cf[i] || {}, {
            name: name,
            mapping: 'td:nth('+(i+1)+')/@innerHTML'
        }));

		cols.push(Ext.applyIf(ch[i] || {}, {
			'header': text,
			'dataIndex': name,
			'width': h.offsetWidth,
			'tooltip': h.title,
			'css' : 'white-space: normal;',
        		'sortable': true
        }));
	}

    var ds  = new Ext.data.Store({
        reader: new Ext.data.XmlReader({
            record:'tbody tr'
        }, fields)
    });

	ds.loadData(table.dom);

    var cm = new Ext.grid.ColumnModel(cols);

    if(config.width || config.height){
        ct.setSize(config.width || 'auto', config.height || 'auto');
    }
    if(config.remove !== false){
        table.remove();
    }

    Ext.grid.TableGrid.superclass.constructor.call(this, ct,
        Ext.applyIf(config, {
            'ds': ds,
            'cm': cm,
            'sm': new Ext.grid.RowSelectionModel(),
            autoHeight:true,
            autoWidth:true
        }
    ));
	
};




Ext.tree.TreePanel.prototype.getChecked = function(node){
	var checked = [], i;
	if( typeof node == 'undefined' ) {
		node = this.rootVisible ? this.getRootNode() : this.getRootNode().firstChild;
	}

	if( node.attributes.checked ) {
		checked.push(node.id);
		if( !node.isLeaf() ) {
			for( i = 0; i < node.childNodes.length; i++ ) {
				checked = checked.concat( this.getChecked(node.childNodes[i]) );
			}
		}
	};
	return checked;
};

/**
 * @class Ext.tree.CustomUITreeLoader
 * @extends Ext.tree.TreeLoader
 * Overrides createNode to force uiProvider to be an arbitrary TreeNodeUI to save bandwidth
 */
Ext.tree.CustomUITreeLoader = function() {
	Ext.tree.CustomUITreeLoader.superclass.constructor.apply(this, arguments);
};

Ext.extend(Ext.tree.CustomUITreeLoader, Ext.tree.TreeLoader, {
	createNode : function(attr){
		Ext.apply(attr, this.baseAttr || {});

		if(this.applyLoader !== false){
			attr.loader = this;
		}

		if(typeof attr.uiProvider == 'string'){
			attr.uiProvider = this.uiProviders[attr.uiProvider] || eval(attr.uiProvider);
		}

		return(attr.leaf ?
			new Ext.tree.TreeNode(attr) :
				new Ext.tree.AsyncTreeNode(attr));
	}
});



Ext.tree.CheckboxNodeUI = function() {
	Ext.tree.CheckboxNodeUI.superclass.constructor.apply(this, arguments);
};

Ext.extend(Ext.tree.CheckboxNodeUI, Ext.tree.TreeNodeUI, {
	/**
	 * This is virtually identical to Ext.tree.TreeNodeUI.render, modifications are indicated inline
	 */
	render : function(bulkRender){
		var n = this.node;
		var targetNode = n.parentNode ?
			n.parentNode.ui.getContainer() : n.ownerTree.container.dom; /* in later svn builds this changes to n.ownerTree.innerCt.dom */
		if(!this.rendered){
			this.rendered = true;
			var a = n.attributes;

			// add some indent caching, this helps performance when rendering a large tree
			this.indentMarkup = "";
			if(n.parentNode){
				this.indentMarkup = n.parentNode.ui.getChildIndent();
			}

			// modification: added checkbox
			var buf = ['<li class="x-tree-node"><div class="x-tree-node-el ', n.attributes.cls,'">',
				'<span class="x-tree-node-indent">',this.indentMarkup,"</span>",
				'<img src="', this.emptyIcon, '" class="x-tree-ec-icon">',
				'<img src="', a.icon || this.emptyIcon, '" class="x-tree-node-icon',(a.icon ? " x-tree-node-inline-icon" : ""),(a.iconCls ? " "+a.iconCls : ""),'" unselectable="on">',
				'<input class="l-tcb" type="checkbox" ', (a.checked ? "checked>" : '>'),
				'<a hidefocus="on" href="',a.href ? a.href : "#",'" ',
				 a.hrefTarget ? ' target="'+a.hrefTarget+'"' : "", '>',
				 '<span unselectable="on">',n.text,"</span></a></div>",
				'<ul class="x-tree-node-ct" style="display:none;"></ul>',
				"</li>"];

			if(bulkRender !== true && n.nextSibling && n.nextSibling.ui.getEl()){
				this.wrap = Ext.DomHelper.insertHtml("beforeBegin",
															n.nextSibling.ui.getEl(), buf.join(""));
			}else{
				this.wrap = Ext.DomHelper.insertHtml("beforeEnd", targetNode, buf.join(""));
			}
			this.elNode = this.wrap.childNodes[0];
			this.ctNode = this.wrap.childNodes[1];
			var cs = this.elNode.childNodes;
			this.indentNode = cs[0];
			this.ecNode = cs[1];
			this.iconNode = cs[2];
			this.checkbox = cs[3]; // modification: inserted checkbox
			this.anchor = cs[4];
			this.textNode = cs[4].firstChild;
			if(a.qtip){
			 if(this.textNode.setAttributeNS){
				 this.textNode.setAttributeNS("ext", "qtip", a.qtip);
				 if(a.qtipTitle){
					 this.textNode.setAttributeNS("ext", "qtitle", a.qtipTitle);
				 }
			 }else{
				 this.textNode.setAttribute("ext:qtip", a.qtip);
				 if(a.qtipTitle){
					 this.textNode.setAttribute("ext:qtitle", a.qtipTitle);
				 }
			 }
			} else if(a.qtipCfg) {
				a.qtipCfg.target = Ext.id(this.textNode);
				Ext.QuickTips.register(a.qtipCfg);
			}

			this.initEvents();

			// modification: Add additional handlers here to avoid modifying Ext.tree.TreeNodeUI
			Ext.fly(this.checkbox).on('click', this.check.createDelegate(this, [null]));
			n.on('dblclick', function(e) {
				if( this.isLeaf() ) {
					this.getUI().toggleCheck();
				}
			});

			if(!this.node.expanded){
				this.updateExpandIcon();
			}
		}else{
			if(bulkRender === true) {
				targetNode.appendChild(this.wrap);
			}
		}
	},

	checked : function() {
		return this.checkbox.checked;
	},

	check : function(state, descend, bulk) {
		var n = this.node;
		var tree = n.getOwnerTree();
		var parentNode = n.parentNode;
//		if( !n.expanded && !n.childrenRendered ) {
//			n.expand(false, false, this.check.createDelegate(this, arguments));
//		}

		if( typeof bulk == 'undefined' ) {
			bulk = false;
		}
		if( typeof state == 'undefined' || state === null ) {
			state = this.checkbox.checked;
			descend = !state;
			//if( state ) {
				//n.expand(false, false);
			//}
		} else {
			this.checkbox.checked = state;
		}
		n.attributes.checked = state;

		// do we have parents?
		if( parentNode !== null && state ) {
		}		
		if( !bulk ) {
			tree.fireEvent('check', n, state);
		}
	},

	toggleCheck : function(state) {
		this.check(!this.checkbox.checked, true);
	}

});


Ext.tree.CheckNodeMultiSelectionModel = function(){
   Ext.tree.CheckNodeMultiSelectionModel.superclass.constructor.call(this);
};

Ext.extend(Ext.tree.CheckNodeMultiSelectionModel, Ext.tree.MultiSelectionModel, {
	init : function(tree){
		this.tree = tree;
		tree.el.on("keydown", this.onKeyDown, this);
		tree.on("click", this.onNodeClick, this);
	},

	onNodeClick : function(node, e){
		if( e.shiftKey && this.extendSelection(node) ) {
			return true;
		}
		if( e.ctrlKey && this.isSelected(node) ) {
			this.unselect(node);
		} else {
			this.select(node, e, e.ctrlKey);
		}
	},

	extendSelection : function(node) {
		var last = this.lastSelNode;
		if( node == last || !last ) {
			return false; /* same selection, process normally normally */
		}

		if( node.parentNode == last.parentNode ) {
			var cs = node.parentNode.childNodes;
			var i = 0, attr='id', selecting=false, lastSelect=false;
			this.clearSelections(true);
			for( i = 0; i < cs.length; i++ ) {

				if( cs[i].attributes[attr] == last.attributes[attr] || cs[i].attributes[attr] == node.attributes[attr] ) {
					// lastSelect ensures that we select the final node in the list
					lastSelect = selecting;
					selecting = !selecting;
				}
				if( selecting || lastSelect ) {
					this.select(cs[i], null, true);
					// if we're selecting the last node break to avoid traversing the entire tree
					if( lastSelect ) {
						break;
					}
				}
			}
			return true;
		} else {
			return false;
		}
	},

	onKeyDown : Ext.tree.DefaultSelectionModel.prototype.onKeyDown.createInterceptor(function(e) {
		var s = this.selNode || this.lastSelNode;
		// undesirable, but required
		var sm = this;
		if(!s){
			return;
		}
		var k = e.getKey();
		switch(k){
				case e.SPACE:
					e.stopEvent();
					var sel = this.getSelectedNodes();
					var state = !s.getUI().checked();
					
					if( sel.length == 1 ) {
						s.getUI().check(state, !s.isLeaf());
					} else {
						for( var i = 0; i < sel.length; i++ 
						) {
							sel[i].getUI().check(state, !sel[i].isLeaf() );
						}
					}
			break;
		}

		return true;
	})
});