diff --git a/cypress/platform/current.html b/cypress/platform/current.html
index 56f2c3257..b987d1b08 100644
--- a/cypress/platform/current.html
+++ b/cypress/platform/current.html
@@ -101,9 +101,20 @@
b-->id1
id1 --> id2
+ new:
flowchart LR
- a o--o b
+ a <--> b
+ b o--o c
+ c x--x d
+ a2 --> b2
+ b2 --o c2
+ c2 --x d2
+
+ old:
+
+ graph LR
+ a --> b
diff --git a/src/dagre-wrapper/GraphObjects.md b/src/dagre-wrapper/GraphObjects.md
index d073515b8..d6fd87648 100644
--- a/src/dagre-wrapper/GraphObjects.md
+++ b/src/dagre-wrapper/GraphObjects.md
@@ -38,6 +38,30 @@ This is set by the renderer of the diagram and insert the data that the wrapper
| padding | Padding. Passed from the renderr as this might differ between react for different diagrams. Maybe obsolete. |
-#edge
+# edge
-arrowType sets the type of arrows to use
+arrowType sets the type of arrows to use. The following arrow types are currently supported:
+
+arrow_cross
+double_arrow_cross
+arrow_point
+double_arrow_point
+arrow_circle
+double_arrow_circle
+
+Lets try to make these types semantic free so that diagram type semantics does not find its way in to this more generic layer.
+
+
+# Markers
+
+Define what markers that should be included in the diagram with the insert markers function. The function takes two arguments, first the element in which the markers should be included and a list of the markers that should be added.
+
+Ex:
+insertMarkers(el, ['point', 'circle'])
+
+The example above adds the markers point and cross. This means that edges with the arrowTypes arrow_cross, double_arrow_cross, arrow_point and double_arrow_cross will get the corresponding markers but arrowType arrow_cross will have no impact.
+
+Current markers:
+* point - the standard arrow from flowcharts
+* circle - Arrows ending with circle
+* cross - arrows starting and ending with a cross
\ No newline at end of file
diff --git a/src/dagre-wrapper/edges.js b/src/dagre-wrapper/edges.js
index e3c372220..d81f1c13f 100644
--- a/src/dagre-wrapper/edges.js
+++ b/src/dagre-wrapper/edges.js
@@ -191,6 +191,7 @@ export const insertEdge = function(elem, edge, clusterDb) {
.attr('id', edge.id)
.attr('class', 'transition');
+ // DEBUG code, adds a red circle at each edge coordinate
// edge.points.forEach(point => {
// elem
// .append('circle')
@@ -212,13 +213,29 @@ export const insertEdge = function(elem, edge, clusterDb) {
url = url.replace(/\(/g, '\\(');
url = url.replace(/\)/g, '\\)');
}
+ logger.info('arrowType', edge.arrowType);
switch (edge.arrowType) {
- case 'double_arrow_circle':
- svgPath.attr('marker-end', 'url(' + url + '#' + 'circleEnd' + ')');
- svgPath.attr('marker-start', 'url(' + url + '#' + 'circleStart' + ')');
+ case 'arrow_cross':
+ svgPath.attr('marker-end', 'url(' + url + '#' + 'crossEnd' + ')');
+ break;
+ case 'double_arrow_cross':
+ svgPath.attr('marker-end', 'url(' + url + '#' + 'crossEnd' + ')');
+ svgPath.attr('marker-start', 'url(' + url + '#' + 'crossStart' + ')');
+ break;
+ case 'arrow_point':
+ svgPath.attr('marker-end', 'url(' + url + '#' + 'pointEnd' + ')');
+ break;
+ case 'double_arrow_point':
+ svgPath.attr('marker-end', 'url(' + url + '#' + 'pointEnd' + ')');
+ svgPath.attr('marker-start', 'url(' + url + '#' + 'pointStart' + ')');
break;
case 'arrow_circle':
svgPath.attr('marker-end', 'url(' + url + '#' + 'circleEnd' + ')');
break;
+ case 'double_arrow_circle':
+ svgPath.attr('marker-end', 'url(' + url + '#' + 'circleEnd' + ')');
+ svgPath.attr('marker-start', 'url(' + url + '#' + 'circleStart' + ')');
+ break;
+ default:
}
};
diff --git a/src/dagre-wrapper/index.js b/src/dagre-wrapper/index.js
index bf3127a76..dbfbcc3ee 100644
--- a/src/dagre-wrapper/index.js
+++ b/src/dagre-wrapper/index.js
@@ -12,8 +12,8 @@ const translateClusterId = id => {
return id;
};
-export const render = (elem, graph) => {
- insertMarkers(elem);
+export const render = (elem, graph, markers) => {
+ insertMarkers(elem, markers);
clusterDb = {};
clearNodes();
clearEdges();
diff --git a/src/dagre-wrapper/markers.js b/src/dagre-wrapper/markers.js
index 0515defc4..2850b6714 100644
--- a/src/dagre-wrapper/markers.js
+++ b/src/dagre-wrapper/markers.js
@@ -1,7 +1,14 @@
/**
* Setup arrow head and define the marker. The result is appended to the svg.
*/
-const insertMarkers = elem => {
+// Only add the number of markers that the diagram needs
+const insertMarkers = (elem, markerArray) => {
+ markerArray.forEach(markerName => {
+ markers[markerName](elem);
+ });
+};
+
+const extension = elem => {
elem
.append('defs')
.append('marker')
@@ -26,7 +33,9 @@ const insertMarkers = elem => {
.attr('orient', 'auto')
.append('path')
.attr('d', 'M 1,1 V 13 L18,7 Z'); // this is actual shape for arrowhead
+};
+const composition = elem => {
elem
.append('defs')
.append('marker')
@@ -51,7 +60,8 @@ const insertMarkers = elem => {
.attr('orient', 'auto')
.append('path')
.attr('d', 'M 18,7 L9,13 L1,7 L9,1 Z');
-
+};
+const aggregation = elem => {
elem
.append('defs')
.append('marker')
@@ -76,7 +86,8 @@ const insertMarkers = elem => {
.attr('orient', 'auto')
.append('path')
.attr('d', 'M 18,7 L9,13 L1,7 L9,1 Z');
-
+};
+const dependency = elem => {
elem
.append('defs')
.append('marker')
@@ -101,16 +112,17 @@ const insertMarkers = elem => {
.attr('orient', 'auto')
.append('path')
.attr('d', 'M 18,7 L9,13 L14,7 L9,1 Z');
-
+};
+const point = elem => {
elem
.append('marker')
- .attr('id', 'normalEnd')
+ .attr('id', 'pointEnd')
.attr('viewBox', '0 0 10 10')
- .attr('refX', 9)
+ .attr('refX', 10)
.attr('refY', 5)
.attr('markerUnits', 'strokeWidth')
.attr('markerWidth', 8)
- .attr('markerHeight', 6)
+ .attr('markerHeight', 8)
.attr('orient', 'auto')
.append('path')
.attr('d', 'M 0 0 L 10 5 L 0 10 z')
@@ -119,24 +131,26 @@ const insertMarkers = elem => {
.style('stroke-dasharray', '1,0');
elem
.append('marker')
- .attr('id', 'normalStart')
+ .attr('id', 'pointStart')
.attr('viewBox', '0 0 10 10')
- .attr('refX', 9)
+ .attr('refX', 0)
.attr('refY', 5)
.attr('markerUnits', 'strokeWidth')
.attr('markerWidth', 8)
- .attr('markerHeight', 6)
+ .attr('markerHeight', 8)
.attr('orient', 'auto')
.append('path')
- .attr('d', 'M 0 0 L 10 5 L 0 10 z')
+ .attr('d', 'M 0 5 L 10 10 L 10 0 z')
.attr('class', 'arrowheadPath')
.style('stroke-width', 1)
.style('stroke-dasharray', '1,0');
+};
+const circle = elem => {
elem
.append('marker')
.attr('id', 'circleEnd')
.attr('viewBox', '0 0 10 10')
- .attr('refX', 10)
+ .attr('refX', 11)
.attr('refY', 5)
.attr('markerUnits', 'strokeWidth')
.attr('markerWidth', 7)
@@ -146,7 +160,6 @@ const insertMarkers = elem => {
.attr('cx', '5')
.attr('cy', '5')
.attr('r', '5')
- .attr('fill', 'red')
.attr('class', 'arrowheadPath')
.style('stroke-width', 1)
.style('stroke-dasharray', '1,0');
@@ -155,7 +168,7 @@ const insertMarkers = elem => {
.append('marker')
.attr('id', 'circleStart')
.attr('viewBox', '0 0 10 10')
- .attr('refX', 0)
+ .attr('refX', -1)
.attr('refY', 5)
.attr('markerUnits', 'strokeWidth')
.attr('markerWidth', 7)
@@ -165,10 +178,54 @@ const insertMarkers = elem => {
.attr('cx', '5')
.attr('cy', '5')
.attr('r', '5')
- .attr('fill', 'red')
.attr('class', 'arrowheadPath')
.style('stroke-width', 1)
.style('stroke-dasharray', '1,0');
};
+const cross = elem => {
+ elem
+ .append('marker')
+ .attr('id', 'crossEnd')
+ .attr('viewBox', '0 0 11 11')
+ .attr('refX', 12)
+ .attr('refY', 5.2)
+ .attr('markerUnits', 'strokeWidth')
+ .attr('markerWidth', 7)
+ .attr('markerHeight', 7)
+ .attr('orient', 'auto')
+ .append('path')
+ .attr('stroke', 'black')
+ .attr('d', 'M 1,1 l 9,9 M 10,1 l -9,9')
+ .attr('class', 'arrowheadPath')
+ .style('stroke-width', 2)
+ .style('stroke-dasharray', '1,0');
+ elem
+ .append('marker')
+ .attr('id', 'crossStart')
+ .attr('viewBox', '0 0 11 11')
+ .attr('refX', -1)
+ .attr('refY', 5.2)
+ .attr('markerUnits', 'strokeWidth')
+ .attr('markerWidth', 7)
+ .attr('markerHeight', 7)
+ .attr('orient', 'auto')
+ .append('path')
+ .attr('stroke', 'black')
+ .attr('d', 'M 1,1 l 9,9 M 10,1 l -9,9')
+ .attr('class', 'arrowheadPath')
+ .style('stroke-width', 2)
+ .style('stroke-dasharray', '1,0');
+};
+
+// TODO rename the class diagram markers to something shape descriptive and semanitc free
+const markers = {
+ extension,
+ composition,
+ aggregation,
+ dependency,
+ point,
+ circle,
+ cross
+};
export default insertMarkers;
diff --git a/src/diagrams/flowchart/flowDb.js b/src/diagrams/flowchart/flowDb.js
index d6d766da6..375b1b8ae 100644
--- a/src/diagrams/flowchart/flowDb.js
+++ b/src/diagrams/flowchart/flowDb.js
@@ -496,19 +496,19 @@ const destructStartLink = _str => {
switch (str) {
case '<--':
- return { type: 'arrow', stroke: 'normal' };
+ return { type: 'arrow_point', stroke: 'normal' };
case 'x--':
return { type: 'arrow_cross', stroke: 'normal' };
case 'o--':
return { type: 'arrow_circle', stroke: 'normal' };
case '<-.':
- return { type: 'arrow', stroke: 'dotted' };
+ return { type: 'arrow_point', stroke: 'dotted' };
case 'x-.':
return { type: 'arrow_cross', stroke: 'dotted' };
case 'o-.':
return { type: 'arrow_circle', stroke: 'dotted' };
case '<==':
- return { type: 'arrow', stroke: 'thick' };
+ return { type: 'arrow_point', stroke: 'thick' };
case 'x==':
return { type: 'arrow_cross', stroke: 'thick' };
case 'o==':
@@ -529,7 +529,7 @@ const destructEndLink = _str => {
case '--x':
return { type: 'arrow_cross', stroke: 'normal' };
case '-->':
- return { type: 'arrow', stroke: 'normal' };
+ return { type: 'arrow_point', stroke: 'normal' };
case '<-->':
return { type: 'double_arrow_point', stroke: 'normal' };
case 'x--x':
@@ -561,7 +561,7 @@ const destructEndLink = _str => {
case '-.-x':
return { type: 'arrow_cross', stroke: 'dotted' };
case '-.->':
- return { type: 'arrow', stroke: 'dotted' };
+ return { type: 'arrow_point', stroke: 'dotted' };
case '-.-o':
return { type: 'arrow_circle', stroke: 'dotted' };
case '-.-':
@@ -569,7 +569,7 @@ const destructEndLink = _str => {
case '.-x':
return { type: 'arrow_cross', stroke: 'dotted' };
case '.->':
- return { type: 'arrow', stroke: 'dotted' };
+ return { type: 'arrow_point', stroke: 'dotted' };
case '.-o':
return { type: 'arrow_circle', stroke: 'dotted' };
case '.-':
@@ -577,7 +577,7 @@ const destructEndLink = _str => {
case '==x':
return { type: 'arrow_cross', stroke: 'thick' };
case '==>':
- return { type: 'arrow', stroke: 'thick' };
+ return { type: 'arrow_point', stroke: 'thick' };
case '==o':
return { type: 'arrow_circle', stroke: 'thick' };
case '===':
diff --git a/src/diagrams/flowchart/flowRenderer-v2.js b/src/diagrams/flowchart/flowRenderer-v2.js
index b4a278bcd..e1866d396 100644
--- a/src/diagrams/flowchart/flowRenderer-v2.js
+++ b/src/diagrams/flowchart/flowRenderer-v2.js
@@ -372,7 +372,7 @@ export const draw = function(text, id) {
// Run the renderer. This is what draws the final graph.
const element = d3.select('#' + id + ' g');
- render(element, g);
+ render(element, g, ['point', 'circle', 'cross']);
dagre.layout(g);
element.selectAll('g.node').attr('title', function() {