//http://extjs.com/forum/showthread.php?t=15559
Ext.namespace("Ext.repaired");
Ext.repaired.RootTreeNodeUI = function(){
    Ext.repaired.RootTreeNodeUI.superclass.constructor.apply(this, arguments);
};

Ext.extend(Ext.repaired.RootTreeNodeUI,Ext.tree.RootTreeNodeUI, {
   // private
    render : function(){
        if(!this.rendered){
            var targetNode = this.node.ownerTree.innerCt.dom;
           // this.node.expanded = true;  let this default from the AsynchTreeNode definition - you control it now.
            targetNode.innerHTML = '<div class="x-tree-root-node"></div>';
            this.wrap = this.ctNode = targetNode.firstChild;
        }
    }
});

//Provide a mechanism to define a custom RootTreeNodeUI implementation.
 Ext.override(Ext.tree.TreePanel, {
/**
     * Sets the root node for this tree during initialization. 
     * @param {Node} node
     * @return {Node}
     */
    setRootNode : function(node){
        this.root = node;
        node.ownerTree = this;
        node.isRoot = true;
        this.registerNode(node);
        if(!this.rootVisible){
            node.ui =  node.attributes.uiProvider?
                  new node.attributes.uiProvider(node):
                      new Ext.tree.RootTreeNodeUI(node);
        }
        return node;
    }
});
 
 Ext.override(Ext.tree.AsyncTreeNode, {
    expand : function(deep, anim, callback){
        if(this.loading){ // if an async load is already running, waiting til it's done
            var timer;
            var f = function(){
                if(!this.loading){ // done loading
                    clearInterval(timer);
                    this.expand(deep, anim, callback);
                }
            }.createDelegate(this);
            timer = setInterval(f, 200);
            return;
        }
        if(!this.loaded){
            if(this.fireEvent("beforeload", this) === false){
                return;
            }
            this.loading = true;
            this.ui.beforeLoad(this);
            var loader = this.getLoader();
            if(loader){
                loader.load(this, this.loadComplete.createDelegate(this, [deep, anim, callback]));
                return;
            }
        }
        Ext.tree.AsyncTreeNode.superclass.expand.call(this, deep, anim, callback);
    },
    //return whatever loader is defined
    getLoader : function(){
       return this.loader || this.attributes.loader || this.getOwnerTree().getLoader();
    }
 });
