Vector.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. // wrapped by build app
  2. define("dojox/drawing/tools/custom/Vector", ["dijit","dojo","dojox","dojo/require!dojox/drawing/tools/Arrow,dojox/drawing/util/positioning"], function(dijit,dojo,dojox){
  3. dojo.provide("dojox.drawing.tools.custom.Vector");
  4. dojo.require("dojox.drawing.tools.Arrow");
  5. dojo.require("dojox.drawing.util.positioning");
  6. dojox.drawing.tools.custom.Vector = dojox.drawing.util.oo.declare(
  7. // summary:
  8. // Creates a Vector Stencil.
  9. // description:
  10. // Generally the same as an arrow, except that the arrow
  11. // head is only at the end. There is additionaly functionality
  12. // to allow for a 'zero vector' - one with no length.
  13. //
  14. //
  15. dojox.drawing.tools.Arrow,
  16. function(options){
  17. this.minimumSize = this.style.arrows.length;
  18. this.addShadow({size:3, mult:2});
  19. },
  20. {
  21. draws:true,
  22. type:"dojox.drawing.tools.custom.Vector",
  23. minimumSize:30,
  24. showAngle:true,
  25. changeAxis: function(cosphi){
  26. // summary:
  27. // Converts a vector to and from the z axis.
  28. // If passed a cosphi value that is used to set
  29. // the axis, otherwise it is the opp of what it is.
  30. cosphi = cosphi!==undefined?cosphi:this.style.zAxis? 0 : 1;
  31. if(cosphi == 0){
  32. this.style.zAxis = false;
  33. this.data.cosphi = 0;
  34. }else{
  35. this.style.zAxis = true;
  36. var p = this.points;
  37. var pt = this.zPoint();
  38. this.setPoints([
  39. {x:p[0].x, y:p[0].y},
  40. {x:pt.x, y:pt.y}
  41. ]);
  42. }
  43. this.render();
  44. },
  45. _createZeroVector: function(shp, d, sty){
  46. // summary:
  47. // Special creation function for the zero-vector shape
  48. //
  49. var s = shp=="hit" ? this.minimumSize : this.minimumSize/6;
  50. var f = shp=="hit" ? sty.fill : null;
  51. d = {
  52. cx:this.data.x1,
  53. cy:this.data.y1,
  54. rx:s,
  55. ry:s
  56. };
  57. this.remove(this[shp]);
  58. this[shp] = this.container.createEllipse(d)
  59. .setStroke(sty)
  60. .setFill(f);
  61. this.util.attr(this[shp], "drawingType", "stencil");
  62. },
  63. _create: function(/*String*/shp, /*StencilData*/d, /*Object*/sty){
  64. // summary:
  65. // Creates a dojox.gfx.shape based on passed arguments.
  66. // Can be called many times by implementation to create
  67. // multiple shapes in one stencil.
  68. //
  69. this.remove(this[shp]);
  70. this[shp] = this.container.createLine(d)
  71. .setStroke(sty);
  72. this._setNodeAtts(this[shp]);
  73. },
  74. onDrag: function(/*EventObject*/obj){
  75. // summary: See stencil._Base.onDrag
  76. //
  77. if(this.created){ return; }
  78. var x1 = obj.start.x,
  79. y1 = obj.start.y,
  80. x2 = obj.x,
  81. y2 = obj.y;
  82. if(this.keys.shift && !this.style.zAxis){
  83. var pt = this.util.snapAngle(obj, 45/180);
  84. x2 = pt.x;
  85. y2 = pt.y;
  86. }
  87. if(this.keys.alt){
  88. // FIXME:
  89. // should double the length of the line
  90. // FIXME:
  91. // if alt dragging past ZERO it seems to work
  92. // but select/deselect shows bugs
  93. var dx = x2>x1 ? ((x2-x1)/2) : ((x1-x2)/-2);
  94. var dy = y2>y1 ? ((y2-y1)/2) : ((y1-y2)/-2);
  95. x1 -= dx;
  96. x2 -= dx;
  97. y1 -= dy;
  98. y2 -= dy;
  99. }
  100. if(this.style.zAxis){
  101. var pts = this.zPoint(obj);
  102. x2 = pts.x;
  103. y2 = pts.y;
  104. }
  105. this.setPoints([
  106. {x:x1, y:y1},
  107. {x:x2, y:y2}
  108. ]);
  109. this.render();
  110. },
  111. onTransform: function(/* ? manager.Anchor */anchor){
  112. // summary:
  113. // Called from anchor point mouse drag
  114. // also called from plugins.Pan.checkBounds
  115. if(!this._isBeingModified){
  116. this.onTransformBegin();
  117. }
  118. // this is not needed for anchor moves, but it
  119. // is for stencil move:
  120. this.setPoints(this.points);
  121. this.render();
  122. },
  123. anchorConstrain: function(x, y){
  124. // summary:
  125. // Called from anchor point mouse drag
  126. if(!this.style.zAxis){ return null; }
  127. var radians = this.style.zAngle*Math.PI/180;
  128. //Constrain to angle
  129. var test = x<0 ? x>-y : x<-y;
  130. var dx = test ? x : -y/Math.tan(radians);
  131. var dy = !test ? y : -Math.tan(radians)*x;
  132. return {x:dx, y:dy}
  133. },
  134. zPoint: function(obj){
  135. // summary:
  136. // Takes any point and converts it to
  137. // be on the z-axis.
  138. if(obj===undefined){
  139. if(!this.points[0]){ return null; };
  140. var d = this.pointsToData();
  141. obj = {
  142. start:{
  143. x:d.x1,
  144. y:d.y1
  145. },
  146. x:d.x2,
  147. y:d.y2
  148. };
  149. }
  150. var radius = this.util.length(obj);
  151. var angle = this.util.angle(obj);
  152. angle<0 ? angle = 360 + angle : angle;
  153. angle = angle > 135 && angle < 315 ? this.style.zAngle : this.util.oppAngle(this.style.zAngle);
  154. return this.util.pointOnCircle(obj.start.x, obj.start.y, radius, angle);
  155. },
  156. pointsToData: function(p){
  157. // summary:
  158. // Converts points to data
  159. p = p || this.points;
  160. var cosphi = 0;
  161. var obj = {start:{x:p[0].x, y:p[0].y}, x:p[1].x, y:p[1].y};
  162. if(this.style.zAxis && (this.util.length(obj)>this.minimumSize)){
  163. var angle = this.util.angle(obj);
  164. angle<0 ? angle = 360 + angle : angle;
  165. cosphi = angle > 135 && angle < 315 ? 1 : -1;
  166. }
  167. this.data = {
  168. x1: p[0].x,
  169. y1: p[0].y,
  170. x2: p[1].x,
  171. y2: p[1].y,
  172. cosphi: cosphi
  173. };
  174. return this.data;
  175. },
  176. dataToPoints: function(o){
  177. //summary:
  178. // Converts data to points.
  179. o = o || this.data;
  180. if(o.radius || o.angle){
  181. // instead of using x1,x2,y1,y1,
  182. // it's been set as x,y,angle,radius
  183. var cosphi = 0;
  184. var pt = this.util.pointOnCircle(o.x,o.y,o.radius,o.angle);
  185. if(this.style.zAxis || (o.cosphi && o.cosphi!=0)){
  186. this.style.zAxis = true;
  187. cosphi = o.angle > 135 && o.angle < 315 ? 1 : -1;
  188. }
  189. //console.log(" ---- pts:", pt.x, pt.y);
  190. this.data = o = {
  191. x1:o.x,
  192. y1:o.y,
  193. x2:pt.x,
  194. y2:pt.y,
  195. cosphi:cosphi
  196. }
  197. }
  198. this.points = [
  199. {x:o.x1, y:o.y1},
  200. {x:o.x2, y:o.y2}
  201. ];
  202. return this.points;
  203. },
  204. render: function(){
  205. // summary:
  206. // Renders the 'hit' object (the shape used for an expanded
  207. // hit area and for highlighting) and the'shape' (the actual
  208. // display object). Additionally checks if Vector should be
  209. // drawn as an arrow or a circle (zero-length)
  210. //
  211. this.onBeforeRender(this);
  212. if(this.getRadius() >= this.minimumSize){
  213. this._create("hit", this.data, this.style.currentHit);
  214. this._create("shape", this.data, this.style.current);
  215. }else{
  216. this.data.cosphi = 0;
  217. this._createZeroVector("hit", this.data, this.style.currentHit);
  218. this._createZeroVector("shape", this.data, this.style.current);
  219. }
  220. },
  221. onUp: function(/*EventObject*/obj){
  222. // summary: See stencil._Base.onUp
  223. //
  224. if(this.created || !this._downOnCanvas){ return; }
  225. this._downOnCanvas = false;
  226. //Default vector for single click
  227. if(!this.shape){
  228. var d = 100;
  229. obj.start.x = this.style.zAxis ? obj.start.x + d : obj.start.x;
  230. obj.y = obj.y+d;
  231. this.setPoints([
  232. {x:obj.start.x, y:obj.start.y},
  233. {x:obj.x, y:obj.y}
  234. ]);
  235. this.render();
  236. }
  237. // When within minimum size this sets zero vector length to zero
  238. if(this.getRadius()<this.minimumSize){
  239. var p = this.points;
  240. this.setPoints([
  241. {x:p[0].x, y:p[0].y},
  242. {x:p[0].x, y:p[0].y}
  243. ]);
  244. }else{
  245. //SnapAngle fails for the zero length vector
  246. var p = this.points;
  247. var pt = this.style.zAxis ? this.zPoint(obj) : this.util.snapAngle(obj, this.angleSnap/180);
  248. this.setPoints([
  249. {x:p[0].x, y:p[0].y},
  250. {x:pt.x, y:pt.y}
  251. ]);
  252. }
  253. this.renderedOnce = true;
  254. this.onRender(this);
  255. }
  256. }
  257. );
  258. dojox.drawing.tools.custom.Vector.setup = {
  259. // summary: See stencil._Base ToolsSetup
  260. //
  261. name:"dojox.drawing.tools.custom.Vector",
  262. tooltip:"Vector Tool",
  263. iconClass:"iconVector"
  264. };
  265. if(dojox.drawing.defaults.zAxisEnabled){
  266. dojox.drawing.tools.custom.Vector.setup.secondary = {
  267. // summary:
  268. // Creates a secondary tool for the Vector Stencil.
  269. // description:
  270. // See Toolbar.js makeButtons function. The toolbar
  271. // checks Vector.setup for a secondary tool and requires
  272. // name, label, and funct. Currently it doesn't accept icon
  273. // and only uses text from label for the button. Funct is the
  274. // function that fires when the button is clicked.
  275. //
  276. // Setup and postSetup are optional
  277. // and allow tool specific functions to be added to the
  278. // Toolbar object as if they were written there.
  279. name: "vectorSecondary",
  280. label: "z-axis",
  281. funct: function(button){
  282. button.selected ? this.zDeselect(button) : this.zSelect(button);
  283. var stencils = this.drawing.stencils.selectedStencils;
  284. for(var nm in stencils){
  285. if(stencils[nm].shortType == "vector" && (stencils[nm].style.zAxis != dojox.drawing.defaults.zAxis)){
  286. var s = stencils[nm];
  287. s.changeAxis();
  288. //Reset anchors
  289. if(s.style.zAxis){ s.deselect(); s.select(); }
  290. }
  291. }
  292. },
  293. setup: function(){
  294. // summary:
  295. // All functions, variables and connections defined here
  296. // are treated as if they were added directly to toolbar.
  297. // They are included with the tool because secondary buttons
  298. // are tool specific.
  299. var zAxis = dojox.drawing.defaults.zAxis;
  300. this.zSelect = function(button){
  301. if(!button.enabled){ return; }
  302. zAxis = true;
  303. dojox.drawing.defaults.zAxis = true;
  304. button.select();
  305. this.vectorTest();
  306. this.zSelected = button;
  307. };
  308. this.zDeselect = function(button){
  309. if(!button.enabled){ return; }
  310. zAxis = false;
  311. dojox.drawing.defaults.zAxis = false;
  312. button.deselect();
  313. this.vectorTest();
  314. this.zSelected = null;
  315. };
  316. this.vectorTest = function(){
  317. dojo.forEach(this.buttons, function(b){
  318. if(b.toolType=="vector" && b.selected){
  319. this.drawing.currentStencil.style.zAxis = zAxis;
  320. }
  321. },this);
  322. };
  323. dojo.connect(this, "onRenderStencil", this, function(){ if(this.zSelected){ this.zDeselect(this.zSelected)}});
  324. var c = dojo.connect(this.drawing, "onSurfaceReady", this, function(){
  325. dojo.disconnect(c);
  326. dojo.connect(this.drawing.stencils, "onSelect", this, function(stencil){
  327. if(stencil.shortType == "vector"){
  328. if(stencil.style.zAxis){
  329. //If stencil is on the z-axis, update button to reflect that
  330. dojo.forEach(this.buttons, function(b){
  331. if(b.toolType=="vectorSecondary"){
  332. this.zSelect(b);
  333. }
  334. },this);
  335. }else{
  336. //Update button to not be z-axis
  337. dojo.forEach(this.buttons, function(b){
  338. if(b.toolType=="vectorSecondary"){
  339. this.zDeselect(b);
  340. }
  341. },this);
  342. }
  343. };
  344. });
  345. });
  346. },
  347. postSetup: function(btn){
  348. // summary:
  349. // Depending on the secondary tool, it may need
  350. // extra functionality for some of the basic functions.
  351. // Post is passed the button so those connections can
  352. // be made.
  353. dojo.connect(btn, "enable", function(){ dojox.drawing.defaults.zAxisEnabled = true; });
  354. dojo.connect(btn, "disable", function(){ dojox.drawing.defaults.zAxisEnabled = false; });
  355. }
  356. };
  357. }
  358. dojox.drawing.register(dojox.drawing.tools.custom.Vector.setup, "tool");
  359. });