﻿// class Tree extends Widget
function Tree(treeModel)
{    
    this.onTreeNodeSelected = new EventDelegate;

    extend(this, Container);
    
    this.selectedNode = null;
    this.setTreeModel(treeModel);
}

Tree.prototype = new Container;

// protected void update();
Tree.prototype.update = function()
{
    this.setUpdateSuspended(true);
    this.layoutNode(this.treeModel.getRootNode(), 0, 0);
    this.setUpdateSuspended(false);
};

// private void layoutNode(Node node, int x, int y);
Tree.prototype.layoutNode = function(node, x, y)
{
    var widget = this.getCellWidget(this, node, (node == this.selectedNode), false, true);
    var preferredSize = widget.getPreferredSize();

    if(!widget.container)
    {
        this.add(widget);
    }
    
    widget.setVisible(true);
    widget.setBounds(x, y, preferredSize.width, preferredSize.height);
    
    y += preferredSize.height;
    
    if(!node.isLeaf() && node.isExpanded())
    {
        x += 10; // skin
        
        for(var i = 0; i < node.getNodeCount(); i++)
        {
            y = this.layoutNode(node.getNode(i), x, y);
        }
    }
    
    return y;
};

// public Widget getCellWidget(Node node);
Tree.prototype.getCellWidget = function(tree, node, selected, editing, update)
{
    if(!node.__cell)
    {
        var cell = new Widget();
        
        cell.domContainer.innerHTML = node.getUserObject();
        cell.setPreferredSize({width:100, height:23});
       
        node.__cell = cell;
    }
    
    return node.__cell;
};

// public String getWidgetName();
Tree.prototype.getWidgetName = function()
{
    return "tree";
};

// public void editNode(Node node);
Tree.prototype.editNode = function(node)
{
    if(!node)
    {
        throw new Error("Tree.editNode() - parameter 'node' cannot be null");
    } else
    {
        var widget = this.getCellWidget(this, node, false, false, false);
        
        if(widget.container != this)
        {
            this.treeModel.expand(node, true);
        }
        
        this.getCellWidget(this, node, false, true, true);
    }
};

// public void completeEdit(Node node);
Tree.prototype.completeEdit = function(node)
{
    if(!node)
    {
        throw new Error("Tree.completeEdit() - parameter 'node' cannot be null");
    } else
    {
        this.getCellWidget(this, node, (this.selectedNode == node), false, true);
        // Fire event
    }
};

// public void setTreeModel(TreeModel treeModel);
Tree.prototype.setTreeModel = function(treeModel)
{
    this.clear();
    this.treeModel = treeModel;
    
    this.treeModel.onNodeAdded.addEventListener(getMethodPointer(this, function(model, node) {
        this.update(); // Not necessary
    }));
    
    this.treeModel.onNodeExpansionChanged.addEventListener(getMethodPointer(this, function(model, node, expanded)
    {
        var parent = node.parent;
        
        if(!expanded)
        {
            var hideSubTree = function(parent)
            {
                for(var i = 0; i < parent.getNodeCount(); i++)
                {
                    var child   = parent.getNode(i);
                    var widget  = this.getCellWidget(this, child, false, false, false);

                    widget.setVisible(false);
                    
                    if(child.expanded)
                    {
                        hideSubTree.apply(this, [child]);
                    }
                }
            };
            
            hideSubTree.apply(this, [node]);
        }
        
        if(!parent)
        {
            this.update();
        } else
        {           
            for(var i = parent.getIndexOf(node); i < parent.getNodeCount(); i++)
            {
                var widget = this.getCellWidget(this, node, false, false, false);
                var location = widget.getLocation();
                
                this.layoutNode(node, location.x, location.y);
            }
        }
    }));
    
    this.update();
}

// public TreeModel getTreeModel();
Tree.prototype.getTreeModel = function()
{
    return this.treeModel;
}

// public void selectNode(Node node);
Tree.prototype.selectNode = function(node)
{
    var oldSelection = this.selectedNode;
    
    this.selectedNode = node;
    
    if(oldSelection)
    {
        this.getCellWidget(this, oldSelection, false, false, true);
    }
    
    if(node)
    {
        this.onTreeNodeSelected.fireEvent(this, node);
        this.getCellWidget(this, node, true, false, true);
    }
};

// public boolean isSelected(Node node);
Tree.prototype.isSelected = function(node)
{
    return (this.selectedNode == node);
};
