Digital Office Automation System Backend
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

ProcessDiagramCanvas.js 72KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172
  1. /**
  2. * Represents a canvas on which BPMN 2.0 constructs can be drawn.
  3. *
  4. * Some of the icons used are licenced under a Creative Commons Attribution 2.5
  5. * License, see http://www.famfamfam.com/lab/icons/silk/
  6. *
  7. * @see ProcessDiagramGenerator
  8. * @author (Java) Joram Barrez
  9. * @author (Javascript) Dmitry Farafonov
  10. */
  11. //Color.Cornsilk
  12. var ARROW_HEAD_SIMPLE = "simple";
  13. var ARROW_HEAD_EMPTY = "empty";
  14. var ARROW_HEAD_FILL = "FILL";
  15. var MULTILINE_VERTICAL_ALIGN_TOP = "top";
  16. var MULTILINE_VERTICAL_ALIGN_MIDDLE = "middle";
  17. var MULTILINE_VERTICAL_ALIGN_BOTTOM = "bottom";
  18. var MULTILINE_HORIZONTAL_ALIGN_LEFT = "start";
  19. var MULTILINE_HORIZONTAL_ALIGN_MIDDLE = "middle";
  20. var MULTILINE_HORIZONTAL_ALIGN_RIGHT = "end";
  21. // Predefined sized
  22. var TEXT_PADDING = 3;
  23. var ARROW_WIDTH = 4;
  24. var CONDITIONAL_INDICATOR_WIDTH = 16;
  25. var MARKER_WIDTH = 12;
  26. var ANNOTATION_TEXT_PADDING = 7;
  27. // Colors
  28. var TASK_COLOR = Color.OldLace; // original: Color.get(255, 255, 204);
  29. var TASK_STROKE_COLOR = Color.black; /*Color.SlateGrey; */
  30. //var EXPANDED_SUBPROCESS_ATTRS = Color.black; /*Color.SlateGrey; */
  31. var BOUNDARY_EVENT_COLOR = Color.white;
  32. var CONDITIONAL_INDICATOR_COLOR = Color.get(255, 255, 255);
  33. var HIGHLIGHT_COLOR = Color.Firebrick1;
  34. //var SEQUENCEFLOW_COLOR = Color.DimGrey;
  35. var SEQUENCEFLOW_COLOR = Color.black;
  36. var CATCHING_EVENT_COLOR = Color.black; /* Color.SlateGrey; */
  37. var START_EVENT_COLOR = Color.get(251,251,251);
  38. var START_EVENT_STROKE_COLOR = Color.black; /* Color.SlateGrey; */
  39. var END_EVENT_COLOR = Color.get(251,251,251);
  40. //var END_EVENT_STROKE_COLOR = Color.black;
  41. var NONE_END_EVENT_COLOR = Color.Firebrick4;
  42. var NONE_END_EVENT_STROKE_COLOR = Color.Firebrick4;
  43. var ERROR_END_EVENT_COLOR = Color.Firebrick;
  44. var ERROR_END_EVENT_STROKE_COLOR = Color.Firebrick;
  45. //var LABEL_COLOR = Color.get(112, 146, 190);
  46. var LABEL_COLOR = Color.get(72, 106, 150);
  47. // Fonts
  48. var NORMAL_FONT = {font: "10px Arial", opacity: 1, fill: Color.black};
  49. var LABEL_FONT = {font: "11px Arial", "font-style":"italic", opacity: 1, "fill": LABEL_COLOR};
  50. var LABEL_FONT_SMOOTH = {font: "10px Arial", "font-style":"italic", opacity: 1, "fill": LABEL_COLOR, stroke: LABEL_COLOR, "stroke-width":.4};
  51. var TASK_FONT = {font: "11px Arial", opacity: 1, fill: Color.black};
  52. var TASK_FONT_SMOOTH = {font: "11px Arial", opacity: 1, fill: Color.black, stroke: LABEL_COLOR, "stroke-width":.4};
  53. var POOL_LANE_FONT = {font: "11px Arial", opacity: 1, fill: Color.black};
  54. var EXPANDED_SUBPROCESS_FONT = {font: "11px Arial", opacity: 1, fill: Color.black};
  55. // Strokes
  56. var NORMAL_STROKE = 1;
  57. var SEQUENCEFLOW_STROKE = 1.5;
  58. var SEQUENCEFLOW_HIGHLIGHT_STROKE = 2;
  59. var THICK_TASK_BORDER_STROKE = 2.5;
  60. var GATEWAY_TYPE_STROKE = 3.2;
  61. var END_EVENT_STROKE = NORMAL_STROKE+2;
  62. var MULTI_INSTANCE_STROKE = 1.3;
  63. var EVENT_SUBPROCESS_ATTRS = {"stroke": Color.black, "stroke-width": NORMAL_STROKE, "stroke-dasharray": ". "};
  64. //var EXPANDED_SUBPROCESS_ATTRS = {"stroke": Color.black, "stroke-width": NORMAL_STROKE, "fill": Color.FloralWhite};
  65. var EXPANDED_SUBPROCESS_ATTRS = {"stroke": Color.black, "stroke-width": NORMAL_STROKE, "fill": Color.WhiteSmoke};
  66. var NON_INTERRUPTING_EVENT_STROKE = "- ";
  67. var TASK_CORNER_ROUND = 10;
  68. var EXPANDED_SUBPROCESS_CORNER_ROUND = 10;
  69. // icons
  70. var ICON_SIZE = 16;
  71. var ICON_PADDING = 4;
  72. var USERTASK_IMAGE = "images/deployer/user.png";
  73. var SCRIPTTASK_IMAGE = "images/deployer/script.png";
  74. var SERVICETASK_IMAGE = "images/deployer/service.png";
  75. var RECEIVETASK_IMAGE = "images/deployer/receive.png";
  76. var SENDTASK_IMAGE = "images/deployer/send.png";
  77. var MANUALTASK_IMAGE = "images/deployer/manual.png";
  78. var BUSINESS_RULE_TASK_IMAGE = "images/deployer/business_rule.png";
  79. var TIMER_IMAGE = "images/deployer/timer.png";
  80. var MESSAGE_CATCH_IMAGE = "images/deployer/message_catch.png";
  81. var MESSAGE_THROW_IMAGE = "images/deployer/message_throw.png";
  82. var ERROR_THROW_IMAGE = "images/deployer/error_throw.png";
  83. var ERROR_CATCH_IMAGE = "images/deployer/error_catch.png";
  84. var SIGNAL_CATCH_IMAGE = "images/deployer/signal_catch.png";
  85. var SIGNAL_THROW_IMAGE = "images/deployer/signal_throw.png";
  86. var MULTIPLE_CATCH_IMAGE = "images/deployer/multiple_catch.png";
  87. var ObjectType = {
  88. ELLIPSE: "ellipse",
  89. FLOW: "flow",
  90. RECT: "rect",
  91. RHOMBUS: "rhombus"
  92. };
  93. function OBJ(type){
  94. this.c = null;
  95. this.type = type;
  96. this.nestedElements = [];
  97. };
  98. OBJ.prototype = {
  99. };
  100. var CONNECTION_TYPE = {
  101. SEQUENCE_FLOW: "sequence_flow",
  102. MESSAGE_FLOW: "message_flow",
  103. ASSOCIATION: "association"
  104. };
  105. var ProcessDiagramCanvas = function(){
  106. };
  107. ProcessDiagramCanvas.prototype = {
  108. // var DefaultProcessDiagramCanvas = {
  109. canvasHolder: "holder",
  110. canvasWidth: 0,
  111. canvasHeight: 0,
  112. paint: Color.black,
  113. strokeWidth: 0,
  114. font: null,
  115. fontSmoothing: null,
  116. g: null,
  117. ninjaPaper: null,
  118. objects: [],
  119. processDefinitionId: null,
  120. activity: null,
  121. frame: null,
  122. debug: false,
  123. /**
  124. * Creates an empty canvas with given width and height.
  125. */
  126. init: function(width, height, processDefinitionId){
  127. this.canvasWidth = width;
  128. this.canvasHeight = height;
  129. // TODO: name it as 'canvasName'
  130. if (!processDefinitionId)
  131. processDefinitionId = "holder";
  132. this.processDefinitionId = processDefinitionId;
  133. this.canvasHolder = this.processDefinitionId;
  134. var h = document.getElementById(this.canvasHolder);
  135. if (!h) return;
  136. h.style.width = this.canvasWidth;
  137. h.style.height = this.canvasHeight;
  138. this.g = Raphael(this.canvasHolder);
  139. this.g.clear();
  140. //this.setPaint(Color.DimGrey);
  141. this.setPaint(Color.black);
  142. //this.setPaint(Color.white);
  143. this.setStroke(NORMAL_STROKE);
  144. //this.setFont("Arial", 11);
  145. this.setFont(NORMAL_FONT);
  146. //this.font = this.g.getFont("Arial");
  147. this.fontSmoothing = true;
  148. // ninja!
  149. var RaphaelOriginal = Raphael;
  150. this.ninjaPaper =(function (local_raphael) {
  151. var paper = local_raphael(1, 1, 1, 1, processDefinitionId);
  152. return paper;
  153. })(Raphael.ninja());
  154. Raphael = RaphaelOriginal;
  155. },
  156. setPaint: function(color){
  157. this.paint = color;
  158. },
  159. getPaint: function(){
  160. return this.paint;
  161. },
  162. setStroke: function(strokeWidth){
  163. this.strokeWidth = strokeWidth;
  164. },
  165. getStroke: function(){
  166. return this.strokeWidth;
  167. },
  168. /*
  169. setFont: function(family, weight, style, stretch){
  170. this.font = this.g.getFont(family, weight);
  171. },
  172. */
  173. setFont: function(font){
  174. this.font = font;
  175. },
  176. getFont: function(){
  177. return this.font;
  178. },
  179. drawShaddow: function(object){
  180. var border = object.clone();
  181. border.attr({"stroke-width": this.strokeWidth + 6,
  182. "stroke": Color.white,
  183. "fill": Color.white,
  184. "opacity": 1,
  185. "stroke-dasharray":null});
  186. //border.toBack();
  187. object.toFront();
  188. return border;
  189. },
  190. setConextObject: function(obj){
  191. this.contextObject = obj;
  192. },
  193. getConextObject: function(){
  194. return this.contextObject;
  195. },
  196. setContextToElement: function(object){
  197. var contextObject = this.getConextObject();
  198. object.id = contextObject.id;
  199. object.data("contextObject", contextObject);
  200. },
  201. onClick: function(event, instance, element){
  202. var overlay = element;
  203. var set = overlay.data("set");
  204. var contextObject = overlay.data("contextObject");
  205. //console.log("["+contextObject.getProperty("type")+"], activityId: " + contextObject.getId());
  206. if (ProcessDiagramGenerator.options && ProcessDiagramGenerator.options.on && ProcessDiagramGenerator.options.on.click) {
  207. var args = [instance, element, contextObject];
  208. ProcessDiagramGenerator.options.on.click.apply(event, args);
  209. }
  210. },
  211. onRightClick: function(event, instance, element){
  212. var overlay = element;
  213. var set = overlay.data("set");
  214. var contextObject = overlay.data("contextObject");
  215. //console.log("[%s], activityId: %s (RIGHTCLICK)", contextObject.getProperty("type"), contextObject.getId());
  216. if (ProcessDiagramGenerator.options && ProcessDiagramGenerator.options.on && ProcessDiagramGenerator.options.on.rightClick) {
  217. var args = [instance, element, contextObject];
  218. ProcessDiagramGenerator.options.on.rightClick.apply(event, args);
  219. }
  220. },
  221. onHoverIn: function(event, instance, element){
  222. var overlay = element;
  223. var set = overlay.data("set");
  224. var contextObject = overlay.data("contextObject");
  225. var border = instance.g.getById(contextObject.id + "_border");
  226. border.attr("opacity", 0.3);
  227. // provide callback
  228. if (ProcessDiagramGenerator.options && ProcessDiagramGenerator.options.on && ProcessDiagramGenerator.options.on.over) {
  229. var args = [instance, element, contextObject];
  230. ProcessDiagramGenerator.options.on.over.apply(event, args);
  231. }
  232. },
  233. onHoverOut: function(event, instance, element){
  234. var overlay = element;
  235. var set = overlay.data("set");
  236. var contextObject = overlay.data("contextObject");
  237. var border = instance.g.getById(contextObject.id + "_border");
  238. border.attr("opacity", 0.0);
  239. // provide callback
  240. if (ProcessDiagramGenerator.options && ProcessDiagramGenerator.options.on && ProcessDiagramGenerator.options.on.out) {
  241. var args = [instance, element, contextObject];
  242. ProcessDiagramGenerator.options.on.out.apply(event, args);
  243. }
  244. },
  245. addHandlers: function(set, x, y, width, height, type){
  246. var contextObject = this.getConextObject();
  247. var cx = x+width/2, cy = y+height/2;
  248. if (type == "event") {
  249. var border = this.g.ellipse(cx, cy, width/2+4, height/2+4);
  250. var overlay = this.g.ellipse(cx, cy, width/2, height/2);
  251. } else if (type == "gateway") {
  252. // rhombus
  253. var border = this.g.path( "M" + (x - 4) + " " + (y + (height / 2)) +
  254. "L" + (x + (width / 2)) + " " + (y + height + 4) +
  255. "L" + (x + width + 4) + " " + (y + (height / 2)) +
  256. "L" + (x + (width / 2)) + " " + (y - 4) +
  257. "z" );
  258. var overlay = this.g.path( "M" + x + " " + (y + (height / 2)) +
  259. "L" + (x + (width / 2)) + " " + (y + height) +
  260. "L" + (x + width) + " " + (y + (height / 2)) +
  261. "L" + (x + (width / 2)) + " " + y +
  262. "z" );
  263. } else if (type == "task") {
  264. var border = this.g.rect(x - 4, y - 4, width+9, height+9, TASK_CORNER_ROUND+4);
  265. var overlay = this.g.rect(x, y, width, height, TASK_CORNER_ROUND);
  266. }
  267. border.attr({stroke: Color.get(132,112,255)/*Color.Tan1*/,"stroke-width": 4, opacity: 0.0});
  268. border.id = contextObject.id + "_border";
  269. set.push(border);
  270. overlay.attr({stroke: Color.Orange,"stroke-width": 3, fill: Color.get(0,0,0), opacity: 0.0, cursor: "hand"});
  271. overlay.data("set",set);
  272. overlay.id = contextObject.id;
  273. overlay.data("contextObject",contextObject);
  274. var instance = this;
  275. overlay.mousedown(function(event){if (event.button == 2) instance.onRightClick(event, instance, this);});
  276. overlay.click(function(event){instance.onClick(event, instance, this);});
  277. overlay.hover(function(event){instance.onHoverIn(event, instance, this);}, function(event){instance.onHoverOut(event, instance, this);});
  278. },
  279. /*
  280. * Start Events:
  281. *
  282. * drawNoneStartEvent
  283. * drawTimerStartEvent
  284. * drawMessageStartEvent
  285. * drawErrorStartEvent
  286. * drawSignalStartEvent
  287. * _drawStartEventImage
  288. * _drawStartEvent
  289. */
  290. drawNoneStartEvent: function(x, y, width, height) {
  291. this.g.setStart();
  292. var isInterrupting = undefined;
  293. this._drawStartEvent(x, y, width, height, isInterrupting, null);
  294. var set = this.g.setFinish();
  295. this.addHandlers(set, x, y, width, height, "event");
  296. },
  297. drawTimerStartEvent: function(x, y, width, height, isInterrupting, name) {
  298. this.g.setStart();
  299. this._drawStartEvent(x, y, width, height, isInterrupting, null);
  300. var cx = x + width/2 - this.getStroke()/4;
  301. var cy = y + height/2 - this.getStroke()/4;
  302. var w = width*.9;// - this.getStroke()*2;
  303. var h = height*.9;// - this.getStroke()*2;
  304. this._drawClock(cx, cy, w, h);
  305. if (this.gebug)
  306. var center = this.g.ellipse(cx, cy, 3, 3).attr({stroke:"none", fill: Color.green});
  307. var set = this.g.setFinish();
  308. this.addHandlers(set, x, y, width, height, "event");
  309. },
  310. drawMessageStartEvent: function(x, y, width, height, isInterrupting, name) {
  311. this.g.setStart();
  312. this._drawStartEvent(x, y, width, height, isInterrupting, null);
  313. this._drawStartEventImage(x, y, width, height, MESSAGE_CATCH_IMAGE);
  314. var set = this.g.setFinish();
  315. this.addHandlers(set, x, y, width, height, "event");
  316. },
  317. drawErrorStartEvent: function(x, y, width, height, name) {
  318. this.g.setStart();
  319. var isInterrupting = undefined;
  320. this._drawStartEvent(x, y, width, height, isInterrupting);
  321. this._drawStartEventImage(x, y, width, height, ERROR_CATCH_IMAGE);
  322. var set = this.g.setFinish();
  323. this.addHandlers(set, x, y, width, height, "event");
  324. },
  325. drawSignalStartEvent: function(x, y, width, height, isInterrupting, name) {
  326. this.g.setStart();
  327. this._drawStartEvent(x, y, width, height, isInterrupting, null);
  328. this._drawStartEventImage(x, y, width, height, SIGNAL_CATCH_IMAGE);
  329. var set = this.g.setFinish();
  330. this.addHandlers(set, x, y, width, height, "event");
  331. },
  332. drawMultipleStartEvent: function(x, y, width, height, isInterrupting, name) {
  333. this.g.setStart();
  334. this._drawStartEvent(x, y, width, height, isInterrupting, null);
  335. var cx = x + width/2 - this.getStroke()/4;
  336. var cy = y + height/2 - this.getStroke()/4;
  337. var w = width*1;
  338. var h = height*1;
  339. this._drawPentagon(cx, cy, w, h);
  340. var set = this.g.setFinish();
  341. this.addHandlers(set, x, y, width, height, "event");
  342. },
  343. _drawStartEventImage: function(x, y, width, height, image){
  344. var cx = x + width/2 - this.getStroke()/2;
  345. var cy = y + height/2 - this.getStroke()/2;
  346. var w = width*.65;// - this.getStroke()*2;
  347. var h = height*.65;// - this.getStroke()*2;
  348. var img = this.g.image(image, cx-w/2, cy-h/2, w, h);
  349. },
  350. _drawStartEvent: function(x, y, width, height, isInterrupting){
  351. var originalPaint = this.getPaint();
  352. if (typeof(START_EVENT_STROKE_COLOR) != "undefined")
  353. this.setPaint(START_EVENT_STROKE_COLOR);
  354. width -= this.strokeWidth / 2;
  355. height -= this.strokeWidth / 2;
  356. x = x + width/2;
  357. y = y + height/2;
  358. var circle = this.g.ellipse(x, y, width/2, height/2);
  359. circle.attr({"stroke-width": this.strokeWidth,
  360. "stroke": this.paint,
  361. //"stroke": START_EVENT_STROKE_COLOR,
  362. "fill": START_EVENT_COLOR});
  363. // white shaddow
  364. this.drawShaddow(circle);
  365. if (isInterrupting!=null && isInterrupting!=undefined && !isInterrupting)
  366. circle.attr({"stroke-dasharray": NON_INTERRUPTING_EVENT_STROKE});
  367. this.setContextToElement(circle);
  368. this.setPaint(originalPaint);
  369. },
  370. /*
  371. * End Events:
  372. *
  373. * drawNoneEndEvent
  374. * drawErrorEndEvent
  375. * drawMessageEndEvent
  376. * drawSignalEndEvent
  377. * drawMultipleEndEvent
  378. * _drawEndEventImage
  379. * _drawNoneEndEvent
  380. */
  381. drawNoneEndEvent: function(x, y, width, height) {
  382. this.g.setStart();
  383. this._drawNoneEndEvent(x, y, width, height, null, "noneEndEvent");
  384. var set = this.g.setFinish();
  385. this.addHandlers(set, x, y, width, height, "event");
  386. },
  387. drawErrorEndEvent: function(x, y, width, height) {
  388. this.g.setStart();
  389. var type = "errorEndEvent";
  390. this._drawNoneEndEvent(x, y, width, height, null, type);
  391. this._drawEndEventImage(x, y, width, height, ERROR_THROW_IMAGE);
  392. var set = this.g.setFinish();
  393. this.addHandlers(set, x, y, width, height, "event");
  394. },
  395. drawMessageEndEvent: function(x, y, width, height, name) {
  396. this.g.setStart();
  397. var type = "errorEndEvent";
  398. this._drawNoneEndEvent(x, y, width, height, null, type);
  399. this._drawEndEventImage(x, y, width, height, MESSAGE_THROW_IMAGE);
  400. var set = this.g.setFinish();
  401. this.addHandlers(set, x, y, width, height, "event");
  402. },
  403. drawSignalEndEvent: function(x, y, width, height, name) {
  404. this.g.setStart();
  405. var type = "errorEndEvent";
  406. this._drawNoneEndEvent(x, y, width, height, null, type);
  407. this._drawEndEventImage(x, y, width, height, SIGNAL_THROW_IMAGE);
  408. var set = this.g.setFinish();
  409. this.addHandlers(set, x, y, width, height, "event");
  410. },
  411. drawMultipleEndEvent: function(x, y, width, height, name) {
  412. this.g.setStart();
  413. var type = "errorEndEvent";
  414. this._drawNoneEndEvent(x, y, width, height, null, type);
  415. var cx = x + width/2;// - this.getStroke();
  416. var cy = y + height/2;// - this.getStroke();
  417. var w = width*1;
  418. var h = height*1;
  419. var filled = true;
  420. this._drawPentagon(cx, cy, w, h, filled);
  421. var set = this.g.setFinish();
  422. this.addHandlers(set, x, y, width, height, "event");
  423. },
  424. drawTerminateEndEvent: function(x, y, width, height) {
  425. this.g.setStart();
  426. var type = "errorEndEvent";
  427. this._drawNoneEndEvent(x, y, width, height, null, type);
  428. var cx = x + width/2;// - this.getStroke()/2;
  429. var cy = y + height/2;// - this.getStroke()/2;
  430. var w = width/2*.6;
  431. var h = height/2*.6;
  432. var circle = this.g.ellipse(cx, cy, w, h).attr({fill: Color.black});
  433. var set = this.g.setFinish();
  434. this.addHandlers(set, x, y, width, height, "event");
  435. },
  436. _drawEndEventImage: function(x, y, width, height, image){
  437. var cx = x + width/2 - this.getStroke()/2;
  438. var cy = y + height/2 - this.getStroke()/2;
  439. var w = width*.65;
  440. var h = height*.65;
  441. var img = this.g.image(image, cx-w/2, cy-h/2, w, h);
  442. },
  443. _drawNoneEndEvent: function(x, y, width, height, image, type) {
  444. var originalPaint = this.getPaint();
  445. if (typeof(CATCHING_EVENT_COLOR) != "undefined")
  446. this.setPaint(CATCHING_EVENT_COLOR);
  447. var strokeColor = this.getPaint();
  448. var fillColor = this.getPaint();
  449. if (type == "errorEndEvent") {
  450. strokeColor = ERROR_END_EVENT_STROKE_COLOR;
  451. fillColor = ERROR_END_EVENT_COLOR;
  452. } else if (type == "noneEndEvent") {
  453. strokeColor = NONE_END_EVENT_STROKE_COLOR;
  454. fillColor = NONE_END_EVENT_COLOR;
  455. } else
  456. // event circles
  457. width -= this.strokeWidth / 2;
  458. height -= this.strokeWidth / 2;
  459. x = x + width/2;// + this.strokeWidth/2;
  460. y = y + width/2;// + this.strokeWidth/2;
  461. // outerCircle
  462. var outerCircle = this.g.ellipse(x, y, width/2, height/2);
  463. // white shaddow
  464. var shaddow = this.drawShaddow(outerCircle);
  465. outerCircle.attr({"stroke-width": this.strokeWidth,
  466. "stroke": strokeColor,
  467. "fill": fillColor});
  468. var innerCircleX = x;
  469. var innerCircleY = y;
  470. var innerCircleWidth = width/2 - 2;
  471. var innerCircleHeight = height/2 - 2;
  472. var innerCircle = this.g.ellipse(innerCircleX, innerCircleY, innerCircleWidth, innerCircleHeight);
  473. innerCircle.attr({"stroke-width": this.strokeWidth,
  474. "stroke": strokeColor,
  475. "fill": Color.white});
  476. // TODO: implement it
  477. //var originalPaint = this.getPaint();
  478. //this.g.setPaint(BOUNDARY_EVENT_COLOR);
  479. this.setPaint(originalPaint);
  480. },
  481. /*
  482. * Catching Events:
  483. *
  484. * drawCatchingTimerEvent
  485. * drawCatchingErrorEvent
  486. * drawCatchingSignalEvent
  487. * drawCatchingMessageEvent
  488. * drawCatchingMultipleEvent
  489. * _drawCatchingEventImage
  490. * _drawCatchingEvent
  491. */
  492. drawCatchingTimerEvent: function(x, y, width, height, isInterrupting, name) {
  493. this.g.setStart();
  494. this._drawCatchingEvent(x, y, width, height, isInterrupting, null);
  495. var innerCircleWidth = width - 4;
  496. var innerCircleHeight = height - 4;
  497. var cx = x + width/2 - this.getStroke()/4;
  498. var cy = y + height/2 - this.getStroke()/4;
  499. var w = innerCircleWidth*.9;// - this.getStroke()*2;
  500. var h = innerCircleHeight*.9;// - this.getStroke()*2;
  501. this._drawClock(cx, cy, w, h);
  502. var set = this.g.setFinish();
  503. this.addHandlers(set, x, y, width, height, "event");
  504. },
  505. drawCatchingErrorEvent: function(x, y, width, height, isInterrupting, name) {
  506. this.g.setStart();
  507. this._drawCatchingEvent(x, y, width, height, isInterrupting, null);
  508. this._drawCatchingEventImage(x, y, width, height, ERROR_CATCH_IMAGE);
  509. var set = this.g.setFinish();
  510. this.addHandlers(set, x, y, width, height, "event");
  511. },
  512. drawCatchingSignalEvent: function(x, y, width, height, isInterrupting, name) {
  513. this.g.setStart();
  514. this._drawCatchingEvent(x, y, width, height, isInterrupting, null);
  515. this._drawCatchingEventImage(x, y, width, height, SIGNAL_CATCH_IMAGE);
  516. var set = this.g.setFinish();
  517. this.addHandlers(set, x, y, width, height, "event");
  518. },
  519. drawCatchingMessageEvent: function(x, y, width, height, isInterrupting, name) {
  520. this.g.setStart();
  521. this._drawCatchingEvent(x, y, width, height, isInterrupting, null);
  522. this._drawCatchingEventImage(x, y, width, height, MESSAGE_CATCH_IMAGE);
  523. var set = this.g.setFinish();
  524. this.addHandlers(set, x, y, width, height, "event");
  525. },
  526. drawCatchingMultipleEvent: function(x, y, width, height, isInterrupting, name) {
  527. this.g.setStart();
  528. this._drawCatchingEvent(x, y, width, height, isInterrupting, null);
  529. var cx = x + width/2 - this.getStroke();
  530. var cy = y + height/2 - this.getStroke();
  531. var w = width*.9;
  532. var h = height*.9;
  533. this._drawPentagon(cx, cy, w, h);
  534. var set = this.g.setFinish();
  535. this.addHandlers(set, x, y, width, height, "event");
  536. },
  537. _drawCatchingEventImage: function(x, y, width, height, image){
  538. var innerCircleWidth = width - 4;
  539. var innerCircleHeight = height - 4;
  540. var cx = x + width/2 - this.getStroke()/2;
  541. var cy = y + height/2 - this.getStroke()/2;
  542. var w = innerCircleWidth*.6;// - this.getStroke()*2;
  543. var h = innerCircleHeight*.6;// - this.getStroke()*2;
  544. var img = this.g.image(image, cx-w/2, cy-h/2, w, h);
  545. },
  546. _drawCatchingEvent: function(x, y, width, height, isInterrupting, image) {
  547. var originalPaint = this.getPaint();
  548. if (typeof(CATCHING_EVENT_COLOR) != "undefined")
  549. this.setPaint(CATCHING_EVENT_COLOR);
  550. // event circles
  551. width -= this.strokeWidth / 2;
  552. height -= this.strokeWidth / 2;
  553. x = x + width/2;// + this.strokeWidth/2;
  554. y = y + width/2;// + this.strokeWidth/2;
  555. // outerCircle
  556. var outerCircle = this.g.ellipse(x, y, width/2, height/2);
  557. // white shaddow
  558. var shaddow = this.drawShaddow(outerCircle);
  559. //console.log("isInterrupting: " + isInterrupting, "x:" , x, "y:",y);
  560. if (isInterrupting!=null && isInterrupting!=undefined && !isInterrupting)
  561. outerCircle.attr({"stroke-dasharray": NON_INTERRUPTING_EVENT_STROKE});
  562. outerCircle.attr({"stroke-width": this.strokeWidth,
  563. "stroke": this.getPaint(),
  564. "fill": BOUNDARY_EVENT_COLOR});
  565. var innerCircleX = x;
  566. var innerCircleY = y;
  567. var innerCircleRadiusX = width/2 - 4;
  568. var innerCircleRadiusY = height/2 - 4;
  569. var innerCircle = this.g.ellipse(innerCircleX, innerCircleY, innerCircleRadiusX, innerCircleRadiusY);
  570. innerCircle.attr({"stroke-width": this.strokeWidth,
  571. "stroke": this.getPaint()});
  572. if (image) {
  573. var imageWidth = imageHeight = innerCircleRadiusX*1.2 + this.getStroke()*2;
  574. var imageX = innerCircleX-imageWidth/2 - this.strokeWidth/2;
  575. var imageY = innerCircleY-imageWidth/2 - this.strokeWidth/2;
  576. var img = this.g.image(image, imageX, imageY, imageWidth, imageHeight);
  577. }
  578. this.setPaint(originalPaint);
  579. var set = this.g.set();
  580. set.push(outerCircle, innerCircle, shaddow);
  581. this.setContextToElement(outerCircle);
  582. // TODO: add shapes to set
  583. /*
  584. var st = this.g.set();
  585. st.push(
  586. this.g.ellipse(innerCircleX, innerCircleY, 2, 2),
  587. this.g.ellipse(imageX, imageY, 2, 2)
  588. );
  589. st.attr({fill: "red", "stroke-width":0});
  590. */
  591. },
  592. /*
  593. * Catching Events:
  594. *
  595. * drawThrowingNoneEvent
  596. * drawThrowingSignalEvent
  597. * drawThrowingMessageEvent
  598. * drawThrowingMultipleEvent
  599. */
  600. drawThrowingNoneEvent: function(x, y, width, height, name) {
  601. this.g.setStart();
  602. this._drawCatchingEvent(x, y, width, height, null, null);
  603. var set = this.g.setFinish();
  604. this.addHandlers(set, x, y, width, height, "event");
  605. },
  606. drawThrowingSignalEvent: function(x, y, width, height, name) {
  607. this.g.setStart();
  608. this._drawCatchingEvent(x, y, width, height, null, null);
  609. this._drawCatchingEventImage(x, y, width, height, SIGNAL_THROW_IMAGE);
  610. var set = this.g.setFinish();
  611. this.addHandlers(set, x, y, width, height, "event");
  612. },
  613. drawThrowingMessageEvent: function(x, y, width, height, name) {
  614. this.g.setStart();
  615. this._drawCatchingEvent(x, y, width, height, null, null);
  616. this._drawCatchingEventImage(x, y, width, height, MESSAGE_THROW_IMAGE);
  617. var set = this.g.setFinish();
  618. this.addHandlers(set, x, y, width, height, "event");
  619. },
  620. drawThrowingMultipleEvent: function(x, y, width, height, name) {
  621. this.g.setStart();
  622. this._drawCatchingEvent(x, y, width, height, null, null);
  623. var cx = x + width/2 - this.getStroke();
  624. var cy = y + height/2 - this.getStroke();
  625. var w = width*.9;
  626. var h = height*.9;
  627. var filled = true;
  628. this._drawPentagon(cx, cy, w, h, filled);
  629. var set = this.g.setFinish();
  630. this.addHandlers(set, x, y, width, height, "event");
  631. },
  632. /*
  633. * Draw flows:
  634. *
  635. * _connectFlowToActivity
  636. * _drawFlow
  637. * _drawDefaultSequenceFlowIndicator
  638. * drawSequenceflow
  639. * drawMessageflow
  640. * drawAssociation
  641. * _drawCircleTail
  642. * _drawArrowHead
  643. * _drawConditionalSequenceFlowIndicator
  644. * drawSequenceflowWithoutArrow
  645. */
  646. _connectFlowToActivity: function(sourceActivityId, destinationActivityId, waypoints){
  647. var sourceActivity = this.g.getById(sourceActivityId);
  648. var destinationActivity = this.g.getById(destinationActivityId);
  649. if (sourceActivity == null || destinationActivity == null) {
  650. if (sourceActivity == null)
  651. console.error("source activity["+sourceActivityId+"] not found");
  652. else
  653. console.error("destination activity["+destinationActivityId+"] not found");
  654. return null;
  655. }
  656. var bbSourceActivity = sourceActivity.getBBox()
  657. var bbDestinationActivity = destinationActivity.getBBox()
  658. var path = [];
  659. var newWaypoints = [];
  660. for(var i = 0; i < waypoints.length; i++){
  661. var pathType = ""
  662. if (i==0)
  663. pathType = "M";
  664. else
  665. pathType = "L";
  666. path.push([pathType, waypoints[i].x, waypoints[i].y]);
  667. newWaypoints.push({x:waypoints[i].x, y:waypoints[i].y});
  668. }
  669. var ninjaPathSourceActivity = this.ninjaPaper.path(sourceActivity.realPath);
  670. var ninjaPathDestinationActivity = this.ninjaPaper.path(destinationActivity.realPath);
  671. var ninjaBBSourceActivity = ninjaPathSourceActivity.getBBox();
  672. var ninjaBBDestinationActivity = ninjaPathDestinationActivity.getBBox();
  673. // set target of the flow to the center of the taskObject
  674. var newPath = path;
  675. var originalSource = {x: newPath[0][1], y: newPath[0][2]};
  676. var originalTarget = {x: newPath[newPath.length-1][1], y: newPath[newPath.length-1][2]};
  677. newPath[0][1] = ninjaBBSourceActivity.x + (ninjaBBSourceActivity.x2 - ninjaBBSourceActivity.x ) / 2;
  678. newPath[0][2] = ninjaBBSourceActivity.y + (ninjaBBSourceActivity.y2 - ninjaBBSourceActivity.y ) / 2;
  679. newPath[newPath.length-1][1] = ninjaBBDestinationActivity.x + (ninjaBBDestinationActivity.x2 - ninjaBBDestinationActivity.x ) / 2;
  680. newPath[newPath.length-1][2] = ninjaBBDestinationActivity.y + (ninjaBBDestinationActivity.y2 - ninjaBBDestinationActivity.y ) / 2;
  681. var ninjaPathFlowObject = this.ninjaPaper.path(newPath);
  682. var ninjaBBFlowObject = ninjaPathFlowObject.getBBox();
  683. var intersectionsSource = Raphael.pathIntersection(ninjaPathSourceActivity.realPath, ninjaPathFlowObject.realPath);
  684. var intersectionsDestination = Raphael.pathIntersection(ninjaPathDestinationActivity.realPath, ninjaPathFlowObject.realPath);
  685. var intersectionSource = intersectionsSource.pop();
  686. var intersectionDestination = intersectionsDestination.pop();
  687. if (intersectionSource != undefined) {
  688. if (this.gebug) {
  689. var diameter = 5;
  690. var dotOriginal = this.g.ellipse(originalSource.x, originalSource.y, diameter, diameter).attr({"fill": Color.white, "stroke": Color.Pink});
  691. var dot = this.g.ellipse(intersectionSource.x, intersectionSource.y, diameter, diameter).attr({"fill": Color.white, "stroke": Color.Green});
  692. }
  693. newWaypoints[0].x = intersectionSource.x;
  694. newWaypoints[0].y = intersectionSource.y;
  695. }
  696. if (intersectionDestination != undefined) {
  697. if (this.gebug) {
  698. var diameter = 5;
  699. var dotOriginal = this.g.ellipse(originalTarget.x, originalTarget.y, diameter, diameter).attr({"fill": Color.white, "stroke": Color.Red});
  700. var dot = this.g.ellipse(intersectionDestination.x, intersectionDestination.y, diameter, diameter).attr({"fill": Color.white, "stroke": Color.Blue});
  701. }
  702. newWaypoints[newWaypoints.length-1].x = intersectionDestination.x;
  703. newWaypoints[newWaypoints.length-1].y = intersectionDestination.y;
  704. }
  705. this.ninjaPaper.clear();
  706. return newWaypoints;
  707. },
  708. _drawFlow: function(waypoints, conditional, isDefault, highLighted, withArrowHead, connectionType){
  709. var originalPaint = this.getPaint();
  710. var originalStroke = this.getStroke();
  711. this.setPaint(SEQUENCEFLOW_COLOR);
  712. this.setStroke(SEQUENCEFLOW_STROKE);
  713. if (highLighted) {
  714. this.setPaint(HIGHLIGHT_COLOR);
  715. this.setStroke(SEQUENCEFLOW_HIGHLIGHT_STROKE);
  716. }
  717. // TODO: generate polylineId or do something!!
  718. var uuid = Raphael.createUUID();
  719. var contextObject = this.getConextObject();
  720. var newWaypoints = waypoints;
  721. if (contextObject) {
  722. var newWaypoints = this._connectFlowToActivity(contextObject.sourceActivityId, contextObject.destinationActivityId, waypoints);
  723. if (!newWaypoints) {
  724. console.error("Error draw flow from '"+contextObject.sourceActivityId+"' to '"+contextObject.destinationActivityId+"' ");
  725. return;
  726. }
  727. }
  728. var polyline = new Polyline(uuid, newWaypoints, this.getStroke());
  729. //var polyline = new Polyline(waypoints, 3);
  730. polyline.element = this.g.path(polyline.path);
  731. polyline.element.attr("stroke-width", this.getStroke());
  732. polyline.element.attr("stroke", this.getPaint());
  733. if (contextObject) {
  734. polyline.element.id = contextObject.id;
  735. polyline.element.data("contextObject", contextObject);
  736. } else {
  737. polyline.element.id = uuid;
  738. }
  739. /*
  740. polyline.element.mouseover(function(){
  741. this.attr({"stroke-width": NORMAL_STROKE + 2});
  742. }).mouseout(function(){
  743. this.attr({"stroke-width": NORMAL_STROKE});
  744. });
  745. */
  746. var last = polyline.getAnchorsCount()-1;
  747. var x = polyline.getAnchor(last).x;
  748. var y = polyline.getAnchor(last).y;
  749. //var c = this.g.ellipse(x, y, 5, 5);
  750. var lastLineIndex = polyline.getLinesCount()-1;
  751. var line = polyline.getLine(lastLineIndex);
  752. var firstLine = polyline.getLine(0);
  753. var arrowHead = null,
  754. circleTail = null,
  755. defaultSequenceFlowIndicator = null,
  756. conditionalSequenceFlowIndicator = null;
  757. if (connectionType == CONNECTION_TYPE.MESSAGE_FLOW) {
  758. circleTail = this._drawCircleTail(firstLine, connectionType);
  759. }
  760. if(withArrowHead)
  761. arrowHead = this._drawArrowHead(line, connectionType);
  762. //console.log("isDefault: ", isDefault, ", isDefaultConditionAvailable: ", polyline.isDefaultConditionAvailable);
  763. if (isDefault && polyline.isDefaultConditionAvailable) {
  764. //var angle = polyline.getLineAngle(0);
  765. //console.log("firstLine", firstLine);
  766. defaultSequenceFlowIndicator = this._drawDefaultSequenceFlowIndicator(firstLine);
  767. }
  768. if (conditional) {
  769. conditionalSequenceFlowIndicator = this._drawConditionalSequenceFlowIndicator(firstLine);
  770. }
  771. // draw flow name
  772. var flowName = contextObject.name;
  773. if (flowName) {
  774. var xPointArray = contextObject.xPointArray;
  775. var yPointArray = contextObject.yPointArray;
  776. var textX = xPointArray[0] < xPointArray[1] ? xPointArray[0] : xPointArray[1];
  777. var textY = yPointArray[0] < yPointArray[1] ? yPointArray[1] : yPointArray[0];
  778. // fix xy
  779. textX += 20;
  780. textY -= 10;
  781. this.g.text(textX, textY, flowName).attr(LABEL_FONT);
  782. }
  783. var st = this.g.set();
  784. st.push(polyline.element, arrowHead, circleTail, conditionalSequenceFlowIndicator);
  785. polyline.element.data("set", st);
  786. polyline.element.data("withArrowHead", withArrowHead);
  787. var polyCloneAttrNormal = {"stroke-width": this.getStroke() + 5, stroke: Color.get(132,112,255), opacity: 0.0, cursor: "hand"};
  788. var polyClone = st.clone().attr(polyCloneAttrNormal).hover(function () {
  789. //if (polyLine.data("isSelected")) return;
  790. polyClone.attr({opacity: 0.2});
  791. }, function () {
  792. //if (polyLine.data("isSelected")) return;
  793. polyClone.attr({opacity: 0.0});
  794. });
  795. polyClone.data("objectId", polyline.element.id);
  796. polyClone.click(function(){
  797. var instance = this;
  798. var objectId = instance.data("objectId");
  799. var object = this.paper.getById(objectId);
  800. var contextObject = object.data("contextObject");
  801. if (contextObject) {
  802. console.log("[flow], objectId: " + object.id +", flow: " + contextObject.flow);
  803. ProcessDiagramGenerator.showFlowInfo(contextObject);
  804. }
  805. }).dblclick(function(){
  806. console.log("!!! DOUBLE CLICK !!!");
  807. }).hover(function (mouseEvent) {
  808. var instance = this;
  809. var objectId = instance.data("objectId");
  810. var object = this.paper.getById(objectId);
  811. var contextObject = object.data("contextObject");
  812. if (contextObject)
  813. ProcessDiagramGenerator.showFlowInfo(contextObject);
  814. });
  815. polyClone.data("parentId", uuid);
  816. if (!connectionType || connectionType == CONNECTION_TYPE.SEQUENCE_FLOW)
  817. polyline.element.attr("stroke-width", this.getStroke());
  818. else if (connectionType == CONNECTION_TYPE.MESSAGE_FLOW)
  819. polyline.element.attr({"stroke-dasharray": "--"});
  820. else if (connectionType == CONNECTION_TYPE.ASSOCIATION)
  821. polyline.element.attr({"stroke-dasharray": ". "});
  822. this.setPaint(originalPaint);
  823. this.setStroke(originalStroke);
  824. },
  825. _drawDefaultSequenceFlowIndicator: function(line) {
  826. //console.log("line: ", line);
  827. var len = 10; c = len/2, f = 8;
  828. var defaultIndicator = this.g.path("M" + (-c) + " " + 0 + "L" + (c) + " " + 0);
  829. defaultIndicator.attr("stroke-width", this.getStroke()+0);
  830. defaultIndicator.attr("stroke", this.getPaint());
  831. var cosAngle = Math.cos((line.angle));
  832. var sinAngle = Math.sin((line.angle));
  833. var dx = f * cosAngle;
  834. var dy = f * sinAngle;
  835. var x1 = line.x1 + dx + 0*c*cosAngle;
  836. var y1 = line.y1 + dy + 0*c*sinAngle;
  837. defaultIndicator.transform("t" + (x1) + "," + (y1) + "");
  838. defaultIndicator.transform("...r" + Raphael.deg(line.angle - 3*Math.PI / 4) + " " + 0 + " " + 0);
  839. /*
  840. var c0 = this.g.ellipse(0, 0, 1, 1).attr({stroke: Color.Blue});
  841. c0.transform("t" + (line.x1) + "," + (line.y1) + "");
  842. var center = this.g.ellipse(0, 0, 1, 1).attr({stroke: Color.Red});
  843. center.transform("t" + (line.x1+dx) + "," + (line.y1+dy) + "");
  844. */
  845. return defaultIndicator;
  846. },
  847. drawSequenceflow: function(waypoints, conditional, isDefault, highLighted) {
  848. var withArrowHead = true;
  849. this._drawFlow(waypoints, conditional, isDefault, highLighted, withArrowHead, CONNECTION_TYPE.SEQUENCE_FLOW);
  850. },
  851. drawMessageflow: function(waypoints, highLighted) {
  852. var withArrowHead = true;
  853. var conditional=isDefault=false;
  854. this._drawFlow(waypoints, conditional, isDefault, highLighted, withArrowHead, CONNECTION_TYPE.MESSAGE_FLOW);
  855. },
  856. drawAssociation: function(waypoints, withArrowHead, highLighted) {
  857. var withArrowHead = withArrowHead;
  858. var conditional=isDefault=false;
  859. this._drawFlow(waypoints, conditional, isDefault, highLighted, withArrowHead, CONNECTION_TYPE.ASSOCIATION);
  860. },
  861. _drawCircleTail: function(line, connectionType){
  862. var diameter = ARROW_WIDTH/2*1.5;
  863. // anti smoothing
  864. if (this.strokeWidth%2 == 1)
  865. line.x1 += .5, line.y1 += .5;
  866. var circleTail = this.g.ellipse(line.x1, line.y1, diameter, diameter);
  867. circleTail.attr("fill", Color.white);
  868. circleTail.attr("stroke", this.getPaint());
  869. return circleTail;
  870. },
  871. _drawArrowHead: function(line, connectionType){
  872. var doubleArrowWidth = 2 * ARROW_WIDTH;
  873. if (connectionType == CONNECTION_TYPE.ASSOCIATION)
  874. var arrowHead = this.g.path("M-" + (ARROW_WIDTH/2+.5) + " -" + doubleArrowWidth + "L 0 0 L" + (ARROW_WIDTH/2+.5) + " -" + doubleArrowWidth);
  875. else
  876. var arrowHead = this.g.path("M0 0L-" + (ARROW_WIDTH/2+.5) + " -" + doubleArrowWidth + "L" + (ARROW_WIDTH/2+.5) + " -" + doubleArrowWidth + "z");
  877. //arrowHead.transform("t" + 0 + ",-" + this.getStroke() + "");
  878. // anti smoothing
  879. if (this.strokeWidth%2 == 1)
  880. line.x2 += .5, line.y2 += .5;
  881. arrowHead.transform("t" + line.x2 + "," + line.y2 + "");
  882. arrowHead.transform("...r" + Raphael.deg(line.angle - Math.PI / 2) + " " + 0 + " " + 0);
  883. if (!connectionType || connectionType == CONNECTION_TYPE.SEQUENCE_FLOW)
  884. arrowHead.attr("fill", this.getPaint());
  885. else if (connectionType == CONNECTION_TYPE.MESSAGE_FLOW)
  886. arrowHead.attr("fill", Color.white);
  887. arrowHead.attr("stroke-width", this.getStroke());
  888. arrowHead.attr("stroke", this.getPaint());
  889. return arrowHead;
  890. },
  891. /*
  892. drawArrowHead2: function(srcX, srcY, targetX, targetY) {
  893. var doubleArrowWidth = 2 * ARROW_WIDTH;
  894. //var arrowHead = this.g.path("M-" + ARROW_WIDTH/2 + " -" + doubleArrowWidth + "L0 0" + "L" + ARROW_WIDTH/2 + " -" + doubleArrowWidth + "z");
  895. var arrowHead = this.g.path("M0 0L-" + ARROW_WIDTH/1.5 + " -" + doubleArrowWidth + "L" + ARROW_WIDTH/1.5 + " -" + doubleArrowWidth + "z");
  896. //var c = DefaultProcessDiagramCanvas.g.ellipse(0, 0, 3, 3);
  897. //c.transform("t"+targetX+","+targetY+"");
  898. var angle = Math.atan2(targetY - srcY, targetX - srcX);
  899. arrowHead.transform("t"+targetX+","+targetY+"");
  900. arrowHead.transform("...r" + Raphael.deg(angle - Math.PI / 2) + " "+0+" "+0);
  901. //console.log(arrowHead.transform());
  902. //console.log("--> " + Raphael.deg(angle - Math.PI / 2));
  903. arrowHead.attr("fill", this.getPaint());
  904. arrowHead.attr("stroke", this.getPaint());
  905. / *
  906. // shaddow
  907. var c0 = arrowHead.clone();
  908. c0.transform("...t-1 1");
  909. c0.attr("stroke-width", this.strokeWidth);
  910. c0.attr("stroke", Color.black);
  911. c0.attr("opacity", 0.15);
  912. c0.toBack();
  913. * /
  914. },
  915. */
  916. _drawConditionalSequenceFlowIndicator: function(line){
  917. var horizontal = (CONDITIONAL_INDICATOR_WIDTH * 0.7);
  918. var halfOfHorizontal = horizontal / 2;
  919. var halfOfVertical = CONDITIONAL_INDICATOR_WIDTH / 2;
  920. var uuid = null;
  921. var waypoints = [{x: 0, y: 0},
  922. {x: -halfOfHorizontal, y: halfOfVertical},
  923. {x: 0, y: CONDITIONAL_INDICATOR_WIDTH},
  924. {x: halfOfHorizontal, y: halfOfVertical}];
  925. /*
  926. var polyline = new Polyline(uuid, waypoints, this.getStroke());
  927. polyline.element = this.g.path(polyline.path);
  928. polyline.element.attr("stroke-width", this.getStroke());
  929. polyline.element.attr("stroke", this.getPaint());
  930. polyline.element.id = uuid;
  931. */
  932. var polygone = new Polygone(waypoints, this.getStroke());
  933. polygone.element = this.g.path(polygone.path);
  934. polygone.element.attr("fill", Color.white);
  935. polygone.transform("t" + line.x1 + "," + line.y1 + "");
  936. polygone.transform("...r" + Raphael.deg(line.angle - Math.PI / 2) + " " + 0 + " " + 0);
  937. var cosAngle = Math.cos((line.angle));
  938. var sinAngle = Math.sin((line.angle));
  939. //polygone.element.attr("stroke-width", this.getStroke());
  940. //polygone.element.attr("stroke", this.getPaint());
  941. polygone.attr({"stroke-width": this.getStroke(), "stroke": this.getPaint()});
  942. return polygone.element;
  943. },
  944. drawSequenceflowWithoutArrow: function(waypoints, conditional, isDefault, highLighted) {
  945. var withArrowHead = false;
  946. this._drawFlow(waypoints, conditional, isDefault, highLighted, withArrowHead, CONNECTION_TYPE.SEQUENCE_FLOW);
  947. },
  948. /*
  949. * Draw artifacts
  950. */
  951. drawPoolOrLane: function(x, y, width, height, name){
  952. // anti smoothing
  953. if (this.strokeWidth%2 == 1)
  954. x = Math.round(x) + .5, y = Math.round(y) + .5;
  955. // shape
  956. var rect = this.g.rect(x, y, width, height);
  957. var attr = {"stroke-width": NORMAL_STROKE, stroke: TASK_STROKE_COLOR};
  958. rect.attr(attr);
  959. // Add the name as text, vertical
  960. if(name != null && name.length > 0) {
  961. var attr = POOL_LANE_FONT;
  962. // Include some padding
  963. var availableTextSpace = height - 6;
  964. // Create rotation for derived font
  965. var truncated = this.fitTextToWidth(name, availableTextSpace);
  966. var realWidth = this.getStringWidth(truncated, attr);
  967. var realHeight = this.getStringHeight(truncated, attr);
  968. //console.log("truncated:", truncated, ", height:", height, ", realHeight:", realHeight, ", availableTextSpace:", availableTextSpace, ", realWidth:", realWidth);
  969. var newX = x + 2 + realHeight*1 - realHeight/2;
  970. var newY = 3 + y + availableTextSpace - (availableTextSpace - realWidth) / 2 - realWidth/2;
  971. var textElement = this.g.text(newX, newY, truncated).attr(attr);
  972. //console.log(".getBBox(): ", t.getBBox());
  973. textElement.transform("r" + Raphael.deg(270 * Math.PI/180) + " " + newX + " " + newY);
  974. }
  975. // TODO: add to set
  976. },
  977. _drawTask: function(name, x, y, width, height, thickBorder) {
  978. var originalPaint = this.getPaint();
  979. this.setPaint(TASK_COLOR);
  980. // anti smoothing
  981. if (this.strokeWidth%2 == 1)
  982. x = Math.round(x) + .5, y = Math.round(y) + .5;
  983. // shape
  984. var shape = this.g.rect(x, y, width, height, TASK_CORNER_ROUND);
  985. var attr = {"stroke-width": this.strokeWidth, stroke: TASK_STROKE_COLOR, fill: this.getPaint()};
  986. shape.attr(attr);
  987. //shape.attr({fill: "90-"+this.getPaint()+"-" + Color.get(250, 250, 244)});
  988. var contextObject = this.getConextObject();
  989. if (contextObject) {
  990. shape.id = contextObject.id;
  991. shape.data("contextObject", contextObject);
  992. }
  993. //var activity = this.getConextObject();
  994. //console.log("activity: " + activity.getId(), activity);
  995. //Object.clone(activity);
  996. /*
  997. c.mouseover(function(){
  998. this.attr({"stroke-width": NORMAL_STROKE + 2});
  999. }).mouseout(function(){
  1000. this.attr({"stroke-width": NORMAL_STROKE});
  1001. });
  1002. */
  1003. this.setPaint(originalPaint);
  1004. // white shaddow
  1005. this.drawShaddow(shape);
  1006. if (thickBorder) {
  1007. shape.attr({"stroke-width": THICK_TASK_BORDER_STROKE});
  1008. } else {
  1009. //g.draw(rect);
  1010. }
  1011. // text
  1012. if (name) {
  1013. var fontAttr = TASK_FONT;
  1014. // Include some padding
  1015. var paddingX = 5;
  1016. var paddingY = 5;
  1017. var availableTextSpace = width - paddingX*2;
  1018. // TODO: this.setFont
  1019. // var originalFont = this.getFont();
  1020. // this.setFont(TASK_FONT)
  1021. /*
  1022. var truncated = this.fitTextToWidth(name, availableTextSpace);
  1023. var realWidth = this.getStringWidth(truncated, fontAttr);
  1024. var realHeight = this.getStringHeight(truncated, fontAttr);
  1025. //var t = this.g.text(x + width/2 + realWidth*0/2 + paddingX*0, y + height/2, truncated).attr(fontAttr);
  1026. */
  1027. //console.log("draw task name: " + name);
  1028. var boxWidth = width - (2 * TEXT_PADDING);
  1029. var boxHeight = height - ICON_SIZE - ICON_PADDING - ICON_PADDING - MARKER_WIDTH - 2 - 2;
  1030. var boxX = x + width/2 - boxWidth/2;
  1031. var boxY = y + height/2 - boxHeight/2 + ICON_PADDING + ICON_PADDING - 2 - 2;
  1032. /*
  1033. var boxWidth = width - (2 * ANNOTATION_TEXT_PADDING);
  1034. var boxHeight = height - (2 * ANNOTATION_TEXT_PADDING);
  1035. var boxX = x + width/2 - boxWidth/2;
  1036. var boxY = y + height/2 - boxHeight/2;
  1037. */
  1038. this.drawTaskLabel(name, boxX, boxY, boxWidth, boxHeight);
  1039. }
  1040. },
  1041. drawTaskLabel: function(text, x, y, boxWidth, boxHeight){
  1042. var originalFont = this.getFont();
  1043. this.setFont(TASK_FONT);
  1044. this._drawMultilineText(text, x, y, boxWidth, boxHeight, MULTILINE_VERTICAL_ALIGN_MIDDLE, MULTILINE_HORIZONTAL_ALIGN_MIDDLE);
  1045. this.setFont(originalFont);
  1046. },
  1047. drawAnnotationText: function(text, x, y, width, height){
  1048. //this._drawMultilineText(text, x, y, width, height, "start");
  1049. var originalPaint = this.getPaint();
  1050. var originalFont = this.getFont();
  1051. this.setPaint(Color.black);
  1052. this.setFont(TASK_FONT);
  1053. this._drawMultilineText(text, x, y, width, height, MULTILINE_VERTICAL_ALIGN_TOP, MULTILINE_HORIZONTAL_ALIGN_LEFT);
  1054. this.setPaint(originalPaint);
  1055. this.setFont(originalFont);
  1056. },
  1057. drawLabel: function(text, x, y, width, height){
  1058. //this._drawMultilineText(text, x, y, width, height, "start");
  1059. var originalPaint = this.getPaint();
  1060. var originalFont = this.getFont();
  1061. this.setPaint(LABEL_COLOR);
  1062. //this.setFont(LABEL_FONT);
  1063. this.setFont(LABEL_FONT_SMOOTH);
  1064. // predefined box width for labels
  1065. // TODO: use label width as is, but not height (for stretching)
  1066. if (!width || !height) {
  1067. width = 100;
  1068. height = 0;
  1069. }
  1070. // TODO: remove it. It is debug
  1071. x = x - width/2;
  1072. this._drawMultilineText(text, x, y, width, height, MULTILINE_VERTICAL_ALIGN_TOP, MULTILINE_HORIZONTAL_ALIGN_MIDDLE);
  1073. this.setPaint(originalPaint);
  1074. this.setFont(originalFont);
  1075. },
  1076. /*
  1077. drawMultilineLabel: function(text, x, y){
  1078. var originalFont = this.getFont();
  1079. this.setFont(LABEL_FONT_SMOOTH);
  1080. var boxWidth = 80;
  1081. x = x - boxWidth/2
  1082. this._drawMultilineText(text, x, y, boxWidth, null, "middle");
  1083. this.setFont(originalFont);
  1084. },
  1085. */
  1086. getStringWidth: function(text, fontAttrs){
  1087. var textElement = this.g.text(0, 0, text).attr(fontAttrs).hide();
  1088. var bb = textElement.getBBox();
  1089. //console.log("string width: ", t.getBBox().width);
  1090. return textElement.getBBox().width;
  1091. },
  1092. getStringHeight: function(text, fontAttrs){
  1093. var textElement = this.g.text(0, 0, text).attr(fontAttrs).hide();
  1094. var bb = textElement.getBBox();
  1095. //console.log("string height: ", t.getBBox().height);
  1096. return textElement.getBBox().height;
  1097. },
  1098. fitTextToWidth: function(original, width) {
  1099. var text = original;
  1100. // TODO: move attr on parameters
  1101. var attr = {font: "11px Arial", opacity: 0};
  1102. // remove length for "..."
  1103. var dots = this.g.text(0, 0, "...").attr(attr).hide();
  1104. var dotsBB = dots.getBBox();
  1105. var maxWidth = width - dotsBB.width;
  1106. var textElement = this.g.text(0, 0, text).attr(attr).hide();
  1107. var bb = textElement.getBBox();
  1108. // it's a little bit incorrect with "..."
  1109. while (bb.width > maxWidth && text.length > 0) {
  1110. text = text.substring(0, text.length - 1);
  1111. textElement.attr({"text": text});
  1112. bb = textElement.getBBox();
  1113. }
  1114. // remove element from paper
  1115. textElement.remove();
  1116. if (text != original) {
  1117. text = text + "...";
  1118. }
  1119. return text;
  1120. },
  1121. wrapTextToWidth: function(original, width){
  1122. //return original;
  1123. var text = original;
  1124. var wrappedText = "\n";
  1125. // TODO: move attr on parameters
  1126. var attr = {font: "11px Arial", opacity: 0};
  1127. var textElement = this.g.text(0, 0, wrappedText).attr(attr).hide();
  1128. var bb = textElement.getBBox();
  1129. var resultText = "";
  1130. var i = 0, j = 0;
  1131. while (text.length > 0) {
  1132. while (bb.width < width && text.length>0) {
  1133. // remove "\n"
  1134. wrappedText = wrappedText.substring(0,wrappedText.length-1);
  1135. // add new char, add "\n"
  1136. wrappedText = wrappedText + text.substring(0,1) + "\n";
  1137. text = text.substring(1);
  1138. textElement.attr({"text": wrappedText});
  1139. bb = textElement.getBBox();
  1140. i++;
  1141. if (i>200) break;
  1142. }
  1143. // remove "\n"
  1144. wrappedText = wrappedText.substring(0, wrappedText.length - 1);
  1145. if (text.length == 0) {
  1146. resultText += wrappedText;
  1147. break;
  1148. }
  1149. // return last char to text
  1150. text = wrappedText.substring(wrappedText.length-1) + text;
  1151. // remove last char from wrappedText
  1152. wrappedText = wrappedText.substring(0, wrappedText.length-1) + "\n";
  1153. textElement.attr({"text": wrappedText});
  1154. bb = textElement.getBBox();
  1155. //console.log(">> ", wrappedText, ", ", text);
  1156. resultText += wrappedText;
  1157. wrappedText = "\n";
  1158. j++;
  1159. if (j>20) break;
  1160. }
  1161. // remove element from paper
  1162. textElement.remove();
  1163. return resultText;
  1164. },
  1165. wrapTextToWidth2: function(original, width){
  1166. var text = original;
  1167. var wrappedText = "\n";
  1168. // TODO: move attr on parameters
  1169. var attr = {font: "11px Arial", opacity: 0};
  1170. var textElement = this.g.text(0, 0, wrappedText).attr(attr).hide();
  1171. var bb = textElement.getBBox();
  1172. var resultText = "";
  1173. var i = 0, j = 0;
  1174. while (text.length > 0) {
  1175. while (bb.width < width && text.length>0) {
  1176. // remove "\n"
  1177. wrappedText = wrappedText.substring(0,wrappedText.length-1);
  1178. // add new char, add "\n"
  1179. wrappedText = wrappedText + text.substring(0,1) + "\n";
  1180. text = text.substring(1);
  1181. textElement.attr({"text": wrappedText});
  1182. bb = textElement.getBBox();
  1183. i++;
  1184. if (i>200) break;
  1185. }
  1186. // remove "\n"
  1187. wrappedText = wrappedText.substring(0, wrappedText.length - 1);
  1188. if (text.length == 0) {
  1189. resultText += wrappedText;
  1190. break;
  1191. }
  1192. // return last char to text
  1193. text = wrappedText.substring(wrappedText.length-1) + text;
  1194. // remove last char from wrappedText
  1195. wrappedText = wrappedText.substring(0, wrappedText.length-1) + "\n";
  1196. textElement.attr({"text": wrappedText});
  1197. bb = textElement.getBBox();
  1198. //console.log(">> ", wrappedText, ", ", text);
  1199. resultText += wrappedText;
  1200. wrappedText = "\n";
  1201. j++;
  1202. if (j>20) break;
  1203. }
  1204. // remove element from paper
  1205. textElement.remove();
  1206. return resultText;
  1207. },
  1208. drawUserTask: function(name, x, y, width, height) {
  1209. this.g.setStart();
  1210. this._drawTask(name, x, y, width, height);
  1211. var img = this.g.image(USERTASK_IMAGE, x + ICON_PADDING, y + ICON_PADDING, ICON_SIZE, ICON_SIZE);
  1212. var set = this.g.setFinish();
  1213. this.addHandlers(set, x, y, width, height, "task");
  1214. },
  1215. drawScriptTask: function(name, x, y, width, height) {
  1216. this.g.setStart();
  1217. this._drawTask(name, x, y, width, height);
  1218. var img = this.g.image(SCRIPTTASK_IMAGE, x + ICON_PADDING, y + ICON_PADDING, ICON_SIZE, ICON_SIZE);
  1219. var set = this.g.setFinish();
  1220. this.addHandlers(set, x, y, width, height, "task");
  1221. },
  1222. drawServiceTask: function(name, x, y, width, height) {
  1223. this.g.setStart();
  1224. this._drawTask(name, x, y, width, height);
  1225. var img = this.g.image(SERVICETASK_IMAGE, x + ICON_PADDING, y + ICON_PADDING, ICON_SIZE, ICON_SIZE);
  1226. var set = this.g.setFinish();
  1227. this.addHandlers(set, x, y, width, height, "task");
  1228. },
  1229. drawReceiveTask: function(name, x, y, width, height) {
  1230. this.g.setStart();
  1231. this._drawTask(name, x, y, width, height);
  1232. var img = this.g.image(RECEIVETASK_IMAGE, x + 7, y + 7, ICON_SIZE, ICON_SIZE);
  1233. var set = this.g.setFinish();
  1234. this.addHandlers(set, x, y, width, height, "task");
  1235. },
  1236. drawSendTask: function(name, x, y, width, height) {
  1237. this.g.setStart();
  1238. this._drawTask(name, x, y, width, height);
  1239. var img = this.g.image(SENDTASK_IMAGE, x + 7, y + 7, ICON_SIZE, ICON_SIZE);
  1240. var set = this.g.setFinish();
  1241. this.addHandlers(set, x, y, width, height, "task");
  1242. },
  1243. drawManualTask: function(name, x, y, width, height) {
  1244. this.g.setStart();
  1245. this._drawTask(name, x, y, width, height);
  1246. var img = this.g.image(MANUALTASK_IMAGE, x + 7, y + 7, ICON_SIZE, ICON_SIZE);
  1247. var set = this.g.setFinish();
  1248. this.addHandlers(set, x, y, width, height, "task");
  1249. },
  1250. drawBusinessRuleTask: function(name, x, y, width, height) {
  1251. this.g.setStart();
  1252. this._drawTask(name, x, y, width, height);
  1253. var img = this.g.image(BUSINESS_RULE_TASK_IMAGE, x + 7, y + 7, ICON_SIZE, ICON_SIZE);
  1254. var set = this.g.setFinish();
  1255. this.addHandlers(set, x, y, width, height, "task");
  1256. },
  1257. drawExpandedSubProcess: function(name, x, y, width, height, isTriggeredByEvent){
  1258. this.g.setStart();
  1259. // anti smoothing
  1260. if (this.strokeWidth%2 == 1)
  1261. x = Math.round(x) + .5, y = Math.round(y) + .5;
  1262. // shape
  1263. var rect = this.g.rect(x, y, width, height, EXPANDED_SUBPROCESS_CORNER_ROUND);
  1264. // Use different stroke (dashed)
  1265. if(isTriggeredByEvent) {
  1266. rect.attr(EVENT_SUBPROCESS_ATTRS);
  1267. } else {
  1268. rect.attr(EXPANDED_SUBPROCESS_ATTRS);
  1269. }
  1270. this.setContextToElement(rect);
  1271. var fontAttr = EXPANDED_SUBPROCESS_FONT;
  1272. // Include some padding
  1273. var paddingX = 10;
  1274. var paddingY = 5;
  1275. var availableTextSpace = width - paddingX*2;
  1276. var truncated = this.fitTextToWidth(name, availableTextSpace);
  1277. var realWidth = this.getStringWidth(truncated, fontAttr);
  1278. var realHeight = this.getStringHeight(truncated, fontAttr);
  1279. var textElement = this.g.text(x + width/2 - realWidth*0/2 + 0*paddingX, y + realHeight/2 + paddingY, truncated).attr(fontAttr);
  1280. var set = this.g.setFinish();
  1281. // TODO: Expanded Sub Process may has specific handlers
  1282. //this.addHandlers(set, x, y, width, height, "task");
  1283. },
  1284. drawCollapsedSubProcess: function(name, x, y, width, height, isTriggeredByEvent) {
  1285. this.g.setStart();
  1286. this._drawCollapsedTask(name, x, y, width, height, false);
  1287. var set = this.g.setFinish();
  1288. this.addHandlers(set, x, y, width, height, "task");
  1289. },
  1290. drawCollapsedCallActivity: function(name, x, y, width, height) {
  1291. this.g.setStart();
  1292. this._drawCollapsedTask(name, x, y, width, height, true);
  1293. var set = this.g.setFinish();
  1294. this.addHandlers(set, x, y, width, height, "task");
  1295. },
  1296. _drawCollapsedTask: function(name, x, y, width, height, thickBorder) {
  1297. // The collapsed marker is now visualized separately
  1298. this._drawTask(name, x, y, width, height, thickBorder);
  1299. },
  1300. drawCollapsedMarker: function(x, y, width, height){
  1301. // rectangle
  1302. var rectangleWidth = MARKER_WIDTH;
  1303. var rectangleHeight = MARKER_WIDTH;
  1304. // anti smoothing
  1305. if (this.strokeWidth%2 == 1)
  1306. y += .5;
  1307. var rect = this.g.rect(x + (width - rectangleWidth) / 2, y + height - rectangleHeight - 3, rectangleWidth, rectangleHeight);
  1308. // plus inside rectangle
  1309. var cx = rect.attr("x") + rect.attr("width")/2;
  1310. var cy = rect.attr("y") + rect.attr("height")/2;
  1311. var line = this.g.path(
  1312. "M" + cx + " " + (cy+2) + "L" + cx + " " + (cy-2) +
  1313. "M" + (cx-2) + " " + cy + "L" + (cx+2) + " " + cy
  1314. ).attr({"stroke-width": this.strokeWidth});
  1315. },
  1316. drawActivityMarkers: function(x, y, width, height, multiInstanceSequential, multiInstanceParallel, collapsed){
  1317. if (collapsed) {
  1318. if (!multiInstanceSequential && !multiInstanceParallel) {
  1319. this.drawCollapsedMarker(x, y, width, height);
  1320. } else {
  1321. this.drawCollapsedMarker(x - MARKER_WIDTH / 2 - 2, y, width, height);
  1322. if (multiInstanceSequential) {
  1323. console.log("is collapsed and multiInstanceSequential");
  1324. this.drawMultiInstanceMarker(true, x + MARKER_WIDTH / 2 + 2, y, width, height);
  1325. } else if (multiInstanceParallel) {
  1326. console.log("is collapsed and multiInstanceParallel");
  1327. this.drawMultiInstanceMarker(false, x + MARKER_WIDTH / 2 + 2, y, width, height);
  1328. }
  1329. }
  1330. } else {
  1331. if (multiInstanceSequential) {
  1332. console.log("is multiInstanceSequential");
  1333. this.drawMultiInstanceMarker(true, x, y, width, height);
  1334. } else if (multiInstanceParallel) {
  1335. console.log("is multiInstanceParallel");
  1336. this.drawMultiInstanceMarker(false, x, y, width, height);
  1337. }
  1338. }
  1339. },
  1340. drawGateway: function(x, y, width, height) {
  1341. var rhombus = this.g.path( "M" + x + " " + (y + (height / 2)) +
  1342. "L" + (x + (width / 2)) + " " + (y + height) +
  1343. "L" + (x + width) + " " + (y + (height / 2)) +
  1344. "L" + (x + (width / 2)) + " " + y +
  1345. "z"
  1346. );
  1347. // white shaddow
  1348. this.drawShaddow(rhombus);
  1349. rhombus.attr("stroke-width", this.strokeWidth);
  1350. rhombus.attr("stroke", Color.SlateGrey);
  1351. rhombus.attr({fill: Color.white});
  1352. this.setContextToElement(rhombus);
  1353. return rhombus;
  1354. },
  1355. drawParallelGateway: function(x, y, width, height) {
  1356. this.g.setStart();
  1357. // rhombus
  1358. this.drawGateway(x, y, width, height);
  1359. // plus inside rhombus
  1360. var originalStroke = this.getStroke();
  1361. this.setStroke(GATEWAY_TYPE_STROKE);
  1362. var plus = this.g.path(
  1363. "M" + (x + 10) + " " + (y + height / 2) + "L" + (x + width - 10) + " " + (y + height / 2) + // horizontal
  1364. "M" + (x + width / 2) + " " + (y + height - 10) + "L" + (x + width / 2) + " " + (y + 10) // vertical
  1365. );
  1366. plus.attr({"stroke-width": this.getStroke(), "stroke": this.getPaint()});
  1367. this.setStroke(originalStroke);
  1368. var set = this.g.setFinish();
  1369. this.addHandlers(set, x, y, width, height, "gateway");
  1370. },
  1371. drawExclusiveGateway: function(x, y, width, height) {
  1372. this.g.setStart();
  1373. // rhombus
  1374. var rhombus = this.drawGateway(x, y, width, height);
  1375. var quarterWidth = width / 4;
  1376. var quarterHeight = height / 4;
  1377. // X inside rhombus
  1378. var originalStroke = this.getStroke();
  1379. this.setStroke(GATEWAY_TYPE_STROKE);
  1380. var iks = this.g.path(
  1381. "M" + (x + quarterWidth + 3) + " " + (y + quarterHeight + 3) + "L" + (x + 3 * quarterWidth - 3) + " " + (y + 3 * quarterHeight - 3) +
  1382. "M" + (x + quarterWidth + 3) + " " + (y + 3 * quarterHeight - 3) + "L" + (x + 3 * quarterWidth - 3) + " " + (y + quarterHeight + 3)
  1383. );
  1384. iks.attr({"stroke-width": this.getStroke(), "stroke": this.getPaint()});
  1385. this.setStroke(originalStroke);
  1386. var set = this.g.setFinish();
  1387. this.addHandlers(set, x, y, width, height, "gateway");
  1388. },
  1389. drawInclusiveGateway: function(x, y, width, height){
  1390. this.g.setStart();
  1391. // rhombus
  1392. this.drawGateway(x, y, width, height);
  1393. var diameter = width / 4;
  1394. // circle inside rhombus
  1395. var originalStroke = this.getStroke();
  1396. this.setStroke(GATEWAY_TYPE_STROKE);
  1397. var circle = this.g.ellipse(width/2 + x, height/2 + y, diameter, diameter);
  1398. circle.attr({"stroke-width": this.getStroke(), "stroke": this.getPaint()});
  1399. this.setStroke(originalStroke);
  1400. var set = this.g.setFinish();
  1401. this.addHandlers(set, x, y, width, height, "gateway");
  1402. },
  1403. drawEventBasedGateway: function(x, y, width, height){
  1404. this.g.setStart();
  1405. // rhombus
  1406. this.drawGateway(x, y, width, height);
  1407. var diameter = width / 2;
  1408. // rombus inside rhombus
  1409. var originalStroke = this.getStroke();
  1410. this.setStroke(GATEWAY_TYPE_STROKE);
  1411. // draw GeneralPath (polygon)
  1412. var n=5;
  1413. var angle = 2*Math.PI/n;
  1414. var x1Points = [];
  1415. var y1Points = [];
  1416. for ( var index = 0; index < n; index++ ) {
  1417. var v = index*angle - Math.PI/2;
  1418. x1Points[index] = x + parseInt(Math.round(width/2)) + parseInt(Math.round((width/4)*Math.cos(v)));
  1419. y1Points[index] = y + parseInt(Math.round(height/2)) + parseInt(Math.round((height/4)*Math.sin(v)));
  1420. }
  1421. //g.drawPolygon(x1Points, y1Points, n);
  1422. var path = "";
  1423. for ( var index = 0; index < n; index++ ) {
  1424. if (index == 0)
  1425. path += "M";
  1426. else
  1427. path += "L";
  1428. path += x1Points[index] + "," + y1Points[index];
  1429. }
  1430. path += "z";
  1431. var polygone = this.g.path(path);
  1432. polygone.attr("stroke-width", this.strokeWidth);
  1433. polygone.attr("stroke", this.getPaint());
  1434. this.setStroke(originalStroke);
  1435. var set = this.g.setFinish();
  1436. this.addHandlers(set, x, y, width, height, "gateway");
  1437. },
  1438. /*
  1439. * drawMultiInstanceMarker
  1440. * drawHighLight
  1441. * highLightFlow
  1442. */
  1443. drawMultiInstanceMarker: function(sequential, x, y, width, height) {
  1444. var rectangleWidth = MARKER_WIDTH;
  1445. var rectangleHeight = MARKER_WIDTH;
  1446. // anti smoothing
  1447. if (this.strokeWidth%2 == 1)
  1448. x += .5;//, y += .5;
  1449. var lineX = x + (width - rectangleWidth) / 2;
  1450. var lineY = y + height - rectangleHeight - 3;
  1451. var originalStroke = this.getStroke();
  1452. this.setStroke(MULTI_INSTANCE_STROKE);
  1453. if (sequential) {
  1454. var line = this.g.path(
  1455. "M" + lineX + " " + lineY + "L" + (lineX + rectangleWidth) + " " + lineY +
  1456. "M" + lineX + " " + (lineY + rectangleHeight / 2) + "L" + (lineX + rectangleWidth) + " " + (lineY + rectangleHeight / 2) +
  1457. "M" + lineX + " " + (lineY + rectangleHeight) + "L" + (lineX + rectangleWidth) + " " + (lineY + rectangleHeight)
  1458. ).attr({"stroke-width": this.strokeWidth});
  1459. } else {
  1460. var line = this.g.path(
  1461. "M" + lineX + " " + lineY + "L" + lineX + " " + (lineY + rectangleHeight) +
  1462. "M" + (lineX + rectangleWidth / 2) + " " + lineY + "L" + (lineX + rectangleWidth / 2) + " " + (lineY + rectangleHeight) +
  1463. "M" + (lineX + rectangleWidth) + " " + lineY + "L" + (lineX + rectangleWidth) + " " + (lineY + rectangleHeight)
  1464. ).attr({"stroke-width": this.strokeWidth});
  1465. }
  1466. this.setStroke(originalStroke);
  1467. },
  1468. drawHighLight: function(x, y, width, height){
  1469. var originalPaint = this.getPaint();
  1470. var originalStroke = this.getStroke();
  1471. this.setPaint(HIGHLIGHT_COLOR);
  1472. this.setStroke(THICK_TASK_BORDER_STROKE);
  1473. //var c = this.g.rect(x - width/2 - THICK_TASK_BORDER_STROKE, y - height/2 - THICK_TASK_BORDER_STROKE, width + THICK_TASK_BORDER_STROKE*2, height + THICK_TASK_BORDER_STROKE*2, 5);
  1474. var rect = this.g.rect(x - THICK_TASK_BORDER_STROKE, y - THICK_TASK_BORDER_STROKE, width + THICK_TASK_BORDER_STROKE*2, height + THICK_TASK_BORDER_STROKE*2, TASK_CORNER_ROUND);
  1475. rect.attr("stroke-width", this.strokeWidth);
  1476. rect.attr("stroke", this.getPaint());
  1477. this.setPaint(originalPaint);
  1478. this.setStroke(originalStroke);
  1479. },
  1480. highLightActivity: function(activityId){
  1481. var shape = this.g.getById(activityId);
  1482. if (!shape) {
  1483. console.error("Activity " + activityId + " not found");
  1484. return;
  1485. }
  1486. var contextObject = shape.data("contextObject");
  1487. if (contextObject)
  1488. console.log("--> highLightActivity: ["+contextObject.getProperty("type")+"], activityId: " + contextObject.getId());
  1489. else
  1490. console.log("--> highLightActivity: ", shape, shape.data("contextObject"));
  1491. shape.attr("stroke-width", THICK_TASK_BORDER_STROKE);
  1492. shape.attr("stroke", HIGHLIGHT_COLOR);
  1493. },
  1494. highLightFlow: function(flowId){
  1495. var shapeFlow = this.g.getById(flowId);
  1496. if (!shapeFlow) {
  1497. console.error("Flow " + flowId + " not found");
  1498. return;
  1499. }
  1500. var contextObject = shapeFlow.data("contextObject");
  1501. if (contextObject)
  1502. console.log("--> highLightFlow: ["+contextObject.id+"] " + contextObject.flow);
  1503. //console.log("--> highLightFlow: ", flow.flow, flow.data("set"));
  1504. var st = shapeFlow.data("set");
  1505. st.attr("stroke-width", SEQUENCEFLOW_HIGHLIGHT_STROKE);
  1506. st.attr("stroke", HIGHLIGHT_COLOR);
  1507. var withArrowHead = shapeFlow.data("withArrowHead");
  1508. if (withArrowHead)
  1509. st[1].attr("fill", HIGHLIGHT_COLOR);
  1510. st.forEach(function(el){
  1511. //console.log("---->", el);
  1512. //el.attr("")
  1513. });
  1514. },
  1515. _drawClock: function(cx, cy, width, height){
  1516. var circle = this.g.ellipse(cx, cy, 1, 1).attr({stroke:"none", fill: Color.get(232, 239, 241)});
  1517. //var c = this.g.ellipse(cx, cy, width, height).attr({stroke:"none", fill: Color.red});
  1518. //x = cx - width/2;
  1519. //y = cy - height/2;
  1520. var clock = this.g.path(
  1521. /* outer circle */ "M15.5,2.374 C8.251,2.375,2.376,8.251,2.374,15.5 C2.376,22.748,8.251,28.623,15.5,28.627c7.249-0.004,13.124-5.879,13.125-13.127C28.624,8.251,22.749,2.375,15.5,2.374z" +
  1522. /* inner circle */ "M15.5,26.623 C8.909,26.615,4.385,22.09,4.375,15.5 C4.385,8.909,8.909,4.384,15.5,4.374c4.59,0.01,11.115,3.535,11.124,11.125C26.615,22.09,22.091,26.615,15.5,26.623z" +
  1523. /* 9 */ "M8.625,15.5c-0.001-0.552-0.448-0.999-1.001-1c-0.553,0-1,0.448-1,1c0,0.553,0.449,1,1,1C8.176,16.5,8.624,16.053,8.625,15.5z" +
  1524. /* 8 */ "M8.179,18.572c-0.478,0.277-0.642,0.889-0.365,1.367c0.275,0.479,0.889,0.641,1.365,0.365c0.479-0.275,0.643-0.887,0.367-1.367C9.27,18.461,8.658,18.297,8.179,18.572z" +
  1525. /* 10 */ "M9.18,10.696c-0.479-0.276-1.09-0.112-1.366,0.366s-0.111,1.09,0.365,1.366c0.479,0.276,1.09,0.113,1.367-0.366C9.821,11.584,9.657,10.973,9.18,10.696z" +
  1526. /* 2 */ "M22.822,12.428c0.478-0.275,0.643-0.888,0.366-1.366c-0.275-0.478-0.89-0.642-1.366-0.366c-0.479,0.278-0.642,0.89-0.366,1.367C21.732,12.54,22.344,12.705,22.822,12.428z" +
  1527. /* 7 */ "M12.062,21.455c-0.478-0.275-1.089-0.111-1.366,0.367c-0.275,0.479-0.111,1.09,0.366,1.365c0.478,0.277,1.091,0.111,1.365-0.365C12.704,22.344,12.54,21.732,12.062,21.455z" +
  1528. /* 11 */ "M12.062,9.545c0.479-0.276,0.642-0.888,0.366-1.366c-0.276-0.478-0.888-0.642-1.366-0.366s-0.642,0.888-0.366,1.366C10.973,9.658,11.584,9.822,12.062,9.545z" +
  1529. /* 4 */ "M22.823,18.572c-0.48-0.275-1.092-0.111-1.367,0.365c-0.275,0.479-0.112,1.092,0.367,1.367c0.477,0.275,1.089,0.113,1.365-0.365C23.464,19.461,23.3,18.848,22.823,18.572z" +
  1530. /* 2 */ "M19.938,7.813c-0.477-0.276-1.091-0.111-1.365,0.366c-0.275,0.48-0.111,1.091,0.366,1.367s1.089,0.112,1.366-0.366C20.581,8.702,20.418,8.089,19.938,7.813z" +
  1531. /* 3 */ "M23.378,14.5c-0.554,0.002-1.001,0.45-1.001,1c0.001,0.552,0.448,1,1.001,1c0.551,0,1-0.447,1-1C24.378,14.949,23.929,14.5,23.378,14.5z" +
  1532. /* arrows */ "M15.501,6.624c-0.552,0-1,0.448-1,1l-0.466,7.343l-3.004,1.96c-0.478,0.277-0.642,0.889-0.365,1.365c0.275,0.479,0.889,0.643,1.365,0.367l3.305-1.676C15.39,16.99,15.444,17,15.501,17c0.828,0,1.5-0.671,1.5-1.5l-0.5-7.876C16.501,7.072,16.053,6.624,15.501,6.624z" +
  1533. /* 9 */ "M15.501,22.377c-0.552,0-1,0.447-1,1s0.448,1,1,1s1-0.447,1-1S16.053,22.377,15.501,22.377z" +
  1534. /* 8 */ "M18.939,21.455c-0.479,0.277-0.643,0.889-0.366,1.367c0.275,0.477,0.888,0.643,1.366,0.365c0.478-0.275,0.642-0.889,0.366-1.365C20.028,21.344,19.417,21.18,18.939,21.455z" +
  1535. "");
  1536. clock.attr({fill: Color.black, stroke: "none"});
  1537. //clock.transform("t " + (cx-29.75/2) + " " + (cy-29.75/2));
  1538. //clock.transform("...s 0.85");
  1539. //clock.transform("...s " + .85 + " " + .85);
  1540. clock.transform("t " + (-2.374) + " " + (-2.374) );
  1541. clock.transform("...t -" + (15.5-2.374) + " -" + (15.5-2.374) );
  1542. clock.transform("...s " + 1*(width/35) + " " + 1*(height/35));
  1543. clock.transform("...T " + cx + " " + cy);
  1544. //clock.transform("t " + (cx-width/2) + " " + (cy-height/2));
  1545. //console.log(".getBBox(): ", clock.getBBox());
  1546. //console.log(".attr(): ", c.attrs);
  1547. circle.attr("rx", clock.getBBox().width/2);
  1548. circle.attr("ry", clock.getBBox().height/2);
  1549. //return circle
  1550. },
  1551. _drawPentagon: function(cx, cy, width, height, filled){
  1552. // draw GeneralPath (polygon)
  1553. var n=5;
  1554. var angle = 2*Math.PI/n;
  1555. var waypoints = [];
  1556. for ( var index = 0; index < n; index++ ) {
  1557. var v = index*angle - Math.PI/2;
  1558. var point = {};
  1559. point.x = -width*1.2/2 + parseInt(Math.round(width*1.2/2)) + parseInt(Math.round((width*1.2/4)*Math.cos(v)));
  1560. point.y = -height*1.2/2 + parseInt(Math.round(height*1.2/2)) + parseInt(Math.round((height*1.2/4)*Math.sin(v)));
  1561. waypoints[index] = point;
  1562. }
  1563. var polygone = new Polygone(waypoints, this.getStroke());
  1564. polygone.element = this.g.path(polygone.path);
  1565. if (filled)
  1566. polygone.element.attr("fill", Color.black);
  1567. else
  1568. polygone.element.attr("fill", Color.white);
  1569. polygone.element.transform("s " + 1*(width/35) + " " + 1*(height/35));
  1570. polygone.element.transform("...T " + cx + " " + cy);
  1571. },
  1572. //_drawMultilineText: function(text, x, y, boxWidth, boxHeight, textAnchor) {
  1573. _drawMultilineText: function(text, x, y, boxWidth, boxHeight, verticalAlign, horizontalAlign) {
  1574. if (!text || text == "")
  1575. return;
  1576. // Autostretch boxHeight if boxHeight is 0
  1577. if (boxHeight == 0)
  1578. verticalAlign = MULTILINE_VERTICAL_ALIGN_TOP;
  1579. //var TEXT_PADDING = 3;
  1580. var width = boxWidth;
  1581. if (boxHeight)
  1582. var height = boxHeight;
  1583. var layouts = [];
  1584. //var font = {font: "11px Arial", opacity: 1, "fill": LABEL_COLOR};
  1585. var font = this.getFont();
  1586. var measurer = new LineBreakMeasurer(this.g, x, y, text, font);
  1587. var lineHeight = measurer.rafaelTextObject.getBBox().height;
  1588. //console.log("text: ", text.replace(/\n/g, "?"));
  1589. if (height) {
  1590. var availableLinesCount = parseInt(height/lineHeight);
  1591. //console.log("availableLinesCount: " + availableLinesCount);
  1592. }
  1593. var i = 1;
  1594. while (measurer.getPosition() < measurer.text.getEndIndex()) {
  1595. var layout = measurer.nextLayout(width);
  1596. //console.log("LAYOUT: " + layout + ", getPosition: " + measurer.getPosition());
  1597. if (layout != null) {
  1598. // TODO: and check if measurer has next layout. If no then don't draw dots
  1599. if (!availableLinesCount || i < availableLinesCount) {
  1600. layouts.push(layout);
  1601. } else {
  1602. layouts.push(this.fitTextToWidth(layout + "...", boxWidth));
  1603. break;
  1604. }
  1605. }
  1606. i++;
  1607. };
  1608. //console.log(layouts);
  1609. measurer.rafaelTextObject.attr({"text": layouts.join("\n")});
  1610. if (horizontalAlign)
  1611. measurer.rafaelTextObject.attr({"text-anchor": horizontalAlign}); // end, middle, start
  1612. var bb = measurer.rafaelTextObject.getBBox();
  1613. // TODO: there is somethin wrong with wertical align. May be: measurer.rafaelTextObject.attr({"y": y + height/2 - bb.height/2})
  1614. measurer.rafaelTextObject.attr({"y": y + bb.height/2});
  1615. //var bb = measurer.rafaelTextObject.getBBox();
  1616. if (measurer.rafaelTextObject.attr("text-anchor") == MULTILINE_HORIZONTAL_ALIGN_MIDDLE )
  1617. measurer.rafaelTextObject.attr("x", x + boxWidth/2);
  1618. else if (measurer.rafaelTextObject.attr("text-anchor") == MULTILINE_HORIZONTAL_ALIGN_RIGHT )
  1619. measurer.rafaelTextObject.attr("x", x + boxWidth);
  1620. var boxStyle = {stroke: Color.LightSteelBlue2, "stroke-width": 1.0, "stroke-dasharray": "- "};
  1621. //var box = this.g.rect(x+.5, y + .5, width, height).attr(boxStyle);
  1622. var textAreaCX = x + boxWidth/2;
  1623. var height = boxHeight;
  1624. if (!height) height = bb.height;
  1625. var textAreaCY = y + height/2;
  1626. var dotLeftTop = this.g.ellipse(x, y, 3, 3).attr({"stroke-width": 0, fill: Color.LightSteelBlue, stroke: "none"}).hide();
  1627. var dotCenter = this.g.ellipse(textAreaCX, textAreaCY, 3, 3).attr({fill: Color.LightSteelBlue2, stroke: "none"}).hide();
  1628. /*
  1629. // real bbox
  1630. var bb = measurer.rafaelTextObject.getBBox();
  1631. var rect = paper.rect(bb.x+.5, bb.y + .5, bb.width, bb.height).attr({"stroke-width": 1});
  1632. */
  1633. var rect = this.g.rect(x, y, boxWidth, height).attr({"stroke-width": 1}).attr(boxStyle).hide();
  1634. var debugSet = this.g.set();
  1635. debugSet.push(dotLeftTop, dotCenter, rect);
  1636. //debugSet.show();
  1637. },
  1638. drawTextAnnotation: function(text, x, y, width, height){
  1639. var lineLength = 18;
  1640. var path = [];
  1641. path.push(["M", x + lineLength, y]);
  1642. path.push(["L", x, y]);
  1643. path.push(["L", x, y + height]);
  1644. path.push(["L", x + lineLength, y + height]);
  1645. path.push(["L", x + lineLength, y + height -1]);
  1646. path.push(["L", x + 1, y + height -1]);
  1647. path.push(["L", x + 1, y + 1]);
  1648. path.push(["L", x + lineLength, y + 1]);
  1649. path.push(["z"]);
  1650. var textAreaLines = this.g.path(path);
  1651. var boxWidth = width - (2 * ANNOTATION_TEXT_PADDING);
  1652. var boxHeight = height - (2 * ANNOTATION_TEXT_PADDING);
  1653. var boxX = x + width/2 - boxWidth/2;
  1654. var boxY = y + height/2 - boxHeight/2;
  1655. // for debug
  1656. var rectStyle = {stroke: Color(112, 146, 190), "stroke-width": 1.0, "stroke-dasharray": "- "};
  1657. var r = this.g.rect(boxX, boxY, boxWidth, boxHeight).attr(rectStyle);
  1658. //
  1659. this.drawAnnotationText(text, boxX, boxY, boxWidth, boxHeight);
  1660. },
  1661. drawLabel111111111: function(text, x, y, width, height, labelAttrs){
  1662. var debug = false;
  1663. // text
  1664. if (text != null && text != undefined && text != "") {
  1665. var attr = LABEL_FONT;
  1666. //console.log("x", x, "y", y, "width", width, "height", height );
  1667. wrappedText = text;
  1668. if (labelAttrs && labelAttrs.wrapWidth) {
  1669. wrappedText = this.wrapTextToWidth(wrappedText, labelAttrs.wrapWidth);
  1670. }
  1671. var realWidth = this.getStringWidth(wrappedText, attr);
  1672. var realHeight = this.getStringHeight(wrappedText, attr);
  1673. var textAreaCX = x + width/2;
  1674. var textAreaCY = y + 3 + height + this.getStringHeight(wrappedText, attr)/2;
  1675. var textX = textAreaCX;
  1676. var textY = textAreaCY;
  1677. var textAttrs = {};
  1678. if (labelAttrs && labelAttrs.align) {
  1679. switch (labelAttrs.align) {
  1680. case "left":
  1681. textAttrs["text-anchor"] = "start";
  1682. textX = textX - realWidth/2;
  1683. break;
  1684. case "center":
  1685. textAttrs["text-anchor"] = "middle";
  1686. break;
  1687. case "right":
  1688. textAttrs["text-anchor"] = "end";
  1689. textX = textX + realWidth/2;
  1690. break;
  1691. }
  1692. }
  1693. if (labelAttrs && labelAttrs.wrapWidth) {
  1694. if (true) {
  1695. // Draw frameborder
  1696. var textAreaStyle = {stroke: Color.LightSteelBlue2, "stroke-width": 1.0, "stroke-dasharray": "- "};
  1697. var textAreaX = textAreaCX - realWidth/2;
  1698. var textAreaY = textAreaCY+.5 - realHeight/2;
  1699. var textArea = this.g.rect(textAreaX, textAreaY, realWidth, realHeight).attr(textAreaStyle);
  1700. var textAreaLines = this.g.path("M" + textAreaX + " " + textAreaY + "L" + (textAreaX+realWidth) + " " + (textAreaY+realHeight) + "M" + + (textAreaX+realWidth) + " " + textAreaY + "L" + textAreaX + " " + (textAreaY+realHeight));
  1701. textAreaLines.attr(textAreaStyle);
  1702. this.g.ellipse(textAreaCX, textAreaCY, 3, 3).attr({fill: Color.LightSteelBlue2, stroke: "none"});
  1703. }
  1704. }
  1705. var label = this.g.text(textX, textY, wrappedText).attr(attr).attr(textAttrs);
  1706. //label.id = Raphael.createUUID();
  1707. //console.log("label ", label.id, ", ", wrappedText);
  1708. if (this.fontSmoothing) {
  1709. label.attr({stroke: LABEL_COLOR, "stroke-width":.4});
  1710. }
  1711. // debug
  1712. if (debug) {
  1713. var imageAreaStyle = {stroke: Color.grey61, "stroke-width": 1.0, "stroke-dasharray": "- "};
  1714. var imageArea = this.g.rect(x+.5, y+.5, width, height).attr(imageAreaStyle);
  1715. var imageAreaLines = this.g.path("M" + x + " " + y + "L" + (x+width) + " " + (y+height) + "M" + + (x+width) + " " + y + "L" + x + " " + (y+height));
  1716. imageAreaLines.attr(imageAreaStyle);
  1717. var dotStyle = {fill: Color.Coral, stroke: "none"};
  1718. this.g.ellipse(x, y, 3, 3).attr(dotStyle);
  1719. this.g.ellipse(x+width, y, 2, 2).attr(dotStyle);
  1720. this.g.ellipse(x+width, y+height, 2, 2).attr(dotStyle);
  1721. this.g.ellipse(x, y+height, 2, 2).attr(dotStyle);
  1722. }
  1723. return label;
  1724. }
  1725. },
  1726. vvoid: function(){}
  1727. };