Annotation.js 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. define("dojox/sketch/Annotation", [
  2. "dojo/_base/kernel",
  3. "dojo/_base/lang",
  4. "dojo/_base/declare",
  5. "dojo/_base/json",
  6. "./Anchor",
  7. "./_Plugin"
  8. ], function(dojo){
  9. dojo.declare("dojox.sketch.AnnotationTool", dojox.sketch._Plugin, {
  10. onMouseDown: function(e){
  11. this._omd=true;
  12. },
  13. onMouseMove: function(e,rect){
  14. if(!this._omd){
  15. return;
  16. }
  17. if(this._cshape){
  18. this._cshape.setShape(rect);
  19. } else {
  20. this._cshape=this.figure.surface.createRect(rect)
  21. .setStroke({color:"#999", width:1, style:"ShortDot"})
  22. .setFill([255,255,255,0.7]);
  23. this._cshape.getEventSource().setAttribute("shape-rendering","crispEdges");
  24. }
  25. },
  26. onMouseUp: function(e){
  27. if(!this._omd){
  28. return;
  29. }
  30. this._omd=false;
  31. var f=this.figure;
  32. if(this._cshape){
  33. f.surface.remove(this._cshape);
  34. delete this._cshape;
  35. }
  36. if(!(f._startPoint.x==e.pageX&&f._startPoint.y==e.pageY)){
  37. // The minimum number of pixels one has to travel before a shape
  38. // gets drawn.
  39. var limit=10;
  40. if(Math.max(
  41. limit,
  42. Math.abs(f._absEnd.x-f._start.x),
  43. Math.abs(f._absEnd.y-f._start.y)
  44. )>limit){
  45. this._create(f._start, f._end);
  46. }
  47. }
  48. },
  49. _create: function(start,end){
  50. // create a new shape, needs to be accessible from the
  51. // dragging functions.
  52. var f=this.figure;
  53. var _=f.nextKey();
  54. var a=new (this.annotation)(f, _);
  55. a.transform={
  56. dx:f._calCol(start.x/f.zoomFactor),
  57. dy:f._calCol(start.y/f.zoomFactor)
  58. };
  59. a.end={
  60. x:f._calCol(end.x/f.zoomFactor),
  61. y:f._calCol(end.y/f.zoomFactor)
  62. };
  63. if(a.control){
  64. a.control={
  65. x:f._calCol((end.x/2)/f.zoomFactor),
  66. y:f._calCol((end.y/2)/f.zoomFactor)
  67. };
  68. }
  69. f.onBeforeCreateShape(a);
  70. a.initialize();
  71. f.select(a);
  72. f.onCreateShape(a);
  73. f.history.add(dojox.sketch.CommandTypes.Create,a);
  74. }
  75. });
  76. dojox.sketch.Annotation=function(figure, id){
  77. // for editing stuff.
  78. this.id=this._key=id;
  79. this.figure=figure;
  80. this.mode=dojox.sketch.Annotation.Modes.View;
  81. this.shape=null; // dojox.gfx.Group
  82. this.boundingBox=null; // rect for boundaries
  83. this.hasAnchors=true;
  84. this.anchors={}; // dojox.sketch.Anchor
  85. this._properties={
  86. 'stroke':{ color:"blue", width:2 },
  87. 'font': {family:"Arial", size:16, weight:"bold"},
  88. 'fill': "blue",
  89. 'label': ""
  90. };
  91. if(this.figure){
  92. this.figure.add(this);
  93. }
  94. };
  95. var p=dojox.sketch.Annotation.prototype;
  96. p.constructor=dojox.sketch.Annotation;
  97. p.type=function(){ return ''; };
  98. p.getType=function(){ return dojox.sketch.Annotation; };
  99. p.onRemove=function(noundo){
  100. //this.figure._delete([this],noundo);
  101. this.figure.history.add(dojox.sketch.CommandTypes.Delete, this, this.serialize());
  102. };
  103. p.property=function(name,/*?*/value){
  104. var r;
  105. name=name.toLowerCase();
  106. if(this._properties[name]!==undefined){
  107. r=this._properties[name];
  108. }
  109. if(arguments.length>1){
  110. this._properties[name]=value;
  111. if(r!=value){
  112. this.onPropertyChange(name,r);
  113. }
  114. }
  115. return r;
  116. };
  117. p.onPropertyChange=function(name,oldvalue){};
  118. p.onCreate=function(){
  119. this.figure.history.add(dojox.sketch.CommandTypes.Create,this);
  120. }
  121. p.onDblClick=function(e){
  122. var l=prompt('Set new text:',this.property('label'));
  123. if(l!==false){
  124. this.beginEdit(dojox.sketch.CommandTypes.Modify);
  125. this.property('label',l);
  126. this.draw();
  127. this.endEdit();
  128. }
  129. }
  130. p.initialize=function(){ };
  131. p.destroy=function(){ };
  132. p.draw=function(){ };
  133. p.apply=function(obj){ };
  134. p.serialize=function(){ };
  135. p.getBBox=function(){ };
  136. p.beginEdit=function(type){
  137. if(!this._type){
  138. this._type=type||dojox.sketch.CommandTypes.Move;
  139. this._prevState=this.serialize();
  140. }
  141. };
  142. p.endEdit=function(){
  143. if(this._prevState!=this.serialize()){
  144. this.figure.history.add(this._type,this,this._prevState);
  145. }
  146. this._type=this._prevState='';
  147. };
  148. p.calculate={
  149. slope:function(p1, p2){
  150. if(!(p1.x-p2.x)){ return 0; }
  151. return ((p1.y-p2.y)/(p1.x-p2.x));
  152. },
  153. dx:function(p1, p2, dy){
  154. var s=this.slope(p1,p2);
  155. if(s==0){ return s; }
  156. return dy/s;
  157. },
  158. dy:function(p1, p2, dx){
  159. return this.slope(p1,p2)*dx;
  160. }
  161. };
  162. p.drawBBox=function(){
  163. var r=this.getBBox();
  164. if(!this.boundingBox){
  165. this.boundingBox=this.shape.createRect(r)
  166. .moveToBack()
  167. .setStroke({color:"#999", width:1, style:"Dash"})
  168. .setFill([238,238,238,0.3]);
  169. this.boundingBox.getEventSource().setAttribute("id",this.id+"-boundingBox");
  170. this.boundingBox.getEventSource().setAttribute("shape-rendering","crispEdges");
  171. this.figure._add(this);
  172. } else {
  173. this.boundingBox.setShape(r);
  174. }
  175. };
  176. p.setBinding=function(pt){
  177. this.transform.dx+=pt.dx;
  178. this.transform.dy+=pt.dy;
  179. this.draw();
  180. };
  181. //p.doChange=function(pt){ };
  182. p.getTextBox=function(zoomfactor){
  183. var fp=this.property('font');
  184. //_getTextBox expect style camlCase properties, do it manually here
  185. var f = {fontFamily:fp.family,fontSize:fp.size,fontWeight:fp.weight};
  186. if(zoomfactor){
  187. f.fontSize = Math.floor(f.fontSize/zoomfactor);
  188. }
  189. return dojox.gfx._base._getTextBox(this.property('label'),f);
  190. };
  191. p.setMode=function(m){
  192. if(this.mode==m){ return; }
  193. this.mode=m;
  194. var method="disable";
  195. if(m==dojox.sketch.Annotation.Modes.Edit){ method="enable"; }
  196. if(method=="enable"){
  197. // draw the bounding box
  198. this.drawBBox();
  199. this.figure._add(this);
  200. } else {
  201. if(this.boundingBox){
  202. if(this.shape){ this.shape.remove(this.boundingBox); }
  203. this.boundingBox=null;
  204. }
  205. }
  206. for(var p in this.anchors){
  207. this.anchors[p][method]();
  208. }
  209. };
  210. p.zoom=function(pct){
  211. pct = pct || this.figure.zoomFactor;
  212. if(this.labelShape){
  213. var f=dojo.clone(this.property('font'));
  214. f.size=Math.ceil(f.size/pct)+"px";
  215. this.labelShape.setFont(f);
  216. }
  217. for(var n in this.anchors){
  218. this.anchors[n].zoom(pct);
  219. }
  220. //In VML, path are always the same width no matter scaling factors,
  221. //so aways use 1 for VML
  222. if(dojox.gfx.renderer=='vml'){
  223. pct=1;
  224. }
  225. if(this.pathShape){
  226. var s=dojo.clone(this.property('stroke'));
  227. s.width=pct>1?s.width:Math.ceil(s.width/pct)+"px";
  228. this.pathShape.setStroke(s);
  229. }
  230. };
  231. p.writeCommonAttrs=function(){
  232. return 'id="' + this.id + '" dojoxsketch:type="' + this.type() + '"'
  233. + ' transform="translate('+ this.transform.dx + "," + this.transform.dy + ')"'
  234. + (this.data?(' ><![CDATA[data:'+dojo.toJson(this.data)+']]'):'');
  235. };
  236. p.readCommonAttrs=function(obj){
  237. var i=0,cs=obj.childNodes,c;
  238. while((c=cs[i++])){
  239. if(c.nodeType==4){ //CDATA
  240. if(c.nodeValue.substr(0,11)=='properties:'){
  241. this._properties=dojo.fromJson(c.nodeValue.substr(11));
  242. }else if(c.nodeValue.substr(0,5)=='data:'){
  243. this.data=dojo.fromJson(c.nodeValue.substr(5));
  244. }else{
  245. console.error('unknown CDATA node in node ',obj);
  246. }
  247. }
  248. }
  249. if(obj.getAttribute('transform')){
  250. var t=obj.getAttribute('transform').replace("translate(","");
  251. var pt=t.split(",");
  252. this.transform.dx=parseFloat(pt[0],10);
  253. this.transform.dy=parseFloat(pt[1],10);
  254. }
  255. };
  256. dojox.sketch.Annotation.Modes={ View:0, Edit:1 };
  257. dojox.sketch.Annotation.register=function(name,toolclass){
  258. var cls=dojox.sketch[name+'Annotation'];
  259. dojox.sketch.registerTool(name, function(p){
  260. dojo.mixin(p, {
  261. shape: name,
  262. annotation:cls
  263. });
  264. return new (toolclass || dojox.sketch.AnnotationTool)(p);
  265. });
  266. };
  267. return dojox.sketch.Annotation;
  268. });