////////////////////////////////////////////////////////////////////////////////////////////
// Drawing client-side script
////////////////////////////////////////////////////////////////////////////////////////////

addNamespace("Drawing");

////////////////////////////////////////////////////////////////////////////////////////////

Drawing.LineStyleClass = Class.create();
Drawing.LineStyleClass.prototype =
{
	_none: 0,
	_solid: 1,
	_dotted: 2,
		
	initialize: function(lineStyle)
	{
		this._value = lineStyle;
	},
	
	None: function()
	{
		return new Drawing.LineStyleClass(this._none);
	},
	
	Solid: function()
	{
		return new Drawing.LineStyleClass(this._solid);
	},
	
	Dotted: function()
	{
		return new Drawing.LineStyleClass(this._dotted);
	},
	
	toString: function(vml)
	{
		if (vml)
		{
			if (this._value == this._none)
				return "none";
			else if (this._value == this._dotted)
				return "dot";
		}
		else
		{
			if (this._value == this._none)
				return "none";
			else if (this._value == this._dotted)
				return "dotted";
		}
		
		return "solid";
	}
};
Drawing.LineStyle = new Drawing.LineStyleClass();

////////////////////////////////////////////////////////////////////////////////////////////

Drawing.WebSafeColors = new Array("330000","333300","336600","339900","33CC00","33FF00","66FF00","66CC00","669900","666600","663300","660000","FF0000","FF3300","FF6600","FF9900","FFCC00","FFFF00",
			"330033","333333","336633","339933","33CC33","33FF33","66FF33","66CC33","669933","666633","663333","660033","FF0033","FF3333","FF6633","FF9933","FFCC33","FFFF33",
			"330066","333366","336666","339966","33CC66","33FF66","66FF66","66CC66","669966","666666","663366","660066","FF0066","FF3366","FF6666","FF9966","FFCC66","FFFF66",
			"330099","333399","336699","339999","33CC99","33FF99","66FF99","66CC99","669999","666699","663399","660099","FF0099","FF3399","FF6699","FF9999","FFCC99","FFFF99",
			"3300CC","3333CC","3366CC","3399CC","33CCCC","33FFCC","66FFCC","66CCCC","6699CC","6666CC","6633CC","6600CC","FF00CC","FF33CC","FF66CC","FF99CC","FFCCCC","FFFFCC",
			"3300FF","3333FF","3366FF","3399FF","33CCFF","33FFFF","66FFFF","66CCFF","6699FF","6666FF","6633FF","6600FF","FF00FF","FF33FF","FF66FF","FF99FF","FFCCFF","FFFFFF",
			"0000FF","0033FF","0066FF","0099FF","00CCFF","00FFFF","99FFFF","99CCFF","9999FF","9966FF","9933FF","9900FF","CC00FF","CC33FF","CC66FF","CC99FF","CCCCFF","CCFFFF",
			"0000CC","0033CC","0066CC","0099CC","00CCCC","00FFCC","99FFCC","99CCCC","9999CC","9966CC","9933CC","9900CC","CC00CC","CC33CC","CC66CC","CC99CC","CCCCCC","CCFFCC",
			"000099","003399","006699","009999","00CC99","00FF99","99FF99","99CC99","999999","996699","993399","990099","CC0099","CC3399","CC6699","CC9999","CCCC99","CCFF99",
			"000066","003366","006666","009966","00CC66","00FF66","99FF66","99CC66","999966","996666","993366","990066","CC0066","CC3366","CC6666","CC9966","CCCC66","CCFF66",
			"000033","003333","006633","009933","00CC33","00FF33","99FF33","99CC33","999933","996633","993333","990033","CC0033","CC3333","CC6633","CC9933","CCCC33","CCFF33",
			"000000","003300","006600","009900","00CC00","00FF00","99FF00","99CC00","999900","996600","993300","990000","CC0000","CC3300","CC6600","CC9900","CCCC00","CCFF00");

////////////////////////////////////////////////////////////////////////////////////////////

// window
Drawing.WindowClass = Class.create();
Drawing.WindowClass.prototype =
{
	initialize: function()
	{
		this._supportsVml = false;
	},
	
	// check if vml is allowed
	supportsVml: function()
	{
		if (this._supportsVml)
			return true;
		
		this._supportsVml = this.enableVml();
		return this._supportsVml;
	},
	
	// enable vml for the document
	enableVml: function()
	{
		if (this._supportsVml)
			return true;
		else if (document.all)
		{
			document.namespaces.add("v", "urn:schemas-microsoft-com:vml")
			
			if (document.styleSheets.length < 1)
				document.body.appendChild(document.createElement("style"));
			
			document.styleSheets.item(0).addRule("v\\:*", "behavior:url(#default#VML)");
			
			return true;
		}
		
		return false;
	},
	
	setCursor: function(cursor, wnd)
	{
		if (wnd && wnd.style)
			wnd.style.cursor = cursor;
	},
	
	getCursor: function(wnd)
	{
		if (!wnd || !wnd.style)
			return document.body.style.cursor;
		else
			return wnd.style.cursor;
	},
	
	load: function(wnd, html)
	{
		if (!html)
			return;
		
		if (html.indexOf("http://") == 0 || html.indexOf("https://") == 0 || html.indexOf("www.") == 0)
		{
			if (html.indexOf("www.") == 0)
				html = "http://" + html;
			
			var style = "width:" + Core.Utility.getElementWidth(wnd) + ";height:" + Core.Utility.getElementHeight(wnd) + ";position:absolute";
			html = "<iframe id=\"" + wnd.id + "iframe\" style=\"" + style + "\" src=\"" + html + "\">";
		}
		
		wnd.innerHTML = html;
	}
};
Drawing.Window = new Drawing.WindowClass();

////////////////////////////////////////////////////////////////////////////////////////////

Drawing.Color = Class.create();
Drawing.Color.prototype =
{
	initialize: function(value)
	{
		this.value = "";
		
		if (value)
			this.value = value;
	},
	
	toString: function()
	{
		if (this.value.length > 0 && this.value.indexOf("#") < 0)
			return "#" + this.value;
		else
			return this.value;
	},
	
	toArgb: function()
	{
		if (this.value.length == 0)
			return 16777215;
		
		if (this.value.indexOf("#") < 0)
			return Core.Utility.convertBase(this.value, 16, 10) - 16777216;
		else
			return Core.Utility.convertBase(this.value.substring(1, this.value.length - 1), 16, 10) - 16777216;
	},
	
	toJSON: function()
	{
		return "{\"__type\":\"System.Drawing.Color\",\"value\":\"" + this.toString() + "\"}";
	}
};

Drawing.ColorsClass = Class.create();
Drawing.ColorsClass.prototype =
{
	Transparent: new Drawing.Color(""),
	White: new Drawing.Color("FFFFFF"),
	Black: new Drawing.Color("000000"),
	Red: new Drawing.Color("FF0000"),
	Green: new Drawing.Color("00FF00"),
	Blue: new Drawing.Color("0000FF"),
	Gray: new Drawing.Color("CCCCCC"),
	DarkGray: new Drawing.Color("333333")
};
Drawing.Colors = new Drawing.ColorsClass();

////////////////////////////////////////////////////////////////////////////////////////////

Drawing.Font = Class.create();
Drawing.Font.prototype =
{
	initialize: function(name, size, bold, italics, underline)
	{
		this.name= "Arial";
		this.size = 14;
		this.bold = false;
		this.italics = false;
		this.underline = false;
			
		if (name)
			this.name = name;
		if (size)
			this.size = size;
		if (bold)
			this.bold = bold;
		if (italics)
			this.italics = italics;
		if (underline)
			this.underline = underline;
	},
	
	toString: function()
	{
		return "Drawing.Font: " + this.name + ", "  + this.size + "pt";
	}
};

////////////////////////////////////////////////////////////////////////////////////////////

Drawing.VMLFactoryClass = Class.create();
Drawing.VMLFactoryClass.prototype =
{
	createShape: function(parent)
	{
		if (!parent)
			parent = document.body;
		
		var _control = document.createElement("<v:shape onselectstart=\"return false;\"/>");
		_control.style.position = "absolute";
		parent.appendChild(_control);

		return _control;
	},
	
	createRectangle: function(parent)
	{
		if (!parent)
			parent = document.body;
		
		var _control = document.createElement("<v:rect onselectstart=\"return false;\"/>");
		_control.style.position = "absolute";
		parent.appendChild(_control);

		return _control;
	},
	
	createRoundRectangle: function(parent, arcsize)
	{
		if (!parent)
			parent = document.body;
		
		var _control = document.createElement("<v:roundrect onselectstart=\"return false;\"/>");
		_control.style.position = "absolute";
		
		if (arcsize)
			_control.arcsize = arcsize;
		
		parent.appendChild(_control);

		return _control;
	},
	
	createEllipse: function(parent)
	{
		if (!parent)
			parent = document.body;
		
		var _control = document.createElement("<v:oval onselectstart=\"return false;\"/>");
		_control.style.position = "absolute";
		parent.appendChild(_control);

		return _control;
	},
	
	createLine: function(parent)
	{
		if (!parent)
			parent = document.body;
		
		var _control = document.createElement("<v:line onselectstart=\"return false;\"/>");
		_control.style.position = "absolute";
		parent.appendChild(_control);

		return _control;
	},
	
	_getChild: function(obj, name)
	{
		var tag = null;
		
		for (i = 0; i < obj.childNodes.length; i++)
		{
			if (obj.childNodes[i].nodeName == name)	
			{
				tag = obj.childNodes[i];
				break;
			}
		}
		
		if (!tag)
		{
			tag = document.createElement("<v:" + name + "/>");
			obj.appendChild(tag);
		}
		
		return tag;
	},
	
	addFill: function(obj, color)
	{
		var fill = this._getChild(obj, "fill");
		fill.color = color.toString();
	},
	
	addOpacity: function(obj, opacity)
	{
		var fill = this._getChild(obj, "fill");
		fill.opacity = opacity;
	},
	
	addStroke: function(obj, color, weight, dashstyle, opacity)
	{
		var stroke = this._getChild(obj, "stroke");
		
		if (dashstyle == "none")
			stroke.on = false;
		if (color)
			stroke.color = color.toString();
		if (weight)
			stroke.weight = weight;
		if (dashstyle)
			stroke.dashstyle = dashstyle;
		if (opacity)
			stroke.opacity = opacity;
	},
	
	addText: function(obj, text, font, color, backColor, haloColor)
	{
		var textbox = this._getChild(obj, "textbox");
		textbox.innerHTML = text;
		
		if (font)
		{
			textbox.style.fontFamily = font.name;
			textbox.style.fontSize = Number(font.size);
			if (font.italics) textbox.style.fontStyle = "italic";
			if (font.bold) textbox.style.fontWeight = "bold";
			if (font.underline) textbox.style.textDecoration = "underline";
		}
		
		if (color && color.value != "")
			textbox.style.color = color.toString();
		if (backColor && backColor.value != "")
			textbox.style.backgroundColor = backColor.toString();
		if (haloColor && haloColor.value != "")
			this.addStroke(textbox, haloColor, 1, "solid");
	}
};
Drawing.VMLFactory = new Drawing.VMLFactoryClass();

////////////////////////////////////////////////////////////////////////////////////////////

Drawing.Shape = Class.create();
Drawing.Shape.prototype =
{
	base: function(left, top, right, bottom)
	{
		this._control = null;
		this.parent = document.body;
		this.visible = false;
		this.redraw = true;
		this.color = Drawing.Colors.Black;
		this.backColor = Drawing.Colors.White;
		this.opacity = 1;
		this.left = this.top = this.right = this.bottom = 0;
		this.lineStyle = Drawing.LineStyle.Solid();
		this.lineWidth = 1;
		
		this.move(left, top, right, bottom, true);
	},		
	
	move: function(left, top, right, bottom, forceNoRedraw)
	{
		if (left != null)
			this.left = left;
		
		if (top != null)
			this.top = top;
		
		if (right != null)
			this.right = right;
		
		if (bottom != null)
			this.bottom = bottom;
		
		if (this.redraw && !forceNoRedraw)
			this.update(true);
	},
	
	createControl: function(){},
	_preDraw: function(){ return true; },
	_position: function(){ return false; },
	
	draw: function()
	{
		if (!this._preDraw())
			return;
		
		this.visible = true;
		
		if (!this._control)
		{
			this.createControl();
			
			if (this._control == null)
				return;
		}
		
		this._control.style.visibility = "visible";
		this._control.style.display = "";
		
		if (!this._position())
		{
			if (Math.abs(this.right - this.left) <= 1 ||
				Math.abs(this.bottom - this.top) <= 1)
			{
				this.hide();
				return;
			}
			
			this._control.style.top = Core.Utility.toSize(this.top);
			this._control.style.left = Core.Utility.toSize(this.left);
			
			if (this.right != this.left && this.right != 0)
				this._control.style.width = Core.Utility.toSize(this.right - this.left - 2);
			
			if (this.bottom != this.top && this.bottom != 0)
				this._control.style.height =  Core.Utility.toSize(this.bottom - this.top - 2);
		}
	},
	
	hide: function()
	{
		this.visible = false;
		
		if (this._control)
		{
			this._control.style.visibility = "hidden";
			this._control.style.display = "none";
		}
	},
	
	// remove the drawing object
	remove: function()
	{
		if (this._control != null)
			this.parent.removeChild(this._control);
		
		this._control = null;
	},
	
	// update the drawing object
	update: function(recreate)
	{
		if (recreate)
			this.remove();
		
		this.draw();
	},
	
	toString: function()
	{
		return "Drawing.Shape";
	}
};

////////////////////////////////////////////////////////////////////////////////////////////

Drawing.Rectangle = Class.inherit(Drawing.Shape, 
{
	initialize: function(left, top, right, bottom)
	{
		this.base(left, top, right, bottom);
	},
	
	// create the control
	createControl: function()
	{
		if (Drawing.Window.supportsVml())
		{
			this._control = Drawing.VMLFactory.createRectangle(this.parent);
			
			if (this.backColor) Drawing.VMLFactory.addFill(this._control, this.backColor);
			if (this.color && this.lineStyle) Drawing.VMLFactory.addStroke(this._control, this.color, this.lineWidth, this.lineStyle.toString(true), this.opacity);
			if (this.opacity) Drawing.VMLFactory.addOpacity(this._control, this.opacity);
		}
		else
		{
			this._control = document.createElement("div");
			this._control.style.position = "absolute";
			
			if (this.backColor) this._control.style.backgroundColor = this.backColor.toString();
			if (this.color) this._control.style.borderColor = this.color.toString();
			if (this.lineStyle) this._control.style.borderStyle = this.lineStyle.toString();
			if (this.lineWidth) this._control.style.borderWidth = this.lineWidth;
			if (this.opacity) this._control.style.opacity = this.opacity + ";filter: alpha(opacity=" + (this.opacity * 100) + "); -moz-opacity: " + this.opacity;
			
			this.parent.appendChild(this._control);
		}
	},
	
	_preDraw: function()
	{
		if (this.top == this.bottom || this.left == this.right)
			return false;
		
		return true;
	},
	
	toString: function()
	{
		return "Drawing.Rectangle: " + this.left + ", " + this.top + ", " + this.right + ", " + this.bottom;
	}
});

////////////////////////////////////////////////////////////////////////////////////////////

Drawing.RoundRectangle = Class.inherit(Drawing.Rectangle, 
{
	initialize: function(left, top, right, bottom, arcsize)
	{
		this.base(left, top, right, bottom);
		
		if (arcsize)
			this.arcsize = arcsize;
		else
			this.arcsize = 0.2;
	},
	
	// create the control
	createControl: function()
	{
		if (Drawing.Window.supportsVml())
		{
			this._control = Drawing.VMLFactory.createRoundRectangle(this.parent, this.arcsize);
			
			if (this.backColor) Drawing.VMLFactory.addFill(this._control, this.backColor);
			if (this.color && this.lineStyle) Drawing.VMLFactory.addStroke(this._control, this.color, this.lineWidth, this.lineStyle.toString(true), this.opacity);
			if (this.opacity) Drawing.VMLFactory.addOpacity(this._control, this.opacity);
		}
		else
		{
			this._control = document.createElement("div");
			this._control.style.position = "absolute";
			
			if (this.backColor) this._control.style.backgroundColor = this.backColor.toString();
			if (this.color) this._control.style.borderColor = this.color.toString();
			if (this.lineStyle) this._control.style.borderStyle = this.lineStyle.toString();
			if (this.lineWidth) this._control.style.borderWidth = this.lineWidth;
			if (this.opacity) this._control.style.opacity = this.opacity + ";filter: alpha(opacity=" + (this.opacity * 100) + "); -moz-opacity: " + this.opacity;
			
			this.parent.appendChild(this._control);
		}
	},
	
	toString: function()
	{
		return "Drawing.RoundRectangle: " + this.left + ", " + this.top + ", " + this.right + ", " + this.bottom;
	}
});

////////////////////////////////////////////////////////////////////////////////////////////

Drawing.Square = Class.inherit(Drawing.Rectangle, 
{
	initialize: function(left, top, width)
	{
		this.base(left, top, left + width, top + width);
		
		this.width = width;
	},
	
	_preDraw: function()
	{
		if (this.top == this.bottom || this.left == this.right)
			return false;
		
		width = Math.min(Math.abs(this.right - this.left), Math.abs(this.bottom - this.top));
		
		if (width != this.width)
			this.width = width;
		
		this.move(this.left, this.top, this.left + this.width, this.top + this.width);
		
		return true;
	},
	
	toString: function()
	{
		return "Drawing.Square: " + this.width + " at " + this.left + ", " + this.top;
	}
});

////////////////////////////////////////////////////////////////////////////////////////////

Drawing.Ellipse = Class.inherit(Drawing.Shape, 
{
	initialize: function(left, top, right, bottom)
	{
		this.base(left, top, right, bottom);
	},
	
	// create the control
	createControl: function()
	{
		if (Drawing.Window.supportsVml())
		{
			this._control = Drawing.VMLFactory.createEllipse(this.parent);
			
			if (this.backColor) Drawing.VMLFactory.addFill(this._control, this.backColor);
			if (this.color && this.lineStyle) Drawing.VMLFactory.addStroke(this._control, this.color, this.lineWidth, this.lineStyle.toString(true), this.opacity);
			if (this.opacity) Drawing.VMLFactory.addOpacity(this._control, this.opacity);
		}
		else
		{
		}
	},
	
	_preDraw: function()
	{
		if (this.top == this.bottom || this.left == this.right)
			return false;
		
		return true;
	},
	
	toString: function()
	{
		return "Drawing.Ellipse: " + this.left + ", " + this.top + ", " + this.right + ", " + this.bottom;
	}
});

////////////////////////////////////////////////////////////////////////////////////////////

Drawing.Circle = Class.inherit(Drawing.Ellipse, 
{
	initialize: function(centerX, centerY, radius)
	{
		this.base(centerX - radius, centerY - radius, centerX + radius, centerY + radius);
		
		this.centerX = centerX;
		this.centerY = centerY;
		this.radius = radius;
	},
	
	// position the circle at the specified screen coordinates
	positionAt: function(centerX, centerY)
	{
		this.centerX = centerX;
		this.centerY = centerY;
	},
	
	_position: function()
	{
		if (!this._control)
			return false;
		
		this._control.style.left = Core.Utility.toSize(this.centerX - this.radius);
		this._control.style.top = Core.Utility.toSize(this.centerY - this.radius);
		this._control.style.width = Core.Utility.toSize(this.radius * 2);
		this._control.style.height =  Core.Utility.toSize(this.radius * 2);
		
		return true;
	},
	
	toString: function()
	{
		return "Drawing.Circle: " + this.centerX + ", " + this.centerY + " radius " + this.radius;
	}
});

////////////////////////////////////////////////////////////////////////////////////////////

Drawing.Line = Class.inherit(Drawing.Shape, 
{
	initialize: function(left, top, right, bottom)
	{
		this.base(left, top, right, bottom);
	},
	
	// create the control
	createControl: function()
	{
		if (Drawing.Window.supportsVml())
		{
			this._control = Drawing.VMLFactory.createLine(this.parent);
			
			if (this.backColor) Drawing.VMLFactory.addFill(this._control, this.backColor);
			if (this.color && this.lineStyle) Drawing.VMLFactory.addStroke(this._control, this.color, this.lineWidth, this.lineStyle.toString(true), this.opacity);
			if (this.opacity) Drawing.VMLFactory.addOpacity(this._control, this.opacity);
		}
		else
		{
			this._control = document.createElement("div");
			this._control.style.position = "absolute";
			
			if (this.backColor) this._control.style.backgroundColor = this.backColor.toString();
			if (this.color) this._control.style.borderColor = this.color.toString();
			if (this.lineStyle) this._control.style.borderStyle = this.lineStyle.toString();
			if (this.lineWidth) this._control.style.borderWidth = this.lineWidth;
			if (this.opacity) this._control.style.opacity = this.opacity + ";filter: alpha(opacity=" + (this.opacity * 100) + "); -moz-opacity: " + this.opacity;
			
			this.parent.appendChild(this._control);
		}
	},
	
	_position: function()
	{
		if (!this._control)
			return false;
		
		this._control.from = this.left + "," + this.top;
		this._control.to = this.right + "," + this.bottom;
		
		this._control.style.top = Core.Utility.toSize(0);
		this._control.style.left = Core.Utility.toSize(0);
		this._control.style.width = Core.Utility.toSize(2000);
		this._control.style.height =  Core.Utility.toSize(2000);
		
		return true;
	},
	
	toString: function()
	{
		return "Drawing.Line";
	}
});

////////////////////////////////////////////////////////////////////////////////////////////

Drawing.Text = Class.inherit(Drawing.Shape, 
{
	initialize: function(text, left, top, right, bottom, font)
	{
		this.base(left, top, right, bottom);
		
		if (font)
			this.font = font;
		else
			this.font = new Drawing.Font();
		
		if (text)
			this.text = text;
		else
			this.text = "";
		
		this.nowrap = false;
		this.backColor = null;
		this.haloColor = Drawing.Colors.Transparent;
		this.lineStyle = Drawing.LineStyle.None();
		this.lineWidth = 0;
	},
	
	// position the text at the specified screen coordinates
	positionAt: function(x, y)
	{
		this.move(x, y, 0, 0);
	},
	
	// create the control
	createControl: function()
	{
		var text = this.text;
		
		if (this.nowrap)
			text = "<nobr>" + text + "</nobr>";
			
		if (Drawing.Window.supportsVml())
		{
			this._control = Drawing.VMLFactory.createRectangle(this.parent);
			
			this._control.style.marginLeft = "-10px";
			this._control.style.marginTop = "-5px";
			
			Drawing.VMLFactory.addText(this._control, text, this.font, this.color, this.backColor, this.haloColor);
			
			if (this.backColor) Drawing.VMLFactory.addFill(this._control, this.backColor);
			if (this.color && this.lineStyle) Drawing.VMLFactory.addStroke(this._control, this.color, this.lineWidth, this.lineStyle.toString(true), this.opacity);
			if (this.opacity) Drawing.VMLFactory.addOpacity(this._control, this.opacity);
		}
		else
		{
			this._control = document.createElement("div");
			this._control.style.position = "absolute";
			
			this._control.style.fontFamily = this.font.name;
			this._control.style.fontSize = Number(this.font.size) + "px";
			if (this.font.italics) this._control.style.fontStyle = "italic";
			if (this.font.bold) this._control.style.fontWeight = "bold";
			if (this.font.underline) this._control.style.textDecoration = "underline";
			
			this._control.innerHTML = text;
			
			if (this.backColor) this._control.style.backgroundColor = this.backColor.toString();
			if (this.color) this._control.style.borderColor = this.color.toString();
			if (this.lineStyle) this._control.style.borderStyle = this.lineStyle.toString();
			if (this.lineWidth) this._control.style.borderWidth = this.lineWidth;
			if (this.opacity) this._control.style.opacity = this.opacity + ";filter: alpha(opacity=" + (this.opacity * 100) + "); -moz-opacity: " + this.opacity;
			
			this.parent.appendChild(this._control);
		}
	},
	
	_position: function()
	{
		if (!this._control)
			return false;
		
		this._control.style.top = Core.Utility.toSize(this.top);
		this._control.style.left = Core.Utility.toSize(this.left);
		
		var child = this._control;
		if (Drawing.Window.supportsVml())
			child = this._control.childNodes[0];
		
		if (this.right > this.left)
			child.style.width = Core.Utility.toSize(Math.abs(this.right - this.left));
		if (this.bottom != 0)
			child.style.height = Core.Utility.toSize(Math.abs(this.bottom - this.top));
		
		return true;
	},
	
	toString: function()
	{
		return "Drawing.Text: " + this.left + ", " + this.top + ", " + this.text;
	}
});

