<?xml version="1.0"?>
<bindings xmlns="http://www.mozilla.org/xbl"
          xmlns:xbl="http://www.mozilla.org/xbl"
          xmlns:svg="http://www.w3.org/2000/svg"
          xmlns:geometry="http://www.ycombe.net/Xul/Geometry" >
<!--  <binding id="svg"> -->
  <binding id="canvas" extends="svg:svg">
	<implementation>
   <field name="selectedButton">null</field>
   <field name="selectedElement">null</field>
   <field name="selectedSet">null</field>
   <field name="selectablesArray">null</field>
   <field name="refX">0</field>
   <field name="refY">0</field>
   <field name="ListOfPoints">null</field>
   <field name="ListOfFreePoints">null</field>
   <field name="ListOfSets">null</field>
   <field name="elementType">"canvas"</field>
   <field name="magnet">100</field>
   <field name="colors"/>
   <constructor><![CDATA[
   	this.ListOfPoints = new Array();
   	this.ListOfFreePoints = new Array();
   	this.ListOfSets = new Array();
   	this.selectablesArray = new Array();
   	this.colors = { selectable: "Turquoise",
   						 selected: "Green",
   						 normal: "Red" };
   	this.addEventListener('mousemove', this.makemove, true);
	]]></constructor>
	<property name="selected">
		<getter>
			return this.selectedElement;
		</getter>
		<setter>
			if (this.selectedElement)
				this.selectedElement.color(this.colors.normal)
			this.selectedElement = val;
			if (this.selectedElement)
				this.selectedElement.color(this.colors.selected)
		</setter>
	</property>
	<property name="selectables">
	   <getter>
	   	return this.selectablesArray;
	   </getter>
	   <setter><![CDATA[
	   	for (var i = 0, item; item = this.selectablesArray[i]; i++) {
	   	   	item.color(this.colors.normal);
	   	}
	   	this.selectablesArray = val;
	   	for (var i = 0, item; item = this.selectablesArray[i]; i++) {
	   	   	item.color(this.colors.selectable);
	   	}
	   ]]></setter>
	</property>
   <property name="button">
   	<setter><![CDATA[
   	   var selectedButton = document.getElementById('selected_tool');
   		if (val == 'move'){
   			selectedButton.image = 'images/move.png';
   		} else if (val == 'point'){
   			selectedButton.image = 'images/free_point.png';
   		} else if (val == 'squarre'){
   			//selectedButton.image = 'images/squarre.png';
   			alert('Pas encore implanté');
   		} else if (val == 'ruler'){
   			selectedButton.image = 'images/rule.png';
   		} else if (val == 'compas'){
   			selectedButton.image = 'images/compas.png';
   		} else {
   		  return;
   		}
   		
   		this.selectedButton = val;
   		if ((this.refX ==0) && (this.refY ==0)){
   			var m = this.getCTM();
   		   this.refX = m.e;
   			this.refY = m.f;
   		}

   	]]></setter>
   	<getter>
   		return this.selectedButton;
   	</getter>
   </property>
   <method name="clicked">
   	<parameter name="event" />
   	<body><![CDATA[

   		if (this.button == 'point')
   			this.add_point(event);
   		if (this.button == 'move')
   			return;
   		if (this.button == 'compas')
   			this.circle(event);
   		if (this.button == 'ruler')
   			this.ruler(event);
   			
   		]]></body>
   </method>
   <method name='ruler'>
   	<parameter name='event' />
   	<body><![CDATA[
   		var creating = false;
   		
   		if (!this.selectedSet){
   			var elm = document.createElementNS("http://www.ycombe.net/Xul/Geometry", "geometry:line");
   		   this.appendChild(elm);
   		   this.selectedSet = elm;
   		   creating = true;
   		}
   		
   		if (event.target.elementType == "point"){
	   			this.selectedSet.set_parent(event.target);
	   			}
	   	else {
				if (this.selectables.length == 1){
					this.selectedSet.set_parent(this.selectables[0]);
					this.selectables = Array();
				} else if (this.selectables.length == 0) {
					this.add_point(event);
					this.selectedSet.set_parent(this.ListOfPoints[this.ListOfPoints.length-1]);
				}
	   	}

			if (creating)
				this.selectedSet.floatingPos(event.clientX - this.refX,
													  event.clientY - this.refY);
  		
		]]></body>   
   </method>
   <method name='circle'>
   	<parameter name='event' />
   	<body><![CDATA[
   		var creating = false;
   		
   		if (!this.selectedSet){
   			var elm = document.createElementNS("http://www.ycombe.net/Xul/Geometry", "geometry:circle");
   		   this.appendChild(elm);
   		   this.selectedSet = elm;
   		   creating = true;
   		}
   		
   		if (event.target.elementType == "point"){
	   			this.selectedSet.set_parent(event.target);
	   			}
	   	else {
	   		this.getSelectables(true,
   									  this.magnet, 
   									  event.clientX - this.refX, 
   									  event.clientY - this.refY);
				if (this.selectables.length == 1){
					this.selectedSet.set_parent(this.selectables[0]);
					this.selectables = Array();
				} else if (this.selectables.length == 0) {
					this.add_point(event);
					this.selectedSet.set_parent(this.ListOfPoints[this.ListOfPoints.length-1]);
				}
	   	}

			if (creating)
				this.selectedSet.floatingPos(event.clientX - this.refX,
													  event.clientY - this.refY);
  		
		]]></body>   
   </method>
   <method name="add_point">
   	<parameter name='event' />
   	<body>
   		// FREE POINTS ONLY FOR THE MOMENT 
   		//alert('add_point : ' + event.clientX + ' ' + event.clientY);
   		var elm = document.createElementNS("http://www.ycombe.net/Xul/Geometry", "geometry:point");
   		this.appendChild(elm);
   		elm.position(event.clientX - this.refX, event.clientY - this.refY);
   		this.ListOfPoints.push(elm);
   		this.ListOfFreePoints.push(elm);
   		elm.free = true; 
   	</body>
   </method>
   <method name="move">
   	<parameter name='event' />
   	<body><![CDATA[
   		if (event.target.elementType == "point"){
   			this.selected = event.target;
   			this.selected.position(event.clientX - this.refX,
   										  event.clientY - this.refY);
   			}
   		else
   			if (this.selectables.length ==1) {
   				this.selected = this.selectables[0];
   				this.selectables = Array();
   				this.selected.position(event.clientX - this.refX,
   										  event.clientY - this.refY);
   			}
   	]]></body>
   </method>
   <method name="getSelectables">
   	<parameter name="free" />
   	<parameter name="limit" />
   	<parameter name="X" />
   	<parameter name="Y" />
   	<body><![CDATA[
   		var selectables = new Array();
   		
   	   var target;
   		if (free)
   			target = this.ListOfFreePoints;
   		else
   			target = this.ListOfPoints;
   			
   		var i;
   		   		
   		for (i=0 ; i < target.length; i++){
   			if (target[i].distanceOK(limit, X, Y)){
   				selectables.push(target[i]);
   				}
   		}
   		this.selectables = selectables;
   	]]></body>
 
   </method>
   
   <method name="mousedown">
   	<parameter name="event" />
   	<body><![CDATA[
   		if (this.button == 'move')
   			this.move(event);
   		else
   			return;
   			
   		]]></body>
   </method>
   
   <method name="makemove">
   	<parameter name='event' />
   	<body><![CDATA[
   		var suspend_id;
   		if (this.button == 'move') {
   			if (this.selected == null)
   				this.getSelectables(true,
   										  this.magnet, 
   										  event.clientX - this.refX, 
   										  event.clientY - this.refY);
   			else {
  			   	//this.removeEventListener('mousemove', this.makemove, true);
					suspend_id = this.suspendRedraw(2000);
   				this.selected.position(event.clientX - this.refX,
   											  event.clientY - this.refY);
	   		   this.unsuspendRedraw(suspend_id);
	   		   this.forceRedraw();
		      	//this.addEventListener('mousemove', this.makemove, true);
 				}
 			}
 				
 			if ((this.button == 'ruler')
 				 || (this.button == 'squarre')
 				 || (this.button == 'compas')){
 				if (this.selectedSet)
 					this.selectedSet.floatingPos(event.clientX - this.refX,
													  event.clientY - this.refY);
   			this.getSelectables(false,
   									  this.magnet, 
   									  event.clientX - this.refX, 
   									  event.clientY - this.refY);
				}
				
   	]]></body>
   </method>
   
   <method name="mouseup">
   	<parameter name='event' />
   	<body>
   		// Is there a Free Point under the click?
   		if (!this.selected)
   			return;
   		else {
   			this.selected.position(event.clientX - this.refX,
   										  event.clientY - this.refY);
   			this.selected = null;
   			}
   	</body>
   </method>

	</implementation>
	<handlers>
		<handler event='click' action='clicked(event)' />
		<handler event='mousedown' action='mousedown(event)' />
		<!-- <handler event='mousemove' action='makemove(event)' /> -->
		<handler event='mouseup' action='mouseup(event)' />
	</handlers>
  </binding>
  
  <!-- tool binding is common for tool buttons -->
  <binding id="tool"  extends="chrome://global/content/bindings/toolbarbutton.xml#toolbarbutton">
  <implementation>
  		<method name="command">
  		<body>
  		   //alert(this.id);
  			var canvas = document.getElementById('canvas');
  			canvas.button = this.id;
  		</body>
  		</method>
  </implementation>
  <handlers>
  	<handler event="command" action="this.command();" />
  </handlers>
  </binding>
  
  <!-- Point binding -->
  <binding id="point" extends="svg:circle">
  	<content>
  		<svg:circle r="2" fill="red"/>
  	</content>
  	<implementation>
  	   <field name="elementType">"point"</field>
  		<field name="posX">0</field>
  		<field name="posY">0</field>
  		<field name="free">false</field>
  		<field name="childs" />
  		<field name="parents" />
  		<field name="inner"/>
  		<constructor>
  			this.childs = new Array();
  			this.parents = new Array();
  			this.inner = document.getAnonymousNodes(this)[0];
  		</constructor>
 		<method name="position">
  			<parameter name="X" />
  			<parameter name="Y" />
  			<body>
  				this.posX = X;
  				this.posY = Y;
  				this.inner.cx.baseVal.value = X;
  				this.inner.cy.baseVal.value = Y;
  				
  				for (var i=0, item; item = this.childs[i]; i++)
  					item.update_pos(this);
  				}							
  			</body>
  		</method>
  		<method name="distanceOK">
  			<parameter name="limit" />
  			<parameter name="X" />
         <parameter name="Y" />
		   <body><![CDATA[
		      var dx, dy;
		      dx = this.posX -X;
		      dy = this.posY -Y;
		   	return ((dx*dx + dy*dy) < limit)	
		   ]]></body>  
  		</method>
  		<method name="color">
  			<parameter name="color" />
		   <body><![CDATA[
		      this.inner.setAttribute('fill',color);
		   ]]></body>  
  		</method>
  	</implementation>
  </binding>
  
  <!-- Line binding -->
  <binding id="line" extends="svg:line">
  	<content>
  		<svg:path stroke="black" stroke-width="1"/>
  	</content>
  	<implementation>
  	   <field name="elementType">"line"</field>
  		<field name="parents"></field>
  		<field name="free">false</field>
  		<field name="inner"/>
  		<constructor>
  			this.parents = { 1 : null, 2 : null };
  			this.inner = document.getAnonymousNodes(this)[0];
  			this.moveto = this.inner.createSVGPathSegMovetoAbs( 0,0);
  			this.lineto = this.inner.createSVGPathSegLinetoAbs( 100,100);
  			this.inner.pathSegList.appendItem(this.moveto);
  			this.inner.pathSegList.appendItem(this.lineto);
  		</constructor>
  		<method name="update_pos">
  			<parameter name="point" />
  			<body>
  			   if (this.parents['1'] == point){
  				   this.lineto.x = point.posX;
				   this.lineto.y = point.posY;
  				} else {
  				   this.moveto.x = point.posX;
				   this.moveto.y = point.posY;
  				}
  			</body>
  		</method>
  		<method name="set_parent">
  			<parameter name="point" />
  			<body>
  			   if (!this.parents['1']){
  				   this.lineto.x = point.posX;
				   this.lineto.y = point.posY;
				   this.parents['1'] = point;
  				   }
  				else {
  				   this.moveto.x = point.posX;
				   this.moveto.y = point.posY;
				   this.parents['2'] = point;
				   this.parentNode.selectedSet = null;
  				}
  				point.childs.push(this);  							
  			</body>
  		</method>
  		<method name="floatingPos">
  		   <parameter name="posX" />
  			<parameter name="posY" />
  			<body> 
	  			if (!this.parents['1']){
  				   this.lineto.x = posX;
				   this.lineto.y = posY;
	  			} else {
  				   this.moveto.x = posX;
				   this.moveto.y = posY;
				}		
  			</body>
  		</method>
  		<method name="distanceOK">
  			<parameter name="limit" />
  			<parameter name="X" />
         <parameter name="Y" />
		   <body><![CDATA[
		   	return false;	
		   ]]></body>  
  		</method>
  		<method name="color">
  			<parameter name="color" />
		   <body><![CDATA[
		      this.inner.setAttribute('stroke',color);
		   ]]></body>  
  		</method>
  	</implementation>
  </binding>

  <!-- Circle binding -->
  <binding id="circle" extends="svg:line">
  	<content>
  		<svg:circle stroke="black" fill="none" stroke-width="1"/>
  	</content>
  	<implementation>
  	   <field name="elementType">"line"</field>
  		<field name="parents"></field>
  		<field name="free">false</field>
  		<field name="CX">0</field>
  		<field name="CY">0</field>
  		<field name="R_posX">0</field>
  		<field name="R_posY">0</field>
  		<field name="R">0</field>
  		<field name="inner"/>
  		<constructor>
  			this.parents = { 1 : null, 2 : null };
  			this.inner = document.getAnonymousNodes(this)[0];
  		</constructor>
  		<method name="update_pos">
  			<parameter name="point" />
  			<body>
  				if (this.parents['1'] == point){
  				   this.CX = point.posX;
  				   this.CY = point.posY;
  				   this.inner.cx.baseVal.value = this.CX;
				   this.inner.cy.baseVal.value = this.CY;
  				   var x = this.R_posX - this.CX;
  				   var y = this.R_posY - this.CY
  				   this.R = Math.sqrt( x*x + y*y);
  				   this.inner.r.baseVal.value = this.R;
  				} else {
  					this.R_posX =  point.posX;
  					this.R_posY =  point.posY;
  				   var x = this.R_posX - this.CX;
  				   var y = this.R_posY - this.CY
  				   this.R = Math.sqrt( x*x + y*y);
  				   this.inner.r.baseVal.value = this.R;
  				}
  			</body>
  		</method>
  		<method name="set_parent">
  			<parameter name="point" />
  			<body>
  				if (!this.parents['1']){
  				   this.CX = point.posX;
  				   this.CY = point.posY;
  				   this.inner.cx.baseVal.value = this.CX;
				   this.inner.cy.baseVal.value = this.CY;
				   this.parents['1'] = point;
  				   }
  				else {
  					this.R_posX =  point.posX;
  					this.R_posY =  point.posY;
  				   var x = this.R_posX - this.CX;
  				   var y = this.R_posY - this.CY
  				   this.R = Math.sqrt( x*x + y*y);
  				   this.inner.r.baseVal.value = this.R;
				   this.parents['2'] = point;
				   this.parentNode.selectedSet = null;
  				}
  				point.childs.push(this);
  				//alert('parent');  							
  			</body>
  		</method>
  		<method name="floatingPos">
  		   <parameter name="posX" />
  			<parameter name="posY" />
  			<body>
	  			if (!this.parents['1']){
  				   this.CX = posX;
  				   this.CY = posY;
  				   this.inner.cx.baseVal.value = this.CX;
				   this.inner.cy.baseVal.value = this.CY;
	  			} else {
  				   var x = posX - this.CX;
  				   var y = posY - this.CY
  				   this.R = Math.sqrt( x*x + y*y);
  				   this.inner.r.baseVal.value = this.R;
				}	  			
  			</body>
  		</method>
  		<method name="distanceOK">
  			<parameter name="limit" />
  			<parameter name="X" />
         <parameter name="Y" />
		   <body><![CDATA[
		   	return false;	
		   ]]></body>  
  		</method>
  		<method name="color">
  			<parameter name="color" />
		   <body><![CDATA[
		      this.inner.setAttribute('stroke',color);
		   ]]></body>  
  		</method>
  	</implementation>
  </binding>
</bindings>
