ProcessDiagramCanvas.js 71 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159
  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 ProcessDiagramCanvas = {
  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. var st = this.g.set();
  772. st.push(polyline.element, arrowHead, circleTail, conditionalSequenceFlowIndicator);
  773. polyline.element.data("set", st);
  774. polyline.element.data("withArrowHead", withArrowHead);
  775. var polyCloneAttrNormal = {"stroke-width": this.getStroke() + 5, stroke: Color.get(132,112,255), opacity: 0.0, cursor: "hand"};
  776. var polyClone = st.clone().attr(polyCloneAttrNormal).hover(function () {
  777. //if (polyLine.data("isSelected")) return;
  778. polyClone.attr({opacity: 0.2});
  779. }, function () {
  780. //if (polyLine.data("isSelected")) return;
  781. polyClone.attr({opacity: 0.0});
  782. });
  783. polyClone.data("objectId", polyline.element.id);
  784. polyClone.click(function(){
  785. var instance = this;
  786. var objectId = instance.data("objectId");
  787. var object = this.paper.getById(objectId);
  788. var contextObject = object.data("contextObject");
  789. if (contextObject) {
  790. console.log("[flow], objectId: " + object.id +", flow: " + contextObject.flow);
  791. ProcessDiagramGenerator.showFlowInfo(contextObject);
  792. }
  793. }).dblclick(function(){
  794. console.log("!!! DOUBLE CLICK !!!");
  795. }).hover(function (mouseEvent) {
  796. var instance = this;
  797. var objectId = instance.data("objectId");
  798. var object = this.paper.getById(objectId);
  799. var contextObject = object.data("contextObject");
  800. if (contextObject)
  801. ProcessDiagramGenerator.showFlowInfo(contextObject);
  802. });
  803. polyClone.data("parentId", uuid);
  804. if (!connectionType || connectionType == CONNECTION_TYPE.SEQUENCE_FLOW)
  805. polyline.element.attr("stroke-width", this.getStroke());
  806. else if (connectionType == CONNECTION_TYPE.MESSAGE_FLOW)
  807. polyline.element.attr({"stroke-dasharray": "--"});
  808. else if (connectionType == CONNECTION_TYPE.ASSOCIATION)
  809. polyline.element.attr({"stroke-dasharray": ". "});
  810. this.setPaint(originalPaint);
  811. this.setStroke(originalStroke);
  812. },
  813. _drawDefaultSequenceFlowIndicator: function(line) {
  814. //console.log("line: ", line);
  815. var len = 10; c = len/2, f = 8;
  816. var defaultIndicator = this.g.path("M" + (-c) + " " + 0 + "L" + (c) + " " + 0);
  817. defaultIndicator.attr("stroke-width", this.getStroke()+0);
  818. defaultIndicator.attr("stroke", this.getPaint());
  819. var cosAngle = Math.cos((line.angle));
  820. var sinAngle = Math.sin((line.angle));
  821. var dx = f * cosAngle;
  822. var dy = f * sinAngle;
  823. var x1 = line.x1 + dx + 0*c*cosAngle;
  824. var y1 = line.y1 + dy + 0*c*sinAngle;
  825. defaultIndicator.transform("t" + (x1) + "," + (y1) + "");
  826. defaultIndicator.transform("...r" + Raphael.deg(line.angle - 3*Math.PI / 4) + " " + 0 + " " + 0);
  827. /*
  828. var c0 = this.g.ellipse(0, 0, 1, 1).attr({stroke: Color.Blue});
  829. c0.transform("t" + (line.x1) + "," + (line.y1) + "");
  830. var center = this.g.ellipse(0, 0, 1, 1).attr({stroke: Color.Red});
  831. center.transform("t" + (line.x1+dx) + "," + (line.y1+dy) + "");
  832. */
  833. return defaultIndicator;
  834. },
  835. drawSequenceflow: function(waypoints, conditional, isDefault, highLighted) {
  836. var withArrowHead = true;
  837. this._drawFlow(waypoints, conditional, isDefault, highLighted, withArrowHead, CONNECTION_TYPE.SEQUENCE_FLOW);
  838. },
  839. drawMessageflow: function(waypoints, highLighted) {
  840. var withArrowHead = true;
  841. var conditional=isDefault=false;
  842. this._drawFlow(waypoints, conditional, isDefault, highLighted, withArrowHead, CONNECTION_TYPE.MESSAGE_FLOW);
  843. },
  844. drawAssociation: function(waypoints, withArrowHead, highLighted) {
  845. var withArrowHead = withArrowHead;
  846. var conditional=isDefault=false;
  847. this._drawFlow(waypoints, conditional, isDefault, highLighted, withArrowHead, CONNECTION_TYPE.ASSOCIATION);
  848. },
  849. _drawCircleTail: function(line, connectionType){
  850. var diameter = ARROW_WIDTH/2*1.5;
  851. // anti smoothing
  852. if (this.strokeWidth%2 == 1)
  853. line.x1 += .5, line.y1 += .5;
  854. var circleTail = this.g.ellipse(line.x1, line.y1, diameter, diameter);
  855. circleTail.attr("fill", Color.white);
  856. circleTail.attr("stroke", this.getPaint());
  857. return circleTail;
  858. },
  859. _drawArrowHead: function(line, connectionType){
  860. var doubleArrowWidth = 2 * ARROW_WIDTH;
  861. if (connectionType == CONNECTION_TYPE.ASSOCIATION)
  862. var arrowHead = this.g.path("M-" + (ARROW_WIDTH/2+.5) + " -" + doubleArrowWidth + "L 0 0 L" + (ARROW_WIDTH/2+.5) + " -" + doubleArrowWidth);
  863. else
  864. var arrowHead = this.g.path("M0 0L-" + (ARROW_WIDTH/2+.5) + " -" + doubleArrowWidth + "L" + (ARROW_WIDTH/2+.5) + " -" + doubleArrowWidth + "z");
  865. //arrowHead.transform("t" + 0 + ",-" + this.getStroke() + "");
  866. // anti smoothing
  867. if (this.strokeWidth%2 == 1)
  868. line.x2 += .5, line.y2 += .5;
  869. arrowHead.transform("t" + line.x2 + "," + line.y2 + "");
  870. arrowHead.transform("...r" + Raphael.deg(line.angle - Math.PI / 2) + " " + 0 + " " + 0);
  871. if (!connectionType || connectionType == CONNECTION_TYPE.SEQUENCE_FLOW)
  872. arrowHead.attr("fill", this.getPaint());
  873. else if (connectionType == CONNECTION_TYPE.MESSAGE_FLOW)
  874. arrowHead.attr("fill", Color.white);
  875. arrowHead.attr("stroke-width", this.getStroke());
  876. arrowHead.attr("stroke", this.getPaint());
  877. return arrowHead;
  878. },
  879. /*
  880. drawArrowHead2: function(srcX, srcY, targetX, targetY) {
  881. var doubleArrowWidth = 2 * ARROW_WIDTH;
  882. //var arrowHead = this.g.path("M-" + ARROW_WIDTH/2 + " -" + doubleArrowWidth + "L0 0" + "L" + ARROW_WIDTH/2 + " -" + doubleArrowWidth + "z");
  883. var arrowHead = this.g.path("M0 0L-" + ARROW_WIDTH/1.5 + " -" + doubleArrowWidth + "L" + ARROW_WIDTH/1.5 + " -" + doubleArrowWidth + "z");
  884. //var c = ProcessDiagramCanvas.g.ellipse(0, 0, 3, 3);
  885. //c.transform("t"+targetX+","+targetY+"");
  886. var angle = Math.atan2(targetY - srcY, targetX - srcX);
  887. arrowHead.transform("t"+targetX+","+targetY+"");
  888. arrowHead.transform("...r" + Raphael.deg(angle - Math.PI / 2) + " "+0+" "+0);
  889. //console.log(arrowHead.transform());
  890. //console.log("--> " + Raphael.deg(angle - Math.PI / 2));
  891. arrowHead.attr("fill", this.getPaint());
  892. arrowHead.attr("stroke", this.getPaint());
  893. / *
  894. // shaddow
  895. var c0 = arrowHead.clone();
  896. c0.transform("...t-1 1");
  897. c0.attr("stroke-width", this.strokeWidth);
  898. c0.attr("stroke", Color.black);
  899. c0.attr("opacity", 0.15);
  900. c0.toBack();
  901. * /
  902. },
  903. */
  904. _drawConditionalSequenceFlowIndicator: function(line){
  905. var horizontal = (CONDITIONAL_INDICATOR_WIDTH * 0.7);
  906. var halfOfHorizontal = horizontal / 2;
  907. var halfOfVertical = CONDITIONAL_INDICATOR_WIDTH / 2;
  908. var uuid = null;
  909. var waypoints = [{x: 0, y: 0},
  910. {x: -halfOfHorizontal, y: halfOfVertical},
  911. {x: 0, y: CONDITIONAL_INDICATOR_WIDTH},
  912. {x: halfOfHorizontal, y: halfOfVertical}];
  913. /*
  914. var polyline = new Polyline(uuid, waypoints, this.getStroke());
  915. polyline.element = this.g.path(polyline.path);
  916. polyline.element.attr("stroke-width", this.getStroke());
  917. polyline.element.attr("stroke", this.getPaint());
  918. polyline.element.id = uuid;
  919. */
  920. var polygone = new Polygone(waypoints, this.getStroke());
  921. polygone.element = this.g.path(polygone.path);
  922. polygone.element.attr("fill", Color.white);
  923. polygone.transform("t" + line.x1 + "," + line.y1 + "");
  924. polygone.transform("...r" + Raphael.deg(line.angle - Math.PI / 2) + " " + 0 + " " + 0);
  925. var cosAngle = Math.cos((line.angle));
  926. var sinAngle = Math.sin((line.angle));
  927. //polygone.element.attr("stroke-width", this.getStroke());
  928. //polygone.element.attr("stroke", this.getPaint());
  929. polygone.attr({"stroke-width": this.getStroke(), "stroke": this.getPaint()});
  930. return polygone.element;
  931. },
  932. drawSequenceflowWithoutArrow: function(waypoints, conditional, isDefault, highLighted) {
  933. var withArrowHead = false;
  934. this._drawFlow(waypoints, conditional, isDefault, highLighted, withArrowHead, CONNECTION_TYPE.SEQUENCE_FLOW);
  935. },
  936. /*
  937. * Draw artifacts
  938. */
  939. drawPoolOrLane: function(x, y, width, height, name){
  940. // anti smoothing
  941. if (this.strokeWidth%2 == 1)
  942. x = Math.round(x) + .5, y = Math.round(y) + .5;
  943. // shape
  944. var rect = this.g.rect(x, y, width, height);
  945. var attr = {"stroke-width": NORMAL_STROKE, stroke: TASK_STROKE_COLOR};
  946. rect.attr(attr);
  947. // Add the name as text, vertical
  948. if(name != null && name.length > 0) {
  949. var attr = POOL_LANE_FONT;
  950. // Include some padding
  951. var availableTextSpace = height - 6;
  952. // Create rotation for derived font
  953. var truncated = this.fitTextToWidth(name, availableTextSpace);
  954. var realWidth = this.getStringWidth(truncated, attr);
  955. var realHeight = this.getStringHeight(truncated, attr);
  956. //console.log("truncated:", truncated, ", height:", height, ", realHeight:", realHeight, ", availableTextSpace:", availableTextSpace, ", realWidth:", realWidth);
  957. var newX = x + 2 + realHeight*1 - realHeight/2;
  958. var newY = 3 + y + availableTextSpace - (availableTextSpace - realWidth) / 2 - realWidth/2;
  959. var textElement = this.g.text(newX, newY, truncated).attr(attr);
  960. //console.log(".getBBox(): ", t.getBBox());
  961. textElement.transform("r" + Raphael.deg(270 * Math.PI/180) + " " + newX + " " + newY);
  962. }
  963. // TODO: add to set
  964. },
  965. _drawTask: function(name, x, y, width, height, thickBorder) {
  966. var originalPaint = this.getPaint();
  967. this.setPaint(TASK_COLOR);
  968. // anti smoothing
  969. if (this.strokeWidth%2 == 1)
  970. x = Math.round(x) + .5, y = Math.round(y) + .5;
  971. // shape
  972. var shape = this.g.rect(x, y, width, height, TASK_CORNER_ROUND);
  973. var attr = {"stroke-width": this.strokeWidth, stroke: TASK_STROKE_COLOR, fill: this.getPaint()};
  974. shape.attr(attr);
  975. //shape.attr({fill: "90-"+this.getPaint()+"-" + Color.get(250, 250, 244)});
  976. var contextObject = this.getConextObject();
  977. if (contextObject) {
  978. shape.id = contextObject.id;
  979. shape.data("contextObject", contextObject);
  980. }
  981. //var activity = this.getConextObject();
  982. //console.log("activity: " + activity.getId(), activity);
  983. //Object.clone(activity);
  984. /*
  985. c.mouseover(function(){
  986. this.attr({"stroke-width": NORMAL_STROKE + 2});
  987. }).mouseout(function(){
  988. this.attr({"stroke-width": NORMAL_STROKE});
  989. });
  990. */
  991. this.setPaint(originalPaint);
  992. // white shaddow
  993. this.drawShaddow(shape);
  994. if (thickBorder) {
  995. shape.attr({"stroke-width": THICK_TASK_BORDER_STROKE});
  996. } else {
  997. //g.draw(rect);
  998. }
  999. // text
  1000. if (name) {
  1001. var fontAttr = TASK_FONT;
  1002. // Include some padding
  1003. var paddingX = 5;
  1004. var paddingY = 5;
  1005. var availableTextSpace = width - paddingX*2;
  1006. // TODO: this.setFont
  1007. // var originalFont = this.getFont();
  1008. // this.setFont(TASK_FONT)
  1009. /*
  1010. var truncated = this.fitTextToWidth(name, availableTextSpace);
  1011. var realWidth = this.getStringWidth(truncated, fontAttr);
  1012. var realHeight = this.getStringHeight(truncated, fontAttr);
  1013. //var t = this.g.text(x + width/2 + realWidth*0/2 + paddingX*0, y + height/2, truncated).attr(fontAttr);
  1014. */
  1015. //console.log("draw task name: " + name);
  1016. var boxWidth = width - (2 * TEXT_PADDING);
  1017. var boxHeight = height - ICON_SIZE - ICON_PADDING - ICON_PADDING - MARKER_WIDTH - 2 - 2;
  1018. var boxX = x + width/2 - boxWidth/2;
  1019. var boxY = y + height/2 - boxHeight/2 + ICON_PADDING + ICON_PADDING - 2 - 2;
  1020. /*
  1021. var boxWidth = width - (2 * ANNOTATION_TEXT_PADDING);
  1022. var boxHeight = height - (2 * ANNOTATION_TEXT_PADDING);
  1023. var boxX = x + width/2 - boxWidth/2;
  1024. var boxY = y + height/2 - boxHeight/2;
  1025. */
  1026. this.drawTaskLabel(name, boxX, boxY, boxWidth, boxHeight);
  1027. }
  1028. },
  1029. drawTaskLabel: function(text, x, y, boxWidth, boxHeight){
  1030. var originalFont = this.getFont();
  1031. this.setFont(TASK_FONT);
  1032. this._drawMultilineText(text, x, y, boxWidth, boxHeight, MULTILINE_VERTICAL_ALIGN_MIDDLE, MULTILINE_HORIZONTAL_ALIGN_MIDDLE);
  1033. this.setFont(originalFont);
  1034. },
  1035. drawAnnotationText: function(text, x, y, width, height){
  1036. //this._drawMultilineText(text, x, y, width, height, "start");
  1037. var originalPaint = this.getPaint();
  1038. var originalFont = this.getFont();
  1039. this.setPaint(Color.black);
  1040. this.setFont(TASK_FONT);
  1041. this._drawMultilineText(text, x, y, width, height, MULTILINE_VERTICAL_ALIGN_TOP, MULTILINE_HORIZONTAL_ALIGN_LEFT);
  1042. this.setPaint(originalPaint);
  1043. this.setFont(originalFont);
  1044. },
  1045. drawLabel: function(text, x, y, width, height){
  1046. //this._drawMultilineText(text, x, y, width, height, "start");
  1047. var originalPaint = this.getPaint();
  1048. var originalFont = this.getFont();
  1049. this.setPaint(LABEL_COLOR);
  1050. //this.setFont(LABEL_FONT);
  1051. this.setFont(LABEL_FONT_SMOOTH);
  1052. // predefined box width for labels
  1053. // TODO: use label width as is, but not height (for stretching)
  1054. if (!width || !height) {
  1055. width = 100;
  1056. height = 0;
  1057. }
  1058. // TODO: remove it. It is debug
  1059. x = x - width/2;
  1060. this._drawMultilineText(text, x, y, width, height, MULTILINE_VERTICAL_ALIGN_TOP, MULTILINE_HORIZONTAL_ALIGN_MIDDLE);
  1061. this.setPaint(originalPaint);
  1062. this.setFont(originalFont);
  1063. },
  1064. /*
  1065. drawMultilineLabel: function(text, x, y){
  1066. var originalFont = this.getFont();
  1067. this.setFont(LABEL_FONT_SMOOTH);
  1068. var boxWidth = 80;
  1069. x = x - boxWidth/2
  1070. this._drawMultilineText(text, x, y, boxWidth, null, "middle");
  1071. this.setFont(originalFont);
  1072. },
  1073. */
  1074. getStringWidth: function(text, fontAttrs){
  1075. var textElement = this.g.text(0, 0, text).attr(fontAttrs).hide();
  1076. var bb = textElement.getBBox();
  1077. //console.log("string width: ", t.getBBox().width);
  1078. return textElement.getBBox().width;
  1079. },
  1080. getStringHeight: function(text, fontAttrs){
  1081. var textElement = this.g.text(0, 0, text).attr(fontAttrs).hide();
  1082. var bb = textElement.getBBox();
  1083. //console.log("string height: ", t.getBBox().height);
  1084. return textElement.getBBox().height;
  1085. },
  1086. fitTextToWidth: function(original, width) {
  1087. var text = original;
  1088. // TODO: move attr on parameters
  1089. var attr = {font: "11px Arial", opacity: 0};
  1090. // remove length for "..."
  1091. var dots = this.g.text(0, 0, "...").attr(attr).hide();
  1092. var dotsBB = dots.getBBox();
  1093. var maxWidth = width - dotsBB.width;
  1094. var textElement = this.g.text(0, 0, text).attr(attr).hide();
  1095. var bb = textElement.getBBox();
  1096. // it's a little bit incorrect with "..."
  1097. while (bb.width > maxWidth && text.length > 0) {
  1098. text = text.substring(0, text.length - 1);
  1099. textElement.attr({"text": text});
  1100. bb = textElement.getBBox();
  1101. }
  1102. // remove element from paper
  1103. textElement.remove();
  1104. if (text != original) {
  1105. text = text + "...";
  1106. }
  1107. return text;
  1108. },
  1109. wrapTextToWidth: function(original, width){
  1110. //return original;
  1111. var text = original;
  1112. var wrappedText = "\n";
  1113. // TODO: move attr on parameters
  1114. var attr = {font: "11px Arial", opacity: 0};
  1115. var textElement = this.g.text(0, 0, wrappedText).attr(attr).hide();
  1116. var bb = textElement.getBBox();
  1117. var resultText = "";
  1118. var i = 0, j = 0;
  1119. while (text.length > 0) {
  1120. while (bb.width < width && text.length>0) {
  1121. // remove "\n"
  1122. wrappedText = wrappedText.substring(0,wrappedText.length-1);
  1123. // add new char, add "\n"
  1124. wrappedText = wrappedText + text.substring(0,1) + "\n";
  1125. text = text.substring(1);
  1126. textElement.attr({"text": wrappedText});
  1127. bb = textElement.getBBox();
  1128. i++;
  1129. if (i>200) break;
  1130. }
  1131. // remove "\n"
  1132. wrappedText = wrappedText.substring(0, wrappedText.length - 1);
  1133. if (text.length == 0) {
  1134. resultText += wrappedText;
  1135. break;
  1136. }
  1137. // return last char to text
  1138. text = wrappedText.substring(wrappedText.length-1) + text;
  1139. // remove last char from wrappedText
  1140. wrappedText = wrappedText.substring(0, wrappedText.length-1) + "\n";
  1141. textElement.attr({"text": wrappedText});
  1142. bb = textElement.getBBox();
  1143. //console.log(">> ", wrappedText, ", ", text);
  1144. resultText += wrappedText;
  1145. wrappedText = "\n";
  1146. j++;
  1147. if (j>20) break;
  1148. }
  1149. // remove element from paper
  1150. textElement.remove();
  1151. return resultText;
  1152. },
  1153. wrapTextToWidth2: function(original, width){
  1154. var text = original;
  1155. var wrappedText = "\n";
  1156. // TODO: move attr on parameters
  1157. var attr = {font: "11px Arial", opacity: 0};
  1158. var textElement = this.g.text(0, 0, wrappedText).attr(attr).hide();
  1159. var bb = textElement.getBBox();
  1160. var resultText = "";
  1161. var i = 0, j = 0;
  1162. while (text.length > 0) {
  1163. while (bb.width < width && text.length>0) {
  1164. // remove "\n"
  1165. wrappedText = wrappedText.substring(0,wrappedText.length-1);
  1166. // add new char, add "\n"
  1167. wrappedText = wrappedText + text.substring(0,1) + "\n";
  1168. text = text.substring(1);
  1169. textElement.attr({"text": wrappedText});
  1170. bb = textElement.getBBox();
  1171. i++;
  1172. if (i>200) break;
  1173. }
  1174. // remove "\n"
  1175. wrappedText = wrappedText.substring(0, wrappedText.length - 1);
  1176. if (text.length == 0) {
  1177. resultText += wrappedText;
  1178. break;
  1179. }
  1180. // return last char to text
  1181. text = wrappedText.substring(wrappedText.length-1) + text;
  1182. // remove last char from wrappedText
  1183. wrappedText = wrappedText.substring(0, wrappedText.length-1) + "\n";
  1184. textElement.attr({"text": wrappedText});
  1185. bb = textElement.getBBox();
  1186. //console.log(">> ", wrappedText, ", ", text);
  1187. resultText += wrappedText;
  1188. wrappedText = "\n";
  1189. j++;
  1190. if (j>20) break;
  1191. }
  1192. // remove element from paper
  1193. textElement.remove();
  1194. return resultText;
  1195. },
  1196. drawUserTask: function(name, x, y, width, height) {
  1197. this.g.setStart();
  1198. this._drawTask(name, x, y, width, height);
  1199. var img = this.g.image(USERTASK_IMAGE, x + ICON_PADDING, y + ICON_PADDING, ICON_SIZE, ICON_SIZE);
  1200. var set = this.g.setFinish();
  1201. this.addHandlers(set, x, y, width, height, "task");
  1202. },
  1203. drawScriptTask: function(name, x, y, width, height) {
  1204. this.g.setStart();
  1205. this._drawTask(name, x, y, width, height);
  1206. var img = this.g.image(SCRIPTTASK_IMAGE, x + ICON_PADDING, y + ICON_PADDING, ICON_SIZE, ICON_SIZE);
  1207. var set = this.g.setFinish();
  1208. this.addHandlers(set, x, y, width, height, "task");
  1209. },
  1210. drawServiceTask: function(name, x, y, width, height) {
  1211. this.g.setStart();
  1212. this._drawTask(name, x, y, width, height);
  1213. var img = this.g.image(SERVICETASK_IMAGE, x + ICON_PADDING, y + ICON_PADDING, ICON_SIZE, ICON_SIZE);
  1214. var set = this.g.setFinish();
  1215. this.addHandlers(set, x, y, width, height, "task");
  1216. },
  1217. drawReceiveTask: function(name, x, y, width, height) {
  1218. this.g.setStart();
  1219. this._drawTask(name, x, y, width, height);
  1220. var img = this.g.image(RECEIVETASK_IMAGE, x + 7, y + 7, ICON_SIZE, ICON_SIZE);
  1221. var set = this.g.setFinish();
  1222. this.addHandlers(set, x, y, width, height, "task");
  1223. },
  1224. drawSendTask: function(name, x, y, width, height) {
  1225. this.g.setStart();
  1226. this._drawTask(name, x, y, width, height);
  1227. var img = this.g.image(SENDTASK_IMAGE, x + 7, y + 7, ICON_SIZE, ICON_SIZE);
  1228. var set = this.g.setFinish();
  1229. this.addHandlers(set, x, y, width, height, "task");
  1230. },
  1231. drawManualTask: function(name, x, y, width, height) {
  1232. this.g.setStart();
  1233. this._drawTask(name, x, y, width, height);
  1234. var img = this.g.image(MANUALTASK_IMAGE, x + 7, y + 7, ICON_SIZE, ICON_SIZE);
  1235. var set = this.g.setFinish();
  1236. this.addHandlers(set, x, y, width, height, "task");
  1237. },
  1238. drawBusinessRuleTask: function(name, x, y, width, height) {
  1239. this.g.setStart();
  1240. this._drawTask(name, x, y, width, height);
  1241. var img = this.g.image(BUSINESS_RULE_TASK_IMAGE, x + 7, y + 7, ICON_SIZE, ICON_SIZE);
  1242. var set = this.g.setFinish();
  1243. this.addHandlers(set, x, y, width, height, "task");
  1244. },
  1245. drawExpandedSubProcess: function(name, x, y, width, height, isTriggeredByEvent){
  1246. this.g.setStart();
  1247. // anti smoothing
  1248. if (this.strokeWidth%2 == 1)
  1249. x = Math.round(x) + .5, y = Math.round(y) + .5;
  1250. // shape
  1251. var rect = this.g.rect(x, y, width, height, EXPANDED_SUBPROCESS_CORNER_ROUND);
  1252. // Use different stroke (dashed)
  1253. if(isTriggeredByEvent) {
  1254. rect.attr(EVENT_SUBPROCESS_ATTRS);
  1255. } else {
  1256. rect.attr(EXPANDED_SUBPROCESS_ATTRS);
  1257. }
  1258. this.setContextToElement(rect);
  1259. var fontAttr = EXPANDED_SUBPROCESS_FONT;
  1260. // Include some padding
  1261. var paddingX = 10;
  1262. var paddingY = 5;
  1263. var availableTextSpace = width - paddingX*2;
  1264. var truncated = this.fitTextToWidth(name, availableTextSpace);
  1265. var realWidth = this.getStringWidth(truncated, fontAttr);
  1266. var realHeight = this.getStringHeight(truncated, fontAttr);
  1267. var textElement = this.g.text(x + width/2 - realWidth*0/2 + 0*paddingX, y + realHeight/2 + paddingY, truncated).attr(fontAttr);
  1268. var set = this.g.setFinish();
  1269. // TODO: Expanded Sub Process may has specific handlers
  1270. //this.addHandlers(set, x, y, width, height, "task");
  1271. },
  1272. drawCollapsedSubProcess: function(name, x, y, width, height, isTriggeredByEvent) {
  1273. this.g.setStart();
  1274. this._drawCollapsedTask(name, x, y, width, height, false);
  1275. var set = this.g.setFinish();
  1276. this.addHandlers(set, x, y, width, height, "task");
  1277. },
  1278. drawCollapsedCallActivity: function(name, x, y, width, height) {
  1279. this.g.setStart();
  1280. this._drawCollapsedTask(name, x, y, width, height, true);
  1281. var set = this.g.setFinish();
  1282. this.addHandlers(set, x, y, width, height, "task");
  1283. },
  1284. _drawCollapsedTask: function(name, x, y, width, height, thickBorder) {
  1285. // The collapsed marker is now visualized separately
  1286. this._drawTask(name, x, y, width, height, thickBorder);
  1287. },
  1288. drawCollapsedMarker: function(x, y, width, height){
  1289. // rectangle
  1290. var rectangleWidth = MARKER_WIDTH;
  1291. var rectangleHeight = MARKER_WIDTH;
  1292. // anti smoothing
  1293. if (this.strokeWidth%2 == 1)
  1294. y += .5;
  1295. var rect = this.g.rect(x + (width - rectangleWidth) / 2, y + height - rectangleHeight - 3, rectangleWidth, rectangleHeight);
  1296. // plus inside rectangle
  1297. var cx = rect.attr("x") + rect.attr("width")/2;
  1298. var cy = rect.attr("y") + rect.attr("height")/2;
  1299. var line = this.g.path(
  1300. "M" + cx + " " + (cy+2) + "L" + cx + " " + (cy-2) +
  1301. "M" + (cx-2) + " " + cy + "L" + (cx+2) + " " + cy
  1302. ).attr({"stroke-width": this.strokeWidth});
  1303. },
  1304. drawActivityMarkers: function(x, y, width, height, multiInstanceSequential, multiInstanceParallel, collapsed){
  1305. if (collapsed) {
  1306. if (!multiInstanceSequential && !multiInstanceParallel) {
  1307. this.drawCollapsedMarker(x, y, width, height);
  1308. } else {
  1309. this.drawCollapsedMarker(x - MARKER_WIDTH / 2 - 2, y, width, height);
  1310. if (multiInstanceSequential) {
  1311. console.log("is collapsed and multiInstanceSequential");
  1312. this.drawMultiInstanceMarker(true, x + MARKER_WIDTH / 2 + 2, y, width, height);
  1313. } else if (multiInstanceParallel) {
  1314. console.log("is collapsed and multiInstanceParallel");
  1315. this.drawMultiInstanceMarker(false, x + MARKER_WIDTH / 2 + 2, y, width, height);
  1316. }
  1317. }
  1318. } else {
  1319. if (multiInstanceSequential) {
  1320. console.log("is multiInstanceSequential");
  1321. this.drawMultiInstanceMarker(true, x, y, width, height);
  1322. } else if (multiInstanceParallel) {
  1323. console.log("is multiInstanceParallel");
  1324. this.drawMultiInstanceMarker(false, x, y, width, height);
  1325. }
  1326. }
  1327. },
  1328. drawGateway: function(x, y, width, height) {
  1329. var rhombus = this.g.path( "M" + x + " " + (y + (height / 2)) +
  1330. "L" + (x + (width / 2)) + " " + (y + height) +
  1331. "L" + (x + width) + " " + (y + (height / 2)) +
  1332. "L" + (x + (width / 2)) + " " + y +
  1333. "z"
  1334. );
  1335. // white shaddow
  1336. this.drawShaddow(rhombus);
  1337. rhombus.attr("stroke-width", this.strokeWidth);
  1338. rhombus.attr("stroke", Color.SlateGrey);
  1339. rhombus.attr({fill: Color.white});
  1340. this.setContextToElement(rhombus);
  1341. return rhombus;
  1342. },
  1343. drawParallelGateway: function(x, y, width, height) {
  1344. this.g.setStart();
  1345. // rhombus
  1346. this.drawGateway(x, y, width, height);
  1347. // plus inside rhombus
  1348. var originalStroke = this.getStroke();
  1349. this.setStroke(GATEWAY_TYPE_STROKE);
  1350. var plus = this.g.path(
  1351. "M" + (x + 10) + " " + (y + height / 2) + "L" + (x + width - 10) + " " + (y + height / 2) + // horizontal
  1352. "M" + (x + width / 2) + " " + (y + height - 10) + "L" + (x + width / 2) + " " + (y + 10) // vertical
  1353. );
  1354. plus.attr({"stroke-width": this.getStroke(), "stroke": this.getPaint()});
  1355. this.setStroke(originalStroke);
  1356. var set = this.g.setFinish();
  1357. this.addHandlers(set, x, y, width, height, "gateway");
  1358. },
  1359. drawExclusiveGateway: function(x, y, width, height) {
  1360. this.g.setStart();
  1361. // rhombus
  1362. var rhombus = this.drawGateway(x, y, width, height);
  1363. var quarterWidth = width / 4;
  1364. var quarterHeight = height / 4;
  1365. // X inside rhombus
  1366. var originalStroke = this.getStroke();
  1367. this.setStroke(GATEWAY_TYPE_STROKE);
  1368. var iks = this.g.path(
  1369. "M" + (x + quarterWidth + 3) + " " + (y + quarterHeight + 3) + "L" + (x + 3 * quarterWidth - 3) + " " + (y + 3 * quarterHeight - 3) +
  1370. "M" + (x + quarterWidth + 3) + " " + (y + 3 * quarterHeight - 3) + "L" + (x + 3 * quarterWidth - 3) + " " + (y + quarterHeight + 3)
  1371. );
  1372. iks.attr({"stroke-width": this.getStroke(), "stroke": this.getPaint()});
  1373. this.setStroke(originalStroke);
  1374. var set = this.g.setFinish();
  1375. this.addHandlers(set, x, y, width, height, "gateway");
  1376. },
  1377. drawInclusiveGateway: function(x, y, width, height){
  1378. this.g.setStart();
  1379. // rhombus
  1380. this.drawGateway(x, y, width, height);
  1381. var diameter = width / 4;
  1382. // circle inside rhombus
  1383. var originalStroke = this.getStroke();
  1384. this.setStroke(GATEWAY_TYPE_STROKE);
  1385. var circle = this.g.ellipse(width/2 + x, height/2 + y, diameter, diameter);
  1386. circle.attr({"stroke-width": this.getStroke(), "stroke": this.getPaint()});
  1387. this.setStroke(originalStroke);
  1388. var set = this.g.setFinish();
  1389. this.addHandlers(set, x, y, width, height, "gateway");
  1390. },
  1391. drawEventBasedGateway: function(x, y, width, height){
  1392. this.g.setStart();
  1393. // rhombus
  1394. this.drawGateway(x, y, width, height);
  1395. var diameter = width / 2;
  1396. // rombus inside rhombus
  1397. var originalStroke = this.getStroke();
  1398. this.setStroke(GATEWAY_TYPE_STROKE);
  1399. // draw GeneralPath (polygon)
  1400. var n=5;
  1401. var angle = 2*Math.PI/n;
  1402. var x1Points = [];
  1403. var y1Points = [];
  1404. for ( var index = 0; index < n; index++ ) {
  1405. var v = index*angle - Math.PI/2;
  1406. x1Points[index] = x + parseInt(Math.round(width/2)) + parseInt(Math.round((width/4)*Math.cos(v)));
  1407. y1Points[index] = y + parseInt(Math.round(height/2)) + parseInt(Math.round((height/4)*Math.sin(v)));
  1408. }
  1409. //g.drawPolygon(x1Points, y1Points, n);
  1410. var path = "";
  1411. for ( var index = 0; index < n; index++ ) {
  1412. if (index == 0)
  1413. path += "M";
  1414. else
  1415. path += "L";
  1416. path += x1Points[index] + "," + y1Points[index];
  1417. }
  1418. path += "z";
  1419. var polygone = this.g.path(path);
  1420. polygone.attr("stroke-width", this.strokeWidth);
  1421. polygone.attr("stroke", this.getPaint());
  1422. this.setStroke(originalStroke);
  1423. var set = this.g.setFinish();
  1424. this.addHandlers(set, x, y, width, height, "gateway");
  1425. },
  1426. /*
  1427. * drawMultiInstanceMarker
  1428. * drawHighLight
  1429. * highLightFlow
  1430. */
  1431. drawMultiInstanceMarker: function(sequential, x, y, width, height) {
  1432. var rectangleWidth = MARKER_WIDTH;
  1433. var rectangleHeight = MARKER_WIDTH;
  1434. // anti smoothing
  1435. if (this.strokeWidth%2 == 1)
  1436. x += .5;//, y += .5;
  1437. var lineX = x + (width - rectangleWidth) / 2;
  1438. var lineY = y + height - rectangleHeight - 3;
  1439. var originalStroke = this.getStroke();
  1440. this.setStroke(MULTI_INSTANCE_STROKE);
  1441. if (sequential) {
  1442. var line = this.g.path(
  1443. "M" + lineX + " " + lineY + "L" + (lineX + rectangleWidth) + " " + lineY +
  1444. "M" + lineX + " " + (lineY + rectangleHeight / 2) + "L" + (lineX + rectangleWidth) + " " + (lineY + rectangleHeight / 2) +
  1445. "M" + lineX + " " + (lineY + rectangleHeight) + "L" + (lineX + rectangleWidth) + " " + (lineY + rectangleHeight)
  1446. ).attr({"stroke-width": this.strokeWidth});
  1447. } else {
  1448. var line = this.g.path(
  1449. "M" + lineX + " " + lineY + "L" + lineX + " " + (lineY + rectangleHeight) +
  1450. "M" + (lineX + rectangleWidth / 2) + " " + lineY + "L" + (lineX + rectangleWidth / 2) + " " + (lineY + rectangleHeight) +
  1451. "M" + (lineX + rectangleWidth) + " " + lineY + "L" + (lineX + rectangleWidth) + " " + (lineY + rectangleHeight)
  1452. ).attr({"stroke-width": this.strokeWidth});
  1453. }
  1454. this.setStroke(originalStroke);
  1455. },
  1456. drawHighLight: function(x, y, width, height){
  1457. var originalPaint = this.getPaint();
  1458. var originalStroke = this.getStroke();
  1459. this.setPaint(HIGHLIGHT_COLOR);
  1460. this.setStroke(THICK_TASK_BORDER_STROKE);
  1461. //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);
  1462. 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);
  1463. rect.attr("stroke-width", this.strokeWidth);
  1464. rect.attr("stroke", this.getPaint());
  1465. this.setPaint(originalPaint);
  1466. this.setStroke(originalStroke);
  1467. },
  1468. highLightActivity: function(activityId){
  1469. var shape = this.g.getById(activityId);
  1470. if (!shape) {
  1471. console.error("Activity " + activityId + " not found");
  1472. return;
  1473. }
  1474. var contextObject = shape.data("contextObject");
  1475. if (contextObject)
  1476. console.log("--> highLightActivity: ["+contextObject.getProperty("type")+"], activityId: " + contextObject.getId());
  1477. else
  1478. console.log("--> highLightActivity: ", shape, shape.data("contextObject"));
  1479. shape.attr("stroke-width", THICK_TASK_BORDER_STROKE);
  1480. shape.attr("stroke", HIGHLIGHT_COLOR);
  1481. },
  1482. highLightFlow: function(flowId){
  1483. var shapeFlow = this.g.getById(flowId);
  1484. if (!shapeFlow) {
  1485. console.error("Flow " + flowId + " not found");
  1486. return;
  1487. }
  1488. var contextObject = shapeFlow.data("contextObject");
  1489. if (contextObject)
  1490. console.log("--> highLightFlow: ["+contextObject.id+"] " + contextObject.flow);
  1491. //console.log("--> highLightFlow: ", flow.flow, flow.data("set"));
  1492. var st = shapeFlow.data("set");
  1493. st.attr("stroke-width", SEQUENCEFLOW_HIGHLIGHT_STROKE);
  1494. st.attr("stroke", HIGHLIGHT_COLOR);
  1495. var withArrowHead = shapeFlow.data("withArrowHead");
  1496. if (withArrowHead)
  1497. st[1].attr("fill", HIGHLIGHT_COLOR);
  1498. st.forEach(function(el){
  1499. //console.log("---->", el);
  1500. //el.attr("")
  1501. });
  1502. },
  1503. _drawClock: function(cx, cy, width, height){
  1504. var circle = this.g.ellipse(cx, cy, 1, 1).attr({stroke:"none", fill: Color.get(232, 239, 241)});
  1505. //var c = this.g.ellipse(cx, cy, width, height).attr({stroke:"none", fill: Color.red});
  1506. //x = cx - width/2;
  1507. //y = cy - height/2;
  1508. var clock = this.g.path(
  1509. /* 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" +
  1510. /* 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" +
  1511. /* 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" +
  1512. /* 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" +
  1513. /* 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" +
  1514. /* 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" +
  1515. /* 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" +
  1516. /* 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" +
  1517. /* 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" +
  1518. /* 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" +
  1519. /* 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" +
  1520. /* 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" +
  1521. /* 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" +
  1522. /* 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" +
  1523. "");
  1524. clock.attr({fill: Color.black, stroke: "none"});
  1525. //clock.transform("t " + (cx-29.75/2) + " " + (cy-29.75/2));
  1526. //clock.transform("...s 0.85");
  1527. //clock.transform("...s " + .85 + " " + .85);
  1528. clock.transform("t " + (-2.374) + " " + (-2.374) );
  1529. clock.transform("...t -" + (15.5-2.374) + " -" + (15.5-2.374) );
  1530. clock.transform("...s " + 1*(width/35) + " " + 1*(height/35));
  1531. clock.transform("...T " + cx + " " + cy);
  1532. //clock.transform("t " + (cx-width/2) + " " + (cy-height/2));
  1533. //console.log(".getBBox(): ", clock.getBBox());
  1534. //console.log(".attr(): ", c.attrs);
  1535. circle.attr("rx", clock.getBBox().width/2);
  1536. circle.attr("ry", clock.getBBox().height/2);
  1537. //return circle
  1538. },
  1539. _drawPentagon: function(cx, cy, width, height, filled){
  1540. // draw GeneralPath (polygon)
  1541. var n=5;
  1542. var angle = 2*Math.PI/n;
  1543. var waypoints = [];
  1544. for ( var index = 0; index < n; index++ ) {
  1545. var v = index*angle - Math.PI/2;
  1546. var point = {};
  1547. point.x = -width*1.2/2 + parseInt(Math.round(width*1.2/2)) + parseInt(Math.round((width*1.2/4)*Math.cos(v)));
  1548. point.y = -height*1.2/2 + parseInt(Math.round(height*1.2/2)) + parseInt(Math.round((height*1.2/4)*Math.sin(v)));
  1549. waypoints[index] = point;
  1550. }
  1551. var polygone = new Polygone(waypoints, this.getStroke());
  1552. polygone.element = this.g.path(polygone.path);
  1553. if (filled)
  1554. polygone.element.attr("fill", Color.black);
  1555. else
  1556. polygone.element.attr("fill", Color.white);
  1557. polygone.element.transform("s " + 1*(width/35) + " " + 1*(height/35));
  1558. polygone.element.transform("...T " + cx + " " + cy);
  1559. },
  1560. //_drawMultilineText: function(text, x, y, boxWidth, boxHeight, textAnchor) {
  1561. _drawMultilineText: function(text, x, y, boxWidth, boxHeight, verticalAlign, horizontalAlign) {
  1562. if (!text || text == "")
  1563. return;
  1564. // Autostretch boxHeight if boxHeight is 0
  1565. if (boxHeight == 0)
  1566. verticalAlign = MULTILINE_VERTICAL_ALIGN_TOP;
  1567. //var TEXT_PADDING = 3;
  1568. var width = boxWidth;
  1569. if (boxHeight)
  1570. var height = boxHeight;
  1571. var layouts = [];
  1572. //var font = {font: "11px Arial", opacity: 1, "fill": LABEL_COLOR};
  1573. var font = this.getFont();
  1574. var measurer = new LineBreakMeasurer(this.g, x, y, text, font);
  1575. var lineHeight = measurer.rafaelTextObject.getBBox().height;
  1576. //console.log("text: ", text.replace(/\n/g, "?"));
  1577. if (height) {
  1578. var availableLinesCount = parseInt(height/lineHeight);
  1579. //console.log("availableLinesCount: " + availableLinesCount);
  1580. }
  1581. var i = 1;
  1582. while (measurer.getPosition() < measurer.text.getEndIndex()) {
  1583. var layout = measurer.nextLayout(width);
  1584. //console.log("LAYOUT: " + layout + ", getPosition: " + measurer.getPosition());
  1585. if (layout != null) {
  1586. // TODO: and check if measurer has next layout. If no then don't draw dots
  1587. if (!availableLinesCount || i < availableLinesCount) {
  1588. layouts.push(layout);
  1589. } else {
  1590. layouts.push(this.fitTextToWidth(layout + "...", boxWidth));
  1591. break;
  1592. }
  1593. }
  1594. i++;
  1595. };
  1596. //console.log(layouts);
  1597. measurer.rafaelTextObject.attr({"text": layouts.join("\n")});
  1598. if (horizontalAlign)
  1599. measurer.rafaelTextObject.attr({"text-anchor": horizontalAlign}); // end, middle, start
  1600. var bb = measurer.rafaelTextObject.getBBox();
  1601. // TODO: there is somethin wrong with wertical align. May be: measurer.rafaelTextObject.attr({"y": y + height/2 - bb.height/2})
  1602. measurer.rafaelTextObject.attr({"y": y + bb.height/2});
  1603. //var bb = measurer.rafaelTextObject.getBBox();
  1604. if (measurer.rafaelTextObject.attr("text-anchor") == MULTILINE_HORIZONTAL_ALIGN_MIDDLE )
  1605. measurer.rafaelTextObject.attr("x", x + boxWidth/2);
  1606. else if (measurer.rafaelTextObject.attr("text-anchor") == MULTILINE_HORIZONTAL_ALIGN_RIGHT )
  1607. measurer.rafaelTextObject.attr("x", x + boxWidth);
  1608. var boxStyle = {stroke: Color.LightSteelBlue2, "stroke-width": 1.0, "stroke-dasharray": "- "};
  1609. //var box = this.g.rect(x+.5, y + .5, width, height).attr(boxStyle);
  1610. var textAreaCX = x + boxWidth/2;
  1611. var height = boxHeight;
  1612. if (!height) height = bb.height;
  1613. var textAreaCY = y + height/2;
  1614. var dotLeftTop = this.g.ellipse(x, y, 3, 3).attr({"stroke-width": 0, fill: Color.LightSteelBlue, stroke: "none"}).hide();
  1615. var dotCenter = this.g.ellipse(textAreaCX, textAreaCY, 3, 3).attr({fill: Color.LightSteelBlue2, stroke: "none"}).hide();
  1616. /*
  1617. // real bbox
  1618. var bb = measurer.rafaelTextObject.getBBox();
  1619. var rect = paper.rect(bb.x+.5, bb.y + .5, bb.width, bb.height).attr({"stroke-width": 1});
  1620. */
  1621. var rect = this.g.rect(x, y, boxWidth, height).attr({"stroke-width": 1}).attr(boxStyle).hide();
  1622. var debugSet = this.g.set();
  1623. debugSet.push(dotLeftTop, dotCenter, rect);
  1624. //debugSet.show();
  1625. },
  1626. drawTextAnnotation: function(text, x, y, width, height){
  1627. var lineLength = 18;
  1628. var path = [];
  1629. path.push(["M", x + lineLength, y]);
  1630. path.push(["L", x, y]);
  1631. path.push(["L", x, y + height]);
  1632. path.push(["L", x + lineLength, y + height]);
  1633. path.push(["L", x + lineLength, y + height -1]);
  1634. path.push(["L", x + 1, y + height -1]);
  1635. path.push(["L", x + 1, y + 1]);
  1636. path.push(["L", x + lineLength, y + 1]);
  1637. path.push(["z"]);
  1638. var textAreaLines = this.g.path(path);
  1639. var boxWidth = width - (2 * ANNOTATION_TEXT_PADDING);
  1640. var boxHeight = height - (2 * ANNOTATION_TEXT_PADDING);
  1641. var boxX = x + width/2 - boxWidth/2;
  1642. var boxY = y + height/2 - boxHeight/2;
  1643. // for debug
  1644. var rectStyle = {stroke: Color(112, 146, 190), "stroke-width": 1.0, "stroke-dasharray": "- "};
  1645. var r = this.g.rect(boxX, boxY, boxWidth, boxHeight).attr(rectStyle);
  1646. //
  1647. this.drawAnnotationText(text, boxX, boxY, boxWidth, boxHeight);
  1648. },
  1649. drawLabel111111111: function(text, x, y, width, height, labelAttrs){
  1650. var debug = false;
  1651. // text
  1652. if (text != null && text != undefined && text != "") {
  1653. var attr = LABEL_FONT;
  1654. //console.log("x", x, "y", y, "width", width, "height", height );
  1655. wrappedText = text;
  1656. if (labelAttrs && labelAttrs.wrapWidth) {
  1657. wrappedText = this.wrapTextToWidth(wrappedText, labelAttrs.wrapWidth);
  1658. }
  1659. var realWidth = this.getStringWidth(wrappedText, attr);
  1660. var realHeight = this.getStringHeight(wrappedText, attr);
  1661. var textAreaCX = x + width/2;
  1662. var textAreaCY = y + 3 + height + this.getStringHeight(wrappedText, attr)/2;
  1663. var textX = textAreaCX;
  1664. var textY = textAreaCY;
  1665. var textAttrs = {};
  1666. if (labelAttrs && labelAttrs.align) {
  1667. switch (labelAttrs.align) {
  1668. case "left":
  1669. textAttrs["text-anchor"] = "start";
  1670. textX = textX - realWidth/2;
  1671. break;
  1672. case "center":
  1673. textAttrs["text-anchor"] = "middle";
  1674. break;
  1675. case "right":
  1676. textAttrs["text-anchor"] = "end";
  1677. textX = textX + realWidth/2;
  1678. break;
  1679. }
  1680. }
  1681. if (labelAttrs && labelAttrs.wrapWidth) {
  1682. if (true) {
  1683. // Draw frameborder
  1684. var textAreaStyle = {stroke: Color.LightSteelBlue2, "stroke-width": 1.0, "stroke-dasharray": "- "};
  1685. var textAreaX = textAreaCX - realWidth/2;
  1686. var textAreaY = textAreaCY+.5 - realHeight/2;
  1687. var textArea = this.g.rect(textAreaX, textAreaY, realWidth, realHeight).attr(textAreaStyle);
  1688. var textAreaLines = this.g.path("M" + textAreaX + " " + textAreaY + "L" + (textAreaX+realWidth) + " " + (textAreaY+realHeight) + "M" + + (textAreaX+realWidth) + " " + textAreaY + "L" + textAreaX + " " + (textAreaY+realHeight));
  1689. textAreaLines.attr(textAreaStyle);
  1690. this.g.ellipse(textAreaCX, textAreaCY, 3, 3).attr({fill: Color.LightSteelBlue2, stroke: "none"});
  1691. }
  1692. }
  1693. var label = this.g.text(textX, textY, wrappedText).attr(attr).attr(textAttrs);
  1694. //label.id = Raphael.createUUID();
  1695. //console.log("label ", label.id, ", ", wrappedText);
  1696. if (this.fontSmoothing) {
  1697. label.attr({stroke: LABEL_COLOR, "stroke-width":.4});
  1698. }
  1699. // debug
  1700. if (debug) {
  1701. var imageAreaStyle = {stroke: Color.grey61, "stroke-width": 1.0, "stroke-dasharray": "- "};
  1702. var imageArea = this.g.rect(x+.5, y+.5, width, height).attr(imageAreaStyle);
  1703. var imageAreaLines = this.g.path("M" + x + " " + y + "L" + (x+width) + " " + (y+height) + "M" + + (x+width) + " " + y + "L" + x + " " + (y+height));
  1704. imageAreaLines.attr(imageAreaStyle);
  1705. var dotStyle = {fill: Color.Coral, stroke: "none"};
  1706. this.g.ellipse(x, y, 3, 3).attr(dotStyle);
  1707. this.g.ellipse(x+width, y, 2, 2).attr(dotStyle);
  1708. this.g.ellipse(x+width, y+height, 2, 2).attr(dotStyle);
  1709. this.g.ellipse(x, y+height, 2, 2).attr(dotStyle);
  1710. }
  1711. return label;
  1712. }
  1713. },
  1714. vvoid: function(){}
  1715. };