 /** default icon for a leaf (node with no child) */
    var defaultLeafIcon = 'images/leaf.gif';
    /** default icon for a opened node with at least one child */
    var defaultOpenedNodeIcon = 'images/opened_node.gif';
    /** default icon for a closed node with at least one child */
    var defaultClosedNodeIcon = 'images/closed_node.gif';

    /**
     * Creates a new tree.
     */
    function Tree()
    {
        this.m_Children = new Array();
        this.m_HoveredLinks = new Array();

        this.appendChild = Tree_appendChild;
        this.create = Tree_create;
        this.addHoveredLink = Tree_addHoveredLink;
        this.createHoveredLinks = Tree_createHoveredLinks;
    }

    /**
     * Adds a hovered link.
     * @param hoveredLink the hovered link
     */
    function Tree_addHoveredLink( hoveredLink )
    {
        this.m_HoveredLinks[this.m_HoveredLinks.length] = hoveredLink;
    }

    /**
     * Creates the hovered links.
     */
    function Tree_createHoveredLinks()
    {
        var i;
        for ( i=0; i < this.m_HoveredLinks.length; i++ )
        {
            this.m_HoveredLinks[i].create();
        }
    }

    /**
     * Appends a tree node to the tree.
     * @param node the tree node
     */
    function Tree_appendChild( node )
    {
        this.m_Children[this.m_Children.length] = node;
        node.setTree( this );
    }

    /**
     * Creates and shows the tree.
     */
    function Tree_create()
    {
        var i;

        var panel = document.createElement( 'DIV' );
        panel.className = 'Tree';

        for ( i=0; i < this.m_Children.length; i++ )
        {
            panel.appendChild( this.m_Children[i].create() );
        }

        document.body.appendChild( panel );

        this.createHoveredLinks();
    }

    /**
     * Creates a new tree node for the tree.
     */
    function TreeNode()
    {
        this.m_Panel = null;
        this.m_Icon = null;
        this.m_Link = null;

        this.m_Url = '#';
        this.m_Target = '';
        this.m_Text = '';
        this.m_LeafIcon = defaultLeafIcon;
        this.m_OpenedIcon = defaultOpenedNodeIcon;
        this.m_ClosedIcon = defaultClosedNodeIcon;
        this.m_Children = new Array();
        this.m_IsLeaf = true;
        this.m_IsOpened = false;
        this.m_Tree = null;

        this.setUrl = TreeNode_setUrl;
        this.setTarget = TreeNode_setTarget;
        this.setText = TreeNode_setText;
        this.setIcon = TreeNode_setIcon;
        this.setLeafIcon = TreeNode_setLeafIcon;
        this.setOpenedIcon = TreeNode_setOpenedIcon;
        this.setClosedIcon = TreeNode_setClosedIcon;
        this.setOpened = TreeNode_setOpened;
        this.isOpened = TreeNode_isOpened;
        this.getPanel = TreeNode_getPanel;
        this.setTree = TreeNode_setTree;
        this.getTree = TreeNode_getTree;
        this.getLink = TreeNode_getLink;
        this.appendChild = TreeNode_appendChild;
        this.create = TreeNode_create;
        this.createIcon = TreeNode_createIcon;
        this.createLink = TreeNode_createLink;
        this.openOrClose = TreeNode_openOrClose;
    }

    /**
     * Sets the url for the tree node. Used in <a href
     * @param url the url
     */
    function TreeNode_setUrl( url )
    {
        this.m_Url = url;
    }

    /**
     * Sets the target frame for the tree node.
     * @param target the target frame
     */
    function TreeNode_setTarget( target )
    {
        this.m_Target = target;
    }

    /**
     * Sets the tree node text.
     * @param text the text
     */
    function TreeNode_setText( text )
    {
        this.m_Text = text;
    }

    /**
     * Sets the leaf, opened and closed icon.
     * @param icon the icon
     */
    function TreeNode_setIcon( icon )
    {
        this.m_LeafIcon = icon;
        this.m_OpenedIcon = icon;
        this.m_ClosedIcon = icon;
    }

    /**
     * Sets the leaf icon.
     * @param icon the leaf icon
     */
    function TreeNode_setLeafIcon( icon )
    {
        this.m_LeafIcon = icon;
    }

    /**
     * Sets the opened icon.
     * @param icon the icon
     */
    function TreeNode_setOpenedIcon( icon )
    {
        this.m_OpenedIcon = icon;
    }

    /**
     * Sets the closed icon.
     * @param icon the icon
     */
    function TreeNode_setClosedIcon( icon )
    {
        this.m_ClosedIcon = icon;
    }

    /**
     * Sets if a tree node is opened.
     * @param opened true, if the tree node is opened
     */
    function TreeNode_setOpened( opened )
    {
        this.m_IsOpened = opened;
    }

    /**
     * Returns if the tree node is opened.
     * @return true, if the tree node is opened.
     */
    function TreeNode_isOpened()
    {
        return this.m_IsOpened;
    }

    /**
     * Returns the html panel of the tree node.
     * @return the panel
     */
    function TreeNode_getPanel()
    {
        return this.m_Panel;
    }

    /**
     * Sets the parent tree.
     * @param tree the parent tree
     */
    function TreeNode_setTree( tree )
    {
        this.m_Tree = tree;
    }

    /**
     * Returns the parent tree.
     * @return the parent tree
     */
    function TreeNode_getTree()
    {
        return this.m_Tree;
    }

    /**
     * Returns the link.
     * @return the link
     */
    function TreeNode_getLink()
    {
        return this.m_Link;
    }

    /**
     * Appends a tree node to the current node, current node is no more a leaf.
     * @param node the tree node
     */
    function TreeNode_appendChild( node )
    {
        this.m_Children[this.m_Children.length] = node;
        node.setTree( this.getTree() );
        this.m_IsLeaf = false;
    }

    /**
     * Creates the tree node.
     * @return the tree node html element
     */
    function TreeNode_create()
    {
        this.m_Panel = document.createElement( 'DIV' );
        this.m_Panel.className = 'TreeNode';
        var table = document.createElement( 'TABLE' );
        table.className = 'TreeNode';
        table.cellPadding = '0';
        table.cellSpacing = '0';

        var row = table.insertRow( table.rows.length );
        row.className = 'TreeNode';

        var cell = row.insertCell( row.cells.length );
        cell.className = 'TreeNode';
        this.m_Icon = this.createIcon();
        cell.appendChild( this.m_Icon );

        cell = row.insertCell( row.cells.length );
        cell.className = 'TreeNode';
        this.m_Link = this.createLink();
        cell.appendChild( this.m_Link );

        this.m_Panel.appendChild( table );

        if ( this.isOpened() )
        {
            for ( i=0; i < this.m_Children.length; i++ )
            {
                this.m_Panel.appendChild( this.m_Children[i].create() );
            }
        }

        return this.m_Panel;
    }

    /**
     * Creates an icon for the tree node.
     * @return the icon html element
     */
    function TreeNode_createIcon()
    {
        var icon = document.createElement( 'IMG' );
        if ( this.m_IsLeaf )
        {
            icon.src = this.m_LeafIcon;
        }
        else if ( !this.m_IsLeaf && this.m_IsOpened )
        {
            icon.src = this.m_OpenedIcon;
        }
        else if ( !this.m_IsLeaf && !this.m_IsOpened )
        {
            icon.src = this.m_ClosedIcon;
        }

        return icon;
    }

    /**
     * Creates a link for the tree node.
     * @return the link html element
     */
    function TreeNode_createLink()
    {
        var link = document.createElement( 'A' );
        link.href = this.m_Url;
        link.target = this.m_Target;
        link.treeNode = this;

        if ( this.m_IsLeaf )
        {
            link.className = 'TreeLeaf';
        }
        else if ( !this.m_IsLeaf && this.m_IsOpened )
        {
            link.className = 'TreeOpenedNode';
        }
        else if ( !this.m_IsLeaf && !this.m_IsOpened )
        {
            link.className = 'TreeClosedNode';
        }

        if ( !this.m_IsLeaf )
        {
            link.onclick = function() { this.treeNode.openOrClose(); };
        }
        link.onfocus = function() { this.blur(); };

        link.appendChild( document.createTextNode( this.m_Text ) );

        return link;
    }

    /**
     * Open a menu.
     */
    function TreeNode_openOrClose()
    {
        if ( this.m_IsOpened )
        {
            var i;
            for ( i=0; i < this.m_Children.length; i++ )
            {
                this.m_Panel.removeChild( this.m_Children[i].getPanel() );
                document.body.removeChild( this.m_Children[i].getLink().hoverContainer );
            }
            this.setOpened( false );
            this.m_Icon.src = this.m_ClosedIcon;
        }
        else
        {
            var i;
            for ( i=0; i < this.m_Children.length; i++ )
            {
                this.m_Panel.appendChild( this.m_Children[i].create() );
            }
            this.setOpened( true );
            this.m_Icon.src = this.m_OpenedIcon;
        }

        this.getTree().createHoveredLinks();
    }
//-->
