diff --git a/lib/draw/BpmnRenderer.js b/lib/draw/BpmnRenderer.js
index 98316998..f96875fa 100644
--- a/lib/draw/BpmnRenderer.js
+++ b/lib/draw/BpmnRenderer.js
@@ -144,10 +144,6 @@ function BpmnRenderer(events, styles, bpmnRegistry, pathMap) {
function drawRect(p, width, height, r, offset) {
offset = offset || 0;
- var x, y;
-
- x = y = offset;
-
return p.rect(offset, offset, width - offset * 2, height - offset * 2, r).attr({
'stroke': 'Black',
'stroke-width': 2,
@@ -183,7 +179,7 @@ function BpmnRenderer(events, styles, bpmnRegistry, pathMap) {
var fillColor = fill ? 'Black' : 'None';
var path = p.path(d).attr(styles.style([ 'no-fill' ],{
- 'stroke-width': 2,
+ 'stroke-width': 1,
'stroke': 'Black',
'fill': fillColor
}));
@@ -600,6 +596,7 @@ function BpmnRenderer(events, styles, bpmnRegistry, pathMap) {
'bpmn:Task': function(p, data) {
var rect = renderer('bpmn:Activity')(p, data);
renderEmbeddedLabel(p, data, 'center-middle');
+ attachTaskMarkers(p, data);
return rect;
},
'bpmn:ServiceTask': as('bpmn:Task'),
@@ -612,12 +609,24 @@ function BpmnRenderer(events, styles, bpmnRegistry, pathMap) {
'bpmn:SubProcess': function(p, data) {
var rect = renderer('bpmn:Activity')(p, data);
+
var di = bpmnRegistry.getDi(data);
renderEmbeddedLabel(p, data, di.isExpanded ? 'center-top' : 'center-middle');
+
+ if(di.isExpanded) {
+ attachTaskMarkers(p, data);
+ } else {
+ attachTaskMarkers(p, data, ['SubProcessMarker']);
+ }
+
return rect;
},
- 'bpmn:AdHocSubProcess': as('bpmn:SubProcess'),
+ 'bpmn:AdHocSubProcess': function(p, data) {
+ var process = renderer('bpmn:SubProcess')(p, data);
+
+ return process;
+ },
'bpmn:Transaction': function(p, data) {
var outer = renderer('bpmn:SubProcess')(p, data);
var inner = drawRect(p, data.width, data.height, TASK_BORDER_RADIUS - 2, INNER_OUTER_DIST)
@@ -974,15 +983,159 @@ function BpmnRenderer(events, styles, bpmnRegistry, pathMap) {
my: 0.0
}
});
- var textPath = drawPath(p, textPathData);
+ drawPath(p, textPathData);
var text = bpmnRegistry.getSemantic(data.id).text || '';
var label = renderLabel(p, text, { box: data, align: 'left-middle' });
return label;
+ },
+ 'SubProcessMarker': function(p, data) {
+ var markerRect = drawRect(p, 14, 14, 0);
+ // Process marker is placed in the middle of the box
+ // therefore fixed values can be used here
+ markerRect.transform('translate(' + (data.width / 2 - 7.5) + ',' + (data.height - 20) + ')');
+ markerRect.attr({
+ 'stroke-width': 1
+ });
+
+ var subProcessPath = pathMap.getScaledPath('MARKER_SUB_PROCESS', {
+ xScaleFactor: 1.5,
+ yScaleFactor: 1.5,
+ containerWidth: data.width,
+ containerHeight: data.height,
+ position: {
+ mx: (data.width / 2 - 7.5) / data.width,
+ my: (data.height - 20) / data.height
+ }
+ });
+ drawPath(p, subProcessPath);
+ },
+ 'ParallelMarker': function(p, data, position) {
+ var subProcessPath = pathMap.getScaledPath('MARKER_PARALLEL', {
+ xScaleFactor: 1,
+ yScaleFactor: 1,
+ containerWidth: data.width,
+ containerHeight: data.height,
+ position: {
+ mx: ((data.width / 2 + position.parallel) / data.width),
+ my: (data.height - 20) / data.height
+ }
+ });
+ drawPath(p, subProcessPath);
+ },
+ 'SequentialMarker': function(p, data, position) {
+ var sequentialPath = pathMap.getScaledPath('MARKER_SEQUENTIAL', {
+ xScaleFactor: 1,
+ yScaleFactor: 1,
+ containerWidth: data.width,
+ containerHeight: data.height,
+ position: {
+ mx: ((data.width / 2 + position.seq) / data.width),
+ my: (data.height - 19) / data.height
+ }
+ });
+ drawPath(p, sequentialPath);
+ },
+ 'CompensationMarker': function(p, data, position) {
+ var compensationPath = pathMap.getScaledPath('MARKER_COMPENSATION', {
+ xScaleFactor: 1,
+ yScaleFactor: 1,
+ containerWidth: data.width,
+ containerHeight: data.height,
+ position: {
+ mx: ((data.width / 2 + position.compensation) / data.width),
+ my: (data.height - 13) / data.height
+ }
+ });
+ drawPath(p, compensationPath);
+ },
+ 'LoopMarker': function(p, data, position) {
+ var loopPath = pathMap.getScaledPath('MARKER_LOOP', {
+ xScaleFactor: 1,
+ yScaleFactor: 1,
+ containerWidth: data.width,
+ containerHeight: data.height,
+ position: {
+ mx: ((data.width / 2 + position.loop) / data.width),
+ my: (data.height - 7) / data.height
+ }
+ });
+ var marker = drawPath(p, loopPath);
+ marker.attr({
+ 'stroke-width': 1,
+ 'fill': 'None',
+ 'stroke-linecap':'round',
+ 'stroke-miterlimit':0.5
+ });
+ },
+ 'AdhocMarker': function(p, data, position) {
+ console.log(data);
+ var loopPath = pathMap.getScaledPath('MARKER_ADHOC', {
+ xScaleFactor: 1,
+ yScaleFactor: 1,
+ containerWidth: data.width,
+ containerHeight: data.height,
+ position: {
+ mx: ((data.width / 2 + position.adhoc) / data.width),
+ my: (data.height - 15) / data.height
+ }
+ });
+ var marker = drawPath(p, loopPath);
+ marker.attr({
+ 'stroke-width': 1,
+ 'fill': 'Black'
+ });
+ }
+ };
+
+ function attachTaskMarkers(p, data, taskMarkers) {
+ var obj = bpmnRegistry.getSemantic(data.id);
+
+ var subprocess = _.contains(taskMarkers, 'SubProcessMarker');
+ var position;
+
+ if(subprocess) {
+ position = {
+ seq: -21,
+ parallel: -22,
+ compensation: -42,
+ loop: -18,
+ adhoc: 10
+ };
+ } else {
+ position = {
+ seq: -3,
+ parallel: -6,
+ compensation: -27,
+ loop: 0,
+ adhoc: 10
+ };
}
- };
+ _.forEach(taskMarkers, function(marker) {
+ renderer(marker)(p, data, position);
+ });
+
+ if(obj.$type === 'bpmn:AdHocSubProcess') {
+ renderer('AdhocMarker')(p, data, position);
+ }
+ if(obj.loopCharacteristics && obj.loopCharacteristics.isSequential === undefined) {
+ renderer('LoopMarker')(p, data, position);
+ return;
+ }
+ if(obj.loopCharacteristics &&
+ obj.loopCharacteristics.isSequential !== undefined &&
+ !obj.loopCharacteristics.isSequential) {
+ renderer('ParallelMarker')(p, data, position);
+ }
+ if(obj.loopCharacteristics && !!obj.loopCharacteristics.isSequential) {
+ renderer('SequentialMarker')(p, data, position);
+ }
+ if(!!obj.isForCompensation) {
+ renderer('CompensationMarker')(p, data, position);
+ }
+ }
function drawShape(parent, data) {
var type = data.type;
diff --git a/lib/draw/PathMap.js b/lib/draw/PathMap.js
index 243bda69..3bbfe8bd 100644
--- a/lib/draw/PathMap.js
+++ b/lib/draw/PathMap.js
@@ -204,6 +204,55 @@ function PathMap(Snap) {
width: 10,
heightElements: [30],
widthElements: [10]
+ },
+ 'MARKER_SUB_PROCESS': {
+ d: 'm{mx} {my}, m 7,2 l 0,10 m -5,-5 l 10,0',
+ height: 10,
+ width: 10,
+ heightElements: [],
+ widthElements: []
+ },
+ 'MARKER_PARALLEL': {
+ d: 'm{mx} {my}, m 3,2 l 0,10 m 3,-10 l 0,10 m 3,-10 l 0,10',
+ height: 10,
+ width: 10,
+ heightElements: [],
+ widthElements: []
+ },
+ 'MARKER_SEQUENTIAL': {
+ d: 'm{mx} {my}, m 0,3 l 10,0 m -10,3 l 10,0 m -10,3 l 10,0',
+ height: 10,
+ width: 10,
+ heightElements: [],
+ widthElements: []
+ },
+ 'MARKER_COMPENSATION': {
+ d: 'm {mx},{my} 8,-5 0,10 z m 9,0 8,-5 0,10 z',
+ height: 10,
+ width: 21,
+ heightElements: [],
+ widthElements: []
+ },
+ 'MARKER_LOOP': {
+ d: 'm {mx},{my} c 3.526979,0 6.386161,-2.829858 6.386161,-6.320661 0,-3.490806 -2.859182,-6.320661 ' +
+ '-6.386161,-6.320661 -3.526978,0 -6.38616,2.829855 -6.38616,6.320661 0,1.745402 ' +
+ '0.714797,3.325567 1.870463,4.469381 0.577834,0.571908 1.265885,1.034728 2.029916,1.35457 ' +
+ 'l -0.718163,-3.909793 m 0.718163,3.909793 -3.885211,0.802902',
+ height: 13.9,
+ width: 13.7,
+ heightElements: [],
+ widthElements: []
+ },
+ 'MARKER_ADHOC': {
+ d: 'm {mx},{my} m 0.84461,2.64411 c 1.05533,-1.23780996 2.64337,-2.07882 4.29653,-1.97997996 2.05163,0.0805 ' +
+ '3.85579,1.15803 5.76082,1.79107 1.06385,0.34139996 2.24454,0.1438 3.18759,-0.43767 0.61743,-0.33642 ' +
+ '1.2775,-0.64078 1.7542,-1.17511 0,0.56023 0,1.12046 0,1.6807 -0.98706,0.96237996 -2.29792,1.62393996 ' +
+ '-3.6918,1.66181996 -1.24459,0.0927 -2.46671,-0.2491 -3.59505,-0.74812 -1.35789,-0.55965 ' +
+ '-2.75133,-1.33436996 -4.27027,-1.18121996 -1.37741,0.14601 -2.41842,1.13685996 -3.44288,1.96782996 z',
+ height: 4,
+ width: 15,
+ heightElements: [],
+ widthElements: []
}
};
diff --git a/test/fixtures/bpmn/render/activity-marker-combination.bpmn b/test/fixtures/bpmn/render/activity-marker-combination.bpmn
new file mode 100644
index 00000000..02e2ea9b
--- /dev/null
+++ b/test/fixtures/bpmn/render/activity-marker-combination.bpmn
@@ -0,0 +1,141 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/fixtures/bpmn/render/activity-marker.bpmn b/test/fixtures/bpmn/render/activity-marker.bpmn
new file mode 100644
index 00000000..974b3438
--- /dev/null
+++ b/test/fixtures/bpmn/render/activity-marker.bpmn
@@ -0,0 +1,212 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/spec/browser/draw/BpmnRendererSpec.js b/test/spec/browser/draw/BpmnRendererSpec.js
index b4b4b3fe..2a44c3f5 100644
--- a/test/spec/browser/draw/BpmnRendererSpec.js
+++ b/test/spec/browser/draw/BpmnRendererSpec.js
@@ -28,6 +28,27 @@ describe('draw/BpmnRenderer', function() {
});
});
+ it('should render activity-marker', function(done) {
+
+ var xml = fs.readFileSync(__dirname + '/../../../fixtures/bpmn/render/activity-marker-combination.bpmn', 'utf8');
+
+ var renderer = new Viewer(container);
+
+ renderer.importXML(xml, function(err) {
+ done(err);
+ });
+ });
+
+ it('should render activity-marker', function(done) {
+
+ var xml = fs.readFileSync(__dirname + '/../../../fixtures/bpmn/render/activity-marker.bpmn', 'utf8');
+
+ var renderer = new Viewer(container);
+
+ renderer.importXML(xml, function(err) {
+ done(err);
+ });
+ });
it('should render data objects', function(done) {