diff --git a/.github/scripts/release-snapshot.sh b/.github/scripts/release-snapshot.sh index aef91a4a7..c850400bf 100755 --- a/.github/scripts/release-snapshot.sh +++ b/.github/scripts/release-snapshot.sh @@ -34,6 +34,7 @@ fi echo -n "${DATE_TIME_UTC}" > "${RELEASE_DIR}/plantuml-SNAPSHOT.timestamp" cat <<-EOF >notes.txt + ## Version ~v${POM_VERSION%-SNAPSHOT} of the ${DATE_TIME_UTC} This is a pre-release of [the latest development work](https://github.com/plantuml/plantuml/commits/). ⚠️ **It is not ready for general use** ⚠️ ⏱ _Snapshot taken the ${DATE_TIME_UTC}_ @@ -42,8 +43,8 @@ EOF gh release create \ --prerelease \ --target "${GITHUB_SHA}" \ - --title "${TAG}" \ + --title "${TAG} (~v${POM_VERSION%-SNAPSHOT})" \ --notes-file notes.txt \ "${TAG}" ${RELEASE_DIR}/* -echo "::notice title=release snapshot::Snapshot released at ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/releases/tag/${TAG} and taken the ${DATE_TIME_UTC}" +echo "::notice title=release snapshot::Snapshot (~v${POM_VERSION%-SNAPSHOT}) released at ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/releases/tag/${TAG} and taken the ${DATE_TIME_UTC}" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7f3665009..c973cb87d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,6 +27,9 @@ jobs: do_snapshot_release: ${{ steps.config.outputs.do_snapshot_release }} pom_version: ${{ steps.config.outputs.pom_version }} steps: + - name: Checkout the repository + uses: actions/checkout@v3 + - name: Configure workflow id: config env: @@ -59,6 +62,8 @@ jobs: elif [[ "${GITHUB_EVENT_NAME}" =~ push|workflow_dispatch && "${REF}" == "refs/heads/master" ]]; then echo "::notice title=::This run will release a snapshot" echo "::set-output name=do_snapshot_release::true" + V=$(perl -ne 'if (/return (\d{6,7});/) {$v=$1} if (/final int beta = (\d+);/) {$b=$1} END{print(substr($v, 0, 1),".", substr($v, 1, 4),"."); if ($b) {print(int(substr($v+1, 5)), "beta", $b);} else {print(int(substr($v, 5)))}}' src/net/sourceforge/plantuml/version/Version.java) + echo "::set-output name=pom_version::$V-SNAPSHOT" # pom_version is taken from Version.java else echo "This run will NOT make a release" diff --git a/gradle.properties b/gradle.properties index 92dd41656..7ca89723a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1 @@ -version = 1.2022.1-SNAPSHOT +version = M.YYYY.m-SNAPSHOT diff --git a/skin/plantuml.skin b/skin/plantuml.skin index 641e5e181..d2183accf 100644 --- a/skin/plantuml.skin +++ b/skin/plantuml.skin @@ -205,6 +205,9 @@ spot { spotEntity { BackgroundColor #ADD1B2 } + spotException { + BackgroundColor #D94321 + } } @@ -551,6 +554,9 @@ spot { spotEntity { BackgroundColor #2E5233 } + spotException { + BackgroundColor #7D0000 + } } diff --git a/src/net/sourceforge/plantuml/AnnotatedWorker.java b/src/net/sourceforge/plantuml/AnnotatedWorker.java index 080fbbfc4..4cac307da 100644 --- a/src/net/sourceforge/plantuml/AnnotatedWorker.java +++ b/src/net/sourceforge/plantuml/AnnotatedWorker.java @@ -179,7 +179,8 @@ public class AnnotatedWorker { final Style style = StyleSignatureBasic.of(SName.root, SName.document, SName.caption) .getMergedStyle(skinParam.getCurrentStyleBuilder()); - return style.createTextBlockBordered(caption.getDisplay(), skinParam.getIHtmlColorSet(), skinParam); + return style.createTextBlockBordered(caption.getDisplay(), skinParam.getIHtmlColorSet(), skinParam, + Style.ID_CAPTION); } @@ -191,7 +192,7 @@ public class AnnotatedWorker { final Style style = StyleSignatureBasic.of(SName.root, SName.document, SName.title) .getMergedStyle(skinParam.getCurrentStyleBuilder()); final TextBlock block = style.createTextBlockBordered(title.getDisplay(), skinParam.getIHtmlColorSet(), - skinParam); + skinParam, Style.ID_TITLE); return DecorateEntityImage.addTop(original, block, HorizontalAlignment.CENTER); } diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/EntityImageLegend.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/EntityImageLegend.java index d64176e79..e84c09991 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/EntityImageLegend.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/EntityImageLegend.java @@ -49,7 +49,7 @@ public class EntityImageLegend { final Style style = StyleSignatureBasic .of(SName.root, SName.root, SName.document, skinParam.getUmlDiagramType().getStyleName(), SName.legend) .getMergedStyle(skinParam.getCurrentStyleBuilder()); - return style.createTextBlockBordered(note, skinParam.getIHtmlColorSet(), skinParam); + return style.createTextBlockBordered(note, skinParam.getIHtmlColorSet(), skinParam, Style.ID_LEGEND); } } diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/Snake.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/Snake.java index 08767b436..054243b4b 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/Snake.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/Snake.java @@ -321,9 +321,9 @@ public class Snake implements UShape { if (same(this.getLast(), other.getFirst())) { final UPolygon oneOf = other.endDecoration == null ? endDecoration : other.endDecoration; - if (this.startDecoration != null || other.startDecoration != null) { + if (this.startDecoration != null || other.startDecoration != null) throw new UnsupportedOperationException("Not yet coded: to be done"); - } + final ArrayList mergeTexts = new ArrayList(this.texts); mergeTexts.addAll(other.texts); final Snake result = new Snake(skinParam, null, color, oneOf, this.worm.merge(other.worm, strategy), diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vertical/FtileBoxOld.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vertical/FtileBoxOld.java index d0501f0db..ff82a7c2f 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vertical/FtileBoxOld.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vertical/FtileBoxOld.java @@ -57,7 +57,6 @@ import net.sourceforge.plantuml.creole.SheetBlock1; import net.sourceforge.plantuml.creole.SheetBlock2; import net.sourceforge.plantuml.creole.Stencil; import net.sourceforge.plantuml.cucadiagram.Display; -import net.sourceforge.plantuml.cucadiagram.Stereotype; import net.sourceforge.plantuml.graphic.FontConfiguration; import net.sourceforge.plantuml.graphic.HorizontalAlignment; import net.sourceforge.plantuml.graphic.Rainbow; @@ -135,23 +134,6 @@ public class FtileBoxOld extends AbstractFtile { } - public static FtileBoxOld create(ISkinParam skinParam, Display label, Swimlane swimlane, BoxStyle boxStyle, - Stereotype stereotype) { - final Style style = getDefaultStyleDefinitionActivity().withTOBECHANGED(stereotype) - .getMergedStyle(skinParam.getCurrentStyleBuilder()); - final Style styleArrow = getDefaultStyleDefinitionArrow().getMergedStyle(skinParam.getCurrentStyleBuilder()); - - return new FtileBoxOld(skinParam, label, swimlane, boxStyle, style, styleArrow); - } - - public static TextBlock createWbs(StyleBuilder styleBuilder, ISkinParam skinParam, Display label, - StyleSignatureBasic styleDefinition) { - final Style style = styleDefinition.getMergedStyle(styleBuilder); - final Style styleArrow = style; - - return new FtileBoxOld(skinParam, label, null, BoxStyle.PLAIN, style, styleArrow); - } - public static TextBlock createWbs(Style style, ISkinParam skinParam, Display label) { final Style styleArrow = style; return new FtileBoxOld(skinParam, label, null, BoxStyle.PLAIN, style, styleArrow); @@ -232,8 +214,7 @@ public class FtileBoxOld extends AbstractFtile { tb.drawU(ug.apply(new UTranslate(dimTotal.getWidth() - tbWidth(stringBounder) - padding.getRight(), padding.getBottom()))); else if (horizontalAlignment == HorizontalAlignment.CENTER) - tb.drawU(ug.apply(new UTranslate(padding.getRight() + (dimTotal.getWidth() - tbWidth(stringBounder)) / 2, - padding.getBottom()))); + tb.drawU(ug.apply(new UTranslate((dimTotal.getWidth() - tbWidth(stringBounder)) / 2, padding.getBottom()))); } diff --git a/src/net/sourceforge/plantuml/classdiagram/command/CommandCreateClass.java b/src/net/sourceforge/plantuml/classdiagram/command/CommandCreateClass.java index 980d3166f..f49233dad 100644 --- a/src/net/sourceforge/plantuml/classdiagram/command/CommandCreateClass.java +++ b/src/net/sourceforge/plantuml/classdiagram/command/CommandCreateClass.java @@ -80,7 +80,7 @@ public class CommandCreateClass extends SingleLineCommand2 { private static IRegex getRegexConcat() { return RegexConcat.build(CommandCreateClass.class.getName(), RegexLeaf.start(), // new RegexLeaf("TYPE", // - "(interface|enum|annotation|abstract[%s]+class|abstract|class|entity|circle|diamond|protocol|struct)"), // + "(interface|enum|annotation|abstract[%s]+class|abstract|class|entity|circle|diamond|protocol|struct|exception)"), // RegexLeaf.spaceOneOrMore(), // new RegexOr(// new RegexConcat(// diff --git a/src/net/sourceforge/plantuml/classdiagram/command/CommandCreateClassMultilines.java b/src/net/sourceforge/plantuml/classdiagram/command/CommandCreateClassMultilines.java index f011d49d7..ee891ebce 100644 --- a/src/net/sourceforge/plantuml/classdiagram/command/CommandCreateClassMultilines.java +++ b/src/net/sourceforge/plantuml/classdiagram/command/CommandCreateClassMultilines.java @@ -92,7 +92,8 @@ public class CommandCreateClassMultilines extends CommandMultilines2 1) { entity.setCodeLine(lines.getAt(0).getLocation()); lines = lines.subExtract(1, 1); @@ -165,9 +166,9 @@ public class CommandCreateClassMultilines extends CommandMultilines2 0 && VisibilityModifier.isVisibilityCharacter(s.getString())) { + if (s.getString().length() > 0 && VisibilityModifier.isVisibilityCharacter(s.getString())) diagram.setVisibilityModifierPresent(true); - } + entity.getBodier().addFieldOrMethod(s.getString()); } // if (url != null) { @@ -183,9 +184,9 @@ public class CommandCreateClassMultilines extends CommandMultilines2 { gender = EntityGenderUtils.byEntityType(LeafType.PROTOCOL); } else if (arg1.equalsIgnoreCase("struct")) { gender = EntityGenderUtils.byEntityType(LeafType.STRUCT); + } else if (arg1.equalsIgnoreCase("exception")) { + gender = EntityGenderUtils.byEntityType(LeafType.EXCEPTION); } else if (arg1.startsWith("<<")) { gender = EntityGenderUtils.byStereotype(arg1); } else { @@ -171,6 +173,8 @@ public class CommandHideShowByGender extends SingleLineCommand2 { gender = EntityGenderUtils.byEntityType(LeafType.PROTOCOL); } else if (arg1.equalsIgnoreCase("struct")) { gender = EntityGenderUtils.byEntityType(LeafType.STRUCT); + } else if (arg1.equalsIgnoreCase("exception")) { + gender = EntityGenderUtils.byEntityType(LeafType.EXCEPTION); } else if (arg1.startsWith("<<")) { gender = EntityGenderUtils.byStereotype(arg1); } else { diff --git a/src/net/sourceforge/plantuml/classdiagram/command/CommandLinkLollipop.java b/src/net/sourceforge/plantuml/classdiagram/command/CommandLinkLollipop.java index d9b1bd146..d8755c7c1 100644 --- a/src/net/sourceforge/plantuml/classdiagram/command/CommandLinkLollipop.java +++ b/src/net/sourceforge/plantuml/classdiagram/command/CommandLinkLollipop.java @@ -95,7 +95,7 @@ final public class CommandLinkLollipop extends SingleLineCommand2 implements Command if (m1.matches() == false) return CommandControl.OK_PARTIAL; - actionIfCommandValid(); - return CommandControl.OK; + return finalVerification(); } protected boolean isCommandForbidden() { return false; } - protected void actionIfCommandValid() { + protected CommandControl finalVerification() { + return CommandControl.OK; } protected final Pattern2 getStartingPattern() { diff --git a/src/net/sourceforge/plantuml/command/CommandMultilines2.java b/src/net/sourceforge/plantuml/command/CommandMultilines2.java index 7bc1dc30f..0e56f5bb4 100644 --- a/src/net/sourceforge/plantuml/command/CommandMultilines2.java +++ b/src/net/sourceforge/plantuml/command/CommandMultilines2.java @@ -96,8 +96,7 @@ public abstract class CommandMultilines2 implements Command implements Command implements Command implements Command implements Com return new String[] { "BRACKET: " + starting.pattern() }; } - protected void actionIfCommandValid() { + protected CommandControl finalVerification() { + return CommandControl.OK; } protected final Pattern2 getStartingPattern() { @@ -98,8 +99,7 @@ public abstract class CommandMultilinesBracket implements Com if (level != 0) return CommandControl.OK_PARTIAL; - actionIfCommandValid(); - return CommandControl.OK; + return finalVerification(); } protected abstract boolean isLineConsistent(String line, int level); diff --git a/src/net/sourceforge/plantuml/command/SingleLineCommand2.java b/src/net/sourceforge/plantuml/command/SingleLineCommand2.java index 95723c695..6d9cd4ffc 100644 --- a/src/net/sourceforge/plantuml/command/SingleLineCommand2.java +++ b/src/net/sourceforge/plantuml/command/SingleLineCommand2.java @@ -104,9 +104,9 @@ public abstract class SingleLineCommand2 implements Command implements Command { private final HorizontalAlignment naturalHorizontalAlignment; private final boolean isNull; private final CreoleMode defaultCreoleMode; + private final boolean showStereotype; - public final static Display NULL = new Display(null, null, true, CreoleMode.FULL); + public final static Display NULL = new Display(true, null, null, true, CreoleMode.FULL); + + public boolean showStereotype() { + return showStereotype; + } public Display withoutStereotypeIfNeeded(Style usedStyle) { if (this == NULL) return NULL; - final boolean showStereotype = usedStyle.value(PName.ShowStereotype).asBoolean(); - if (showStereotype) + final Value showStereotype = usedStyle.value(PName.ShowStereotype); + if (showStereotype instanceof ValueNull || showStereotype.asBoolean()) return this; - final List copy = new ArrayList<>(displayData); - final Display result = new Display(naturalHorizontalAlignment, isNull, defaultCreoleMode); - for (Iterator it = copy.iterator(); it.hasNext();) { - final CharSequence cs = it.next(); - if (cs instanceof Stereotype && usedStyle.getSignature().match(((Stereotype) cs))) - it.remove(); + return new Display(false, this, this.defaultCreoleMode); - } - result.displayData.addAll(copy); - return result; } public Stereotype getStereotypeIfAny() { @@ -121,7 +120,7 @@ public class Display implements Iterable { } public Display replaceBackslashT() { - final Display result = new Display(this, defaultCreoleMode); + final Display result = new Display(this.showStereotype, this, defaultCreoleMode); for (int i = 0; i < result.displayData.size(); i++) { final CharSequence s = displayData.get(i); if (s.toString().contains("\\t")) @@ -138,7 +137,7 @@ public class Display implements Iterable { newDisplay.add(cs); } - return new Display(newDisplay, naturalHorizontalAlignment, isNull, defaultCreoleMode); + return new Display(showStereotype, newDisplay, naturalHorizontalAlignment, isNull, defaultCreoleMode); } public boolean isWhite() { @@ -147,7 +146,7 @@ public class Display implements Iterable { } public static Display empty() { - return new Display((HorizontalAlignment) null, false, CreoleMode.FULL); + return new Display(true, (HorizontalAlignment) null, false, CreoleMode.FULL); } public static Display create(CharSequence... s) { @@ -165,7 +164,7 @@ public class Display implements Iterable { } public static Display create(Collection other) { - return new Display(other, null, false, CreoleMode.FULL); + return new Display(true, other, null, false, CreoleMode.FULL); } public static Display getWithNewlines(Code s) { @@ -221,24 +220,26 @@ public class Display implements Iterable { } } result.add(current.toString()); - return new Display(result, naturalHorizontalAlignment, false, CreoleMode.FULL); + return new Display(true, result, naturalHorizontalAlignment, false, CreoleMode.FULL); } - private Display(Display other, CreoleMode mode) { - this(other.naturalHorizontalAlignment, other.isNull, mode); + private Display(boolean showStereotype, Display other, CreoleMode mode) { + this(showStereotype, other.naturalHorizontalAlignment, other.isNull, mode); this.displayData.addAll(other.displayData); } - private Display(HorizontalAlignment naturalHorizontalAlignment, boolean isNull, CreoleMode defaultCreoleMode) { + private Display(boolean showStereotype, HorizontalAlignment naturalHorizontalAlignment, boolean isNull, + CreoleMode defaultCreoleMode) { + this.showStereotype = showStereotype; this.defaultCreoleMode = defaultCreoleMode; this.isNull = isNull; this.displayData = isNull ? null : new ArrayList(); this.naturalHorizontalAlignment = isNull ? null : naturalHorizontalAlignment; } - private Display(Collection other, HorizontalAlignment naturalHorizontalAlignment, - boolean isNull, CreoleMode defaultCreoleMode) { - this(naturalHorizontalAlignment, isNull, defaultCreoleMode); + private Display(boolean showStereotype, Collection other, + HorizontalAlignment naturalHorizontalAlignment, boolean isNull, CreoleMode defaultCreoleMode) { + this(showStereotype, naturalHorizontalAlignment, isNull, defaultCreoleMode); if (isNull == false) this.displayData.addAll(manageEmbeddedDiagrams(other)); @@ -284,7 +285,8 @@ public class Display implements Iterable { } first = false; } - return new Display(result, this.naturalHorizontalAlignment, this.isNull, this.defaultCreoleMode); + return new Display(showStereotype, result, this.naturalHorizontalAlignment, this.isNull, + this.defaultCreoleMode); } public Display withPage(int page, int lastpage) { @@ -297,7 +299,8 @@ public class Display implements Iterable { line = line.toString().replace("%lastpage%", "" + lastpage); result.add(line); } - return new Display(result, this.naturalHorizontalAlignment, this.isNull, this.defaultCreoleMode); + return new Display(showStereotype, result, this.naturalHorizontalAlignment, this.isNull, + this.defaultCreoleMode); } public Display removeEndingStereotype() { @@ -305,7 +308,8 @@ public class Display implements Iterable { if (m.matches()) { final List result = new ArrayList<>(this.displayData); result.set(result.size() - 1, m.group(1)); - return new Display(result, this.naturalHorizontalAlignment, this.isNull, this.defaultCreoleMode); + return new Display(showStereotype, result, this.naturalHorizontalAlignment, this.isNull, + this.defaultCreoleMode); } return this; } @@ -325,7 +329,8 @@ public class Display implements Iterable { for (CharSequence line : displayData) result.add("" + line); - return new Display(result, this.naturalHorizontalAlignment, this.isNull, this.defaultCreoleMode); + return new Display(showStereotype, result, this.naturalHorizontalAlignment, this.isNull, + this.defaultCreoleMode); } public Display underlinedName() { @@ -342,14 +347,15 @@ public class Display implements Iterable { result.add("" + line); } } - return new Display(result, this.naturalHorizontalAlignment, this.isNull, this.defaultCreoleMode); + return new Display(showStereotype, result, this.naturalHorizontalAlignment, this.isNull, + this.defaultCreoleMode); } public Display withCreoleMode(CreoleMode mode) { if (isNull) throw new IllegalArgumentException(); - return new Display(this, mode); + return new Display(this.showStereotype, this, mode); } @Override @@ -371,25 +377,25 @@ public class Display implements Iterable { } public Display addAll(Display other) { - final Display result = new Display(this, this.defaultCreoleMode); + final Display result = new Display(this.showStereotype, this, this.defaultCreoleMode); result.displayData.addAll(other.displayData); return result; } public Display addFirst(CharSequence s) { - final Display result = new Display(this, this.defaultCreoleMode); + final Display result = new Display(this.showStereotype, this, this.defaultCreoleMode); result.displayData.add(0, s); return result; } public Display add(CharSequence s) { - final Display result = new Display(this, this.defaultCreoleMode); + final Display result = new Display(this.showStereotype, this, this.defaultCreoleMode); result.displayData.add(s); return result; } public Display addGeneric(CharSequence s) { - final Display result = new Display(this, this.defaultCreoleMode); + final Display result = new Display(this.showStereotype, this, this.defaultCreoleMode); final int size = displayData.size(); if (size == 0) result.displayData.add("<" + s + ">"); @@ -415,7 +421,7 @@ public class Display implements Iterable { } public Display subList(int i, int size) { - return new Display(displayData.subList(i, size), this.naturalHorizontalAlignment, this.isNull, + return new Display(showStereotype, displayData.subList(i, size), this.naturalHorizontalAlignment, this.isNull, this.defaultCreoleMode); } @@ -448,7 +454,8 @@ public class Display implements Iterable { public List splitMultiline(Pattern2 separator) { final List result = new ArrayList<>(); - Display pending = new Display(this.naturalHorizontalAlignment, this.isNull, this.defaultCreoleMode); + Display pending = new Display(showStereotype, this.naturalHorizontalAlignment, this.isNull, + this.defaultCreoleMode); result.add(pending); for (CharSequence line : displayData) { final Matcher2 m = separator.matcher(line); @@ -456,7 +463,8 @@ public class Display implements Iterable { final CharSequence s1 = line.subSequence(0, m.start()); pending.displayData.add(s1); final CharSequence s2 = line.subSequence(m.end(), line.length()); - pending = new Display(this.naturalHorizontalAlignment, this.isNull, this.defaultCreoleMode); + pending = new Display(showStereotype, this.naturalHorizontalAlignment, this.isNull, + this.defaultCreoleMode); result.add(pending); pending.displayData.add(s2); } else { diff --git a/src/net/sourceforge/plantuml/cucadiagram/DisplaySection.java b/src/net/sourceforge/plantuml/cucadiagram/DisplaySection.java index 923dc7893..553506428 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/DisplaySection.java +++ b/src/net/sourceforge/plantuml/cucadiagram/DisplaySection.java @@ -95,7 +95,7 @@ public class DisplaySection { return null; if (style != null) - return style.createTextBlockBordered(display, spriteContainer.getIHtmlColorSet(), spriteContainer); + return style.createTextBlockBordered(display, spriteContainer.getIHtmlColorSet(), spriteContainer, null); return display.create(fontConfiguration, getHorizontalAlignment(), spriteContainer); } diff --git a/src/net/sourceforge/plantuml/cucadiagram/Elected.java b/src/net/sourceforge/plantuml/cucadiagram/Elected.java index 0a99093eb..f1b445159 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/Elected.java +++ b/src/net/sourceforge/plantuml/cucadiagram/Elected.java @@ -40,6 +40,11 @@ class Elected { private final String shortName; private final int score; + @Override + public String toString() { + return shortName + "/" + score; + } + public Elected(String shortName, int score) { this.shortName = shortName; this.score = score; diff --git a/src/net/sourceforge/plantuml/cucadiagram/EntityPort.java b/src/net/sourceforge/plantuml/cucadiagram/EntityPort.java index 741b08eb2..45ba7a03f 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/EntityPort.java +++ b/src/net/sourceforge/plantuml/cucadiagram/EntityPort.java @@ -48,9 +48,9 @@ public class EntityPort { } public String getFullString() { - if (portId != null) { + if (portId != null) return entityUid + ":" + portId; - } + return entityUid; } @@ -59,9 +59,9 @@ public class EntityPort { } public String getPrefix() { - if (isShielded()) { + if (isShielded()) return entityUid.substring(0, entityUid.length() - 2); - } + return entityUid; } diff --git a/src/net/sourceforge/plantuml/cucadiagram/LeafType.java b/src/net/sourceforge/plantuml/cucadiagram/LeafType.java index c05782bf7..504cac6c6 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/LeafType.java +++ b/src/net/sourceforge/plantuml/cucadiagram/LeafType.java @@ -44,6 +44,7 @@ public enum LeafType { ABSTRACT_CLASS, CLASS, INTERFACE, ANNOTATION, PROTOCOL, STRUCT, + EXCEPTION, LOLLIPOP_FULL, LOLLIPOP_HALF, NOTE, TIPS, OBJECT, MAP, JSON, ASSOCIATION, ENUM, CIRCLE, @@ -78,8 +79,8 @@ public enum LeafType { public boolean isLikeClass() { return this == LeafType.ANNOTATION || this == LeafType.ABSTRACT_CLASS || this == LeafType.CLASS - || this == LeafType.INTERFACE || this == LeafType.ENUM || this == LeafType.ENTITY - || this == LeafType.PROTOCOL || this == LeafType.STRUCT; + || this == LeafType.INTERFACE || this == LeafType.ENUM || this == LeafType.ENTITY + || this == LeafType.PROTOCOL || this == LeafType.STRUCT || this == LeafType.EXCEPTION; } public String toHtml() { diff --git a/src/net/sourceforge/plantuml/cucadiagram/MethodsOrFieldsArea.java b/src/net/sourceforge/plantuml/cucadiagram/MethodsOrFieldsArea.java index cc1edc1d8..8ef6c1f60 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/MethodsOrFieldsArea.java +++ b/src/net/sourceforge/plantuml/cucadiagram/MethodsOrFieldsArea.java @@ -36,8 +36,11 @@ package net.sourceforge.plantuml.cucadiagram; import java.awt.geom.Rectangle2D; +import java.util.ArrayList; import java.util.Collection; -import java.util.HashSet; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; import net.sourceforge.plantuml.Dimension2DDouble; import net.sourceforge.plantuml.EmbeddedDiagram; @@ -130,21 +133,37 @@ public class MethodsOrFieldsArea extends AbstractTextBlock implements TextBlock, return new Dimension2DDouble(x, y); } + private Collection sortBySize(Collection all) { + final List result = new ArrayList(all); + Collections.sort(result, new Comparator() { + @Override + public int compare(String s1, String s2) { + final int diff = s2.length() - s1.length(); + if (diff != 0) + return diff; + return s1.compareTo(s2); + } + }); + return result; + } + @Override public Ports getPorts(StringBounder stringBounder) { - final Ports result = new Ports(); + final Ports ports = new Ports(); double y = 0; + final Collection shortNames = sortBySize(leaf.getPortShortNames()); + for (CharSequence cs : members) { final TextBlock bloc = createTextBlock(cs); final Dimension2D dim = bloc.calculateDimension(stringBounder); - final Elected port = getElected(leaf.getPortShortNames(), convert(cs)); - if (port != null) - result.add(port.getShortName(), port.getScore(), y, dim.getHeight()); + final Elected elected = getElected(convert(cs), shortNames); + if (elected != null) + ports.add(elected.getShortName(), elected.getScore(), y, dim.getHeight()); y += dim.getHeight(); } - return result; + return ports; } private String convert(CharSequence cs) { @@ -153,16 +172,16 @@ public class MethodsOrFieldsArea extends AbstractTextBlock implements TextBlock, return cs.toString(); } - public Elected getElected(Collection shortNames, String cs) { - for (String shortName : new HashSet<>(shortNames)) { - final int score = getScore(shortName, cs); + public Elected getElected(String cs, Collection shortNames) { + for (String shortName : shortNames) { + final int score = getScore(cs, shortName); if (score > 0) return new Elected(shortName, score); } return null; } - private int getScore(String shortName, String cs) { + private int getScore(String cs, String shortName) { if (cs.matches(".*\\b" + shortName + "\\b.*")) return 100; diff --git a/src/net/sourceforge/plantuml/cucadiagram/dot/GraphvizUtils.java b/src/net/sourceforge/plantuml/cucadiagram/dot/GraphvizUtils.java index d5bc7d0e1..c320205fa 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/dot/GraphvizUtils.java +++ b/src/net/sourceforge/plantuml/cucadiagram/dot/GraphvizUtils.java @@ -195,7 +195,7 @@ public class GraphvizUtils { if (s == null) return -1; - final Pattern p = Pattern.compile("\\s([23])\\.(\\d\\d?)\\D"); + final Pattern p = Pattern.compile("\\s([23456])\\.(\\d\\d?)\\D"); final Matcher m = p.matcher(s); if (m.find() == false) return -1; diff --git a/src/net/sourceforge/plantuml/cucadiagram/dot/GraphvizVersionFinder.java b/src/net/sourceforge/plantuml/cucadiagram/dot/GraphvizVersionFinder.java index d7884ce8a..2fb92e2bb 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/dot/GraphvizVersionFinder.java +++ b/src/net/sourceforge/plantuml/cucadiagram/dot/GraphvizVersionFinder.java @@ -72,7 +72,7 @@ public class GraphvizVersionFinder { public GraphvizVersion getVersion() { final String dotVersion = dotVersion(); - final Pattern p = Pattern.compile("([23])\\.(\\d\\d?)"); + final Pattern p = Pattern.compile("([23456])\\.(\\d\\d?)"); final Matcher m = p.matcher(dotVersion); final boolean find = m.find(); if (find == false) { diff --git a/src/net/sourceforge/plantuml/cucadiagram/entity/EntityImpl.java b/src/net/sourceforge/plantuml/cucadiagram/entity/EntityImpl.java index f0e966a38..cc2868423 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/entity/EntityImpl.java +++ b/src/net/sourceforge/plantuml/cucadiagram/entity/EntityImpl.java @@ -146,9 +146,9 @@ final public class EntityImpl implements ILeaf, IGroup { private EntityImpl(Ident ident, EntityFactory entityFactory, Code code, Bodier bodier, IGroup parentContainer, String namespaceSeparator, int rawLayout) { this.ident = Objects.requireNonNull(ident); - if (entityFactory.namespaceSeparator.V1972()) { + if (entityFactory.namespaceSeparator.V1972()) code = ident; - } + this.code = Objects.requireNonNull(code); this.entityFactory = entityFactory; this.bodier = bodier; @@ -188,9 +188,9 @@ final public class EntityImpl implements ILeaf, IGroup { checkNotGroup(); Objects.requireNonNull(newType); if (leafType != LeafType.STILL_UNKNOWN) { - if (newType == this.leafType) { + if (newType == this.leafType) return true; - } + if (leafType != LeafType.ANNOTATION && leafType != LeafType.ABSTRACT_CLASS && leafType != LeafType.CLASS && leafType != LeafType.ENUM && leafType != LeafType.INTERFACE) { return false; @@ -202,9 +202,9 @@ final public class EntityImpl implements ILeaf, IGroup { // throw new IllegalArgumentException("newtype=" + newType); } } - if (leafType == LeafType.CLASS && newType == LeafType.OBJECT) { + if (leafType == LeafType.CLASS && newType == LeafType.OBJECT) bodier.muteClassToObject(); - } + this.leafType = newType; this.symbol = newSymbol; return true; @@ -223,9 +223,9 @@ final public class EntityImpl implements ILeaf, IGroup { } public Display getDisplay() { - if (intricated) { + if (intricated) return entityFactory.getIntricatedDisplay(ident); - } + return display; } @@ -266,12 +266,12 @@ final public class EntityImpl implements ILeaf, IGroup { } public boolean hasUrl() { - if (Display.isNull(display) == false && display.hasUrl()) { + if (Display.isNull(display) == false && display.hasUrl()) return true; - } - if (bodier.hasUrl()) { + + if (bodier.hasUrl()) return true; - } + return url != null; } @@ -325,25 +325,25 @@ final public class EntityImpl implements ILeaf, IGroup { public EntityPosition getEntityPosition() { checkNotGroup(); - if (leafType == LeafType.PORT) { + if (leafType == LeafType.PORT) return EntityPosition.PORT; - } - if (leafType == LeafType.PORTIN) { + + if (leafType == LeafType.PORTIN) return EntityPosition.PORTIN; - } - if (leafType == LeafType.PORTOUT) { + + if (leafType == LeafType.PORTOUT) return EntityPosition.PORTOUT; - } - if (leafType != LeafType.STATE) { + + if (leafType != LeafType.STATE) return EntityPosition.NORMAL; - } - if (getParentContainer() instanceof GroupRoot) { + + if (getParentContainer() instanceof GroupRoot) return EntityPosition.NORMAL; - } + final Stereotype stereotype = getStereotype(); - if (stereotype == null) { + if (stereotype == null) return EntityPosition.NORMAL; - } + return EntityPosition.fromStereotype(stereotype.getLabel(Guillemet.DOUBLE_COMPARATOR)); } @@ -351,30 +351,29 @@ final public class EntityImpl implements ILeaf, IGroup { // ---------- private void checkGroup() { - if (isGroup() == false) { + if (isGroup() == false) throw new UnsupportedOperationException(); - } + } private void checkNotGroup() { - if (isGroup()) { + if (isGroup()) throw new UnsupportedOperationException(); - } + } public boolean containsLeafRecurse(ILeaf leaf) { - if (Objects.requireNonNull(leaf).isGroup()) { + if (Objects.requireNonNull(leaf).isGroup()) throw new IllegalArgumentException(); - } + checkGroup(); - if (leaf.getParentContainer() == this) { + if (leaf.getParentContainer() == this) return true; - } - for (IGroup child : getChildren()) { - if (child.containsLeafRecurse(leaf)) { + + for (IGroup child : getChildren()) + if (child.containsLeafRecurse(leaf)) return true; - } - } + return false; } @@ -382,12 +381,12 @@ final public class EntityImpl implements ILeaf, IGroup { checkGroup(); final List result = new ArrayList<>(); for (ILeaf ent : entityFactory.leafs()) { - if (ent.isGroup()) { + if (ent.isGroup()) throw new IllegalStateException(); - } - if (ent.getParentContainer() == this) { + + if (ent.getParentContainer() == this) result.add(ent); - } + } return Collections.unmodifiableCollection(result); } @@ -395,11 +394,10 @@ final public class EntityImpl implements ILeaf, IGroup { public Collection getChildren() { checkGroup(); final Collection result = new ArrayList<>(); - for (IGroup g : entityFactory.groups()) { - if (g != this && g.getParentContainer() == this) { + for (IGroup g : entityFactory.groups()) + if (g != this && g.getParentContainer() == this) result.add(g); - } - } + return Collections.unmodifiableCollection(result); } @@ -409,21 +407,20 @@ final public class EntityImpl implements ILeaf, IGroup { return; } checkGroup(); - if (dest.isGroup() == false) { + if (dest.isGroup() == false) throw new UnsupportedOperationException(); - } - for (ILeaf ent : getLeafsDirect()) { + + for (ILeaf ent : getLeafsDirect()) ((EntityImpl) ent).parentContainer = dest; - } - for (IGroup g : dest.getChildren()) { + + for (IGroup g : dest.getChildren()) // ((EntityImpl) g).parentContainer = dest; throw new IllegalStateException(); - } for (IGroup g : getChildren()) { - if (g == dest) { + if (g == dest) continue; - } + ((EntityImpl) g).parentContainer = dest; } @@ -510,23 +507,23 @@ final public class EntityImpl implements ILeaf, IGroup { public PackageStyle getPackageStyle() { checkGroup(); - if (stereotype == null) { + if (stereotype == null) return null; - } + return stereotype.getPackageStyle(); } public boolean isGroup() { - if (groupType != null && leafType != null) { + if (groupType != null && leafType != null) throw new IllegalStateException(); - } + assert groupType == null || leafType == null; - if (groupType != null) { + if (groupType != null) return true; - } - if (leafType != null) { + + if (leafType != null) return false; - } + throw new IllegalStateException(); } @@ -537,26 +534,21 @@ final public class EntityImpl implements ILeaf, IGroup { this.svekImage = img; this.url = null; - for (final Link link : new ArrayList<>(entityFactory.getLinks())) { - if (EntityUtils.isPureInnerLink12(this, link)) { + for (final Link link : new ArrayList<>(entityFactory.getLinks())) + if (EntityUtils.isPureInnerLink12(this, link)) entityFactory.removeLink(link); - } - } if (entityFactory.namespaceSeparator.V1972()) { entityFactory.removeGroup(getIdent()); - for (ILeaf ent : new ArrayList<>(entityFactory.leafs())) { - if (this != ent && getIdent().equals(ent.getIdent().parent())) { + for (ILeaf ent : new ArrayList<>(entityFactory.leafs())) + if (this != ent && getIdent().equals(ent.getIdent().parent())) entityFactory.removeLeaf(ent.getIdent()); - } - } + } else { entityFactory.removeGroup(getCodeGetName()); - for (ILeaf ent : new ArrayList<>(entityFactory.leafs())) { - if (this != ent && this == ent.getParentContainer()) { + for (ILeaf ent : new ArrayList<>(entityFactory.leafs())) + if (this != ent && this == ent.getParentContainer()) entityFactory.removeLeaf(ent.getCodeGetName()); - } - } } entityFactory.addLeaf(this); @@ -566,9 +558,9 @@ final public class EntityImpl implements ILeaf, IGroup { void muteToGroup(Code namespaceNew, GroupType groupType, IGroup parentContainer) { checkNotGroup(); - if (parentContainer.isGroup() == false) { + if (parentContainer.isGroup() == false) throw new IllegalArgumentException(); - } + this.namespace = namespaceNew; this.groupType = groupType; this.leafType = null; @@ -576,9 +568,9 @@ final public class EntityImpl implements ILeaf, IGroup { } public USymbol getUSymbol() { - if (getLeafType() == LeafType.CIRCLE) { + if (getLeafType() == LeafType.CIRCLE) return USymbols.INTERFACE; - } + // if (symbol != null && stereotype != null && stereotype.getSprite() != null) { // return symbol.withStereoAlignment(HorizontalAlignment.RIGHT); // } @@ -594,74 +586,69 @@ final public class EntityImpl implements ILeaf, IGroup { } public boolean isHidden() { - if (parentContainer != null && parentContainer.isHidden()) { + if (parentContainer != null && parentContainer.isHidden()) return true; - } + return isHiddenInternal(); } private boolean isHiddenInternal() { if (isGroup()) { - if (entityFactory.isHidden(this)) { + if (entityFactory.isHidden(this)) return true; - } - if (getLeafsDirect().size() == 0) { + + if (getLeafsDirect().size() == 0) return false; - } - for (ILeaf leaf : getLeafsDirect()) { - if (((EntityImpl) leaf).isHiddenInternal() == false) { + + for (ILeaf leaf : getLeafsDirect()) + if (((EntityImpl) leaf).isHiddenInternal() == false) return false; - } - } - for (IGroup g : getChildren()) { - if (((EntityImpl) g).isHiddenInternal() == false) { + + for (IGroup g : getChildren()) + if (((EntityImpl) g).isHiddenInternal() == false) return false; - } - } + return true; } return entityFactory.isHidden(this); } public boolean isRemoved() { - if (parentContainer != null && parentContainer.isRemoved()) { + if (parentContainer != null && parentContainer.isRemoved()) return true; - } + return isRemovedInternal(); } private boolean isRemovedInternal() { if (isGroup()) { - if (entityFactory.isRemoved(this)) { + if (entityFactory.isRemoved(this)) return true; - } - if (getLeafsDirect().size() == 0 && getChildren().size() == 0) { + + if (getLeafsDirect().size() == 0 && getChildren().size() == 0) return false; - } - for (ILeaf leaf : getLeafsDirect()) { - if (((EntityImpl) leaf).isRemovedInternal() == false) { + + for (ILeaf leaf : getLeafsDirect()) + if (((EntityImpl) leaf).isRemovedInternal() == false) return false; - } - } - for (IGroup g : getChildren()) { - if (((EntityImpl) g).isRemovedInternal() == false) { + + for (IGroup g : getChildren()) + if (((EntityImpl) g).isRemovedInternal() == false) return false; - } - } + return true; } return entityFactory.isRemoved(this); } public boolean isAloneAndUnlinked() { - if (isGroup()) { + if (isGroup()) return false; - } - for (Link link : entityFactory.getLinks()) { - if (link.contains(this) && link.getType().isInvisible() == false) { + + for (Link link : entityFactory.getLinks()) + if (link.contains(this) && link.getType().isInvisible() == false) return false; - } - } + return true; } @@ -721,9 +708,9 @@ final public class EntityImpl implements ILeaf, IGroup { } public void setSpecificColorTOBEREMOVED(ColorType type, HColor color) { - if (color != null) { + if (color != null) this.colors = colors.add(type, color); - } + } public Collection getPortShortNames() { @@ -780,9 +767,9 @@ final public class EntityImpl implements ILeaf, IGroup { } public String getCodeLine() { - if (this.codeLine == null) { + if (this.codeLine == null) return null; - } + return "" + this.codeLine.getPosition(); } diff --git a/src/net/sourceforge/plantuml/elk/CucaDiagramFileMakerElk.java b/src/net/sourceforge/plantuml/elk/CucaDiagramFileMakerElk.java index 6a2cf9f77..0b9f80c6d 100644 --- a/src/net/sourceforge/plantuml/elk/CucaDiagramFileMakerElk.java +++ b/src/net/sourceforge/plantuml/elk/CucaDiagramFileMakerElk.java @@ -110,6 +110,7 @@ import net.sourceforge.plantuml.graphic.QuoteUtils; import net.sourceforge.plantuml.graphic.StringBounder; import net.sourceforge.plantuml.graphic.TextBlock; import net.sourceforge.plantuml.graphic.TextBlockUtils; +import net.sourceforge.plantuml.graphic.USymbolFolder; import net.sourceforge.plantuml.style.PName; import net.sourceforge.plantuml.style.SName; import net.sourceforge.plantuml.style.Style; @@ -310,8 +311,16 @@ public class CucaDiagramFileMakerElk implements CucaDiagramFileMaker { // Unfortunately, we have to translate "edge" in its own "cluster" coordinate final Point2D translate = getPosition(edge.getContainingNode()); + final double magicY2 = 0; + final IEntity dest = link.getEntity2(); + if (dest.getUSymbol() instanceof USymbolFolder) { +// System.err.println("dest=" + dest); +// final IEntityImage image = printEntityInternal((ILeaf) dest); +// System.err.println("image=" + image); + + } final ElkPath elkPath = new ElkPath(diagram, SName.classDiagram, link, edge, getLabel(link), - getQualifier(link, 1), getQualifier(link, 2)); + getQualifier(link, 1), getQualifier(link, 2), magicY2); elkPath.drawU(ug.apply(new UTranslate(translate))); } diff --git a/src/net/sourceforge/plantuml/elk/ElkPath.java b/src/net/sourceforge/plantuml/elk/ElkPath.java index e40f5023f..e801cc46a 100644 --- a/src/net/sourceforge/plantuml/elk/ElkPath.java +++ b/src/net/sourceforge/plantuml/elk/ElkPath.java @@ -71,7 +71,6 @@ import net.sourceforge.plantuml.elk.proxy.graph.ElkLabel; import net.sourceforge.plantuml.graphic.TextBlock; import net.sourceforge.plantuml.graphic.UDrawable; import net.sourceforge.plantuml.graphic.color.ColorType; -import net.sourceforge.plantuml.skin.rose.Rose; import net.sourceforge.plantuml.style.PName; import net.sourceforge.plantuml.style.SName; import net.sourceforge.plantuml.style.Style; @@ -94,11 +93,13 @@ public class ElkPath implements UDrawable { private final TextBlock centerLabel; private final TextBlock headLabel; private final TextBlock tailLabel; - private final Rose rose = new Rose(); + private final SName styleName; + private final double magicY2; + public ElkPath(CucaDiagram diagram, SName styleName, Link link, ElkEdge edge, TextBlock centerLabel, - TextBlock tailLabel, TextBlock headLabel) { + TextBlock tailLabel, TextBlock headLabel, double magicY2) { this.link = link; this.edge = edge; @@ -107,6 +108,7 @@ public class ElkPath implements UDrawable { this.tailLabel = tailLabel; this.headLabel = headLabel; this.styleName = styleName; + this.magicY2 = magicY2; } @@ -170,13 +172,13 @@ public class ElkPath implements UDrawable { private UDrawable getDecors(LinkDecor decors, double angle, HColor backColor) { // For legacy reason, extends are treated differently - if (decors == LinkDecor.EXTENDS) { + if (decors == LinkDecor.EXTENDS) return new ExtremityFactoryExtends(backColor).createUDrawable(new Point2D.Double(), angle, null); - } + final ExtremityFactory extremityFactory = decors.getExtremityFactory(backColor); - if (extremityFactory == null) { + if (extremityFactory == null) return null; - } + return extremityFactory.createUDrawable(new Point2D.Double(), angle, null); } @@ -213,12 +215,11 @@ public class ElkPath implements UDrawable { y1 = pt.getY(); } - drawLine(ug, x1, y1, section.getEndX(), section.getEndY()); - + drawLine(ug, x1, y1, section.getEndX(), section.getEndY() + magicY2); } } - private void drawLine(UGraphic ug, final double x1, final double y1, final double x2, final double y2) { + private void drawLine(UGraphic ug, double x1, double y1, double x2, double y2) { final ULine line = new ULine(x2 - x1, y2 - y1); ug.apply(new UTranslate(x1, y1)).draw(line); } diff --git a/src/net/sourceforge/plantuml/graphic/Img.java b/src/net/sourceforge/plantuml/graphic/Img.java index ceda56359..840a19d2d 100644 --- a/src/net/sourceforge/plantuml/graphic/Img.java +++ b/src/net/sourceforge/plantuml/graphic/Img.java @@ -63,17 +63,17 @@ public class Img implements HtmlCommand { static int getVspace(String html) { final Matcher2 m = vspacePattern.matcher(html); - if (m.find() == false) { + if (m.find() == false) return 0; - } + return Integer.parseInt(m.group(1)); } static ImgValign getValign(String html) { final Matcher2 m = valignPattern.matcher(html); - if (m.find() == false) { + if (m.find() == false) return ImgValign.TOP; - } + return ImgValign.valueOf(StringUtils.goUpperCase(m.group(1))); } @@ -99,28 +99,28 @@ public class Img implements HtmlCommand { // Check if valid URL if (src.startsWith("http:") || src.startsWith("https:")) { final SURL tmp = SURL.create(src); - if (tmp == null) { + if (tmp == null) return new Text("(Cannot decode: " + src + ")"); - } + final BufferedImage read = tmp.readRasterImageFromURL(); - if (read == null) { + if (read == null) return new Text("(Cannot decode: " + src + ")"); - } + return new Img(new TileImage(read, valign, vspace)); } return new Text("(Cannot decode: " + f + ")"); } if (f.getName().endsWith(".svg")) { final String tmp = FileUtils.readSvg(f); - if (tmp == null) { + if (tmp == null) return new Text("(Cannot decode: " + f + ")"); - } - return new Img(new TileImageSvg(tmp)); + + return new Img(new TileImageSvg(tmp, 1)); } final BufferedImage read = f.readRasterImageFromFile(); - if (read == null) { + if (read == null) return new Text("(Cannot decode: " + f + ")"); - } + return new Img(new TileImage(f.readRasterImageFromFile(), valign, vspace)); } catch (IOException e) { e.printStackTrace(); diff --git a/src/net/sourceforge/plantuml/graphic/Rainbow.java b/src/net/sourceforge/plantuml/graphic/Rainbow.java index 76aabc9fe..5e2cfba83 100644 --- a/src/net/sourceforge/plantuml/graphic/Rainbow.java +++ b/src/net/sourceforge/plantuml/graphic/Rainbow.java @@ -42,17 +42,18 @@ import java.util.Objects; import net.sourceforge.plantuml.ISkinParam; import net.sourceforge.plantuml.api.ThemeStyle; -import net.sourceforge.plantuml.skin.rose.Rose; import net.sourceforge.plantuml.style.PName; import net.sourceforge.plantuml.style.Style; +import net.sourceforge.plantuml.style.Value; +import net.sourceforge.plantuml.style.ValueNull; +import net.sourceforge.plantuml.ugraphic.color.ColorUtils; import net.sourceforge.plantuml.ugraphic.color.HColor; import net.sourceforge.plantuml.ugraphic.color.HColorSet; +import net.sourceforge.plantuml.ugraphic.color.HColorUtils; import net.sourceforge.plantuml.ugraphic.color.NoSuchColorException; public class Rainbow { - private final static Rose rose = new Rose(); - private final List colors = new ArrayList<>(); private final int colorArrowSeparationSpace; @@ -83,7 +84,15 @@ public class Rainbow { public static Rainbow build(Style style, HColorSet set, ThemeStyle themeStyle) { final HColor color = style.value(PName.LineColor).asColor(themeStyle, set); - return fromColor(color, null); + final Value head = style.value(PName.HeadColor); + HColor colorHead; + if (head instanceof ValueNull) + colorHead = color; + else + colorHead = head.asColor(themeStyle, set); + if (colorHead == null) + colorHead = HColorUtils.transparent(); + return fromColor(color, colorHead); } public Rainbow withDefault(Rainbow defaultColor) { diff --git a/src/net/sourceforge/plantuml/graphic/TextBlockBordered.java b/src/net/sourceforge/plantuml/graphic/TextBlockBordered.java index 876ac9c97..124839390 100644 --- a/src/net/sourceforge/plantuml/graphic/TextBlockBordered.java +++ b/src/net/sourceforge/plantuml/graphic/TextBlockBordered.java @@ -58,25 +58,11 @@ public class TextBlockBordered extends AbstractTextBlock implements TextBlock { private final double left; private final UStroke stroke; private final boolean withShadow; - + private final String id; private final TextBlock textBlock; TextBlockBordered(TextBlock textBlock, UStroke stroke, HColor borderColor, HColor backgroundColor, - double cornersize, double marginX, double marginY) { - this.top = marginY; - this.right = marginX; - this.bottom = marginY; - this.left = marginX; - this.cornersize = cornersize; - this.textBlock = textBlock; - this.withShadow = false; - this.stroke = stroke; - this.borderColor = borderColor; - this.backgroundColor = backgroundColor; - } - - TextBlockBordered(TextBlock textBlock, UStroke stroke, HColor borderColor, HColor backgroundColor, - double cornersize, ClockwiseTopRightBottomLeft margins) { + double cornersize, ClockwiseTopRightBottomLeft margins, String id) { this.top = margins.getTop(); this.right = margins.getRight(); this.bottom = margins.getBottom(); @@ -87,11 +73,7 @@ public class TextBlockBordered extends AbstractTextBlock implements TextBlock { this.stroke = stroke; this.borderColor = borderColor; this.backgroundColor = backgroundColor; - } - - TextBlockBordered(TextBlock textBlock, UStroke stroke, HColor borderColor, HColor backgroundColor, - double cornersize) { - this(textBlock, stroke, borderColor, backgroundColor, cornersize, 6, 5); + this.id = id; } private double getTextHeight(StringBounder stringBounder) { @@ -115,16 +97,16 @@ public class TextBlockBordered extends AbstractTextBlock implements TextBlock { } private UGraphic applyStroke(UGraphic ug) { - if (stroke == null) { + if (stroke == null) return ug; - } + return ug.apply(stroke); } private boolean noBorder() { - if (stroke == null) { + if (stroke == null) return false; - } + return stroke.getThickness() == 0; } @@ -132,32 +114,32 @@ public class TextBlockBordered extends AbstractTextBlock implements TextBlock { final StringBounder stringBounder = ug.getStringBounder(); final Shadowable polygon = getPolygonNormal(stringBounder); final UGraphic ugOriginal = ug; - if (withShadow) { + if (withShadow) polygon.setDeltaShadow(4); - } - if (backgroundColor == null) { + + if (backgroundColor == null) ug = ug.apply(new HColorNone().bg()); - } else { + else ug = ug.apply(backgroundColor.bg()); - } + HColor color = noBorder() ? backgroundColor : borderColor; - if (color == null) { + if (color == null) color = new HColorNone(); - } + ug = ug.apply(color); ug = applyStroke(ug); ug.draw(polygon); TextBlock toDraw = textBlock; - if (textBlock instanceof SheetBlock2) { + if (textBlock instanceof SheetBlock2) toDraw = ((SheetBlock2) textBlock).enlargeMe(left, right); - } + toDraw.drawU(ugOriginal.apply(color).apply(new UTranslate(left, top))); } private Shadowable getPolygonNormal(final StringBounder stringBounder) { final double height = getTextHeight(stringBounder); final double width = getTextWidth(stringBounder); - return new URectangle(width, height).rounded(cornersize); + return new URectangle(width, height).rounded(cornersize).withCommentAndCodeLine(id, null); } } diff --git a/src/net/sourceforge/plantuml/graphic/TextBlockUtils.java b/src/net/sourceforge/plantuml/graphic/TextBlockUtils.java index 3e4562047..3deffa096 100644 --- a/src/net/sourceforge/plantuml/graphic/TextBlockUtils.java +++ b/src/net/sourceforge/plantuml/graphic/TextBlockUtils.java @@ -42,9 +42,7 @@ import java.awt.geom.Rectangle2D; import net.sourceforge.plantuml.Dimension2DDouble; import net.sourceforge.plantuml.FileFormat; -import net.sourceforge.plantuml.ISkinParam; import net.sourceforge.plantuml.awt.geom.Dimension2D; -import net.sourceforge.plantuml.cucadiagram.Display; import net.sourceforge.plantuml.posimo.Positionable; import net.sourceforge.plantuml.posimo.PositionableImpl; import net.sourceforge.plantuml.style.ClockwiseTopRightBottomLeft; @@ -63,22 +61,8 @@ public class TextBlockUtils { public static final TextBlock EMPTY_TEXT_BLOCK = TextBlockUtils.empty(0, 0); public static TextBlock bordered(TextBlock textBlock, UStroke stroke, HColor borderColor, HColor backgroundColor, - double cornersize) { - return new TextBlockBordered(textBlock, stroke, borderColor, backgroundColor, cornersize); - } - - public static TextBlock bordered(TextBlock textBlock, UStroke stroke, HColor borderColor, HColor backgroundColor, - double cornersize, double marginX, double marginY) { - return new TextBlockBordered(textBlock, stroke, borderColor, backgroundColor, cornersize, marginX, marginY); - } - - public static TextBlock bordered(TextBlock textBlock, UStroke stroke, HColor borderColor, HColor backgroundColor, - double cornersize, ClockwiseTopRightBottomLeft margins) { - return new TextBlockBordered(textBlock, stroke, borderColor, backgroundColor, cornersize, margins); - } - - public static TextBlock title(FontConfiguration font, Display stringsToDisplay, ISkinParam skinParam) { - throw new UnsupportedOperationException(); + double cornersize, ClockwiseTopRightBottomLeft margins, String id) { + return new TextBlockBordered(textBlock, stroke, borderColor, backgroundColor, cornersize, margins, id); } public static TextBlock withMargin(TextBlock textBlock, double marginX, double marginY) { diff --git a/src/net/sourceforge/plantuml/graphic/TileImageSvg.java b/src/net/sourceforge/plantuml/graphic/TileImageSvg.java index 82911a800..06be3a753 100644 --- a/src/net/sourceforge/plantuml/graphic/TileImageSvg.java +++ b/src/net/sourceforge/plantuml/graphic/TileImageSvg.java @@ -43,9 +43,11 @@ import net.sourceforge.plantuml.ugraphic.UImageSvg; public class TileImageSvg extends AbstractTextBlock implements TextBlock { private final UImageSvg svg; + private final double scale; - public TileImageSvg(String svg) { - this.svg = new UImageSvg(svg, 1); + public TileImageSvg(String svg, double scale) { + this.svg = new UImageSvg(svg, scale); + this.scale = scale; } public Dimension2D calculateDimension(StringBounder stringBounder) { diff --git a/src/net/sourceforge/plantuml/objectdiagram/command/CommandCreateJson.java b/src/net/sourceforge/plantuml/objectdiagram/command/CommandCreateJson.java index 39d5f4ea0..b3c816297 100644 --- a/src/net/sourceforge/plantuml/objectdiagram/command/CommandCreateJson.java +++ b/src/net/sourceforge/plantuml/objectdiagram/command/CommandCreateJson.java @@ -39,6 +39,7 @@ import net.sourceforge.plantuml.FontParam; import net.sourceforge.plantuml.StringLocated; import net.sourceforge.plantuml.UrlBuilder; import net.sourceforge.plantuml.command.BlocLines; +import net.sourceforge.plantuml.command.CommandControl; import net.sourceforge.plantuml.command.CommandExecutionResult; import net.sourceforge.plantuml.command.CommandMultilines2; import net.sourceforge.plantuml.command.MultilinesStrategy; @@ -97,22 +98,46 @@ public class CommandCreateJson extends CommandMultilines2 0; - System.err.println("l=" + line); sb.append(line); } sb.append("}"); - - final DefaultHandler handler = new DefaultHandler(); - new JsonParser(handler).parse(sb.toString()); - final JsonValue json = handler.getValue(); - ((BodierJSon) entity1.getBodier()).setJson(json); - - return CommandExecutionResult.ok(); + return sb.toString(); } private IEntity executeArg0(AbstractClassOrObjectDiagram diagram, RegexResult line0) throws NoSuchColorException { diff --git a/src/net/sourceforge/plantuml/objectdiagram/command/CommandCreateMap.java b/src/net/sourceforge/plantuml/objectdiagram/command/CommandCreateMap.java index df695947e..7d33778d8 100644 --- a/src/net/sourceforge/plantuml/objectdiagram/command/CommandCreateMap.java +++ b/src/net/sourceforge/plantuml/objectdiagram/command/CommandCreateMap.java @@ -45,6 +45,7 @@ import net.sourceforge.plantuml.command.MultilinesStrategy; 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.BodierMap; import net.sourceforge.plantuml.cucadiagram.Code; @@ -59,7 +60,9 @@ import net.sourceforge.plantuml.cucadiagram.LinkType; import net.sourceforge.plantuml.cucadiagram.Stereotype; import net.sourceforge.plantuml.graphic.color.ColorParser; import net.sourceforge.plantuml.graphic.color.ColorType; +import net.sourceforge.plantuml.graphic.color.Colors; import net.sourceforge.plantuml.objectdiagram.AbstractClassOrObjectDiagram; +import net.sourceforge.plantuml.ugraphic.color.HColor; import net.sourceforge.plantuml.ugraphic.color.NoSuchColorException; public class CommandCreateMap extends CommandMultilines2 { @@ -78,12 +81,19 @@ public class CommandCreateMap extends CommandMultilines2 LIMIT) { // Log.debug("Line truncated from " + s.length() + " to " + LIMIT); // s = s.substring(0, LIMIT); // } - if (s.startsWith("\uFEFF")) { + if (s.startsWith("\uFEFF")) s = s.substring(1); - } + s = s.replace('\u2013', '-'); // s = BackSlash.convertHiddenNewLine(s); // s = s.replace('\u00A0', ' '); diff --git a/src/net/sourceforge/plantuml/security/SURL.java b/src/net/sourceforge/plantuml/security/SURL.java index fb9a48777..c8533b84d 100644 --- a/src/net/sourceforge/plantuml/security/SURL.java +++ b/src/net/sourceforge/plantuml/security/SURL.java @@ -244,7 +244,7 @@ public class SURL { } private boolean forbiddenURL(String full) { - if (full.matches("^https?://[.0-9]+/.*")) + if (full.matches("^https?://[-#.0-9:\\[\\]+]+/.*")) return true; if (full.matches("^https?://[^.]+/.*")) return true; diff --git a/src/net/sourceforge/plantuml/sequencediagram/graphic/SequenceDiagramFileMakerPuma2.java b/src/net/sourceforge/plantuml/sequencediagram/graphic/SequenceDiagramFileMakerPuma2.java index 4068599af..a70690ce6 100644 --- a/src/net/sourceforge/plantuml/sequencediagram/graphic/SequenceDiagramFileMakerPuma2.java +++ b/src/net/sourceforge/plantuml/sequencediagram/graphic/SequenceDiagramFileMakerPuma2.java @@ -149,7 +149,7 @@ public class SequenceDiagramFileMakerPuma2 implements FileMaker { final Style style = StyleSignatureBasic.of(SName.root, SName.document, SName.title) .getMergedStyle(diagram.getSkinParam().getCurrentStyleBuilder()); compTitle = style.createTextBlockBordered(page.getTitle(), diagram.getSkinParam().getIHtmlColorSet(), - diagram.getSkinParam()); + diagram.getSkinParam(), Style.ID_TITLE); final Dimension2D dimTitle = compTitle.calculateDimension(stringBounder); area.setTitleArea(dimTitle.getWidth(), dimTitle.getHeight()); } @@ -163,7 +163,7 @@ public class SequenceDiagramFileMakerPuma2 implements FileMaker { final Style style = StyleSignatureBasic.of(SName.root, SName.document, SName.legend) .getMergedStyle(diagram.getSkinParam().getCurrentStyleBuilder()); legendBlock = style.createTextBlockBordered(diagram.getLegend().getDisplay(), - diagram.getSkinParam().getIHtmlColorSet(), diagram.getSkinParam()); + diagram.getSkinParam().getIHtmlColorSet(), diagram.getSkinParam(), Style.ID_LEGEND); } final Dimension2D dimLegend = legendBlock.calculateDimension(stringBounder); area.setLegend(dimLegend, isLegendTop(), diagram.getLegend().getHorizontalAlignment()); diff --git a/src/net/sourceforge/plantuml/sequencediagram/teoz/SequenceDiagramFileMakerTeoz.java b/src/net/sourceforge/plantuml/sequencediagram/teoz/SequenceDiagramFileMakerTeoz.java index d78dbe13f..18f84328c 100644 --- a/src/net/sourceforge/plantuml/sequencediagram/teoz/SequenceDiagramFileMakerTeoz.java +++ b/src/net/sourceforge/plantuml/sequencediagram/teoz/SequenceDiagramFileMakerTeoz.java @@ -209,7 +209,7 @@ public class SequenceDiagramFileMakerTeoz implements FileMaker { final Style style = StyleSignatureBasic.of(SName.root, SName.document, SName.title) .getMergedStyle(diagram.getSkinParam().getCurrentStyleBuilder()); final TextBlock compTitle = style.createTextBlockBordered(diagram.getTitle().getDisplay(), - diagram.getSkinParam().getIHtmlColorSet(), diagram.getSkinParam()); + diagram.getSkinParam().getIHtmlColorSet(), diagram.getSkinParam(), Style.ID_TITLE); return compTitle; } diff --git a/src/net/sourceforge/plantuml/skin/AbstractTextualComponent.java b/src/net/sourceforge/plantuml/skin/AbstractTextualComponent.java index 8a4effb9d..d4ec560d8 100644 --- a/src/net/sourceforge/plantuml/skin/AbstractTextualComponent.java +++ b/src/net/sourceforge/plantuml/skin/AbstractTextualComponent.java @@ -55,8 +55,6 @@ import net.sourceforge.plantuml.ugraphic.color.HColorSet; public abstract class AbstractTextualComponent extends AbstractComponent { - private final Display display; - private final int marginX1; private final int marginX2; private final int marginY; @@ -91,20 +89,18 @@ public abstract class AbstractTextualComponent extends AbstractComponent { final UFont fontForStereotype = stereo.getUFont(); final HColor htmlColorForStereotype = stereo.value(PName.FontColor).asColor(spriteContainer.getThemeStyle(), getIHtmlColorSet()); - this.display = display.withoutStereotypeIfNeeded(style); + display = display.withoutStereotypeIfNeeded(style); this.marginX1 = marginX1; this.marginX2 = marginX2; this.marginY = marginY; - // this.display = keepStereotype ? display : display.withoutStereotype(); - if (this.display.size() == 1 && this.display.get(0).length() == 0) + if (display.size() == 1 && display.get(0).length() == 0) textBlock = new TextBlockEmpty(); else if (enhanced) - textBlock = BodyFactory.create3(this.display, spriteContainer, horizontalAlignment, fc, maxMessageSize, - style); + textBlock = BodyFactory.create3(display, spriteContainer, horizontalAlignment, fc, maxMessageSize, style); else - textBlock = this.display.create0(fc, horizontalAlignment, spriteContainer, maxMessageSize, CreoleMode.FULL, + textBlock = display.create0(fc, horizontalAlignment, spriteContainer, maxMessageSize, CreoleMode.FULL, fontForStereotype, htmlColorForStereotype, marginX1, marginX2); this.alignment = horizontalAlignment; diff --git a/src/net/sourceforge/plantuml/skin/rose/ComponentRoseArrow.java b/src/net/sourceforge/plantuml/skin/rose/ComponentRoseArrow.java index 58dc71596..eec849af2 100644 --- a/src/net/sourceforge/plantuml/skin/rose/ComponentRoseArrow.java +++ b/src/net/sourceforge/plantuml/skin/rose/ComponentRoseArrow.java @@ -150,11 +150,10 @@ public class ComponentRoseArrow extends AbstractComponentRoseArrow { if (inclination1 == 0 && inclination2 == 0) getArrowConfiguration().applyStroke(ug).apply(new UTranslate(start, posArrow)).draw(new ULine(len, 0)); - else if (inclination1 != 0) { + else if (inclination1 != 0) drawLine(getArrowConfiguration().applyStroke(ug), start + len, posArrow, 0, posArrow + inclination1); - } else if (inclination2 != 0) { + else if (inclination2 != 0) drawLine(getArrowConfiguration().applyStroke(ug), start, posArrow, pos2, posArrow + inclination2); - } final ArrowDirection direction2 = getDirection2(); final double textPos; @@ -203,10 +202,12 @@ public class ComponentRoseArrow extends AbstractComponentRoseArrow { if (dressing.getHead() == ArrowHead.ASYNC) { if (dressing.getPart() != ArrowPart.BOTTOM_PART) - getArrowConfiguration().applyThicknessOnly(ug).draw(new ULine(getArrowDeltaX(), -getArrowDeltaY())); + getArrowConfiguration().applyThicknessOnly(ug).draw( + new ULine(getArrowDeltaX(), -getArrowDeltaY()).rotate(Math.atan2(-inclination1, lenFull))); if (dressing.getPart() != ArrowPart.TOP_PART) - getArrowConfiguration().applyThicknessOnly(ug).draw(new ULine(getArrowDeltaX(), getArrowDeltaY())); + getArrowConfiguration().applyThicknessOnly(ug) + .draw(new ULine(getArrowDeltaX(), getArrowDeltaY()).rotate(Math.atan2(-inclination1, lenFull))); } else if (dressing.getHead() == ArrowHead.CROSSX) { ug = ug.apply(new UStroke(2)); @@ -237,10 +238,12 @@ public class ComponentRoseArrow extends AbstractComponentRoseArrow { if (dressing.getHead() == ArrowHead.ASYNC) { if (dressing.getPart() != ArrowPart.BOTTOM_PART) - getArrowConfiguration().applyThicknessOnly(ug).draw(new ULine(-getArrowDeltaX(), -getArrowDeltaY())); + getArrowConfiguration().applyThicknessOnly(ug).draw( + new ULine(-getArrowDeltaX(), -getArrowDeltaY()).rotate(Math.atan2(inclination2, lenFull))); if (dressing.getPart() != ArrowPart.TOP_PART) - getArrowConfiguration().applyThicknessOnly(ug).draw(new ULine(-getArrowDeltaX(), getArrowDeltaY())); + getArrowConfiguration().applyThicknessOnly(ug) + .draw(new ULine(-getArrowDeltaX(), getArrowDeltaY()).rotate(Math.atan2(inclination2, lenFull))); } else if (dressing.getHead() == ArrowHead.CROSSX) { ug = ug.apply(new UStroke(2)); diff --git a/src/net/sourceforge/plantuml/style/FromSkinparamToStyle.java b/src/net/sourceforge/plantuml/style/FromSkinparamToStyle.java index 7d9a33c6c..fc1a28449 100644 --- a/src/net/sourceforge/plantuml/style/FromSkinparamToStyle.java +++ b/src/net/sourceforge/plantuml/style/FromSkinparamToStyle.java @@ -144,6 +144,7 @@ public class FromSkinparamToStyle { addConvert("arrowThickness", PName.LineThickness, SName.arrow); addConvert("arrowColor", PName.LineColor, SName.arrow); addConvert("arrowStyle", PName.LineStyle, SName.arrow); + addConvert("arrowHeadColor", PName.HeadColor, SName.arrow); addConvert("defaulttextalignment", PName.HorizontalAlignment, SName.root); addConvert("defaultFontName", PName.FontName, SName.root); @@ -210,15 +211,22 @@ public class FromSkinparamToStyle { addMagic(SName.usecase); addMagic(SName.map); addMagic(SName.archimate); - - + + addConvert("IconPrivateColor", PName.LineColor, SName.visibilityIcon, SName.private_); + addConvert("IconPrivateBackgroundColor", PName.BackGroundColor, SName.visibilityIcon, SName.private_); + addConvert("IconPackageColor", PName.LineColor, SName.visibilityIcon, SName.package_); + addConvert("IconPackageBackgroundColor", PName.BackGroundColor, SName.visibilityIcon, SName.package_); + addConvert("IconProtectedColor", PName.LineColor, SName.visibilityIcon, SName.protected_); + addConvert("IconProtectedBackgroundColor", PName.BackGroundColor, SName.visibilityIcon, SName.protected_); + addConvert("IconPublicColor", PName.LineColor, SName.visibilityIcon, SName.public_); + addConvert("IconPublicBackgroundColor", PName.BackGroundColor, SName.visibilityIcon, SName.public_); + // addConvert("nodeStereotypeFontSize", PName.FontSize, SName.node, SName.stereotype); // addConvert("sequenceStereotypeFontSize", PName.FontSize, SName.stereotype); // addConvert("sequenceStereotypeFontStyle", PName.FontStyle, SName.stereotype); // addConvert("sequenceStereotypeFontColor", PName.FontColor, SName.stereotype); // addConvert("sequenceStereotypeFontName", PName.FontName, SName.stereotype); - } private static void addMagic(SName sname) { @@ -231,7 +239,7 @@ public class FromSkinparamToStyle { addConvert(cleanName + "BorderStyle", PName.LineStyle, sname); addConFont(cleanName, sname); addConvert(cleanName + "Shadowing", PName.Shadowing, sname); - + addConvert(cleanName + "StereotypeFontSize", PName.FontSize, SName.stereotype, sname); addConvert(cleanName + "StereotypeFontStyle", PName.FontStyle, SName.stereotype, sname); addConvert(cleanName + "StereotypeFontColor", PName.FontColor, SName.stereotype, sname); diff --git a/src/net/sourceforge/plantuml/style/PName.java b/src/net/sourceforge/plantuml/style/PName.java index 5f6fb524c..04b918e1f 100644 --- a/src/net/sourceforge/plantuml/style/PName.java +++ b/src/net/sourceforge/plantuml/style/PName.java @@ -46,6 +46,7 @@ public enum PName { LineThickness, // DiagonalCorner, // HyperLinkColor, // + HeadColor, // LineColor, // LineStyle, // Padding, // diff --git a/src/net/sourceforge/plantuml/style/SName.java b/src/net/sourceforge/plantuml/style/SName.java index 7ac06353d..377ee084d 100644 --- a/src/net/sourceforge/plantuml/style/SName.java +++ b/src/net/sourceforge/plantuml/style/SName.java @@ -41,6 +41,7 @@ public enum SName { activityDiagram, // actor, // agent, // + analog, // archimate, // arrow, // artifact, // @@ -142,6 +143,7 @@ public enum SName { spotProtocol, // spotStruct, // spotEntity, // + spotException, // spotClass, // spotAbstractClass, // diff --git a/src/net/sourceforge/plantuml/style/Style.java b/src/net/sourceforge/plantuml/style/Style.java index c6badc0b3..9fc2b5763 100644 --- a/src/net/sourceforge/plantuml/style/Style.java +++ b/src/net/sourceforge/plantuml/style/Style.java @@ -269,8 +269,12 @@ public class Style { final FontConfiguration fc = getFontConfiguration(spriteContainer.getThemeStyle(), set); return display.create(fc, alignment, spriteContainer); } + + public static final String ID_TITLE = "_title"; + public static final String ID_CAPTION = "_caption"; + public static final String ID_LEGEND = "_legend"; - public TextBlock createTextBlockBordered(Display note, HColorSet set, ISkinSimple spriteContainer) { + public TextBlock createTextBlockBordered(Display note, HColorSet set, ISkinSimple spriteContainer, String id) { final HorizontalAlignment alignment = this.getHorizontalAlignment(); final TextBlock textBlock = this.createTextBlockInternal(note, set, spriteContainer, alignment); @@ -281,7 +285,7 @@ public class Style { final ClockwiseTopRightBottomLeft margin = this.getMargin(); final ClockwiseTopRightBottomLeft padding = this.getPadding(); final TextBlock result = TextBlockUtils.bordered(textBlock, stroke, lineColor, backgroundColor, cornersize, - padding); + padding, id); return TextBlockUtils.withMargin(result, margin); } diff --git a/src/net/sourceforge/plantuml/svek/ClusterDecoration.java b/src/net/sourceforge/plantuml/svek/ClusterDecoration.java index 4fce7f333..ba421b441 100644 --- a/src/net/sourceforge/plantuml/svek/ClusterDecoration.java +++ b/src/net/sourceforge/plantuml/svek/ClusterDecoration.java @@ -70,9 +70,9 @@ public class ClusterDecoration { } private static USymbol guess(USymbol symbol, PackageStyle style) { - if (symbol != null) { + if (symbol != null) return symbol; - } + return style.toUSymbol(); } diff --git a/src/net/sourceforge/plantuml/svek/image/EntityImageClass.java b/src/net/sourceforge/plantuml/svek/image/EntityImageClass.java index 1659a933c..5faae7513 100644 --- a/src/net/sourceforge/plantuml/svek/image/EntityImageClass.java +++ b/src/net/sourceforge/plantuml/svek/image/EntityImageClass.java @@ -169,14 +169,14 @@ public class EntityImageClass extends AbstractEntityImage implements Stencil, Wi double shadow = 0; - HColor classBorder = lineConfig.getColors().getColor(ColorType.LINE); + HColor borderColor = lineConfig.getColors().getColor(ColorType.LINE); HColor headerBackcolor = getEntity().getColors().getColor(ColorType.HEADER); HColor backcolor = getEntity().getColors().getColor(ColorType.BACK); shadow = getStyle().value(PName.Shadowing).asDouble(); - if (classBorder == null) - classBorder = getStyle().value(PName.LineColor).asColor(getSkinParam().getThemeStyle(), + if (borderColor == null) + borderColor = getStyle().value(PName.LineColor).asColor(getSkinParam().getThemeStyle(), getSkinParam().getIHtmlColorSet()); if (headerBackcolor == null) @@ -189,7 +189,7 @@ public class EntityImageClass extends AbstractEntityImage implements Stencil, Wi rect.setDeltaShadow(shadow); - ug = ug.apply(classBorder); + ug = ug.apply(borderColor); ug = ug.apply(backcolor.bg()); final UStroke stroke = getStyle().getStroke(lineConfig.getColors()); diff --git a/src/net/sourceforge/plantuml/svek/image/EntityImageClassHeader.java b/src/net/sourceforge/plantuml/svek/image/EntityImageClassHeader.java index 70d7872aa..3ebf55ff0 100644 --- a/src/net/sourceforge/plantuml/svek/image/EntityImageClassHeader.java +++ b/src/net/sourceforge/plantuml/svek/image/EntityImageClassHeader.java @@ -198,6 +198,8 @@ public class EntityImageClassHeader extends AbstractEntityImage { return StyleSignatureBasic.of(SName.root, SName.element, SName.spot, SName.spotProtocol); case STRUCT: return StyleSignatureBasic.of(SName.root, SName.element, SName.spot, SName.spotStruct); + case EXCEPTION: + return StyleSignatureBasic.of(SName.root, SName.element, SName.spot, SName.spotException); } throw new IllegalStateException(); } @@ -220,6 +222,8 @@ public class EntityImageClassHeader extends AbstractEntityImage { return 'P'; case STRUCT: return 'S'; + case EXCEPTION: + return 'X'; } assert false; return '?'; diff --git a/src/net/sourceforge/plantuml/svek/image/EntityImageMap.java b/src/net/sourceforge/plantuml/svek/image/EntityImageMap.java index af27409c3..05391cfcd 100644 --- a/src/net/sourceforge/plantuml/svek/image/EntityImageMap.java +++ b/src/net/sourceforge/plantuml/svek/image/EntityImageMap.java @@ -156,13 +156,16 @@ public class EntityImageMap extends AbstractEntityImage implements Stencil, With final double heightTotal = dimTotal.getHeight(); final Shadowable rect = new URectangle(widthTotal, heightTotal).rounded(roundCorner); + HColor borderColor = lineConfig.getColors().getColor(ColorType.LINE); HColor backcolor = getEntity().getColors().getColor(ColorType.BACK); HColor headerBackcolor = getEntity().getColors().getColor(ColorType.HEADER); final Style style = getStyle(); - final HColor borderColor = style.value(PName.LineColor).asColor(getSkinParam().getThemeStyle(), - getSkinParam().getIHtmlColorSet()); - + + if (borderColor == null) + borderColor = getStyle().value(PName.LineColor).asColor(getSkinParam().getThemeStyle(), + getSkinParam().getIHtmlColorSet()); + if (headerBackcolor == null) headerBackcolor = backcolor == null ? getStyleHeader().value(PName.BackGroundColor) .asColor(getSkinParam().getThemeStyle(), getSkinParam().getIHtmlColorSet()) : backcolor; @@ -170,7 +173,7 @@ public class EntityImageMap extends AbstractEntityImage implements Stencil, With if (backcolor == null) backcolor = style.value(PName.BackGroundColor).asColor(getSkinParam().getThemeStyle(), getSkinParam().getIHtmlColorSet()); - + rect.setDeltaShadow(style.value(PName.Shadowing).asDouble()); final UStroke stroke = style.getStroke(); @@ -184,7 +187,7 @@ public class EntityImageMap extends AbstractEntityImage implements Stencil, With typeIDent.put(UGroupType.ID, "elem_" + getEntity().getCode()); ug.startGroup(typeIDent); ug.apply(stroke).draw(rect); - + if (roundCorner == 0 && headerBackcolor != null && backcolor.equals(headerBackcolor) == false) { final Shadowable rect2 = new URectangle(widthTotal, dimTitle.getHeight()); final UGraphic ugHeader = ug.apply(headerBackcolor.bg()); diff --git a/src/net/sourceforge/plantuml/svek/image/Footprint.java b/src/net/sourceforge/plantuml/svek/image/Footprint.java index 0e8b2afa4..bb99e9ed9 100644 --- a/src/net/sourceforge/plantuml/svek/image/Footprint.java +++ b/src/net/sourceforge/plantuml/svek/image/Footprint.java @@ -46,6 +46,7 @@ import net.sourceforge.plantuml.graphic.StringBounder; import net.sourceforge.plantuml.graphic.UDrawable; import net.sourceforge.plantuml.ugraphic.UBackground; import net.sourceforge.plantuml.ugraphic.UChange; +import net.sourceforge.plantuml.ugraphic.UEllipse; import net.sourceforge.plantuml.ugraphic.UEmpty; import net.sourceforge.plantuml.ugraphic.UGraphic; import net.sourceforge.plantuml.ugraphic.UGraphicNo; @@ -111,6 +112,8 @@ public class Footprint { drawPath(x, y, (UPath) shape); } else if (shape instanceof URectangle) { drawRectangle(x, y, (URectangle) shape); + } else if (shape instanceof UEllipse) { + drawEllipse(x, y, (UEllipse) shape); } else if (shape instanceof UEmpty) { drawEmpty(x, y, (UEmpty) shape); } else { @@ -153,6 +156,11 @@ public class Footprint { addPoint(x + rect.getWidth(), y + rect.getHeight()); } + private void drawEllipse(double x, double y, UEllipse rect) { + addPoint(x, y); + addPoint(x + rect.getWidth(), y + rect.getHeight()); + } + private void drawEmpty(double x, double y, UEmpty rect) { addPoint(x, y); addPoint(x + rect.getWidth(), y + rect.getHeight()); diff --git a/src/net/sourceforge/plantuml/svg/SvgGraphics.java b/src/net/sourceforge/plantuml/svg/SvgGraphics.java index 7c01ae1bc..213a624e7 100644 --- a/src/net/sourceforge/plantuml/svg/SvgGraphics.java +++ b/src/net/sourceforge/plantuml/svg/SvgGraphics.java @@ -71,6 +71,7 @@ import net.sourceforge.plantuml.SignatureUtils; import net.sourceforge.plantuml.awt.geom.Dimension2D; import net.sourceforge.plantuml.code.Base64Coder; import net.sourceforge.plantuml.security.SImageIO; +import net.sourceforge.plantuml.security.SecurityProfile; import net.sourceforge.plantuml.security.SecurityUtils; import net.sourceforge.plantuml.tikz.TikzGraphics; import net.sourceforge.plantuml.ugraphic.UGroupType; @@ -641,8 +642,19 @@ public class SvgGraphics { } public void createXml(OutputStream os) throws TransformerException, IOException { - createXmlInternal(os); -// s = removeXmlHeader(s); + if (images.size() == 0) { + createXmlInternal(os); + return; + } + final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + createXmlInternal(baos); + String s = new String(baos.toByteArray()); + for (Map.Entry ent : images.entrySet()) { + final String k = "<" + ent.getKey() + "/>"; + s = s.replace(k, ent.getValue()); + } + s = removeXmlHeader(s); + os.write(s.getBytes()); } private String removeXmlHeader(String s) { @@ -882,7 +894,30 @@ public class SvgGraphics { ensureVisible(x + image.getWidth(), y + image.getHeight()); } + private final Map images = new HashMap(); + + + private void svgImageUnsecure(UImageSvg image, double x, double y) { + if (hidden == false) { + String svg = manageScale(image); + final String pos = ""; + svg = pos + svg.substring(5); + final String key = "imagesvginlined" + image.getMD5Hex() + images.size(); + final Element elt = (Element) document.createElement(key); + getG().appendChild(elt); + images.put(key, svg); + } + ensureVisible(x, y); + ensureVisible(x + image.getData("width"), y + image.getData("height")); + } + + public void svgImage(UImageSvg image, double x, double y) { + if (SecurityUtils.getSecurityProfile() == SecurityProfile.UNSECURE) { + svgImageUnsecure(image, x, y); + return; + } + // https://developer.mozilla.org/fr/docs/Web/SVG/Element/image if (hidden == false) { final Element elt = (Element) document.createElement("image"); diff --git a/src/net/sourceforge/plantuml/tim/EaterTheme.java b/src/net/sourceforge/plantuml/tim/EaterTheme.java index d78b1fe63..782a93ce6 100644 --- a/src/net/sourceforge/plantuml/tim/EaterTheme.java +++ b/src/net/sourceforge/plantuml/tim/EaterTheme.java @@ -38,6 +38,7 @@ import static java.nio.charset.StandardCharsets.UTF_8; import java.io.BufferedReader; import java.io.IOException; +import java.io.Reader; import java.io.UnsupportedEncodingException; import net.sourceforge.plantuml.AFile; @@ -114,7 +115,11 @@ public class EaterTheme extends Eater { try { final FileWithSuffix file = context.getFileWithSuffix(from, realName); - return ReadLineReader.create(file.getReader(UTF_8), "theme " + realName); + final Reader tmp = file.getReader(UTF_8); + if (tmp == null) + throw EaterException.located("No such theme " + realName); + + return ReadLineReader.create(tmp, "theme " + realName); } catch (IOException e) { e.printStackTrace(); throw EaterException.located("Cannot load " + realName); diff --git a/src/net/sourceforge/plantuml/timingdiagram/PlayerAnalog.java b/src/net/sourceforge/plantuml/timingdiagram/PlayerAnalog.java index 341831ad7..ccfd23e3d 100644 --- a/src/net/sourceforge/plantuml/timingdiagram/PlayerAnalog.java +++ b/src/net/sourceforge/plantuml/timingdiagram/PlayerAnalog.java @@ -35,6 +35,8 @@ package net.sourceforge.plantuml.timingdiagram; import java.awt.geom.Point2D; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.SortedMap; @@ -45,6 +47,7 @@ import net.sourceforge.plantuml.ISkinParam; import net.sourceforge.plantuml.awt.geom.Dimension2D; import net.sourceforge.plantuml.command.Position; import net.sourceforge.plantuml.cucadiagram.Display; +import net.sourceforge.plantuml.cucadiagram.Stereotype; import net.sourceforge.plantuml.graphic.AbstractTextBlock; import net.sourceforge.plantuml.graphic.HorizontalAlignment; import net.sourceforge.plantuml.graphic.StringBounder; @@ -52,6 +55,7 @@ import net.sourceforge.plantuml.graphic.TextBlock; import net.sourceforge.plantuml.graphic.UDrawable; import net.sourceforge.plantuml.graphic.color.Colors; import net.sourceforge.plantuml.style.SName; +import net.sourceforge.plantuml.style.StyleSignature; import net.sourceforge.plantuml.style.StyleSignatureBasic; import net.sourceforge.plantuml.timingdiagram.graphic.IntricatedPoint; import net.sourceforge.plantuml.ugraphic.UGraphic; @@ -61,14 +65,17 @@ import net.sourceforge.plantuml.ugraphic.UTranslate; public class PlayerAnalog extends Player { private final SortedMap values = new TreeMap(); + + private final List constraints = new ArrayList<>(); + private final double ymargin = 8; private Double initialState; private Double start; private Double end; private Integer ticksEvery; - public PlayerAnalog(String code, ISkinParam skinParam, TimingRuler ruler, boolean compact) { - super(code, skinParam, ruler, compact, null); + public PlayerAnalog(String code, ISkinParam skinParam, TimingRuler ruler, boolean compact, Stereotype stereotype) { + super(code, skinParam, ruler, compact, stereotype); this.suggestedHeight = 100; } @@ -94,16 +101,17 @@ public class PlayerAnalog extends Player { } public double getFullHeight(StringBounder stringBounder) { - return suggestedHeight; + return getHeightForConstraints(stringBounder) + suggestedHeight; } public IntricatedPoint getTimeProjection(StringBounder stringBounder, TimeTick tick) { final double x = ruler.getPosInPixel(tick); - final double value = getValueAt(tick); - return new IntricatedPoint(new Point2D.Double(x, getYpos(value)), new Point2D.Double(x, getYpos(value))); + final double value = getValueAt(stringBounder, tick); + return new IntricatedPoint(new Point2D.Double(x, getYpos(stringBounder, value)), + new Point2D.Double(x, getYpos(stringBounder, value))); } - private double getValueAt(TimeTick tick) { + private double getValueAt(StringBounder stringBounder, TimeTick tick) { final Double result = values.get(tick); if (result != null) return result; @@ -155,14 +163,14 @@ public class PlayerAnalog extends Player { } } + @Override public void createConstraint(TimeTick tick1, TimeTick tick2, String message) { - throw new UnsupportedOperationException(); + this.constraints.add(new TimeConstraint(tick1, tick2, message, skinParam)); } - private double getYpos(double value) { - final double fullHeight = getFullHeight(null); - final double y = (value - getMin()) * (fullHeight - 2 * ymargin) / (getMax() - getMin()); - return fullHeight - ymargin - y; + private double getYpos(StringBounder stringBounder, double value) { + final double y = (value - getMin()) * (suggestedHeight - 2 * ymargin) / (getMax() - getMin()); + return getHeightForConstraints(stringBounder) + suggestedHeight - ymargin - y; } public TextBlock getPart1(final double fullAvailableWidth, final double specialVSpace) { @@ -224,7 +232,7 @@ public class PlayerAnalog extends Player { final TextBlock label = getTextBlock(value); final Dimension2D dim = label.calculateDimension(ug.getStringBounder()); ug = ug.apply(UTranslate.dx(fullAvailableWidth - dim.getWidth() - 2)); - label.drawU(ug.apply(UTranslate.dy(getYpos(value) - dim.getHeight() / 2))); + label.drawU(ug.apply(UTranslate.dy(getYpos(ug.getStringBounder(), value) - dim.getHeight() / 2))); } private TextBlock getTextBlock(double value) { @@ -239,7 +247,7 @@ public class PlayerAnalog extends Player { final ULine hline = ULine.hline(ruler.getWidth()); for (int i = first; i <= last; i++) if (i % ticksEvery == 0) - ug.apply(UTranslate.dy(getYpos(i))).draw(hline); + ug.apply(UTranslate.dy(getYpos(ug.getStringBounder(), i))).draw(hline); } @@ -253,14 +261,18 @@ public class PlayerAnalog extends Player { double lastx = 0; double lastValue = initialState == null ? 0 : initialState; for (Map.Entry ent : values.entrySet()) { - final double y1 = getYpos(lastValue); - final double y2 = getYpos(ent.getValue()); + final double y1 = getYpos(ug.getStringBounder(), lastValue); + final double y2 = getYpos(ug.getStringBounder(), ent.getValue()); final double x = ruler.getPosInPixel(ent.getKey()); ug.apply(new UTranslate(lastx, y1)).draw(new ULine(x - lastx, y2 - y1)); lastx = x; lastValue = ent.getValue(); } - ug.apply(new UTranslate(lastx, getYpos(lastValue))).draw(ULine.hline(ruler.getWidth() - lastx)); + ug.apply(new UTranslate(lastx, getYpos(ug.getStringBounder(), lastValue))) + .draw(ULine.hline(ruler.getWidth() - lastx)); + + drawConstraints(ug.apply(UTranslate.dy(getHeightForConstraints(ug.getStringBounder())))); + } }; } @@ -275,8 +287,19 @@ public class PlayerAnalog extends Player { } @Override - protected StyleSignatureBasic getStyleSignature() { - return StyleSignatureBasic.of(SName.root, SName.element, SName.timingDiagram); + protected StyleSignature getStyleSignature() { + return StyleSignatureBasic.of(SName.root, SName.element, SName.timingDiagram, SName.analog) + .withTOBECHANGED(stereotype); + } + + private void drawConstraints(final UGraphic ug) { + for (TimeConstraint constraint : constraints) { + constraint.drawU(ug, ruler); + } + } + + private double getHeightForConstraints(StringBounder stringBounder) { + return TimeConstraint.getHeightForConstraints(stringBounder, constraints); } } diff --git a/src/net/sourceforge/plantuml/timingdiagram/PlayerBinary.java b/src/net/sourceforge/plantuml/timingdiagram/PlayerBinary.java index fa3ddf3be..a14f2397b 100644 --- a/src/net/sourceforge/plantuml/timingdiagram/PlayerBinary.java +++ b/src/net/sourceforge/plantuml/timingdiagram/PlayerBinary.java @@ -126,6 +126,7 @@ public class PlayerBinary extends Player { return LOW_STRING; } + @Override public void createConstraint(TimeTick tick1, TimeTick tick2, String message) { this.constraints.add(new TimeConstraint(tick1, tick2, message, skinParam)); } diff --git a/src/net/sourceforge/plantuml/timingdiagram/PlayerClock.java b/src/net/sourceforge/plantuml/timingdiagram/PlayerClock.java index 70cfc11e7..31778fe6b 100644 --- a/src/net/sourceforge/plantuml/timingdiagram/PlayerClock.java +++ b/src/net/sourceforge/plantuml/timingdiagram/PlayerClock.java @@ -106,6 +106,7 @@ public class PlayerClock extends Player { throw new UnsupportedOperationException(); } + @Override public void createConstraint(TimeTick tick1, TimeTick tick2, String message) { throw new UnsupportedOperationException(); } diff --git a/src/net/sourceforge/plantuml/timingdiagram/TimingDiagram.java b/src/net/sourceforge/plantuml/timingdiagram/TimingDiagram.java index 08bb3d87d..8a8152f4b 100644 --- a/src/net/sourceforge/plantuml/timingdiagram/TimingDiagram.java +++ b/src/net/sourceforge/plantuml/timingdiagram/TimingDiagram.java @@ -313,8 +313,8 @@ public class TimingDiagram extends UmlDiagram implements Clocks { return CommandExecutionResult.ok(); } - public PlayerAnalog createAnalog(String code, String full, boolean compact) { - final PlayerAnalog player = new PlayerAnalog(full, getSkinParam(), ruler, compactByDefault); + public PlayerAnalog createAnalog(String code, String full, boolean compact, Stereotype stereotype) { + final PlayerAnalog player = new PlayerAnalog(full, getSkinParam(), ruler, compactByDefault, stereotype); players.put(code, player); return player; } diff --git a/src/net/sourceforge/plantuml/timingdiagram/command/CommandAnalog.java b/src/net/sourceforge/plantuml/timingdiagram/command/CommandAnalog.java index a90697cd7..71e766f77 100644 --- a/src/net/sourceforge/plantuml/timingdiagram/command/CommandAnalog.java +++ b/src/net/sourceforge/plantuml/timingdiagram/command/CommandAnalog.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.Stereotype; import net.sourceforge.plantuml.timingdiagram.PlayerAnalog; import net.sourceforge.plantuml.timingdiagram.TimingDiagram; @@ -61,6 +62,8 @@ public class CommandAnalog extends SingleLineCommand2 { new RegexLeaf("analog"), // RegexLeaf.spaceOneOrMore(), // new RegexLeaf("FULL", "[%g]([^%g]+)[%g]"), // + RegexLeaf.spaceZeroOrMore(), // + new RegexLeaf("STEREOTYPE", "(\\<\\<.*\\>\\>)?"), // RegexLeaf.spaceOneOrMore(), // new RegexOptional(// new RegexConcat( // @@ -74,7 +77,11 @@ public class CommandAnalog extends SingleLineCommand2 { RegexLeaf.spaceOneOrMore())), // new RegexLeaf("as"), // RegexLeaf.spaceOneOrMore(), // - new RegexLeaf("CODE", "([%pLN_.@]+)"), RegexLeaf.end()); + new RegexLeaf("CODE", "([%pLN_.@]+)"), // + RegexLeaf.spaceZeroOrMore(), // + new RegexLeaf("STEREOTYPE2", "(\\<\\<.*\\>\\>)?"), // + RegexLeaf.spaceZeroOrMore(), // + RegexLeaf.end()); } @Override @@ -82,7 +89,14 @@ public class CommandAnalog extends SingleLineCommand2 { final String compact = arg.get("COMPACT", 0); final String code = arg.get("CODE", 0); final String full = arg.get("FULL", 0); - final PlayerAnalog player = diagram.createAnalog(code, full, compact != null); + + Stereotype stereotype = null; + if (arg.get("STEREOTYPE", 0) != null) + stereotype = Stereotype.build(arg.get("STEREOTYPE", 0)); + else if (arg.get("STEREOTYPE2", 0) != null) + stereotype = Stereotype.build(arg.get("STEREOTYPE2", 0)); + + final PlayerAnalog player = diagram.createAnalog(code, full, compact != null, stereotype); final String start = arg.get("START", 0); final String end = arg.get("END", 0); if (start != null && end != null) { diff --git a/src/net/sourceforge/plantuml/timingdiagram/graphic/Ribbon.java b/src/net/sourceforge/plantuml/timingdiagram/graphic/Ribbon.java index 57265ff66..adbec2af6 100644 --- a/src/net/sourceforge/plantuml/timingdiagram/graphic/Ribbon.java +++ b/src/net/sourceforge/plantuml/timingdiagram/graphic/Ribbon.java @@ -151,7 +151,8 @@ public class Ribbon implements PDrawing { private void drawNotes(UGraphic ug, final Position position) { for (TimingNote note : notes) if (note.getPosition() == position) { - final double x = ruler.getPosInPixel(note.getWhen()); + final TimeTick when = note.getWhen(); + final double x = when == null ? 0 : ruler.getPosInPixel(when); note.drawU(ug.apply(UTranslate.dx(x))); } } diff --git a/src/net/sourceforge/plantuml/ugraphic/UImageSvg.java b/src/net/sourceforge/plantuml/ugraphic/UImageSvg.java index 6152a05ff..cc4b988c4 100644 --- a/src/net/sourceforge/plantuml/ugraphic/UImageSvg.java +++ b/src/net/sourceforge/plantuml/ugraphic/UImageSvg.java @@ -128,12 +128,12 @@ public class UImageSvg implements UShape { throw new IllegalStateException("Cannot find " + name); } - public int getHeight() { - return this.getData("height"); + public double getHeight() { + return this.getData("height") * scale; } - public int getWidth() { - return this.getData("width"); + public double getWidth() { + return this.getData("width") * scale; } public double getScale() { diff --git a/src/net/sourceforge/plantuml/ugraphic/ULine.java b/src/net/sourceforge/plantuml/ugraphic/ULine.java index cb5c5be3e..2f6fbed49 100644 --- a/src/net/sourceforge/plantuml/ugraphic/ULine.java +++ b/src/net/sourceforge/plantuml/ugraphic/ULine.java @@ -35,6 +35,7 @@ */ package net.sourceforge.plantuml.ugraphic; +import java.awt.geom.AffineTransform; import java.awt.geom.Point2D; public class ULine extends AbstractShadowable implements UShapeSized { @@ -51,6 +52,14 @@ public class ULine extends AbstractShadowable implements UShapeSized { this.dy = dy; } + public ULine rotate(double theta) { + if (theta == 0) + return this; + final AffineTransform rot = AffineTransform.getRotateInstance(theta); + final Point2D result = rot.transform(new Point2D.Double(dx, dy), null); + return new ULine(result.getX(), result.getY()); + } + public static ULine hline(double dx) { return new ULine(dx, 0); } diff --git a/src/net/sourceforge/plantuml/ugraphic/UPolygon.java b/src/net/sourceforge/plantuml/ugraphic/UPolygon.java index 23bb3f404..13ad6fa58 100644 --- a/src/net/sourceforge/plantuml/ugraphic/UPolygon.java +++ b/src/net/sourceforge/plantuml/ugraphic/UPolygon.java @@ -73,7 +73,7 @@ public class UPolygon extends AbstractShadowable { (pt1.getY() + pt2.getY()) / 2); final double delta = middle.distance(center); if (delta < 1) - return all.get((i - 1) % all.size()); + return all.get((i + all.size() - 1) % all.size()); } return null; diff --git a/src/net/sourceforge/plantuml/version/Version.java b/src/net/sourceforge/plantuml/version/Version.java index 8adf14f32..3de4de91b 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 1202205; + return 1202206; } public static int versionPatched() { @@ -80,7 +80,7 @@ public class Version { } public static int beta() { - final int beta = 5; + final int beta = 3; return beta; } @@ -93,7 +93,7 @@ public class Version { } public static long compileTime() { - return 1651316152000L; + return 1655832889469L; } public static String compileTimeString() { diff --git a/src/net/sourceforge/plantuml/yaml/YamlLines.java b/src/net/sourceforge/plantuml/yaml/YamlLines.java index 7fdf08ad0..5ea9b1afe 100644 --- a/src/net/sourceforge/plantuml/yaml/YamlLines.java +++ b/src/net/sourceforge/plantuml/yaml/YamlLines.java @@ -44,15 +44,15 @@ import java.util.regex.Pattern; public class YamlLines implements Iterable { - public static final String KEY = "([^:\\s]+)"; + public static final String KEY = "([^:]+)"; private List lines = new ArrayList<>(); public YamlLines(List rawLines) { for (String s : rawLines) { - if (s.startsWith("#")) { + if (s.startsWith("#")) continue; - } + s = removeDiese(s); if (s.trim().length() == 0) continue; @@ -79,9 +79,9 @@ public class YamlLines implements Iterable { private String removeDiese(String s) { final int idx = s.indexOf(" #"); - if (idx == -1) { + if (idx == -1) return s; - } + return s.substring(0, idx); } @@ -104,9 +104,9 @@ public class YamlLines implements Iterable { } private void removeFirstCols(int startingEmptyCols) { - if (startingEmptyCols == 0) { + if (startingEmptyCols == 0) return; - } + for (ListIterator it = lines.listIterator(); it.hasNext();) { final String s = it.next().substring(startingEmptyCols); it.set(s); @@ -117,9 +117,8 @@ public class YamlLines implements Iterable { int result = Integer.MAX_VALUE; for (String s : lines) { result = Math.min(result, startingSpaces(s)); - if (result == 0) { + if (result == 0) return 0; - } } return result; } @@ -127,9 +126,9 @@ public class YamlLines implements Iterable { private static int startingSpaces(String s) { final Pattern p1 = Pattern.compile("^(\\s*).*"); final Matcher m1 = p1.matcher(s); - if (m1.matches()) { + if (m1.matches()) return m1.group(1).length(); - } + return 0; } diff --git a/src/org/stathissideris/ascii2image/graphics/CompositeDiagramShape.java b/src/org/stathissideris/ascii2image/graphics/CompositeDiagramShape.java index 108f01e4a..1d7ab045e 100644 --- a/src/org/stathissideris/ascii2image/graphics/CompositeDiagramShape.java +++ b/src/org/stathissideris/ascii2image/graphics/CompositeDiagramShape.java @@ -122,7 +122,12 @@ public class CompositeDiagramShape extends DiagramComponent { if(workGrid.cellContainsDashedLineChar(previousCell)) shape.setStrokeDashed(true); boolean finished = false; + int nb = 0; while(!finished) { + // https://github.com/plantuml/plantuml/issues/1036 + nb++; + if (nb > 1000) + return result; visitedCells.add(cell); if(workGrid.isPointCell(cell)) { if(DEBUG) System.out.println("point at "+cell+" (call from line: "+DebugUtils.getLineNumber()+")");