function TreeView()
{
	var D;
	var D0;
	var D2;
	var D3;
	
	var T0;
	var T1;
	var T4;

	// Properties	
	var P0 = 0;											// Left
	var P1 = 0;											// Top
	var P2 = 100;										// Width
	var P3 = 100;										// Height
	var P4 = 100;										// Parent
	var P5 = new Array();								// Nodes
	var P6 = null;										// SelectedNode
	var P7 = 'absolute';								// Position
	var P8 = new Array();								// Images
	var P9 = false;										// AutoSizeHeight
	var P10 = new Image();								// ExpandedNodeImage
	var P11 = new Image();								// CollapsedNodeImage
	var P12 = new Image();								// EmptyNodeImage
	var P13 = SystemColor.ControlBorder;				// BorderColor
	var P14 = SystemColor.ScrollBarBackgroundColor;		// ScrollBarBackgroundColor
	var P15 = SystemColor.ScrollBarColor;				// ScrollBarColor
	var P16 = SystemColor.ScrollBarBorderColor;			// ScrollBarBorderColor
	var P17 = SystemColor.ScrollBarBorderColor;			// ScrollBarMarkerColor
	var P18 = VSCROLLBAR_WIDTH;							// VerticalScrollBarWidth
	var P19 = HSCROLLBAR_HEIGHT;						// HorizontalScrollBarHeight

	// Events
	var E0 = new Event('NodeSelected', null);

	P10.src = WEB_SITE + IMAGES_DIRECTORY + EXPANDED_NODE_IMAGE;

	P11.src = WEB_SITE + IMAGES_DIRECTORY + COLLAPSED_NODE_IMAGE;

	P12.src = WEB_SITE + IMAGES_DIRECTORY + EMPTY_NODE_IMAGE;

	D = this;
	
	this.GetProperty = function(property)
	{
		if (property == 'ExpandedNodeImage')
		{
			return P10;
		}
		else if (property == 'CollapsedNodeImage')
		{
			return P11;
		}
		else if (property == 'EmptyNodeImage')
		{
			return P12;
		}
		else if (property == 'SelectedNode')
		{
			return P6;
		}
		else if (property == 'NodeCount')
		{
			return P5.length;
		}
		else
		{
			return null;
		}
	}

	this.SetProperty = function(property, value)
	{
		var i;

		if (property == 'AutoSizeHeight')
		{
			P9 = value;
		}
		else if (property == 'Left')
		{
			P0 = value;
			
			if (D0)
			{
				D0.style.left = P0;
			}
		}
		else if (property == 'Top')
		{
			P1 = value;
			
			if (D0)
			{
				D0.style.top = P1;
			}
		}
		else if (property == 'Width')
		{
			P2 = value;
			
			if (D0)
			{
				D0.style.width = P2;
				
				if (D2)
				{
					D2.style.width = P2 - 2;
				}
			}
		}
		else if (property == 'Height')
		{
			P3 = value;
			
			if (D0)
			{
				if (! P9)
				{
					D0.style.height = P3;
				}
				
				if (D2)
				{
					if (! P9)
					{
						D2.style.height = P3 - 2;
					}
				}
			}
		}
		else if (property == 'Parent')
		{
			if (P4)
			{
				if (D0)
				{
					P4.removeChild(D0);
				}
			}
			
			P4 = value;
		}
		else if (property == 'Position')
		{
			P7 = value;
			
			if (D0)
			{
				D0.style.position = P7;
			}
		}
		else if (property == 'BorderColor')
		{
			P13 = value;
			
			if (D0)
			{
				D0.style.borderColor = P13;
			}
		}
		else if (property == 'ScrollBarBackgroundColor')
		{
			P14 = value;
			
			if (H)
			{
				H.BackgroundColor = P14;
			}
			
			if (V)
			{
				V.BackgroundColor = P14;
			}
		}
		else if (property == 'ScrollBarColor')
		{
			P15 = value;
			
			if (H)
			{
				H.ScrollbarColor = P15;
			}
			
			if (V)
			{
				V.ScrollbarColor = P15;
			}
		}
		else if (property == 'ScrollBarBorderColor')
		{
			P16 = value;
			
			if (H)
			{
				H.BorderColor = P16;
			}
			
			if (V)
			{
				V.BorderColor = P16;
			}
		}
		else if (property == 'ScrollBarMarkerColor')
		{
			P17 = value;
			
			if (H)
			{
				H.ScrollButtonColor = P17;
			}
			
			if (V)
			{
				V.ScrollButtonColor = P17;
			}
		}
		else if (property == 'VerticalScrollBarWidth')
		{
			P18 = value;
		}
		else if (property == 'HorizontalScrollBarHeight')
		{
			P19 = value;
		}
	}

	var NodeSelected = function()
	{
		E0.fire();
	}

	this.AddImage = function(source)
	{
		var n;

		n = new Image();

		n.src = source;

		Collection.AddElement(P8, n);
	}
	
	this.Images = function(index)
	{
		return P8[index];
	}

	this.Subscribe = function(type, fn, obj, override)
	{
		if (type == E0.type)
		{
			E0.subscribe(fn, obj, override);
		}
	}

	this.Initialize = function()
	{
		var r;
		var c;
		var r1;
		var c1;
		
		D0 = document.createElement('div');
		D0.style.position = P7;
		D0.style.left = P0;
		D0.style.top = P1;
		D0.style.width = P2;
		if (! P9) {D0.style.height = P3;}
		D0.style.backgroundColor = '#FFFFFF';
		D0.style.overflow = 'hidden';
		D0.style.borderWidth = 1;
		D0.style.borderStyle = 'solid';
		D0.style.borderColor = P13;
		D0.className = 'divElement';

			T0 = document.createElement('table');
			T0.style.position = 'relative';
			T0.style.height = '100%';
			T0.style.width = '100%';
			T0.cellSpacing = 0;
			T0.cellPadding = 0;
			//T0.style.backgroundColor = 'lime';

				r = T0.insertRow(-1);

				c = r.insertCell(-1);

					T1 = document.createElement('table');
					//T1.style.backgroundColor = 'forestgreen';
					T1.style.position = 'relative';
					T1.style.width = '100%';
					if (! P9) {T1.style.height = '100%';}
					T1.cellSpacing = 0;
					T1.cellPadding = 0;

					r1 = T1.insertRow(-1);

					c1 = r1.insertCell(-1);
					c1.style.verticalAlign = 'top';

						D2 = document.createElement('div');
						//D2.style.backgroundColor = 'maroon';
						D2.style.position = 'relative';
						D2.style.top = 0;
						D2.style.left = 0;
						D2.style.width = P2 - 2;
						if (! P9) {D2.style.height = P3 - 2;}
						D2.style.overflow = 'hidden';
						D2.className = 'divElement';
						
							D3 = document.createElement('div');
							//D2.style.backgroundColor = 'maroon';
							D3.style.position = 'relative';
							D3.style.top = 0;
							D3.style.left = 0;
							D3.style.width = 10000;
							if (! P9) {D3.style.height = 10000;}
							D3.style.overflow = 'hidden';
							
							D2.appendChild(D3);

						c1.appendChild(D2);
					
					c.appendChild(T1);
				
			D0.appendChild(T0);
			
			P4.appendChild(D0);
			
			T4 = RenderTable();

			D3.appendChild(T4);
	}

	function MoveArea(x, y)
	{
		T4.style.left = x;

		T4.style.top = y;
	}

	this.SelectNode = function(node)
	{
		var i;

		if (P6)
		{
			P6.DeselectNode();
		}

		P6 = null;

		if (node)
		{
			node.SelectNode();
		}

		P6 = node;
		
		NodeSelected();
	}

	this.AddNode = function(node)
	{
		var r;
		var c;
		var n;

		node.SetTreeView(D);

		Collection.AddElement(P5, node);

		r = T4.insertRow(-1);

		c = r.insertCell(-1);

		node.SetParent(c);

		node.DrawNode();

		node.Subscribe('NodeAdded', OnNodeAdded, this, true);
		
		node.Subscribe('NodeExpanded', OnNodeExpanded, this, true);
		
		node.Subscribe('NodeCollapsed', OnNodeCollapsed, this, true);
		
		OnNodeAdded();
	}

	this.OnNodeAdded = function()
	{
		OnNodeAdded();
	}

	this.OnNodeExpanded = function()
	{
		OnNodeExpanded();
	}
	
	this.OnNodeCollapsed = function()
	{
		OnNodeCollapsed();
	}

	var OnNodeAdded = function()
	{
		CalculateScrollBars();
	}
	
	var OnNodeExpanded = function()
	{
		CalculateScrollBars();
	}
	
	var OnNodeCollapsed = function()
	{
		CalculateScrollBars();
	}
	
	var CalculateScrollBars = function()
	{
		var w0;
		var w1;
		var h0;
		var h1;
		var v_p;		// Is v-bar present
		var h_p;		// Is h-bar present
		var v_n;		// Is v-bar needed
		var h_n;		// Is h-bar needed

		v_p = (T1.rows[0].cells.length > 1) ? true : false;

		h_p = (T0.rows.length > 1) ? true : false;

		h0 = parseInt(T4.offsetHeight);
		h1 = (D2.offsetHeight) ? D2.offsetHeight : parseInt(D2.style.pixelHeight);

		w0 = parseInt(T4.offsetWidth);
		w1 = (D2.offsetWidth) ? D2.offsetWidth : parseInt(D2.style.pixelWidth);

		if (! v_p && ! h_p)
		{
			if (w0 <= (w1 - (P18 + 2)))
			{
				if (h0 <= (h1 - (P19 + 2)))
				{
					h_n = false;
					
					v_n = false;
				}
				else if (((h1 - (P19 + 2)) < h0) && (h0 <= h1))
				{
					h_n = false;
					
					v_n = false;
				}
				else if (h1 < h0)
				{
					h_n = false;
					
					v_n = true;
				}
			}
			else if (((w1 - (P18 + 2)) < w0) && (w0 <= w1))
			{
				if (h0 <= (h1 - (P19 + 2)))
				{
					h_n = false;
					
					v_n = false;
				}
				else if (((h1 - (P19 + 2)) < h0) && (h0 <= h1))
				{
					h_n = false;
					
					v_n = false;
				}
				else if (h1 < h0)
				{
					h_n = true;
					
					v_n = true;
				}
			}
			else if (w1 < w0)
			{
				if (h0 <= (h1 - (P19 + 2)))
				{
					h_n = true;
					
					v_n = false;
				}
				else if (((h1 - (P19 + 2)) < h0) && (h0 <= h1))
				{
					h_n = true;
					
					v_n = true;
				}
				else if (h1 < h0)
				{
					h_n = true;
					
					v_n = true;
				}
			}
		}
		else if (! v_p && h_p)
		{
			if (w0 <= (w1 - (P18 + 2)))
			{
				if (h0 <= h1)
				{
					h_n = false;
					
					v_n = false;
				}
				else if ((h1 < h0) && (h0 <= (h1 + (P19 + 2))))
				{
					h_n = false;
					
					v_n = false;
				}
				else if ((h1 + (P19 + 2)) < h0)
				{
					h_n = false;
					
					v_n = true;
				}
			}
			else if (((w1 - (P18 + 2)) < w0) && (w0 <= w1))
			{
				if (h0 <= h1)
				{
					h_n = false;
					
					v_n = false;
				}
				else if ((h1 < h0) && (h0 <= (h1 + (P19 + 2))))
				{
					h_n = false;
					
					v_n = false;
				}
				else if ((h1 + (P19 + 2)) < h0)
				{
					h_n = true;
					
					v_n = true;
				}
			}
			else if (w1 < w0)
			{
				if (h0 <= h1)
				{
					h_n = true;
					
					v_n = false;
				}
				else if ((h1 < h0) && (h0 <= (h1 + (P19 + 2))))
				{
					h_n = true;
					
					v_n = true;
				}
				else if ((h1 + (P19 + 2)) < h0)
				{
					h_n = true;
					
					v_n = true;
				}
			}
		}
		else if (v_p && ! h_p)
		{
			if (w0 <= w1)
			{
				if (h0 <= (h1 - (P19 + 2)))
				{
					h_n = false;
					
					v_n = false;
				}
				else if (((h1 - (P19 + 2)) < h0) && (h0 <= h1))
				{
					h_n = false;
					
					v_n = false;
				}
				else if (h1 < h0)
				{
					h_n = false;
					
					v_n = true;
				}
			}
			else if ((w1 < w0) && (w0 <= (w1 + (P18 + 2))))
			{
				if (h0 <= (h1 - (P19 + 2)))
				{
					h_n = false;
					
					v_n = false;
				}
				else if (((h1 - (P19 + 2)) < h0) && (h0 <= h1))
				{
					h_n = false;
					
					v_n = false;
				}
				else if (h1 < h0)
				{
					h_n = true;
					
					v_n = true;
				}
			}
			else if ((w1 + (P18 + 2)) < w0)
			{
				if (h0 <= (h1 - (P19 + 2)))
				{
					h_n = true;
					
					v_n = false;
				}
				else if (((h1 - (P19 + 2)) < h0) && (h0 <= h1))
				{
					h_n = true;
					
					v_n = true;
				}
				else if (h1 < h0)
				{
					h_n = true;
					
					v_n = true;
				}
			}
		}
		else if (v_p && h_p)
		{
			if (w0 <= w1)
			{
				if (h0 <= h1)
				{
					h_n = false;
					
					v_n = false;
				}
				else if ((h1 < h0) && (h0 <= (h1 + (P19 + 2))))
				{
					h_n = false;
					
					v_n = false;
				}
				else if ((h1 + (P19 + 2)) < h0)
				{
					h_n = false;
					
					v_n = true;
				}
			}
			else if ((w1 < w0) && (w0 <= (w1 + (P18 + 2))))
			{
				if (h0 <= h1)
				{
					h_n = false;
					
					v_n = false;
				}
				else if ((h1 < h0) && (h0 <= (h1 + (P19 + 2))))
				{
					h_n = false;
					
					v_n = false;
				}
				else if ((h1 + (P19 + 2)) < h0)
				{
					h_n = true;
					
					v_n = true;
				}
			}
			else if ((w1 + (P18 + 2)) < w0)
			{
				if (h0 <= h1)
				{
					h_n = true;
					
					v_n = false;
				}
				else if ((h1 < h0) && (h0 <= (h1 + (P19 + 2))))
				{
					h_n = true;
					
					v_n = true;
				}
				else if ((h1 + (P19 + 2)) < h0)
				{
					h_n = true;
					
					v_n = true;
				}
			}
		}
		
		if (P9) {v_n = false;}
		
		if (!v_n && !v_p && !h_n && !h_p)
		{
		}
		else if (!v_n && !v_p && !h_n && h_p)
		{
			RemoveHorizontalScrollBar();
		}
		else if (!v_n && !v_p && h_n && !h_p)
		{
			AddHorizontalScrollBar();
		}
		else if (!v_n && !v_p && h_n && h_p)
		{
		}
		else if (!v_n && v_p && !h_n && !h_p)
		{
			RemoveVerticalScrollBar();
		}
		else if (!v_n && v_p && !h_n && h_p)
		{
			RemoveVerticalScrollBar();
			
			RemoveHorizontalScrollBar();
		}
		else if (!v_n && v_p && h_n && !h_p)
		{
			RemoveVerticalScrollBar();
			
			AddHorizontalScrollBar();
		}
		else if (!v_n && v_p && h_n && h_p)
		{
			RemoveVerticalScrollBar();
		}
		else if (v_n && !v_p && !h_n && !h_p)
		{
			AddVerticalScrollBar();
		}
		else if (v_n && !v_p && !h_n && h_p)
		{
			AddVerticalScrollBar();
			
			RemoveHorizontalScrollBar();
		}
		else if (v_n && !v_p && h_n && !h_p)
		{
			AddVerticalScrollBar();

			AddHorizontalScrollBar();
		}
		else if (v_n && !v_p && h_n && h_p)
		{
			AddVerticalScrollBar();
		}
		else if (v_n && v_p && !h_n && !h_p)
		{
		}
		else if (v_n && v_p && !h_n && h_p)
		{
			RemoveHorizontalScrollBar();
		}
		else if (v_n && v_p && h_n && !h_p)
		{
			AddHorizontalScrollBar();
		}
		else if (v_n && v_p && h_n && h_p)
		{
		}
		
		// Adapt width of the h-bar
		if (h_n)
		{
			if (v_n)
			{
				H.SetWidth(((D5.offsetWidth) ? D5.offsetWidth : parseInt(D5.style.pixelWidth)) - (P18 + 2));
			}
			else
			{
				H.SetWidth((D5.offsetWidth) ? D5.offsetWidth : parseInt(D5.style.pixelWidth));
			}
		}

		var h2;
		var h3;
		var w2;
		var w3;
		var p0;
		var x;
		var x0;
		var y;
		var d;

		// Recalculate parameters of the v-scroll bar.
		if (v_n)
		{
			h2 = parseInt(T4.offsetHeight);

			h3 = ((D2.offsetHeight) ? D2.offsetHeight : parseInt(D2.style.pixelHeight));

			y0 = parseInt(T4.offsetTop);
			
			if (y0 < 0)
			{
				d = h2 - ((- y0) + h3);

				if (d < 0)
				{
					y0 = y0 + Math.min(- y0, - d);
				}
			}
			
			p0 = h2 - ((- y0) + Math.max(0, (h2 - h3 - (- y0))));

			p0 = Math.min(100, p0 * 100 / h2);

			y0 = - (y0 * 100 / h2);

			V.SetParameters(y0, p0);
		}
		else
		{
			MoveArea(T4.offsetLeft, 0);
		}

		// Recalculate parameters of the h-scroll bar.
		if (h_n)
		{
			w2 = parseInt(T4.offsetWidth);
			
			w3 = ((D2.offsetWidth) ? D2.offsetWidth : parseInt(D2.style.pixelWidth));

			x0 = parseInt(T4.offsetLeft);
			
			if (x0 < 0)
			{
				d = w2 - ((- x0) + w3);

				if (d < 0)
				{
					x0 = x0 + Math.min(- x0, - d);
				}
			}
			
			p0 = w2 - ((- x0) + Math.max(0, (w2 - w3 - (- x0))));

			p0 = Math.min(100, p0 * 100 / w2);

			x0 = - (x0 * 100 / w2);

			H.SetParameters(x0, p0);
		}
		else
		{
			MoveArea(0, T4.offsetTop);
		}
	}

	var AddHorizontalScrollBar = function()
	{
		var c;
		var r;

		r = T0.insertRow(-1);

		c = r.insertCell(-1);

		c.style.height = (P19 + 2);

		if (! P9) {D2.style.height = parseInt(D2.style.height) - (P19 + 2);}
		
		D5 = document.createElement('div');
		D5.style.position = 'relative';
		D5.style.width = '100%';
		D5.style.height = (P19 + 2);
		D5.style.overflow = 'hidden';
		D5.className = 'divElement';
		
		c.appendChild(D5);
		
			H = new HorizontalScrollBar();
			//H.BackgroundColor = P14;
			//H.ScrollbarColor = P15;
			//H.BorderColor = P16;
			//H.ScrollButtonColor = P17;
			H.Left = 0;
			H.Top = 0;
			H.Height = '100%';
			H.SetWidth('100%');
			H.BackgroundColor = 'white';
			H.Parent = D5;
			H.Initialize();
			
			H.Subscribe('Scroll', OnHorizontalScroll, this, true);
	}
	
	var RemoveHorizontalScrollBar = function()
	{
		T0.deleteRow(1);

		if (! P9) {D2.style.height = parseInt(D2.style.height) + (P19 + 2);}
	}

	var AddVerticalScrollBar = function()
	{
		var c;
		var r;

		c = T1.rows[0].insertCell(-1);

		c.style.width = (P18 + 2);

		D2.style.width = parseInt(D2.style.width) - (P18 + 2);

		D4 = document.createElement('div');
		D4.style.position = 'relative';
		D4.style.width = (P18 + 2);
		D4.style.height = '100%';
		D4.style.overflow = 'hidden';
		D4.className = 'divElement';
		
		c.appendChild(D4);

			V = new VerticalScrollBar();
			V.BackgroundColor = P14;
			V.ScrollbarColor = P15;
			V.BorderColor = P16;
			V.ScrollButtonColor = P17;
			V.Left = 0;
			V.Top = 0;
			V.Height = '100%';
			V.Width = '100%';
			//V.BackgroundColor = 'white';
			V.Parent = D4;
			V.Initialize();

			V.Subscribe('Scroll', OnVerticalScroll, this, true);
	}

	var RemoveVerticalScrollBar = function()
	{
		T1.rows[0].deleteCell(1);

		D2.style.width = parseInt(D2.style.width) + (P18 + 2);
	}
	
	var OnVerticalScroll = function()
	{
		var h2;
		var y;

		y = V.GetPosition();

		h2 = parseInt(T4.offsetHeight);

		y = - y * h2 / 100;

		MoveArea(T4.offsetLeft, y);
	}

	var MoveArea = function(x, y)
	{
		T4.style.left = x;

		T4.style.top = y;
	}

	var OnHorizontalScroll = function()
	{
		var w2;
		var x;

		x = H.GetPosition();

		w2 = parseInt(T4.offsetWidth);

		x = - x * w2 / 100;

		MoveArea(x, T4.offsetTop);
	}

	var RenderTable = function()
	{
		var t;
		var r;
		var c;

		t = document.createElement('table');

		t.style.position = 'relative';

		t.style.left = 0;

		t.style.top = 0;

		t.cellSpacing = 0;

	    t.cellPadding = 0;

		r = t.insertRow(-1);

		c = r.insertCell(-1);

	    return t;
	}

	this.Nodes = function(index)
	{
		return P5[index];
	}
}
