1 | import RRElement from './rrelement';
|
2 | import RRDiagramToSVG from './rrdiagramtosvg';
|
3 | import LayoutInfo from './layoutinfo';
|
4 | import { escapeXml, getFontInfo } from '../utils/utils';
|
5 |
|
6 | export default class RRLoop extends RRElement {
|
7 |
|
8 | |
9 |
|
10 |
|
11 |
|
12 |
|
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 |
|
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 |