function TreeNode()
{
	var element;
	var nodes;
	var text;
	var parent;
	var childNodesTable;
	var isExpanded;
	var parentNode;
	var isVisible;
	var isSelected;
	var treeView;
	var treeNode;
	var imageIndex;

	imageIndex = 0;
	
	text = '';

	isExpanded = false;

	isSelected = false;

	isVisible = false;

	nodes = new Array();

	treeNode = this;

	this.Font = 'normal 8pt Verdana';

	this.BackgroundColor = 'white';
	
	this.SelectedBackgroundColor = '#CAD3FF';

	this.Color = '#5F5F5F';
	
	this.SelectedColor = '#000000';

	this.BorderColor = 'white';
	
	this.SelectedBorderColor = '#5469CA';

	this.Tag = null;
	
	// Events
	var nodeAddedEvent;
	var nodeCollapsedEvent;
	var nodeExpandedEvent;

	nodeAddedEvent = new Event('NodeAdded', null);
	nodeCollapsedEvent = new Event('NodeCollapsed', null);
	nodeExpandedEvent = new Event('NodeExpanded', null);
	
	this.GetProperty = function(property)
	{
		if (property == 'TreeView')
		{
			return treeView;
		}
		else
		{
			return null;
		}
	}

	var NodeAdded = function()
	{
		nodeAddedEvent.fire();
	}

	var NodeCollapsed = function()
	{
		nodeCollapsedEvent.fire();
	}

	var NodeExpanded = function()
	{
		nodeExpandedEvent.fire();
	}

	this.Subscribe = function(type, fn, obj, override)
	{
		if (type == nodeAddedEvent.type)
		{
			nodeAddedEvent.subscribe(fn, obj, override);
		}

		if (type == nodeCollapsedEvent.type)
		{
			nodeCollapsedEvent.subscribe(fn, obj, override);
		}

		if (type == nodeExpandedEvent.type)
		{
			nodeExpandedEvent.subscribe(fn, obj, override);
		}
	}

	this.AddNode = function(node)
	{
		var r;
		var c;
		var n;

		node.SetTreeView(treeView);

		node.SetParentNode(this);

		AddElement(nodes, node);

		if (element)
		{
			if (isExpanded)
			{
				element.rows[1].cells[0].innerHTML = '&nbsp;';

				r = childNodesTable.insertRow(-1);

				c = r.insertCell(-1);

				node.SetParent(c);

				node.DrawNode();
			}

			RefreshState();
		}
		
		node.Subscribe('NodeAdded', treeView.OnNodeAdded, this, true);
		node.Subscribe('NodeCollapsed', treeView.OnNodeCollapsed, this, true);
		node.Subscribe('NodeExpanded', treeView.OnNodeExpanded, this, true);

		NodeAdded();
	}

	this.DrawNode = function()
	{
		element = RenderTable();
		
		parent.appendChild(element);
		
		isVisible = true;
	}

	var RefreshState = function()
	{
		if (isVisible)
		{
			if (nodes.length == 0)
			{
				element.rows[0].cells[0].style.backgroundImage = 'url(' + treeView.GetProperty('EmptyNodeImage').src + ')';
				
				element.rows[0].cells[0].style.cursor = 'default';
			}
			else
			{
				if (isExpanded)
				{
					element.rows[0].cells[0].style.backgroundImage = 'url(' + treeView.GetProperty('ExpandedNodeImage').src + ')';
				}
				else
				{
					element.rows[0].cells[0].style.backgroundImage = 'url(' + treeView.GetProperty('CollapsedNodeImage').src + ')';
				}
				
				element.rows[0].cells[0].style.cursor = 'hand';
	    
			    if (! element.rows[0].cells[0].style.cursor)
			    {
					element.rows[0].cells[0].style.cursor = 'pointer';
			    }
			}
		}
	}

	var RenderTable = function()
	{
		var t;
		var r;
		var c;
		
		var t1;
		var r1;
		var c1;
		
		var t2;
		var r2;
		var c2;

		t = document.createElement('table');
		
		//t.style.backgroundColor = 'orangered';

		t.style.position = 'relative';

		t.style.left = 0;

		t.style.top = 0;

		t.style.width = '100%';

		t.cellSpacing = 0;

	    t.cellPadding = 0;

			r = t.insertRow(-1);

				// State cell
				c = r.insertCell(-1);
				c.style.width = '15';
				c.style.verticalAlign = 'middle';
				c.style.backgroundRepeat = 'no-repeat';

				if (nodes.length == 0)
				{
					c.style.backgroundImage = 'url(' + treeView.GetProperty('EmptyNodeImage').src + ')';
					
				}
				else
				{
					if (isExpanded)
					{
						c.style.backgroundImage = 'url(' + treeView.GetProperty('ExpandedNodeImage').src + ')';
					}
					else
					{
						c.style.backgroundImage = 'url(' + treeView.GetProperty('CollapsedNodeImage').src + ')';
					}
					
					c.style.cursor = 'hand';
	    
				    if (! c.style.cursor)
				    {
						c.style.cursor = 'pointer';
				    }
				}

				c.onclick = ChangeExpandedState;

				// Container cell
				c = r.insertCell(-1);
				c.style.verticalAlign = 'middle';

					t1 = document.createElement('table');
					t1.style.position = 'relative';
					t1.style.left = 0;
					t1.style.top = 0;
					t1.style.height = '100%';
					t1.style.width = '100%';
					t1.cellSpacing = 0;
					t1.cellPadding = 0;

					r1 = t1.insertRow(-1);

					// Image cell
					c1 = r1.insertCell(-1);

					if (imageIndex >= 0)
					{
						c1.style.width = '20';
					}
					else
					{
						c1.style.width = '0';
					}

					c1.style.verticalAlign = 'middle';
					c1.style.backgroundRepeat = 'no-repeat';
					
					if (imageIndex >= 0)
					{
						c1.style.backgroundImage = 'url(' + treeView.Images(imageIndex).src + ')';
					}
					c1.onclick = SelectNode;

					c1.style.cursor = 'hand';

				    if (! c1.style.cursor)
				    {
						c1.style.cursor = 'pointer';
				    }

					// Label cell
					c1 = r1.insertCell(-1);
					c1.style.height = '20';
					c1.style.verticalAlign = 'middle';
					c1.style.cursor = 'hand';

				    if (! c1.style.cursor)
				    {
						c1.style.cursor = 'pointer';
				    }
					
					c1.onclick = SelectNode;
					
						t2 = document.createElement('table');
						t2.style.position = 'relative';
						t2.style.left = 0;
						t2.style.top = 0;
						t2.style.height = '100%';
						t2.cellSpacing = 0;
						t2.cellPadding = 0;
						t2.style.color = '#282e4c';
						t2.style.backgroundColor = treeNode.BackgroundColor;
						t2.style.borderStyle = 'solid';
						t2.style.borderWidth = '1';
						t2.style.borderColor = treeNode.BorderColor;

						r2 = t2.insertRow(-1);

						c2 = r2.insertCell(-1);
						c2.style.verticalAlign = 'middle';
						
						if (imageIndex >= 0)
						{
							c2.style.lineHeight = '12px';
						}
						else
						{
							c2.style.lineHeight = '0';
						}
						
						//c2.innerHTML = '&nbsp;';

						c2 = r2.insertCell(-1);
						//c2.style.backgroundColor = 'forestgreen';
						c2.style.verticalAlign = 'middle';
						c2.style.font = treeNode.Font;
						c2.style.lineHeight = '12px';
						c2.innerHTML = text;

						c2 = r2.insertCell(-1);
						c2.style.verticalAlign = 'middle';
						c2.style.lineHeight = '12px';
						//c2.innerHTML = '&nbsp;';

					c1.appendChild(t2);

					c.appendChild(t1);

			r = t.insertRow(-1);

				// State cell
				c = r.insertCell(-1);
				c.style.verticalAlign = 'middle';

				// Container cell
				c = r.insertCell(-1);

					childNodesTable = document.createElement('table');
					childNodesTable.style.position = 'relative';
					childNodesTable.style.left = 0;
					childNodesTable.style.top = 0;
					childNodesTable.style.height = '100%';
					childNodesTable.style.width = '100%';
					childNodesTable.cellSpacing = 0;
					childNodesTable.cellPadding = 0;

					r2 = childNodesTable.insertRow(-1);

					c2 = r2.insertCell(-1);

					c.appendChild(childNodesTable);

	    return t;
	}

	this.GetImageIndex = function()
	{
		return imageIndex;
	}

	this.SetImageIndex = function(index)
	{
		imageIndex = index;
	}

	this.SetParent = function(n)
	{
		parent = n;
	}

	this.Nodes = function(index)
	{
		return nodes[index];
	}
	
	this.NodeCount = function()
	{
		return nodes.length;
	}

	this.SetText = function(n)
	{
		text = n;
	}
	
	this.GetText = function()
	{
		return text;
	}

	this.GetParentNode = function()
	{
		return parentNode;
	}

	this.SetParentNode = function(n)
	{
		parentNode = n;
	}

	this.GetTreeView = function()
	{
		return treeView;
	}

	this.SetTreeView = function(n)
	{
		treeView = n;
	}

	this.HideNode = function()
	{
		element = null;

		isVisible = false;
	}

	this.SetIsExpanded = function(n)
	{
		SetIsExpanded(n);
	}
	
	var ChangeExpandedState = function()
	{
		SetIsExpanded(! isExpanded);
	}

	var SelectNode = function()
	{
		treeView.SelectNode(treeNode);
	}

	this.SelectNode = function()
	{
		var t;

		isSelected = true;

		if (isVisible)
		{
			t = element.rows[0].cells[1].childNodes[0].rows[0].cells[1].childNodes[0];

			t.style.backgroundColor = this.SelectedBackgroundColor;
			t.style.color = this.SelectedColor;
			t.style.borderStyle = 'solid';
			t.style.borderWidth = '1';
			t.style.borderColor = this.SelectedBorderColor;
		}
	}

	this.DeselectNode = function(node)
	{
		var t;

		isSelected = false;

		if (isVisible)
		{
			t = element.rows[0].cells[1].childNodes[0].rows[0].cells[1].childNodes[0];

			t.style.backgroundColor = this.BackgroundColor;
			t.style.color = this.Color;
			t.style.borderStyle = 'solid';
			t.style.borderWidth = '1';
			t.style.borderColor = this.BorderColor;
		}
	}

	var SetIsExpanded = function(n)
	{
		var i;
		var r;
		var c;

		if (isExpanded != n)
		{
			if (nodes.length > 0)
			{
				isExpanded = n;
		
				if (isVisible)
				{
					if (isExpanded)
					{
						if (nodes.length > 0)
						{
							element.rows[1].cells[0].innerHTML = '&nbsp;';
						}
		
						for (i = 0; i < nodes.length; i ++)
						{
							r = childNodesTable.insertRow(-1);
		
							c = r.insertCell(-1);
		
							nodes[i].SetParent(c);
		
							nodes[i].DrawNode();
						}
						
						NodeExpanded();
					}
					else
					{
						for (i = 0; i < nodes.length; i ++)
						{
							nodes[i].SetIsExpanded(false);
							
							nodes[i].HideNode();
							
							if (treeView.GetProperty('SelectedNode') == nodes[i])
							{
								treeView.SelectNode(null);
							}
						}
		
						for (i = childNodesTable.rows.length - 1; i > 0; i --)
						{
							childNodesTable.deleteRow(i);
						}
		
						element.rows[1].cells[0].innerHTML = '';

						NodeCollapsed();
					}

					RefreshState();
				}
			}
		}
	}

	var DeleteElement = function(array, i)
    {
	    var j;
    	
	    try {delete array[i]} catch(e) { }
    	
	    for (j = i + 1; j < array.length; j ++) array[j - 1] = array[j];

	    array.length = array.length - 1;
    }

    var AddElement = function(array, element)
    {
	    array.length = array.length + 1;

	    array[array.length - 1] = element;
    }
}
