diff --git a/build.xml b/build.xml index 5a42a7c21..e96a52bed 100644 --- a/build.xml +++ b/build.xml @@ -83,6 +83,7 @@ + diff --git a/pom.xml b/pom.xml index 3f9841f86..1f08503ae 100644 --- a/pom.xml +++ b/pom.xml @@ -35,7 +35,7 @@ net.sourceforge.plantuml plantuml - 1.2020.27-SNAPSHOT + 1.2021.1-SNAPSHOT jar PlantUML diff --git a/src/net/sourceforge/plantuml/FileFormat.java b/src/net/sourceforge/plantuml/FileFormat.java index ff00bdf25..624d1394f 100644 --- a/src/net/sourceforge/plantuml/FileFormat.java +++ b/src/net/sourceforge/plantuml/FileFormat.java @@ -46,7 +46,9 @@ import java.io.IOException; import net.sourceforge.plantuml.braille.BrailleCharFactory; import net.sourceforge.plantuml.braille.UGraphicBraille; +import net.sourceforge.plantuml.graphic.FontStyle; import net.sourceforge.plantuml.graphic.StringBounder; +import net.sourceforge.plantuml.graphic.StyledString; import net.sourceforge.plantuml.png.MetadataTag; import net.sourceforge.plantuml.security.SFile; import net.sourceforge.plantuml.svg.SvgGraphics; @@ -142,10 +144,20 @@ public enum FileFormat { } static private Dimension2DDouble getJavaDimension(UFont font, String text) { - final Font javaFont = font.getFont(); - final FontMetrics fm = gg.getFontMetrics(javaFont); - final Rectangle2D rect = fm.getStringBounds(text, gg); - return new Dimension2DDouble(rect.getWidth(), rect.getHeight()); + double width = 0; + double height = 0; + for (StyledString styledString : StyledString.build(text)) { + final Font javaFont; + if (styledString.getStyle() == FontStyle.BOLD) + javaFont = font.bold().getFont(); + else + javaFont = font.getFont(); + final FontMetrics fm = gg.getFontMetrics(javaFont); + final Rectangle2D rect = fm.getStringBounds(styledString.getText(), gg); + width += rect.getWidth(); + height = Math.max(height, rect.getHeight()); + } + return new Dimension2DDouble(width, height); } private StringBounder getBrailleStringBounder() { diff --git a/src/net/sourceforge/plantuml/ISkinParam.java b/src/net/sourceforge/plantuml/ISkinParam.java index a69c50498..c1d69a15d 100644 --- a/src/net/sourceforge/plantuml/ISkinParam.java +++ b/src/net/sourceforge/plantuml/ISkinParam.java @@ -51,6 +51,7 @@ import net.sourceforge.plantuml.style.StyleBuilder; import net.sourceforge.plantuml.svek.ConditionEndStyle; import net.sourceforge.plantuml.svek.ConditionStyle; import net.sourceforge.plantuml.svek.PackageStyle; +import net.sourceforge.plantuml.svg.LengthAdjust; import net.sourceforge.plantuml.ugraphic.UFont; import net.sourceforge.plantuml.ugraphic.UStroke; import net.sourceforge.plantuml.ugraphic.color.HColor; @@ -189,5 +190,8 @@ public interface ISkinParam extends ISkinSimple { public ActorStyle actorStyle(); public void setSvgSize(String origin, String sizeToUse); + + public LengthAdjust getlengthAdjust(); + } \ No newline at end of file diff --git a/src/net/sourceforge/plantuml/PSystemBuilder.java b/src/net/sourceforge/plantuml/PSystemBuilder.java index 96b4f71af..1689482c4 100644 --- a/src/net/sourceforge/plantuml/PSystemBuilder.java +++ b/src/net/sourceforge/plantuml/PSystemBuilder.java @@ -97,6 +97,7 @@ import net.sourceforge.plantuml.version.PSystemLicenseFactory; import net.sourceforge.plantuml.version.PSystemVersionFactory; import net.sourceforge.plantuml.wbs.WBSDiagramFactory; import net.sourceforge.plantuml.wire.WireDiagramFactory; +import net.sourceforge.plantuml.yaml.YamlDiagramFactory; public class PSystemBuilder { @@ -217,6 +218,7 @@ public class PSystemBuilder { factories.add(new JsonDiagramFactory()); factories.add(new GitDiagramFactory()); factories.add(new BoardDiagramFactory()); + factories.add(new YamlDiagramFactory()); return factories; } diff --git a/src/net/sourceforge/plantuml/SkinParam.java b/src/net/sourceforge/plantuml/SkinParam.java index ba152d34f..2dbeff312 100644 --- a/src/net/sourceforge/plantuml/SkinParam.java +++ b/src/net/sourceforge/plantuml/SkinParam.java @@ -73,6 +73,7 @@ import net.sourceforge.plantuml.style.StyleLoader; import net.sourceforge.plantuml.svek.ConditionEndStyle; import net.sourceforge.plantuml.svek.ConditionStyle; import net.sourceforge.plantuml.svek.PackageStyle; +import net.sourceforge.plantuml.svg.LengthAdjust; import net.sourceforge.plantuml.ugraphic.UFont; import net.sourceforge.plantuml.ugraphic.UStroke; import net.sourceforge.plantuml.ugraphic.color.ColorMapper; @@ -113,6 +114,9 @@ public class SkinParam implements ISkinParam { if (type == UmlDiagramType.BOARD) { UseStyle.setBetaStyle(true); } + if (type == UmlDiagramType.YAML) { + UseStyle.setBetaStyle(true); + } if (type == UmlDiagramType.SEQUENCE) { // skin = "debug.skin"; // USE_STYLE2.set(true); @@ -1258,4 +1262,18 @@ public class SkinParam implements ISkinParam { return s; } + public LengthAdjust getlengthAdjust() { + final String value = getValue("lengthAdjust"); + if ("spacingAndGlyphs".equalsIgnoreCase(value)) { + return LengthAdjust.SPACING_AND_GLYPHS; + } + if ("spacing".equalsIgnoreCase(value)) { + return LengthAdjust.SPACING; + } + if ("none".equalsIgnoreCase(value)) { + return LengthAdjust.NONE; + } + return LengthAdjust.defaultValue(); + } + } diff --git a/src/net/sourceforge/plantuml/SkinParamDelegator.java b/src/net/sourceforge/plantuml/SkinParamDelegator.java index c1771f81b..b9292535c 100644 --- a/src/net/sourceforge/plantuml/SkinParamDelegator.java +++ b/src/net/sourceforge/plantuml/SkinParamDelegator.java @@ -53,6 +53,7 @@ import net.sourceforge.plantuml.style.StyleBuilder; import net.sourceforge.plantuml.svek.ConditionEndStyle; import net.sourceforge.plantuml.svek.ConditionStyle; import net.sourceforge.plantuml.svek.PackageStyle; +import net.sourceforge.plantuml.svg.LengthAdjust; import net.sourceforge.plantuml.ugraphic.UFont; import net.sourceforge.plantuml.ugraphic.UStroke; import net.sourceforge.plantuml.ugraphic.color.ColorMapper; @@ -372,4 +373,8 @@ public class SkinParamDelegator implements ISkinParam { return skinParam.transformStringForSizeHack(s); } + public LengthAdjust getlengthAdjust() { + return skinParam.getlengthAdjust(); + } + } diff --git a/src/net/sourceforge/plantuml/StringUtils.java b/src/net/sourceforge/plantuml/StringUtils.java index cbcb4b4d7..f194c4152 100644 --- a/src/net/sourceforge/plantuml/StringUtils.java +++ b/src/net/sourceforge/plantuml/StringUtils.java @@ -68,6 +68,9 @@ public class StringUtils { public static final char PACKAGE_PRIVATE_METHOD = '\uEEF5'; public static final char PUBLIC_METHOD = '\uEEF4'; public static final char IE_MANDATORY = '\uEEF3'; + + public static final char BOLD_START = '\uEEF2'; + public static final char BOLD_END = '\uEEF1'; // Used in BackSlash public static final char PRIVATE_BLOCK = '\uE000'; diff --git a/src/net/sourceforge/plantuml/TitledDiagram.java b/src/net/sourceforge/plantuml/TitledDiagram.java index 8c32b482b..a44e55377 100644 --- a/src/net/sourceforge/plantuml/TitledDiagram.java +++ b/src/net/sourceforge/plantuml/TitledDiagram.java @@ -58,6 +58,7 @@ public abstract class TitledDiagram extends AbstractPSystem implements Diagram, private final DisplaySection header = DisplaySection.none(); private final DisplaySection footer = DisplaySection.none(); private Display mainFrame; + private final UmlDiagramType type; private final SkinParam skinParam; @@ -67,22 +68,25 @@ public abstract class TitledDiagram extends AbstractPSystem implements Diagram, return pragma; } - public TitledDiagram() { - this.skinParam = SkinParam.create(getUmlDiagramType()); + public TitledDiagram(UmlDiagramType type) { + this.type = type; + this.skinParam = SkinParam.create(type); } public final StyleBuilder getCurrentStyleBuilder() { return skinParam.getCurrentStyleBuilder(); } - public TitledDiagram(ISkinSimple orig) { - this(); + public TitledDiagram(UmlDiagramType type, ISkinSimple orig) { + this(type); if (orig != null) { this.skinParam.copyAllFrom(orig); } } - abstract public UmlDiagramType getUmlDiagramType(); + final public UmlDiagramType getUmlDiagramType() { + return type; + } public final ISkinParam getSkinParam() { return skinParam; diff --git a/src/net/sourceforge/plantuml/UmlDiagram.java b/src/net/sourceforge/plantuml/UmlDiagram.java index 0ffd3b4c8..6e39b76fc 100644 --- a/src/net/sourceforge/plantuml/UmlDiagram.java +++ b/src/net/sourceforge/plantuml/UmlDiagram.java @@ -98,12 +98,12 @@ public abstract class UmlDiagram extends TitledDiagram implements Diagram, Annot private Animation animation; - public UmlDiagram() { - super(); + public UmlDiagram(UmlDiagramType type) { + super(type); } - public UmlDiagram(ISkinSimple orig) { - super(orig); + public UmlDiagram(UmlDiagramType type, ISkinSimple orig) { + super(type, orig); } final public int getMinwidth() { diff --git a/src/net/sourceforge/plantuml/UmlDiagramType.java b/src/net/sourceforge/plantuml/UmlDiagramType.java index 353491dd9..3311a9d73 100644 --- a/src/net/sourceforge/plantuml/UmlDiagramType.java +++ b/src/net/sourceforge/plantuml/UmlDiagramType.java @@ -39,7 +39,7 @@ import net.sourceforge.plantuml.style.SName; public enum UmlDiagramType { SEQUENCE, STATE, CLASS, OBJECT, ACTIVITY, DESCRIPTION, COMPOSITE, FLOW, TIMING, BPM, NWDIAG, MINDMAP, WBS, WIRE, - HELP, GANTT, SALT, JSON, GIT, BOARD; + HELP, GANTT, SALT, JSON, GIT, BOARD, YAML; public SName getStyleName() { if (this == SEQUENCE) { diff --git a/src/net/sourceforge/plantuml/activitydiagram/ActivityDiagram.java b/src/net/sourceforge/plantuml/activitydiagram/ActivityDiagram.java index 061199041..922a20389 100644 --- a/src/net/sourceforge/plantuml/activitydiagram/ActivityDiagram.java +++ b/src/net/sourceforge/plantuml/activitydiagram/ActivityDiagram.java @@ -61,7 +61,7 @@ public class ActivityDiagram extends CucaDiagram { private ConditionalContext currentContext; public ActivityDiagram(ISkinSimple skinParam) { - super(skinParam); + super(UmlDiagramType.ACTIVITY, skinParam); setNamespaceSeparator(null); } @@ -163,11 +163,6 @@ public class ActivityDiagram extends CucaDiagram { return lastEntityBrancheConsulted; } - @Override - public UmlDiagramType getUmlDiagramType() { - return UmlDiagramType.ACTIVITY; - } - public final ConditionalContext getCurrentContext() { return currentContext; } diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ActivityDiagram3.java b/src/net/sourceforge/plantuml/activitydiagram3/ActivityDiagram3.java index 13ad44103..94559c6f7 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ActivityDiagram3.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ActivityDiagram3.java @@ -82,7 +82,7 @@ public class ActivityDiagram3 extends UmlDiagram { private final Swimlanes swinlanes = new Swimlanes(getSkinParam(), getPragma()); public ActivityDiagram3(ISkinSimple skinParam) { - super(skinParam); + super(UmlDiagramType.ACTIVITY, skinParam); } private void manageSwimlaneStrategy() { @@ -199,11 +199,6 @@ public class ActivityDiagram3 extends UmlDiagram { return new DiagramDescription("activity3"); } - @Override - public UmlDiagramType getUmlDiagramType() { - return UmlDiagramType.ACTIVITY; - } - @Override protected ImageData exportDiagramInternal(OutputStream os, int index, FileFormatOption fileFormatOption) throws IOException { diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/UGraphicInterceptorUDrawable2.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/UGraphicInterceptorUDrawable2.java index d399cdacd..be7257e84 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/UGraphicInterceptorUDrawable2.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/UGraphicInterceptorUDrawable2.java @@ -47,6 +47,7 @@ import net.sourceforge.plantuml.ugraphic.UGraphic; import net.sourceforge.plantuml.ugraphic.ULine; import net.sourceforge.plantuml.ugraphic.UShape; import net.sourceforge.plantuml.ugraphic.UTranslate; +import net.sourceforge.plantuml.ugraphic.color.HColor; import net.sourceforge.plantuml.ugraphic.color.HColorUtils; public class UGraphicInterceptorUDrawable2 extends UGraphicDelegator { @@ -85,10 +86,11 @@ public class UGraphicInterceptorUDrawable2 extends UGraphicDelegator { } private void drawGoto(FtileGoto ftile) { + final HColor gotoColor = HColorUtils.MY_RED; + final FtileGeometry geom = ftile.calculateDimension(getStringBounder()); final Point2D pt = geom.getPointIn(); - UGraphic ugGoto = getUg().apply(HColorUtils.GREEN).apply( - HColorUtils.GREEN.bg()); + UGraphic ugGoto = getUg().apply(gotoColor).apply(gotoColor.bg()); ugGoto = ugGoto.apply(new UTranslate(pt)); final UTranslate posNow = getPosition(); final UTranslate dest = positions.get(ftile.getName()); diff --git a/src/net/sourceforge/plantuml/board/BoardDiagram.java b/src/net/sourceforge/plantuml/board/BoardDiagram.java index 2371508c7..e4a1942ea 100644 --- a/src/net/sourceforge/plantuml/board/BoardDiagram.java +++ b/src/net/sourceforge/plantuml/board/BoardDiagram.java @@ -80,9 +80,8 @@ public class BoardDiagram extends UmlDiagram { return new DiagramDescription("Board"); } - @Override - public UmlDiagramType getUmlDiagramType() { - return UmlDiagramType.BOARD; + public BoardDiagram() { + super(UmlDiagramType.BOARD); } @Override diff --git a/src/net/sourceforge/plantuml/bpm/BpmDiagram.java b/src/net/sourceforge/plantuml/bpm/BpmDiagram.java index 8b71abbfd..e2d1ca9e7 100644 --- a/src/net/sourceforge/plantuml/bpm/BpmDiagram.java +++ b/src/net/sourceforge/plantuml/bpm/BpmDiagram.java @@ -78,9 +78,8 @@ public class BpmDiagram extends UmlDiagram { return new DiagramDescription("(Bpm Diagram)"); } - @Override - public UmlDiagramType getUmlDiagramType() { - return UmlDiagramType.BPM; + public BpmDiagram() { + super(UmlDiagramType.BPM); } @Override diff --git a/src/net/sourceforge/plantuml/classdiagram/AbstractEntityDiagram.java b/src/net/sourceforge/plantuml/classdiagram/AbstractEntityDiagram.java index a219e41ed..0baa074ed 100644 --- a/src/net/sourceforge/plantuml/classdiagram/AbstractEntityDiagram.java +++ b/src/net/sourceforge/plantuml/classdiagram/AbstractEntityDiagram.java @@ -41,13 +41,14 @@ import java.util.Collections; import java.util.List; import net.sourceforge.plantuml.ISkinSimple; +import net.sourceforge.plantuml.UmlDiagramType; import net.sourceforge.plantuml.core.DiagramDescription; import net.sourceforge.plantuml.cucadiagram.CucaDiagram; public abstract class AbstractEntityDiagram extends CucaDiagram { - public AbstractEntityDiagram(ISkinSimple orig) { - super(orig); + public AbstractEntityDiagram(UmlDiagramType type, ISkinSimple orig) { + super(type, orig); } final protected List getDotStrings() { diff --git a/src/net/sourceforge/plantuml/classdiagram/ClassDiagram.java b/src/net/sourceforge/plantuml/classdiagram/ClassDiagram.java index 9ab5beede..6a1f7ca1b 100644 --- a/src/net/sourceforge/plantuml/classdiagram/ClassDiagram.java +++ b/src/net/sourceforge/plantuml/classdiagram/ClassDiagram.java @@ -67,7 +67,7 @@ import net.sourceforge.plantuml.ugraphic.color.HColor; public class ClassDiagram extends AbstractClassOrObjectDiagram { public ClassDiagram(ISkinSimple skinParam) { - super(skinParam); + super(UmlDiagramType.CLASS, skinParam); } private Code getShortName1972(Code code) { @@ -170,11 +170,6 @@ public class ClassDiagram extends AbstractClassOrObjectDiagram { return super.leafExist(getFullyQualifiedCode1972(code)); } - @Override - public UmlDiagramType getUmlDiagramType() { - return UmlDiagramType.CLASS; - } - private boolean allowMixing; public void setAllowMixing(boolean allowMixing) { diff --git a/src/net/sourceforge/plantuml/command/CommandCaption.java b/src/net/sourceforge/plantuml/command/CommandCaption.java index e05583db6..b8b2c5634 100644 --- a/src/net/sourceforge/plantuml/command/CommandCaption.java +++ b/src/net/sourceforge/plantuml/command/CommandCaption.java @@ -40,6 +40,7 @@ import net.sourceforge.plantuml.TitledDiagram; import net.sourceforge.plantuml.command.regex.IRegex; import net.sourceforge.plantuml.command.regex.RegexConcat; import net.sourceforge.plantuml.command.regex.RegexLeaf; +import net.sourceforge.plantuml.command.regex.RegexOr; import net.sourceforge.plantuml.command.regex.RegexResult; import net.sourceforge.plantuml.cucadiagram.Display; import net.sourceforge.plantuml.cucadiagram.DisplayPositionned; @@ -57,13 +58,16 @@ public class CommandCaption extends SingleLineCommand2 { RegexLeaf.start(), // new RegexLeaf("caption"), // new RegexLeaf("(?:[%s]*:[%s]*|[%s]+)"), // - new RegexLeaf("DISPLAY", "(.*[\\p{L}0-9_.].*)"), RegexLeaf.end()); // + new RegexOr(// + new RegexLeaf("DISPLAY1", "[%g](.*)[%g]"), // + new RegexLeaf("DISPLAY2", "(.*[\\p{L}0-9_.].*)")), // + RegexLeaf.end()); // } @Override protected CommandExecutionResult executeArg(TitledDiagram diagram, LineLocation location, RegexResult arg) { - diagram.setCaption(DisplayPositionned.single(Display.getWithNewlines(arg.get("DISPLAY", 0)), - HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM)); + final Display s = Display.getWithNewlines(arg.getLazzy("DISPLAY", 0)); + diagram.setCaption(DisplayPositionned.single(s, HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM)); return CommandExecutionResult.ok(); } diff --git a/src/net/sourceforge/plantuml/command/CommandFooter.java b/src/net/sourceforge/plantuml/command/CommandFooter.java index c628f8c71..c33b3d925 100644 --- a/src/net/sourceforge/plantuml/command/CommandFooter.java +++ b/src/net/sourceforge/plantuml/command/CommandFooter.java @@ -63,7 +63,10 @@ public class CommandFooter extends SingleLineCommand2 { new RegexOr( // new RegexConcat(RegexLeaf.spaceZeroOrMore(), new RegexLeaf(":"), RegexLeaf.spaceZeroOrMore()), // RegexLeaf.spaceOneOrMore()), // - new RegexLeaf("LABEL", "(.*[\\p{L}0-9_.].*)"), RegexLeaf.end()); // + new RegexOr(// + new RegexLeaf("LABEL1", "[%g](.*)[%g]"), // + new RegexLeaf("LABEL2", "(.*[\\p{L}0-9_.].*)")), // + RegexLeaf.end()); // } @Override @@ -74,7 +77,8 @@ public class CommandFooter extends SingleLineCommand2 { ha = FontParam.FOOTER.getStyleDefinition(null).getMergedStyle(diagram.getCurrentStyleBuilder()) .getHorizontalAlignment(); } - diagram.getFooter().putDisplay(Display.getWithNewlines(arg.get("LABEL", 0)), ha); + final Display s = Display.getWithNewlines(arg.getLazzy("LABEL", 0)); + diagram.getFooter().putDisplay(s, ha); return CommandExecutionResult.ok(); } diff --git a/src/net/sourceforge/plantuml/command/CommandHeader.java b/src/net/sourceforge/plantuml/command/CommandHeader.java index 8a49f0377..29e7e2029 100644 --- a/src/net/sourceforge/plantuml/command/CommandHeader.java +++ b/src/net/sourceforge/plantuml/command/CommandHeader.java @@ -65,7 +65,10 @@ public class CommandHeader extends SingleLineCommand2 { new RegexLeaf(":"), // RegexLeaf.spaceZeroOrMore()), // RegexLeaf.spaceOneOrMore()), // - new RegexLeaf("LABEL", "(.*[\\p{L}0-9_.].*)"), RegexLeaf.end()); // + new RegexOr(// + new RegexLeaf("LABEL1", "[%g](.*)[%g]"), // + new RegexLeaf("LABEL2", "(.*[\\p{L}0-9_.].*)")), // + RegexLeaf.end()); // } @Override @@ -76,7 +79,8 @@ public class CommandHeader extends SingleLineCommand2 { ha = FontParam.HEADER.getStyleDefinition(null).getMergedStyle(diagram.getCurrentStyleBuilder()) .getHorizontalAlignment(); } - diagram.getHeader().putDisplay(Display.getWithNewlines(arg.get("LABEL", 0)), ha); + final Display s = Display.getWithNewlines(arg.getLazzy("LABEL", 0)); + diagram.getHeader().putDisplay(s, ha); return CommandExecutionResult.ok(); } } diff --git a/src/net/sourceforge/plantuml/command/CommandLegend.java b/src/net/sourceforge/plantuml/command/CommandLegend.java new file mode 100644 index 000000000..5bec424b6 --- /dev/null +++ b/src/net/sourceforge/plantuml/command/CommandLegend.java @@ -0,0 +1,73 @@ +/* ======================================================================== + * 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.command; + +import net.sourceforge.plantuml.LineLocation; +import net.sourceforge.plantuml.TitledDiagram; +import net.sourceforge.plantuml.command.regex.IRegex; +import net.sourceforge.plantuml.command.regex.RegexConcat; +import net.sourceforge.plantuml.command.regex.RegexLeaf; +import net.sourceforge.plantuml.command.regex.RegexOr; +import net.sourceforge.plantuml.command.regex.RegexResult; +import net.sourceforge.plantuml.cucadiagram.Display; +import net.sourceforge.plantuml.cucadiagram.DisplayPositionned; +import net.sourceforge.plantuml.graphic.HorizontalAlignment; +import net.sourceforge.plantuml.graphic.VerticalAlignment; + +public class CommandLegend extends SingleLineCommand2 { + + public CommandLegend() { + super(getRegexConcat()); + } + + static IRegex getRegexConcat() { + return RegexConcat.build(CommandLegend.class.getName(), // + RegexLeaf.start(), // + new RegexLeaf("legend"), // + new RegexLeaf("(?:[%s]*:[%s]*|[%s]+)"), // + new RegexOr(// + new RegexLeaf("LEGEND1", "[%g](.*)[%g]"), // + new RegexLeaf("LEGEND2", "(.*[\\p{L}0-9_.].*)")), // + RegexLeaf.end()); // + } + + @Override + protected CommandExecutionResult executeArg(TitledDiagram diagram, LineLocation location, RegexResult arg) { + final Display s = Display.getWithNewlines(arg.getLazzy("LEGEND", 0)); + diagram.setLegend(DisplayPositionned.single(s, HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM)); + return CommandExecutionResult.ok(); + } +} diff --git a/src/net/sourceforge/plantuml/command/CommandTitle.java b/src/net/sourceforge/plantuml/command/CommandTitle.java index 864af6c44..a69825010 100644 --- a/src/net/sourceforge/plantuml/command/CommandTitle.java +++ b/src/net/sourceforge/plantuml/command/CommandTitle.java @@ -40,6 +40,7 @@ import net.sourceforge.plantuml.TitledDiagram; import net.sourceforge.plantuml.command.regex.IRegex; import net.sourceforge.plantuml.command.regex.RegexConcat; import net.sourceforge.plantuml.command.regex.RegexLeaf; +import net.sourceforge.plantuml.command.regex.RegexOr; import net.sourceforge.plantuml.command.regex.RegexResult; import net.sourceforge.plantuml.cucadiagram.Display; import net.sourceforge.plantuml.cucadiagram.DisplayPositionned; @@ -57,13 +58,16 @@ public class CommandTitle extends SingleLineCommand2 { RegexLeaf.start(), // new RegexLeaf("title"), // new RegexLeaf("(?:[%s]*:[%s]*|[%s]+)"), // - new RegexLeaf("TITLE", "(.*[\\p{L}0-9_.].*)"), RegexLeaf.end()); // + new RegexOr(// + new RegexLeaf("TITLE1", "[%g](.*)[%g]"), // + new RegexLeaf("TITLE2", "(.*[\\p{L}0-9_.].*)")), // + RegexLeaf.end()); // } @Override protected CommandExecutionResult executeArg(TitledDiagram diagram, LineLocation location, RegexResult arg) { - diagram.setTitle(DisplayPositionned.single(Display.getWithNewlines(arg.get("TITLE", 0)), - HorizontalAlignment.CENTER, VerticalAlignment.TOP)); + final Display s = Display.getWithNewlines(arg.getLazzy("TITLE", 0)); + diagram.setTitle(DisplayPositionned.single(s, HorizontalAlignment.CENTER, VerticalAlignment.TOP)); return CommandExecutionResult.ok(); } } diff --git a/src/net/sourceforge/plantuml/command/PSystemCommandFactory.java b/src/net/sourceforge/plantuml/command/PSystemCommandFactory.java index 801c1658c..31826e56d 100644 --- a/src/net/sourceforge/plantuml/command/PSystemCommandFactory.java +++ b/src/net/sourceforge/plantuml/command/PSystemCommandFactory.java @@ -262,6 +262,7 @@ public abstract class PSystemCommandFactory extends PSystemAbstractFactory { cmds.add(new CommandMultilinesCaption()); cmds.add(new CommandMultilinesTitle()); cmds.add(new CommandMultilinesLegend()); + cmds.add(new CommandLegend()); cmds.add(new CommandFooter()); cmds.add(new CommandMultilinesFooter()); diff --git a/src/net/sourceforge/plantuml/compositediagram/CompositeDiagram.java b/src/net/sourceforge/plantuml/compositediagram/CompositeDiagram.java index 25a80f879..b438035f8 100644 --- a/src/net/sourceforge/plantuml/compositediagram/CompositeDiagram.java +++ b/src/net/sourceforge/plantuml/compositediagram/CompositeDiagram.java @@ -47,7 +47,7 @@ import net.sourceforge.plantuml.graphic.USymbol; public class CompositeDiagram extends AbstractEntityDiagram { public CompositeDiagram(ISkinSimple skinParam) { - super(skinParam); + super(UmlDiagramType.COMPOSITE, skinParam); } @Override @@ -63,9 +63,4 @@ public class CompositeDiagram extends AbstractEntityDiagram { return getOrCreateLeafDefault(ident, code, type, symbol); } - @Override - public UmlDiagramType getUmlDiagramType() { - return UmlDiagramType.COMPOSITE; - } - } diff --git a/src/net/sourceforge/plantuml/core/DiagramType.java b/src/net/sourceforge/plantuml/core/DiagramType.java index d5984d0fb..8a0435518 100644 --- a/src/net/sourceforge/plantuml/core/DiagramType.java +++ b/src/net/sourceforge/plantuml/core/DiagramType.java @@ -39,7 +39,7 @@ import net.sourceforge.plantuml.utils.StartUtils; public enum DiagramType { UML, BPM, DITAA, DOT, PROJECT, JCCKIT, SALT, FLOW, CREOLE, JUNGLE, CUTE, MATH, LATEX, - DEFINITION, GANTT, NW, MINDMAP, WBS, WIRE, JSON, GIT, BOARD, + DEFINITION, GANTT, NW, MINDMAP, WBS, WIRE, JSON, GIT, BOARD, YAML, UNKNOWN; static public DiagramType getTypeFromArobaseStart(String s) { @@ -113,6 +113,9 @@ public enum DiagramType { if (StartUtils.startsWithSymbolAnd("startboard", s)) { return BOARD; } + if (StartUtils.startsWithSymbolAnd("startyaml", s)) { + return YAML; + } return UNKNOWN; } } diff --git a/src/net/sourceforge/plantuml/creole/command/CommandCreoleStyle.java b/src/net/sourceforge/plantuml/creole/command/CommandCreoleStyle.java index 3a03ab8bc..f5972488f 100644 --- a/src/net/sourceforge/plantuml/creole/command/CommandCreoleStyle.java +++ b/src/net/sourceforge/plantuml/creole/command/CommandCreoleStyle.java @@ -50,7 +50,7 @@ public class CommandCreoleStyle implements Command { private final FontStyle style; private final boolean tryExtendedColor; - public static CommandCreoleStyle createCreole(FontStyle style) { + public static Command createCreole(FontStyle style) { return new CommandCreoleStyle("^(" + style.getCreoleSyntax() + "(.+?)" + style.getCreoleSyntax() + ")", style, false); } diff --git a/src/net/sourceforge/plantuml/creole/command/CommandCreoleStyle2.java b/src/net/sourceforge/plantuml/creole/command/CommandCreoleStyle2.java new file mode 100644 index 000000000..93e6550e9 --- /dev/null +++ b/src/net/sourceforge/plantuml/creole/command/CommandCreoleStyle2.java @@ -0,0 +1,89 @@ +/* ======================================================================== + * 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.creole.command; + +import net.sourceforge.plantuml.StringUtils; +import net.sourceforge.plantuml.command.regex.Matcher2; +import net.sourceforge.plantuml.command.regex.MyPattern; +import net.sourceforge.plantuml.command.regex.Pattern2; +import net.sourceforge.plantuml.creole.legacy.StripeSimple; +import net.sourceforge.plantuml.graphic.FontStyle; + +public class CommandCreoleStyle2 implements Command { + + private final Pattern2 p; + private final FontStyle style; + + public static Command createCreole(FontStyle style) { + return new CommandCreoleStyle2("^(" + style.getCreoleSyntax() + "(.+?)" + style.getCreoleSyntax() + ")", style); + } + + public static Command createLegacy(FontStyle style) { + return new CommandCreoleStyle2( + "^((" + style.getActivationPattern() + ")(.+?)" + style.getDeactivationPattern() + ")", style); + } + + public static Command createLegacyEol(FontStyle style) { + return new CommandCreoleStyle2("^((" + style.getActivationPattern() + ")(.+))$", style); + } + + private CommandCreoleStyle2(String p, FontStyle style) { + this.p = MyPattern.cmpile(p); + this.style = style; + } + + public String executeAndGetRemaining(final String line, StripeSimple stripe) { + final Matcher2 m = p.matcher(line); + if (m.find() == false) { + throw new IllegalStateException(); + } + + final int groupCount = m.groupCount(); + final String part1 = m.group(groupCount); + final String part2 = line.substring(m.group(1).length()); + return StringUtils.BOLD_START + part1 + StringUtils.BOLD_END + part2; + + } + + public int matchingSize(String line) { + final Matcher2 m = p.matcher(line); + if (m.find() == false) { + return 0; + } + return m.group(1).length(); + } + +} diff --git a/src/net/sourceforge/plantuml/creole/legacy/StripeSimple.java b/src/net/sourceforge/plantuml/creole/legacy/StripeSimple.java index 5b7ab8883..a6848290f 100644 --- a/src/net/sourceforge/plantuml/creole/legacy/StripeSimple.java +++ b/src/net/sourceforge/plantuml/creole/legacy/StripeSimple.java @@ -69,6 +69,7 @@ import net.sourceforge.plantuml.creole.command.CommandCreoleSizeChange; import net.sourceforge.plantuml.creole.command.CommandCreoleSpace; import net.sourceforge.plantuml.creole.command.CommandCreoleSprite; import net.sourceforge.plantuml.creole.command.CommandCreoleStyle; +import net.sourceforge.plantuml.creole.command.CommandCreoleStyle2; import net.sourceforge.plantuml.creole.command.CommandCreoleSvgAttributeChange; import net.sourceforge.plantuml.creole.command.CommandCreoleUrl; import net.sourceforge.plantuml.graphic.FontConfiguration; @@ -113,6 +114,8 @@ public class StripeSimple implements Stripe { return header; } + public final static boolean TSPAN = false; + public StripeSimple(FontConfiguration fontConfiguration, StripeStyle style, CreoleContext context, ISkinSimple skinParam, CreoleMode modeSimpleLine) { this.fontConfiguration = fontConfiguration; @@ -120,9 +123,16 @@ public class StripeSimple implements Stripe { this.skinParam = skinParam; // class Splitter - this.commands.add(CommandCreoleStyle.createCreole(FontStyle.BOLD)); - this.commands.add(CommandCreoleStyle.createLegacy(FontStyle.BOLD)); - this.commands.add(CommandCreoleStyle.createLegacyEol(FontStyle.BOLD)); + if (TSPAN) { + this.commands.add(CommandCreoleStyle2.createCreole(FontStyle.BOLD)); + this.commands.add(CommandCreoleStyle2.createLegacy(FontStyle.BOLD)); + this.commands.add(CommandCreoleStyle2.createLegacyEol(FontStyle.BOLD)); + } else { + this.commands.add(CommandCreoleStyle.createCreole(FontStyle.BOLD)); + this.commands.add(CommandCreoleStyle.createLegacy(FontStyle.BOLD)); + this.commands.add(CommandCreoleStyle.createLegacyEol(FontStyle.BOLD)); + } + this.commands.add(CommandCreoleStyle.createCreole(FontStyle.ITALIC)); this.commands.add(CommandCreoleStyle.createLegacy(FontStyle.ITALIC)); this.commands.add(CommandCreoleStyle.createLegacyEol(FontStyle.ITALIC)); diff --git a/src/net/sourceforge/plantuml/cucadiagram/CucaDiagram.java b/src/net/sourceforge/plantuml/cucadiagram/CucaDiagram.java index 289c4c790..5ab89226d 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/CucaDiagram.java +++ b/src/net/sourceforge/plantuml/cucadiagram/CucaDiagram.java @@ -118,8 +118,8 @@ public abstract class CucaDiagram extends UmlDiagram implements GroupHierarchy, return ident; } - public CucaDiagram(ISkinSimple orig) { - super(orig); + public CucaDiagram(UmlDiagramType type, ISkinSimple orig) { + super(type, orig); this.stacks2.add(Ident.empty()); } diff --git a/src/net/sourceforge/plantuml/cucadiagram/dot/AbstractGraphviz.java b/src/net/sourceforge/plantuml/cucadiagram/dot/AbstractGraphviz.java index 095a8d319..8328e8a1d 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/dot/AbstractGraphviz.java +++ b/src/net/sourceforge/plantuml/cucadiagram/dot/AbstractGraphviz.java @@ -77,10 +77,14 @@ abstract class AbstractGraphviz implements Graphviz { this.dotString = dotString; this.type = type; } + + protected boolean findExecutableOnPath() { + return true; + } - protected File searchDotExe() { + final protected File searchDotExe() { String getenv = GraphvizUtils.getenvGraphvizDot(); - if (getenv == null) { + if (findExecutableOnPath() && getenv == null) { getenv = findExecutableOnPath(getExeName()); } if (getenv == null) { diff --git a/src/net/sourceforge/plantuml/cucadiagram/dot/GraphvizWindowsLite.java b/src/net/sourceforge/plantuml/cucadiagram/dot/GraphvizWindowsLite.java index 7b55b5bab..7a12b1b6c 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/dot/GraphvizWindowsLite.java +++ b/src/net/sourceforge/plantuml/cucadiagram/dot/GraphvizWindowsLite.java @@ -46,8 +46,8 @@ class GraphvizWindowsLite extends AbstractGraphviz { static private File specificDotExe; @Override - protected File searchDotExe() { - return specificDotExe(); + protected boolean findExecutableOnPath() { + return false; } @Override diff --git a/src/net/sourceforge/plantuml/descdiagram/DescriptionDiagram.java b/src/net/sourceforge/plantuml/descdiagram/DescriptionDiagram.java index 944527f12..f9475f900 100644 --- a/src/net/sourceforge/plantuml/descdiagram/DescriptionDiagram.java +++ b/src/net/sourceforge/plantuml/descdiagram/DescriptionDiagram.java @@ -48,7 +48,7 @@ import net.sourceforge.plantuml.graphic.USymbol; public class DescriptionDiagram extends AbstractEntityDiagram { public DescriptionDiagram(ISkinSimple skinParam) { - super(skinParam); + super(UmlDiagramType.DESCRIPTION, skinParam); } @Override @@ -74,7 +74,7 @@ public class DescriptionDiagram extends AbstractEntityDiagram { if (type == null) { String codeString = code.getName(); if (codeString.startsWith("[") && codeString.endsWith("]")) { - final USymbol sym = getSkinParam().componentStyle().toUSymbol() ; + final USymbol sym = getSkinParam().componentStyle().toUSymbol(); final Ident idNewLong = ident.eventuallyRemoveStartingAndEndingDoubleQuote("\"([:"); return getOrCreateLeafDefault(idNewLong, idNewLong.toCode(this), LeafType.DESCRIPTION, sym); } @@ -127,9 +127,4 @@ public class DescriptionDiagram extends AbstractEntityDiagram { return super.checkFinalError(); } - @Override - public UmlDiagramType getUmlDiagramType() { - return UmlDiagramType.DESCRIPTION; - } - } diff --git a/src/net/sourceforge/plantuml/flowdiagram/FlowDiagram.java b/src/net/sourceforge/plantuml/flowdiagram/FlowDiagram.java index e3792f028..724fdfe66 100644 --- a/src/net/sourceforge/plantuml/flowdiagram/FlowDiagram.java +++ b/src/net/sourceforge/plantuml/flowdiagram/FlowDiagram.java @@ -87,9 +87,8 @@ public class FlowDiagram extends UmlDiagram implements TextBlock { return new DiagramDescription("Flow Diagram"); } - @Override - public UmlDiagramType getUmlDiagramType() { - return UmlDiagramType.FLOW; + public FlowDiagram() { + super(UmlDiagramType.FLOW); } public void lineSimple(TileGeometry orientation, String idDest, String label) { diff --git a/src/net/sourceforge/plantuml/gitlog/GitDiagram.java b/src/net/sourceforge/plantuml/gitlog/GitDiagram.java index 7e8c1663f..18d5eda0e 100644 --- a/src/net/sourceforge/plantuml/gitlog/GitDiagram.java +++ b/src/net/sourceforge/plantuml/gitlog/GitDiagram.java @@ -67,6 +67,7 @@ public class GitDiagram extends UmlDiagram { private final Collection gnodes; public GitDiagram(GitTextArea textArea) { + super(UmlDiagramType.GIT); this.gnodes = new GNodeBuilder(textArea.getAllCommits()).getAllNodes(); new GNodeBuilder(textArea.getAllCommits()); } @@ -75,10 +76,6 @@ public class GitDiagram extends UmlDiagram { return new DiagramDescription("(Git)"); } - @Override - public UmlDiagramType getUmlDiagramType() { - return UmlDiagramType.GIT; - } @Override protected ImageData exportDiagramInternal(OutputStream os, int index, FileFormatOption fileFormatOption) diff --git a/src/net/sourceforge/plantuml/graphic/StyledString.java b/src/net/sourceforge/plantuml/graphic/StyledString.java new file mode 100644 index 000000000..fba2d7255 --- /dev/null +++ b/src/net/sourceforge/plantuml/graphic/StyledString.java @@ -0,0 +1,92 @@ +/* ======================================================================== + * 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.graphic; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import net.sourceforge.plantuml.StringUtils; + +public class StyledString { + + private final String text; + private final FontStyle style; + + private StyledString(String text, FontStyle style) { + this.text = text; + this.style = style; + } + + @Override + public String toString() { + return style + "[" + text + "]"; + } + + public final String getText() { + return text; + } + + public final FontStyle getStyle() { + return style; + } + + public static List build(String s) { + final List result = new ArrayList(); + while (s.length() > 0) { + final int i1 = s.indexOf(StringUtils.BOLD_START); + if (i1 == -1) { + result.add(new StyledString(s, FontStyle.PLAIN)); + s = ""; + break; + } + final int i2 = s.indexOf(StringUtils.BOLD_END); + if (i1 > 0) + result.add(new StyledString(s.substring(0, i1), FontStyle.PLAIN)); + + if (i2 == -1) { + result.add(new StyledString(s.substring(i1 + 1), FontStyle.BOLD)); + s = ""; + } else { + result.add(new StyledString(s.substring(i1 + 1, i2), FontStyle.BOLD)); + s = s.substring(i2 + 1); + } + } + return Collections.unmodifiableList(result); + + } + +} diff --git a/src/net/sourceforge/plantuml/help/Help.java b/src/net/sourceforge/plantuml/help/Help.java index a9b961677..024b03fc8 100644 --- a/src/net/sourceforge/plantuml/help/Help.java +++ b/src/net/sourceforge/plantuml/help/Help.java @@ -66,9 +66,8 @@ public class Help extends UmlDiagram { return new DiagramDescription("(Help)"); } - @Override - public UmlDiagramType getUmlDiagramType() { - return UmlDiagramType.HELP; + public Help() { + super(UmlDiagramType.HELP); } @Override diff --git a/src/net/sourceforge/plantuml/jsondiagram/JsonDiagram.java b/src/net/sourceforge/plantuml/jsondiagram/JsonDiagram.java index e917257b2..fa20bca87 100644 --- a/src/net/sourceforge/plantuml/jsondiagram/JsonDiagram.java +++ b/src/net/sourceforge/plantuml/jsondiagram/JsonDiagram.java @@ -74,7 +74,8 @@ public class JsonDiagram extends UmlDiagram { private final JsonValue root; private final List highlighted; - public JsonDiagram(JsonValue json, List highlighted) { + public JsonDiagram(UmlDiagramType type, JsonValue json, List highlighted) { + super(UmlDiagramType.JSON); if (json != null && (json.isString() || json.isBoolean() || json.isNumber())) { this.root = new JsonArray(); ((JsonArray) this.root).add(json); @@ -85,14 +86,12 @@ public class JsonDiagram extends UmlDiagram { } public DiagramDescription getDescription() { + if (getUmlDiagramType() == UmlDiagramType.YAML) { + return new DiagramDescription("(Yaml)"); + } return new DiagramDescription("(Json)"); } - @Override - public UmlDiagramType getUmlDiagramType() { - return UmlDiagramType.JSON; - } - @Override protected ImageData exportDiagramInternal(OutputStream os, int index, FileFormatOption fileFormatOption) throws IOException { @@ -124,7 +123,8 @@ public class JsonDiagram extends UmlDiagram { private void drawInternal(UGraphic ug) { if (root == null) { - final Display display = Display.getWithNewlines("Your data does not sound like JSON data"); + final Display display = Display + .getWithNewlines("Your data does not sound like " + getUmlDiagramType() + " data"); final FontConfiguration fontConfiguration = FontConfiguration.blackBlueTrue(UFont.courier(14)); TextBlock result = display.create(fontConfiguration, HorizontalAlignment.LEFT, getSkinParam()); result = TextBlockUtils.withMargin(result, 5, 2); diff --git a/src/net/sourceforge/plantuml/jsondiagram/JsonDiagramFactory.java b/src/net/sourceforge/plantuml/jsondiagram/JsonDiagramFactory.java index 5b741ab71..a4c55391b 100644 --- a/src/net/sourceforge/plantuml/jsondiagram/JsonDiagramFactory.java +++ b/src/net/sourceforge/plantuml/jsondiagram/JsonDiagramFactory.java @@ -41,6 +41,7 @@ import java.util.List; import net.sourceforge.plantuml.BackSlash; import net.sourceforge.plantuml.StringLocated; +import net.sourceforge.plantuml.UmlDiagramType; import net.sourceforge.plantuml.command.PSystemAbstractFactory; import net.sourceforge.plantuml.core.Diagram; import net.sourceforge.plantuml.core.DiagramType; @@ -81,7 +82,9 @@ public class JsonDiagramFactory extends PSystemAbstractFactory { } catch (ParseException e) { json = null; } - return new JsonDiagram(json, highlighted); + final JsonDiagram result = new JsonDiagram(UmlDiagramType.JSON, json, highlighted); + result.setSource(source); + return result; } } diff --git a/src/net/sourceforge/plantuml/jsondiagram/SmetanaForJson.java b/src/net/sourceforge/plantuml/jsondiagram/SmetanaForJson.java index decd89c01..74277b3f2 100644 --- a/src/net/sourceforge/plantuml/jsondiagram/SmetanaForJson.java +++ b/src/net/sourceforge/plantuml/jsondiagram/SmetanaForJson.java @@ -80,16 +80,16 @@ public class SmetanaForJson { private ST_Agraph_s g; private StringBounder stringBounder; - private final List nodes = new ArrayList(); + private final List nodes = new ArrayList(); private final List edges = new ArrayList(); private Mirror xMirror; - static class Node { + static class InternalNode { private final TextBlockJson block; private final ST_Agnode_s node; - public Node(TextBlockJson block, ST_Agnode_s node) { + public InternalNode(TextBlockJson block, ST_Agnode_s node) { this.block = block; this.node = node; } @@ -118,7 +118,7 @@ public class SmetanaForJson { final TextBlockJson block = new TextBlockJson(skinParam, current, highlighted); final ST_Agnode_s node1 = createNode(block.calculateDimension(stringBounder), block.size(), current.isArray(), (int) block.getWidthColA(stringBounder), (int) block.getWidthColB(stringBounder)); - nodes.add(new Node(block, node1)); + nodes.add(new InternalNode(block, node1)); final List children = block.children(); final List keys = block.keys(); for (int i = 0; i < children.size(); i++) { @@ -151,12 +151,12 @@ public class SmetanaForJson { public void drawMe(JsonValue root, List highlighted) { initGraph(root, highlighted); double max = 0; - for (Node node : nodes) { + for (InternalNode node : nodes) { max = Math.max(max, node.getMaxX()); } xMirror = new Mirror(max); - for (Node node : nodes) { + for (InternalNode node : nodes) { node.block.drawU(ug.apply(getPosition(node.node))); } final HColor color = getStyle().value(PName.LineColor).asColor(skinParam.getIHtmlColorSet()); diff --git a/src/net/sourceforge/plantuml/mindmap/CommandMindMapPlus.java b/src/net/sourceforge/plantuml/mindmap/CommandMindMapPlus.java index df5275f89..42fbdebdc 100644 --- a/src/net/sourceforge/plantuml/mindmap/CommandMindMapPlus.java +++ b/src/net/sourceforge/plantuml/mindmap/CommandMindMapPlus.java @@ -42,8 +42,10 @@ import net.sourceforge.plantuml.command.SingleLineCommand2; import net.sourceforge.plantuml.command.regex.IRegex; import net.sourceforge.plantuml.command.regex.RegexConcat; import net.sourceforge.plantuml.command.regex.RegexLeaf; +import net.sourceforge.plantuml.command.regex.RegexOptional; import net.sourceforge.plantuml.command.regex.RegexResult; import net.sourceforge.plantuml.cucadiagram.Display; +import net.sourceforge.plantuml.ugraphic.color.HColor; public class CommandMindMapPlus extends SingleLineCommand2 { @@ -54,6 +56,7 @@ public class CommandMindMapPlus extends SingleLineCommand2 { static IRegex getRegexConcat() { return RegexConcat.build(CommandMindMapPlus.class.getName(), RegexLeaf.start(), // new RegexLeaf("TYPE", "([+-]+)"), // + new RegexOptional(new RegexLeaf("BACKCOLOR", "\\[(#\\w+)\\]")), // new RegexLeaf("SHAPE", "(_)?"), // RegexLeaf.spaceOneOrMore(), // new RegexLeaf("LABEL", "([^%s].*)"), RegexLeaf.end()); @@ -63,8 +66,13 @@ public class CommandMindMapPlus extends SingleLineCommand2 { protected CommandExecutionResult executeArg(MindMapDiagram diagram, LineLocation location, RegexResult arg) { final String type = arg.get("TYPE", 0); final String label = arg.get("LABEL", 0); + final String stringColor = arg.get("BACKCOLOR", 0); + HColor backColor = null; + if (stringColor != null) { + backColor = diagram.getSkinParam().getIHtmlColorSet().getColorIfValid(stringColor); + } final Direction direction = type.contains("-") ? Direction.LEFT : Direction.RIGHT; - return diagram.addIdea(null, type.length() - 1, Display.getWithNewlines(label), + return diagram.addIdea(backColor, type.length() - 1, Display.getWithNewlines(label), IdeaShape.fromDesc(arg.get("SHAPE", 0)), direction); } diff --git a/src/net/sourceforge/plantuml/mindmap/MindMapDiagram.java b/src/net/sourceforge/plantuml/mindmap/MindMapDiagram.java index aa884ec4d..555760385 100644 --- a/src/net/sourceforge/plantuml/mindmap/MindMapDiagram.java +++ b/src/net/sourceforge/plantuml/mindmap/MindMapDiagram.java @@ -87,9 +87,8 @@ public class MindMapDiagram extends UmlDiagram { return new DiagramDescription("MindMap"); } - @Override - public UmlDiagramType getUmlDiagramType() { - return UmlDiagramType.MINDMAP; + public MindMapDiagram() { + super(UmlDiagramType.MINDMAP); } @Override diff --git a/src/net/sourceforge/plantuml/nwdiag/NwDiagram.java b/src/net/sourceforge/plantuml/nwdiag/NwDiagram.java index 230f9e285..0c208971d 100644 --- a/src/net/sourceforge/plantuml/nwdiag/NwDiagram.java +++ b/src/net/sourceforge/plantuml/nwdiag/NwDiagram.java @@ -92,9 +92,8 @@ public class NwDiagram extends UmlDiagram { return new DiagramDescription("(Nwdiag)"); } - @Override - public UmlDiagramType getUmlDiagramType() { - return UmlDiagramType.NWDIAG; + public NwDiagram() { + super(UmlDiagramType.NWDIAG); } public void init() { diff --git a/src/net/sourceforge/plantuml/objectdiagram/AbstractClassOrObjectDiagram.java b/src/net/sourceforge/plantuml/objectdiagram/AbstractClassOrObjectDiagram.java index 875fdc996..5635324b1 100644 --- a/src/net/sourceforge/plantuml/objectdiagram/AbstractClassOrObjectDiagram.java +++ b/src/net/sourceforge/plantuml/objectdiagram/AbstractClassOrObjectDiagram.java @@ -39,6 +39,7 @@ import java.util.ArrayList; import java.util.List; import net.sourceforge.plantuml.ISkinSimple; +import net.sourceforge.plantuml.UmlDiagramType; import net.sourceforge.plantuml.classdiagram.AbstractEntityDiagram; import net.sourceforge.plantuml.command.CommandExecutionResult; import net.sourceforge.plantuml.cucadiagram.Code; @@ -57,10 +58,10 @@ import net.sourceforge.plantuml.utils.UniqueSequence; public abstract class AbstractClassOrObjectDiagram extends AbstractEntityDiagram { - public AbstractClassOrObjectDiagram(ISkinSimple orig) { - super(orig); + public AbstractClassOrObjectDiagram(UmlDiagramType type, ISkinSimple orig) { + super(type, orig); } - + @Override public Ident cleanIdent(Ident ident) { String codeString = ident.getName(); @@ -70,18 +71,16 @@ public abstract class AbstractClassOrObjectDiagram extends AbstractEntityDiagram return ident; } - final public boolean insertBetween(IEntity entity1, IEntity entity2, IEntity node) { final Link link = foundLink(entity1, entity2); if (link == null) { return false; } - final Link l1 = new Link(entity1, node, link.getType(), link.getLabel(), link.getLength(), - link.getQualifier1(), null, link.getLabeldistance(), link.getLabelangle(), getSkinParam() - .getCurrentStyleBuilder()); + final Link l1 = new Link(entity1, node, link.getType(), link.getLabel(), link.getLength(), link.getQualifier1(), + null, link.getLabeldistance(), link.getLabelangle(), getSkinParam().getCurrentStyleBuilder()); final Link l2 = new Link(node, entity2, link.getType(), link.getLabel(), link.getLength(), null, - link.getQualifier2(), link.getLabeldistance(), link.getLabelangle(), getSkinParam() - .getCurrentStyleBuilder()); + link.getQualifier2(), link.getLabeldistance(), link.getLabelangle(), + getSkinParam().getCurrentStyleBuilder()); addLink(l1); addLink(l2); removeLink(link); @@ -146,8 +145,8 @@ public abstract class AbstractClassOrObjectDiagram extends AbstractEntityDiagram insertPointBetween(entity2A, entity2B, point2); final int length = 1; - final Link point1ToPoint2 = new Link(point1, point2, linkType, label, length, getSkinParam() - .getCurrentStyleBuilder()); + final Link point1ToPoint2 = new Link(point1, point2, linkType, label, length, + getSkinParam().getCurrentStyleBuilder()); addLink(point1ToPoint2); return CommandExecutionResult.ok(); @@ -164,15 +163,15 @@ public abstract class AbstractClassOrObjectDiagram extends AbstractEntityDiagram removeLink(existingLink1); } - final IEntity entity1real = existingLink1.isInverted() ? existingLink1.getEntity2() : existingLink1 - .getEntity1(); - final IEntity entity2real = existingLink1.isInverted() ? existingLink1.getEntity1() : existingLink1 - .getEntity2(); + final IEntity entity1real = existingLink1.isInverted() ? existingLink1.getEntity2() + : existingLink1.getEntity1(); + final IEntity entity2real = existingLink1.isInverted() ? existingLink1.getEntity1() + : existingLink1.getEntity2(); final Link entity1ToPoint = new Link(entity1real, point1, existingLink1.getType().getPart2(), existingLink1.getLabel(), existingLink1.getLength(), existingLink1.getQualifier1(), null, - existingLink1.getLabeldistance(), existingLink1.getLabelangle(), getSkinParam() - .getCurrentStyleBuilder()); + existingLink1.getLabeldistance(), existingLink1.getLabelangle(), + getSkinParam().getCurrentStyleBuilder()); entity1ToPoint.setLinkArrow(existingLink1.getLinkArrow()); final Link pointToEntity2 = new Link(point1, entity2real, existingLink1.getType().getPart1(), Display.NULL, existingLink1.getLength(), null, existingLink1.getQualifier2(), existingLink1.getLabeldistance(), @@ -267,16 +266,16 @@ public abstract class AbstractClassOrObjectDiagram extends AbstractEntityDiagram void createNew(int mode, LinkType linkType, Display label) { existingLink = foundLink(entity1, entity2); if (existingLink == null) { - existingLink = new Link(entity1, entity2, new LinkType(LinkDecor.NONE, LinkDecor.NONE), Display.NULL, - 2, getSkinParam().getCurrentStyleBuilder()); + existingLink = new Link(entity1, entity2, new LinkType(LinkDecor.NONE, LinkDecor.NONE), Display.NULL, 2, + getSkinParam().getCurrentStyleBuilder()); } else { removeLink(existingLink); } - final IEntity entity1real = existingLink.isInverted() ? existingLink.getEntity2() : existingLink - .getEntity1(); - final IEntity entity2real = existingLink.isInverted() ? existingLink.getEntity1() : existingLink - .getEntity2(); + final IEntity entity1real = existingLink.isInverted() ? existingLink.getEntity2() + : existingLink.getEntity1(); + final IEntity entity2real = existingLink.isInverted() ? existingLink.getEntity1() + : existingLink.getEntity2(); entity1ToPoint = new Link(entity1real, point, existingLink.getType().getPart2(), existingLink.getLabel(), existingLink.getLength(), existingLink.getQualifier1(), null, existingLink.getLabeldistance(), @@ -303,11 +302,11 @@ public abstract class AbstractClassOrObjectDiagram extends AbstractEntityDiagram addLink(pointToEntity2); if (mode == 1) { - pointToAssocied = new Link(point, associed, linkType, label, length, getSkinParam() - .getCurrentStyleBuilder()); + pointToAssocied = new Link(point, associed, linkType, label, length, + getSkinParam().getCurrentStyleBuilder()); } else { - pointToAssocied = new Link(associed, point, linkType, label, length, getSkinParam() - .getCurrentStyleBuilder()); + pointToAssocied = new Link(associed, point, linkType, label, length, + getSkinParam().getCurrentStyleBuilder()); } addLink(pointToAssocied); } @@ -315,8 +314,8 @@ public abstract class AbstractClassOrObjectDiagram extends AbstractEntityDiagram void createInSecond(LinkType linkType, Display label) { existingLink = foundLink(entity1, entity2); if (existingLink == null) { - existingLink = new Link(entity1, entity2, new LinkType(LinkDecor.NONE, LinkDecor.NONE), Display.NULL, - 2, getSkinParam().getCurrentStyleBuilder()); + existingLink = new Link(entity1, entity2, new LinkType(LinkDecor.NONE, LinkDecor.NONE), Display.NULL, 2, + getSkinParam().getCurrentStyleBuilder()); } else { removeLink(existingLink); } diff --git a/src/net/sourceforge/plantuml/postit/PostItDiagram.java b/src/net/sourceforge/plantuml/postit/PostItDiagram.java index 9821265da..c65f503b8 100644 --- a/src/net/sourceforge/plantuml/postit/PostItDiagram.java +++ b/src/net/sourceforge/plantuml/postit/PostItDiagram.java @@ -65,9 +65,8 @@ public class PostItDiagram extends UmlDiagram { private final Map postIts = new HashMap(); - @Override - public UmlDiagramType getUmlDiagramType() { - return null; + public PostItDiagram() { + super(UmlDiagramType.TIMING); } @Override diff --git a/src/net/sourceforge/plantuml/project/GanttDiagram.java b/src/net/sourceforge/plantuml/project/GanttDiagram.java index f6fd4f1fe..2e264b8e0 100644 --- a/src/net/sourceforge/plantuml/project/GanttDiagram.java +++ b/src/net/sourceforge/plantuml/project/GanttDiagram.java @@ -130,15 +130,14 @@ public class GanttDiagram extends TitledDiagram implements ToTaskDraw, WithSprit private Day printStart; private Day printEnd; - private HColor linksColor = HColorUtils.RED_DARK; + private HColor linksColor = null; public DiagramDescription getDescription() { return new DiagramDescription("(Project)"); } - @Override - public UmlDiagramType getUmlDiagramType() { - return UmlDiagramType.GANTT; + public GanttDiagram() { + super(UmlDiagramType.GANTT); } private int horizontalPages = 1; @@ -261,12 +260,14 @@ public class GanttDiagram extends TitledDiagram implements ToTaskDraw, WithSprit if (openClose.getCalendar() == null) { return new TimeHeaderSimple(min, max); } else if (printScale == PrintScale.WEEKLY) { - return new TimeHeaderWeekly(openClose.getCalendar(), min, max, openClose, colorDays, colorDaysOfWeek, nameDays); + return new TimeHeaderWeekly(openClose.getCalendar(), min, max, openClose, colorDays, colorDaysOfWeek, + nameDays); } else if (printScale == PrintScale.MONTHLY) { - return new TimeHeaderMonthly(openClose.getCalendar(), min, max, openClose, colorDays, colorDaysOfWeek, nameDays); + return new TimeHeaderMonthly(openClose.getCalendar(), min, max, openClose, colorDays, colorDaysOfWeek, + nameDays); } else { - return new TimeHeaderDaily(openClose.getCalendar(), min, max, openClose, colorDays, colorDaysOfWeek, nameDays, - printStart, printEnd); + return new TimeHeaderDaily(openClose.getCalendar(), min, max, openClose, colorDays, colorDaysOfWeek, + nameDays, printStart, printEnd); } } @@ -293,19 +294,17 @@ public class GanttDiagram extends TitledDiagram implements ToTaskDraw, WithSprit if (printStart != null && constraint.isHidden(min, max)) { continue; } - - // If the linksColor is the default color, we should try to get the arrow color (default is RED_DARK) - if (linksColor == HColorUtils.RED_DARK) { - constraint.getUDrawable(timeScale, getLinkColor(), this).drawU(ug); - } else { - constraint.getUDrawable(timeScale, linksColor, this).drawU(ug); - } + constraint.getUDrawable(timeScale, getLinkColor(), this).drawU(ug); } + } private HColor getLinkColor() { - final Style styleArrow = getDefaultStyleDefinitionArrow().getMergedStyle(getCurrentStyleBuilder()); - return styleArrow.value(PName.LineColor).asColor(colorSet); + if (linksColor == null) { + final Style styleArrow = getDefaultStyleDefinitionArrow().getMergedStyle(getCurrentStyleBuilder()); + return styleArrow.value(PName.LineColor).asColor(colorSet); + } + return linksColor; } public StyleSignature getDefaultStyleDefinitionArrow() { @@ -596,7 +595,7 @@ public class GanttDiagram extends TitledDiagram implements ToTaskDraw, WithSprit return openClose.getLoadAt(day) > 0; } - public void affectResource(Task result, String description) { + public boolean affectResource(Task result, String description) { final Pattern p = Pattern.compile("([^:]+)(:(\\d+))?"); final Matcher m = p.matcher(description); if (m.find() == false) { @@ -607,7 +606,11 @@ public class GanttDiagram extends TitledDiagram implements ToTaskDraw, WithSprit if (m.group(3) != null) { percentage = Integer.parseInt(m.group(3)); } + if (percentage == 0) { + return false; + } result.addResource(resource, percentage); + return true; } public Resource getResource(String resourceName) { @@ -677,7 +680,7 @@ public class GanttDiagram extends TitledDiagram implements ToTaskDraw, WithSprit public void colorDay(DayOfWeek day, HColor color) { colorDaysOfWeek.put(day, color); } - + public void nameDay(Day day, String name) { nameDays.put(day, name); } @@ -734,4 +737,4 @@ public class GanttDiagram extends TitledDiagram implements ToTaskDraw, WithSprit } -} +} \ No newline at end of file diff --git a/src/net/sourceforge/plantuml/project/draw/TimeHeaderDaily.java b/src/net/sourceforge/plantuml/project/draw/TimeHeaderDaily.java index d679e65f8..dc24abe9d 100644 --- a/src/net/sourceforge/plantuml/project/draw/TimeHeaderDaily.java +++ b/src/net/sourceforge/plantuml/project/draw/TimeHeaderDaily.java @@ -103,7 +103,7 @@ public class TimeHeaderDaily extends TimeHeader { final double x2 = getTimeScale().getEndingPosition(wink); HColor back = colorDays.get(wink); // Day of week should be stronger than period of time (back color). - HColor backDoW = colorDaysOfWeek.get(wink.getDayOfWeek()); + final HColor backDoW = colorDaysOfWeek.get(wink.getDayOfWeek()); if (backDoW != null) { back = backDoW; } diff --git a/src/net/sourceforge/plantuml/project/draw/TimeHeaderWeekly.java b/src/net/sourceforge/plantuml/project/draw/TimeHeaderWeekly.java index 22f3723be..fca6daeb3 100644 --- a/src/net/sourceforge/plantuml/project/draw/TimeHeaderWeekly.java +++ b/src/net/sourceforge/plantuml/project/draw/TimeHeaderWeekly.java @@ -102,7 +102,7 @@ public class TimeHeaderWeekly extends TimeHeader { for (Day wink = min; wink.compareTo(max) <= 0; wink = wink.increment()) { HColor back = colorDays.get(wink); // Day of week should be stronger than period of time (back color). - HColor backDoW = colorDaysOfWeek.get(wink.getDayOfWeek()); + final HColor backDoW = colorDaysOfWeek.get(wink.getDayOfWeek()); if (backDoW != null) { back = backDoW; } diff --git a/src/net/sourceforge/plantuml/project/lang/SubjectTask.java b/src/net/sourceforge/plantuml/project/lang/SubjectTask.java index 148f83b2b..aa1da4393 100644 --- a/src/net/sourceforge/plantuml/project/lang/SubjectTask.java +++ b/src/net/sourceforge/plantuml/project/lang/SubjectTask.java @@ -63,7 +63,10 @@ public class SubjectTask implements Subject { for (final StringTokenizer st = new StringTokenizer(resource, "{}"); st.hasMoreTokens();) { final String part = st.nextToken().trim(); if (part.length() > 0) { - project.affectResource(result, part); + final boolean ok = project.affectResource(result, part); + if (ok == false) { + return Failable.error("Bad argument for resource"); + } } } diff --git a/src/net/sourceforge/plantuml/project/solver/SolverImpl.java b/src/net/sourceforge/plantuml/project/solver/SolverImpl.java index b25021aa2..83da16e1e 100644 --- a/src/net/sourceforge/plantuml/project/solver/SolverImpl.java +++ b/src/net/sourceforge/plantuml/project/solver/SolverImpl.java @@ -52,9 +52,14 @@ public class SolverImpl extends AbstractSolver implements Solver { protected Day computeEnd() { Day current = (Day) values.get(TaskAttribute.START); int fullLoad = ((Load) values.get(TaskAttribute.LOAD)).getFullLoad(); + int cpt = 0; while (fullLoad > 0) { fullLoad -= loadPlanable.getLoadAt(current); current = current.increment(); + cpt++; + if (cpt > 100000) { + throw new IllegalStateException(); + } } return current.decrement(); } @@ -63,12 +68,17 @@ public class SolverImpl extends AbstractSolver implements Solver { protected Day computeStart() { Day current = (Day) values.get(TaskAttribute.END); int fullLoad = ((Load) values.get(TaskAttribute.LOAD)).getFullLoad(); + int cpt = 0; while (fullLoad > 0) { fullLoad -= loadPlanable.getLoadAt(current); current = current.decrement(); if (current.getMillis() <= 0) { return current; } + cpt++; + if (cpt > 100000) { + throw new IllegalStateException(); + } } return current.increment(); } diff --git a/src/net/sourceforge/plantuml/salt/PSystemSalt.java b/src/net/sourceforge/plantuml/salt/PSystemSalt.java index 5ae8c52fb..5721dffd1 100644 --- a/src/net/sourceforge/plantuml/salt/PSystemSalt.java +++ b/src/net/sourceforge/plantuml/salt/PSystemSalt.java @@ -104,6 +104,7 @@ public class PSystemSalt extends TitledDiagram implements WithSprite { @Deprecated public PSystemSalt(List data) { + super(UmlDiagramType.SALT); this.data = data; } @@ -280,11 +281,6 @@ public class PSystemSalt extends TitledDiagram implements WithSprite { this.iamSalt = true; } - @Override - public UmlDiagramType getUmlDiagramType() { - return UmlDiagramType.SALT; - } - public final boolean isIamSalt() { return iamSalt; } diff --git a/src/net/sourceforge/plantuml/sequencediagram/SequenceDiagram.java b/src/net/sourceforge/plantuml/sequencediagram/SequenceDiagram.java index 8e6543524..d431cc1e0 100644 --- a/src/net/sourceforge/plantuml/sequencediagram/SequenceDiagram.java +++ b/src/net/sourceforge/plantuml/sequencediagram/SequenceDiagram.java @@ -81,7 +81,7 @@ public class SequenceDiagram extends UmlDiagram { private final Rose skin2 = new Rose(); public SequenceDiagram(ISkinSimple skinParam) { - super(skinParam); + super(UmlDiagramType.SEQUENCE, skinParam); } @Deprecated @@ -388,11 +388,6 @@ public class SequenceDiagram extends UmlDiagram { } - @Override - public UmlDiagramType getUmlDiagramType() { - return UmlDiagramType.SEQUENCE; - } - private ParticipantEnglober participantEnglober; public void boxStart(Display comment, HColor color, Stereotype stereotype) { diff --git a/src/net/sourceforge/plantuml/sequencediagram/command/CommandArrow.java b/src/net/sourceforge/plantuml/sequencediagram/command/CommandArrow.java index e3d98577d..142d6d55b 100644 --- a/src/net/sourceforge/plantuml/sequencediagram/command/CommandArrow.java +++ b/src/net/sourceforge/plantuml/sequencediagram/command/CommandArrow.java @@ -112,7 +112,9 @@ public class CommandArrow extends SingleLineCommand2 { new RegexLeaf("LIFECOLOR", "(?:(#\\w+)?)"), // RegexLeaf.spaceZeroOrMore(), // new RegexLeaf("URL", "(" + UrlBuilder.getRegexp() + ")?"), // - RegexLeaf.spaceZeroOrMore(), new RegexLeaf("MESSAGE", "(?::[%s]*(.*))?"), RegexLeaf.end()); + RegexLeaf.spaceZeroOrMore(), // + new RegexLeaf("MESSAGE", "(?::[%s]*(.*))?"), // + RegexLeaf.end()); } private Participant getOrCreateParticipant(SequenceDiagram system, RegexResult arg2, String n) { diff --git a/src/net/sourceforge/plantuml/skin/ArrowDirection.java b/src/net/sourceforge/plantuml/skin/ArrowDirection.java index 00701a50e..5a00d80c2 100644 --- a/src/net/sourceforge/plantuml/skin/ArrowDirection.java +++ b/src/net/sourceforge/plantuml/skin/ArrowDirection.java @@ -35,7 +35,6 @@ */ package net.sourceforge.plantuml.skin; - public enum ArrowDirection { LEFT_TO_RIGHT_NORMAL, RIGHT_TO_LEFT_REVERSE, SELF, BOTH_DIRECTION; diff --git a/src/net/sourceforge/plantuml/sprite/ListSpriteDiagram.java b/src/net/sourceforge/plantuml/sprite/ListSpriteDiagram.java index 011dcbcb2..a957956e8 100644 --- a/src/net/sourceforge/plantuml/sprite/ListSpriteDiagram.java +++ b/src/net/sourceforge/plantuml/sprite/ListSpriteDiagram.java @@ -68,18 +68,13 @@ import net.sourceforge.plantuml.ugraphic.color.HColorUtils; public class ListSpriteDiagram extends UmlDiagram { public ListSpriteDiagram(ISkinSimple skinParam) { - super(skinParam); + super(UmlDiagramType.HELP, skinParam); } public DiagramDescription getDescription() { return new DiagramDescription("(Sprites)"); } - @Override - public UmlDiagramType getUmlDiagramType() { - return UmlDiagramType.HELP; - } - @Override protected ImageData exportDiagramInternal(OutputStream os, int index, FileFormatOption fileFormatOption) throws IOException { diff --git a/src/net/sourceforge/plantuml/sprite/StdlibDiagram.java b/src/net/sourceforge/plantuml/sprite/StdlibDiagram.java index 277b703f5..5e0a3e5db 100644 --- a/src/net/sourceforge/plantuml/sprite/StdlibDiagram.java +++ b/src/net/sourceforge/plantuml/sprite/StdlibDiagram.java @@ -77,18 +77,13 @@ public class StdlibDiagram extends UmlDiagram { private String name; public StdlibDiagram(ISkinSimple skinParam) { - super(skinParam); + super(UmlDiagramType.HELP, skinParam); } public DiagramDescription getDescription() { return new DiagramDescription("(Sprites)"); } - @Override - public UmlDiagramType getUmlDiagramType() { - return UmlDiagramType.HELP; - } - @Override protected ImageData exportDiagramInternal(OutputStream os, int index, FileFormatOption fileFormatOption) throws IOException { diff --git a/src/net/sourceforge/plantuml/statediagram/StateDiagram.java b/src/net/sourceforge/plantuml/statediagram/StateDiagram.java index 6f57711cf..5a745310d 100644 --- a/src/net/sourceforge/plantuml/statediagram/StateDiagram.java +++ b/src/net/sourceforge/plantuml/statediagram/StateDiagram.java @@ -57,7 +57,7 @@ public class StateDiagram extends AbstractEntityDiagram { private static final String CONCURRENT_PREFIX = "CONC"; public StateDiagram(ISkinSimple skinParam) { - super(skinParam); + super(UmlDiagramType.STATE, skinParam); // setNamespaceSeparator(null); } @@ -260,11 +260,6 @@ public class StateDiagram extends AbstractEntityDiagram { super.endGroup(); } - @Override - public UmlDiagramType getUmlDiagramType() { - return UmlDiagramType.STATE; - } - private boolean hideEmptyDescription = false; @Override diff --git a/src/net/sourceforge/plantuml/sudoku/GraphicsSudoku.java b/src/net/sourceforge/plantuml/sudoku/GraphicsSudoku.java index 30d7e0f0b..d3dfda28d 100644 --- a/src/net/sourceforge/plantuml/sudoku/GraphicsSudoku.java +++ b/src/net/sourceforge/plantuml/sudoku/GraphicsSudoku.java @@ -57,6 +57,7 @@ import net.sourceforge.plantuml.graphic.FontConfiguration; import net.sourceforge.plantuml.graphic.HorizontalAlignment; import net.sourceforge.plantuml.graphic.TextBlock; import net.sourceforge.plantuml.png.PngIO; +import net.sourceforge.plantuml.svg.LengthAdjust; import net.sourceforge.plantuml.ugraphic.UFont; import net.sourceforge.plantuml.ugraphic.UGraphic; import net.sourceforge.plantuml.ugraphic.URectangle; @@ -88,7 +89,7 @@ public class GraphicsSudoku { public ImageData writeImageSvg(OutputStream os) throws IOException { final UGraphicSvg ug = new UGraphicSvg(true, new Dimension2DDouble(0, 0), new ColorMapperIdentity(), - (String) null, false, 1.0, null, null, 0, "none", SvgCharSizeHack.NO_HACK); + (String) null, false, 1.0, null, null, 0, "none", SvgCharSizeHack.NO_HACK, LengthAdjust.defaultValue()); drawInternal(ug); ug.createXml(os, null); return ImageDataSimple.ok(); diff --git a/src/net/sourceforge/plantuml/svek/GraphvizCrash.java b/src/net/sourceforge/plantuml/svek/GraphvizCrash.java index 2845d8713..87ce7f06a 100644 --- a/src/net/sourceforge/plantuml/svek/GraphvizCrash.java +++ b/src/net/sourceforge/plantuml/svek/GraphvizCrash.java @@ -110,8 +110,9 @@ public class GraphvizCrash extends AbstractTextBlock implements IEntityImage { 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"); - strings.add(" consider upgrading from https://plantuml.com/download"); + strings.add(" "); + strings.add("This version of PlantUML is " + days + " days old, so you should"); + strings.add("consider upgrading from https://plantuml.com/download"); } } diff --git a/src/net/sourceforge/plantuml/svg/LengthAdjust.java b/src/net/sourceforge/plantuml/svg/LengthAdjust.java new file mode 100644 index 000000000..0c8fb1d0e --- /dev/null +++ b/src/net/sourceforge/plantuml/svg/LengthAdjust.java @@ -0,0 +1,44 @@ +/* ======================================================================== + * 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.svg; + +public enum LengthAdjust { + NONE, SPACING, SPACING_AND_GLYPHS; + + public static LengthAdjust defaultValue() { + return SPACING; + } +} diff --git a/src/net/sourceforge/plantuml/svg/SvgGraphics.java b/src/net/sourceforge/plantuml/svg/SvgGraphics.java index 007884099..d34f9c65c 100644 --- a/src/net/sourceforge/plantuml/svg/SvgGraphics.java +++ b/src/net/sourceforge/plantuml/svg/SvgGraphics.java @@ -118,6 +118,7 @@ public class SvgGraphics { private final String shadowId; private final String gradientId; private final boolean svgDimensionStyle; + private final LengthAdjust lengthAdjust; final protected void ensureVisible(double x, double y) { if (x > maxX) { @@ -129,13 +130,14 @@ public class SvgGraphics { } public SvgGraphics(boolean svgDimensionStyle, Dimension2D minDim, double scale, String hover, long seed, - String preserveAspectRatio) { - this(svgDimensionStyle, minDim, null, scale, hover, seed, preserveAspectRatio); + String preserveAspectRatio, LengthAdjust lengthAdjust) { + this(svgDimensionStyle, minDim, null, scale, hover, seed, preserveAspectRatio, lengthAdjust); } public SvgGraphics(boolean svgDimensionStyle, Dimension2D minDim, String backcolor, double scale, String hover, - long seed, String preserveAspectRatio) { + long seed, String preserveAspectRatio, LengthAdjust lengthAdjust) { try { + this.lengthAdjust = lengthAdjust; this.svgDimensionStyle = svgDimensionStyle; this.scale = scale; this.document = getDocument(); @@ -436,8 +438,15 @@ public class SvgGraphics { fillMe(elt); elt.setAttribute("font-size", format(fontSize)); // elt.setAttribute("text-anchor", "middle"); - elt.setAttribute("lengthAdjust", "spacingAndGlyphs"); - elt.setAttribute("textLength", format(textLength)); + + if (lengthAdjust == LengthAdjust.SPACING) { + elt.setAttribute("lengthAdjust", "spacing"); + elt.setAttribute("textLength", format(textLength)); + } else if (lengthAdjust == LengthAdjust.SPACING_AND_GLYPHS) { + elt.setAttribute("lengthAdjust", "spacingAndGlyphs"); + elt.setAttribute("textLength", format(textLength)); + } + if (fontWeight != null) { elt.setAttribute("font-weight", fontWeight); } diff --git a/src/net/sourceforge/plantuml/tim/Eater.java b/src/net/sourceforge/plantuml/tim/Eater.java index bb6fa985d..4268d917b 100644 --- a/src/net/sourceforge/plantuml/tim/Eater.java +++ b/src/net/sourceforge/plantuml/tim/Eater.java @@ -218,6 +218,12 @@ public abstract class Eater { return s.charAt(i); } + final public boolean matchAffectation() { + final String tmp = s.substring(i); + final boolean result = tmp.matches("^\\$?[_\\p{L}][_\\p{L}0-9]*\\s*=.*"); + return result; + } + final public char peekCharN2() { if (i + 1 >= s.length()) { return 0; diff --git a/src/net/sourceforge/plantuml/tim/EaterFunctionCall.java b/src/net/sourceforge/plantuml/tim/EaterFunctionCall.java index c1c844a2c..0777d642d 100644 --- a/src/net/sourceforge/plantuml/tim/EaterFunctionCall.java +++ b/src/net/sourceforge/plantuml/tim/EaterFunctionCall.java @@ -74,20 +74,34 @@ public class EaterFunctionCall extends Eater { final TValue result = TValue.fromString(value); values.add(result); } else if (unquoted) { - final String read = eatAndGetOptionalQuotedString(); - if (TokenStack.isSpecialAffectationWhenFunctionCall(read)) { - updateNamedArguments(read, context, memory); + if (matchAffectation()) { + final String varname = eatAndGetVarname(); + skipSpaces(); + checkAndEatChar('='); + skipSpaces(); + final String read = eatAndGetOptionalQuotedString(); + final String value = context.applyFunctionsAndVariables(memory, getLineLocation(), read); + final TValue result = TValue.fromString(value); + namedArguments.put(varname, result); } else { + final String read = eatAndGetOptionalQuotedString(); final String value = context.applyFunctionsAndVariables(memory, getLineLocation(), read); final TValue result = TValue.fromString(value); values.add(result); } +// } } else { - final TokenStack tokens = TokenStack.eatUntilCloseParenthesisOrComma(this).withoutSpace(); - if (tokens.isSpecialAffectationWhenFunctionCall()) { - final String special = tokens.tokenIterator().nextToken().getSurface(); - updateNamedArguments(special, context, memory); + if (matchAffectation()) { + final String varname = eatAndGetVarname(); + skipSpaces(); + checkAndEatChar('='); + skipSpaces(); + final TokenStack tokens = TokenStack.eatUntilCloseParenthesisOrComma(this).withoutSpace(); + tokens.guessFunctions(); + final TValue result = tokens.getResult(getLineLocation(), context, memory); + namedArguments.put(varname, result); } else { + final TokenStack tokens = TokenStack.eatUntilCloseParenthesisOrComma(this).withoutSpace(); tokens.guessFunctions(); final TValue result = tokens.getResult(getLineLocation(), context, memory); values.add(result); @@ -108,16 +122,6 @@ public class EaterFunctionCall extends Eater { } } - private void updateNamedArguments(String special, TContext context, TMemory memory) - throws EaterException, EaterExceptionLocated { - assert special.contains("="); - final StringEater stringEater = new StringEater(special); - final String varname = stringEater.eatAndGetVarname(); - stringEater.checkAndEatChar('='); - final TValue expr = stringEater.eatExpression(context, memory); - namedArguments.put(varname, expr); - } - public final List getValues() { return Collections.unmodifiableList(values); } diff --git a/src/net/sourceforge/plantuml/tim/expression/TokenStack.java b/src/net/sourceforge/plantuml/tim/expression/TokenStack.java index 071a71014..421487cc5 100644 --- a/src/net/sourceforge/plantuml/tim/expression/TokenStack.java +++ b/src/net/sourceforge/plantuml/tim/expression/TokenStack.java @@ -47,39 +47,38 @@ import net.sourceforge.plantuml.tim.Eater; import net.sourceforge.plantuml.tim.EaterException; import net.sourceforge.plantuml.tim.EaterExceptionLocated; import net.sourceforge.plantuml.tim.TContext; -import net.sourceforge.plantuml.tim.TLineType; import net.sourceforge.plantuml.tim.TMemory; public class TokenStack { final private List tokens; - public boolean isSpecialAffectationWhenFunctionCall() { - if (tokens.size() != 1) { - return false; - } - final Token single = tokens.get(0); - if (single.getTokenType() != TokenType.PLAIN_TEXT) { - return false; - } - return isSpecialAffectationWhenFunctionCall(single.getSurface()); - } - - public static boolean isSpecialAffectationWhenFunctionCall(String surface) { - final int idx = surface.indexOf('='); - if (idx <= 0) { - return false; - } - if (TLineType.isLetterOrUnderscoreOrDollar(surface.charAt(0)) == false) { - return false; - } - for (int i = 1; i < idx; i++) { - if (TLineType.isLetterOrUnderscoreOrDigit(surface.charAt(i)) == false) { - return false; - } - } - return true; - } +// public boolean isSpecialAffectationWhenFunctionCall() { +// if (tokens.size() != 1) { +// return false; +// } +// final Token single = tokens.get(0); +// if (single.getTokenType() != TokenType.PLAIN_TEXT) { +// return false; +// } +// return isSpecialAffectationWhenFunctionCall(single.getSurface()); +// } +// +// public static boolean isSpecialAffectationWhenFunctionCall(String surface) { +// final int idx = surface.indexOf('='); +// if (idx <= 0) { +// return false; +// } +// if (TLineType.isLetterOrUnderscoreOrDollar(surface.charAt(0)) == false) { +// return false; +// } +// for (int i = 1; i < idx; i++) { +// if (TLineType.isLetterOrUnderscoreOrDigit(surface.charAt(i)) == false) { +// return false; +// } +// } +// return true; +// } public TokenStack() { this(new ArrayList()); diff --git a/src/net/sourceforge/plantuml/timingdiagram/TimingDiagram.java b/src/net/sourceforge/plantuml/timingdiagram/TimingDiagram.java index 6ca095bd0..2d3eb4510 100644 --- a/src/net/sourceforge/plantuml/timingdiagram/TimingDiagram.java +++ b/src/net/sourceforge/plantuml/timingdiagram/TimingDiagram.java @@ -95,9 +95,8 @@ public class TimingDiagram extends UmlDiagram implements Clocks { return new DiagramDescription("(Timing Diagram)"); } - @Override - public UmlDiagramType getUmlDiagramType() { - return UmlDiagramType.TIMING; + public TimingDiagram() { + super(UmlDiagramType.TIMING); } @Override diff --git a/src/net/sourceforge/plantuml/ugraphic/FontChecker.java b/src/net/sourceforge/plantuml/ugraphic/FontChecker.java index 4e29cc886..c9df3eab4 100644 --- a/src/net/sourceforge/plantuml/ugraphic/FontChecker.java +++ b/src/net/sourceforge/plantuml/ugraphic/FontChecker.java @@ -60,6 +60,7 @@ import net.sourceforge.plantuml.graphic.UDrawable; import net.sourceforge.plantuml.security.ImageIO; import net.sourceforge.plantuml.security.SFile; import net.sourceforge.plantuml.style.ClockwiseTopRightBottomLeft; +import net.sourceforge.plantuml.svg.LengthAdjust; import net.sourceforge.plantuml.svg.SvgGraphics; import net.sourceforge.plantuml.ugraphic.color.ColorMapperIdentity; import net.sourceforge.plantuml.ugraphic.color.HColorUtils; @@ -159,7 +160,8 @@ public class FontChecker { } private String getSvgImage(char c) throws IOException, TransformerException { - final SvgGraphics svg = new SvgGraphics(true, new Dimension2DDouble(0, 0), 1.0, null, 42, "none"); + final SvgGraphics svg = new SvgGraphics(true, new Dimension2DDouble(0, 0), 1.0, null, 42, "none", + LengthAdjust.defaultValue()); svg.setStrokeColor("black"); svg.svgImage(getBufferedImage(c), 0, 0); final ByteArrayOutputStream os = new ByteArrayOutputStream(); diff --git a/src/net/sourceforge/plantuml/ugraphic/ImageBuilder.java b/src/net/sourceforge/plantuml/ugraphic/ImageBuilder.java index e7fc2acf4..26587344a 100644 --- a/src/net/sourceforge/plantuml/ugraphic/ImageBuilder.java +++ b/src/net/sourceforge/plantuml/ugraphic/ImageBuilder.java @@ -71,6 +71,7 @@ import net.sourceforge.plantuml.graphic.UDrawable; import net.sourceforge.plantuml.mjpeg.MJPEGGenerator; import net.sourceforge.plantuml.security.ImageIO; import net.sourceforge.plantuml.security.SFile; +import net.sourceforge.plantuml.svg.LengthAdjust; import net.sourceforge.plantuml.ugraphic.color.ColorMapper; import net.sourceforge.plantuml.ugraphic.color.HColor; import net.sourceforge.plantuml.ugraphic.color.HColorBackground; @@ -283,7 +284,8 @@ public class ImageBuilder { option.getWatermark()); case SVG: return createUGraphicSVG(colorMapper, param.getDpiFactor(), dim, param.getBackcolor(), - option.getSvgLinkTarget(), option.getHoverColor(), seed, option.getPreserveAspectRatio()); + option.getSvgLinkTarget(), option.getHoverColor(), seed, option.getPreserveAspectRatio(), + param.getlengthAdjust()); case EPS: return new UGraphicEps(colorMapper, EpsStrategy.getDefault2()); case EPS_TEXT: @@ -307,7 +309,7 @@ public class ImageBuilder { } private UGraphic2 createUGraphicSVG(ColorMapper colorMapper, double scale, Dimension2D dim, final HColor suggested, - String svgLinkTarget, String hover, long seed, String preserveAspectRatio) { + String svgLinkTarget, String hover, long seed, String preserveAspectRatio, LengthAdjust lengthAdjust) { HColor backColor = HColorUtils.WHITE; if (suggested instanceof HColorSimple) { backColor = suggested; @@ -316,14 +318,15 @@ public class ImageBuilder { final UGraphicSvg ug; if (suggested instanceof HColorGradient) { ug = new UGraphicSvg(dimensionStyle, dim, colorMapper, (HColorGradient) suggested, false, scale, - svgLinkTarget, hover, seed, preserveAspectRatio, param.getSvgCharSizeHack()); + svgLinkTarget, hover, seed, preserveAspectRatio, param.getSvgCharSizeHack(), + param.getlengthAdjust()); } else if (backColor == null || colorMapper.toColor(backColor).equals(Color.WHITE)) { ug = new UGraphicSvg(dimensionStyle, dim, colorMapper, false, scale, svgLinkTarget, hover, seed, - preserveAspectRatio, param.getSvgCharSizeHack()); + preserveAspectRatio, param.getSvgCharSizeHack(), param.getlengthAdjust()); } else { final String tmp = colorMapper.toSvg(backColor); ug = new UGraphicSvg(dimensionStyle, dim, colorMapper, tmp, false, scale, svgLinkTarget, hover, seed, - preserveAspectRatio, param.getSvgCharSizeHack()); + preserveAspectRatio, param.getSvgCharSizeHack(), param.getlengthAdjust()); } return ug; diff --git a/src/net/sourceforge/plantuml/ugraphic/ImageParameter.java b/src/net/sourceforge/plantuml/ugraphic/ImageParameter.java index f9777fedd..9260ed8e1 100644 --- a/src/net/sourceforge/plantuml/ugraphic/ImageParameter.java +++ b/src/net/sourceforge/plantuml/ugraphic/ImageParameter.java @@ -43,6 +43,7 @@ import net.sourceforge.plantuml.SvgCharSizeHack; import net.sourceforge.plantuml.anim.Animation; import net.sourceforge.plantuml.skin.rose.Rose; import net.sourceforge.plantuml.style.ClockwiseTopRightBottomLeft; +import net.sourceforge.plantuml.svg.LengthAdjust; import net.sourceforge.plantuml.ugraphic.color.ColorMapper; import net.sourceforge.plantuml.ugraphic.color.HColor; @@ -58,6 +59,7 @@ public class ImageParameter { private final HColor backcolor; private final boolean svgDimensionStyle; private final SvgCharSizeHack svgCharSizeHack; + private final LengthAdjust lengthAdjust; private final UStroke borderStroke; private final HColor borderColor; @@ -79,6 +81,7 @@ public class ImageParameter { this.borderCorner = 0; this.borderStroke = null; this.svgCharSizeHack = SvgCharSizeHack.NO_HACK; + this.lengthAdjust = LengthAdjust.defaultValue(); } public ImageParameter(ISkinParam skinParam, Animation animation, double dpiFactor, String metadata, @@ -104,6 +107,7 @@ public class ImageParameter { } this.svgCharSizeHack = skinParam; + this.lengthAdjust = skinParam.getlengthAdjust(); } @@ -159,4 +163,8 @@ public class ImageParameter { return svgCharSizeHack; } + public final LengthAdjust getlengthAdjust() { + return lengthAdjust; + } + } diff --git a/src/net/sourceforge/plantuml/ugraphic/UGraphicUtils.java b/src/net/sourceforge/plantuml/ugraphic/UGraphicUtils.java index 6e6288ad4..52564fa00 100644 --- a/src/net/sourceforge/plantuml/ugraphic/UGraphicUtils.java +++ b/src/net/sourceforge/plantuml/ugraphic/UGraphicUtils.java @@ -48,6 +48,7 @@ import net.sourceforge.plantuml.SvgCharSizeHack; import net.sourceforge.plantuml.eps.EpsStrategy; import net.sourceforge.plantuml.graphic.TextBlock; import net.sourceforge.plantuml.png.PngIO; +import net.sourceforge.plantuml.svg.LengthAdjust; import net.sourceforge.plantuml.ugraphic.color.ColorMapper; import net.sourceforge.plantuml.ugraphic.color.HColor; import net.sourceforge.plantuml.ugraphic.eps.UGraphicEps; @@ -66,7 +67,8 @@ public abstract class UGraphicUtils { final Dimension2D size = computeSize(colorMapper, background, image); final UGraphicSvg svg = new UGraphicSvg(true, size, colorMapper, colorMapper.toRGB(background), false, 1.0, fileFormatOption.getSvgLinkTarget(), fileFormatOption.getHoverColor(), seed, - fileFormatOption.getPreserveAspectRatio(), SvgCharSizeHack.NO_HACK); + fileFormatOption.getPreserveAspectRatio(), SvgCharSizeHack.NO_HACK, + LengthAdjust.defaultValue()); image.drawU(svg); svg.createXml(os, fileFormatOption.isWithMetadata() ? metadata : null); } else if (fileFormat == FileFormat.EPS) { diff --git a/src/net/sourceforge/plantuml/ugraphic/UText.java b/src/net/sourceforge/plantuml/ugraphic/UText.java index 214c74056..29decbf13 100644 --- a/src/net/sourceforge/plantuml/ugraphic/UText.java +++ b/src/net/sourceforge/plantuml/ugraphic/UText.java @@ -44,16 +44,26 @@ public class UText implements UShape { private final String text; private final FontConfiguration font; + private final int orientation; @Override public String toString() { return "UText[" + text + "]"; } - public UText(String text, FontConfiguration font) { + private UText(String text, FontConfiguration font, int orientation) { assert text.indexOf('\t') == -1; this.text = text; this.font = font; + this.orientation = orientation; + } + + public UText(String text, FontConfiguration font) { + this(text, font, 0); + } + + public UText withOrientation(int orientation) { + return new UText(text, font, orientation); } public String getText() { @@ -70,4 +80,8 @@ public class UText implements UShape { return descent; } + public final int getOrientation() { + return orientation; + } + } diff --git a/src/net/sourceforge/plantuml/ugraphic/g2d/DriverTextG2d.java b/src/net/sourceforge/plantuml/ugraphic/g2d/DriverTextG2d.java index 075ea0a00..f84a061d0 100644 --- a/src/net/sourceforge/plantuml/ugraphic/g2d/DriverTextG2d.java +++ b/src/net/sourceforge/plantuml/ugraphic/g2d/DriverTextG2d.java @@ -40,19 +40,20 @@ import java.awt.Color; import java.awt.FontMetrics; import java.awt.GradientPaint; import java.awt.Graphics2D; -import java.awt.GraphicsEnvironment; import java.awt.RenderingHints; +import java.awt.geom.AffineTransform; import java.awt.geom.Dimension2D; import java.awt.geom.Rectangle2D; +import java.util.List; import net.sourceforge.plantuml.Dimension2DDouble; import net.sourceforge.plantuml.EnsureVisible; import net.sourceforge.plantuml.FileFormat; -import net.sourceforge.plantuml.Log; import net.sourceforge.plantuml.TikzFontDistortion; import net.sourceforge.plantuml.graphic.FontConfiguration; import net.sourceforge.plantuml.graphic.FontStyle; import net.sourceforge.plantuml.graphic.StringBounder; +import net.sourceforge.plantuml.graphic.StyledString; import net.sourceforge.plantuml.ugraphic.UDriver; import net.sourceforge.plantuml.ugraphic.UFont; import net.sourceforge.plantuml.ugraphic.UParam; @@ -70,83 +71,108 @@ public class DriverTextG2d implements UDriver { this.visible = visible; } - private static void printFont() { - final GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); - final String fontNames[] = ge.getAvailableFontFamilyNames(); - final int j = fontNames.length; - for (int i = 0; i < j; i++) { - Log.info("Available fonts: " + fontNames[i]); - } - } - public void draw(UShape ushape, double x, double y, ColorMapper mapper, UParam param, Graphics2D g2d) { final UText shape = (UText) ushape; final FontConfiguration fontConfiguration = shape.getFontConfiguration(); + final String text = shape.getText(); + + final List strings = StyledString.build(text); final UFont font = fontConfiguration.getFont().scaled(param.getScale()); - final Dimension2D dimBack = calculateDimension( - FileFormat.PNG.getDefaultStringBounder(TikzFontDistortion.getDefault()), font, shape.getText()); + + for (StyledString styledString : strings) { + final FontConfiguration fc = styledString.getStyle() == FontStyle.BOLD ? fontConfiguration.bold() + : fontConfiguration; + final Dimension2D dim = calculateDimension( + FileFormat.PNG.getDefaultStringBounder(TikzFontDistortion.getDefault()), fc.getFont(), + styledString.getText()); + printSingleText(g2d, fc, styledString.getText(), x, y, mapper, param); + x += dim.getWidth(); + } + } + + private void printSingleText(Graphics2D g2d, final FontConfiguration fontConfiguration, final String text, double x, + double y, ColorMapper mapper, UParam param) { + final UFont font = fontConfiguration.getFont().scaled(param.getScale()); final HColor extended = fontConfiguration.getExtendedColor(); - if (fontConfiguration.containsStyle(FontStyle.BACKCOLOR)) { - final Rectangle2D.Double area = new Rectangle2D.Double(x, y - dimBack.getHeight() + 1.5, dimBack.getWidth(), - dimBack.getHeight()); - if (extended instanceof HColorGradient) { - final GradientPaint paint = DriverRectangleG2d.getPaintGradient(x, y, mapper, dimBack.getWidth(), - dimBack.getHeight(), extended); - g2d.setPaint(paint); - g2d.fill(area); - } else { - final Color backColor = mapper.toColor(extended); - if (backColor != null) { - g2d.setColor(backColor); - g2d.setBackground(backColor); + + final int orientation = 0; + + if (orientation == 90) { + g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + g2d.setFont(font.getFont()); + g2d.setColor(mapper.toColor(fontConfiguration.getColor())); + final AffineTransform orig = g2d.getTransform(); + g2d.translate(x, y); + g2d.rotate(Math.PI / 2); + g2d.drawString(text, 0, 0); + g2d.setTransform(orig); + + } else if (orientation == 0) { + + final Dimension2D dimBack = calculateDimension( + FileFormat.PNG.getDefaultStringBounder(TikzFontDistortion.getDefault()), font, text); + if (fontConfiguration.containsStyle(FontStyle.BACKCOLOR)) { + final Rectangle2D.Double area = new Rectangle2D.Double(x, y - dimBack.getHeight() + 1.5, + dimBack.getWidth(), dimBack.getHeight()); + if (extended instanceof HColorGradient) { + final GradientPaint paint = DriverRectangleG2d.getPaintGradient(x, y, mapper, dimBack.getWidth(), + dimBack.getHeight(), extended); + g2d.setPaint(paint); g2d.fill(area); + } else { + final Color backColor = mapper.toColor(extended); + if (backColor != null) { + g2d.setColor(backColor); + g2d.setBackground(backColor); + g2d.fill(area); + } } } - } - visible.ensureVisible(x, y - dimBack.getHeight() + 1.5); - visible.ensureVisible(x + dimBack.getWidth(), y + 1.5); + visible.ensureVisible(x, y - dimBack.getHeight() + 1.5); + visible.ensureVisible(x + dimBack.getWidth(), y + 1.5); - g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); - g2d.setFont(font.getFont()); - g2d.setColor(mapper.toColor(fontConfiguration.getColor())); - g2d.drawString(shape.getText(), (float) x, (float) y); + g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + g2d.setFont(font.getFont()); + g2d.setColor(mapper.toColor(fontConfiguration.getColor())); + g2d.drawString(text, (float) x, (float) y); - if (fontConfiguration.containsStyle(FontStyle.UNDERLINE)) { - if (extended != null) { - g2d.setColor(mapper.toColor(extended)); + if (fontConfiguration.containsStyle(FontStyle.UNDERLINE)) { + if (extended != null) { + g2d.setColor(mapper.toColor(extended)); + } + final Dimension2D dim = calculateDimension( + FileFormat.PNG.getDefaultStringBounder(TikzFontDistortion.getDefault()), font, text); + final int ypos = (int) (y + 2.5); + g2d.setStroke(new BasicStroke((float) 1)); + g2d.drawLine((int) x, ypos, (int) (x + dim.getWidth()), ypos); + g2d.setStroke(new BasicStroke()); } - final Dimension2D dim = calculateDimension( - FileFormat.PNG.getDefaultStringBounder(TikzFontDistortion.getDefault()), font, shape.getText()); - final int ypos = (int) (y + 2.5); - g2d.setStroke(new BasicStroke((float) 1)); - g2d.drawLine((int) x, ypos, (int) (x + dim.getWidth()), ypos); - g2d.setStroke(new BasicStroke()); - } - if (fontConfiguration.containsStyle(FontStyle.WAVE)) { - final Dimension2D dim = calculateDimension( - FileFormat.PNG.getDefaultStringBounder(TikzFontDistortion.getDefault()), font, shape.getText()); - final int ypos = (int) (y + 2.5) - 1; - if (extended != null) { - g2d.setColor(mapper.toColor(extended)); + if (fontConfiguration.containsStyle(FontStyle.WAVE)) { + final Dimension2D dim = calculateDimension( + FileFormat.PNG.getDefaultStringBounder(TikzFontDistortion.getDefault()), font, text); + final int ypos = (int) (y + 2.5) - 1; + if (extended != null) { + g2d.setColor(mapper.toColor(extended)); + } + for (int i = (int) x; i < x + dim.getWidth() - 5; i += 6) { + g2d.drawLine(i, ypos - 0, i + 3, ypos + 1); + g2d.drawLine(i + 3, ypos + 1, i + 6, ypos - 0); + } } - for (int i = (int) x; i < x + dim.getWidth() - 5; i += 6) { - g2d.drawLine(i, ypos - 0, i + 3, ypos + 1); - g2d.drawLine(i + 3, ypos + 1, i + 6, ypos - 0); + if (fontConfiguration.containsStyle(FontStyle.STRIKE)) { + final Dimension2D dim = calculateDimension( + FileFormat.PNG.getDefaultStringBounder(TikzFontDistortion.getDefault()), font, text); + final FontMetrics fm = g2d.getFontMetrics(font.getFont()); + final int ypos = (int) (y - fm.getDescent() - 0.5); + if (extended != null) { + g2d.setColor(mapper.toColor(extended)); + } + g2d.setStroke(new BasicStroke((float) 1.5)); + g2d.drawLine((int) x, ypos, (int) (x + dim.getWidth()), ypos); + g2d.setStroke(new BasicStroke()); } } - if (fontConfiguration.containsStyle(FontStyle.STRIKE)) { - final Dimension2D dim = calculateDimension( - FileFormat.PNG.getDefaultStringBounder(TikzFontDistortion.getDefault()), font, shape.getText()); - final FontMetrics fm = g2d.getFontMetrics(font.getFont()); - final int ypos = (int) (y - fm.getDescent() - 0.5); - if (extended != null) { - g2d.setColor(mapper.toColor(extended)); - } - g2d.setStroke(new BasicStroke((float) 1.5)); - g2d.drawLine((int) x, ypos, (int) (x + dim.getWidth()), ypos); - g2d.setStroke(new BasicStroke()); - } } static public Dimension2D calculateDimension(StringBounder stringBounder, UFont font, String text) { diff --git a/src/net/sourceforge/plantuml/ugraphic/svg/UGraphicSvg.java b/src/net/sourceforge/plantuml/ugraphic/svg/UGraphicSvg.java index 56450367b..851a57d77 100644 --- a/src/net/sourceforge/plantuml/ugraphic/svg/UGraphicSvg.java +++ b/src/net/sourceforge/plantuml/ugraphic/svg/UGraphicSvg.java @@ -47,6 +47,7 @@ import net.sourceforge.plantuml.Url; import net.sourceforge.plantuml.graphic.StringBounder; import net.sourceforge.plantuml.graphic.TextBlockUtils; import net.sourceforge.plantuml.posimo.DotPath; +import net.sourceforge.plantuml.svg.LengthAdjust; import net.sourceforge.plantuml.svg.SvgGraphics; import net.sourceforge.plantuml.ugraphic.AbstractCommonUGraphic; import net.sourceforge.plantuml.ugraphic.AbstractUGraphic; @@ -90,23 +91,24 @@ public class UGraphicSvg extends AbstractUGraphic implements ClipCo public UGraphicSvg(boolean svgDimensionStyle, Dimension2D minDim, ColorMapper colorMapper, String backcolor, boolean textAsPath, double scale, String linkTarget, String hover, long seed, String preserveAspectRatio, - SvgCharSizeHack charSizeHack) { - this(minDim, colorMapper, - new SvgGraphics(svgDimensionStyle, minDim, backcolor, scale, hover, seed, preserveAspectRatio), - textAsPath, linkTarget, charSizeHack); + SvgCharSizeHack charSizeHack, LengthAdjust lengthAdjust) { + this(minDim, colorMapper, new SvgGraphics(svgDimensionStyle, minDim, backcolor, scale, hover, seed, + preserveAspectRatio, lengthAdjust), textAsPath, linkTarget, charSizeHack); } public UGraphicSvg(boolean svgDimensionStyle, Dimension2D minDim, ColorMapper colorMapper, boolean textAsPath, double scale, String linkTarget, String hover, long seed, String preserveAspectRatio, - SvgCharSizeHack charSizeHack) { - this(minDim, colorMapper, new SvgGraphics(svgDimensionStyle, minDim, scale, hover, seed, preserveAspectRatio), + SvgCharSizeHack charSizeHack, LengthAdjust lengthAdjust) { + this(minDim, colorMapper, + new SvgGraphics(svgDimensionStyle, minDim, scale, hover, seed, preserveAspectRatio, lengthAdjust), textAsPath, linkTarget, charSizeHack); } public UGraphicSvg(boolean svgDimensionStyle, Dimension2D minDim, ColorMapper mapper, HColorGradient gr, boolean textAsPath, double scale, String linkTarget, String hover, long seed, String preserveAspectRatio, - SvgCharSizeHack charSizeHack) { - this(minDim, mapper, new SvgGraphics(svgDimensionStyle, minDim, scale, hover, seed, preserveAspectRatio), + SvgCharSizeHack charSizeHack, LengthAdjust lengthAdjust) { + this(minDim, mapper, + new SvgGraphics(svgDimensionStyle, minDim, scale, hover, seed, preserveAspectRatio, lengthAdjust), textAsPath, linkTarget, charSizeHack); final SvgGraphics svg = getGraphicObject(); diff --git a/src/net/sourceforge/plantuml/version/Version.java b/src/net/sourceforge/plantuml/version/Version.java index 7f1582918..809d1a4c9 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 1202026; + return 1202100; } public static int versionPatched() { @@ -93,7 +93,7 @@ public class Version { } public static long compileTime() { - return 1608572707669L; + return 1610274305536L; } public static String compileTimeString() { diff --git a/src/net/sourceforge/plantuml/wbs/WBSDiagram.java b/src/net/sourceforge/plantuml/wbs/WBSDiagram.java index a6094981c..589d6bd6c 100644 --- a/src/net/sourceforge/plantuml/wbs/WBSDiagram.java +++ b/src/net/sourceforge/plantuml/wbs/WBSDiagram.java @@ -75,9 +75,8 @@ public class WBSDiagram extends UmlDiagram { return new DiagramDescription("Work Breakdown Structure"); } - @Override - public UmlDiagramType getUmlDiagramType() { - return UmlDiagramType.WBS; + public WBSDiagram() { + super(UmlDiagramType.WBS); } @Override diff --git a/src/net/sourceforge/plantuml/wire/CommandComponent.java b/src/net/sourceforge/plantuml/wire/CommandComponent.java index aa5db1581..65ca8d28d 100644 --- a/src/net/sourceforge/plantuml/wire/CommandComponent.java +++ b/src/net/sourceforge/plantuml/wire/CommandComponent.java @@ -43,6 +43,8 @@ import net.sourceforge.plantuml.command.regex.RegexConcat; import net.sourceforge.plantuml.command.regex.RegexLeaf; import net.sourceforge.plantuml.command.regex.RegexOptional; import net.sourceforge.plantuml.command.regex.RegexResult; +import net.sourceforge.plantuml.ugraphic.color.HColor; +import net.sourceforge.plantuml.ugraphic.color.HColorSet; public class CommandComponent extends SingleLineCommand2 { @@ -53,7 +55,9 @@ public class CommandComponent extends SingleLineCommand2 { static IRegex getRegexConcat() { return RegexConcat.build(CommandComponent.class.getName(), RegexLeaf.start(), // new RegexLeaf("INDENT", "([\\s\\t]*)"), // - new RegexLeaf("NAME", "\\$([\\w]+)"), // + new RegexLeaf("\\*"), // + RegexLeaf.spaceZeroOrMore(), // + new RegexLeaf("NAME", "([\\w]+)"), // new RegexOptional(new RegexConcat( // RegexLeaf.spaceOneOrMore(), // new RegexLeaf("\\["), // @@ -62,6 +66,9 @@ public class CommandComponent extends SingleLineCommand2 { new RegexLeaf("HEIGHT", "([\\d]+)"), // new RegexLeaf("\\]")) // ), // + new RegexOptional(new RegexConcat( // + RegexLeaf.spaceZeroOrMore(), // + new RegexLeaf("COLOR", "(#\\w+)?"))), // RegexLeaf.spaceZeroOrMore(), // RegexLeaf.end()); } @@ -80,7 +87,13 @@ public class CommandComponent extends SingleLineCommand2 { height = Integer.parseInt(heightString); } - return diagram.addComponent(indent, name, width, height); + final String stringColor = arg.get("COLOR", 0); + HColor color = null; + if (stringColor != null) { + color = HColorSet.instance().getColorIfValid(stringColor); + } + + return diagram.addComponent(indent, name, width, height, color); } } diff --git a/src/net/sourceforge/plantuml/wire/CommandPrint.java b/src/net/sourceforge/plantuml/wire/CommandPrint.java new file mode 100644 index 000000000..cb4a4480b --- /dev/null +++ b/src/net/sourceforge/plantuml/wire/CommandPrint.java @@ -0,0 +1,78 @@ +/* ======================================================================== + * 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.wire; + +import net.sourceforge.plantuml.LineLocation; +import net.sourceforge.plantuml.command.CommandExecutionResult; +import net.sourceforge.plantuml.command.SingleLineCommand2; +import net.sourceforge.plantuml.command.regex.IRegex; +import net.sourceforge.plantuml.command.regex.RegexConcat; +import net.sourceforge.plantuml.command.regex.RegexLeaf; +import net.sourceforge.plantuml.command.regex.RegexResult; + +public class CommandPrint extends SingleLineCommand2 { + + public CommandPrint() { + super(false, getRegexConcat()); + } + + static IRegex getRegexConcat() { + return RegexConcat.build(CommandPrint.class.getName(), RegexLeaf.start(), // + new RegexLeaf("INDENT", "([\\s\\t]*)"), // + new RegexLeaf("print"), // + RegexLeaf.spaceZeroOrMore(), // + new RegexLeaf("\\("), // + RegexLeaf.spaceZeroOrMore(), // + new RegexLeaf("[%g]"), // + RegexLeaf.spaceZeroOrMore(), // + new RegexLeaf("TEXT", "(.*)"), // + RegexLeaf.spaceZeroOrMore(), // + new RegexLeaf("[%g]"), // + RegexLeaf.spaceZeroOrMore(), // + new RegexLeaf("\\)"), // + RegexLeaf.spaceZeroOrMore(), // + RegexLeaf.end()); + } + + @Override + protected CommandExecutionResult executeArg(WireDiagram diagram, LineLocation location, RegexResult arg) { + final String indent = arg.get("INDENT", 0); + final String text = arg.get("TEXT", 0); + return diagram.print(indent, text); + + } + +} diff --git a/src/net/sourceforge/plantuml/wire/CommandSpot.java b/src/net/sourceforge/plantuml/wire/CommandSpot.java index c637054d4..446dec8d5 100644 --- a/src/net/sourceforge/plantuml/wire/CommandSpot.java +++ b/src/net/sourceforge/plantuml/wire/CommandSpot.java @@ -56,7 +56,7 @@ public class CommandSpot extends SingleLineCommand2 { return RegexConcat.build(CommandSpot.class.getName(), RegexLeaf.start(), // new RegexLeaf("spot"), // RegexLeaf.spaceOneOrMore(), // - new RegexLeaf("NAME", "\\$([\\w][.\\w]*)"), // + new RegexLeaf("NAME", "([\\w][.\\w]*)"), // new RegexOptional(new RegexConcat(// new RegexLeaf("\\("), // RegexLeaf.spaceZeroOrMore(), // diff --git a/src/net/sourceforge/plantuml/wire/CommandWLink.java b/src/net/sourceforge/plantuml/wire/CommandWLink.java index 49e914c8b..528e2211f 100644 --- a/src/net/sourceforge/plantuml/wire/CommandWLink.java +++ b/src/net/sourceforge/plantuml/wire/CommandWLink.java @@ -43,6 +43,7 @@ import net.sourceforge.plantuml.command.regex.RegexConcat; import net.sourceforge.plantuml.command.regex.RegexLeaf; import net.sourceforge.plantuml.command.regex.RegexOptional; import net.sourceforge.plantuml.command.regex.RegexResult; +import net.sourceforge.plantuml.cucadiagram.Display; import net.sourceforge.plantuml.ugraphic.color.HColor; import net.sourceforge.plantuml.ugraphic.color.HColorSet; @@ -54,7 +55,7 @@ public class CommandWLink extends SingleLineCommand2 { static IRegex getRegexConcat() { return RegexConcat.build(CommandWLink.class.getName(), RegexLeaf.start(), // - new RegexLeaf("NAME1", "\\$([\\w][.\\w]*)"), // + new RegexLeaf("NAME1", "([\\w][.\\w]*)"), // new RegexOptional(new RegexConcat(// new RegexLeaf("\\("), // RegexLeaf.spaceZeroOrMore(), // @@ -67,13 +68,15 @@ public class CommandWLink extends SingleLineCommand2 { new RegexLeaf("\\)") // )), // RegexLeaf.spaceZeroOrMore(), // - new RegexLeaf("STYLE", "([-=])\\>"), // + new RegexLeaf("STYLE", "(\\|\\ { final String name1 = arg.get("NAME1", 0); final String x1 = arg.get("X1", 0); final String y1 = arg.get("Y1", 0); - + final String name2 = arg.get("NAME2", 0); - final WLinkType type = WLinkType.from(arg.get("STYLE", 0)); + final String style = arg.get("STYLE", 0); + final WLinkType type = WLinkType.from(style); + final WArrowDirection direction = WArrowDirection.from(style); + final WOrientation orientation = WOrientation.from(style); final String stringColor = arg.get("COLOR", 0); HColor color = null; @@ -93,7 +99,18 @@ public class CommandWLink extends SingleLineCommand2 { color = HColorSet.instance().getColorIfValid(stringColor); } - return diagram.link(name1, x1, y1, name2, type, color); + final Display label; + if (arg.get("MESSAGE", 0) == null) { + label = Display.NULL; + } else { + final String message = arg.get("MESSAGE", 0); + label = Display.getWithNewlines(message); + } + + if (orientation == WOrientation.VERTICAL) { + return diagram.vlink(name1, x1, y1, name2, type, direction, color, label); + } + return diagram.hlink(name1, x1, y1, name2, type, direction, color, label); } } diff --git a/src/net/sourceforge/plantuml/wire/WArrowDirection.java b/src/net/sourceforge/plantuml/wire/WArrowDirection.java new file mode 100644 index 000000000..dc3d0990e --- /dev/null +++ b/src/net/sourceforge/plantuml/wire/WArrowDirection.java @@ -0,0 +1,54 @@ +/* ======================================================================== + * 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.wire; + +public enum WArrowDirection { + NORMAL, REVERSE, BOTH, NONE; + + public static WArrowDirection from(String type) { + if (type.contains("<") && type.contains(">")) { + return BOTH; + } + if (type.contains(">")) { + return NORMAL; + } + if (type.contains("<")) { + return REVERSE; + } + return NONE; + } + +} diff --git a/src/net/sourceforge/plantuml/wire/WBlock.java b/src/net/sourceforge/plantuml/wire/WBlock.java index 26d018c38..4aea0460a 100644 --- a/src/net/sourceforge/plantuml/wire/WBlock.java +++ b/src/net/sourceforge/plantuml/wire/WBlock.java @@ -41,30 +41,41 @@ import java.util.List; import java.util.StringTokenizer; import net.sourceforge.plantuml.Dimension2DDouble; +import net.sourceforge.plantuml.ISkinParam; import net.sourceforge.plantuml.SpriteContainerEmpty; import net.sourceforge.plantuml.command.CommandExecutionResult; 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.ugraphic.UFont; import net.sourceforge.plantuml.ugraphic.UGraphic; import net.sourceforge.plantuml.ugraphic.URectangle; import net.sourceforge.plantuml.ugraphic.UTranslate; +import net.sourceforge.plantuml.ugraphic.color.HColor; import net.sourceforge.plantuml.ugraphic.color.HColorUtils; public class WBlock { + private final static int STARTING_Y = 10; + private final String name; private final double forcedWidth; private final double forcedHeight; + private final HColor color; private final List children = new ArrayList(); - private UTranslate position = new UTranslate(); + private final UTranslate position; private WBlock parent; - private UTranslate futureGoto; - private UTranslate futureMove = new UTranslate(0, 20); + private UTranslate cursor = new UTranslate(10, STARTING_Y); + private WBlock addedToCursor = null; + + private UTranslate futureOutHorizontal; + private UTranslate futureOutVertical; + + private final List prints = new ArrayList(); public UTranslate getAbsolutePosition(String supx, String supy) { if (parent == null) { @@ -113,10 +124,12 @@ public class WBlock { return name + " " + position; } - public WBlock(String name, double width, double height) { + public WBlock(String name, UTranslate position, double width, double height, HColor color) { this.name = name; this.forcedWidth = width; this.forcedHeight = height; + this.color = color; + this.position = position; } private WBlock getChildByName(String name) { @@ -147,8 +160,8 @@ public class WBlock { public CommandExecutionResult newColumn(int level) { if (level == 0) { final Dimension2D max = getNaturalDimension(); - futureGoto = new UTranslate(max.getWidth() + 10, 20); - futureMove = new UTranslate(); + this.cursor = new UTranslate(max.getWidth() + 10, STARTING_Y); + this.addedToCursor = null; return CommandExecutionResult.ok(); } return getLastChild().newColumn(level - 1); @@ -156,8 +169,8 @@ public class WBlock { public CommandExecutionResult wgoto(int level, double x, double y) { if (level == 0) { - futureGoto = new UTranslate(x, y); - futureMove = new UTranslate(); + this.cursor = new UTranslate(x, y); + this.addedToCursor = null; return CommandExecutionResult.ok(); } return getLastChild().wgoto(level - 1, x, y); @@ -165,13 +178,24 @@ public class WBlock { public CommandExecutionResult wmove(int level, double x, double y) { if (level == 0) { - futureMove = futureMove.compose(new UTranslate(x, y)); + this.cursor = this.cursor.compose(new UTranslate(x, y)); return CommandExecutionResult.ok(); } return getLastChild().wmove(level - 1, x, y); } - public CommandExecutionResult addComponent(int level, String name, double width, double height) { + public CommandExecutionResult print(StringBounder stringBounder, ISkinParam skinParam, int level, String text) { + if (level == 0) { + final WPrint print = new WPrint(skinParam, getNextPosition(), null, Display.getWithNewlines(text)); + this.prints.add(print); + this.cursor = this.cursor.compose(UTranslate.dy(print.getHeight(stringBounder))); + + return CommandExecutionResult.ok(); + } + return getLastChild().print(stringBounder, skinParam, level - 1, text); + } + + public CommandExecutionResult addBlock(int level, String name, double width, double height, HColor color) { if (name.contains(".")) { throw new IllegalArgumentException(); } @@ -179,8 +203,10 @@ public class WBlock { return CommandExecutionResult.error("Component exists already"); } if (level == 0) { - final WBlock newBlock = new WBlock(name, width, height); - newBlock.position = getNextPosition(); + this.cursor = this.cursor.compose(UTranslate.dy(10)); + final WBlock newBlock = new WBlock(name, getNextPosition(), width, height, color); + this.cursor = this.cursor.compose(UTranslate.dy(10)); + this.addedToCursor = newBlock; children.add(newBlock); newBlock.parent = this; @@ -188,25 +214,16 @@ public class WBlock { } final WBlock last = getLastChild(); - return last.addComponent(level - 1, name, width, height); + return last.addBlock(level - 1, name, width, height, color); } private UTranslate getNextPosition() { - final UTranslate result; - if (futureGoto != null) { - result = futureGoto.compose(futureMove); - } else { - final WBlock last = getLastChild(); - if (last == null) { - result = futureMove.compose(UTranslate.dx(10)); - } else { - final Dimension2D dim = last.getMaxDimension(); - result = last.position.compose(UTranslate.dy(dim.getHeight())).compose(futureMove); - } + if (this.addedToCursor != null) { + final Dimension2D dim = this.addedToCursor.getMaxDimension(); + this.cursor = this.cursor.compose(UTranslate.dy(dim.getHeight())); } - futureGoto = null; - futureMove = new UTranslate(0, 20); - return result; + this.addedToCursor = null; + return this.cursor; } private WBlock getLastChild() { @@ -230,11 +247,18 @@ public class WBlock { ug = ug.apply(HColorUtils.BLACK); if (name.length() > 0) { final URectangle rect = new URectangle(getMaxDimension()); - ug.draw(rect); + UGraphic ugRect = ug; + if (color != null) { + ugRect = ugRect.apply(color.bg()); + } + ugRect.draw(rect); } for (WBlock child : children) { child.drawMe(ug.apply(child.position)); } + for (WPrint print : prints) { + print.drawMe(ug.apply(print.getPosition())); + } } private Dimension2D getMaxDimension() { @@ -260,20 +284,29 @@ public class WBlock { return new Dimension2DDouble(x, y); } - private UTranslate futureOut; - - public UTranslate getNextOut(String x1, String y1, WLinkType type) { + public UTranslate getNextOutHorizontal(String x, String y, WLinkType type) { final UTranslate result; - if (x1 != null && y1 != null) { - result = getAbsolutePosition(x1, y1); - } else if (futureOut == null) { + if (x != null && y != null) { + result = getAbsolutePosition(x, y); + } else if (futureOutHorizontal == null) { result = getAbsolutePosition("100%", "5"); } else { - result = futureOut; + result = futureOutHorizontal; } + futureOutHorizontal = result.compose(UTranslate.dy(type.spaceForNext())); + return result; + } - futureOut = result.compose(UTranslate.dy(type.ySpaceForNext())); - + public UTranslate getNextOutVertical(String x, String y, WLinkType type) { + final UTranslate result; + if (x != null && y != null) { + result = getAbsolutePosition(x, y); + } else if (futureOutVertical == null) { + result = getAbsolutePosition("5", "100%"); + } else { + result = futureOutVertical; + } + futureOutVertical = result.compose(UTranslate.dx(type.spaceForNext())); return result; } diff --git a/src/net/sourceforge/plantuml/wire/WLinkHorizontal.java b/src/net/sourceforge/plantuml/wire/WLinkHorizontal.java new file mode 100644 index 000000000..77b5de15b --- /dev/null +++ b/src/net/sourceforge/plantuml/wire/WLinkHorizontal.java @@ -0,0 +1,197 @@ +/* ======================================================================== + * 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.wire; + +import java.awt.geom.Dimension2D; + +import net.sourceforge.plantuml.ISkinParam; +import net.sourceforge.plantuml.cucadiagram.Display; +import net.sourceforge.plantuml.graphic.FontConfiguration; +import net.sourceforge.plantuml.graphic.HorizontalAlignment; +import net.sourceforge.plantuml.graphic.TextBlock; +import net.sourceforge.plantuml.ugraphic.UFont; +import net.sourceforge.plantuml.ugraphic.UGraphic; +import net.sourceforge.plantuml.ugraphic.ULine; +import net.sourceforge.plantuml.ugraphic.UPath; +import net.sourceforge.plantuml.ugraphic.URectangle; +import net.sourceforge.plantuml.ugraphic.UTranslate; +import net.sourceforge.plantuml.ugraphic.color.HColor; +import net.sourceforge.plantuml.ugraphic.color.HColorUtils; + +public class WLinkHorizontal { + + private final UTranslate start; + private final double destination; + private final WLinkType type; + private final WArrowDirection direction; + private final HColor color; + private final Display label; + private final ISkinParam skinParam; + + public WLinkHorizontal(ISkinParam skinParam, UTranslate start, double destination, WLinkType type, + WArrowDirection direction, HColor color, Display label) { + this.start = start; + this.destination = destination; + this.skinParam = skinParam; + this.direction = direction; + this.type = type; + this.label = label; + this.color = color == null ? HColorUtils.BLACK : color; + } + + private TextBlock getTextBlock() { + final FontConfiguration fontConfiguration = FontConfiguration.blackBlueTrue(UFont.sansSerif(10)) + .changeColor(color); + return label.create(fontConfiguration, HorizontalAlignment.LEFT, skinParam); + } + + public void drawMe(UGraphic ug) { + ug = ug.apply(color); + final TextBlock textBlock = getTextBlock(); + final Dimension2D dimText = textBlock.calculateDimension(ug.getStringBounder()); + + UGraphic ugText = ug.apply(start); + final double len = destination - start.getDx(); + + if (type == WLinkType.NORMAL) { + ug = ug.apply(color.bg()); + drawNormalArrow(ug); + + ugText = ugText.apply(UTranslate.dy(-dimText.getHeight() / 2)); + + } else if (type == WLinkType.BUS) { + ug = ug.apply(HColorUtils.WHITE.bg()); + drawBusArrow(ug); + ugText = ugText.apply(UTranslate.dy((20 - dimText.getHeight()) / 2 - 5)); + } + + if (dimText.getHeight() > 0) { + switch (direction) { + case NORMAL: + ugText = ugText.apply(UTranslate.dx(4)); + break; + case REVERSE: + ugText = ugText.apply(UTranslate.dx(len - dimText.getWidth() - 4)); + break; + default: + ugText = ugText.apply(UTranslate.dx((len - dimText.getWidth()) / 2)); + break; + } + if (type == WLinkType.NORMAL) { + ugText.apply(HColorUtils.WHITE).apply(HColorUtils.WHITE.bg()).draw(new URectangle(dimText)); + } + textBlock.drawU(ugText); + } + + } + + private void drawBusArrow(UGraphic ug) { + final double dx = destination - start.getDx() - 2; + final UPath path = new UPath(); + if (direction == WArrowDirection.NONE) { + path.moveTo(0, 0); + path.lineTo(dx, 0); + path.lineTo(dx, 10); + path.lineTo(0, 10); + path.lineTo(0, 0); + path.closePath(); + ug.apply(start.compose(UTranslate.dx(1))).draw(path); + } + if (direction == WArrowDirection.NORMAL) { + path.moveTo(0, 0); + path.lineTo(dx - 15, 0); + path.lineTo(dx - 15, -5); + path.lineTo(dx, 5); + path.lineTo(dx - 15, 15); + path.lineTo(dx - 15, 10); + path.lineTo(0, 10); + path.lineTo(0, 0); + path.closePath(); + ug.apply(start.compose(UTranslate.dx(1))).draw(path); + } + if (direction == WArrowDirection.BOTH) { + path.moveTo(0, 5); + path.lineTo(15, -5); + path.lineTo(15, 0); + path.lineTo(dx - 15, 0); + path.lineTo(dx - 15, -5); + path.lineTo(dx, 5); + path.lineTo(dx - 15, 15); + path.lineTo(dx - 15, 10); + path.lineTo(15, 10); + path.lineTo(15, 15); + path.lineTo(0, 5); + path.closePath(); + ug.apply(start.compose(UTranslate.dx(1))).draw(path); + } + if (direction == WArrowDirection.REVERSE) { + path.moveTo(0, 5); + path.lineTo(15, -5); + path.lineTo(15, 0); + path.lineTo(dx, 0); + path.lineTo(dx, 10); + path.lineTo(15, 10); + path.lineTo(15, 15); + path.lineTo(0, 5); + path.closePath(); + ug.apply(start.compose(UTranslate.dx(1))).draw(path); + } + } + + private void drawNormalArrow(UGraphic ug) { + final double dx = destination - start.getDx() - 2; + if (direction == WArrowDirection.BOTH || direction == WArrowDirection.NORMAL) { + final UPath path = new UPath(); + path.moveTo(0, 0); + path.lineTo(-5, -5); + path.lineTo(-5, 5); + path.lineTo(0, 0); + path.closePath(); + ug.apply(start.compose(UTranslate.dx(dx))).draw(path); + } + if (direction == WArrowDirection.BOTH || direction == WArrowDirection.REVERSE) { + final UPath path = new UPath(); + path.moveTo(0, 0); + path.lineTo(5, -5); + path.lineTo(5, 5); + path.lineTo(0, 0); + path.closePath(); + ug.apply(start.compose(UTranslate.dx(1))).draw(path); + } + ug.apply(start.compose(UTranslate.dx(1))).draw(ULine.hline(dx)); + } + +} diff --git a/src/net/sourceforge/plantuml/wire/WLinkType.java b/src/net/sourceforge/plantuml/wire/WLinkType.java index 6c1df7926..3a08379eb 100644 --- a/src/net/sourceforge/plantuml/wire/WLinkType.java +++ b/src/net/sourceforge/plantuml/wire/WLinkType.java @@ -40,16 +40,16 @@ public enum WLinkType { NORMAL, BUS; static public WLinkType from(String arg) { - if (arg.equals("-")) { + if (arg.contains("-")) { return WLinkType.NORMAL; } - if (arg.equals("=")) { + if (arg.contains("=")) { return WLinkType.BUS; } throw new IllegalArgumentException(); } - public double ySpaceForNext() { + public double spaceForNext() { switch (this) { case NORMAL: return 15; diff --git a/src/net/sourceforge/plantuml/wire/WLinkVertical.java b/src/net/sourceforge/plantuml/wire/WLinkVertical.java new file mode 100644 index 000000000..945d796ee --- /dev/null +++ b/src/net/sourceforge/plantuml/wire/WLinkVertical.java @@ -0,0 +1,164 @@ +/* ======================================================================== + * 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.wire; + +import net.sourceforge.plantuml.ISkinParam; +import net.sourceforge.plantuml.cucadiagram.Display; +import net.sourceforge.plantuml.graphic.FontConfiguration; +import net.sourceforge.plantuml.graphic.HorizontalAlignment; +import net.sourceforge.plantuml.graphic.TextBlock; +import net.sourceforge.plantuml.ugraphic.UFont; +import net.sourceforge.plantuml.ugraphic.UGraphic; +import net.sourceforge.plantuml.ugraphic.ULine; +import net.sourceforge.plantuml.ugraphic.UPath; +import net.sourceforge.plantuml.ugraphic.UTranslate; +import net.sourceforge.plantuml.ugraphic.color.HColor; +import net.sourceforge.plantuml.ugraphic.color.HColorUtils; + +public class WLinkVertical { + + private final UTranslate start; + private final double destination; + private final WLinkType type; + private final WArrowDirection direction; + private final HColor color; + private final Display label; + private final ISkinParam skinParam; + + public WLinkVertical(ISkinParam skinParam, UTranslate start, double destination, WLinkType type, + WArrowDirection direction, HColor color, Display label) { + this.start = start; + this.destination = destination; + this.skinParam = skinParam; + this.direction = direction; + this.type = type; + this.label = label; + this.color = color == null ? HColorUtils.BLACK : color; + } + + private TextBlock getTextBlock() { + final FontConfiguration fontConfiguration = FontConfiguration.blackBlueTrue(UFont.sansSerif(10)) + .changeColor(color); + return label.create(fontConfiguration, HorizontalAlignment.LEFT, skinParam); + } + + public void drawMe(UGraphic ug) { + ug = ug.apply(color); + if (type == WLinkType.NORMAL) { + ug = ug.apply(color.bg()); + drawNormalArrow(ug); + } else if (type == WLinkType.BUS) { + ug = ug.apply(HColorUtils.WHITE.bg()); + drawBusArrow(ug); + } + } + + private void drawBusArrow(UGraphic ug) { + final double dy = destination - start.getDy() - 2; + final UPath path = new UPath(); + if (direction == WArrowDirection.NONE) { + path.moveTo(0, 0); + path.lineTo(0, dy); + path.lineTo(10, dy); + path.lineTo(10, 0); + path.lineTo(0, 0); + path.closePath(); + ug.apply(start.compose(UTranslate.dy(1))).draw(path); + } + if (direction == WArrowDirection.NORMAL) { + path.moveTo(0, 0); + path.lineTo(0, dy - 15); + path.lineTo(-5, dy - 15); + path.lineTo(5, dy); + path.lineTo(15, dy - 15); + path.lineTo(10, dy - 15); + path.lineTo(10, 0); + path.lineTo(0, 0); + path.closePath(); + ug.apply(start.compose(UTranslate.dy(1))).draw(path); + } + if (direction == WArrowDirection.BOTH) { + path.moveTo(5, 0); + path.lineTo(-5, 15); + path.lineTo(0, 15); + path.lineTo(0, dy - 15); + path.lineTo(-5, dy - 15); + path.lineTo(5, dy); + path.lineTo(15, dy - 15); + path.lineTo(10, dy - 15); + path.lineTo(10, 15); + path.lineTo(15, 15); + path.lineTo(5, 0); + path.closePath(); + ug.apply(start.compose(UTranslate.dy(1))).draw(path); + } + if (direction == WArrowDirection.REVERSE) { + path.moveTo(5, 0); + path.lineTo(-5, 15); + path.lineTo(0, 15); + path.lineTo(0, dy); + path.lineTo(10, dy); + path.lineTo(10, 15); + path.lineTo(15, 15); + path.lineTo(5, 0); + path.closePath(); + ug.apply(start.compose(UTranslate.dy(1))).draw(path); + } } + + private void drawNormalArrow(UGraphic ug) { + final double dy = destination - start.getDy() - 2; + if (direction == WArrowDirection.BOTH || direction == WArrowDirection.NORMAL) { + final UPath path = new UPath(); + path.moveTo(0, 0); + path.lineTo(5, -5); + path.lineTo(-5, -5); + path.lineTo(0, 0); + path.closePath(); + ug.apply(start.compose(UTranslate.dy(dy))).draw(path); + } + if (direction == WArrowDirection.BOTH || direction == WArrowDirection.REVERSE) { + final UPath path = new UPath(); + path.moveTo(0, 0); + path.lineTo(5, 5); + path.lineTo(-5, 5); + path.lineTo(0, 0); + path.closePath(); + ug.apply(start.compose(UTranslate.dy(1))).draw(path); + } + ug.apply(start.compose(UTranslate.dy(1))).draw(ULine.vline(dy)); + } + +} diff --git a/src/net/sourceforge/plantuml/wire/WOrientation.java b/src/net/sourceforge/plantuml/wire/WOrientation.java new file mode 100644 index 000000000..56f97d0f6 --- /dev/null +++ b/src/net/sourceforge/plantuml/wire/WOrientation.java @@ -0,0 +1,48 @@ +/* ======================================================================== + * 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.wire; + +public enum WOrientation { + + HORIZONTAL, VERTICAL; + + public static WOrientation from(String style) { + if (style.contains("==") || style.contains("--")) { + return WOrientation.VERTICAL; + } + return HORIZONTAL; + } +} diff --git a/src/net/sourceforge/plantuml/wire/WLink.java b/src/net/sourceforge/plantuml/wire/WPrint.java similarity index 58% rename from src/net/sourceforge/plantuml/wire/WLink.java rename to src/net/sourceforge/plantuml/wire/WPrint.java index 618c05933..4f53de05f 100644 --- a/src/net/sourceforge/plantuml/wire/WLink.java +++ b/src/net/sourceforge/plantuml/wire/WPrint.java @@ -35,57 +35,49 @@ */ package net.sourceforge.plantuml.wire; +import net.sourceforge.plantuml.ISkinParam; +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.ugraphic.UChange; +import net.sourceforge.plantuml.ugraphic.UFont; import net.sourceforge.plantuml.ugraphic.UGraphic; -import net.sourceforge.plantuml.ugraphic.ULine; -import net.sourceforge.plantuml.ugraphic.UPath; import net.sourceforge.plantuml.ugraphic.UTranslate; import net.sourceforge.plantuml.ugraphic.color.HColor; import net.sourceforge.plantuml.ugraphic.color.HColorUtils; -public class WLink { +public class WPrint { - private final UTranslate pos1; - private final double pos2x; - private final WLinkType type; + private final UTranslate position; private final HColor color; + private final Display label; + private final ISkinParam skinParam; - public WLink(WBlock block1, String x1, String y1, WBlock block2, WLinkType type, HColor color) { - pos1 = block1.getNextOut(x1, y1, type); - pos2x = block2.getAbsolutePosition("0", "0").getDx(); - this.type = type; + public WPrint(ISkinParam skinParam, UTranslate position, HColor color, Display label) { + this.position = position; + this.skinParam = skinParam; + this.label = label; this.color = color == null ? HColorUtils.BLACK : color; } + private TextBlock getTextBlock() { + final FontConfiguration fontConfiguration = FontConfiguration.blackBlueTrue(UFont.sansSerif(10)) + .changeColor(color); + return label.create(fontConfiguration, HorizontalAlignment.LEFT, skinParam); + } + + public UChange getPosition() { + return position; + } + public void drawMe(UGraphic ug) { + getTextBlock().drawU(ug); + } - final double dx = pos2x - pos1.getDx() - 2; - - ug = ug.apply(color).apply(color.bg()); - - if (type == WLinkType.NORMAL) { - final UPath path = new UPath(); - path.moveTo(0, 0); - path.lineTo(-5, -5); - path.lineTo(-5, 5); - path.lineTo(0, 0); - path.closePath(); - ug.apply(pos1.compose(UTranslate.dx(dx))).draw(path); - ug.apply(pos1.compose(UTranslate.dx(1))).draw(ULine.hline(dx)); - - } else if (type == WLinkType.BUS) { - final UPath path = new UPath(); - path.moveTo(0, 0); - path.lineTo(dx - 15, 0); - path.lineTo(dx - 15, -5); - path.lineTo(dx, 5); - path.lineTo(dx - 15, 15); - path.lineTo(dx - 15, 10); - path.lineTo(0, 10); - path.lineTo(0, 0); - path.closePath(); - ug.apply(pos1.compose(UTranslate.dx(1))).draw(path); - } - + public double getHeight(StringBounder stringBounder) { + return getTextBlock().calculateDimension(stringBounder).getHeight(); } } diff --git a/src/net/sourceforge/plantuml/wire/WireDiagram.java b/src/net/sourceforge/plantuml/wire/WireDiagram.java index 2623bdda3..0df0ad217 100644 --- a/src/net/sourceforge/plantuml/wire/WireDiagram.java +++ b/src/net/sourceforge/plantuml/wire/WireDiagram.java @@ -43,16 +43,19 @@ import java.util.ArrayList; import java.util.List; import net.sourceforge.plantuml.AnnotatedWorker; +import net.sourceforge.plantuml.FileFormat; import net.sourceforge.plantuml.FileFormatOption; import net.sourceforge.plantuml.ISkinParam; import net.sourceforge.plantuml.Scale; import net.sourceforge.plantuml.SkinParam; +import net.sourceforge.plantuml.TikzFontDistortion; import net.sourceforge.plantuml.UmlDiagram; import net.sourceforge.plantuml.UmlDiagramType; import net.sourceforge.plantuml.UseStyle; import net.sourceforge.plantuml.command.CommandExecutionResult; import net.sourceforge.plantuml.core.DiagramDescription; import net.sourceforge.plantuml.core.ImageData; +import net.sourceforge.plantuml.cucadiagram.Display; import net.sourceforge.plantuml.graphic.InnerStrategy; import net.sourceforge.plantuml.graphic.StringBounder; import net.sourceforge.plantuml.graphic.TextBlock; @@ -62,21 +65,22 @@ import net.sourceforge.plantuml.ugraphic.ImageBuilder; import net.sourceforge.plantuml.ugraphic.ImageParameter; import net.sourceforge.plantuml.ugraphic.MinMax; import net.sourceforge.plantuml.ugraphic.UGraphic; +import net.sourceforge.plantuml.ugraphic.UTranslate; import net.sourceforge.plantuml.ugraphic.color.HColor; public class WireDiagram extends UmlDiagram { - private final WBlock root = new WBlock("", 0, 0); + private final WBlock root = new WBlock("", new UTranslate(), 0, 0, null); private final List spots = new ArrayList(); - private final List links = new ArrayList(); + private final List hlinks = new ArrayList(); + private final List vlinks = new ArrayList(); public DiagramDescription getDescription() { return new DiagramDescription("Wire Diagram"); } - @Override - public UmlDiagramType getUmlDiagramType() { - return UmlDiagramType.WIRE; + public WireDiagram() { + super(UmlDiagramType.WIRE); } @Override @@ -145,19 +149,22 @@ public class WireDiagram extends UmlDiagram { for (Spot spot : spots) { spot.drawMe(ug); } - for (WLink link : links) { + for (WLinkHorizontal link : hlinks) { + link.drawMe(ug); + } + for (WLinkVertical link : vlinks) { link.drawMe(ug); } } - public CommandExecutionResult addComponent(String indent, String name, int width, int height) { - final int level = indent.replace(" ", "\t").length(); - return this.root.addComponent(level, name, width, height); + public CommandExecutionResult addComponent(String indent, String name, int width, int height, HColor color) { + final int level = computeIndentationLevel(indent); + return this.root.addBlock(level, name, width, height, color); } public CommandExecutionResult newColumn(String indent) { - final int level = indent.replace(" ", "\t").length(); + final int level = computeIndentationLevel(indent); return this.root.newColumn(level); } @@ -172,16 +179,29 @@ public class WireDiagram extends UmlDiagram { } public CommandExecutionResult wgoto(String indent, double x, double y) { - final int level = indent.replace(" ", "\t").length(); + final int level = computeIndentationLevel(indent); return this.root.wgoto(level, x, y); } public CommandExecutionResult wmove(String indent, double x, double y) { - final int level = indent.replace(" ", "\t").length(); + final int level = computeIndentationLevel(indent); return this.root.wmove(level, x, y); } - public CommandExecutionResult link(String name1, String x1, String y1, String name2, WLinkType type, HColor color) { + public CommandExecutionResult print(String indent, String text) { + final int level = computeIndentationLevel(indent); + + final StringBounder stringBounder = FileFormat.PNG.getDefaultStringBounder(TikzFontDistortion.getDefault()); + return this.root.print(stringBounder, getSkinParam(), level, text); + } + + private int computeIndentationLevel(String indent) { + final int level = indent.replace(" ", "\t").length(); + return level; + } + + public CommandExecutionResult vlink(String name1, String x1, String y1, String name2, WLinkType type, + WArrowDirection direction, HColor color, Display label) { final WBlock block1 = this.root.getBlock(name1); if (block1 == null) { return CommandExecutionResult.error("No such element " + name1); @@ -190,8 +210,30 @@ public class WireDiagram extends UmlDiagram { if (block2 == null) { return CommandExecutionResult.error("No such element " + name2); } - final WLink link = new WLink(block1, x1, y1, block2, type, color); - this.links.add(link); + + final UTranslate start = block1.getNextOutVertical(x1, y1, type); + final double destination = block2.getAbsolutePosition("0", "0").getDy(); + + this.vlinks.add(new WLinkVertical(getSkinParam(), start, destination, type, direction, color, label)); + + return CommandExecutionResult.ok(); + } + + public CommandExecutionResult hlink(String name1, String x1, String y1, String name2, WLinkType type, + WArrowDirection direction, HColor color, Display label) { + final WBlock block1 = this.root.getBlock(name1); + if (block1 == null) { + return CommandExecutionResult.error("No such element " + name1); + } + final WBlock block2 = this.root.getBlock(name2); + if (block2 == null) { + return CommandExecutionResult.error("No such element " + name2); + } + + final UTranslate start = block1.getNextOutHorizontal(x1, y1, type); + final double destination = block2.getAbsolutePosition("0", "0").getDx(); + + this.hlinks.add(new WLinkHorizontal(getSkinParam(), start, destination, type, direction, color, label)); return CommandExecutionResult.ok(); } diff --git a/src/net/sourceforge/plantuml/wire/WireDiagramFactory.java b/src/net/sourceforge/plantuml/wire/WireDiagramFactory.java index 3dcd90ca1..32d34775f 100644 --- a/src/net/sourceforge/plantuml/wire/WireDiagramFactory.java +++ b/src/net/sourceforge/plantuml/wire/WireDiagramFactory.java @@ -59,6 +59,7 @@ public class WireDiagramFactory extends PSystemCommandFactory { cmds.add(new CommandMove()); cmds.add(new CommandWLink()); cmds.add(new CommandNewColumn()); + cmds.add(new CommandPrint()); return cmds; } diff --git a/src/net/sourceforge/plantuml/yaml/SimpleYamlParser.java b/src/net/sourceforge/plantuml/yaml/SimpleYamlParser.java new file mode 100644 index 000000000..e844baaf0 --- /dev/null +++ b/src/net/sourceforge/plantuml/yaml/SimpleYamlParser.java @@ -0,0 +1,273 @@ +/* ======================================================================== + * 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.yaml; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import net.sourceforge.plantuml.StringUtils; +import net.sourceforge.plantuml.json.JsonArray; +import net.sourceforge.plantuml.json.JsonObject; +import net.sourceforge.plantuml.json.JsonValue; + +public class SimpleYamlParser { + + private static final String KEY = "([_0-9\\w][- _0-9\\w]*)"; + + private JsonObject result; + private final List pendingIndents = new ArrayList(); + + public JsonObject parse(List lines) { + List tmp = new ArrayList(); + for (String s : lines) { + if (s.trim().length() == 0) + continue; + if (s.trim().startsWith("#")) + continue; + tmp.add(s); + } + tmp = mergeMultiline(tmp); + result = new JsonObject(); + pendingIndents.clear(); + pendingIndents.add(0); + for (String s : tmp) { + parseSingleLine(s); + } + return result; + + } + + private List mergeMultiline(List tmp) { + final List result = new ArrayList(); + for (int i = 0; i < tmp.size(); i++) { + if (nameOnly(tmp.get(i)) != null && textOnly(tmp.get(i + 1))) { + final StringBuilder sb = new StringBuilder(tmp.get(i)); + while (textOnly(tmp.get(i + 1))) { + sb.append(" " + tmp.get(i + 1).trim()); + i++; + } + result.add(sb.toString()); + } else { + result.add(tmp.get(i)); + } + } + return result; + } + + private String[] dashNameAndValue(String s) { + final Pattern p1 = Pattern.compile("^\\s*[-]\\s*" + KEY + "\\s*:\\s*(\\S.*)$"); + final Matcher m1 = p1.matcher(s); + if (m1.matches()) { + final String name = m1.group(1); + final String data = m1.group(2).trim(); + return new String[] { name, data }; + } + return null; + } + + private String[] nameAndValue(String s) { + final Pattern p1 = Pattern.compile("^\\s*" + KEY + "\\s*:\\s*(\\S.*)$"); + final Matcher m1 = p1.matcher(s); + if (m1.matches()) { + final String name = m1.group(1); + final String data = m1.group(2).trim(); + return new String[] { name, data }; + } + return null; + } + + private String nameOnly(String s) { + final Pattern p1 = Pattern.compile("^\\s*" + KEY + "\\s*:\\s*\\|?\\s*$"); + final Matcher m1 = p1.matcher(s); + if (m1.matches()) { + final String name = m1.group(1); + return name; + } + return null; + } + + private String listedValue(String s) { + final Pattern p1 = Pattern.compile("^\\s*[-]\\s*(\\S.*)$"); + final Matcher m1 = p1.matcher(s); + if (m1.matches()) { + final String name = m1.group(1).trim(); + return name; + } + return null; + } + + private boolean textOnly(String s) { + if (isList(s)) + return false; + return s.indexOf(':') == -1; + } + + private void parseSingleLine(String s) { + // System.err.println("s=" + s); + final int indent = getIndent(s); + + if (isListStrict(s)) { + muteToArray(indent); + return; + } + + final String[] dashNameAndValue = dashNameAndValue(s); + if (dashNameAndValue != null) { + muteToArray(indent); + parseSingleLine(s.replaceFirst("[-]", " ")); + return; + } + + final String listedValue = listedValue(s); + if (listedValue != null) { + final JsonArray array = getForceArray(indent); + array.add(listedValue); + return; + } + + final JsonObject working = getWorking(indent); + if (working == null) { + System.err.println("ERROR: ignoring " + s); + return; + } + + final String[] nameAndValue = nameAndValue(s); + if (nameAndValue != null) { + final String name = nameAndValue[0]; + final String data = StringUtils.eventuallyRemoveStartingAndEndingDoubleQuote(nameAndValue[1], "\""); + working.add(name, data); + return; + } + + final String nameOnly = nameOnly(s); + if (nameOnly != null) { + working.add(nameOnly, new JsonObject()); + return; + } + + throw new UnsupportedOperationException(s); + } + + private JsonArray getForceArray(int indent) { + while (getLastIndent() > indent - 1) + pendingIndents.remove(pendingIndents.size() - 1); + + final JsonObject last = search(result, pendingIndents.size()); + final String field = last.names().get(last.size() - 1); + if (last.get(field) instanceof JsonArray == false) { + last.set(field, new JsonArray()); + } + return (JsonArray) last.get(field); + } + + private void muteToArray(int indent) { + while (getLastIndent() > indent) + pendingIndents.remove(pendingIndents.size() - 1); + + final JsonObject last = search(result, pendingIndents.size()); + final String field = last.names().get(last.size() - 1); + if (last.get(field) instanceof JsonArray == false) { + last.set(field, new JsonArray()); + } else { + ((JsonArray) last.get(field)).add(new JsonObject()); + } + } + + private boolean isList(String s) { + return s.trim().startsWith("-"); + } + + private boolean isListStrict(String s) { + return s.trim().equals("-"); + } + + private int getLastIndent() { + return pendingIndents.get(pendingIndents.size() - 1); + } + + private JsonObject getWorking(int indent) { + if (indent > getLastIndent()) { + pendingIndents.add(indent); + return search(result, pendingIndents.size()); + } + if (indent == getLastIndent()) { + return search(result, pendingIndents.size()); + } + final int idx = pendingIndents.indexOf(indent); + if (idx == -1) { + return null; + } + + while (pendingIndents.size() > idx + 1) + pendingIndents.remove(pendingIndents.size() - 1); + + return search(result, pendingIndents.size()); + } + + private static JsonObject search(JsonObject current, int size) { + if (size <= 1) { + return current; + } + final String last = current.names().get(current.size() - 1); + // System.err.println("last=" + last); + JsonValue tmp = current.get(last); + if (tmp instanceof JsonArray) { + JsonArray array = (JsonArray) tmp; + if (array.size() == 0) { + tmp = new JsonObject(); + array.add(tmp); + } else { + tmp = array.get(array.size() - 1); + } + } + return search((JsonObject) tmp, size - 1); + } + + private int getIndent(String s) { + int indent = 0; + for (int i = 0; i < s.length(); i++) { + final char ch = s.charAt(i); + if (ch == ' ' || ch == '\t') { + indent++; + } else { + return indent; + } + } + return 0; + } + +} \ No newline at end of file diff --git a/src/net/sourceforge/plantuml/yaml/YamlDiagramFactory.java b/src/net/sourceforge/plantuml/yaml/YamlDiagramFactory.java new file mode 100644 index 000000000..f351ab708 --- /dev/null +++ b/src/net/sourceforge/plantuml/yaml/YamlDiagramFactory.java @@ -0,0 +1,79 @@ +/* ======================================================================== + * 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.yaml; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import net.sourceforge.plantuml.StringLocated; +import net.sourceforge.plantuml.UmlDiagramType; +import net.sourceforge.plantuml.command.PSystemAbstractFactory; +import net.sourceforge.plantuml.core.Diagram; +import net.sourceforge.plantuml.core.DiagramType; +import net.sourceforge.plantuml.core.UmlSource; +import net.sourceforge.plantuml.json.JsonObject; +import net.sourceforge.plantuml.jsondiagram.JsonDiagram; + +public class YamlDiagramFactory extends PSystemAbstractFactory { + + public YamlDiagramFactory() { + super(DiagramType.YAML); + } + + public Diagram createSystem(UmlSource source) { + JsonObject yaml = null; + try { + final List list = new ArrayList(); + final Iterator it = source.iterator2(); + it.next(); + while (true) { + final String line = it.next().getString(); + if (it.hasNext() == false) { + break; + } + list.add(line); + } + yaml = new SimpleYamlParser().parse(list); + } catch (Exception e) { + e.printStackTrace(); + } + final JsonDiagram result = new JsonDiagram(UmlDiagramType.YAML, yaml, new ArrayList()); + result.setSource(source); + return result; + } + +} diff --git a/stdlib/c4-abx.repx b/stdlib/c4-abx.repx index 5f36249ad..86f12fdf5 100644 Binary files a/stdlib/c4-abx.repx and b/stdlib/c4-abx.repx differ diff --git a/stdlib/c4-dex.repx b/stdlib/c4-dex.repx index 1c8a0e797..82d2be92e 100644 Binary files a/stdlib/c4-dex.repx and b/stdlib/c4-dex.repx differ diff --git a/stdlib/cloudogu-abx.repx b/stdlib/cloudogu-abx.repx index d65355036..24c9f725c 100644 Binary files a/stdlib/cloudogu-abx.repx and b/stdlib/cloudogu-abx.repx differ diff --git a/stdlib/office-abx.repx b/stdlib/office-abx.repx index aab96209e..f0069b29f 100644 Binary files a/stdlib/office-abx.repx and b/stdlib/office-abx.repx differ