//<script type="text/javascript">

Doodle.Canvas = JSX.Class.create({
	name: 'Canvas',
	constructor: function(divCanvas, document) {
		this.divCanvas = divCanvas;
		this.document = document;
		this.gr = new Graphics(divCanvas);
		
		this.widgets = new Array(); // array of widgets indexed by ID

		// set up mouse handlers
		this.divCanvas.onmousedown = this.onMouseDown.bindEvent(this);
		this.divCanvas.onmousemove = this.onMouseMove.bindEvent(this);
		this.divCanvas.onmouseup = this.onMouseUp.bindEvent(this);
		
		// canvas properties
		this.bMouseDown = false;
		
		// other properties
		this.gr.penColor = "black";
	},
	members: {
		getDocument: function() {
			return this.document;
		},

		addWidget: function(widget) {
			this.widgets[widget.getID()] = widget;
		},
		delWidget: function(widget) {
			delete this.widgets[widget.getID()];
		},
		delWidgetByID: function(id) {
			delete this.widgets[id];
		},

		getMousePos: function(evt) {
			var pos = dhtml.getElementPosition(this.divCanvas);
			var scroll = dhtml.getScrollPos();
			var x = evt.clientX - (pos.left - scroll.left);
			var y = evt.clientY - (pos.top - scroll.top);
				
			return {x:x, y:y};
		},

		onMouseDown: function(evt) {
			if ( !this.widget ) {
				var pos = this.getMousePos(evt);
				var dLine = this.document.createLine(pos,pos);
				this.widget = new Doodle.Canvas.Line(this, dLine);
				this.widget.select();
				this.widget.draw();
			}
		},
		onMouseMove: function(evt) {
			if ( this.widget ) {
				this.widget.setP2(this.getMousePos(evt));
			}
		},
		onMouseUp: function(evt) {
			if ( this.widget ) {
				this.widget.unselect();
				delete this.widget;
			}
		}
	}
});

//=============================================================================
// Widget heirarchy
//
// Widgets are view-objects that represent document shapes within the canvas
Doodle.Canvas.Widget = JSX.Class.create({
	name: 'Widget',
	constructor: function(canvas, shape) {
		// base classes must do nothing when constructed with no arguments
		if ( arguments.length == 0 ) return;
		
		// pointer to canvas
		this.canvas = canvas;
		
		// pointer to graphics
		this.gr = canvas.gr;
		
		// store the document shape
		this.shape = shape;
		
		// some properties
		this.bSelected = false;
	},
	members: {
		getID: function() {
			return this.shape.getID();
		},

		// destroy - destroy the Widget instance (doesn't affect document)
		destroy: function() {
			delete this.canvas;
			delete this.shape;
		},

		// remove - remove shape from document.
		remove: function() {
			this.canvas.getDocument().delShape(this.shape);
		},

		// select - activate widget for editing.
		select: function() {
			this.bSelected = true;
		},

		// unselect - deactivate widget.
		unselect: function() {
			this.bSelected = false;
		},
		
		draw: function() {
			// to be overridden
		},
		undraw: function() {
			// to be overridden
		}
	}
});

//=============================================================================
// Line Widget
Doodle.Canvas.Line = JSX.Class.create({
	name: 'Line',
	base: Doodle.Canvas.Widget,
	constructor: function(canvas, line) {
		this.Widget.call(this, canvas, line);
	},
	members: {
		draw: function() {
			var p1 = this.shape.getP1();
			var p2 = this.shape.getP2();
			this.grLine = this.gr.drawLine(p1.x,p1.y,p2.x,p2.y);
			if ( !this.bSelected ) this.setTrigger();
		},
		undraw: function() {
			if ( this.grLine ) {
				this.grLine.undraw();
				delete this.grLine;
			}
		},

		unselect: function() {
			this.Widget.prototype.unselect.call(this);
			this.setTrigger();
		},
		setTrigger: function() {
			this.grLine.setStyle('cursor', 'pointer');
			this.grLine.setMouseDown(this.onMouseDown.bindEvent(this));
		},

		setP1: function(pos) {
			var bDraw = this.grLine != null;
			if ( bDraw ) this.undraw();
			this.shape.setP1(pos);
			if ( bDraw ) this.draw();
		},
		setP2: function(pos) {
			var bDraw = this.grLine != null;
			if ( bDraw ) this.undraw();
			this.shape.setP2(pos);
			if ( bDraw ) this.draw();
		},

		onMouseDown: function(evt) {
			this.canvas.delWidget(this);
			this.remove();
			this.destroy();
			dhtml.cancelEvent(evt);
		},

		destroy: function() {
			this.Widget.prototype.destroy.call(this);
			this.undraw();
		}
	}
});

//</script>