BpmnRenderer.js 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912
  1. import inherits from 'inherits';
  2. import {
  3. isObject,
  4. assign,
  5. forEach
  6. } from 'min-dash';
  7. import BaseRenderer from 'diagram-js/lib/draw/BaseRenderer';
  8. import {
  9. isExpanded,
  10. isEventSubProcess
  11. } from '../util/DiUtil';
  12. import { is } from '../util/ModelUtil';
  13. import {
  14. createLine
  15. } from 'diagram-js/lib/util/RenderUtil';
  16. import {
  17. isTypedEvent,
  18. isThrowEvent,
  19. isCollection,
  20. getDi,
  21. getSemantic,
  22. getCirclePath,
  23. getRoundRectPath,
  24. getDiamondPath,
  25. getRectPath,
  26. getFillColor,
  27. getStrokeColor
  28. } from './BpmnRenderUtil';
  29. import {
  30. query as domQuery
  31. } from 'min-dom';
  32. import {
  33. append as svgAppend,
  34. attr as svgAttr,
  35. create as svgCreate,
  36. classes as svgClasses
  37. } from 'tiny-svg';
  38. import {
  39. rotate,
  40. transform,
  41. translate
  42. } from 'diagram-js/lib/util/SvgTransformUtil';
  43. import Ids from 'ids';
  44. var RENDERER_IDS = new Ids();
  45. var TASK_BORDER_RADIUS = 10;
  46. var INNER_OUTER_DIST = 3;
  47. var DEFAULT_FILL_OPACITY = .95,
  48. HIGH_FILL_OPACITY = .35;
  49. export default function BpmnRenderer(
  50. config, eventBus, styles, pathMap,
  51. canvas, textRenderer, priority) {
  52. BaseRenderer.call(this, eventBus, priority);
  53. var defaultFillColor = config && config.defaultFillColor,
  54. defaultStrokeColor = config && config.defaultStrokeColor;
  55. var rendererId = RENDERER_IDS.next();
  56. var markers = {};
  57. var computeStyle = styles.computeStyle;
  58. function addMarker(id, options) {
  59. var attrs = assign({
  60. fill: 'black',
  61. strokeWidth: 1,
  62. strokeLinecap: 'round',
  63. strokeDasharray: 'none'
  64. }, options.attrs);
  65. var ref = options.ref || { x: 0, y: 0 };
  66. var scale = options.scale || 1;
  67. // fix for safari / chrome / firefox bug not correctly
  68. // resetting stroke dash array
  69. if (attrs.strokeDasharray === 'none') {
  70. attrs.strokeDasharray = [10000, 1];
  71. }
  72. var marker = svgCreate('marker');
  73. svgAttr(options.element, attrs);
  74. svgAppend(marker, options.element);
  75. svgAttr(marker, {
  76. id: id,
  77. viewBox: '0 0 20 20',
  78. refX: ref.x,
  79. refY: ref.y,
  80. markerWidth: 20 * scale,
  81. markerHeight: 20 * scale,
  82. orient: 'auto'
  83. });
  84. var defs = domQuery('defs', canvas._svg);
  85. if (!defs) {
  86. defs = svgCreate('defs');
  87. svgAppend(canvas._svg, defs);
  88. }
  89. svgAppend(defs, marker);
  90. markers[id] = marker;
  91. }
  92. function colorEscape(str) {
  93. return str.replace(/[()\s,#]+/g, '_');
  94. }
  95. function marker(type, fill, stroke) {
  96. var id = type + '-' + colorEscape(fill) + '-' + colorEscape(stroke) + '-' + rendererId;
  97. if (!markers[id]) {
  98. createMarker(id, type, fill, stroke);
  99. }
  100. return 'url(#' + id + ')';
  101. }
  102. function createMarker(id, type, fill, stroke) {
  103. if (type === 'sequenceflow-end') {
  104. var sequenceflowEnd = svgCreate('path');
  105. svgAttr(sequenceflowEnd, { d: 'M 1 5 L 11 10 L 1 15 Z' });
  106. addMarker(id, {
  107. element: sequenceflowEnd,
  108. ref: { x: 11, y: 10 },
  109. scale: 0.5,
  110. attrs: {
  111. fill: stroke,
  112. stroke: stroke
  113. }
  114. });
  115. }
  116. if (type === 'messageflow-start') {
  117. var messageflowStart = svgCreate('circle');
  118. svgAttr(messageflowStart, { cx: 6, cy: 6, r: 3.5 });
  119. addMarker(id, {
  120. element: messageflowStart,
  121. attrs: {
  122. fill: fill,
  123. stroke: stroke
  124. },
  125. ref: { x: 6, y: 6 }
  126. });
  127. }
  128. if (type === 'messageflow-end') {
  129. var messageflowEnd = svgCreate('path');
  130. svgAttr(messageflowEnd, { d: 'm 1 5 l 0 -3 l 7 3 l -7 3 z' });
  131. addMarker(id, {
  132. element: messageflowEnd,
  133. attrs: {
  134. fill: fill,
  135. stroke: stroke,
  136. strokeLinecap: 'butt'
  137. },
  138. ref: { x: 8.5, y: 5 }
  139. });
  140. }
  141. if (type === 'association-start') {
  142. var associationStart = svgCreate('path');
  143. svgAttr(associationStart, { d: 'M 11 5 L 1 10 L 11 15' });
  144. addMarker(id, {
  145. element: associationStart,
  146. attrs: {
  147. fill: 'none',
  148. stroke: stroke,
  149. strokeWidth: 1.5
  150. },
  151. ref: { x: 1, y: 10 },
  152. scale: 0.5
  153. });
  154. }
  155. if (type === 'association-end') {
  156. var associationEnd = svgCreate('path');
  157. svgAttr(associationEnd, { d: 'M 1 5 L 11 10 L 1 15' });
  158. addMarker(id, {
  159. element: associationEnd,
  160. attrs: {
  161. fill: 'none',
  162. stroke: stroke,
  163. strokeWidth: 1.5
  164. },
  165. ref: { x: 12, y: 10 },
  166. scale: 0.5
  167. });
  168. }
  169. if (type === 'conditional-flow-marker') {
  170. var conditionalflowMarker = svgCreate('path');
  171. svgAttr(conditionalflowMarker, { d: 'M 0 10 L 8 6 L 16 10 L 8 14 Z' });
  172. addMarker(id, {
  173. element: conditionalflowMarker,
  174. attrs: {
  175. fill: fill,
  176. stroke: stroke
  177. },
  178. ref: { x: -1, y: 10 },
  179. scale: 0.5
  180. });
  181. }
  182. if (type === 'conditional-default-flow-marker') {
  183. var conditionaldefaultflowMarker = svgCreate('path');
  184. svgAttr(conditionaldefaultflowMarker, { d: 'M 6 4 L 10 16' });
  185. addMarker(id, {
  186. element: conditionaldefaultflowMarker,
  187. attrs: {
  188. stroke: stroke
  189. },
  190. ref: { x: 0, y: 10 },
  191. scale: 0.5
  192. });
  193. }
  194. }
  195. function drawCircle(parentGfx, width, height, offset, attrs) {
  196. if (isObject(offset)) {
  197. attrs = offset;
  198. offset = 0;
  199. }
  200. offset = offset || 0;
  201. attrs = computeStyle(attrs, {
  202. stroke: 'black',
  203. strokeWidth: 2,
  204. fill: 'white'
  205. });
  206. if (attrs.fill === 'none') {
  207. delete attrs.fillOpacity;
  208. }
  209. var cx = width / 2,
  210. cy = height / 2;
  211. var circle = svgCreate('circle');
  212. svgAttr(circle, {
  213. cx: cx,
  214. cy: cy,
  215. r: Math.round((width + height) / 4 - offset)
  216. });
  217. svgAttr(circle, attrs);
  218. svgAppend(parentGfx, circle);
  219. return circle;
  220. }
  221. function drawRect(parentGfx, width, height, r, offset, attrs) {
  222. if (isObject(offset)) {
  223. attrs = offset;
  224. offset = 0;
  225. }
  226. offset = offset || 0;
  227. attrs = computeStyle(attrs, {
  228. stroke: 'black',
  229. strokeWidth: 2,
  230. fill: 'white'
  231. });
  232. var rect = svgCreate('rect');
  233. svgAttr(rect, {
  234. x: offset,
  235. y: offset,
  236. width: width - offset * 2,
  237. height: height - offset * 2,
  238. rx: r,
  239. ry: r
  240. });
  241. svgAttr(rect, attrs);
  242. svgAppend(parentGfx, rect);
  243. return rect;
  244. }
  245. function drawDiamond(parentGfx, width, height, attrs) {
  246. var x_2 = width / 2;
  247. var y_2 = height / 2;
  248. var points = [{ x: x_2, y: 0 }, { x: width, y: y_2 }, { x: x_2, y: height }, { x: 0, y: y_2 }];
  249. var pointsString = points.map(function(point) {
  250. return point.x + ',' + point.y;
  251. }).join(' ');
  252. attrs = computeStyle(attrs, {
  253. stroke: 'black',
  254. strokeWidth: 2,
  255. fill: 'white'
  256. });
  257. var polygon = svgCreate('polygon');
  258. svgAttr(polygon, {
  259. points: pointsString
  260. });
  261. svgAttr(polygon, attrs);
  262. svgAppend(parentGfx, polygon);
  263. return polygon;
  264. }
  265. function drawLine(parentGfx, waypoints, attrs) {
  266. attrs = computeStyle(attrs, [ 'no-fill' ], {
  267. stroke: 'black',
  268. strokeWidth: 2,
  269. fill: 'none'
  270. });
  271. var line = createLine(waypoints, attrs);
  272. svgAppend(parentGfx, line);
  273. return line;
  274. }
  275. function drawPath(parentGfx, d, attrs) {
  276. attrs = computeStyle(attrs, [ 'no-fill' ], {
  277. strokeWidth: 2,
  278. stroke: 'black'
  279. });
  280. var path = svgCreate('path');
  281. svgAttr(path, { d: d });
  282. svgAttr(path, attrs);
  283. svgAppend(parentGfx, path);
  284. return path;
  285. }
  286. function drawMarker(type, parentGfx, path, attrs) {
  287. return drawPath(parentGfx, path, assign({ 'data-marker': type }, attrs));
  288. }
  289. function as(type) {
  290. return function(parentGfx, element) {
  291. return handlers[type](parentGfx, element);
  292. };
  293. }
  294. function renderer(type) {
  295. return handlers[type];
  296. }
  297. function renderEventContent(element, parentGfx) {
  298. var event = getSemantic(element);
  299. var isThrowing = isThrowEvent(event);
  300. if (isTypedEvent(event, 'bpmn:MessageEventDefinition')) {
  301. return renderer('bpmn:MessageEventDefinition')(parentGfx, element, isThrowing);
  302. }
  303. if (isTypedEvent(event, 'bpmn:TimerEventDefinition')) {
  304. return renderer('bpmn:TimerEventDefinition')(parentGfx, element, isThrowing);
  305. }
  306. if (isTypedEvent(event, 'bpmn:ConditionalEventDefinition')) {
  307. return renderer('bpmn:ConditionalEventDefinition')(parentGfx, element);
  308. }
  309. if (isTypedEvent(event, 'bpmn:SignalEventDefinition')) {
  310. return renderer('bpmn:SignalEventDefinition')(parentGfx, element, isThrowing);
  311. }
  312. if (isTypedEvent(event, 'bpmn:CancelEventDefinition') &&
  313. isTypedEvent(event, 'bpmn:TerminateEventDefinition', { parallelMultiple: false })) {
  314. return renderer('bpmn:MultipleEventDefinition')(parentGfx, element, isThrowing);
  315. }
  316. if (isTypedEvent(event, 'bpmn:CancelEventDefinition') &&
  317. isTypedEvent(event, 'bpmn:TerminateEventDefinition', { parallelMultiple: true })) {
  318. return renderer('bpmn:ParallelMultipleEventDefinition')(parentGfx, element, isThrowing);
  319. }
  320. if (isTypedEvent(event, 'bpmn:EscalationEventDefinition')) {
  321. return renderer('bpmn:EscalationEventDefinition')(parentGfx, element, isThrowing);
  322. }
  323. if (isTypedEvent(event, 'bpmn:LinkEventDefinition')) {
  324. return renderer('bpmn:LinkEventDefinition')(parentGfx, element, isThrowing);
  325. }
  326. if (isTypedEvent(event, 'bpmn:ErrorEventDefinition')) {
  327. return renderer('bpmn:ErrorEventDefinition')(parentGfx, element, isThrowing);
  328. }
  329. if (isTypedEvent(event, 'bpmn:CancelEventDefinition')) {
  330. return renderer('bpmn:CancelEventDefinition')(parentGfx, element, isThrowing);
  331. }
  332. if (isTypedEvent(event, 'bpmn:CompensateEventDefinition')) {
  333. return renderer('bpmn:CompensateEventDefinition')(parentGfx, element, isThrowing);
  334. }
  335. if (isTypedEvent(event, 'bpmn:TerminateEventDefinition')) {
  336. return renderer('bpmn:TerminateEventDefinition')(parentGfx, element, isThrowing);
  337. }
  338. return null;
  339. }
  340. function renderLabel(parentGfx, label, options) {
  341. options = assign({
  342. size: {
  343. width: 100
  344. }
  345. }, options);
  346. var text = textRenderer.createText(label || '', options);
  347. svgClasses(text).add('djs-label');
  348. svgAppend(parentGfx, text);
  349. return text;
  350. }
  351. function renderEmbeddedLabel(parentGfx, element, align) {
  352. var semantic = getSemantic(element);
  353. return renderLabel(parentGfx, semantic.name, {
  354. box: element,
  355. align: align,
  356. padding: 5,
  357. style: {
  358. fill: getStrokeColor(element, defaultStrokeColor)
  359. }
  360. });
  361. }
  362. function renderExternalLabel(parentGfx, element) {
  363. var semantic = getSemantic(element);
  364. var box = {
  365. width: 90,
  366. height: 30,
  367. x: element.width / 2 + element.x,
  368. y: element.height / 2 + element.y
  369. };
  370. return renderLabel(parentGfx, semantic.name, {
  371. box: box,
  372. fitBox: true,
  373. style: assign(
  374. {},
  375. textRenderer.getExternalStyle(),
  376. {
  377. fill: getStrokeColor(element, defaultStrokeColor)
  378. }
  379. )
  380. });
  381. }
  382. function renderLaneLabel(parentGfx, text, element) {
  383. var textBox = renderLabel(parentGfx, text, {
  384. box: {
  385. height: 30,
  386. width: element.height
  387. },
  388. align: 'center-middle',
  389. style: {
  390. fill: getStrokeColor(element, defaultStrokeColor)
  391. }
  392. });
  393. var top = -1 * element.height;
  394. transform(textBox, 0, -top, 270);
  395. }
  396. function createPathFromConnection(connection) {
  397. var waypoints = connection.waypoints;
  398. var pathData = 'm ' + waypoints[0].x + ',' + waypoints[0].y;
  399. for (var i = 1; i < waypoints.length; i++) {
  400. pathData += 'L' + waypoints[i].x + ',' + waypoints[i].y + ' ';
  401. }
  402. return pathData;
  403. }
  404. var handlers = this.handlers = {
  405. 'bpmn:Event': function(parentGfx, element, attrs) {
  406. if (!('fillOpacity' in attrs)) {
  407. attrs.fillOpacity = DEFAULT_FILL_OPACITY;
  408. }
  409. return drawCircle(parentGfx, element.width, element.height, attrs);
  410. },
  411. 'bpmn:StartEvent': function(parentGfx, element) {
  412. var attrs = {
  413. fill: getFillColor(element, defaultFillColor),
  414. stroke: getStrokeColor(element, defaultStrokeColor)
  415. };
  416. var semantic = getSemantic(element);
  417. if (!semantic.isInterrupting) {
  418. attrs = {
  419. strokeDasharray: '6',
  420. strokeLinecap: 'round',
  421. fill: getFillColor(element, defaultFillColor),
  422. stroke: getStrokeColor(element, defaultStrokeColor)
  423. };
  424. }
  425. var circle = renderer('bpmn:Event')(parentGfx, element, attrs);
  426. renderEventContent(element, parentGfx);
  427. return circle;
  428. },
  429. 'bpmn:MessageEventDefinition': function(parentGfx, element, isThrowing) {
  430. var pathData = pathMap.getScaledPath('EVENT_MESSAGE', {
  431. xScaleFactor: 0.9,
  432. yScaleFactor: 0.9,
  433. containerWidth: element.width,
  434. containerHeight: element.height,
  435. position: {
  436. mx: 0.235,
  437. my: 0.315
  438. }
  439. });
  440. var fill = isThrowing ? getStrokeColor(element, defaultStrokeColor) : getFillColor(element, defaultFillColor);
  441. var stroke = isThrowing ? getFillColor(element, defaultFillColor) : getStrokeColor(element, defaultStrokeColor);
  442. var messagePath = drawPath(parentGfx, pathData, {
  443. strokeWidth: 1,
  444. fill: fill,
  445. stroke: stroke
  446. });
  447. return messagePath;
  448. },
  449. 'bpmn:TimerEventDefinition': function(parentGfx, element) {
  450. var circle = drawCircle(parentGfx, element.width, element.height, 0.2 * element.height, {
  451. strokeWidth: 2,
  452. fill: getFillColor(element, defaultFillColor),
  453. stroke: getStrokeColor(element, defaultStrokeColor)
  454. });
  455. var pathData = pathMap.getScaledPath('EVENT_TIMER_WH', {
  456. xScaleFactor: 0.75,
  457. yScaleFactor: 0.75,
  458. containerWidth: element.width,
  459. containerHeight: element.height,
  460. position: {
  461. mx: 0.5,
  462. my: 0.5
  463. }
  464. });
  465. drawPath(parentGfx, pathData, {
  466. strokeWidth: 2,
  467. strokeLinecap: 'square',
  468. stroke: getStrokeColor(element, defaultStrokeColor)
  469. });
  470. for (var i = 0;i < 12; i++) {
  471. var linePathData = pathMap.getScaledPath('EVENT_TIMER_LINE', {
  472. xScaleFactor: 0.75,
  473. yScaleFactor: 0.75,
  474. containerWidth: element.width,
  475. containerHeight: element.height,
  476. position: {
  477. mx: 0.5,
  478. my: 0.5
  479. }
  480. });
  481. var width = element.width / 2;
  482. var height = element.height / 2;
  483. drawPath(parentGfx, linePathData, {
  484. strokeWidth: 1,
  485. strokeLinecap: 'square',
  486. transform: 'rotate(' + (i * 30) + ',' + height + ',' + width + ')',
  487. stroke: getStrokeColor(element, defaultStrokeColor)
  488. });
  489. }
  490. return circle;
  491. },
  492. 'bpmn:EscalationEventDefinition': function(parentGfx, event, isThrowing) {
  493. var pathData = pathMap.getScaledPath('EVENT_ESCALATION', {
  494. xScaleFactor: 1,
  495. yScaleFactor: 1,
  496. containerWidth: event.width,
  497. containerHeight: event.height,
  498. position: {
  499. mx: 0.5,
  500. my: 0.2
  501. }
  502. });
  503. var fill = isThrowing ? getStrokeColor(event, defaultStrokeColor) : 'none';
  504. return drawPath(parentGfx, pathData, {
  505. strokeWidth: 1,
  506. fill: fill,
  507. stroke: getStrokeColor(event, defaultStrokeColor)
  508. });
  509. },
  510. 'bpmn:ConditionalEventDefinition': function(parentGfx, event) {
  511. var pathData = pathMap.getScaledPath('EVENT_CONDITIONAL', {
  512. xScaleFactor: 1,
  513. yScaleFactor: 1,
  514. containerWidth: event.width,
  515. containerHeight: event.height,
  516. position: {
  517. mx: 0.5,
  518. my: 0.222
  519. }
  520. });
  521. return drawPath(parentGfx, pathData, {
  522. strokeWidth: 1,
  523. stroke: getStrokeColor(event, defaultStrokeColor)
  524. });
  525. },
  526. 'bpmn:LinkEventDefinition': function(parentGfx, event, isThrowing) {
  527. var pathData = pathMap.getScaledPath('EVENT_LINK', {
  528. xScaleFactor: 1,
  529. yScaleFactor: 1,
  530. containerWidth: event.width,
  531. containerHeight: event.height,
  532. position: {
  533. mx: 0.57,
  534. my: 0.263
  535. }
  536. });
  537. var fill = isThrowing ? getStrokeColor(event, defaultStrokeColor) : 'none';
  538. return drawPath(parentGfx, pathData, {
  539. strokeWidth: 1,
  540. fill: fill,
  541. stroke: getStrokeColor(event, defaultStrokeColor)
  542. });
  543. },
  544. 'bpmn:ErrorEventDefinition': function(parentGfx, event, isThrowing) {
  545. var pathData = pathMap.getScaledPath('EVENT_ERROR', {
  546. xScaleFactor: 1.1,
  547. yScaleFactor: 1.1,
  548. containerWidth: event.width,
  549. containerHeight: event.height,
  550. position: {
  551. mx: 0.2,
  552. my: 0.722
  553. }
  554. });
  555. var fill = isThrowing ? getStrokeColor(event, defaultStrokeColor) : 'none';
  556. return drawPath(parentGfx, pathData, {
  557. strokeWidth: 1,
  558. fill: fill,
  559. stroke: getStrokeColor(event, defaultStrokeColor)
  560. });
  561. },
  562. 'bpmn:CancelEventDefinition': function(parentGfx, event, isThrowing) {
  563. var pathData = pathMap.getScaledPath('EVENT_CANCEL_45', {
  564. xScaleFactor: 1.0,
  565. yScaleFactor: 1.0,
  566. containerWidth: event.width,
  567. containerHeight: event.height,
  568. position: {
  569. mx: 0.638,
  570. my: -0.055
  571. }
  572. });
  573. var fill = isThrowing ? getStrokeColor(event, defaultStrokeColor) : 'none';
  574. var path = drawPath(parentGfx, pathData, {
  575. strokeWidth: 1,
  576. fill: fill,
  577. stroke: getStrokeColor(event, defaultStrokeColor)
  578. });
  579. rotate(path, 45);
  580. return path;
  581. },
  582. 'bpmn:CompensateEventDefinition': function(parentGfx, event, isThrowing) {
  583. var pathData = pathMap.getScaledPath('EVENT_COMPENSATION', {
  584. xScaleFactor: 1,
  585. yScaleFactor: 1,
  586. containerWidth: event.width,
  587. containerHeight: event.height,
  588. position: {
  589. mx: 0.22,
  590. my: 0.5
  591. }
  592. });
  593. var fill = isThrowing ? getStrokeColor(event, defaultStrokeColor) : 'none';
  594. return drawPath(parentGfx, pathData, {
  595. strokeWidth: 1,
  596. fill: fill,
  597. stroke: getStrokeColor(event, defaultStrokeColor)
  598. });
  599. },
  600. 'bpmn:SignalEventDefinition': function(parentGfx, event, isThrowing) {
  601. var pathData = pathMap.getScaledPath('EVENT_SIGNAL', {
  602. xScaleFactor: 0.9,
  603. yScaleFactor: 0.9,
  604. containerWidth: event.width,
  605. containerHeight: event.height,
  606. position: {
  607. mx: 0.5,
  608. my: 0.2
  609. }
  610. });
  611. var fill = isThrowing ? getStrokeColor(event, defaultStrokeColor) : 'none';
  612. return drawPath(parentGfx, pathData, {
  613. strokeWidth: 1,
  614. fill: fill,
  615. stroke: getStrokeColor(event, defaultStrokeColor)
  616. });
  617. },
  618. 'bpmn:MultipleEventDefinition': function(parentGfx, event, isThrowing) {
  619. var pathData = pathMap.getScaledPath('EVENT_MULTIPLE', {
  620. xScaleFactor: 1.1,
  621. yScaleFactor: 1.1,
  622. containerWidth: event.width,
  623. containerHeight: event.height,
  624. position: {
  625. mx: 0.222,
  626. my: 0.36
  627. }
  628. });
  629. var fill = isThrowing ? getStrokeColor(event, defaultStrokeColor) : 'none';
  630. return drawPath(parentGfx, pathData, {
  631. strokeWidth: 1,
  632. fill: fill
  633. });
  634. },
  635. 'bpmn:ParallelMultipleEventDefinition': function(parentGfx, event) {
  636. var pathData = pathMap.getScaledPath('EVENT_PARALLEL_MULTIPLE', {
  637. xScaleFactor: 1.2,
  638. yScaleFactor: 1.2,
  639. containerWidth: event.width,
  640. containerHeight: event.height,
  641. position: {
  642. mx: 0.458,
  643. my: 0.194
  644. }
  645. });
  646. return drawPath(parentGfx, pathData, {
  647. strokeWidth: 1,
  648. fill: getStrokeColor(event, defaultStrokeColor),
  649. stroke: getStrokeColor(event, defaultStrokeColor)
  650. });
  651. },
  652. 'bpmn:EndEvent': function(parentGfx, element) {
  653. var circle = renderer('bpmn:Event')(parentGfx, element, {
  654. strokeWidth: 4,
  655. fill: getFillColor(element, defaultFillColor),
  656. stroke: getStrokeColor(element, defaultStrokeColor)
  657. });
  658. renderEventContent(element, parentGfx, true);
  659. return circle;
  660. },
  661. 'bpmn:TerminateEventDefinition': function(parentGfx, element) {
  662. var circle = drawCircle(parentGfx, element.width, element.height, 8, {
  663. strokeWidth: 4,
  664. fill: getStrokeColor(element, defaultStrokeColor),
  665. stroke: getStrokeColor(element, defaultStrokeColor)
  666. });
  667. return circle;
  668. },
  669. 'bpmn:IntermediateEvent': function(parentGfx, element) {
  670. var outer = renderer('bpmn:Event')(parentGfx, element, {
  671. strokeWidth: 1,
  672. fill: getFillColor(element, defaultFillColor),
  673. stroke: getStrokeColor(element, defaultStrokeColor)
  674. });
  675. /* inner */
  676. drawCircle(parentGfx, element.width, element.height, INNER_OUTER_DIST, {
  677. strokeWidth: 1,
  678. fill: getFillColor(element, 'none'),
  679. stroke: getStrokeColor(element, defaultStrokeColor)
  680. });
  681. renderEventContent(element, parentGfx);
  682. return outer;
  683. },
  684. 'bpmn:IntermediateCatchEvent': as('bpmn:IntermediateEvent'),
  685. 'bpmn:IntermediateThrowEvent': as('bpmn:IntermediateEvent'),
  686. 'bpmn:Activity': function(parentGfx, element, attrs) {
  687. attrs = attrs || {};
  688. if (!('fillOpacity' in attrs)) {
  689. attrs.fillOpacity = DEFAULT_FILL_OPACITY;
  690. }
  691. return drawRect(parentGfx, element.width, element.height, TASK_BORDER_RADIUS, attrs);
  692. },
  693. 'bpmn:Task': function(parentGfx, element) {
  694. var attrs = {
  695. fill: getFillColor(element, defaultFillColor),
  696. stroke: getStrokeColor(element, defaultStrokeColor)
  697. };
  698. var rect = renderer('bpmn:Activity')(parentGfx, element, attrs);
  699. renderEmbeddedLabel(parentGfx, element, 'center-middle');
  700. attachTaskMarkers(parentGfx, element);
  701. return rect;
  702. },
  703. 'bpmn:ServiceTask': function(parentGfx, element) {
  704. var task = renderer('bpmn:Task')(parentGfx, element);
  705. var pathDataBG = pathMap.getScaledPath('TASK_TYPE_SERVICE', {
  706. abspos: {
  707. x: 12,
  708. y: 18
  709. }
  710. });
  711. /* service bg */ drawPath(parentGfx, pathDataBG, {
  712. strokeWidth: 1,
  713. fill: getFillColor(element, defaultFillColor),
  714. stroke: getStrokeColor(element, defaultStrokeColor)
  715. });
  716. var fillPathData = pathMap.getScaledPath('TASK_TYPE_SERVICE_FILL', {
  717. abspos: {
  718. x: 17.2,
  719. y: 18
  720. }
  721. });
  722. /* service fill */ drawPath(parentGfx, fillPathData, {
  723. strokeWidth: 0,
  724. fill: getFillColor(element, defaultFillColor)
  725. });
  726. var pathData = pathMap.getScaledPath('TASK_TYPE_SERVICE', {
  727. abspos: {
  728. x: 17,
  729. y: 22
  730. }
  731. });
  732. /* service */ drawPath(parentGfx, pathData, {
  733. strokeWidth: 1,
  734. fill: getFillColor(element, defaultFillColor),
  735. stroke: getStrokeColor(element, defaultStrokeColor)
  736. });
  737. return task;
  738. },
  739. 'bpmn:UserTask': function(parentGfx, element) {
  740. var task = renderer('bpmn:Task')(parentGfx, element);
  741. var x = 15;
  742. var y = 12;
  743. var pathData = pathMap.getScaledPath('TASK_TYPE_USER_1', {
  744. abspos: {
  745. x: x,
  746. y: y
  747. }
  748. });
  749. /* user path */ drawPath(parentGfx, pathData, {
  750. strokeWidth: 0.5,
  751. fill: getFillColor(element, defaultFillColor),
  752. stroke: getStrokeColor(element, defaultStrokeColor)
  753. });
  754. var pathData2 = pathMap.getScaledPath('TASK_TYPE_USER_2', {
  755. abspos: {
  756. x: x,
  757. y: y
  758. }
  759. });
  760. /* user2 path */ drawPath(parentGfx, pathData2, {
  761. strokeWidth: 0.5,
  762. fill: getFillColor(element, defaultFillColor),
  763. stroke: getStrokeColor(element, defaultStrokeColor)
  764. });
  765. var pathData3 = pathMap.getScaledPath('TASK_TYPE_USER_3', {
  766. abspos: {
  767. x: x,
  768. y: y
  769. }
  770. });
  771. /* user3 path */ drawPath(parentGfx, pathData3, {
  772. strokeWidth: 0.5,
  773. fill: getStrokeColor(element, defaultStrokeColor),
  774. stroke: getStrokeColor(element, defaultStrokeColor)
  775. });
  776. return task;
  777. },
  778. 'bpmn:ManualTask': function(parentGfx, element) {
  779. var task = renderer('bpmn:Task')(parentGfx, element);
  780. var pathData = pathMap.getScaledPath('TASK_TYPE_MANUAL', {
  781. abspos: {
  782. x: 17,
  783. y: 15
  784. }
  785. });
  786. /* manual path */ drawPath(parentGfx, pathData, {
  787. strokeWidth: 0.5, // 0.25,
  788. fill: getFillColor(element, defaultFillColor),
  789. stroke: getStrokeColor(element, defaultStrokeColor)
  790. });
  791. return task;
  792. },
  793. 'bpmn:SendTask': function(parentGfx, element) {
  794. var task = renderer('bpmn:Task')(parentGfx, element);
  795. var pathData = pathMap.getScaledPath('TASK_TYPE_SEND', {
  796. xScaleFactor: 1,
  797. yScaleFactor: 1,
  798. containerWidth: 21,
  799. containerHeight: 14,
  800. position: {
  801. mx: 0.285,
  802. my: 0.357
  803. }
  804. });
  805. /* send path */ drawPath(parentGfx, pathData, {
  806. strokeWidth: 1,
  807. fill: getStrokeColor(element, defaultStrokeColor),
  808. stroke: getFillColor(element, defaultFillColor)
  809. });
  810. return task;
  811. },
  812. 'bpmn:ReceiveTask' : function(parentGfx, element) {
  813. var semantic = getSemantic(element);
  814. var task = renderer('bpmn:Task')(parentGfx, element);
  815. var pathData;
  816. if (semantic.instantiate) {
  817. drawCircle(parentGfx, 28, 28, 20 * 0.22, { strokeWidth: 1 });
  818. pathData = pathMap.getScaledPath('TASK_TYPE_INSTANTIATING_SEND', {
  819. abspos: {
  820. x: 7.77,
  821. y: 9.52
  822. }
  823. });
  824. } else {
  825. pathData = pathMap.getScaledPath('TASK_TYPE_SEND', {
  826. xScaleFactor: 0.9,
  827. yScaleFactor: 0.9,
  828. containerWidth: 21,
  829. containerHeight: 14,
  830. position: {
  831. mx: 0.3,
  832. my: 0.4
  833. }
  834. });
  835. }
  836. /* receive path */ drawPath(parentGfx, pathData, {
  837. strokeWidth: 1,
  838. fill: getFillColor(element, defaultFillColor),
  839. stroke: getStrokeColor(element, defaultStrokeColor)
  840. });
  841. return task;
  842. },
  843. 'bpmn:ScriptTask': function(parentGfx, element) {
  844. var task = renderer('bpmn:Task')(parentGfx, element);
  845. var pathData = pathMap.getScaledPath('TASK_TYPE_SCRIPT', {
  846. abspos: {
  847. x: 15,
  848. y: 20
  849. }
  850. });
  851. /* script path */ drawPath(parentGfx, pathData, {
  852. strokeWidth: 1,
  853. stroke: getStrokeColor(element, defaultStrokeColor)
  854. });
  855. return task;
  856. },
  857. 'bpmn:BusinessRuleTask': function(parentGfx, element) {
  858. var task = renderer('bpmn:Task')(parentGfx, element);
  859. var headerPathData = pathMap.getScaledPath('TASK_TYPE_BUSINESS_RULE_HEADER', {
  860. abspos: {
  861. x: 8,
  862. y: 8
  863. }
  864. });
  865. var businessHeaderPath = drawPath(parentGfx, headerPathData);
  866. svgAttr(businessHeaderPath, {
  867. strokeWidth: 1,
  868. fill: getFillColor(element, '#aaaaaa'),
  869. stroke: getStrokeColor(element, defaultStrokeColor)
  870. });
  871. var headerData = pathMap.getScaledPath('TASK_TYPE_BUSINESS_RULE_MAIN', {
  872. abspos: {
  873. x: 8,
  874. y: 8
  875. }
  876. });
  877. var businessPath = drawPath(parentGfx, headerData);
  878. svgAttr(businessPath, {
  879. strokeWidth: 1,
  880. stroke: getStrokeColor(element, defaultStrokeColor)
  881. });
  882. return task;
  883. },
  884. 'bpmn:SubProcess': function(parentGfx, element, attrs) {
  885. attrs = assign({
  886. fill: getFillColor(element, defaultFillColor),
  887. stroke: getStrokeColor(element, defaultStrokeColor)
  888. }, attrs);
  889. var rect = renderer('bpmn:Activity')(parentGfx, element, attrs);
  890. var expanded = isExpanded(element);
  891. if (isEventSubProcess(element)) {
  892. svgAttr(rect, {
  893. strokeDasharray: '1,2'
  894. });
  895. }
  896. renderEmbeddedLabel(parentGfx, element, expanded ? 'center-top' : 'center-middle');
  897. if (expanded) {
  898. attachTaskMarkers(parentGfx, element);
  899. } else {
  900. attachTaskMarkers(parentGfx, element, ['SubProcessMarker']);
  901. }
  902. return rect;
  903. },
  904. 'bpmn:AdHocSubProcess': function(parentGfx, element) {
  905. return renderer('bpmn:SubProcess')(parentGfx, element);
  906. },
  907. 'bpmn:Transaction': function(parentGfx, element) {
  908. var outer = renderer('bpmn:SubProcess')(parentGfx, element);
  909. var innerAttrs = styles.style([ 'no-fill', 'no-events' ], {
  910. stroke: getStrokeColor(element, defaultStrokeColor)
  911. });
  912. /* inner path */ drawRect(parentGfx, element.width, element.height, TASK_BORDER_RADIUS - 2, INNER_OUTER_DIST, innerAttrs);
  913. return outer;
  914. },
  915. 'bpmn:CallActivity': function(parentGfx, element) {
  916. return renderer('bpmn:SubProcess')(parentGfx, element, {
  917. strokeWidth: 5
  918. });
  919. },
  920. 'bpmn:Participant': function(parentGfx, element) {
  921. var attrs = {
  922. fillOpacity: DEFAULT_FILL_OPACITY,
  923. fill: getFillColor(element, defaultFillColor),
  924. stroke: getStrokeColor(element, defaultStrokeColor)
  925. };
  926. var lane = renderer('bpmn:Lane')(parentGfx, element, attrs);
  927. var expandedPool = isExpanded(element);
  928. if (expandedPool) {
  929. drawLine(parentGfx, [
  930. { x: 30, y: 0 },
  931. { x: 30, y: element.height }
  932. ], {
  933. stroke: getStrokeColor(element, defaultStrokeColor)
  934. });
  935. var text = getSemantic(element).name;
  936. renderLaneLabel(parentGfx, text, element);
  937. } else {
  938. // Collapsed pool draw text inline
  939. var text2 = getSemantic(element).name;
  940. renderLabel(parentGfx, text2, {
  941. box: element, align: 'center-middle',
  942. style: {
  943. fill: getStrokeColor(element, defaultStrokeColor)
  944. }
  945. });
  946. }
  947. var participantMultiplicity = !!(getSemantic(element).participantMultiplicity);
  948. if (participantMultiplicity) {
  949. renderer('ParticipantMultiplicityMarker')(parentGfx, element);
  950. }
  951. return lane;
  952. },
  953. 'bpmn:Lane': function(parentGfx, element, attrs) {
  954. var rect = drawRect(parentGfx, element.width, element.height, 0, assign({
  955. fill: getFillColor(element, defaultFillColor),
  956. fillOpacity: HIGH_FILL_OPACITY,
  957. stroke: getStrokeColor(element, defaultStrokeColor)
  958. }, attrs));
  959. var semantic = getSemantic(element);
  960. if (semantic.$type === 'bpmn:Lane') {
  961. var text = semantic.name;
  962. renderLaneLabel(parentGfx, text, element);
  963. }
  964. return rect;
  965. },
  966. 'bpmn:InclusiveGateway': function(parentGfx, element) {
  967. var diamond = renderer('bpmn:Gateway')(parentGfx, element);
  968. /* circle path */
  969. drawCircle(parentGfx, element.width, element.height, element.height * 0.24, {
  970. strokeWidth: 2.5,
  971. fill: getFillColor(element, defaultFillColor),
  972. stroke: getStrokeColor(element, defaultStrokeColor)
  973. });
  974. return diamond;
  975. },
  976. 'bpmn:ExclusiveGateway': function(parentGfx, element) {
  977. var diamond = renderer('bpmn:Gateway')(parentGfx, element);
  978. var pathData = pathMap.getScaledPath('GATEWAY_EXCLUSIVE', {
  979. xScaleFactor: 0.4,
  980. yScaleFactor: 0.4,
  981. containerWidth: element.width,
  982. containerHeight: element.height,
  983. position: {
  984. mx: 0.32,
  985. my: 0.3
  986. }
  987. });
  988. if ((getDi(element).isMarkerVisible)) {
  989. drawPath(parentGfx, pathData, {
  990. strokeWidth: 1,
  991. fill: getStrokeColor(element, defaultStrokeColor),
  992. stroke: getStrokeColor(element, defaultStrokeColor)
  993. });
  994. }
  995. return diamond;
  996. },
  997. 'bpmn:ComplexGateway': function(parentGfx, element) {
  998. var diamond = renderer('bpmn:Gateway')(parentGfx, element);
  999. var pathData = pathMap.getScaledPath('GATEWAY_COMPLEX', {
  1000. xScaleFactor: 0.5,
  1001. yScaleFactor:0.5,
  1002. containerWidth: element.width,
  1003. containerHeight: element.height,
  1004. position: {
  1005. mx: 0.46,
  1006. my: 0.26
  1007. }
  1008. });
  1009. /* complex path */ drawPath(parentGfx, pathData, {
  1010. strokeWidth: 1,
  1011. fill: getStrokeColor(element, defaultStrokeColor),
  1012. stroke: getStrokeColor(element, defaultStrokeColor)
  1013. });
  1014. return diamond;
  1015. },
  1016. 'bpmn:ParallelGateway': function(parentGfx, element) {
  1017. var diamond = renderer('bpmn:Gateway')(parentGfx, element);
  1018. var pathData = pathMap.getScaledPath('GATEWAY_PARALLEL', {
  1019. xScaleFactor: 0.6,
  1020. yScaleFactor:0.6,
  1021. containerWidth: element.width,
  1022. containerHeight: element.height,
  1023. position: {
  1024. mx: 0.46,
  1025. my: 0.2
  1026. }
  1027. });
  1028. /* parallel path */ drawPath(parentGfx, pathData, {
  1029. strokeWidth: 1,
  1030. fill: getStrokeColor(element, defaultStrokeColor),
  1031. stroke: getStrokeColor(element, defaultStrokeColor)
  1032. });
  1033. return diamond;
  1034. },
  1035. 'bpmn:EventBasedGateway': function(parentGfx, element) {
  1036. var semantic = getSemantic(element);
  1037. var diamond = renderer('bpmn:Gateway')(parentGfx, element);
  1038. /* outer circle path */ drawCircle(parentGfx, element.width, element.height, element.height * 0.20, {
  1039. strokeWidth: 1,
  1040. fill: 'none',
  1041. stroke: getStrokeColor(element, defaultStrokeColor)
  1042. });
  1043. var type = semantic.eventGatewayType;
  1044. var instantiate = !!semantic.instantiate;
  1045. function drawEvent() {
  1046. var pathData = pathMap.getScaledPath('GATEWAY_EVENT_BASED', {
  1047. xScaleFactor: 0.18,
  1048. yScaleFactor: 0.18,
  1049. containerWidth: element.width,
  1050. containerHeight: element.height,
  1051. position: {
  1052. mx: 0.36,
  1053. my: 0.44
  1054. }
  1055. });
  1056. var attrs = {
  1057. strokeWidth: 2,
  1058. fill: getFillColor(element, 'none'),
  1059. stroke: getStrokeColor(element, defaultStrokeColor)
  1060. };
  1061. /* event path */ drawPath(parentGfx, pathData, attrs);
  1062. }
  1063. if (type === 'Parallel') {
  1064. var pathData = pathMap.getScaledPath('GATEWAY_PARALLEL', {
  1065. xScaleFactor: 0.4,
  1066. yScaleFactor:0.4,
  1067. containerWidth: element.width,
  1068. containerHeight: element.height,
  1069. position: {
  1070. mx: 0.474,
  1071. my: 0.296
  1072. }
  1073. });
  1074. var parallelPath = drawPath(parentGfx, pathData);
  1075. svgAttr(parallelPath, {
  1076. strokeWidth: 1,
  1077. fill: 'none'
  1078. });
  1079. } else if (type === 'Exclusive') {
  1080. if (!instantiate) {
  1081. var innerCircle = drawCircle(parentGfx, element.width, element.height, element.height * 0.26);
  1082. svgAttr(innerCircle, {
  1083. strokeWidth: 1,
  1084. fill: 'none',
  1085. stroke: getStrokeColor(element, defaultStrokeColor)
  1086. });
  1087. }
  1088. drawEvent();
  1089. }
  1090. return diamond;
  1091. },
  1092. 'bpmn:Gateway': function(parentGfx, element) {
  1093. var attrs = {
  1094. fill: getFillColor(element, defaultFillColor),
  1095. fillOpacity: DEFAULT_FILL_OPACITY,
  1096. stroke: getStrokeColor(element, defaultStrokeColor)
  1097. };
  1098. return drawDiamond(parentGfx, element.width, element.height, attrs);
  1099. },
  1100. 'bpmn:SequenceFlow': function(parentGfx, element) {
  1101. var pathData = createPathFromConnection(element);
  1102. var fill = getFillColor(element, defaultFillColor),
  1103. stroke = getStrokeColor(element, defaultStrokeColor);
  1104. var attrs = {
  1105. strokeLinejoin: 'round',
  1106. markerEnd: marker('sequenceflow-end', fill, stroke),
  1107. stroke: getStrokeColor(element, defaultStrokeColor)
  1108. };
  1109. var path = drawPath(parentGfx, pathData, attrs);
  1110. var sequenceFlow = getSemantic(element);
  1111. var source;
  1112. if (element.source) {
  1113. source = element.source.businessObject;
  1114. // conditional flow marker
  1115. if (sequenceFlow.conditionExpression && source.$instanceOf('bpmn:Activity')) {
  1116. svgAttr(path, {
  1117. markerStart: marker('conditional-flow-marker', fill, stroke)
  1118. });
  1119. }
  1120. // default marker
  1121. if (source.default && (source.$instanceOf('bpmn:Gateway') || source.$instanceOf('bpmn:Activity')) &&
  1122. source.default === sequenceFlow) {
  1123. svgAttr(path, {
  1124. markerStart: marker('conditional-default-flow-marker', fill, stroke)
  1125. });
  1126. }
  1127. }
  1128. return path;
  1129. },
  1130. 'bpmn:Association': function(parentGfx, element, attrs) {
  1131. var semantic = getSemantic(element);
  1132. var fill = getFillColor(element, defaultFillColor),
  1133. stroke = getStrokeColor(element, defaultStrokeColor);
  1134. attrs = assign({
  1135. strokeDasharray: '0.5, 5',
  1136. strokeLinecap: 'round',
  1137. strokeLinejoin: 'round',
  1138. stroke: getStrokeColor(element, defaultStrokeColor)
  1139. }, attrs || {});
  1140. if (semantic.associationDirection === 'One' ||
  1141. semantic.associationDirection === 'Both') {
  1142. attrs.markerEnd = marker('association-end', fill, stroke);
  1143. }
  1144. if (semantic.associationDirection === 'Both') {
  1145. attrs.markerStart = marker('association-start', fill, stroke);
  1146. }
  1147. return drawLine(parentGfx, element.waypoints, attrs);
  1148. },
  1149. 'bpmn:DataInputAssociation': function(parentGfx, element) {
  1150. var fill = getFillColor(element, defaultFillColor),
  1151. stroke = getStrokeColor(element, defaultStrokeColor);
  1152. return renderer('bpmn:Association')(parentGfx, element, {
  1153. markerEnd: marker('association-end', fill, stroke)
  1154. });
  1155. },
  1156. 'bpmn:DataOutputAssociation': function(parentGfx, element) {
  1157. var fill = getFillColor(element, defaultFillColor),
  1158. stroke = getStrokeColor(element, defaultStrokeColor);
  1159. return renderer('bpmn:Association')(parentGfx, element, {
  1160. markerEnd: marker('association-end', fill, stroke)
  1161. });
  1162. },
  1163. 'bpmn:MessageFlow': function(parentGfx, element) {
  1164. var semantic = getSemantic(element),
  1165. di = getDi(element);
  1166. var fill = getFillColor(element, defaultFillColor),
  1167. stroke = getStrokeColor(element, defaultStrokeColor);
  1168. var pathData = createPathFromConnection(element);
  1169. var attrs = {
  1170. markerEnd: marker('messageflow-end', fill, stroke),
  1171. markerStart: marker('messageflow-start', fill, stroke),
  1172. strokeDasharray: '10, 12',
  1173. strokeLinecap: 'round',
  1174. strokeLinejoin: 'round',
  1175. strokeWidth: '1.5px',
  1176. stroke: getStrokeColor(element, defaultStrokeColor)
  1177. };
  1178. var path = drawPath(parentGfx, pathData, attrs);
  1179. if (semantic.messageRef) {
  1180. var midPoint = path.getPointAtLength(path.getTotalLength() / 2);
  1181. var markerPathData = pathMap.getScaledPath('MESSAGE_FLOW_MARKER', {
  1182. abspos: {
  1183. x: midPoint.x,
  1184. y: midPoint.y
  1185. }
  1186. });
  1187. var messageAttrs = { strokeWidth: 1 };
  1188. if (di.messageVisibleKind === 'initiating') {
  1189. messageAttrs.fill = 'white';
  1190. messageAttrs.stroke = 'black';
  1191. } else {
  1192. messageAttrs.fill = '#888';
  1193. messageAttrs.stroke = 'white';
  1194. }
  1195. drawPath(parentGfx, markerPathData, messageAttrs);
  1196. }
  1197. return path;
  1198. },
  1199. 'bpmn:DataObject': function(parentGfx, element) {
  1200. var pathData = pathMap.getScaledPath('DATA_OBJECT_PATH', {
  1201. xScaleFactor: 1,
  1202. yScaleFactor: 1,
  1203. containerWidth: element.width,
  1204. containerHeight: element.height,
  1205. position: {
  1206. mx: 0.474,
  1207. my: 0.296
  1208. }
  1209. });
  1210. var elementObject = drawPath(parentGfx, pathData, {
  1211. fill: getFillColor(element, defaultFillColor),
  1212. fillOpacity: DEFAULT_FILL_OPACITY,
  1213. stroke: getStrokeColor(element, defaultStrokeColor)
  1214. });
  1215. var semantic = getSemantic(element);
  1216. if (isCollection(semantic)) {
  1217. renderDataItemCollection(parentGfx, element);
  1218. }
  1219. return elementObject;
  1220. },
  1221. 'bpmn:DataObjectReference': as('bpmn:DataObject'),
  1222. 'bpmn:DataInput': function(parentGfx, element) {
  1223. var arrowPathData = pathMap.getRawPath('DATA_ARROW');
  1224. // page
  1225. var elementObject = renderer('bpmn:DataObject')(parentGfx, element);
  1226. /* input arrow path */ drawPath(parentGfx, arrowPathData, { strokeWidth: 1 });
  1227. return elementObject;
  1228. },
  1229. 'bpmn:DataOutput': function(parentGfx, element) {
  1230. var arrowPathData = pathMap.getRawPath('DATA_ARROW');
  1231. // page
  1232. var elementObject = renderer('bpmn:DataObject')(parentGfx, element);
  1233. /* output arrow path */ drawPath(parentGfx, arrowPathData, {
  1234. strokeWidth: 1,
  1235. fill: 'black'
  1236. });
  1237. return elementObject;
  1238. },
  1239. 'bpmn:DataStoreReference': function(parentGfx, element) {
  1240. var DATA_STORE_PATH = pathMap.getScaledPath('DATA_STORE', {
  1241. xScaleFactor: 1,
  1242. yScaleFactor: 1,
  1243. containerWidth: element.width,
  1244. containerHeight: element.height,
  1245. position: {
  1246. mx: 0,
  1247. my: 0.133
  1248. }
  1249. });
  1250. var elementStore = drawPath(parentGfx, DATA_STORE_PATH, {
  1251. strokeWidth: 2,
  1252. fill: getFillColor(element, defaultFillColor),
  1253. fillOpacity: DEFAULT_FILL_OPACITY,
  1254. stroke: getStrokeColor(element, defaultStrokeColor)
  1255. });
  1256. return elementStore;
  1257. },
  1258. 'bpmn:BoundaryEvent': function(parentGfx, element) {
  1259. var semantic = getSemantic(element),
  1260. cancel = semantic.cancelActivity;
  1261. var attrs = {
  1262. strokeWidth: 1,
  1263. fill: getFillColor(element, defaultFillColor),
  1264. stroke: getStrokeColor(element, defaultStrokeColor)
  1265. };
  1266. if (!cancel) {
  1267. attrs.strokeDasharray = '6';
  1268. attrs.strokeLinecap = 'round';
  1269. }
  1270. // apply fillOpacity
  1271. var outerAttrs = assign({}, attrs, {
  1272. fillOpacity: 1
  1273. });
  1274. // apply no-fill
  1275. var innerAttrs = assign({}, attrs, {
  1276. fill: 'none'
  1277. });
  1278. var outer = renderer('bpmn:Event')(parentGfx, element, outerAttrs);
  1279. /* inner path */ drawCircle(parentGfx, element.width, element.height, INNER_OUTER_DIST, innerAttrs);
  1280. renderEventContent(element, parentGfx);
  1281. return outer;
  1282. },
  1283. 'bpmn:Group': function(parentGfx, element) {
  1284. var semantic = getSemantic(element),
  1285. di = getDi(element);
  1286. var group = drawRect(parentGfx, element.width, element.height, TASK_BORDER_RADIUS, {
  1287. strokeWidth: 1,
  1288. strokeDasharray: '8,3,1,3',
  1289. fill: 'none',
  1290. pointerEvents: 'none'
  1291. });
  1292. var categoryValueRef = semantic.categoryValueRef || {};
  1293. if (categoryValueRef.value) {
  1294. var box = di.label ? di.label.bounds : element;
  1295. renderLabel(parentGfx, categoryValueRef.value, {
  1296. box: box,
  1297. style: {
  1298. fill: getStrokeColor(element, defaultStrokeColor)
  1299. }
  1300. });
  1301. }
  1302. return group;
  1303. },
  1304. 'label': function(parentGfx, element) {
  1305. return renderExternalLabel(parentGfx, element);
  1306. },
  1307. 'bpmn:TextAnnotation': function(parentGfx, element) {
  1308. var style = {
  1309. 'fill': 'none',
  1310. 'stroke': 'none'
  1311. };
  1312. var textElement = drawRect(parentGfx, element.width, element.height, 0, 0, style);
  1313. var textPathData = pathMap.getScaledPath('TEXT_ANNOTATION', {
  1314. xScaleFactor: 1,
  1315. yScaleFactor: 1,
  1316. containerWidth: element.width,
  1317. containerHeight: element.height,
  1318. position: {
  1319. mx: 0.0,
  1320. my: 0.0
  1321. }
  1322. });
  1323. drawPath(parentGfx, textPathData, {
  1324. stroke: getStrokeColor(element, defaultStrokeColor)
  1325. });
  1326. var text = getSemantic(element).text || '';
  1327. renderLabel(parentGfx, text, {
  1328. box: element,
  1329. align: 'left-top',
  1330. padding: 5,
  1331. style: {
  1332. fill: getStrokeColor(element, defaultStrokeColor)
  1333. }
  1334. });
  1335. return textElement;
  1336. },
  1337. 'ParticipantMultiplicityMarker': function(parentGfx, element) {
  1338. var markerPath = pathMap.getScaledPath('MARKER_PARALLEL', {
  1339. xScaleFactor: 1,
  1340. yScaleFactor: 1,
  1341. containerWidth: element.width,
  1342. containerHeight: element.height,
  1343. position: {
  1344. mx: ((element.width / 2) / element.width),
  1345. my: (element.height - 15) / element.height
  1346. }
  1347. });
  1348. drawMarker('participant-multiplicity', parentGfx, markerPath, {
  1349. strokeWidth: 1,
  1350. fill: getFillColor(element, defaultFillColor),
  1351. stroke: getStrokeColor(element, defaultStrokeColor)
  1352. });
  1353. },
  1354. 'SubProcessMarker': function(parentGfx, element) {
  1355. var markerRect = drawRect(parentGfx, 14, 14, 0, {
  1356. strokeWidth: 1,
  1357. fill: getFillColor(element, defaultFillColor),
  1358. stroke: getStrokeColor(element, defaultStrokeColor)
  1359. });
  1360. // Process marker is placed in the middle of the box
  1361. // therefore fixed values can be used here
  1362. translate(markerRect, element.width / 2 - 7.5, element.height - 20);
  1363. var markerPath = pathMap.getScaledPath('MARKER_SUB_PROCESS', {
  1364. xScaleFactor: 1.5,
  1365. yScaleFactor: 1.5,
  1366. containerWidth: element.width,
  1367. containerHeight: element.height,
  1368. position: {
  1369. mx: (element.width / 2 - 7.5) / element.width,
  1370. my: (element.height - 20) / element.height
  1371. }
  1372. });
  1373. drawMarker('sub-process', parentGfx, markerPath, {
  1374. fill: getFillColor(element, defaultFillColor),
  1375. stroke: getStrokeColor(element, defaultStrokeColor)
  1376. });
  1377. },
  1378. 'ParallelMarker': function(parentGfx, element, position) {
  1379. var markerPath = pathMap.getScaledPath('MARKER_PARALLEL', {
  1380. xScaleFactor: 1,
  1381. yScaleFactor: 1,
  1382. containerWidth: element.width,
  1383. containerHeight: element.height,
  1384. position: {
  1385. mx: ((element.width / 2 + position.parallel) / element.width),
  1386. my: (element.height - 20) / element.height
  1387. }
  1388. });
  1389. drawMarker('parallel', parentGfx, markerPath, {
  1390. fill: getFillColor(element, defaultFillColor),
  1391. stroke: getStrokeColor(element, defaultStrokeColor)
  1392. });
  1393. },
  1394. 'SequentialMarker': function(parentGfx, element, position) {
  1395. var markerPath = pathMap.getScaledPath('MARKER_SEQUENTIAL', {
  1396. xScaleFactor: 1,
  1397. yScaleFactor: 1,
  1398. containerWidth: element.width,
  1399. containerHeight: element.height,
  1400. position: {
  1401. mx: ((element.width / 2 + position.seq) / element.width),
  1402. my: (element.height - 19) / element.height
  1403. }
  1404. });
  1405. drawMarker('sequential', parentGfx, markerPath, {
  1406. fill: getFillColor(element, defaultFillColor),
  1407. stroke: getStrokeColor(element, defaultStrokeColor)
  1408. });
  1409. },
  1410. 'CompensationMarker': function(parentGfx, element, position) {
  1411. var markerMath = pathMap.getScaledPath('MARKER_COMPENSATION', {
  1412. xScaleFactor: 1,
  1413. yScaleFactor: 1,
  1414. containerWidth: element.width,
  1415. containerHeight: element.height,
  1416. position: {
  1417. mx: ((element.width / 2 + position.compensation) / element.width),
  1418. my: (element.height - 13) / element.height
  1419. }
  1420. });
  1421. drawMarker('compensation', parentGfx, markerMath, {
  1422. strokeWidth: 1,
  1423. fill: getFillColor(element, defaultFillColor),
  1424. stroke: getStrokeColor(element, defaultStrokeColor)
  1425. });
  1426. },
  1427. 'LoopMarker': function(parentGfx, element, position) {
  1428. var markerPath = pathMap.getScaledPath('MARKER_LOOP', {
  1429. xScaleFactor: 1,
  1430. yScaleFactor: 1,
  1431. containerWidth: element.width,
  1432. containerHeight: element.height,
  1433. position: {
  1434. mx: ((element.width / 2 + position.loop) / element.width),
  1435. my: (element.height - 7) / element.height
  1436. }
  1437. });
  1438. drawMarker('loop', parentGfx, markerPath, {
  1439. strokeWidth: 1,
  1440. fill: getFillColor(element, defaultFillColor),
  1441. stroke: getStrokeColor(element, defaultStrokeColor),
  1442. strokeLinecap: 'round',
  1443. strokeMiterlimit: 0.5
  1444. });
  1445. },
  1446. 'AdhocMarker': function(parentGfx, element, position) {
  1447. var markerPath = pathMap.getScaledPath('MARKER_ADHOC', {
  1448. xScaleFactor: 1,
  1449. yScaleFactor: 1,
  1450. containerWidth: element.width,
  1451. containerHeight: element.height,
  1452. position: {
  1453. mx: ((element.width / 2 + position.adhoc) / element.width),
  1454. my: (element.height - 15) / element.height
  1455. }
  1456. });
  1457. drawMarker('adhoc', parentGfx, markerPath, {
  1458. strokeWidth: 1,
  1459. fill: getStrokeColor(element, defaultStrokeColor),
  1460. stroke: getStrokeColor(element, defaultStrokeColor)
  1461. });
  1462. }
  1463. };
  1464. function attachTaskMarkers(parentGfx, element, taskMarkers) {
  1465. var obj = getSemantic(element);
  1466. var subprocess = taskMarkers && taskMarkers.indexOf('SubProcessMarker') !== -1;
  1467. var position;
  1468. if (subprocess) {
  1469. position = {
  1470. seq: -21,
  1471. parallel: -22,
  1472. compensation: -42,
  1473. loop: -18,
  1474. adhoc: 10
  1475. };
  1476. } else {
  1477. position = {
  1478. seq: -3,
  1479. parallel: -6,
  1480. compensation: -27,
  1481. loop: 0,
  1482. adhoc: 10
  1483. };
  1484. }
  1485. forEach(taskMarkers, function(marker) {
  1486. renderer(marker)(parentGfx, element, position);
  1487. });
  1488. if (obj.isForCompensation) {
  1489. renderer('CompensationMarker')(parentGfx, element, position);
  1490. }
  1491. if (obj.$type === 'bpmn:AdHocSubProcess') {
  1492. renderer('AdhocMarker')(parentGfx, element, position);
  1493. }
  1494. var loopCharacteristics = obj.loopCharacteristics,
  1495. isSequential = loopCharacteristics && loopCharacteristics.isSequential;
  1496. if (loopCharacteristics) {
  1497. if (isSequential === undefined) {
  1498. renderer('LoopMarker')(parentGfx, element, position);
  1499. }
  1500. if (isSequential === false) {
  1501. renderer('ParallelMarker')(parentGfx, element, position);
  1502. }
  1503. if (isSequential === true) {
  1504. renderer('SequentialMarker')(parentGfx, element, position);
  1505. }
  1506. }
  1507. }
  1508. function renderDataItemCollection(parentGfx, element) {
  1509. var yPosition = (element.height - 16) / element.height;
  1510. var pathData = pathMap.getScaledPath('DATA_OBJECT_COLLECTION_PATH', {
  1511. xScaleFactor: 1,
  1512. yScaleFactor: 1,
  1513. containerWidth: element.width,
  1514. containerHeight: element.height,
  1515. position: {
  1516. mx: 0.451,
  1517. my: yPosition
  1518. }
  1519. });
  1520. /* collection path */ drawPath(parentGfx, pathData, {
  1521. strokeWidth: 2
  1522. });
  1523. }
  1524. // extension API, use at your own risk
  1525. this._drawPath = drawPath;
  1526. }
  1527. inherits(BpmnRenderer, BaseRenderer);
  1528. BpmnRenderer.$inject = [
  1529. 'config.bpmnRenderer',
  1530. 'eventBus',
  1531. 'styles',
  1532. 'pathMap',
  1533. 'canvas',
  1534. 'textRenderer'
  1535. ];
  1536. BpmnRenderer.prototype.canRender = function(element) {
  1537. return is(element, 'bpmn:BaseElement');
  1538. };
  1539. BpmnRenderer.prototype.drawShape = function(parentGfx, element) {
  1540. var type = element.type;
  1541. var h = this.handlers[type];
  1542. /* jshint -W040 */
  1543. return h(parentGfx, element);
  1544. };
  1545. BpmnRenderer.prototype.drawConnection = function(parentGfx, element) {
  1546. var type = element.type;
  1547. var h = this.handlers[type];
  1548. /* jshint -W040 */
  1549. return h(parentGfx, element);
  1550. };
  1551. BpmnRenderer.prototype.getShapePath = function(element) {
  1552. if (is(element, 'bpmn:Event')) {
  1553. return getCirclePath(element);
  1554. }
  1555. if (is(element, 'bpmn:Activity')) {
  1556. return getRoundRectPath(element, TASK_BORDER_RADIUS);
  1557. }
  1558. if (is(element, 'bpmn:Gateway')) {
  1559. return getDiamondPath(element);
  1560. }
  1561. return getRectPath(element);
  1562. };