diff --git a/pom.xml b/pom.xml index b2f69ff48..6b4f66779 100644 --- a/pom.xml +++ b/pom.xml @@ -30,13 +30,12 @@ Script Author: Julien Eluard --> - + 4.0.0 net.sourceforge.plantuml plantuml - 1.2020.16-SNAPSHOT + 1.2020.18-SNAPSHOT jar PlantUML diff --git a/src/net/sourceforge/plantuml/StdrptNull.java b/src/net/sourceforge/plantuml/StdrptNull.java index d5e780424..e8535ea24 100644 --- a/src/net/sourceforge/plantuml/StdrptNull.java +++ b/src/net/sourceforge/plantuml/StdrptNull.java @@ -55,7 +55,7 @@ public class StdrptNull implements Stdrpt { } public void errorLine(int lineError, File file) { - Log.error("Error line " + lineError + " in file: " + file.getPath()); + Log.error("Error line " + (lineError + 1) + " in file: " + file.getPath()); } } diff --git a/src/net/sourceforge/plantuml/StdrptPipe0.java b/src/net/sourceforge/plantuml/StdrptPipe0.java index 90bffcfe4..cf034be52 100644 --- a/src/net/sourceforge/plantuml/StdrptPipe0.java +++ b/src/net/sourceforge/plantuml/StdrptPipe0.java @@ -65,7 +65,7 @@ public class StdrptPipe0 implements Stdrpt { } public void errorLine(int lineError, File file) { - Log.error("Error line " + lineError + " in file: " + file.getPath()); + Log.error("Error line " + (lineError + 1) + " in file: " + file.getPath()); } } diff --git a/src/net/sourceforge/plantuml/StdrptV1.java b/src/net/sourceforge/plantuml/StdrptV1.java index 7eb67cd92..4c9a30fdd 100644 --- a/src/net/sourceforge/plantuml/StdrptV1.java +++ b/src/net/sourceforge/plantuml/StdrptV1.java @@ -55,7 +55,7 @@ public class StdrptV1 implements Stdrpt { } public void errorLine(int lineError, File file) { - Log.error("Error line " + lineError + " in file: " + file.getPath()); + Log.error("Error line " + (lineError + 1) + " in file: " + file.getPath()); } private void out(final PrintStream output, final PSystemError err) { @@ -64,7 +64,7 @@ public class StdrptV1 implements Stdrpt { output.println("status=NO_DATA"); } else { output.println("status=ERROR"); - output.println("lineNumber=" + err.getLineLocation().getPosition()); + output.println("lineNumber=" + (err.getLineLocation().getPosition() + 1)); for (ErrorUml er : err.getErrorsUml()) { output.println("label=" + er.getError()); } diff --git a/src/net/sourceforge/plantuml/StdrptV2.java b/src/net/sourceforge/plantuml/StdrptV2.java index d54b6aa96..d1046173b 100644 --- a/src/net/sourceforge/plantuml/StdrptV2.java +++ b/src/net/sourceforge/plantuml/StdrptV2.java @@ -69,7 +69,7 @@ public class StdrptV2 implements Stdrpt { } else { line.append(err.getLineLocation().getDescription()); line.append(":"); - line.append(err.getLineLocation().getPosition()); + line.append(err.getLineLocation().getPosition() + 1); line.append(":"); line.append("error"); line.append(":"); diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileRepeat.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileRepeat.java index 45ca924c9..f61616c82 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileRepeat.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileRepeat.java @@ -111,16 +111,15 @@ class FtileRepeat extends AbstractFtile { } public static Ftile create(LinkRendering backRepeatLinkRendering, Swimlane swimlane, Swimlane swimlaneOut, - Ftile entry, Ftile repeat, Display test, Display yes, Display out, HColor borderColor, - HColor diamondColor, Rainbow arrowColor, Rainbow endRepeatLinkColor, ConditionStyle conditionStyle, - ISkinSimple spriteContainer, FontConfiguration fcDiamond, FontConfiguration fcArrow, Ftile backward, - boolean noOut) { + Ftile entry, Ftile repeat, Display test, Display yes, Display out, HColor borderColor, HColor diamondColor, + Rainbow arrowColor, Rainbow endRepeatLinkColor, ConditionStyle conditionStyle, ISkinSimple spriteContainer, + FontConfiguration fcDiamond, FontConfiguration fcArrow, Ftile backward, boolean noOut) { final FontConfiguration fontConfiguration1 = conditionStyle == ConditionStyle.INSIDE ? fcDiamond : fcArrow; - final TextBlock tbTest = (Display.isNull(test) || test.isWhite()) ? TextBlockUtils.empty(0, 0) : test.create( - fontConfiguration1, repeat.skinParam().getDefaultTextAlignment(HorizontalAlignment.LEFT), - spriteContainer); + final TextBlock tbTest = (Display.isNull(test) || test.isWhite()) ? TextBlockUtils.empty(0, 0) + : test.create(fontConfiguration1, repeat.skinParam().getDefaultTextAlignment(HorizontalAlignment.LEFT), + spriteContainer); final TextBlock yesTb = yes.create(fcArrow, HorizontalAlignment.LEFT, spriteContainer); final TextBlock outTb = out.create(fcArrow, HorizontalAlignment.LEFT, spriteContainer); @@ -146,7 +145,8 @@ class FtileRepeat extends AbstractFtile { .withEast(tbTest); result = new FtileRepeat(repeat, diamond1, diamond2, tbTest, backward); } else if (conditionStyle == ConditionStyle.FOO1) { - final Ftile diamond2 = new FtileDiamondFoo1(repeat.skinParam(), diamondColor, borderColor, swimlane, tbTest); + final Ftile diamond2 = new FtileDiamondFoo1(repeat.skinParam(), diamondColor, borderColor, swimlane, + tbTest); result = new FtileRepeat(repeat, diamond1, diamond2, TextBlockUtils.empty(0, 0), backward); } else { throw new IllegalStateException(); @@ -154,14 +154,14 @@ class FtileRepeat extends AbstractFtile { final List conns = new ArrayList(); final Display in1 = repeat.getInLinkRendering().getDisplay(); - final TextBlock tbin1 = in1 == null ? null : in1.create7(fcArrow, HorizontalAlignment.LEFT, spriteContainer, - CreoleMode.SIMPLE_LINE); + final TextBlock tbin1 = in1 == null ? null + : in1.create7(fcArrow, HorizontalAlignment.LEFT, spriteContainer, CreoleMode.SIMPLE_LINE); conns.add(result.new ConnectionIn(repeat.getInLinkRendering().getRainbow(arrowColor), tbin1)); final Display backLink1 = backRepeatLinkRendering.getDisplay(); - final TextBlock tbbackLink1 = backLink1 == null ? null : backLink1.create7(fcArrow, HorizontalAlignment.LEFT, - spriteContainer, CreoleMode.SIMPLE_LINE); - if (repeat.getSwimlaneIn() == swimlaneOut) { + final TextBlock tbbackLink1 = backLink1 == null ? null + : backLink1.create7(fcArrow, HorizontalAlignment.LEFT, spriteContainer, CreoleMode.SIMPLE_LINE); + if (repeat.getSwimlaneIn() == null || repeat.getSwimlaneIn() == swimlaneOut) { if (backward == null) { conns.add(result.new ConnectionBackSimple(backRepeatLinkRendering.getRainbow(arrowColor), tbbackLink1)); } else { @@ -176,8 +176,8 @@ class FtileRepeat extends AbstractFtile { } final Display out1 = repeat.getOutLinkRendering().getDisplay(); - final TextBlock tbout1 = out1 == null ? null : out1.create7(fcArrow, HorizontalAlignment.LEFT, spriteContainer, - CreoleMode.SIMPLE_LINE); + final TextBlock tbout1 = out1 == null ? null + : out1.create7(fcArrow, HorizontalAlignment.LEFT, spriteContainer, CreoleMode.SIMPLE_LINE); final Rainbow tmpColor = endRepeatLinkColor.withDefault(arrowColor); conns.add(result.new ConnectionOut(tmpColor, tbout1)); @@ -227,13 +227,13 @@ class FtileRepeat extends AbstractFtile { } private Point2D getP1(final StringBounder stringBounder) { - return getTranslateForRepeat(stringBounder).getTranslated( - getFtile1().calculateDimension(stringBounder).getPointOut()); + return getTranslateForRepeat(stringBounder) + .getTranslated(getFtile1().calculateDimension(stringBounder).getPointOut()); } private Point2D getP2(final StringBounder stringBounder) { - return getTranslateDiamond2(stringBounder).getTranslated( - getFtile2().calculateDimension(stringBounder).getPointIn()); + return getTranslateDiamond2(stringBounder) + .getTranslated(getFtile2().calculateDimension(stringBounder).getPointIn()); } public void drawU(UGraphic ug) { @@ -545,8 +545,8 @@ class FtileRepeat extends AbstractFtile { if (backward != null) { width += backward.calculateDimension(stringBounder).getWidth(); } - final double height = dimDiamond1.getHeight() + dimRepeat.getHeight() + dimDiamond2.getHeight() + 8 - * Diamond.diamondHalfSize; + final double height = dimDiamond1.getHeight() + dimRepeat.getHeight() + dimDiamond2.getHeight() + + 8 * Diamond.diamondHalfSize; return new Dimension2DDouble(width + 2 * Diamond.diamondHalfSize, height); } diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vertical/FtileBox.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vertical/FtileBox.java index e401a067a..79f263d5a 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vertical/FtileBox.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vertical/FtileBox.java @@ -170,12 +170,8 @@ public class FtileBox extends AbstractFtile { public static FtileBox createMindMap(StyleBuilder styleBuilder, ISkinParam skinParam, Display label, StyleSignature styleDefinition) { - Style style = null; - Style styleArrow = null; - if (SkinParam.USE_STYLES()) { - style = styleDefinition.getMergedStyle(styleBuilder); - styleArrow = style; - } + final Style style = styleDefinition.getMergedStyle(styleBuilder); + final Style styleArrow = style; return new FtileBox(skinParam, label, null, BoxStyle.PLAIN, style, styleArrow); } diff --git a/src/net/sourceforge/plantuml/classdiagram/command/CommandLinkClass.java b/src/net/sourceforge/plantuml/classdiagram/command/CommandLinkClass.java index ec18915ed..78b7547ca 100644 --- a/src/net/sourceforge/plantuml/classdiagram/command/CommandLinkClass.java +++ b/src/net/sourceforge/plantuml/classdiagram/command/CommandLinkClass.java @@ -160,15 +160,28 @@ final public class CommandLinkClass extends SingleLineCommand2 members = new ArrayList(); - // final LineBreakStrategy lineBreakStrategy = skinParam.wrapWidth(); for (ListIterator it = rawBody.listIterator(); it.hasNext();) { final CharSequence s2 = it.next(); if (s2 instanceof EmbeddedDiagram) { + if (members.size() > 0) { + blocks.add(decorate(stringBounder, new MethodsOrFieldsArea(members, fontParam, skinParam, align, + stereotype, entity, diagramType), separator, title)); + members = new ArrayList(); + } blocks.add(((EmbeddedDiagram) s2).asDraw(skinParam)); } else { final String s = s2.toString(); diff --git a/src/net/sourceforge/plantuml/cucadiagram/dot/Graphviz.java b/src/net/sourceforge/plantuml/cucadiagram/dot/Graphviz.java index 9073875a9..821a3a51b 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/dot/Graphviz.java +++ b/src/net/sourceforge/plantuml/cucadiagram/dot/Graphviz.java @@ -40,12 +40,14 @@ import java.io.OutputStream; public interface Graphviz { - ProcessState createFile3(OutputStream os); + public ProcessState createFile3(OutputStream os); - File getDotExe(); + public File getDotExe(); - String dotVersion(); + public String dotVersion(); - ExeState getExeState(); + public ExeState getExeState(); + + public boolean graphviz244onWindows(); } \ No newline at end of file diff --git a/src/net/sourceforge/plantuml/cucadiagram/dot/GraphvizLinux.java b/src/net/sourceforge/plantuml/cucadiagram/dot/GraphvizLinux.java index 1cb835a48..7924f1d24 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/dot/GraphvizLinux.java +++ b/src/net/sourceforge/plantuml/cucadiagram/dot/GraphvizLinux.java @@ -64,4 +64,8 @@ class GraphvizLinux extends AbstractGraphviz { return "dot"; } + public boolean graphviz244onWindows() { + return false; + } + } diff --git a/src/net/sourceforge/plantuml/cucadiagram/dot/GraphvizUtils.java b/src/net/sourceforge/plantuml/cucadiagram/dot/GraphvizUtils.java index 08fa4a4d0..e0f2a5467 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/dot/GraphvizUtils.java +++ b/src/net/sourceforge/plantuml/cucadiagram/dot/GraphvizUtils.java @@ -163,6 +163,15 @@ public class GraphvizUtils { return dotVersion; } + public static boolean graphviz244onWindows() { + try { + return create(null, "png").graphviz244onWindows(); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + public static int retrieveVersion(String s) { if (s == null) { return -1; diff --git a/src/net/sourceforge/plantuml/cucadiagram/dot/GraphvizWindows.java b/src/net/sourceforge/plantuml/cucadiagram/dot/GraphvizWindows.java index a5cbb556b..716aa9195 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/dot/GraphvizWindows.java +++ b/src/net/sourceforge/plantuml/cucadiagram/dot/GraphvizWindows.java @@ -58,6 +58,15 @@ class GraphvizWindows extends AbstractGraphviz { } } + public boolean graphviz244onWindows() { + try { + return GraphvizUtils.getDotVersion() == 244; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + private File specificDotExeSlow() { for (File tmp : new File("c:/").listFiles(new FileFilter() { public boolean accept(java.io.File pathname) { diff --git a/src/net/sourceforge/plantuml/cucadiagram/entity/EntityImpl.java b/src/net/sourceforge/plantuml/cucadiagram/entity/EntityImpl.java index 3f4cd8653..70789e7f9 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/entity/EntityImpl.java +++ b/src/net/sourceforge/plantuml/cucadiagram/entity/EntityImpl.java @@ -785,7 +785,6 @@ final public class EntityImpl implements ILeaf, IGroup { } public DisplayPositionned getLegend() { - checkGroup(); return legend; } @@ -800,6 +799,7 @@ final public class EntityImpl implements ILeaf, IGroup { public void setOriginalGroup(IGroup originalGroup) { this.originalGroup = originalGroup; + this.legend = originalGroup.getLegend(); } public IGroup getOriginalGroup() { diff --git a/src/net/sourceforge/plantuml/donors/PSystemDonors.java b/src/net/sourceforge/plantuml/donors/PSystemDonors.java index 71a2115d4..474608ec2 100644 --- a/src/net/sourceforge/plantuml/donors/PSystemDonors.java +++ b/src/net/sourceforge/plantuml/donors/PSystemDonors.java @@ -74,26 +74,26 @@ public class PSystemDonors extends AbstractPSystem { private static final int COLS = 6; private static final int FREE_LINES = 6; - public static final String DONORS = "6omC02mFkBap0p4nqLYNlhbPJVbOScQJ29Rd2SLXO15FTmFY3t3lzBZVI7yHNUdUDys8jcnDSPung1O4" - + "FPwQQuPjxks1q5RAY-189RY0513Vnibv7ploFdrIPKW9Ogde_il4xUdMSQ4oJbGZb0F5hGtlEsFpx3I-" - + "UFLeWZO2FmRsrVzTqygwUrKLXdHPrPWQTRh28Oo87E7_KRUfMzJ6oTIcqGCwbNC5DzMfYDFX0Gjea1Ku" - + "P6qTvwLPawgOI1Cfdjf8mIC6CxJdPFLvyaCVT7wf5z2bjRg6UEw0uZ5JUdJTDjg_xs3x5H8l4ixW2pOB" - + "pA6Kmtg2ukUc6nqd3n9QTv6DhRxoboSc6FpGGj_yeKYkz1uIsML8qN6fWGAFjp50CYQrQyBPeJy3gkh1" - + "5lqQXEfolt5thSFoL38R3RU0XOi5jO0QWlmFUi9dz9MNJEwvAM89UPh4Sza6rA-Izz4s5NqphoQ1yBRz" - + "qCpWLvcozP36bTSn_-hea7SDMRdwpLYZa4SmbvUv5CmlBL0_0Zqq9oA9hob_B2GWN5VgHUywDvtKBC8f" - + "7L8grkcNsF9QyWzTWSN6HNCwMABFng_BJObW2rsPL4DlQ5MbMUSJ9QcX_dx8ewNpNN1DbTgzGxGUQNEU" - + "_TzrIpD3SO2EJp4BkXOG2AjfrLTi88B3GfU7t0J81fHFarl-j7o8FV83WZUN2Bh2Hae7-FDDo4CEBin0" - + "bsvEKG7CdbBgISVjW8Sw7O9kHPLyUfcxVeP9oxPbOsQPjC5rky4O-J6TK9ouN-O2Zp2iKelcv6xj8-mI" - + "FCxBQLvrhy6yYcvx2-zf5w7zGmRy37D6H2fDL-nxsYNkeOx0BDg2fxhOdcu71m_TjU0KYrOmeqqxP0cO" - + "N4X6JRr5wKE3uUyWP1DsRohg2smDrwd1pOmqUBuqkQKcHtISjhCS6ri0lERY5Rk2mYb2j2qjcQjh2PCZ" - + "Laz2XlnEzGaibNLXQSEExQx6Cr6FWZoSzyYgexvDAMuBg3wc2VBIGfWpfCZ3rW8PM2lfMMu3x7vgnuAw" - + "pKyk77CelcsYxSODCKo1wIdS6maYCJgHbEWb9ea2lklZL-f5SnriV7TFAyP1qa8I0rL4brD_C5OQgbje" - + "6kir-h-jjPTbvy-_rv5DJXr-xsiAekSWBW0HNg2Zd404JmDVR_cYvAs4bQnG3Z9SkLRfQI1XmIvwvrVK" - + "WsL6zOuNoytAHIjl7whgkxjo39pr3IikyYdosPSOQUsb7bH1stUziLZa8FWFKMLI9bUZoMgCXCuWYtCt" - + "TfkfcEV69h1WTamcqFQhpvffF6NCVKTIQNW4oFTxP4WoUcXXJKthuaHWatH-trlOXaH6_mr6z0jgdJmU" - + "rKFxGUvkj0WqVEj36XT4Wk4Y-K21t9npea4ttoZ8YsgX32pjc67d25ReR_n7H27Xc6ry8CWn5yjfB-IG" - + "BMGVdusY5-GrXGQoi5YlPn8BfHmFf4WAvioMyJpI3jg6VRq3w1G5u_zz6y8b4yqloAmopzv8vjBFlJY3" - + "I8VxiqbichAr8Hls8osNRLsHspyNwR1J_vtOSRxp4PMuY55oBX4yeGIViVncv3Wkqt4m-Ka0"; + public static final String DONORS = "6peC02mFU3XMJbc44wzsvvsjcZxOY0eHBCyJYiF08fxk1iGVuDxfSR-H_YAwqhrlcX5jsPhYF6DGBGXw" + + "F3NN3DlSsmFFQdxwAlbcQdI5gJ0auIuaB6JOJp-fCgG4ptAz-MSKutlkfA5Pjis5a1j8l_2-CpRFJkEB" + + "LuycQ2FmOs1V_TyrhQoxLrLXI9TLZQbHfoiSmeZ84VuVTPkwHMsSJ6qQFQ1JELTmKvsAj0LlUgALD1Da" + + "NEiu7ysQLCL4caZnr4OA7ZcPeRqcgy-JAttG-QL-W3QjtJN4SmOKnqhfqVsrqVxp1DklaFYGS8POi5bW" + + "3fKSrYSeVcswqN6A8A5r5jdOwYktF371u8SM-kOFPNB5UqXabY55n-KA57WynW39dDIk2MU7RWPKrOCj" + + "-ZK8rULnu-uQX-MfP3OQRW4B5mjg1se8yZ_e4pwjx_p8v5o78fQGfqdSbcr0_LdoFkvDHT_CgqaWV6qV" + + "cXdYAbEr7jBOyZFMgqQ7t3LarUXVnXg57C6ytysbOFxH0laHwA4-4KdyBFkDXGI4QqlzqBlEJITN5k6K" + + "3YaLw_HRR7aj-K9NOB5nqQmEbkYxyUjoKoBOGbScbw47MbMvhVE9aj9G_x_8ew7hl-2QAhLxXsWzq-Oy" + + "-x_hbcQ6uW0Txs8MT2qW44RJgg_OG0I7XIuFkGcG0wXk9hVYPdaHU-G716yk6NI5ZPGEYEUNa9iSGfY6" + + "BjrSeWAOFQNKHSTjWOSwdO9kHPLyUfcxFgP9oxHjO-O-QOFdxGPZ5CTqGld4_JONk8LXbLeq9qzh7s6M" + + "u74-JlEg-npCg-Ysj_2UzY4qhsJ0hp1dHAJITELvfdt4tTGHc4LRy58NszrjSF3GNGjEiMW5CzgqGvQ0" + + "oOLarDAlA3ur6FuEGZPXhqr5li3MS9qQmin8WzTBarjgSaJ7QJhBiR4DmAilNh4hA9mYHDlIajcwbZ0r" + + "O_KaLCZlb4zWgQmBInisjhiApyGy2l9mtYEhB_LZIN5RGFMnJ92N5a9V8KKHjZV8m5X9ptAROFjJEnRK" + + "RJrouPX3yMqJRJTkY64AJ4_XVf4W4gCJIOLUOf8eu7j-_4gzQAw3ZU_iQSKuI5f88g2As7Bg1yPAG_L8" + + "JMEzHlzVQ-rksVdpxtLaarE7t_Cp1T5pK3J-ZHJ0KKuWWwU1hoPVbBoLi98LoY33bMkLdWOI5kp2ErTH" + + "3vOPrJjHB3Uh5gsYVQYgt-xACN0sDgouoASeLjzYbBMxUb05RT_rncAHW-0_H9L9cLoD9gin4Zg3BCxT" + + "sFTAnJmtDe45lMCoWRPVVNQQnat6dAz8AWsF0Fb-Zqn9MWyjhAbfNJuHs2ITwtiBsvH8wt_1Y7v1hPFZ" + + "KJsq3t9texj0mxS-f7P19XWkaayKoBTpJZHmyus2kgWMoiJIZXbsZc25_iP_H1GIZjd61u8iSx6iTaSE" + + "sKBsyTue-a1HKsWW6ulr-anYePJZWHH9mPhPCfv7sg1jsDSJW5CKpFVtDeHB9ffVa5dxUlP6CfT-xiKP" + + "H3gSdqrYqvIj3Jcm7scvREkEtFw-I8UT-k_4ZlETZwXR1n740Z7I25wF2UlcncxL5ZuZpwqQ7CTbEWuc" + "FuoJc9O0"; /* * Special thanks to our sponsors and donors: diff --git a/src/net/sourceforge/plantuml/graphic/TextBlockUtils.java b/src/net/sourceforge/plantuml/graphic/TextBlockUtils.java index 67762433e..95d1aac4e 100644 --- a/src/net/sourceforge/plantuml/graphic/TextBlockUtils.java +++ b/src/net/sourceforge/plantuml/graphic/TextBlockUtils.java @@ -163,6 +163,13 @@ public class TextBlockUtils { return new TextBlockVertical2(b1, b2, horizontalAlignment); } + public static TextBlock mergeTB(TextBlock b1, UImage image, HorizontalAlignment horizontalAlignment) { + if (b1 == EMPTY_TEXT_BLOCK) { + throw new IllegalArgumentException(); + } + return new TextBlockVertical2(b1, image, horizontalAlignment); + } + // public static TextBlockBackcolored mergeColoredTB(TextBlockBackcolored b1, // TextBlockBackcolored b2, // HorizontalAlignment horizontalAlignment) { diff --git a/src/net/sourceforge/plantuml/graphic/TextBlockVertical2.java b/src/net/sourceforge/plantuml/graphic/TextBlockVertical2.java index fcf765b1e..c15b78bde 100644 --- a/src/net/sourceforge/plantuml/graphic/TextBlockVertical2.java +++ b/src/net/sourceforge/plantuml/graphic/TextBlockVertical2.java @@ -45,6 +45,7 @@ import net.sourceforge.plantuml.svek.Ports; import net.sourceforge.plantuml.svek.TextBlockBackcolored; import net.sourceforge.plantuml.svek.WithPorts; import net.sourceforge.plantuml.ugraphic.UGraphic; +import net.sourceforge.plantuml.ugraphic.UImage; import net.sourceforge.plantuml.ugraphic.URectangle; import net.sourceforge.plantuml.ugraphic.UTranslate; import net.sourceforge.plantuml.ugraphic.color.HColor; @@ -60,6 +61,23 @@ public class TextBlockVertical2 extends AbstractTextBlock implements TextBlock, this.horizontalAlignment = horizontalAlignment; } + TextBlockVertical2(TextBlock b1, final UImage image, HorizontalAlignment horizontalAlignment) { + this(b1, convertImage(image), horizontalAlignment); + } + + static private AbstractTextBlock convertImage(final UImage image) { + return new AbstractTextBlock() { + + public void drawU(UGraphic ug) { + ug.draw(image); + } + + public Dimension2D calculateDimension(StringBounder stringBounder) { + return new Dimension2DDouble(image.getWidth(), image.getHeight()); + } + }; + } + public TextBlockVertical2(List all, HorizontalAlignment horizontalAlignment) { if (all.size() < 2) { throw new IllegalArgumentException(); diff --git a/src/net/sourceforge/plantuml/mindmap/FingerImpl.java b/src/net/sourceforge/plantuml/mindmap/FingerImpl.java index b510364e7..ca4e4200c 100644 --- a/src/net/sourceforge/plantuml/mindmap/FingerImpl.java +++ b/src/net/sourceforge/plantuml/mindmap/FingerImpl.java @@ -163,21 +163,13 @@ public class FingerImpl implements Finger, UDrawable { } private HColor getLinkColor() { - if (SkinParam.USE_STYLES()) { - final Style styleArrow = getDefaultStyleDefinitionArrow().getMergedStyle(styleBuilder); - return styleArrow.value(PName.LineColor).asColor(skinParam.getIHtmlColorSet()); - - } - return ColorParam.activityBorder.getDefaultValue(); + final Style styleArrow = getDefaultStyleDefinitionArrow().getMergedStyle(styleBuilder); + return styleArrow.value(PName.LineColor).asColor(skinParam.getIHtmlColorSet()); } private UStroke getUStroke() { - if (SkinParam.USE_STYLES()) { - final Style styleArrow = getDefaultStyleDefinitionArrow().getMergedStyle(styleBuilder); - return styleArrow.getStroke(); - - } - return new UStroke(); + final Style styleArrow = getDefaultStyleDefinitionArrow().getMergedStyle(styleBuilder); + return styleArrow.getStroke(); } private void drawLine(UGraphic ug, Point2D p1, Point2D p2) { @@ -239,22 +231,16 @@ public class FingerImpl implements Finger, UDrawable { if (drawPhalanx == false) { return TextBlockUtils.empty(0, 0); } - final UFont font; - if (SkinParam.USE_STYLES()) { - final Style styleNode = getDefaultStyleDefinitionNode().getMergedStyle(styleBuilder); - font = styleNode.getUFont(); - } else { - font = skinParam.getFont(null, false, FontParam.ACTIVITY); - } if (shape == IdeaShape.BOX) { - // final ISkinParam foo = new - // SkinParamBackcolored(Colors.empty().mute(skinParam), backColor); final ISkinParam foo = new SkinParamColors(skinParam, Colors.empty().add(ColorType.BACK, backColor)); final FtileBox box = FtileBox.createMindMap(styleBuilder, foo, label, getDefaultStyleDefinitionNode()); return TextBlockUtils.withMargin(box, 0, 0, marginTop, marginBottom); } - final TextBlock text = label.create(FontConfiguration.blackBlueTrue(font), HorizontalAlignment.LEFT, skinParam); + assert shape == IdeaShape.NONE; + final Style styleNode = getDefaultStyleDefinitionNode().getMergedStyle(styleBuilder); + final TextBlock text = label.create(styleNode.getFontConfiguration(skinParam.getIHtmlColorSet()), + HorizontalAlignment.LEFT, skinParam); if (direction == Direction.RIGHT) { return TextBlockUtils.withMargin(text, 3, 0, 1, 1); } diff --git a/src/net/sourceforge/plantuml/mindmap/MindMapDiagram.java b/src/net/sourceforge/plantuml/mindmap/MindMapDiagram.java index da358efc0..d7866f5ee 100644 --- a/src/net/sourceforge/plantuml/mindmap/MindMapDiagram.java +++ b/src/net/sourceforge/plantuml/mindmap/MindMapDiagram.java @@ -99,17 +99,11 @@ public class MindMapDiagram extends UmlDiagram { final int margin1; final int margin2; final HColor backgroundColor; - if (SkinParam.USE_STYLES()) { - margin1 = SkinParam.zeroMargin(10); - margin2 = SkinParam.zeroMargin(10); - final Style style = StyleSignature.of(SName.root, SName.document, SName.mindmapDiagram) - .getMergedStyle(skinParam.getCurrentStyleBuilder()); - backgroundColor = style.value(PName.BackGroundColor).asColor(skinParam.getIHtmlColorSet()); - } else { - margin1 = 10; - margin2 = 10; - backgroundColor = skinParam.getBackgroundColor(false); - } + margin1 = SkinParam.zeroMargin(10); + margin2 = SkinParam.zeroMargin(10); + final Style style = StyleSignature.of(SName.root, SName.document, SName.mindmapDiagram) + .getMergedStyle(skinParam.getCurrentStyleBuilder()); + backgroundColor = style.value(PName.BackGroundColor).asColor(skinParam.getIHtmlColorSet()); final ImageBuilder imageBuilder = ImageBuilder.buildBB(skinParam.getColorMapper(), skinParam.handwritten(), ClockwiseTopRightBottomLeft.margin1margin2(margin1, margin2), null, fileFormatOption.isWithMetadata() ? getMetadata() : null, "", dpiFactor, backgroundColor); diff --git a/src/net/sourceforge/plantuml/nwdiag/CommandLink.java b/src/net/sourceforge/plantuml/nwdiag/CommandLink.java index 359e0e757..3f401ac61 100644 --- a/src/net/sourceforge/plantuml/nwdiag/CommandLink.java +++ b/src/net/sourceforge/plantuml/nwdiag/CommandLink.java @@ -52,18 +52,20 @@ public class CommandLink extends SingleLineCommand2 { static IRegex getRegexConcat() { return RegexConcat.build(CommandLink.class.getName(), RegexLeaf.start(), // RegexLeaf.spaceZeroOrMore(), // - new RegexLeaf("NAME1", "[\\p{L}0-9_]+"), // + new RegexLeaf("NAME1", "([\\p{L}0-9_]+)"), // RegexLeaf.spaceZeroOrMore(), // new RegexLeaf("--"), // RegexLeaf.spaceZeroOrMore(), // - new RegexLeaf("NAME2", "[\\p{L}0-9_]+"), // + new RegexLeaf("NAME2", "([\\p{L}0-9_]+)"), // RegexLeaf.spaceZeroOrMore(), // new RegexLeaf(";?"), RegexLeaf.end()); } @Override protected CommandExecutionResult executeArg(NwDiagram diagram, LineLocation location, RegexResult arg) { - return diagram.link(); + final String name1 = arg.get("NAME1", 0); + final String name2 = arg.get("NAME2", 0); + return diagram.link(name1, name2); } } diff --git a/src/net/sourceforge/plantuml/nwdiag/CommandProperty.java b/src/net/sourceforge/plantuml/nwdiag/CommandProperty.java index 430020f6c..25bfe68aa 100644 --- a/src/net/sourceforge/plantuml/nwdiag/CommandProperty.java +++ b/src/net/sourceforge/plantuml/nwdiag/CommandProperty.java @@ -52,13 +52,13 @@ public class CommandProperty extends SingleLineCommand2 { static IRegex getRegexConcat() { return RegexConcat.build(CommandProperty.class.getName(), RegexLeaf.start(), // RegexLeaf.spaceZeroOrMore(), // - new RegexLeaf("NAME", "(address|color)"), // + new RegexLeaf("NAME", "(address|color|width)"), // RegexLeaf.spaceZeroOrMore(), // new RegexLeaf("="), // RegexLeaf.spaceZeroOrMore(), // - new RegexLeaf("\""), // - new RegexLeaf("VALUE", "(.*)"), // - new RegexLeaf("\""), // + new RegexLeaf("\"?"), // + new RegexLeaf("VALUE", "([^\"]*)"), // + new RegexLeaf("\"?"), // RegexLeaf.spaceZeroOrMore(), // new RegexLeaf(";?"), // RegexLeaf.end()); diff --git a/src/net/sourceforge/plantuml/nwdiag/DiagElement.java b/src/net/sourceforge/plantuml/nwdiag/DiagElement.java index 941156a02..1b4234146 100644 --- a/src/net/sourceforge/plantuml/nwdiag/DiagElement.java +++ b/src/net/sourceforge/plantuml/nwdiag/DiagElement.java @@ -60,6 +60,7 @@ public class DiagElement { private String description; private final Network mainNetwork; private final ISkinSimple spriteContainer; + private boolean hasItsOwnColumn = true; @Override public String toString() { @@ -126,4 +127,12 @@ public class DiagElement { } } + public void doNotHaveItsOwnColumn() { + this.hasItsOwnColumn = false; + } + + public final boolean hasItsOwnColumn() { + return hasItsOwnColumn; + } + } diff --git a/src/net/sourceforge/plantuml/nwdiag/GridTextBlockDecorated.java b/src/net/sourceforge/plantuml/nwdiag/GridTextBlockDecorated.java index cf10ca2fc..6b356bfc9 100644 --- a/src/net/sourceforge/plantuml/nwdiag/GridTextBlockDecorated.java +++ b/src/net/sourceforge/plantuml/nwdiag/GridTextBlockDecorated.java @@ -134,7 +134,7 @@ public class GridTextBlockDecorated extends GridTextBlockSimple { for (int i = 0; i < data.length; i++) { final Network network = getNetwork(i); double x = 0; - double xmin = -1; + double xmin = network.isFullWidth() ? 0 : -1; double xmax = 0; for (int j = 0; j < data[i].length; j++) { final boolean hline = isThereALink(j, network); @@ -142,10 +142,11 @@ public class GridTextBlockDecorated extends GridTextBlockSimple { xmin = x; } x += colWidth(stringBounder, j); - if (hline) { + if (hline || network.isFullWidth()) { xmax = x; } } + final URectangle rect = new URectangle(xmax - xmin, NETWORK_THIN); rect.setDeltaShadow(1.0); UGraphic ug2 = ug.apply(new UTranslate(xmin, y)); @@ -155,7 +156,9 @@ public class GridTextBlockDecorated extends GridTextBlockSimple { if (network != null) { pos.put(network, y); } - ug2.draw(rect); + if (network.isVisible()) { + ug2.draw(rect); + } y += lineHeight(stringBounder, i); } return pos; diff --git a/src/net/sourceforge/plantuml/nwdiag/LinkedElement.java b/src/net/sourceforge/plantuml/nwdiag/LinkedElement.java index a4bd8ee61..8e32bba66 100644 --- a/src/net/sourceforge/plantuml/nwdiag/LinkedElement.java +++ b/src/net/sourceforge/plantuml/nwdiag/LinkedElement.java @@ -35,6 +35,7 @@ package net.sourceforge.plantuml.nwdiag; import java.awt.geom.Dimension2D; +import java.util.Collections; import java.util.Map; import java.util.Map.Entry; import java.util.TreeSet; @@ -105,8 +106,15 @@ public class LinkedElement { final double xMiddle = width / 2; final TreeSet skip = new TreeSet(pos.values()); - new VerticalLine(ynet1 + GridTextBlockDecorated.NETWORK_THIN, ynet1 + alpha, skip) - .drawU(ug.apply(UTranslate.dx(xMiddle))); + if (element.hasItsOwnColumn()) { + if (element.getMainNetwork().isVisible()) { + new VerticalLine(ynet1 + GridTextBlockDecorated.NETWORK_THIN, ynet1 + alpha, skip) + .drawU(ug.apply(UTranslate.dx(xMiddle))); + } else { + new VerticalLine(ynet1, ynet1 + alpha, Collections.emptySet()) + .drawU(ug.apply(UTranslate.dx(xMiddle))); + } + } drawCenter(ug, link1(), xMiddle, ynet1 + alpha / 2); final double seven = 7.0; @@ -144,13 +152,17 @@ public class LinkedElement { } private void drawCenter(UGraphic ug, TextBlock block, double x, double y) { + if (block == null) { + return; + } final Dimension2D dim = block.calculateDimension(ug.getStringBounder()); block.drawU(ug.apply(new UTranslate(x - dim.getWidth() / 2, y - dim.getHeight() / 2))); } public Dimension2D naturalDimension(StringBounder stringBounder) { - final Dimension2D dim1 = link1().calculateDimension(stringBounder); + final Dimension2D dim1 = link1() == null ? new Dimension2DDouble(0, 0) + : link1().calculateDimension(stringBounder); final Dimension2D dimBox = box.calculateDimension(stringBounder); final Dimension2D dim2 = link2() == null ? new Dimension2DDouble(0, 0) : link2().calculateDimension(stringBounder); diff --git a/src/net/sourceforge/plantuml/nwdiag/Network.java b/src/net/sourceforge/plantuml/nwdiag/Network.java index bc430f197..a183c1aed 100644 --- a/src/net/sourceforge/plantuml/nwdiag/Network.java +++ b/src/net/sourceforge/plantuml/nwdiag/Network.java @@ -44,8 +44,9 @@ public class Network { private final String name; private final Map localElements = new LinkedHashMap(); private HColor color; - + private boolean visible = true; private String ownAdress; + private boolean fullWidth; @Override public String toString() { @@ -100,4 +101,20 @@ public class Network { this.color = color; } + public void goInvisible() { + this.visible = false; + } + + public final boolean isVisible() { + return visible; + } + + public void setFullWidth(boolean fullWidth) { + this.fullWidth = fullWidth; + } + + public final boolean isFullWidth() { + return fullWidth; + } + } diff --git a/src/net/sourceforge/plantuml/nwdiag/NwDiagram.java b/src/net/sourceforge/plantuml/nwdiag/NwDiagram.java index 044384e93..ea6b4bb9f 100644 --- a/src/net/sourceforge/plantuml/nwdiag/NwDiagram.java +++ b/src/net/sourceforge/plantuml/nwdiag/NwDiagram.java @@ -124,6 +124,45 @@ public class NwDiagram extends UmlDiagram { return CommandExecutionResult.ok(); } + public CommandExecutionResult link(String name1, String name2) { + if (initDone == false) { + return error(); + } + if (currentNetwork() == null) { + final Network network1 = new Network(name1); + networks.add(network1); + addElement(null, name2, toSet(null)); + return CommandExecutionResult.ok(); + } else { + final DiagElement already = elements.get(name1); + final Network network1 = new Network(""); + network1.goInvisible(); + networks.add(network1); + if (already != null) { + currentNetwork().addElement(already, toSet(null)); + } + addElement(null, name2, toSet(null)); + return CommandExecutionResult.ok(); + } + } + + private DiagElement addElement(DiagElement element, String name, Map props) { + if (element == null) { + element = new DiagElement(name, currentNetwork(), this.getSkinParam()); + elements.put(name, element); + } + currentNetwork().addElement(element, props); + final String description = props.get("description"); + if (description != null) { + element.setDescription(description); + } + final String shape = props.get("shape"); + if (shape != null) { + element.setShape(shape); + } + return element; + } + public CommandExecutionResult endSomething() { if (initDone == false) { return error(); @@ -139,22 +178,17 @@ public class NwDiagram extends UmlDiagram { if (currentGroup != null) { currentGroup.addElement(name); } - if (currentNetwork() != null) { - DiagElement element = elements.get(name); - if (element == null) { - element = new DiagElement(name, currentNetwork(), this.getSkinParam()); - elements.put(name, element); + if (currentNetwork() == null) { + if (currentGroup == null) { + final Network network1 = new Network(""); + network1.goInvisible(); + networks.add(network1); + final DiagElement first = addElement(null, name, toSet(definition)); + first.doNotHaveItsOwnColumn(); } - final Map props = toSet(definition); - final String description = props.get("description"); - if (description != null) { - element.setDescription(description); - } - final String shape = props.get("shape"); - if (shape != null) { - element.setShape(shape); - } - currentNetwork().addElement(element, props); + } else { + final DiagElement element = elements.get(name); + addElement(element, name, toSet(definition)); } return CommandExecutionResult.ok(); } @@ -303,7 +337,8 @@ public class NwDiagram extends UmlDiagram { } private GridTextBlockDecorated buildGrid() { - final GridTextBlockDecorated grid = new GridTextBlockDecorated(networks.size(), elements.size(), groups, networks); + final GridTextBlockDecorated grid = new GridTextBlockDecorated(networks.size(), elements.size(), groups, + networks); for (int i = 0; i < networks.size(); i++) { final Network current = networks.get(i); @@ -315,7 +350,9 @@ public class NwDiagram extends UmlDiagram { final Map conns = getLinks(element); grid.add(i, j, element.asTextBlock(conns, next)); } - j++; + if (element.hasItsOwnColumn()) { + j++; + } } } return grid; @@ -328,6 +365,9 @@ public class NwDiagram extends UmlDiagram { if ("address".equalsIgnoreCase(property) && currentNetwork() != null) { currentNetwork().setOwnAdress(value); } + if ("width".equalsIgnoreCase(property) && currentNetwork() != null) { + currentNetwork().setFullWidth("full".equalsIgnoreCase(value)); + } if ("color".equalsIgnoreCase(property)) { final HColor color = GridTextBlockDecorated.colors.getColorIfValid(value); if (currentGroup != null) { @@ -339,11 +379,4 @@ public class NwDiagram extends UmlDiagram { return CommandExecutionResult.ok(); } - public CommandExecutionResult link() { - if (initDone == false) { - return error(); - } - return CommandExecutionResult.ok(); - } - } diff --git a/src/net/sourceforge/plantuml/nwdiag/VerticalLine.java b/src/net/sourceforge/plantuml/nwdiag/VerticalLine.java index a983cfb57..775083361 100644 --- a/src/net/sourceforge/plantuml/nwdiag/VerticalLine.java +++ b/src/net/sourceforge/plantuml/nwdiag/VerticalLine.java @@ -34,29 +34,31 @@ */ package net.sourceforge.plantuml.nwdiag; -import java.util.TreeSet; +import java.util.Set; import net.sourceforge.plantuml.graphic.UDrawable; -import net.sourceforge.plantuml.ugraphic.UEllipse; import net.sourceforge.plantuml.ugraphic.UGraphic; -import net.sourceforge.plantuml.ugraphic.ULine; -import net.sourceforge.plantuml.ugraphic.UTranslate; +import net.sourceforge.plantuml.ugraphic.UPath; +import net.sourceforge.plantuml.ugraphic.color.HColorNone; public class VerticalLine implements UDrawable { private final double y1; private final double y2; - private final TreeSet skip; + private final Set skip; - public VerticalLine(double y1, double y2, TreeSet skip) { + public VerticalLine(double y1, double y2, Set skip) { this.y1 = Math.min(y1, y2); this.y2 = Math.max(y1, y2); this.skip = skip; } public void drawU(UGraphic ug) { + ug = ug.apply(new HColorNone().bg()); boolean drawn = false; double current = y1; + UPath path = new UPath(); + path.moveTo(0, current); for (Double step : skip) { if (step < y1) { continue; @@ -64,33 +66,27 @@ public class VerticalLine implements UDrawable { assert step >= y1; drawn = true; if (step == y2) { - drawVLine(ug, current, y2); + path.lineTo(0, y2); } else { - drawVLine(ug, current, Math.min(y2, step - 3)); + path.lineTo(0, Math.min(y2, step - 3)); if (y2 > step) { - drawArc(ug, step - 3); + path.arcTo(4, 4, 0, 0, 1, 0, step + 9); + continue; } } + ug.draw(path); + path = new UPath(); current = step + 9; + path.moveTo(0, current); if (current >= y2) { break; } } if (drawn == false) { - drawVLine(ug, y1, y2); + path.lineTo(0, y2); + ug.draw(path); } } - private void drawArc(UGraphic ug, double y) { - final UEllipse arc = new UEllipse(11, 11, 90, -180); - ug.apply(new UTranslate(-5, y)).draw(arc); - - } - - private void drawVLine(UGraphic ug, double start, double end) { - final ULine line = ULine.vline(end - start); - ug.apply(UTranslate.dy(start)).draw(line); - } - } diff --git a/src/net/sourceforge/plantuml/nwdiag/VerticalLine2.java b/src/net/sourceforge/plantuml/nwdiag/VerticalLine2.java new file mode 100644 index 000000000..95411ee7a --- /dev/null +++ b/src/net/sourceforge/plantuml/nwdiag/VerticalLine2.java @@ -0,0 +1,97 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * http://plantuml.com/patreon (only 1$ per month!) + * http://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PlantUML distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + */ +package net.sourceforge.plantuml.nwdiag; + +import java.util.Set; + +import net.sourceforge.plantuml.graphic.UDrawable; +import net.sourceforge.plantuml.ugraphic.UEllipse; +import net.sourceforge.plantuml.ugraphic.UGraphic; +import net.sourceforge.plantuml.ugraphic.ULine; +import net.sourceforge.plantuml.ugraphic.UTranslate; +import net.sourceforge.plantuml.ugraphic.color.HColorNone; + +public class VerticalLine2 implements UDrawable { + + private final double y1; + private final double y2; + private final Set skip; + + public VerticalLine2(double y1, double y2, Set skip) { + this.y1 = Math.min(y1, y2); + this.y2 = Math.max(y1, y2); + this.skip = skip; + } + + public void drawU(UGraphic ug) { + boolean drawn = false; + double current = y1; + for (Double step : skip) { + if (step < y1) { + continue; + } + assert step >= y1; + drawn = true; + if (step == y2) { + drawVLine(ug, current, y2); + } else { + drawVLine(ug, current, Math.min(y2, step - 3)); + if (y2 > step) { + drawArc(ug, step - 3); + } + } + current = step + 9; + if (current >= y2) { + break; + } + } + if (drawn == false) { + drawVLine(ug, y1, y2); + } + + } + + private void drawArc(UGraphic ug, double y) { + final UEllipse arc = new UEllipse(11, 11, 90, -180); + ug.apply(new HColorNone().bg()).apply(new UTranslate(-5, y)).draw(arc); + + } + + private void drawVLine(UGraphic ug, double start, double end) { + final ULine line = ULine.vline(end - start); + ug.apply(UTranslate.dy(start)).draw(line); + } + +} diff --git a/src/net/sourceforge/plantuml/project/GanttArrow.java b/src/net/sourceforge/plantuml/project/GanttArrow.java index fda24c1c9..bd8ac7303 100644 --- a/src/net/sourceforge/plantuml/project/GanttArrow.java +++ b/src/net/sourceforge/plantuml/project/GanttArrow.java @@ -98,13 +98,13 @@ public class GanttArrow implements UDrawable { ug = ug.apply(color.bg()).apply(color).apply(style.getStroke3(new UStroke(1.5))); double x1 = getX(source.withDelta(0), atStart); - double y1 = getSource().getY(atStart); + double y1 = getSource().getY(atStart).getValue(); final double x2 = getX(dest, atEnd.getInv()); - final double y2 = getDestination().getY(atEnd); + final double y2 = getDestination().getY(atEnd).getValue(); if (atStart == Direction.DOWN && y2 < y1) { - y1 = getSource().getY(atStart.getInv()); + y1 = getSource().getY(atStart.getInv()).getValue(); } if (this.atStart == Direction.DOWN && this.atEnd == Direction.RIGHT) { @@ -115,7 +115,7 @@ public class GanttArrow implements UDrawable { drawLine(ug, x1, y1, x1, y2, x2, y2); } else { x1 = getX(source.withDelta(0), Direction.RIGHT); - y1 = getSource().getY(Direction.RIGHT); + y1 = getSource().getY(Direction.RIGHT).getValue(); drawLine(ug, x1, y1, x1 + 6, y1, x1 + 6, y1 + 8, x2 - 8, y1 + 8, x2 - 8, y2, x2, y2); } } else if (this.atStart == Direction.RIGHT && this.atEnd == Direction.LEFT) { diff --git a/src/net/sourceforge/plantuml/project/GanttDiagram.java b/src/net/sourceforge/plantuml/project/GanttDiagram.java index a2a4bd4e5..d4a8a1fc9 100644 --- a/src/net/sourceforge/plantuml/project/GanttDiagram.java +++ b/src/net/sourceforge/plantuml/project/GanttDiagram.java @@ -74,6 +74,7 @@ import net.sourceforge.plantuml.project.core.TaskCode; import net.sourceforge.plantuml.project.core.TaskImpl; import net.sourceforge.plantuml.project.core.TaskInstant; import net.sourceforge.plantuml.project.core.TaskSeparator; +import net.sourceforge.plantuml.project.draw.FingerPrint; import net.sourceforge.plantuml.project.draw.ResourceDraw; import net.sourceforge.plantuml.project.draw.TaskDraw; import net.sourceforge.plantuml.project.draw.TaskDrawDiamond; @@ -84,6 +85,7 @@ import net.sourceforge.plantuml.project.draw.TimeHeaderDaily; import net.sourceforge.plantuml.project.draw.TimeHeaderMonthly; import net.sourceforge.plantuml.project.draw.TimeHeaderSimple; import net.sourceforge.plantuml.project.draw.TimeHeaderWeekly; +import net.sourceforge.plantuml.project.draw.YMovable; import net.sourceforge.plantuml.project.lang.CenterBorderColor; import net.sourceforge.plantuml.project.time.Day; import net.sourceforge.plantuml.project.time.DayOfWeek; @@ -183,7 +185,7 @@ public class GanttDiagram extends TitledDiagram implements ToTaskDraw { final ImageBuilder imageBuilder = ImageBuilder.buildB(new ColorMapperIdentity(), false, ClockwiseTopRightBottomLeft.margin1margin2(margin1, margin2), null, getMetadata(), "", dpiFactor, null); - TextBlock result = getTextBlock(); + TextBlock result = getTextBlock(fileFormatOption.getDefaultStringBounder()); result = new AnnotatedWorker(this, getSkinParam(), fileFormatOption.getDefaultStringBounder()).addAdd(result); imageBuilder.setUDrawable(result); @@ -207,7 +209,7 @@ public class GanttDiagram extends TitledDiagram implements ToTaskDraw { return false; } - private TextBlockBackcolored getTextBlock() { + private TextBlockBackcolored getTextBlock(StringBounder stringBounder) { if (printStart == null) { initMinMax(); } else { @@ -226,7 +228,7 @@ public class GanttDiagram extends TitledDiagram implements ToTaskDraw { timeHeader = new TimeHeaderDaily(calendar, min, max, getDefaultPlan(), colorDays, nameDays, printStart, printEnd); } - initTaskAndResourceDraws(timeHeader.getTimeScale(), timeHeader.getFullHeaderHeight()); + initTaskAndResourceDraws(timeHeader.getTimeScale(), timeHeader.getFullHeaderHeight(), stringBounder); return new TextBlockBackcolored() { public void drawU(UGraphic ug) { @@ -260,7 +262,7 @@ public class GanttDiagram extends TitledDiagram implements ToTaskDraw { private void drawTasksRect(UGraphic ug) { for (Task task : tasks.values()) { final TaskDraw draw = draws.get(task); - final UTranslate move = UTranslate.dy(draw.getY()); + final UTranslate move = UTranslate.dy(draw.getY().getValue()); draw.drawU(ug.apply(move)); } } @@ -280,7 +282,7 @@ public class GanttDiagram extends TitledDiagram implements ToTaskDraw { continue; } final TaskDraw draw = draws.get(task); - final UTranslate move = UTranslate.dy(draw.getY()); + final UTranslate move = UTranslate.dy(draw.getY().getValue()); draw.drawTitle(ug1.apply(move)); } } @@ -330,20 +332,8 @@ public class GanttDiagram extends TitledDiagram implements ToTaskDraw { private final Map draws = new LinkedHashMap(); - private void initTaskAndResourceDraws(TimeScale timeScale, double headerHeight) { - double y = headerHeight; -// for (Task task : tasks.values()) { -// if (task instanceof TaskImpl) { -// final TaskImpl taskImpl = (TaskImpl) task; -// if (taskImpl.getRow() != null) { -// continue; -// } -// } -// task.setY5757(y); -// y += task.getHeight(); -// -// } -// double y2 = headerHeight; + private void initTaskAndResourceDraws(TimeScale timeScale, double headerHeight, StringBounder stringBounder) { + YMovable y = new YMovable(headerHeight); for (Task task : tasks.values()) { final TaskDraw draw; if (task instanceof TaskSeparator) { @@ -362,17 +352,60 @@ public class GanttDiagram extends TitledDiagram implements ToTaskDraw { draw.setColorsAndCompletion(tmp.getColors(), tmp.getCompletion(), tmp.getUrl(), tmp.getNote()); } if (task.getRow() == null) { - y += draw.getHeight(); + y = y.add(draw.getHeightTask()); } draws.put(task, draw); } + magicPush(stringBounder); + y = lastY(stringBounder); for (Resource res : resources.values()) { final ResourceDraw draw = new ResourceDraw(this, res, timeScale, y, min, max); res.setTaskDraw(draw); - y += draw.getHeight(); + y = y.add(draw.getHeight()); } - this.totalHeight = y; + this.totalHeight = y.getValue(); + } + + private YMovable lastY(StringBounder stringBounder) { + TaskDraw last = null; + for (TaskDraw td : draws.values()) { + last = td; + } + return last.getY().add(last.getHeightMax(stringBounder)); + } + + private boolean magicPush(StringBounder stringBounder) { + final List notes = new ArrayList(); + for (TaskDraw td : draws.values()) { + final FingerPrint taskPrint = td.getFingerPrint(); + for (FingerPrint note : notes) { + final double deltaY = note.overlap(taskPrint); + if (deltaY > 0) { + pushIncluding(td, deltaY); + return true; + } + } + + final FingerPrint fingerPrintNote = td.getFingerPrintNote(stringBounder); + if (fingerPrintNote != null) { + notes.add(fingerPrintNote); + } + } + return false; + } + + private void pushIncluding(TaskDraw first, double deltaY) { + boolean skipping = true; + for (TaskDraw td : draws.values()) { + if (td == first) + skipping = false; + if (skipping) + continue; + td.getY().pushMe(deltaY + 1); + + } + } private Wink getStart(final TaskImpl tmp) { diff --git a/src/net/sourceforge/plantuml/project/core2/Hole.java b/src/net/sourceforge/plantuml/project/core2/Hole.java new file mode 100644 index 000000000..264886dc9 --- /dev/null +++ b/src/net/sourceforge/plantuml/project/core2/Hole.java @@ -0,0 +1,63 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * http://plantuml.com/patreon (only 1$ per month!) + * http://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PlantUML distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.project.core2; + +public class Hole implements Comparable { + + private final long start; + private final long end; + + public Hole(long start, long end) { + if (end <= start) { + throw new IllegalArgumentException(); + } + this.start = start; + this.end = end; + } + + public final long getStart() { + return start; + } + + public final long getEnd() { + return end; + } + + public int compareTo(Hole other) { + return Long.compare(this.start, other.start); + } + +} diff --git a/src/net/sourceforge/plantuml/project/core2/HolesList.java b/src/net/sourceforge/plantuml/project/core2/HolesList.java new file mode 100644 index 000000000..c76bb23af --- /dev/null +++ b/src/net/sourceforge/plantuml/project/core2/HolesList.java @@ -0,0 +1,69 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * http://plantuml.com/patreon (only 1$ per month!) + * http://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PlantUML distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.project.core2; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +public class HolesList implements Iterable { + + private final List list = new ArrayList(); + + public void add(Hole tooth) { + list.add(tooth); + Collections.sort(list); + } + + @Override + public String toString() { + return list.toString(); + } + + public long getStart() { + return list.get(0).getStart(); + } + + public long getEnd() { + return list.get(list.size() - 1).getEnd(); + } + + public Iterator iterator() { + return Collections.unmodifiableList(list).iterator(); + } + +} diff --git a/src/net/sourceforge/plantuml/project/core2/IteratorSlice.java b/src/net/sourceforge/plantuml/project/core2/IteratorSlice.java new file mode 100644 index 000000000..a9a6a4006 --- /dev/null +++ b/src/net/sourceforge/plantuml/project/core2/IteratorSlice.java @@ -0,0 +1,42 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * http://plantuml.com/patreon (only 1$ per month!) + * http://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PlantUML distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.project.core2; + +public interface IteratorSlice { + + public Slice next(); + +} diff --git a/src/net/sourceforge/plantuml/project/core2/ListIteratorSlice.java b/src/net/sourceforge/plantuml/project/core2/ListIteratorSlice.java new file mode 100644 index 000000000..fe282bf0a --- /dev/null +++ b/src/net/sourceforge/plantuml/project/core2/ListIteratorSlice.java @@ -0,0 +1,57 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * http://plantuml.com/patreon (only 1$ per month!) + * http://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PlantUML distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.project.core2; + +import java.util.List; + +public class ListIteratorSlice implements IteratorSlice { + + private final List data; + private int pos = -1; + + public ListIteratorSlice(List data) { + this.data = data; + } + + public Slice next() { + if (pos + 1 < data.size()) { + pos++; + return data.get(pos); + } + return null; + } + +} diff --git a/src/net/sourceforge/plantuml/project/core2/Slice.java b/src/net/sourceforge/plantuml/project/core2/Slice.java new file mode 100644 index 000000000..fe2237a65 --- /dev/null +++ b/src/net/sourceforge/plantuml/project/core2/Slice.java @@ -0,0 +1,96 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * http://plantuml.com/patreon (only 1$ per month!) + * http://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PlantUML distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.project.core2; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import net.sourceforge.plantuml.project.time.DayOfWeek; + +public class Slice { + + private final long start; + private final long end; + private final int workLoad; + + public Slice(long start, long end, int workLoad) { + if (end <= start) { + throw new IllegalArgumentException(); + } + this.start = start; + this.end = end; + this.workLoad = workLoad; + } + + @Override + public String toString() { + return DayOfWeek.timeToString(start) + " --> " + DayOfWeek.timeToString(end) + " <" + workLoad + ">"; + } + + public boolean containsTime(long time) { + return time >= start && time <= end; + } + + public final long getStart() { + return start; + } + + public final long getEnd() { + return end; + } + + public final int getWorkLoad() { + return workLoad; + } + + public List intersectWith(HolesList holes) { + final List result = new ArrayList(); + for (Hole hole : holes) { + final Slice inter = intersectWith(hole); + + } + return Collections.unmodifiableList(result); + } + + private Slice intersectWith(Hole hole) { + if (hole.getEnd() <= start || hole.getStart() <= end) { + return null; + } + return new Slice(Math.max(start, hole.getStart()), Math.min(end, hole.getEnd()), workLoad); + } + +} diff --git a/src/net/sourceforge/plantuml/project/core2/Solver1.java b/src/net/sourceforge/plantuml/project/core2/Solver1.java new file mode 100644 index 000000000..d5b9d92a8 --- /dev/null +++ b/src/net/sourceforge/plantuml/project/core2/Solver1.java @@ -0,0 +1,69 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * http://plantuml.com/patreon (only 1$ per month!) + * http://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PlantUML distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.project.core2; + +public class Solver1 { + + private final WorkLoad workLoad; + + public Solver1(WorkLoad workLoad) { + this.workLoad = workLoad; + } + + public TeethRange solveEnd(long start, long fullLoad) { + + final IteratorSlice slices = workLoad.slices(start); + final TeethRange result = new TeethRange(); + + while (true) { + final Slice current = slices.next(); + assert current.getEnd() >= start; + start = Math.max(start, current.getStart()); + + final long sliceLoad = 1L * (current.getEnd() - start) * current.getWorkLoad(); + if (sliceLoad >= fullLoad) { + final long theoricalEnd = start + fullLoad / current.getWorkLoad(); + result.add(new Tooth(start, theoricalEnd, fullLoad)); + return result; + } + assert sliceLoad < fullLoad; + result.add(new Tooth(start, current.getEnd(), sliceLoad)); + fullLoad -= sliceLoad; + } + + } + +} diff --git a/src/net/sourceforge/plantuml/project/core2/TeethRange.java b/src/net/sourceforge/plantuml/project/core2/TeethRange.java new file mode 100644 index 000000000..c7af4534d --- /dev/null +++ b/src/net/sourceforge/plantuml/project/core2/TeethRange.java @@ -0,0 +1,72 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * http://plantuml.com/patreon (only 1$ per month!) + * http://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PlantUML distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.project.core2; + +import java.util.ArrayList; +import java.util.List; + +public class TeethRange { + + private final List list = new ArrayList(); + + public void add(Tooth tooth) { + if (list.size() > 0) { + final Tooth last = list.get(list.size() - 1); + if (tooth.getStart() <= last.getEnd()) { + throw new IllegalArgumentException(); + } + } + list.add(tooth); + } + + @Override + public String toString() { + return list.toString(); + } + + public long getStart() { + return list.get(0).getStart(); + } + + public long getEnd() { + return list.get(list.size() - 1).getEnd(); + } + + public long getDuration() { + return getEnd() - getStart(); + } + +} diff --git a/src/net/sourceforge/plantuml/project/core2/Tooth.java b/src/net/sourceforge/plantuml/project/core2/Tooth.java new file mode 100644 index 000000000..f7ee060b3 --- /dev/null +++ b/src/net/sourceforge/plantuml/project/core2/Tooth.java @@ -0,0 +1,72 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * http://plantuml.com/patreon (only 1$ per month!) + * http://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PlantUML distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.project.core2; + +import net.sourceforge.plantuml.project.time.DayOfWeek; + +public class Tooth { + + private final long start; + private final long end; + private final long volume; + + public Tooth(long start, long end, long volume) { + if (end <= start) { + throw new IllegalArgumentException(); + } + this.start = start; + this.end = end; + this.volume = volume; + } + + @Override + public String toString() { + return DayOfWeek.timeToString(start) + " --> " + DayOfWeek.timeToString(end) + " {" + volume + "}"; + } + + public final long getStart() { + return start; + } + + public final long getEnd() { + return end; + } + + public final long getVolume() { + return volume; + } + +} diff --git a/src/net/sourceforge/plantuml/project/core2/WorkLoad.java b/src/net/sourceforge/plantuml/project/core2/WorkLoad.java new file mode 100644 index 000000000..a5b5687c4 --- /dev/null +++ b/src/net/sourceforge/plantuml/project/core2/WorkLoad.java @@ -0,0 +1,42 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * http://plantuml.com/patreon (only 1$ per month!) + * http://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PlantUML distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.project.core2; + +public interface WorkLoad { + + public IteratorSlice slices(long timeBiggerThan); + +} diff --git a/src/net/sourceforge/plantuml/project/core2/WorkLoadConstant.java b/src/net/sourceforge/plantuml/project/core2/WorkLoadConstant.java new file mode 100644 index 000000000..398bc0383 --- /dev/null +++ b/src/net/sourceforge/plantuml/project/core2/WorkLoadConstant.java @@ -0,0 +1,53 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * http://plantuml.com/patreon (only 1$ per month!) + * http://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PlantUML distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.project.core2; + +import java.util.Collections; + +public class WorkLoadConstant implements WorkLoad { + + private final int value; + + public WorkLoadConstant(int value) { + this.value = value; + } + + public IteratorSlice slices(long timeBiggerThan) { + return new ListIteratorSlice( + Collections.singletonList(new Slice(timeBiggerThan, 1000L * Integer.MAX_VALUE, value))); + } + +} diff --git a/src/net/sourceforge/plantuml/project/core2/WorkLoadConstantButWeekDay.java b/src/net/sourceforge/plantuml/project/core2/WorkLoadConstantButWeekDay.java new file mode 100644 index 000000000..d17579090 --- /dev/null +++ b/src/net/sourceforge/plantuml/project/core2/WorkLoadConstantButWeekDay.java @@ -0,0 +1,103 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * http://plantuml.com/patreon (only 1$ per month!) + * http://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PlantUML distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.project.core2; + +import java.util.Arrays; +import java.util.EnumSet; +import java.util.Set; + +import net.sourceforge.plantuml.project.time.DayOfWeek; + +public class WorkLoadConstantButWeekDay implements WorkLoad { + + private final int value; + private final Set excepts = EnumSet.noneOf(DayOfWeek.class); + + public WorkLoadConstantButWeekDay(int value, DayOfWeek... butThisDays) { + this.value = value; + this.excepts.addAll(Arrays.asList(butThisDays)); + } + + private static final long dayDuration = 1000L * 24 * 3600; + + public IteratorSlice slices(final long timeBiggerThan) { + final Slice first = getNext(timeBiggerThan); + return new MyIterator(first); + } + + class MyIterator implements IteratorSlice { + + private Slice current; + + public MyIterator(Slice first) { + this.current = first; + } + + public Slice next() { + final Slice result = current; + current = getNext(current.getEnd()); + return result; + } + } + + private Slice getNext(final long limit) { + long start = limit; + long end; + if (isClose(start)) { + start = round(start); + while (isClose(start)) + start += dayDuration; + end = start + dayDuration; + } else { + end = round(start) + dayDuration; + } + assert !isClose(start); + while (isClose(end) == false) + end += dayDuration; + assert isClose(end); + + return new Slice(start, end, value); + } + + private boolean isClose(long start) { + return excepts.contains(DayOfWeek.fromTime(start)); + } + + private long round(long start) { + return dayDuration * (start / dayDuration); + } + +} diff --git a/src/net/sourceforge/plantuml/project/core2/WorkLoadVariable.java b/src/net/sourceforge/plantuml/project/core2/WorkLoadVariable.java new file mode 100644 index 000000000..30a75eba3 --- /dev/null +++ b/src/net/sourceforge/plantuml/project/core2/WorkLoadVariable.java @@ -0,0 +1,70 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * http://plantuml.com/patreon (only 1$ per month!) + * http://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PlantUML distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.project.core2; + +import java.util.ArrayList; +import java.util.List; + +public class WorkLoadVariable implements WorkLoad { + + private final List slices = new ArrayList(); + + public void add(Slice slice) { + if (slices.size() > 0) { + final Slice last = slices.get(slices.size() - 1); + if (slice.getStart() <= last.getEnd()) { + throw new IllegalArgumentException(); + } + } + slices.add(slice); + } + + public IteratorSlice slices(long timeBiggerThan) { + for (int i = 0; i < slices.size(); i++) { + final Slice current = slices.get(i); + if (current.getEnd() <= timeBiggerThan) { + continue; + } + assert current.getEnd() > timeBiggerThan; + assert current.getStart() >= timeBiggerThan; + final List tmp = slices.subList(i, slices.size()); + assert tmp.get(0).getStart() >= timeBiggerThan; + return new ListIteratorSlice(tmp); + } + throw new UnsupportedOperationException(); + } + +} diff --git a/src/net/sourceforge/plantuml/project/core2/WorkLoadWithHoles.java b/src/net/sourceforge/plantuml/project/core2/WorkLoadWithHoles.java new file mode 100644 index 000000000..96b5ab20b --- /dev/null +++ b/src/net/sourceforge/plantuml/project/core2/WorkLoadWithHoles.java @@ -0,0 +1,72 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * http://plantuml.com/patreon (only 1$ per month!) + * http://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PlantUML distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.project.core2; + +import java.util.ArrayList; +import java.util.List; + +public class WorkLoadWithHoles implements WorkLoad { + + private final WorkLoad source; + private final HolesList holes = new HolesList(); + + public void addHole(long start, long end) { + this.holes.add(new Hole(start, end)); + } + + public WorkLoadWithHoles(WorkLoad source) { + this.source = source; + } + + class MyIterator implements IteratorSlice { + + private final IteratorSlice slices; + + public MyIterator(IteratorSlice slices) { + this.slices = slices; + } + + public Slice next() { + final Slice candidat = slices.next(); + throw new UnsupportedOperationException(); + } + } + + public IteratorSlice slices(long timeBiggerThan) { + return new MyIterator(source.slices(timeBiggerThan)); + } + +} diff --git a/src/net/sourceforge/plantuml/project/draw/AbstractTaskDraw.java b/src/net/sourceforge/plantuml/project/draw/AbstractTaskDraw.java index a8585beea..48e76231a 100644 --- a/src/net/sourceforge/plantuml/project/draw/AbstractTaskDraw.java +++ b/src/net/sourceforge/plantuml/project/draw/AbstractTaskDraw.java @@ -56,7 +56,7 @@ public abstract class AbstractTaskDraw implements TaskDraw { protected Url url; protected Display note; protected final TimeScale timeScale; - protected final double y; + protected final YMovable y; protected final String prettyDisplay; protected final Wink start; protected final ISkinParam skinParam; @@ -72,7 +72,7 @@ public abstract class AbstractTaskDraw implements TaskDraw { this.note = note; } - public AbstractTaskDraw(TimeScale timeScale, double y, String prettyDisplay, Wink start, ISkinParam skinParam, + public AbstractTaskDraw(TimeScale timeScale, YMovable y, String prettyDisplay, Wink start, ISkinParam skinParam, Task task, ToTaskDraw toTaskDraw) { this.y = y; this.toTaskDraw = toTaskDraw; @@ -98,14 +98,14 @@ public abstract class AbstractTaskDraw implements TaskDraw { abstract protected Style getStyle(); final protected double getShapeHeight() { - return getHeight() - 2 * margin; + return getHeightTask() - 2 * margin; } - final public double getHeight() { + final public double getHeightTask() { return getFontConfiguration().getFont().getSize2D() + 5; } - final public double getY() { + final public YMovable getY() { if (task.getRow() == null) { return y; } @@ -116,14 +116,14 @@ public abstract class AbstractTaskDraw implements TaskDraw { return task; } - public final double getY(Direction direction) { + public final YMovable getY(Direction direction) { if (direction == Direction.UP) { return getY(); } if (direction == Direction.DOWN) { - return getY() + getHeight(); + return getY().add(getHeightTask()); } - return getY() + getHeight() / 2; + return getY().add(getHeightTask() / 2); } } diff --git a/src/net/sourceforge/plantuml/project/draw/FingerPrint.java b/src/net/sourceforge/plantuml/project/draw/FingerPrint.java new file mode 100644 index 000000000..8e4b98d38 --- /dev/null +++ b/src/net/sourceforge/plantuml/project/draw/FingerPrint.java @@ -0,0 +1,69 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * http://plantuml.com/patreon (only 1$ per month!) + * http://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PlantUML distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.project.draw; + +public class FingerPrint { + + private final double x; + private final double y; + private final double width; + private final double height; + + public FingerPrint(double x, double y, double width, double height) { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + } + + @Override + public String toString() { + return "X=(" + x + "->" + (x + width) + ") Y=(" + y + " ->" + (y + height) + ")"; + } + + public double overlap(FingerPrint other) { + if (x >= other.x + other.width || other.x >= x + width) { + return 0; + } + + if (y >= other.y + other.height || other.y >= y + height) { + return 0; + } + + return y + height - other.y; + } + +} diff --git a/src/net/sourceforge/plantuml/project/draw/ResourceDraw.java b/src/net/sourceforge/plantuml/project/draw/ResourceDraw.java index 1401c6c16..a2e8d5f55 100644 --- a/src/net/sourceforge/plantuml/project/draw/ResourceDraw.java +++ b/src/net/sourceforge/plantuml/project/draw/ResourceDraw.java @@ -42,7 +42,6 @@ import net.sourceforge.plantuml.graphic.HorizontalAlignment; import net.sourceforge.plantuml.graphic.TextBlock; import net.sourceforge.plantuml.graphic.UDrawable; import net.sourceforge.plantuml.project.GanttDiagram; -import net.sourceforge.plantuml.project.core.PrintScale; import net.sourceforge.plantuml.project.core.Resource; import net.sourceforge.plantuml.project.time.Wink; import net.sourceforge.plantuml.project.timescale.TimeScale; @@ -57,12 +56,12 @@ public class ResourceDraw implements UDrawable { private final Resource res; private final TimeScale timeScale; - private final double y; + private final YMovable y; private final Wink min; private final Wink max; private final GanttDiagram gantt; - public ResourceDraw(GanttDiagram gantt, Resource res, TimeScale timeScale, double y, Wink min, Wink max) { + public ResourceDraw(GanttDiagram gantt, Resource res, TimeScale timeScale, YMovable y, Wink min, Wink max) { this.res = res; this.timeScale = timeScale; this.y = y; @@ -125,7 +124,7 @@ public class ResourceDraw implements UDrawable { } public double getY() { - return y; + return y.getValue(); } } diff --git a/src/net/sourceforge/plantuml/project/draw/TaskDraw.java b/src/net/sourceforge/plantuml/project/draw/TaskDraw.java index cd4fd43ce..101caa0da 100644 --- a/src/net/sourceforge/plantuml/project/draw/TaskDraw.java +++ b/src/net/sourceforge/plantuml/project/draw/TaskDraw.java @@ -38,6 +38,7 @@ package net.sourceforge.plantuml.project.draw; import net.sourceforge.plantuml.Direction; import net.sourceforge.plantuml.Url; import net.sourceforge.plantuml.cucadiagram.Display; +import net.sourceforge.plantuml.graphic.StringBounder; import net.sourceforge.plantuml.graphic.UDrawable; import net.sourceforge.plantuml.project.core.Task; import net.sourceforge.plantuml.project.lang.CenterBorderColor; @@ -47,14 +48,20 @@ public interface TaskDraw extends UDrawable { public void setColorsAndCompletion(CenterBorderColor colors, int completion, Url url, Display note); - public double getY(); + public YMovable getY(); - public double getY(Direction direction); + public YMovable getY(Direction direction); public void drawTitle(UGraphic ug); - public double getHeight(); + public double getHeightTask(); + + public double getHeightMax(StringBounder stringBounder); public Task getTask(); + public FingerPrint getFingerPrint(); + + public FingerPrint getFingerPrintNote(StringBounder stringBounder); + } diff --git a/src/net/sourceforge/plantuml/project/draw/TaskDrawDiamond.java b/src/net/sourceforge/plantuml/project/draw/TaskDrawDiamond.java index 9087ca76b..7194ebeeb 100644 --- a/src/net/sourceforge/plantuml/project/draw/TaskDrawDiamond.java +++ b/src/net/sourceforge/plantuml/project/draw/TaskDrawDiamond.java @@ -39,6 +39,7 @@ import net.sourceforge.plantuml.ISkinParam; import net.sourceforge.plantuml.SpriteContainerEmpty; import net.sourceforge.plantuml.cucadiagram.Display; import net.sourceforge.plantuml.graphic.HorizontalAlignment; +import net.sourceforge.plantuml.graphic.StringBounder; import net.sourceforge.plantuml.graphic.TextBlock; import net.sourceforge.plantuml.project.ToTaskDraw; import net.sourceforge.plantuml.project.core.Task; @@ -54,7 +55,7 @@ import net.sourceforge.plantuml.ugraphic.UTranslate; public class TaskDrawDiamond extends AbstractTaskDraw { - public TaskDrawDiamond(TimeScale timeScale, double y, String prettyDisplay, Wink start, ISkinParam skinParam, + public TaskDrawDiamond(TimeScale timeScale, YMovable y, String prettyDisplay, Wink start, ISkinParam skinParam, Task task, ToTaskDraw toTaskDraw) { super(timeScale, y, prettyDisplay, start, skinParam, task, toTaskDraw); } @@ -66,6 +67,10 @@ public class TaskDrawDiamond extends AbstractTaskDraw { return style; } + public double getHeightMax(StringBounder stringBounder) { + return getHeightTask(); + } + // final UFont font = UFont.serif(11); // return new FontConfiguration(font, HColorUtils.BLACK, HColorUtils.BLACK, false); @@ -74,7 +79,7 @@ public class TaskDrawDiamond extends AbstractTaskDraw { HorizontalAlignment.LEFT, new SpriteContainerEmpty()); final double titleHeight = title.calculateDimension(ug.getStringBounder()).getHeight(); final double h = (margin + getShapeHeight() - titleHeight) / 2; - final double endingPosition = timeScale.getStartingPosition(start) + getHeight(); + final double endingPosition = timeScale.getStartingPosition(start) + getHeightTask(); title.drawU(ug.apply(new UTranslate(endingPosition, h))); } @@ -96,8 +101,18 @@ public class TaskDrawDiamond extends AbstractTaskDraw { ug.draw(getDiamond()); } + public FingerPrint getFingerPrintNote(StringBounder stringBounder) { + return null; + } + + public FingerPrint getFingerPrint() { + final double h = getHeightTask(); + final double startPos = timeScale.getStartingPosition(start); + return new FingerPrint(startPos, y.getValue(), startPos + h, y.getValue() + h); + } + private UShape getDiamond() { - final double h = getHeight() - 2 * margin; + final double h = getHeightTask() - 2 * margin; final UPolygon result = new UPolygon(); result.addPoint(h / 2, 0); result.addPoint(h, h / 2); diff --git a/src/net/sourceforge/plantuml/project/draw/TaskDrawRegular.java b/src/net/sourceforge/plantuml/project/draw/TaskDrawRegular.java index 5295d03cf..95d77304b 100644 --- a/src/net/sourceforge/plantuml/project/draw/TaskDrawRegular.java +++ b/src/net/sourceforge/plantuml/project/draw/TaskDrawRegular.java @@ -35,6 +35,7 @@ */ package net.sourceforge.plantuml.project.draw; +import java.awt.geom.Dimension2D; import java.util.Collection; import net.sourceforge.plantuml.FontParam; @@ -48,6 +49,7 @@ import net.sourceforge.plantuml.creole.SheetBlock1; import net.sourceforge.plantuml.cucadiagram.Display; import net.sourceforge.plantuml.graphic.FontConfiguration; import net.sourceforge.plantuml.graphic.HorizontalAlignment; +import net.sourceforge.plantuml.graphic.StringBounder; import net.sourceforge.plantuml.graphic.TextBlock; import net.sourceforge.plantuml.project.ToTaskDraw; import net.sourceforge.plantuml.project.core.Task; @@ -77,8 +79,8 @@ public class TaskDrawRegular extends AbstractTaskDraw { private final double margin = 2; - public TaskDrawRegular(TimeScale timeScale, double y, String prettyDisplay, Wink start, Wink end, boolean oddStart, - boolean oddEnd, ISkinParam skinParam, Task task, ToTaskDraw toTaskDraw) { + public TaskDrawRegular(TimeScale timeScale, YMovable y, String prettyDisplay, Wink start, Wink end, + boolean oddStart, boolean oddEnd, ISkinParam skinParam, Task task, ToTaskDraw toTaskDraw) { super(timeScale, y, prettyDisplay, start, skinParam, task, toTaskDraw); this.end = end; this.oddStart = oddStart; @@ -106,19 +108,33 @@ public class TaskDrawRegular extends AbstractTaskDraw { } public void drawU(UGraphic ug) { - drawNote(ug.apply(UTranslate.dy(getShapeHeight() + margin * 3))); - final double startPos = timeScale.getStartingPosition(start); - ug = applyColors(ug); - ug = ug.apply(new UTranslate(startPos + margin, margin)); + drawNote(ug.apply((new UTranslate(startPos + margin, getYNotePosition())))); + + ug = applyColors(ug).apply(new UTranslate(margin, margin)); drawShape(ug); } + private double getYNotePosition() { + return getShapeHeight() + margin * 3; + } + private void drawNote(UGraphic ug) { if (note == null) { return; } + getOpaleNote().drawU(ug); + } + + public double getHeightMax(StringBounder stringBounder) { + if (note == null) { + return getHeightTask(); + } + return getYNotePosition() + getOpaleNote().calculateDimension(stringBounder).getHeight(); + } + + private Opale getOpaleNote() { final Style style = StyleSignature.of(SName.root, SName.element, SName.ganttDiagram, SName.note) .getMergedStyle(skinParam.getCurrentStyleBuilder()); FontConfiguration fc = new FontConfiguration(style, skinParam, null, FontParam.NOTE); @@ -133,8 +149,24 @@ public class TaskDrawRegular extends AbstractTaskDraw { final double shadowing = style.value(PName.Shadowing).asDouble(); Opale opale = new Opale(shadowing, borderColor, noteBackgroundColor, sheet1, false); - opale.drawU(ug); + return opale; + } + public FingerPrint getFingerPrint() { + final double h = getHeightTask(); + final double startPos = timeScale.getStartingPosition(start); + final double endPos = timeScale.getEndingPosition(end); + return new FingerPrint(startPos, y.getValue(), endPos - startPos, h); + } + + public FingerPrint getFingerPrintNote(StringBounder stringBounder) { + if (note == null) { + return null; + } + final Dimension2D dim = getOpaleNote().calculateDimension(stringBounder); + final double startPos = timeScale.getStartingPosition(start); + // final double endPos = timeScale.getEndingPosition(end); + return new FingerPrint(startPos, y.getValue() + getYNotePosition(), dim.getWidth(), dim.getHeight()); } private UGraphic applyColors(UGraphic ug) { @@ -156,27 +188,31 @@ public class TaskDrawRegular extends AbstractTaskDraw { ug.startUrl(url); } if (oddStart && !oddEnd) { - ug.draw(PathUtils.UtoRight(fullLength, getShapeHeight())); + ug.apply(UTranslate.dx(startPos)).draw(PathUtils.UtoRight(fullLength, getShapeHeight())); } else if (!oddStart && oddEnd) { - ug.draw(PathUtils.UtoLeft(fullLength, getShapeHeight())); + ug.apply(UTranslate.dx(startPos)).draw(PathUtils.UtoLeft(fullLength, getShapeHeight())); } else { final URectangle full = new URectangle(fullLength, getShapeHeight()).rounded(8); if (completion == 100) { - ug.draw(full); + ug.apply(UTranslate.dx(startPos)).draw(full); } else { final double partialLength = fullLength * completion / 100.; - ug.apply(HColorUtils.WHITE).apply(HColorUtils.WHITE.bg()).draw(full); + ug.apply(UTranslate.dx(startPos)).apply(HColorUtils.WHITE).apply(HColorUtils.WHITE.bg()).draw(full); if (partialLength > 2) { final URectangle partial = new URectangle(partialLength, getShapeHeight()).rounded(8); - ug.apply(new HColorNone()).draw(partial); + ug.apply(UTranslate.dx(startPos)).apply(new HColorNone()).draw(partial); } if (partialLength > 10 && partialLength < fullLength - 10) { final URectangle patch = new URectangle(8, getShapeHeight()); - ug.apply(new HColorNone()).apply(UTranslate.dx(partialLength - 8)).draw(patch); + ug.apply(UTranslate.dx(startPos)).apply(new HColorNone()).apply(UTranslate.dx(partialLength - 8)) + .draw(patch); } - ug.apply(new HColorNone().bg()).draw(full); + ug.apply(UTranslate.dx(startPos)).apply(new HColorNone().bg()).draw(full); } } + if (url != null) { + ug.closeUrl(); + } Wink begin = null; for (Wink pause : paused) { if (paused.contains(pause.increment())) { @@ -190,9 +226,6 @@ public class TaskDrawRegular extends AbstractTaskDraw { begin = null; } } - if (url != null) { - ug.closeUrl(); - } } private void drawPause(UGraphic ug, Wink start1, Wink end) { diff --git a/src/net/sourceforge/plantuml/project/draw/TaskDrawSeparator.java b/src/net/sourceforge/plantuml/project/draw/TaskDrawSeparator.java index f45accecf..ec6fade96 100644 --- a/src/net/sourceforge/plantuml/project/draw/TaskDrawSeparator.java +++ b/src/net/sourceforge/plantuml/project/draw/TaskDrawSeparator.java @@ -41,9 +41,9 @@ import net.sourceforge.plantuml.Url; import net.sourceforge.plantuml.cucadiagram.Display; import net.sourceforge.plantuml.graphic.FontConfiguration; import net.sourceforge.plantuml.graphic.HorizontalAlignment; +import net.sourceforge.plantuml.graphic.StringBounder; import net.sourceforge.plantuml.graphic.TextBlock; import net.sourceforge.plantuml.graphic.TextBlockUtils; -import net.sourceforge.plantuml.project.core.AbstractTask; import net.sourceforge.plantuml.project.core.Task; import net.sourceforge.plantuml.project.lang.CenterBorderColor; import net.sourceforge.plantuml.project.time.Wink; @@ -57,12 +57,12 @@ import net.sourceforge.plantuml.ugraphic.color.HColorUtils; public class TaskDrawSeparator implements TaskDraw { private final TimeScale timeScale; - private final double y; + private final YMovable y; private final Wink min; private final Wink max; private final String name; - public TaskDrawSeparator(String name, TimeScale timeScale, double y, Wink min, Wink max) { + public TaskDrawSeparator(String name, TimeScale timeScale, YMovable y, Wink min, Wink max) { this.name = name; this.y = y; this.timeScale = timeScale; @@ -96,7 +96,7 @@ public class TaskDrawSeparator implements TaskDraw { final double end = timeScale.getEndingPosition(max); ug = ug.apply(HColorUtils.BLACK); - ug = ug.apply(UTranslate.dy(getHeight() / 2)); + ug = ug.apply(UTranslate.dy(getHeightTask() / 2)); if (widthTitle == 0) { final ULine line = ULine.hline(end - start); @@ -109,11 +109,17 @@ public class TaskDrawSeparator implements TaskDraw { } } - public double getHeight() { + public FingerPrint getFingerPrint() { + final double h = getHeightTask(); + final double end = timeScale.getEndingPosition(max); + return new FingerPrint(0, y.getValue(), end, y.getValue() + h); + } + + public double getHeightTask() { return 16; } - public double getY() { + public YMovable getY() { return y; } @@ -124,8 +130,16 @@ public class TaskDrawSeparator implements TaskDraw { throw new UnsupportedOperationException(); } - public double getY(Direction direction) { + public YMovable getY(Direction direction) { throw new UnsupportedOperationException(); } + public FingerPrint getFingerPrintNote(StringBounder stringBounder) { + return null; + } + + public double getHeightMax(StringBounder stringBounder) { + return getHeightTask(); + } + } diff --git a/src/net/sourceforge/plantuml/project/draw/YMovable.java b/src/net/sourceforge/plantuml/project/draw/YMovable.java new file mode 100644 index 000000000..78bc87cc5 --- /dev/null +++ b/src/net/sourceforge/plantuml/project/draw/YMovable.java @@ -0,0 +1,59 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * http://plantuml.com/patreon (only 1$ per month!) + * http://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PlantUML distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.project.draw; + +public class YMovable { + + private double y; + + public YMovable(double y) { + this.y = y; + } + + public YMovable add(double v) { + return new YMovable(y + v); + } + + public final double getValue() { + return y; + } + + public void pushMe(double delta) { + this.y += delta; + + } + +} diff --git a/src/net/sourceforge/plantuml/project/time/DayOfWeek.java b/src/net/sourceforge/plantuml/project/time/DayOfWeek.java index 26c3818cf..d838fcae5 100644 --- a/src/net/sourceforge/plantuml/project/time/DayOfWeek.java +++ b/src/net/sourceforge/plantuml/project/time/DayOfWeek.java @@ -35,12 +35,37 @@ */ package net.sourceforge.plantuml.project.time; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Locale; +import java.util.TimeZone; + import net.sourceforge.plantuml.StringUtils; public enum DayOfWeek { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY; + static final private Calendar gmt = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + static final private SimpleDateFormat dateFormatGmt = new SimpleDateFormat("dd MMM yyyy HH:mm:ss.SSS", Locale.US); + static { + dateFormatGmt.setTimeZone(TimeZone.getTimeZone("GMT")); + } + + public static synchronized DayOfWeek fromTime(long time) { + gmt.setTimeInMillis(time); + final int result = gmt.get(Calendar.DAY_OF_WEEK); + if (result == Calendar.SUNDAY) { + return SUNDAY; + } + return DayOfWeek.values()[result - 2]; + } + + public static synchronized String timeToString(long value) { + gmt.setTimeInMillis(value); + return fromTime(value).shortName() + " " + dateFormatGmt.format(gmt.getTime()); + } + static public String getRegexString() { final StringBuilder sb = new StringBuilder(); for (DayOfWeek day : DayOfWeek.values()) { diff --git a/src/net/sourceforge/plantuml/sequencediagram/graphic/SequenceDiagramArea.java b/src/net/sourceforge/plantuml/sequencediagram/graphic/SequenceDiagramArea.java index 03cd41759..9222a837d 100644 --- a/src/net/sourceforge/plantuml/sequencediagram/graphic/SequenceDiagramArea.java +++ b/src/net/sourceforge/plantuml/sequencediagram/graphic/SequenceDiagramArea.java @@ -62,6 +62,36 @@ public class SequenceDiagramArea { private double footerHeight; private double footerMargin; + private double legendWidth; + private double legendHeight; + private boolean isLegendTop; + private HorizontalAlignment legendHorizontalAlignment; + + public void setLegend(Dimension2D dimLegend, boolean isLegendTop, HorizontalAlignment horizontalAlignment) { + this.legendHorizontalAlignment = horizontalAlignment; + this.legendWidth = dimLegend.getWidth(); + this.legendHeight = dimLegend.getHeight(); + this.isLegendTop = isLegendTop; + } + + public double getLegendWidth() { + return legendWidth; + } + + public boolean hasLegend() { + return legendHeight > 0 && legendWidth > 0; + } + + public double getLegendX() { + if (legendHorizontalAlignment == HorizontalAlignment.LEFT) { + return 0; + } else if (legendHorizontalAlignment == HorizontalAlignment.RIGHT) { + return Math.max(0, getWidth() - legendWidth); + } else { + return Math.max(0, getWidth() - legendWidth) / 2; + } + } + public SequenceDiagramArea(double width, double height) { this.sequenceWidth = width; this.sequenceHeight = height; @@ -98,7 +128,24 @@ public class SequenceDiagramArea { } public double getHeight() { - return sequenceHeight + headerHeight + headerMargin + titleHeight + footerMargin + footerHeight + captionHeight; + return sequenceHeight + headerHeight + headerMargin + titleHeight + footerMargin + footerHeight + captionHeight + + legendHeight; + } + + public double getFooterY() { + return sequenceHeight + headerHeight + headerMargin + titleHeight + footerMargin + captionHeight + legendHeight; + } + + public double getCaptionY() { + return sequenceHeight + headerHeight + headerMargin + titleHeight + legendHeight; + } + + public double getLegendY() { + if (isLegendTop) { + return titleHeight + headerHeight + headerMargin; + } + return sequenceHeight + headerHeight + headerMargin + titleHeight; + } public double getTitleX() { @@ -117,15 +164,14 @@ public class SequenceDiagramArea { return (getWidth() - captionWidth) / 2; } - public double getCaptionY() { - return sequenceHeight + headerHeight + headerMargin + titleHeight; - } - public double getSequenceAreaX() { return (getWidth() - sequenceWidth) / 2; } public double getSequenceAreaY() { + if (isLegendTop) { + return getTitleY() + titleHeight + legendHeight; + } return getTitleY() + titleHeight; } @@ -133,10 +179,6 @@ public class SequenceDiagramArea { return 0; } - public double getFooterY() { - return sequenceHeight + headerHeight + headerMargin + titleHeight + footerMargin + captionHeight; - } - public double getFooterX(HorizontalAlignment align) { if (align == HorizontalAlignment.LEFT) { return 0; diff --git a/src/net/sourceforge/plantuml/sequencediagram/graphic/SequenceDiagramFileMakerPuma2.java b/src/net/sourceforge/plantuml/sequencediagram/graphic/SequenceDiagramFileMakerPuma2.java index eca770315..9002ff842 100644 --- a/src/net/sourceforge/plantuml/sequencediagram/graphic/SequenceDiagramFileMakerPuma2.java +++ b/src/net/sourceforge/plantuml/sequencediagram/graphic/SequenceDiagramFileMakerPuma2.java @@ -176,21 +176,21 @@ public class SequenceDiagramFileMakerPuma2 implements FileMaker { area.initFooter(getPngTitler(FontParam.FOOTER, index), stringBounder); area.initHeader(getPngTitler(FontParam.HEADER, index), stringBounder); - final DisplayPositionned legend = diagram.getLegend(); final TextBlock legendBlock; - if (legend.isNull()) { + if (diagram.getLegend().isNull()) { legendBlock = TextBlockUtils.empty(0, 0); } else { if (SkinParam.USE_STYLES()) { final Style style = StyleSignature.of(SName.root, SName.legend) .getMergedStyle(diagram.getSkinParam().getCurrentStyleBuilder()); - legendBlock = style.createTextBlockBordered(legend.getDisplay(), + legendBlock = style.createTextBlockBordered(diagram.getLegend().getDisplay(), diagram.getSkinParam().getIHtmlColorSet(), diagram.getSkinParam()); } else { - legendBlock = EntityImageLegend.create(legend.getDisplay(), diagram.getSkinParam()); + legendBlock = EntityImageLegend.create(diagram.getLegend().getDisplay(), diagram.getSkinParam()); } } final Dimension2D dimLegend = legendBlock.calculateDimension(stringBounder); + area.setLegend(dimLegend, isLegendTop(), diagram.getLegend().getHorizontalAlignment()); scale = getScale(area.getWidth(), area.getHeight()); @@ -224,61 +224,40 @@ public class SequenceDiagramFileMakerPuma2 implements FileMaker { delta = 0; } - double legendYdelta = 0; if (compTitle != null) { - final StringBounder stringBounder = ug.getStringBounder(); - final double h = compTitle.calculateDimension(stringBounder).getHeight(); - legendYdelta += h; compTitle.drawU(ug.apply(new UTranslate(area.getTitleX(), area.getTitleY()))); } - legendYdelta += area.getHeaderHeightMargin(); caption.drawU(ug.apply(new UTranslate(area.getCaptionX(), area.getCaptionY()))); - final double delta1 = Math.max(0, dimLegend.getWidth() - area.getWidth()); + final double delta1 = Math.max(0, area.getLegendWidth() - area.getWidth()); - final boolean legendTop = legend.isNull() == false - && legend.getVerticalAlignment() == VerticalAlignment.TOP; - - double sequenceAreaY = area.getSequenceAreaY(); - if (legendTop) { - sequenceAreaY += legendBlock.calculateDimension(ug.getStringBounder()).getHeight(); - } - final UTranslate forCore = new UTranslate(area.getSequenceAreaX() + delta1 / 2, sequenceAreaY); + final UTranslate forCore = new UTranslate(area.getSequenceAreaX() + delta1 / 2, + area.getSequenceAreaY()); TextBlock core = drawableSet.asTextBlock(delta, fullDimension.getWidth(), page, diagram.isShowFootbox()); core = annotatedWorker.addFrame(core); core.drawU(ug.apply(forCore)); - // drawableSet.drawU22(ug.apply(forCore), delta, fullDimension.getWidth(), page, - // diagram.isShowFootbox()); drawHeader(area, ug, index); - drawFooter(area, ug, index, dimLegend.getHeight()); + drawFooter(area, ug, index); - if (legend.isNull() == false) { - final double delta2; - if (legend.getHorizontalAlignment() == HorizontalAlignment.LEFT) { - delta2 = 0; - } else if (legend.getHorizontalAlignment() == HorizontalAlignment.RIGHT) { - delta2 = Math.max(0, area.getWidth() - dimLegend.getWidth()); - } else { - delta2 = Math.max(0, area.getWidth() - dimLegend.getWidth()) / 2; - } - legendBlock.drawU(ug.apply(new UTranslate(delta2, legendTop ? legendYdelta : area.getHeight()))); + if (area.hasLegend()) { + legendBlock.drawU(ug.apply(new UTranslate(area.getLegendX(), area.getLegendY()))); } - } + }); return imageBuilder.writeImageTOBEMOVED(fileFormatOption, diagram.seed(), os); } - private void drawFooter(SequenceDiagramArea area, UGraphic ug, int page, double legendHeight) { + private void drawFooter(SequenceDiagramArea area, UGraphic ug, int page) { final PngTitler pngTitler = getPngTitler(FontParam.FOOTER, page); final TextBlock text = pngTitler.getRibbonBlock(); if (text == null) { return; } - text.drawU(ug.apply(new UTranslate(area.getFooterX(diagram.getFooter().getHorizontalAlignment()), - area.getFooterY() + legendHeight))); + text.drawU(ug.apply( + new UTranslate(area.getFooterX(diagram.getFooter().getHorizontalAlignment()), area.getFooterY()))); } private void drawHeader(SequenceDiagramArea area, UGraphic ug, int page) { @@ -334,4 +313,9 @@ public class SequenceDiagramFileMakerPuma2 implements FileMaker { skinParam.useUnderlineForHyperlink(), style, skinParam.getIHtmlColorSet(), skinParam); } + private boolean isLegendTop() { + return diagram.getLegend().isNull() == false + && diagram.getLegend().getVerticalAlignment() == VerticalAlignment.TOP; + } + } diff --git a/src/net/sourceforge/plantuml/sequencediagram/teoz/SequenceDiagramFileMakerTeoz.java b/src/net/sourceforge/plantuml/sequencediagram/teoz/SequenceDiagramFileMakerTeoz.java index 354a82892..ed99f118f 100644 --- a/src/net/sourceforge/plantuml/sequencediagram/teoz/SequenceDiagramFileMakerTeoz.java +++ b/src/net/sourceforge/plantuml/sequencediagram/teoz/SequenceDiagramFileMakerTeoz.java @@ -112,6 +112,7 @@ public class SequenceDiagramFileMakerTeoz implements FileMaker { + heightEnglober2 + title.calculateDimension(stringBounder).getHeight() + header.calculateDimension(stringBounder).getHeight() + legend.calculateDimension(stringBounder).getHeight() + + caption.calculateDimension(stringBounder).getHeight() + footer.calculateDimension(stringBounder).getHeight() + (annotatedWorker.hasMainFrame() ? 10 : 0); this.dimTotal = new Dimension2DDouble(totalWidth, totalHeight); } @@ -159,8 +160,9 @@ public class SequenceDiagramFileMakerTeoz implements FileMaker { margin1 = 3; margin2 = 10; } - final ImageBuilder imageBuilder = ImageBuilder.buildD(diagram.getSkinParam(), ClockwiseTopRightBottomLeft.margin1margin2((double) margin1, (double) margin2), diagram.getAnimation(), metadata, - null, oneOf(scale, dpiFactor)); + final ImageBuilder imageBuilder = ImageBuilder.buildD(diagram.getSkinParam(), + ClockwiseTopRightBottomLeft.margin1margin2((double) margin1, (double) margin2), diagram.getAnimation(), + metadata, null, oneOf(scale, dpiFactor)); imageBuilder.setUDrawable(new Foo(index)); return imageBuilder.writeImageTOBEMOVED(fileFormatOption, diagram.seed(), os); @@ -315,12 +317,12 @@ public class SequenceDiagramFileMakerTeoz implements FileMaker { ug = goDown(ug, bodyFramed); ug = ug.apply(UTranslate.dy(heightEnglober2)); - printAligned(ug, HorizontalAlignment.CENTER, caption); - if (diagram.getLegend().getVerticalAlignment() == VerticalAlignment.BOTTOM) { printAligned(ug, diagram.getLegend().getHorizontalAlignment(), legend); ug = goDown(ug, legend); } + printAligned(ug, HorizontalAlignment.CENTER, caption); + ug = goDown(ug, caption); printAligned(ug, diagram.getFooterOrHeaderTeoz(FontParam.FOOTER).getHorizontalAlignment(), footer); } diff --git a/src/net/sourceforge/plantuml/statediagram/command/CommandLinkState.java b/src/net/sourceforge/plantuml/statediagram/command/CommandLinkState.java index 92da4e855..5cf3bab32 100644 --- a/src/net/sourceforge/plantuml/statediagram/command/CommandLinkState.java +++ b/src/net/sourceforge/plantuml/statediagram/command/CommandLinkState.java @@ -92,7 +92,7 @@ public class CommandLinkState extends SingleLineCommand2 { private static RegexLeaf getStatePattern(String name) { return new RegexLeaf(name, - "([\\p{L}0-9_.]+|[\\p{L}0-9_.]+\\[H\\*?\\]|\\[\\*\\]|\\[H\\*?\\]|(?:==+)(?:[\\p{L}0-9_.]+)(?:==+))[%s]*(\\<\\<.*\\>\\>)?[%s]*(#\\w+)?"); + "([\\p{L}0-9_.:]+|[\\p{L}0-9_.:]+\\[H\\*?\\]|\\[\\*\\]|\\[H\\*?\\]|(?:==+)(?:[\\p{L}0-9_.:]+)(?:==+))[%s]*(\\<\\<.*\\>\\>)?[%s]*(#\\w+)?"); } @Override diff --git a/src/net/sourceforge/plantuml/svek/GeneralImageBuilder.java b/src/net/sourceforge/plantuml/svek/GeneralImageBuilder.java index 86148af5f..805b98ee2 100644 --- a/src/net/sourceforge/plantuml/svek/GeneralImageBuilder.java +++ b/src/net/sourceforge/plantuml/svek/GeneralImageBuilder.java @@ -84,6 +84,7 @@ import net.sourceforge.plantuml.cucadiagram.Stereotype; import net.sourceforge.plantuml.cucadiagram.UnparsableGraphvizException; import net.sourceforge.plantuml.cucadiagram.dot.DotData; import net.sourceforge.plantuml.cucadiagram.dot.ExeState; +import net.sourceforge.plantuml.cucadiagram.dot.GraphvizUtils; import net.sourceforge.plantuml.cucadiagram.dot.GraphvizVersion; import net.sourceforge.plantuml.cucadiagram.dot.Neighborhood; import net.sourceforge.plantuml.cucadiagram.entity.EntityFactory; @@ -459,10 +460,10 @@ public final class GeneralImageBuilder { try { svg = dotStringFactory.getSvg(basefile, dotStrings); } catch (IOException e) { - return new GraphvizCrash(source.getPlainString()); + return new GraphvizCrash(source.getPlainString(), GraphvizUtils.graphviz244onWindows()); } if (svg.length() == 0) { - return new GraphvizCrash(source.getPlainString()); + return new GraphvizCrash(source.getPlainString(), GraphvizUtils.graphviz244onWindows()); } final String graphvizVersion = extractGraphvizVersion(svg); try { diff --git a/src/net/sourceforge/plantuml/svek/GraphvizCrash.java b/src/net/sourceforge/plantuml/svek/GraphvizCrash.java index 038d53dd6..6f01cdbf1 100644 --- a/src/net/sourceforge/plantuml/svek/GraphvizCrash.java +++ b/src/net/sourceforge/plantuml/svek/GraphvizCrash.java @@ -42,7 +42,6 @@ import java.util.ArrayList; import java.util.List; import net.sourceforge.plantuml.BackSlash; -import net.sourceforge.plantuml.Dimension2DDouble; import net.sourceforge.plantuml.OptionPrint; import net.sourceforge.plantuml.StringUtils; import net.sourceforge.plantuml.cucadiagram.dot.GraphvizUtils; @@ -52,28 +51,33 @@ import net.sourceforge.plantuml.fun.IconLoader; import net.sourceforge.plantuml.graphic.AbstractTextBlock; import net.sourceforge.plantuml.graphic.GraphicPosition; import net.sourceforge.plantuml.graphic.GraphicStrings; +import net.sourceforge.plantuml.graphic.HorizontalAlignment; import net.sourceforge.plantuml.graphic.QuoteUtils; import net.sourceforge.plantuml.graphic.StringBounder; +import net.sourceforge.plantuml.graphic.TextBlock; +import net.sourceforge.plantuml.graphic.TextBlockUtils; import net.sourceforge.plantuml.ugraphic.AffineTransformType; import net.sourceforge.plantuml.ugraphic.PixelImage; import net.sourceforge.plantuml.ugraphic.UGraphic; import net.sourceforge.plantuml.ugraphic.UImage; -import net.sourceforge.plantuml.ugraphic.UTranslate; import net.sourceforge.plantuml.ugraphic.color.HColor; import net.sourceforge.plantuml.ugraphic.color.HColorUtils; +import net.sourceforge.plantuml.version.PSystemVersion; import net.sourceforge.plantuml.version.Version; public class GraphvizCrash extends AbstractTextBlock implements IEntityImage { - private final TextBlockBackcolored graphicStrings; + private final TextBlock text1; private final BufferedImage flashCode; private final String text; + private final boolean graphviz244onWindows; - public GraphvizCrash(String text) { + public GraphvizCrash(String text, boolean graphviz244onWindows) { this.text = text; + this.graphviz244onWindows = graphviz244onWindows; final FlashCodeUtils utils = FlashCodeFactory.getFlashCodeUtils(); this.flashCode = utils.exportFlashcode(text, Color.BLACK, Color.WHITE); - this.graphicStrings = GraphicStrings.createBlackOnWhite(init(), IconLoader.getRandom(), + this.text1 = GraphicStrings.createBlackOnWhite(init(), IconLoader.getRandom(), GraphicPosition.BACKGROUND_CORNER_TOP_RIGHT); } @@ -102,7 +106,7 @@ public class GraphvizCrash extends AbstractTextBlock implements IEntityImage { return result; } - public static void checkOldVersionWarning(final List strings) { + public static void checkOldVersionWarning(List strings) { final long days = (System.currentTimeMillis() - Version.compileTime()) / 1000L / 3600 / 24; if (days >= 90) { strings.add("This version of PlantUML is " + days + " days old, so you should"); @@ -110,13 +114,13 @@ public class GraphvizCrash extends AbstractTextBlock implements IEntityImage { } } - public static void pleaseGoTo(final List strings) { + public static void pleaseGoTo(List strings) { strings.add(" "); strings.add("Please go to https://plantuml.com/graphviz-dot to check your GraphViz version."); strings.add(" "); } - public static void youShouldSendThisDiagram(final List strings) { + public static void youShouldSendThisDiagram(List strings) { strings.add("You should send this diagram and this image to plantuml@gmail.com or"); strings.add("post to https://plantuml.com/qa to solve this issue."); strings.add("You can try to turn arround this issue by simplifing your diagram."); @@ -151,6 +155,14 @@ public class GraphvizCrash extends AbstractTextBlock implements IEntityImage { return strings; } + private List getText2() { + final List strings = new ArrayList(); + strings.add("It looks like you are running GraphViz 2.44 under Windows."); + strings.add("If you have just installed GraphViz, you may have to execute"); + strings.add("the post-install command dot -c like in the following example:"); + return strings; + } + public static void addDecodeHint(final List strings) { strings.add(" "); strings.add(" Diagram source: (Use http://zxing.org/w/decode.jspx to decode the qrcode)"); @@ -161,11 +173,6 @@ public class GraphvizCrash extends AbstractTextBlock implements IEntityImage { strings.addAll(OptionPrint.interestingValues()); } - // private static void addTextProperty(final List strings, String prop) - // { - // strings.add(prop + ": " + System.getProperty(prop)); - // } - public boolean isHidden() { return false; } @@ -175,22 +182,30 @@ public class GraphvizCrash extends AbstractTextBlock implements IEntityImage { } public Dimension2D calculateDimension(StringBounder stringBounder) { - Dimension2D result = graphicStrings.calculateDimension(stringBounder); - if (flashCode != null) { - result = Dimension2DDouble.mergeTB(result, - new Dimension2DDouble(flashCode.getWidth(), flashCode.getHeight())); - } - return result; + return getMain().calculateDimension(stringBounder); } public void drawU(UGraphic ug) { - graphicStrings.drawU(ug); + getMain().drawU(ug); + } + + private TextBlock getMain() { + TextBlock result = text1; if (flashCode != null) { - final double h = graphicStrings.calculateDimension(ug.getStringBounder()).getHeight(); - ug = ug.apply(UTranslate.dy(h)); - ug.draw(new UImage(new PixelImage(flashCode, AffineTransformType.TYPE_NEAREST_NEIGHBOR)) - .scale(3)); + final UImage flash = new UImage(new PixelImage(flashCode, AffineTransformType.TYPE_NEAREST_NEIGHBOR)) + .scale(3); + result = TextBlockUtils.mergeTB(result, flash, HorizontalAlignment.LEFT); } + + if (graphviz244onWindows) { + final TextBlock text2 = GraphicStrings.createBlackOnWhite(getText2()); + result = TextBlockUtils.mergeTB(result, text2, HorizontalAlignment.LEFT); + + final UImage dotc = new UImage(new PixelImage(PSystemVersion.getDotc(), AffineTransformType.TYPE_BILINEAR)); + result = TextBlockUtils.mergeTB(result, dotc, HorizontalAlignment.LEFT); + } + + return result; } public ShapeType getShapeType() { diff --git a/src/net/sourceforge/plantuml/svek/image/EntityImageEmptyPackage.java b/src/net/sourceforge/plantuml/svek/image/EntityImageEmptyPackage.java index f50009396..270cc6ff5 100644 --- a/src/net/sourceforge/plantuml/svek/image/EntityImageEmptyPackage.java +++ b/src/net/sourceforge/plantuml/svek/image/EntityImageEmptyPackage.java @@ -45,11 +45,14 @@ import net.sourceforge.plantuml.Guillemet; import net.sourceforge.plantuml.ISkinParam; import net.sourceforge.plantuml.SkinParamUtils; import net.sourceforge.plantuml.Url; +import net.sourceforge.plantuml.activitydiagram3.ftile.EntityImageLegend; import net.sourceforge.plantuml.cucadiagram.Display; +import net.sourceforge.plantuml.cucadiagram.DisplayPositionned; import net.sourceforge.plantuml.cucadiagram.EntityPortion; import net.sourceforge.plantuml.cucadiagram.ILeaf; import net.sourceforge.plantuml.cucadiagram.PortionShower; import net.sourceforge.plantuml.cucadiagram.Stereotype; +import net.sourceforge.plantuml.cucadiagram.entity.EntityImpl; import net.sourceforge.plantuml.graphic.FontConfiguration; import net.sourceforge.plantuml.graphic.HorizontalAlignment; import net.sourceforge.plantuml.graphic.StringBounder; @@ -87,13 +90,20 @@ public class EntityImageEmptyPackage extends AbstractEntityImage { HorizontalAlignment.CENTER, skinParam); this.url = entity.getUrl99(); - if (stereotype == null || stereotype.getLabel(Guillemet.DOUBLE_COMPARATOR) == null - || portionShower.showPortion(EntityPortion.STEREOTYPE, entity) == false) { - stereoBlock = TextBlockUtils.empty(0, 0); + final DisplayPositionned legend = ((EntityImpl) entity).getLegend(); + if (legend != null) { + final TextBlock legendBlock = EntityImageLegend.create(legend.getDisplay(), skinParam); + stereoBlock = legendBlock; } else { - stereoBlock = TextBlockUtils.withMargin(Display.create(stereotype.getLabels(skinParam.guillemet())).create( - new FontConfiguration(getSkinParam(), FontParam.PACKAGE_STEREOTYPE, stereotype), - HorizontalAlignment.CENTER, skinParam), 1, 0); + if (stereotype == null || stereotype.getLabel(Guillemet.DOUBLE_COMPARATOR) == null + || portionShower.showPortion(EntityPortion.STEREOTYPE, entity) == false) { + stereoBlock = TextBlockUtils.empty(0, 0); + } else { + stereoBlock = TextBlockUtils.withMargin(Display.create(stereotype.getLabels(skinParam.guillemet())) + .create(new FontConfiguration(getSkinParam(), FontParam.PACKAGE_STEREOTYPE, stereotype), + HorizontalAlignment.CENTER, skinParam), + 1, 0); + } } } diff --git a/src/net/sourceforge/plantuml/svek/image/Footprint.java b/src/net/sourceforge/plantuml/svek/image/Footprint.java index 860bfdb37..2935fae3b 100644 --- a/src/net/sourceforge/plantuml/svek/image/Footprint.java +++ b/src/net/sourceforge/plantuml/svek/image/Footprint.java @@ -42,6 +42,7 @@ import java.util.List; import net.sourceforge.plantuml.graphic.StringBounder; import net.sourceforge.plantuml.graphic.UDrawable; +import net.sourceforge.plantuml.ugraphic.UBackground; import net.sourceforge.plantuml.ugraphic.UChange; import net.sourceforge.plantuml.ugraphic.UGraphic; import net.sourceforge.plantuml.ugraphic.UGraphicNo; @@ -51,6 +52,7 @@ import net.sourceforge.plantuml.ugraphic.ULine; import net.sourceforge.plantuml.ugraphic.UParam; import net.sourceforge.plantuml.ugraphic.UParamNull; import net.sourceforge.plantuml.ugraphic.UPath; +import net.sourceforge.plantuml.ugraphic.URectangle; import net.sourceforge.plantuml.ugraphic.UShape; import net.sourceforge.plantuml.ugraphic.UStroke; import net.sourceforge.plantuml.ugraphic.UText; @@ -93,7 +95,7 @@ public class Footprint { public UGraphic apply(UChange change) { if (change instanceof UTranslate) { return new MyUGraphic(all, translate.compose((UTranslate) change)); - } else if (change instanceof UStroke || change instanceof HColor) { + } else if (change instanceof UStroke || change instanceof HColor || change instanceof UBackground) { return new MyUGraphic(all, translate); } throw new UnsupportedOperationException(); @@ -121,6 +123,8 @@ public class Footprint { drawImage(x, y, (UImage) shape); } else if (shape instanceof UPath) { drawPath(x, y, (UPath) shape); + } else if (shape instanceof URectangle) { + drawRectangle(x, y, (URectangle) shape); } else { throw new UnsupportedOperationException(shape.getClass().toString()); } @@ -156,6 +160,11 @@ public class Footprint { addPoint(x + path.getMaxX(), y + path.getMaxY()); } + private void drawRectangle(double x, double y, URectangle rect) { + addPoint(x, y); + addPoint(x + rect.getWidth(), y + rect.getHeight()); + } + public void flushUg() { } diff --git a/src/net/sourceforge/plantuml/timingdiagram/graphic/Ribbon.java b/src/net/sourceforge/plantuml/timingdiagram/graphic/Ribbon.java index 9a0c0ff95..e9e0383ec 100644 --- a/src/net/sourceforge/plantuml/timingdiagram/graphic/Ribbon.java +++ b/src/net/sourceforge/plantuml/timingdiagram/graphic/Ribbon.java @@ -90,7 +90,8 @@ public class Ribbon implements PDrawing { public IntricatedPoint getTimeProjection(StringBounder stringBounder, TimeTick tick) { final double x = ruler.getPosInPixel(tick); - final double y = getHeightForConstraints(stringBounder) + getRibbonHeight() / 2; + final double y = getHeightForConstraints(stringBounder) + getHeightForNotes(stringBounder, Position.TOP) + + getHeightForTopComment(stringBounder) + getRibbonHeight() / 2; for (ChangeState change : changes) { if (change.getWhen().compareTo(tick) == 0) { return new IntricatedPoint(new Point2D.Double(x, y), new Point2D.Double(x, y)); diff --git a/src/net/sourceforge/plantuml/ugraphic/svg/DriverEllipseSvg.java b/src/net/sourceforge/plantuml/ugraphic/svg/DriverEllipseSvg.java index 77f55a6e0..0e9440d41 100644 --- a/src/net/sourceforge/plantuml/ugraphic/svg/DriverEllipseSvg.java +++ b/src/net/sourceforge/plantuml/ugraphic/svg/DriverEllipseSvg.java @@ -72,8 +72,8 @@ public class DriverEllipseSvg implements UDriver { final HColor back = param.getBackcolor(); if (back instanceof HColorGradient) { final HColorGradient gr = (HColorGradient) back; - final String id = svg.createSvgGradient(mapper.toRGB(gr.getColor1()), - mapper.toRGB(gr.getColor2()), gr.getPolicy()); + final String id = svg.createSvgGradient(mapper.toRGB(gr.getColor1()), mapper.toRGB(gr.getColor2()), + gr.getPolicy()); svg.setFillColor("url(#" + id + ")"); } else if (back == null || back instanceof HColorBackground) { svg.setFillColor("none"); @@ -92,15 +92,22 @@ public class DriverEllipseSvg implements UDriver { if (start == 0 && extend == 0) { svg.svgEllipse(cx, cy, width / 2, height / 2, shape.getDeltaShadow()); } else { - // http://www.itk.ilstu.edu/faculty/javila/SVG/SVG_drawing1/elliptical_curve.htm start = start + 90; - final double x1 = cx + Math.sin(start * Math.PI / 180.) * width / 2; - final double y1 = cy + Math.cos(start * Math.PI / 180.) * height / 2; - final double x2 = cx + Math.sin((start + extend) * Math.PI / 180.) * width / 2; - final double y2 = cy + Math.cos((start + extend) * Math.PI / 180.) * height / 2; - // svg.svgEllipse(x1, y1, 1, 1, 0); - // svg.svgEllipse(x2, y2, 1, 1, 0); - svg.svgArcEllipse(width / 2, height / 2, x1, y1, x2, y2); + if (extend > 0) { + // http://www.itk.ilstu.edu/faculty/javila/SVG/SVG_drawing1/elliptical_curve.htm + final double x1 = cx + Math.sin(start * Math.PI / 180.) * width / 2; + final double y1 = cy + Math.cos(start * Math.PI / 180.) * height / 2; + final double x2 = cx + Math.sin((start + extend) * Math.PI / 180.) * width / 2; + final double y2 = cy + Math.cos((start + extend) * Math.PI / 180.) * height / 2; + svg.svgArcEllipse(width / 2, height / 2, x1, y1, x2, y2); + } else { + final double x1 = cx + Math.sin((start + extend) * Math.PI / 180.) * width / 2; + final double y1 = cy + Math.cos((start + extend) * Math.PI / 180.) * height / 2; + final double x2 = cx + Math.sin(start * Math.PI / 180.) * width / 2; + final double y2 = cy + Math.cos(start * Math.PI / 180.) * height / 2; + svg.svgArcEllipse(width / 2, height / 2, x1, y1, x2, y2); + + } } } diff --git a/src/net/sourceforge/plantuml/version/PSystemVersion.java b/src/net/sourceforge/plantuml/version/PSystemVersion.java index 2c925a901..532800ab5 100644 --- a/src/net/sourceforge/plantuml/version/PSystemVersion.java +++ b/src/net/sourceforge/plantuml/version/PSystemVersion.java @@ -106,6 +106,10 @@ public class PSystemVersion extends AbstractPSystem { return getImage("arecibo.png"); } + public static BufferedImage getDotc() { + return getImage("dotc.png"); + } + public static BufferedImage getApple2Image() { return getImageWebp("apple2.png"); } diff --git a/src/net/sourceforge/plantuml/version/Version.java b/src/net/sourceforge/plantuml/version/Version.java index ab221217f..58871d92b 100644 --- a/src/net/sourceforge/plantuml/version/Version.java +++ b/src/net/sourceforge/plantuml/version/Version.java @@ -44,7 +44,7 @@ public class Version { private static final int MAJOR_SEPARATOR = 1000000; public static int version() { - return 1202016; + return 1202017; } public static int versionPatched() { @@ -93,7 +93,7 @@ public class Version { } public static long compileTime() { - return 1598214043932L; + return 1600518611890L; } public static String compileTimeString() { diff --git a/src/net/sourceforge/plantuml/version/dotc.png b/src/net/sourceforge/plantuml/version/dotc.png new file mode 100644 index 000000000..f3e84bd99 Binary files /dev/null and b/src/net/sourceforge/plantuml/version/dotc.png differ diff --git a/src/net/sourceforge/plantuml/vizjs/GraphvizJs.java b/src/net/sourceforge/plantuml/vizjs/GraphvizJs.java index fdbf7d8d6..b45373519 100644 --- a/src/net/sourceforge/plantuml/vizjs/GraphvizJs.java +++ b/src/net/sourceforge/plantuml/vizjs/GraphvizJs.java @@ -143,4 +143,8 @@ public class GraphvizJs implements Graphviz { }; } + public boolean graphviz244onWindows() { + return false; + } + } diff --git a/src/net/sourceforge/plantuml/wbs/Fork.java b/src/net/sourceforge/plantuml/wbs/Fork.java index 3bafa0af7..ce5cf951d 100644 --- a/src/net/sourceforge/plantuml/wbs/Fork.java +++ b/src/net/sourceforge/plantuml/wbs/Fork.java @@ -72,8 +72,8 @@ class Fork extends WBSTextBlock { final Dimension2D mainDim = main.calculateDimension(stringBounder); final double dx = (fullDim.getWidth() - mainDim.getWidth()) / 2; main.drawU(ug.apply(UTranslate.dx(dx))); - drawLine(ug, dx + mainDim.getWidth() / 2, mainDim.getHeight(), dx + mainDim.getWidth() / 2, mainDim.getHeight() - + deltay / 2); + drawLine(ug, dx + mainDim.getWidth() / 2, mainDim.getHeight(), dx + mainDim.getWidth() / 2, + mainDim.getHeight() + deltay / 2); double x = 0; final double y = mainDim.getHeight() + deltay; if (right.size() == 0) { @@ -102,6 +102,7 @@ class Fork extends WBSTextBlock { } final Dimension2D mainDim = main.calculateDimension(stringBounder); height += mainDim.getHeight(); + height += deltay; width = Math.max(width, mainDim.getWidth()); return new Dimension2DDouble(width, height); }