<?xml version="1.0"?>
<bindings xmlns="http://www.mozilla.org/xbl" 
          xmlns:xbl="http://www.mozilla.org/xbl" 
          xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">

<binding id="dnd">
  <implementation>
    <field name="dragElement">false</field>
    <field name="initial_top">0</field>
    <field name="initial_left">0</field>
    <field name="delta_x">0</field>
    <field name="delta_y">0</field>
    <field name="popup">false</field>
    
    <method name="dragStart">
     <parameter name="evt"/>
     <body><![CDATA[
	if (this.dragElement){
	   this.dragStop(false,null)
	   return;
	}

	if (evt.target == this)
           return;

	element =  evt.target;

	while (element != this){
            if (element.hasAttribute("dnddata") && element.getAttribute("dnddata"))
             break;
	    element = element.parentNode;
	}

	if (element == this)
	   return;

	// found 
        this.dragElement = element;

	if (this.dragElement.dragStarted)
	  this.dragElement.dragStarted(this);

        if (this.dragElement.hasAttribute("top"))
            this.initial_top = this.dragElement.top;
        if (this.dragElement.hasAttribute("left"))
            this.initial_left = this.dragElement.left;

	this.delta_x =  evt.clientX - this.initial_left;
	this.delta_y =  evt.clientY - this.initial_top;

	//popup is a clone of the node
        //it can be set by this.dragElement.dragStarted(this))
	if (!this.popup){
   	   this.popup = this.dragElement.cloneNode(true);
	   this.appendChild(this.popup);
	
	   this.popup.width = this.dragElement.boxObject.width/2;
	   this.popup.height = this.dragElement.boxObject.height/2;

	}

        this.dragElement.setAttribute("collapsed",true);

        this.popup.left = evt.clientX + 1;
        this.popup.top = evt.clientY + 1;

        evt.stopPropagation();
      ]]></body>
    </method>

    <method name="dragStop">
      <parameter name="succeed"/>
      <parameter name="evt"/>
      <body><![CDATA[
	if (!this.dragElement)
	   return;

	// check
	if (!evt) succeed = false;

        if (evt){
         if (!succeed){
           if (this != evt.target)
              return;
	   //detects we are really out of the stack.
	   if ((evt.clientX > this.boxObject.x) &&
	       (evt.clientY > this.boxObject.y) &&
	       (evt.clientX <  this.boxObject.x +  this.boxObject.width) &&
	       (evt.clientY <  this.boxObject.y +  this.boxObject.height))
	      return;
         }
        }

	if (succeed){
          if (this.hasAttribute("dndtype") && this.getAttribute("dndtype") == "moveObject")
             mode_move = true;
	  else
	     mode_move = false;

	  found_target = false;

	  if (!mode_move){
	     element =  evt.target;
	     while (element != this){
                if (element.hasAttribute("dndtarget") && element.getAttribute("dndtarget")){
	          found_target = true;
                  break;
                  } 
	        element = element.parentNode;
	     }
          }

	if (mode_move){
      	   this.dragElement.left = this.popup.left - this.delta_x; 
	   this.dragElement.top = this.popup.top - this.delta_y;
	} else {
          if (found_target){
            if (element.dragReceive)
		if (!element.dragReceive(this.dragElement)){
	      	   this.dragElement.left = this.popup.left - this.delta_x; 
		   this.dragElement.top = this.popup.top - this.delta_y;
		}
	    else {
              this.dragElement.parentNode.removeChild(this.dragElement);
              element.appendChild(this.dragElement);
	      }
	    }
 	   }
        }

	this.dragElement.setAttribute("collapsed",false);
	this.removeChild(this.popup);

	this.dragElement = false;
	this.initial_top = 0;
	this.initial_left = 0;
	this.delta_x = 0;
	this.delta_y = 0;
        delete(this.popup);
        this.popup = false;
        evt.stopPropagation();
      ]]></body>
    </method>

    <method name="dragRun">
      <parameter name="evt"/>
      <body><![CDATA[
	if (!this.dragElement)
	   return;

	//if (this.popup != evt.target){
	//   alert('no target');
        //   this.dragStop(false, evt);
        //   return;
	//   }

	if (this.hasAttribute('width') && this.hasAttribute('height'))
	   if ((evt.clientX > this.boxObject.x + this.width) || 
               (evt.clientY > this.boxObject.y + this.width)){
	      this.dragStop(false, null);
	      return;
	   }

	this.popup.left = evt.clientX + 1;
	this.popup.top = evt.clientY +1 ;

        //evt.stopPropagation();

      ]]></body>
    </method>

  </implementation>
  <handlers>
  <handler event="mousedown" button="0" action="this.dragStart(event);"/>
  <handler event="mousemove" action="this.dragRun(event);"/>
  <handler event="mouseup" button="0" action="this.dragStop(true, event);"/>
  <handler event="mouseout" action="this.dragStop(false, event);"/>
  <handler event="blur" action="this.dragStop(false, null);"/>
  </handlers>
</binding>

</bindings>
