UNPKG

5.26 kBJavaScriptView Raw
1import RRElement from './rrelement';
2import RRDiagramToSVG from './rrdiagramtosvg';
3import LayoutInfo from './layoutinfo';
4import { escapeXml, getFontInfo } from '../utils/utils';
5
6export default class RRLoop extends RRElement {
7
8 /**
9 * @param {RRElement} rrElement
10 * @param {RRElement} loopElement
11 * @param {?number} minRepetitionCount
12 * @param {?number} maxRepetitionCount
13 */
14 constructor(rrElement, loopElement, minRepetitionCount, maxRepetitionCount) {
15 super();
16 this.rrElement = rrElement;
17 this.loopElement = loopElement;
18 if (minRepetitionCount < 0) {
19 throw new IllegalArgumentException("Minimum repetition must be positive!");
20 }
21 if (maxRepetitionCount != null && maxRepetitionCount < minRepetitionCount) {
22 throw new IllegalArgumentException("Maximum repetition must not be smaller than minimum!");
23 }
24 this.minRepetitionCount = minRepetitionCount;
25 this.maxRepetitionCount = maxRepetitionCount;
26 this.cardinalitiesText = null;
27 this.cardinalitiesWidth = null;
28 this.fontYOffset = null;
29 }
30
31 computeLayoutInfo(rrDiagramToSVG) {
32 this.cardinalitiesText = null;
33 this.cardinalitiesWidth = 0;
34 this.fontYOffset = 0;
35 if (this.minRepetitionCount > 0 || this.maxRepetitionCount != null) {
36 this.cardinalitiesText = this.minRepetitionCount + ".." + (this.maxRepetitionCount == null ? "N" : this.maxRepetitionCount);
37 // TODO: get font from CSS tag.
38 const fontInfo = getFontInfo(this.cardinalitiesText, rrDiagramToSVG.cssLoopCardinalitiesTextClass);
39 this.fontYOffset = fontInfo.descent;
40 this.cardinalitiesWidth = fontInfo.textWidth + 2;
41 }
42 this.rrElement.computeLayoutInfo(rrDiagramToSVG);
43 const layoutInfo1 = this.rrElement.getLayoutInfo();
44 let width = layoutInfo1.getWidth();
45 let height = layoutInfo1.getHeight();
46 let connectorOffset = layoutInfo1.getConnectorOffset();
47 if (this.loopElement != null) {
48 this.loopElement.computeLayoutInfo(rrDiagramToSVG);
49 const layoutInfo2 = this.loopElement.getLayoutInfo();
50 width = Math.max(width, layoutInfo2.getWidth());
51 const height2 = layoutInfo2.getHeight();
52 height += 5 + height2;
53 connectorOffset += 5 + height2;
54 } else {
55 height += 15;
56 connectorOffset += 15;
57 }
58 width += 20 + 20 + this.cardinalitiesWidth;
59 this.setLayoutInfo(new LayoutInfo(width, height, connectorOffset));
60 }
61
62 toSVG(rrDiagramToSVG, xOffset, yOffset, svgContent) {
63 const layoutInfo1 = this.rrElement.getLayoutInfo();
64 const width1 = layoutInfo1.getWidth();
65 let maxWidth = width1;
66 let yOffset2 = yOffset;
67 const layoutInfo = this.getLayoutInfo();
68 const connectorOffset = layoutInfo.getConnectorOffset();
69 let y1 = yOffset;
70 let loopOffset = 0;
71 let loopWidth = 0;
72 if (this.loopElement != null) {
73 const layoutInfo2 = this.loopElement.getLayoutInfo();
74 loopWidth = layoutInfo2.getWidth();
75 maxWidth = Math.max(maxWidth, loopWidth);
76 loopOffset = xOffset + 20 + Math.floor((maxWidth - loopWidth) / 2);
77 yOffset2 += 5 + layoutInfo2.getHeight();
78 y1 += layoutInfo2.getConnectorOffset();
79 } else {
80 yOffset2 += 15;
81 y1 += 5;
82 }
83 const x1 = xOffset + 10;
84 const x2 = xOffset + 20 + maxWidth + 10 + this.cardinalitiesWidth;
85 const y2 = yOffset + connectorOffset;
86 svgContent.addLineConnector(x1 - 10, y2, x1 + 10 + Math.floor((maxWidth - width1) / 2), y2);
87 let loopPathStartX = x1 + 5;
88 svgContent.addPathConnector(x1 + 5, y2, "q-5 0-5-5", x1, y2 - 5);
89 svgContent.addLineConnector(x1, y2 - 5, x1, y1 + 5);
90 svgContent.addPathConnector(x1, y1 + 5, "q0-5 5-5", x1 + 5, y1);
91 if (this.loopElement != null) {
92 svgContent.addLineConnector(x1 + 5, y1, loopOffset, y1);
93 this.loopElement.toSVG(rrDiagramToSVG, loopOffset, yOffset, svgContent);
94 loopPathStartX = loopOffset + loopWidth;
95 }
96 svgContent.addLineConnector(loopPathStartX, y1, x2 - 5, y1);
97 svgContent.addPathConnector(x2 - 5, y1, "q5 0 5 5", x2, y1 + 5);
98 svgContent.addLineConnector(x2, y1 + 5, x2, y2 - 5);
99 svgContent.addPathConnector(x2, y2 - 5, "q0 5-5 5", x2 - 5, y2);
100 if (this.cardinalitiesText != null) {
101 svgContent.addElement("<text class=\"" + escapeXml(rrDiagramToSVG.cssLoopCardinalitiesTextClass) + "\" x=\"" + (x2 - this.cardinalitiesWidth) + "\" y=\"" + (y2 - this.fontYOffset - 5) + "\">" + escapeXml(this.cardinalitiesText) + "</text>");
102 }
103 this.rrElement.toSVG(rrDiagramToSVG, xOffset + 20 + Math.floor((maxWidth - width1) / 2), yOffset2, svgContent);
104 svgContent.addLineConnector(x2 - this.cardinalitiesWidth - 10 - Math.floor((maxWidth - width1) / 2), y2, xOffset + layoutInfo.getWidth(), y2);
105 }
106
107}
\No newline at end of file