<@doc hierarchy="GMLDOM">
   Aspect for drawing curved lines using quadratic bezier function

   <copyright>(c) SAP AG 2003-2006. All rights reserved.</copyright>
</doc@>


Aspect CurvedLine for GmlDrawing; 
inherit Line;


//////////////////////////////////////////////////////////////////////////////////////
// PROPERTIES


//////////////////////////////////////////////////////////////////////////////////////
// METHODS

override virtual method reroute()
   if (this.diagram.bufferedReroute(this)) return;
   
   var p1=this.srcpin.getCP(this.trgpin);
   var p2=this.trgpin.getCP(this.srcpin);
   var dx=p2.x-p1.x, dy=p2.y-p1.y, C=SPLITN(base.@controls);
   if (C.length==5 && C[0]==(p2.rot*4+p1.rot)) {
      var cx1=C[1], cy1=C[2], cx2=C[3], cy2=C[4];
   } else {
      var leg1=20*p1.scale, leg2=20*p2.scale;
      var cx1=(p1.rot==0 ? leg1 : p1.rot==2 ? -leg1 : 0), cy1=(p1.rot==3 ? leg1 : p1.rot==1 ? -leg1 : 0);
      var cx2=(p2.rot==0 ? leg2 : p2.rot==2 ? -leg2 : 0), cy2=(p2.rot==3 ? leg2 : p2.rot==1 ? -leg2 : 0);
      this.diagram.silentUpdate(this, '@controls', ''); // Silent update: (see Line.reroute)
   }
   var mx=(cx1+cx2+dx)/2, my=(cy1+cy2+dy)/2;

	// Silent update: (see Line.reroute)
   this.diagram.silentUpdate(this, '@path', this.path2str('q', cx1, cy1, mx, my, 'q', cx2+dx-mx, cy2+dy-my, dx-mx, dy-my));
   this.lineNode.setAttribute ('d', 'M'+p1.x+','+p1.y+base.@path);

   // calculate label position
   var x1 = p1.x+cx1;
   var x2 = p2.x+cx2;
   var y1 = p1.y+cy1
   var y2 = p2.y+cy2;
   var lx = (x1+x2)/2;
   var ly = (y1+y2)/2;
   var la = Math.atan2(y2-y1, x2-x1)*SVG.R2D;
   if (Math.abs(la) > 90) la += 180;

   this.labelNode.setAttribute('x', lx);
   this.labelNode.setAttribute('y', ly-3);
   this.labelNode.setAttribute('transform', 'rotate('+la+' '+lx+' '+ly+')');
end

override virtual method getHandlesData()
   var path=SPLITN(base.@path);
   if (path.length != 10) return null;
   var p1=this.srcpin.getCP(this.trgpin);
   return {
      C1: {cx:path[1]+p1.x,cy:path[2]+p1.y},
      C2: {cx:path[3]+path[6]+p1.x,cy:path[4]+path[7]+p1.y}
   }
end

override virtual method onHandleMove(ptr)
   switch (ptr.phase) {
      case #[PTR_START]:
         ptr.scrollMode = #[PTR_AUTOSCROLL];
         ptr.handle = ptr.source.getAttribute('handle');
         ptr.wire   = SVG.createElement(this.diagram.linesLayer, 'path', {fill:'none', 'stroke':this.base.@strokeColor, 'stroke-dasharray':'4 3', 'pointer-events':'none'});
         
         var path=SPLITN(base.@path);
         if (path.length != 10) { ptr.cancel=true; break; }
         ptr.p1  = this.srcpin.getCP(this.trgpin); 
         ptr.p2  = this.trgpin.getCP(this.srcpin); 
         ptr.dx  = ptr.p2.x-ptr.p1.x;
         ptr.dy  = ptr.p2.y-ptr.p1.y;
         ptr.cx1 = path[1];
         ptr.cy1 = path[2];
         ptr.cx2 = path[3]+path[6]-ptr.dx;
         ptr.cy2 = path[4]+path[7]-ptr.dy;
         break;
         
      case #[PTR_MOVE]:
         var p1=ptr.p1, p2=ptr.p2, dx=ptr.dx, dy=ptr.dy;
         var cx1=ptr.cx1, cy1=ptr.cy1, cx2=ptr.cx2, cy2=ptr.cy2;
         switch (ptr.handle) {
            case 'C1':  cx1 += ptr.offset.x; cy1 += ptr.offset.y; break;
            case 'C2':  cx2 += ptr.offset.x; cy2 += ptr.offset.y; break;
         }
         var mx=(cx1+cx2+dx)/2, my=(cy1+cy2+dy)/2;
         
         ptr.path = this.path2str('q', cx1, cy1, mx, my, 'q', cx2+dx-mx, cy2+dy-my, dx-mx, dy-my);
         ptr.controls = this.path2str(p2.rot*4+p1.rot, cx1, cy1, cx2, cy2);
         ptr.wire.setAttribute('d', 'M'+p1.x+','+p1.y+ptr.path);
         this.diagram.moveHandle(ptr.handle, ptr.pos.x, ptr.pos.y);
         break;

      case #[PTR_FINISH]:
			// Silent update: (see Line.reroute)
         this.diagram.silentUpdate(this, '@path', ptr.path);
         this.diagram.silentUpdate(this, '@controls', ptr.controls);
         this.reroute(); 
         SVG.removeElement(ptr.wire);
         if (!ptr.isOverSource) SVG.setProperty(ptr.source, 'class', 'handleNormal');
         break;

      case #[PTR_CANCEL]:
         SVG.removeElement(ptr.wire);
         if (!ptr.isOverSource) SVG.setProperty(ptr.source, 'class', 'handleNormal');
         var data=this.getHandlesData();
         this.diagram.moveHandle(ptr.handle, data[ptr.handle].cx, data[ptr.handle].cy);
         break;

   }
end