//>>built // wrapped by build app define("dojox/drawing/tools/custom/Vector", ["dijit","dojo","dojox","dojo/require!dojox/drawing/tools/Arrow,dojox/drawing/util/positioning"], function(dijit,dojo,dojox){ dojo.provide("dojox.drawing.tools.custom.Vector"); dojo.require("dojox.drawing.tools.Arrow"); dojo.require("dojox.drawing.util.positioning"); dojox.drawing.tools.custom.Vector = dojox.drawing.util.oo.declare( // summary: // Creates a Vector Stencil. // description: // Generally the same as an arrow, except that the arrow // head is only at the end. There is additionaly functionality // to allow for a 'zero vector' - one with no length. // // dojox.drawing.tools.Arrow, function(options){ this.minimumSize = this.style.arrows.length; this.addShadow({size:3, mult:2}); }, { draws:true, type:"dojox.drawing.tools.custom.Vector", minimumSize:30, showAngle:true, changeAxis: function(cosphi){ // summary: // Converts a vector to and from the z axis. // If passed a cosphi value that is used to set // the axis, otherwise it is the opp of what it is. cosphi = cosphi!==undefined?cosphi:this.style.zAxis? 0 : 1; if(cosphi == 0){ this.style.zAxis = false; this.data.cosphi = 0; }else{ this.style.zAxis = true; var p = this.points; var pt = this.zPoint(); this.setPoints([ {x:p[0].x, y:p[0].y}, {x:pt.x, y:pt.y} ]); } this.render(); }, _createZeroVector: function(shp, d, sty){ // summary: // Special creation function for the zero-vector shape // var s = shp=="hit" ? this.minimumSize : this.minimumSize/6; var f = shp=="hit" ? sty.fill : null; d = { cx:this.data.x1, cy:this.data.y1, rx:s, ry:s }; this.remove(this[shp]); this[shp] = this.container.createEllipse(d) .setStroke(sty) .setFill(f); this.util.attr(this[shp], "drawingType", "stencil"); }, _create: function(/*String*/shp, /*StencilData*/d, /*Object*/sty){ // summary: // Creates a dojox.gfx.shape based on passed arguments. // Can be called many times by implementation to create // multiple shapes in one stencil. // this.remove(this[shp]); this[shp] = this.container.createLine(d) .setStroke(sty); this._setNodeAtts(this[shp]); }, onDrag: function(/*EventObject*/obj){ // summary: See stencil._Base.onDrag // if(this.created){ return; } var x1 = obj.start.x, y1 = obj.start.y, x2 = obj.x, y2 = obj.y; if(this.keys.shift && !this.style.zAxis){ var pt = this.util.snapAngle(obj, 45/180); x2 = pt.x; y2 = pt.y; } if(this.keys.alt){ // FIXME: // should double the length of the line // FIXME: // if alt dragging past ZERO it seems to work // but select/deselect shows bugs var dx = x2>x1 ? ((x2-x1)/2) : ((x1-x2)/-2); var dy = y2>y1 ? ((y2-y1)/2) : ((y1-y2)/-2); x1 -= dx; x2 -= dx; y1 -= dy; y2 -= dy; } if(this.style.zAxis){ var pts = this.zPoint(obj); x2 = pts.x; y2 = pts.y; } this.setPoints([ {x:x1, y:y1}, {x:x2, y:y2} ]); this.render(); }, onTransform: function(/* ? manager.Anchor */anchor){ // summary: // Called from anchor point mouse drag // also called from plugins.Pan.checkBounds if(!this._isBeingModified){ this.onTransformBegin(); } // this is not needed for anchor moves, but it // is for stencil move: this.setPoints(this.points); this.render(); }, anchorConstrain: function(x, y){ // summary: // Called from anchor point mouse drag if(!this.style.zAxis){ return null; } var radians = this.style.zAngle*Math.PI/180; //Constrain to angle var test = x<0 ? x>-y : x<-y; var dx = test ? x : -y/Math.tan(radians); var dy = !test ? y : -Math.tan(radians)*x; return {x:dx, y:dy} }, zPoint: function(obj){ // summary: // Takes any point and converts it to // be on the z-axis. if(obj===undefined){ if(!this.points[0]){ return null; }; var d = this.pointsToData(); obj = { start:{ x:d.x1, y:d.y1 }, x:d.x2, y:d.y2 }; } var radius = this.util.length(obj); var angle = this.util.angle(obj); angle<0 ? angle = 360 + angle : angle; angle = angle > 135 && angle < 315 ? this.style.zAngle : this.util.oppAngle(this.style.zAngle); return this.util.pointOnCircle(obj.start.x, obj.start.y, radius, angle); }, pointsToData: function(p){ // summary: // Converts points to data p = p || this.points; var cosphi = 0; var obj = {start:{x:p[0].x, y:p[0].y}, x:p[1].x, y:p[1].y}; if(this.style.zAxis && (this.util.length(obj)>this.minimumSize)){ var angle = this.util.angle(obj); angle<0 ? angle = 360 + angle : angle; cosphi = angle > 135 && angle < 315 ? 1 : -1; } this.data = { x1: p[0].x, y1: p[0].y, x2: p[1].x, y2: p[1].y, cosphi: cosphi }; return this.data; }, dataToPoints: function(o){ //summary: // Converts data to points. o = o || this.data; if(o.radius || o.angle){ // instead of using x1,x2,y1,y1, // it's been set as x,y,angle,radius var cosphi = 0; var pt = this.util.pointOnCircle(o.x,o.y,o.radius,o.angle); if(this.style.zAxis || (o.cosphi && o.cosphi!=0)){ this.style.zAxis = true; cosphi = o.angle > 135 && o.angle < 315 ? 1 : -1; } //console.log(" ---- pts:", pt.x, pt.y); this.data = o = { x1:o.x, y1:o.y, x2:pt.x, y2:pt.y, cosphi:cosphi } } this.points = [ {x:o.x1, y:o.y1}, {x:o.x2, y:o.y2} ]; return this.points; }, render: function(){ // summary: // Renders the 'hit' object (the shape used for an expanded // hit area and for highlighting) and the'shape' (the actual // display object). Additionally checks if Vector should be // drawn as an arrow or a circle (zero-length) // this.onBeforeRender(this); if(this.getRadius() >= this.minimumSize){ this._create("hit", this.data, this.style.currentHit); this._create("shape", this.data, this.style.current); }else{ this.data.cosphi = 0; this._createZeroVector("hit", this.data, this.style.currentHit); this._createZeroVector("shape", this.data, this.style.current); } }, onUp: function(/*EventObject*/obj){ // summary: See stencil._Base.onUp // if(this.created || !this._downOnCanvas){ return; } this._downOnCanvas = false; //Default vector for single click if(!this.shape){ var d = 100; obj.start.x = this.style.zAxis ? obj.start.x + d : obj.start.x; obj.y = obj.y+d; this.setPoints([ {x:obj.start.x, y:obj.start.y}, {x:obj.x, y:obj.y} ]); this.render(); } // When within minimum size this sets zero vector length to zero if(this.getRadius()