diff --git a/pom.xml b/pom.xml index b5c98ef18..7758fd8ef 100644 --- a/pom.xml +++ b/pom.xml @@ -35,7 +35,7 @@ net.sourceforge.plantuml plantuml - 8049-SNAPSHOT + 8050-SNAPSHOT jar PlantUML diff --git a/src/net/sourceforge/plantuml/AnnotatedWorker.java b/src/net/sourceforge/plantuml/AnnotatedWorker.java index 434245866..b4448294f 100644 --- a/src/net/sourceforge/plantuml/AnnotatedWorker.java +++ b/src/net/sourceforge/plantuml/AnnotatedWorker.java @@ -93,17 +93,15 @@ public class AnnotatedWorker { } private TextBlock addTitle(TextBlock original) { - if (DisplayPositionned.isNull(annotated.getTitle())) { + final DisplayPositionned title = annotated.getTitle(); + if (DisplayPositionned.isNull(title)) { return original; } - final TextBlock text = annotated - .getTitle() - .getDisplay() - .create(new FontConfiguration(getSkinParam(), FontParam.TITLE, null), HorizontalAlignment.CENTER, - getSkinParam()); + ISkinParam skinParam = getSkinParam(); + final FontConfiguration fontConfiguration = new FontConfiguration(skinParam, FontParam.TITLE, null); - return DecorateEntityImage.addTop(original, text, HorizontalAlignment.CENTER); - // return new DecorateTextBlock(original, text, HorizontalAlignment.CENTER); + final TextBlock block = TextBlockUtils.title(fontConfiguration, title.getDisplay(), skinParam); + return DecorateEntityImage.addTop(original, block, HorizontalAlignment.CENTER); } private TextBlock addHeaderAndFooter(TextBlock original) { @@ -121,9 +119,6 @@ public class AnnotatedWorker { .create(new FontConfiguration(getSkinParam(), FontParam.HEADER, null), annotated.getHeader().getHorizontalAlignment(), getSkinParam()); - // return new DecorateTextBlock(original, textHeader, annotated.getHeader().getHorizontalAlignment(), - // textFooter, - // annotated.getFooter().getHorizontalAlignment()); return new DecorateEntityImage(original, textHeader, annotated.getHeader().getHorizontalAlignment(), textFooter, annotated.getFooter().getHorizontalAlignment()); } diff --git a/src/net/sourceforge/plantuml/ColorParam.java b/src/net/sourceforge/plantuml/ColorParam.java index deb31ee81..88151dd17 100644 --- a/src/net/sourceforge/plantuml/ColorParam.java +++ b/src/net/sourceforge/plantuml/ColorParam.java @@ -89,6 +89,11 @@ public enum ColorParam { legendBackground(HtmlColorUtils.COL_DDDDDD, true, ColorType.BACK), legendBorder(HtmlColorUtils.BLACK, ColorType.LINE), + titleBackground(null, true, ColorType.BACK), + titleBorder(null, ColorType.LINE), + + diagramBorder(null, ColorType.LINE), + actorBackground(HtmlColorUtils.MY_YELLOW, true, ColorType.BACK), actorBorder(HtmlColorUtils.MY_RED, ColorType.LINE), participantBackground(HtmlColorUtils.MY_YELLOW, true, ColorType.BACK), @@ -118,6 +123,8 @@ public enum ColorParam { databaseBorder(HtmlColorUtils.BLACK, ColorType.LINE), folderBackground(HtmlColorUtils.MY_YELLOW, ColorType.BACK), folderBorder(HtmlColorUtils.BLACK, ColorType.LINE), + fileBackground(HtmlColorUtils.MY_YELLOW, ColorType.BACK), + fileBorder(HtmlColorUtils.BLACK, ColorType.LINE), frameBackground(HtmlColorUtils.MY_YELLOW, ColorType.BACK), frameBorder(HtmlColorUtils.BLACK, ColorType.LINE), nodeBackground(HtmlColorUtils.MY_YELLOW, ColorType.BACK), diff --git a/src/net/sourceforge/plantuml/FileUtils.java b/src/net/sourceforge/plantuml/FileUtils.java index d58deb996..14111e8c7 100644 --- a/src/net/sourceforge/plantuml/FileUtils.java +++ b/src/net/sourceforge/plantuml/FileUtils.java @@ -32,11 +32,14 @@ package net.sourceforge.plantuml; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; +import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; +import java.io.FileReader; import java.io.IOException; import java.io.InputStream; +import java.io.InputStreamReader; import java.io.OutputStream; import java.util.concurrent.atomic.AtomicInteger; @@ -105,4 +108,26 @@ public class FileUtils { fos.close(); } + static public String readSvg(File svgFile) throws IOException { + final BufferedReader br = new BufferedReader(new FileReader(svgFile)); + return readSvg(br, true); + } + + static public String readSvg(InputStream is) throws IOException { + final BufferedReader br = new BufferedReader(new InputStreamReader(is)); + return readSvg(br, false); + } + + private static String readSvg(final BufferedReader br, boolean withClose) throws IOException { + final StringBuilder sb = new StringBuilder(); + String s; + while ((s = br.readLine()) != null) { + sb.append(s); + } + if (withClose) { + br.close(); + } + return sb.toString(); + } + } diff --git a/src/net/sourceforge/plantuml/FontParam.java b/src/net/sourceforge/plantuml/FontParam.java index 9ceddeafc..b758a5450 100644 --- a/src/net/sourceforge/plantuml/FontParam.java +++ b/src/net/sourceforge/plantuml/FontParam.java @@ -62,6 +62,7 @@ public enum FontParam { ARTIFACT(14, Font.PLAIN), // CLOUD(14, Font.PLAIN), // FOLDER(14, Font.PLAIN), // + FILE(14, Font.PLAIN), // FRAME(14, Font.PLAIN), // STORAGE(14, Font.PLAIN), // BOUNDARY(14, Font.PLAIN), // @@ -101,6 +102,7 @@ public enum FontParam { RECTANGLE_STEREOTYPE(14, Font.ITALIC), // NODE_STEREOTYPE(14, Font.ITALIC), // FOLDER_STEREOTYPE(14, Font.ITALIC), // + FILE_STEREOTYPE(14, Font.ITALIC), // FRAME_STEREOTYPE(14, Font.ITALIC), // DATABASE_STEREOTYPE(14, Font.ITALIC), // QUEUE_STEREOTYPE(14, Font.ITALIC), // diff --git a/src/net/sourceforge/plantuml/ISkinParam.java b/src/net/sourceforge/plantuml/ISkinParam.java index aa9dfcb17..ad383f7e7 100644 --- a/src/net/sourceforge/plantuml/ISkinParam.java +++ b/src/net/sourceforge/plantuml/ISkinParam.java @@ -37,6 +37,7 @@ import net.sourceforge.plantuml.graphic.HorizontalAlignment; import net.sourceforge.plantuml.graphic.HtmlColor; import net.sourceforge.plantuml.graphic.SkinParameter; import net.sourceforge.plantuml.graphic.color.Colors; +import net.sourceforge.plantuml.skin.ArrowDirection; import net.sourceforge.plantuml.svek.ConditionStyle; import net.sourceforge.plantuml.svek.PackageStyle; import net.sourceforge.plantuml.ugraphic.ColorMapper; @@ -61,7 +62,7 @@ public interface ISkinParam extends ISkinSimple { public UFont getFont(Stereotype stereotype, boolean inPackageTitle, FontParam... fontParam); - public HorizontalAlignment getHorizontalAlignment(AlignParam param); + public HorizontalAlignment getHorizontalAlignment(AlignParam param, ArrowDirection arrowDirection); public HorizontalAlignment getDefaultTextAlignment(HorizontalAlignment defaultValue); @@ -95,7 +96,7 @@ public interface ISkinParam extends ISkinSimple { public double getRanksep(); - public double getRoundCorner(); + public double getRoundCorner(String param); public double maxMessageSize(); @@ -126,6 +127,8 @@ public interface ISkinParam extends ISkinSimple { public int maxAsciiMessageLength(); public int colorArrowSeparationSpace(); + + public SplitParam getSplitParam(); } \ No newline at end of file diff --git a/src/net/sourceforge/plantuml/LineParam.java b/src/net/sourceforge/plantuml/LineParam.java index af3bcf5ea..bc7b34770 100644 --- a/src/net/sourceforge/plantuml/LineParam.java +++ b/src/net/sourceforge/plantuml/LineParam.java @@ -45,7 +45,9 @@ public enum LineParam { partitionBorder, packageBorder, swimlaneBorder, - activityBorder; + activityBorder, + titleBorder, + diagramBorder; // sequenceBoxBorder(0.1); } diff --git a/src/net/sourceforge/plantuml/Option.java b/src/net/sourceforge/plantuml/Option.java index a9ecd68d1..c8e47727a 100644 --- a/src/net/sourceforge/plantuml/Option.java +++ b/src/net/sourceforge/plantuml/Option.java @@ -56,6 +56,7 @@ public class Option { private boolean computeurl = false; private boolean decodeurl = false; private boolean pipe = false; + private boolean pipeMap = false; private boolean syntax = false; private boolean checkOnly = false; private boolean failfast = false; @@ -193,6 +194,8 @@ public class Option { OptionFlags.getInstance().setVerbose(true); } else if (s.equalsIgnoreCase("-pipe") || s.equalsIgnoreCase("-p")) { pipe = true; + } else if (s.equalsIgnoreCase("-pipemap")) { + pipeMap = true; } else if (s.equalsIgnoreCase("-pattern")) { pattern = true; } else if (s.equalsIgnoreCase("-syntax")) { @@ -362,6 +365,10 @@ public class Option { return pipe; } + public final boolean isPipeMap() { + return pipeMap; + } + public final boolean isSyntax() { return syntax; } diff --git a/src/net/sourceforge/plantuml/OptionPrint.java b/src/net/sourceforge/plantuml/OptionPrint.java index da18d2f50..012c9d3f1 100644 --- a/src/net/sourceforge/plantuml/OptionPrint.java +++ b/src/net/sourceforge/plantuml/OptionPrint.java @@ -159,6 +159,7 @@ public class OptionPrint { public static Collection interestingValues() { final List strings = new ArrayList(); + strings.add("PLANTUML_LIMIT_SIZE: " + GraphvizUtils.getenvImageLimit()); strings.add("Processors: " + Runtime.getRuntime().availableProcessors()); final long freeMemory = Runtime.getRuntime().freeMemory(); final long maxMemory = Runtime.getRuntime().maxMemory(); diff --git a/src/net/sourceforge/plantuml/PSystemUtils.java b/src/net/sourceforge/plantuml/PSystemUtils.java index 3c76d386f..5066206d0 100644 --- a/src/net/sourceforge/plantuml/PSystemUtils.java +++ b/src/net/sourceforge/plantuml/PSystemUtils.java @@ -216,7 +216,8 @@ public class PSystemUtils { if (fileFormat.getFileFormat() == FileFormat.PNG) { result = new PngSplitter(suggestedFile, system.getHorizontalPages(), system.getVerticalPages(), - system.getMetadata(), system.getDpi(fileFormat), fileFormat.isWithMetadata()).getFiles(); + system.getMetadata(), system.getDpi(fileFormat), fileFormat.isWithMetadata(), system.getSkinParam() + .getSplitParam()).getFiles(); } return result; diff --git a/src/net/sourceforge/plantuml/Run.java b/src/net/sourceforge/plantuml/Run.java index 1ce65fdb5..a98e1d734 100644 --- a/src/net/sourceforge/plantuml/Run.java +++ b/src/net/sourceforge/plantuml/Run.java @@ -116,7 +116,7 @@ public class Run { } } new MainWindow2(option, dir); - } else if (option.isPipe() || option.isSyntax()) { + } else if (option.isPipe() || option.isPipeMap() || option.isSyntax()) { managePipe(option); forceQuit = true; } else if (option.isFailfast2()) { @@ -283,6 +283,9 @@ public class Run { ps.println("OTHER"); ps.println(system.getDescription()); } + } else if (option.isPipeMap()) { + final String result = sourceStringReader.getCMapData(0, option.getFileFormatOption()); + ps.println(result); } else if (option.isPipe()) { final String result = sourceStringReader.generateImage(ps, 0, option.getFileFormatOption()); if ("(error)".equalsIgnoreCase(result)) { diff --git a/src/net/sourceforge/plantuml/SkinParam.java b/src/net/sourceforge/plantuml/SkinParam.java index 402a0adb5..0127412d4 100644 --- a/src/net/sourceforge/plantuml/SkinParam.java +++ b/src/net/sourceforge/plantuml/SkinParam.java @@ -53,6 +53,7 @@ import net.sourceforge.plantuml.graphic.HtmlColorUtils; import net.sourceforge.plantuml.graphic.IHtmlColorSet; import net.sourceforge.plantuml.graphic.SkinParameter; import net.sourceforge.plantuml.graphic.color.Colors; +import net.sourceforge.plantuml.skin.ArrowDirection; import net.sourceforge.plantuml.svek.ConditionStyle; import net.sourceforge.plantuml.svek.PackageStyle; import net.sourceforge.plantuml.ugraphic.ColorMapper; @@ -358,6 +359,7 @@ public class SkinParam implements ISkinParam { result.add("Nodesep"); result.add("Ranksep"); result.add("RoundCorner"); + result.add("TitleBorderRoundCorner"); result.add("MaxMessageSize"); result.add("Style"); result.add("SequenceParticipant"); @@ -412,7 +414,7 @@ public class SkinParam implements ISkinParam { return DotSplines.SPLINES; } - public HorizontalAlignment getHorizontalAlignment(AlignParam param) { + public HorizontalAlignment getHorizontalAlignment(AlignParam param, ArrowDirection arrowDirection) { final String value; switch (param) { case SEQUENCE_MESSAGE_ALIGN: @@ -424,6 +426,22 @@ public class SkinParam implements ISkinParam { default: value = getValue(param.name()); } + if ("direction".equalsIgnoreCase(value)) { + if (arrowDirection == ArrowDirection.LEFT_TO_RIGHT_NORMAL) { + return HorizontalAlignment.LEFT; + } + if (arrowDirection == ArrowDirection.RIGHT_TO_LEFT_REVERSE) { + return HorizontalAlignment.RIGHT; + } + } + if ("reversedirection".equalsIgnoreCase(value)) { + if (arrowDirection == ArrowDirection.LEFT_TO_RIGHT_NORMAL) { + return HorizontalAlignment.RIGHT; + } + if (arrowDirection == ArrowDirection.RIGHT_TO_LEFT_REVERSE) { + return HorizontalAlignment.LEFT; + } + } final HorizontalAlignment result = HorizontalAlignment.fromString(value); if (result == null) { return param.getDefaultValue(); @@ -576,8 +594,8 @@ public class SkinParam implements ISkinParam { return 0; } - public double getRoundCorner() { - final String value = getValue("roundcorner"); + public double getRoundCorner(String param) { + final String value = getValue(param + "roundcorner"); if (value != null && value.matches("\\d+")) { return Double.parseDouble(value); } @@ -760,4 +778,18 @@ public class SkinParam implements ISkinParam { return 0; } + public SplitParam getSplitParam() { + final String border = getValue("pageBorderColor"); + final String external = getValue("pageExternalColor"); + + final String marginString = getValue("pageMargin"); + int margin = 0; + if (marginString != null && marginString.matches("\\d+")) { + margin = Integer.parseInt(marginString); + } + + return new SplitParam(getIHtmlColorSet().getColorIfValid(border), getIHtmlColorSet().getColorIfValid(external), + margin); + } + } diff --git a/src/net/sourceforge/plantuml/SkinParamDelegator.java b/src/net/sourceforge/plantuml/SkinParamDelegator.java index d06c50e6b..401c3737d 100644 --- a/src/net/sourceforge/plantuml/SkinParamDelegator.java +++ b/src/net/sourceforge/plantuml/SkinParamDelegator.java @@ -38,6 +38,7 @@ import net.sourceforge.plantuml.graphic.HtmlColor; import net.sourceforge.plantuml.graphic.IHtmlColorSet; import net.sourceforge.plantuml.graphic.SkinParameter; import net.sourceforge.plantuml.graphic.color.Colors; +import net.sourceforge.plantuml.skin.ArrowDirection; import net.sourceforge.plantuml.svek.ConditionStyle; import net.sourceforge.plantuml.svek.PackageStyle; import net.sourceforge.plantuml.ugraphic.ColorMapper; @@ -97,8 +98,8 @@ public class SkinParamDelegator implements ISkinParam { return skinParam.getDotExecutable(); } - public HorizontalAlignment getHorizontalAlignment(AlignParam param) { - return skinParam.getHorizontalAlignment(param); + public HorizontalAlignment getHorizontalAlignment(AlignParam param, ArrowDirection arrowDirection) { + return skinParam.getHorizontalAlignment(param, arrowDirection); } public ColorMapper getColorMapper() { @@ -141,8 +142,8 @@ public class SkinParamDelegator implements ISkinParam { return skinParam.getRanksep(); } - public double getRoundCorner() { - return skinParam.getRoundCorner(); + public double getRoundCorner(String param) { + return skinParam.getRoundCorner(param); } public UStroke getThickness(LineParam param, Stereotype stereotype) { @@ -237,4 +238,8 @@ public class SkinParamDelegator implements ISkinParam { return skinParam.colorArrowSeparationSpace(); } + public SplitParam getSplitParam() { + return skinParam.getSplitParam(); + } + } diff --git a/src/net/sourceforge/plantuml/SourceStringReader.java b/src/net/sourceforge/plantuml/SourceStringReader.java index 504d6acd9..e9073390b 100644 --- a/src/net/sourceforge/plantuml/SourceStringReader.java +++ b/src/net/sourceforge/plantuml/SourceStringReader.java @@ -129,6 +129,26 @@ public class SourceStringReader { } + public String getCMapData(int numImage, FileFormatOption fileFormatOption) throws IOException { + if (blocks.size() == 0) { + return null; + } + for (BlockUml b : blocks) { + final Diagram system = b.getDiagram(); + final int nbInSystem = system.getNbImages(); + if (numImage < nbInSystem) { + final ImageData imageData = system.exportDiagram(new NullOutputStream(), numImage, fileFormatOption); + if (imageData.containsCMapData()) { + return imageData.getCMapData("plantuml"); + } + return null; + } + numImage -= nbInSystem; + } + return null; + + } + private void noStartumlFound(OutputStream os, FileFormatOption fileFormatOption) throws IOException { final GraphicStrings error = GraphicStrings.createDefault(Arrays.asList("No @startuml found"), fileFormatOption.isUseRedForError()); diff --git a/src/net/sourceforge/plantuml/SplitParam.java b/src/net/sourceforge/plantuml/SplitParam.java new file mode 100644 index 000000000..2c1f3d086 --- /dev/null +++ b/src/net/sourceforge/plantuml/SplitParam.java @@ -0,0 +1,80 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2017, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * This file is part of PlantUML. + * + * PlantUML is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PlantUML distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml; + +import java.awt.Color; + +import net.sourceforge.plantuml.graphic.HtmlColor; +import net.sourceforge.plantuml.graphic.HtmlColorSimple; +import net.sourceforge.plantuml.graphic.HtmlColorUtils; + +public class SplitParam { + + private final HtmlColor borderColor; + private final HtmlColor externalColor; + private final int externalMargin; + + public SplitParam() { + this(null, null, 0); + } + + public SplitParam(HtmlColor borderColor, HtmlColor externalColor, int externalMargin) { + if (borderColor != null && externalMargin == 0) { + externalMargin = 1; + } + this.borderColor = borderColor; + this.externalColor = externalColor; + this.externalMargin = externalMargin; + } + + public boolean isSet() { + return externalMargin > 0; + } + + public int getExternalMargin() { + return externalMargin; + } + + public Color getBorderColor() { + if (borderColor == null) { + return null; + } + return ((HtmlColorSimple) borderColor).getColor999(); + } + + public Color getExternalColor() { + if (externalColor == null) { + return null; + } + return ((HtmlColorSimple) externalColor).getColor999(); + } + +} \ No newline at end of file diff --git a/src/net/sourceforge/plantuml/StringUtils.java b/src/net/sourceforge/plantuml/StringUtils.java index ccaae422b..96a8dec3f 100644 --- a/src/net/sourceforge/plantuml/StringUtils.java +++ b/src/net/sourceforge/plantuml/StringUtils.java @@ -414,7 +414,7 @@ public class StringUtils { } public static String manageGuillemet(String st) { - return st.replaceAll("\\<\\<\\s?([^<>]+?)\\s?\\>\\>", "\u00AB$1\u00BB"); + return st.replaceAll("\\<\\<\\s?((?:\\<&\\w+\\>|[^<>])+?)\\s?\\>\\>", "\u00AB$1\u00BB"); } public static String manageUnicodeNotationUplus(String s) { diff --git a/src/net/sourceforge/plantuml/UrlBuilder.java b/src/net/sourceforge/plantuml/UrlBuilder.java index c1a4cc850..3a05aa17b 100644 --- a/src/net/sourceforge/plantuml/UrlBuilder.java +++ b/src/net/sourceforge/plantuml/UrlBuilder.java @@ -52,7 +52,7 @@ public class UrlBuilder { } private static final String URL_PATTERN_OLD = "\\[\\[([%g][^%g]+[%g]|[^{}%s\\]\\[]*)(?:[%s]*\\{((?:[^{}]|\\{[^{}]*\\})+)\\})?(?:[%s]*([^\\]\\[]+))?\\]\\]"; - private static final String URL_PATTERN = "\\[\\[([%g][^%g]+[%g])?([\\w\\W]*)\\]\\]"; + private static final String URL_PATTERN = "\\[\\[([%g][^%g]+[%g])?([\\w\\W]*?)\\]\\]"; private static final String URL_PATTERN_BAD = "\\[\\[([%g][^%g]+[%g]|[^{}%s\\]\\[]*)(?:[%s]*\\{" + "(" + levelN(3) + ")" + "\\})?(?:[%s]*([^\\]\\[]+))?\\]\\]"; diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ActivityDiagram3.java b/src/net/sourceforge/plantuml/activitydiagram3/ActivityDiagram3.java index 4261ba112..10600557d 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ActivityDiagram3.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ActivityDiagram3.java @@ -165,9 +165,8 @@ public class ActivityDiagram3 extends UmlDiagram { final double margin = 10; final double dpiFactor = getDpiFactor(fileFormatOption, Dimension2DDouble.delta(dim, 2 * margin, 0)); - final ImageBuilder imageBuilder = new ImageBuilder(skinParam.getColorMapper(), dpiFactor, getSkinParam() - .getBackgroundColor(), fileFormatOption.isWithMetadata() ? getMetadata() : null, getWarningOrError(), - margin, margin, getAnimation(), getSkinParam().handwritten()); + final ImageBuilder imageBuilder = new ImageBuilder(getSkinParam(), dpiFactor, fileFormatOption.isWithMetadata() ? getMetadata() + : null, getWarningOrError(), margin, margin, getAnimation()); imageBuilder.setUDrawable(result); return imageBuilder.writeImageTOBEMOVED(fileFormatOption, os); diff --git a/src/net/sourceforge/plantuml/activitydiagram3/InstructionEnd.java b/src/net/sourceforge/plantuml/activitydiagram3/InstructionEnd.java index bda99571b..1428bf774 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/InstructionEnd.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/InstructionEnd.java @@ -47,7 +47,9 @@ public class InstructionEnd extends MonoSwimable implements Instruction { } public Ftile createFtile(FtileFactory factory) { - return factory.end(getSwimlaneIn()); + Ftile result = factory.end(getSwimlaneIn()); + result = eventuallyAddNote(factory, result, result.getSwimlaneIn()); + return result; } public void add(Instruction other) { diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/EntityImageLegend.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/EntityImageLegend.java index ea6146824..ee15284d2 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/EntityImageLegend.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/EntityImageLegend.java @@ -30,106 +30,32 @@ */ package net.sourceforge.plantuml.activitydiagram3.ftile; -import java.awt.geom.Dimension2D; - import net.sourceforge.plantuml.ColorParam; -import net.sourceforge.plantuml.Dimension2DDouble; import net.sourceforge.plantuml.FontParam; import net.sourceforge.plantuml.ISkinParam; import net.sourceforge.plantuml.LineParam; import net.sourceforge.plantuml.cucadiagram.Display; -import net.sourceforge.plantuml.graphic.AbstractTextBlock; import net.sourceforge.plantuml.graphic.FontConfiguration; import net.sourceforge.plantuml.graphic.HorizontalAlignment; import net.sourceforge.plantuml.graphic.HtmlColor; -import net.sourceforge.plantuml.graphic.StringBounder; import net.sourceforge.plantuml.graphic.TextBlock; import net.sourceforge.plantuml.graphic.TextBlockUtils; import net.sourceforge.plantuml.skin.rose.Rose; -import net.sourceforge.plantuml.ugraphic.UChangeBackColor; -import net.sourceforge.plantuml.ugraphic.UChangeColor; -import net.sourceforge.plantuml.ugraphic.UGraphic; -import net.sourceforge.plantuml.ugraphic.UPolygon; import net.sourceforge.plantuml.ugraphic.UStroke; -import net.sourceforge.plantuml.ugraphic.UTranslate; -public class EntityImageLegend extends AbstractTextBlock implements TextBlock { +public class EntityImageLegend { - private final int cornersize = 10; - private final HtmlColor legendBackgroundColor; - private final HtmlColor legendColor; - private final int marginX = 6; - private final int marginY = 5; - private final boolean withShadow; - private final ISkinParam skinParam; + public static TextBlock create(Display note, ISkinParam skinParam) { - private final TextBlock textBlock; - - private EntityImageLegend(Display note, ISkinParam skinParam) { - this.withShadow = false; - final Rose rose = new Rose(); - this.skinParam = skinParam; - - legendBackgroundColor = rose.getHtmlColor(skinParam, ColorParam.legendBackground); - legendColor = rose.getHtmlColor(skinParam, ColorParam.legendBorder); - - this.textBlock = note.create(new FontConfiguration(skinParam, FontParam.LEGEND, null), + final TextBlock textBlock = note.create(new FontConfiguration(skinParam, FontParam.LEGEND, null), HorizontalAlignment.LEFT, skinParam); - } - - public static TextBlock create(Display legend, ISkinParam skinParam) { - return TextBlockUtils.withMargin(new EntityImageLegend(legend, skinParam), 8, 8); - } - - private double getTextHeight(StringBounder stringBounder) { - final Dimension2D size = textBlock.calculateDimension(stringBounder); - return size.getHeight() + 2 * marginY; - } - - private double getPureTextWidth(StringBounder stringBounder) { - final Dimension2D size = textBlock.calculateDimension(stringBounder); - return size.getWidth(); - } - - private double getTextWidth(StringBounder stringBounder) { - return getPureTextWidth(stringBounder) + 2 * marginX; - } - - public Dimension2D calculateDimension(StringBounder stringBounder) { - final double height = getTextHeight(stringBounder); - final double width = getTextWidth(stringBounder); - return new Dimension2DDouble(width + 1, height + 1); - } - - private UGraphic applyStroke(UGraphic ug) { + final Rose rose = new Rose(); + final HtmlColor legendBackgroundColor = rose.getHtmlColor(skinParam, ColorParam.legendBackground); + final HtmlColor legendColor = rose.getHtmlColor(skinParam, ColorParam.legendBorder); final UStroke stroke = skinParam.getThickness(LineParam.legendBorder, null); - if (stroke == null) { - return ug; - } - return ug.apply(stroke); - } - public void drawU(UGraphic ug) { - final StringBounder stringBounder = ug.getStringBounder(); - final UPolygon polygon = getPolygonNormal(stringBounder); - if (withShadow) { - polygon.setDeltaShadow(4); - } - ug = ug.apply(new UChangeBackColor(legendBackgroundColor)).apply(new UChangeColor(legendColor)); - ug = applyStroke(ug); - ug.draw(polygon); - textBlock.drawU(ug.apply(new UTranslate(marginX, marginY))); - } - - private UPolygon getPolygonNormal(final StringBounder stringBounder) { - final UPolygon polygon = new UPolygon(); - polygon.addPoint(0, 0); - polygon.addPoint(0, getTextHeight(stringBounder)); - final double width = getTextWidth(stringBounder); - polygon.addPoint(width, getTextHeight(stringBounder)); - polygon.addPoint(width, 0); - polygon.addPoint(0, 0); - return polygon; + final TextBlock result = TextBlockUtils.bordered(textBlock, stroke, legendColor, legendBackgroundColor, 10); + return TextBlockUtils.withMargin(result, 8, 8); } } diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileIfDown.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileIfDown.java index 9ba9e999b..93493a0b3 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileIfDown.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileIfDown.java @@ -30,6 +30,7 @@ */ package net.sourceforge.plantuml.activitydiagram3.ftile.vcompact; +import java.awt.geom.Dimension2D; import java.awt.geom.Point2D; import java.util.ArrayList; import java.util.HashSet; @@ -50,6 +51,8 @@ import net.sourceforge.plantuml.activitydiagram3.ftile.FtileGeometry; import net.sourceforge.plantuml.activitydiagram3.ftile.FtileUtils; import net.sourceforge.plantuml.activitydiagram3.ftile.Snake; import net.sourceforge.plantuml.activitydiagram3.ftile.Swimlane; +import net.sourceforge.plantuml.activitydiagram3.ftile.vertical.FtileDiamond; +import net.sourceforge.plantuml.activitydiagram3.ftile.vertical.FtileDiamondInside; import net.sourceforge.plantuml.graphic.Rainbow; import net.sourceforge.plantuml.graphic.StringBounder; import net.sourceforge.plantuml.ugraphic.UEmpty; @@ -104,11 +107,50 @@ public class FtileIfDown extends AbstractFtile { } else { conns.add(result.new ConnectionElseNoDiamond(elseColor)); } + } else { + conns.add(result.new ConnectionHorizontal(elseColor)); } conns.add(result.new ConnectionOut(thenBlock.getOutLinkRendering().getRainbow(arrowColor))); return FtileUtils.addConnection(result, conns); } + class ConnectionHorizontal extends AbstractConnection { + + private final Rainbow color; + + public ConnectionHorizontal(Rainbow color) { + super(diamond1, optionalStop); + this.color = color; + } + + public void drawU(UGraphic ug) { + final StringBounder stringBounder = ug.getStringBounder(); + final Point2D p1 = getP1(stringBounder); + final Point2D p2 = getP2(stringBounder); + // p2 = new Point2D.Double(p2.getX(), p1.getY()); + + final Snake snake = new Snake(color, Arrows.asToRight()); + snake.addPoint(p1); + snake.addPoint(p2); + ug.draw(snake); + } + + private Point2D getP1(StringBounder stringBounder) { + final FtileGeometry dimDiamond1 = getFtile1().calculateDimension(stringBounder); + final Point2D p = new Point2D.Double(dimDiamond1.getWidth(), + (dimDiamond1.getInY() + dimDiamond1.getOutY()) / 2); + + return getTranslateDiamond1(stringBounder).getTranslated(p); + } + + private Point2D getP2(StringBounder stringBounder) { + final Dimension2D dimStop = getFtile2().calculateDimension(stringBounder); + final Point2D p = new Point2D.Double(0, dimStop.getHeight() / 2); + return getTranslateOptionalStop(stringBounder).getTranslated(p); + } + + } + class ConnectionIn extends AbstractConnection implements ConnectionTranslatable { private final Rainbow arrowColor; @@ -290,11 +332,31 @@ public class FtileIfDown extends AbstractFtile { final FtileGeometry geoDiamond2 = diamond2.calculateDimension(stringBounder); final FtileGeometry geo = geoDiamond1.appendBottom(geoThen).appendBottom(geoDiamond2); final double height = geo.getHeight() + 4 * Diamond.diamondHalfSize; - return new FtileGeometry(geo.getWidth() + Diamond.diamondHalfSize, height, geo.getLeft(), geoDiamond1.getInY(), - height); + double width = geo.getWidth() + Diamond.diamondHalfSize; + if (optionalStop != null) { + width += optionalStop.calculateDimension(stringBounder).getWidth() + getAdditionalWidth(stringBounder); + } + return new FtileGeometry(width, height, geo.getLeft(), geoDiamond1.getInY(), height); } + private double getAdditionalWidth(StringBounder stringBounder) { + final FtileGeometry dimStop = optionalStop.calculateDimension(stringBounder); + final double val1 = getEastLabelWidth(stringBounder); + final double stopWidth = dimStop.getWidth(); + return Math.max(stopWidth, val1 + stopWidth / 2); + } + + private double getEastLabelWidth(StringBounder stringBounder) { + if (diamond1 instanceof FtileDiamondInside) { + return ((FtileDiamondInside) diamond1).getEastLabelWidth(stringBounder); + } + if (diamond1 instanceof FtileDiamond) { + return ((FtileDiamond) diamond1).getEastLabelWidth(stringBounder); + } + return 0; + } + @Override public UTranslate getTranslateFor(Ftile child, StringBounder stringBounder) { if (child == thenBlock) { @@ -338,8 +400,11 @@ public class FtileIfDown extends AbstractFtile { private UTranslate getTranslateOptionalStop(StringBounder stringBounder) { final FtileGeometry dimTotal = calculateDimension(stringBounder); final FtileGeometry dimDiamond1 = diamond1.calculateDimension(stringBounder); - final double y1 = 0; - final double x1 = dimTotal.getLeft() - dimDiamond1.getLeft() + dimDiamond1.getWidth(); + final FtileGeometry dimStop = optionalStop.calculateDimension(stringBounder); + final double labelNorth = dimDiamond1.getInY(); + final double y1 = labelNorth + (dimDiamond1.getHeight() - labelNorth - dimStop.getHeight()) / 2; + final double x1 = dimTotal.getLeft() - dimDiamond1.getLeft() + dimDiamond1.getWidth() + + getAdditionalWidth(stringBounder); return new UTranslate(x1, y1); } diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/cond/ConditionalBuilder.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/cond/ConditionalBuilder.java index d9deca238..1b3c46548 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/cond/ConditionalBuilder.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/cond/ConditionalBuilder.java @@ -102,18 +102,18 @@ public class ConditionalBuilder { ISkinParam skinParam, StringBounder stringBounder, FontConfiguration fcArrow, FontConfiguration fcTest) { final ConditionalBuilder builder = new ConditionalBuilder(swimlane, borderColor, backColor, arrowColor, ftileFactory, conditionStyle, branch1, branch2, skinParam, stringBounder, fcArrow, fcTest); -// if (isEmptyOrOnlySingleStop(branch2) && isEmptyOrOnlySingleStop(branch1) == false) { -// return builder.createDown(builder.branch1, builder.branch2); -// } -// if (branch1.isEmpty() && branch2.isOnlySingleStop()) { -// return builder.createDown(builder.branch1, builder.branch2); -// } -// if (isEmptyOrOnlySingleStop(branch1) && isEmptyOrOnlySingleStop(branch2) == false) { -// return builder.createDown(builder.branch2, builder.branch1); -// } -// if (branch2.isEmpty() && branch1.isOnlySingleStop()) { -// return builder.createDown(builder.branch2, builder.branch1); -// } + if (isEmptyOrOnlySingleStop(branch2) && isEmptyOrOnlySingleStop(branch1) == false) { + return builder.createDown(builder.branch1, builder.branch2); + } + if (branch1.isEmpty() && branch2.isOnlySingleStop()) { + return builder.createDown(builder.branch1, builder.branch2); + } + if (isEmptyOrOnlySingleStop(branch1) && isEmptyOrOnlySingleStop(branch2) == false) { + return builder.createDown(builder.branch2, builder.branch1); + } + if (branch2.isEmpty() && branch1.isOnlySingleStop()) { + return builder.createDown(builder.branch2, builder.branch1); + } return builder.createWithLinks(); // return builder.createWithDiamonds(); // return builder.createNude(); diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vertical/FtileDiamond.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vertical/FtileDiamond.java index 90f18e35b..49bfce2ca 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vertical/FtileDiamond.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vertical/FtileDiamond.java @@ -146,4 +146,9 @@ public class FtileDiamond extends AbstractFtile { return withWest(tb1).withEast(tb2); } + public double getEastLabelWidth(StringBounder stringBounder) { + final Dimension2D dimEast = east1.calculateDimension(stringBounder); + return dimEast.getWidth(); + } + } diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vertical/FtileDiamondInside.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vertical/FtileDiamondInside.java index 54c27e116..4e3759b84 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vertical/FtileDiamondInside.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vertical/FtileDiamondInside.java @@ -159,4 +159,9 @@ public class FtileDiamondInside extends AbstractFtile { // return dimDiamonAlone.incHeight(northHeight).addMarginX(dimWest.getWidth(), dimEast.getWidth()); } + public double getEastLabelWidth(StringBounder stringBounder) { + final Dimension2D dimEast = east.calculateDimension(stringBounder); + return dimEast.getWidth(); + } + } diff --git a/src/net/sourceforge/plantuml/classdiagram/ClassDiagram.java b/src/net/sourceforge/plantuml/classdiagram/ClassDiagram.java index 5acad302f..aa87a7739 100644 --- a/src/net/sourceforge/plantuml/classdiagram/ClassDiagram.java +++ b/src/net/sourceforge/plantuml/classdiagram/ClassDiagram.java @@ -210,8 +210,7 @@ public class ClassDiagram extends AbstractClassOrObjectDiagram { final RowLayout rawLayout = getRawLayout(i); fullLayout.addRowLayout(rawLayout); } - final ImageBuilder imageBuilder = new ImageBuilder(getSkinParam().getColorMapper(), 1, HtmlColorUtils.WHITE, - null, null, 0, 10, null, getSkinParam().handwritten()); + final ImageBuilder imageBuilder = new ImageBuilder(getSkinParam(), 1, null, null, 0, 10, null); imageBuilder.setUDrawable(fullLayout); return imageBuilder.writeImageTOBEMOVED(fileFormatOption, os); } @@ -230,7 +229,6 @@ public class ClassDiagram extends AbstractClassOrObjectDiagram { return new EntityImageClass(null, entity, getSkinParam(), this); } - @Override public String checkFinalError() { for (Link link : this.getLinks()) { diff --git a/src/net/sourceforge/plantuml/classdiagram/command/CommandHideShow.java b/src/net/sourceforge/plantuml/classdiagram/command/CommandHideShowByGender.java similarity index 89% rename from src/net/sourceforge/plantuml/classdiagram/command/CommandHideShow.java rename to src/net/sourceforge/plantuml/classdiagram/command/CommandHideShowByGender.java index 090a4c39e..dda81e8f6 100644 --- a/src/net/sourceforge/plantuml/classdiagram/command/CommandHideShow.java +++ b/src/net/sourceforge/plantuml/classdiagram/command/CommandHideShowByGender.java @@ -35,7 +35,6 @@ import java.util.Set; import net.sourceforge.plantuml.StringUtils; import net.sourceforge.plantuml.UmlDiagram; -import net.sourceforge.plantuml.classdiagram.ClassDiagram; import net.sourceforge.plantuml.command.CommandExecutionResult; import net.sourceforge.plantuml.command.SingleLineCommand2; import net.sourceforge.plantuml.command.regex.RegexConcat; @@ -49,15 +48,16 @@ import net.sourceforge.plantuml.cucadiagram.EntityUtils; import net.sourceforge.plantuml.cucadiagram.IEntity; import net.sourceforge.plantuml.cucadiagram.LeafType; import net.sourceforge.plantuml.descdiagram.DescriptionDiagram; +import net.sourceforge.plantuml.objectdiagram.AbstractClassOrObjectDiagram; -public class CommandHideShow extends SingleLineCommand2 { +public class CommandHideShowByGender extends SingleLineCommand2 { private static final EnumSet PORTION_METHOD = EnumSet. of(EntityPortion.METHOD); private static final EnumSet PORTION_MEMBER = EnumSet. of(EntityPortion.FIELD, EntityPortion.METHOD); private static final EnumSet PORTION_FIELD = EnumSet. of(EntityPortion.FIELD); - public CommandHideShow() { + public CommandHideShowByGender() { super(getRegexConcat()); } @@ -66,7 +66,7 @@ public class CommandHideShow extends SingleLineCommand2 { new RegexLeaf("COMMAND", "(hide|show)"), // new RegexLeaf("[%s]+"), // new RegexLeaf("GENDER", - "(?:(class|interface|enum|annotation|abstract|[\\p{L}0-9_.]+|[%g][^%g]+[%g]|\\<\\<.*\\>\\>)[%s]+)*?"), // + "(?:(class|object|interface|enum|annotation|abstract|[\\p{L}0-9_.]+|[%g][^%g]+[%g]|\\<\\<.*\\>\\>)[%s]+)*?"), // new RegexLeaf("EMPTY", "(?:(empty)[%s]+)?"), // new RegexLeaf("PORTION", "(members?|attributes?|fields?|methods?|circle\\w*|stereotypes?)"), // new RegexLeaf("$")); @@ -87,8 +87,8 @@ public class CommandHideShow extends SingleLineCommand2 { @Override protected CommandExecutionResult executeArg(UmlDiagram classDiagram, RegexResult arg) { - if (classDiagram instanceof ClassDiagram) { - return executeClassDiagram((ClassDiagram) classDiagram, arg); + if (classDiagram instanceof AbstractClassOrObjectDiagram) { + return executeClassDiagram((AbstractClassOrObjectDiagram) classDiagram, arg); } if (classDiagram instanceof DescriptionDiagram) { return executeDescriptionDiagram((DescriptionDiagram) classDiagram, arg); @@ -105,6 +105,8 @@ public class CommandHideShow extends SingleLineCommand2 { gender = EntityGenderUtils.all(); } else if (arg1.equalsIgnoreCase("class")) { gender = EntityGenderUtils.byEntityType(LeafType.CLASS); + } else if (arg1.equalsIgnoreCase("object")) { + gender = EntityGenderUtils.byEntityType(LeafType.OBJECT); } else if (arg1.equalsIgnoreCase("interface")) { gender = EntityGenderUtils.byEntityType(LeafType.INTERFACE); } else if (arg1.equalsIgnoreCase("enum")) { @@ -124,7 +126,7 @@ public class CommandHideShow extends SingleLineCommand2 { return CommandExecutionResult.ok(); } - private CommandExecutionResult executeClassDiagram(ClassDiagram classDiagram, RegexResult arg) { + private CommandExecutionResult executeClassDiagram(AbstractClassOrObjectDiagram classDiagram, RegexResult arg) { final Set portion = getEntityPortion(arg.get("PORTION", 0)); @@ -134,6 +136,8 @@ public class CommandHideShow extends SingleLineCommand2 { gender = EntityGenderUtils.all(); } else if (arg1.equalsIgnoreCase("class")) { gender = EntityGenderUtils.byEntityType(LeafType.CLASS); + } else if (arg1.equalsIgnoreCase("object")) { + gender = EntityGenderUtils.byEntityType(LeafType.OBJECT); } else if (arg1.equalsIgnoreCase("interface")) { gender = EntityGenderUtils.byEntityType(LeafType.INTERFACE); } else if (arg1.equalsIgnoreCase("enum")) { diff --git a/src/net/sourceforge/plantuml/classdiagram/command/CommandHideShow3.java b/src/net/sourceforge/plantuml/classdiagram/command/CommandHideShowByVisibility.java similarity index 97% rename from src/net/sourceforge/plantuml/classdiagram/command/CommandHideShow3.java rename to src/net/sourceforge/plantuml/classdiagram/command/CommandHideShowByVisibility.java index 4274a1e90..e075d34a9 100644 --- a/src/net/sourceforge/plantuml/classdiagram/command/CommandHideShow3.java +++ b/src/net/sourceforge/plantuml/classdiagram/command/CommandHideShowByVisibility.java @@ -45,14 +45,14 @@ import net.sourceforge.plantuml.command.regex.RegexResult; import net.sourceforge.plantuml.cucadiagram.EntityPortion; import net.sourceforge.plantuml.skin.VisibilityModifier; -public class CommandHideShow3 extends SingleLineCommand2 { +public class CommandHideShowByVisibility extends SingleLineCommand2 { private static final EnumSet PORTION_METHOD = EnumSet. of(EntityPortion.METHOD); private static final EnumSet PORTION_MEMBER = EnumSet. of(EntityPortion.FIELD, EntityPortion.METHOD); private static final EnumSet PORTION_FIELD = EnumSet. of(EntityPortion.FIELD); - public CommandHideShow3() { + public CommandHideShowByVisibility() { super(getRegexConcat()); } diff --git a/src/net/sourceforge/plantuml/code/CompressionZlib.java b/src/net/sourceforge/plantuml/code/CompressionZlib.java index 986cbc156..d2b9b913b 100644 --- a/src/net/sourceforge/plantuml/code/CompressionZlib.java +++ b/src/net/sourceforge/plantuml/code/CompressionZlib.java @@ -37,8 +37,8 @@ import java.util.zip.Inflater; public class CompressionZlib implements Compression { - // private static final int COMPRESSION_LEVEL = 9; - private static final int COMPRESSION_LEVEL = 1; + private static final int COMPRESSION_LEVEL = 9; + // private static final int COMPRESSION_LEVEL = 1; public byte[] compress(byte[] in) { if (in.length == 0) { diff --git a/src/net/sourceforge/plantuml/command/CommandSpriteFile.java b/src/net/sourceforge/plantuml/command/CommandSpriteFile.java index 778cb7ead..4bd307763 100644 --- a/src/net/sourceforge/plantuml/command/CommandSpriteFile.java +++ b/src/net/sourceforge/plantuml/command/CommandSpriteFile.java @@ -32,18 +32,24 @@ package net.sourceforge.plantuml.command; import java.awt.image.BufferedImage; import java.io.File; +import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; import javax.imageio.ImageIO; import net.sourceforge.plantuml.FileSystem; +import net.sourceforge.plantuml.FileUtils; import net.sourceforge.plantuml.Log; import net.sourceforge.plantuml.UmlDiagram; import net.sourceforge.plantuml.command.regex.RegexConcat; import net.sourceforge.plantuml.command.regex.RegexLeaf; import net.sourceforge.plantuml.command.regex.RegexResult; +import net.sourceforge.plantuml.ugraphic.sprite.Sprite; import net.sourceforge.plantuml.ugraphic.sprite.SpriteImage; +import net.sourceforge.plantuml.ugraphic.sprite.SpriteSvg; public class CommandSpriteFile extends SingleLineCommand2 { @@ -63,7 +69,7 @@ public class CommandSpriteFile extends SingleLineCommand2 { @Override protected CommandExecutionResult executeArg(UmlDiagram system, RegexResult arg) { final String src = arg.get("FILE", 0); - final BufferedImage im; + final Sprite sprite; try { if (src.startsWith("jar:")) { final String inner = src.substring(4) + ".png"; @@ -71,20 +77,65 @@ public class CommandSpriteFile extends SingleLineCommand2 { if (is == null) { return CommandExecutionResult.error("No such internal sprite: " + inner); } - im = ImageIO.read(is); + sprite = new SpriteImage(ImageIO.read(is)); + } else if (src.contains("~")) { + final int idx = src.lastIndexOf("~"); + final File f = FileSystem.getInstance().getFile(src.substring(0, idx)); + if (f.exists() == false) { + return CommandExecutionResult.error("File does not exist: " + src); + } + final String name = src.substring(idx + 1); + sprite = getImageFromZip(f, name); + if (sprite == null) { + return CommandExecutionResult.error("No image " + name + " in " + f.getAbsolutePath()); + } } else { final File f = FileSystem.getInstance().getFile(src); if (f.exists() == false) { return CommandExecutionResult.error("File does not exist: " + src); } - im = ImageIO.read(f); + if (isSvg(f.getName())) { + sprite = new SpriteSvg(f); + } else { + sprite = new SpriteImage(ImageIO.read(f)); + } } } catch (IOException e) { Log.error("Error reading " + src + " " + e); return CommandExecutionResult.error("Cannot read: " + src); } - system.addSprite(arg.get("NAME", 0), new SpriteImage(im)); + system.addSprite(arg.get("NAME", 0), sprite); return CommandExecutionResult.ok(); } + private Sprite getImageFromZip(File f, String name) throws IOException { + ZipInputStream zis = null; + try { + zis = new ZipInputStream(new FileInputStream(f)); + ZipEntry ze = zis.getNextEntry(); + + while (ze != null) { + final String fileName = ze.getName(); + if (ze.isDirectory()) { + } else if (fileName.equals(name)) { + if (isSvg(name)) { + return new SpriteSvg(FileUtils.readSvg(zis)); + } else { + return new SpriteImage(ImageIO.read(zis)); + } + } + ze = zis.getNextEntry(); + } + } finally { + if (zis != null) { + zis.closeEntry(); + zis.close(); + } + } + return null; + } + + private boolean isSvg(String name) { + return name.toLowerCase().endsWith(".svg"); + } } diff --git a/src/net/sourceforge/plantuml/command/UmlDiagramFactory.java b/src/net/sourceforge/plantuml/command/UmlDiagramFactory.java index 38f868687..3452ab51c 100644 --- a/src/net/sourceforge/plantuml/command/UmlDiagramFactory.java +++ b/src/net/sourceforge/plantuml/command/UmlDiagramFactory.java @@ -43,8 +43,8 @@ import net.sourceforge.plantuml.NewpagedDiagram; import net.sourceforge.plantuml.OptionFlags; import net.sourceforge.plantuml.PSystemError; import net.sourceforge.plantuml.StringUtils; -import net.sourceforge.plantuml.classdiagram.command.CommandHideShow; -import net.sourceforge.plantuml.classdiagram.command.CommandHideShow3; +import net.sourceforge.plantuml.classdiagram.command.CommandHideShowByGender; +import net.sourceforge.plantuml.classdiagram.command.CommandHideShowByVisibility; import net.sourceforge.plantuml.core.Diagram; import net.sourceforge.plantuml.core.DiagramType; import net.sourceforge.plantuml.core.UmlSource; @@ -290,8 +290,8 @@ public abstract class UmlDiagramFactory extends PSystemAbstractFactory { cmds.add(factorySpriteCommand.createSingleLine()); cmds.add(new CommandSpriteFile()); - cmds.add(new CommandHideShow3()); - cmds.add(new CommandHideShow()); + cmds.add(new CommandHideShowByVisibility()); + cmds.add(new CommandHideShowByGender()); } diff --git a/src/net/sourceforge/plantuml/cucadiagram/Bodier.java b/src/net/sourceforge/plantuml/cucadiagram/Bodier.java index 5e12bb463..19051ce92 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/Bodier.java +++ b/src/net/sourceforge/plantuml/cucadiagram/Bodier.java @@ -40,8 +40,8 @@ import net.sourceforge.plantuml.ISkinParam; import net.sourceforge.plantuml.StringUtils; import net.sourceforge.plantuml.graphic.HorizontalAlignment; import net.sourceforge.plantuml.graphic.TextBlock; +import net.sourceforge.plantuml.graphic.TextBlockLineBefore; import net.sourceforge.plantuml.graphic.TextBlockUtils; -import net.sourceforge.plantuml.graphic.TextBlockVertical2; import net.sourceforge.plantuml.skin.VisibilityModifier; public class Bodier { @@ -166,14 +166,19 @@ public class Bodier { } return null; } - final MethodsOrFieldsArea fields = new MethodsOrFieldsArea(getFieldsToDisplay(), fontParam, skinParam, stereotype); + final MethodsOrFieldsArea fields = new MethodsOrFieldsArea(getFieldsToDisplay(), fontParam, skinParam, + stereotype); if (type == LeafType.OBJECT) { + if (showFields == false) { + return new TextBlockLineBefore(TextBlockUtils.empty(0, 0)); + } return fields.asBlockMemberImpl(); } if (type.isLikeClass() == false) { throw new UnsupportedOperationException(); } - final MethodsOrFieldsArea methods = new MethodsOrFieldsArea(getMethodsToDisplay(), fontParam, skinParam, stereotype); + final MethodsOrFieldsArea methods = new MethodsOrFieldsArea(getMethodsToDisplay(), fontParam, skinParam, + stereotype); if (showFields && showMethods == false) { return fields.asBlockMemberImpl(); } else if (showMethods && showFields == false) { @@ -184,7 +189,7 @@ public class Bodier { final TextBlock bb1 = fields.asBlockMemberImpl(); final TextBlock bb2 = methods.asBlockMemberImpl(); - return new TextBlockVertical2(bb1, bb2, HorizontalAlignment.LEFT); + return TextBlockUtils.mergeTB(bb1, bb2, HorizontalAlignment.LEFT); } } diff --git a/src/net/sourceforge/plantuml/cucadiagram/Display.java b/src/net/sourceforge/plantuml/cucadiagram/Display.java index 732f12450..8cba93daf 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/Display.java +++ b/src/net/sourceforge/plantuml/cucadiagram/Display.java @@ -75,10 +75,6 @@ public class Display implements Iterable { private final boolean isNull; private final CreoleMode defaultCreoleMode; - // public void setDefaultCreoleMode(CreoleMode defaultCreoleMode) { - // this.defaultCreoleMode = defaultCreoleMode; - // } - public Display removeUrlHiddenNewLineUrl() { final String full = UrlBuilder.purgeUrl(asStringWithHiddenNewLine()); return new Display(StringUtils.splitHiddenNewLine(full), this.naturalHorizontalAlignment, this.isNull, @@ -190,6 +186,19 @@ public class Display implements Iterable { return result; } + public Display manageGuillemet() { + final List result = new ArrayList(); + for (CharSequence line : display) { + final String withGuillement = StringUtils.manageGuillemet(line.toString()); + if (withGuillement.equals(line.toString())) { + result.add(line); + } else { + result.add(withGuillement); + } + } + return new Display(result, this.naturalHorizontalAlignment, this.isNull, this.defaultCreoleMode); + } + public Display underlined() { final List result = new ArrayList(); for (CharSequence line : display) { diff --git a/src/net/sourceforge/plantuml/cucadiagram/DisplayPositionned.java b/src/net/sourceforge/plantuml/cucadiagram/DisplayPositionned.java index 7301f5be7..ba66ab86f 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/DisplayPositionned.java +++ b/src/net/sourceforge/plantuml/cucadiagram/DisplayPositionned.java @@ -30,7 +30,12 @@ */ package net.sourceforge.plantuml.cucadiagram; +import net.sourceforge.plantuml.FontParam; +import net.sourceforge.plantuml.ISkinParam; +import net.sourceforge.plantuml.graphic.FontConfiguration; import net.sourceforge.plantuml.graphic.HorizontalAlignment; +import net.sourceforge.plantuml.graphic.TextBlock; +import net.sourceforge.plantuml.graphic.TextBlockUtils; import net.sourceforge.plantuml.graphic.VerticalAlignment; public class DisplayPositionned { diff --git a/src/net/sourceforge/plantuml/cucadiagram/Link.java b/src/net/sourceforge/plantuml/cucadiagram/Link.java index 291e3b3d7..4cc1146b1 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/Link.java +++ b/src/net/sourceforge/plantuml/cucadiagram/Link.java @@ -116,9 +116,9 @@ public class Link implements Hideable, Removeable { this.label = Display.NULL; } else if (doWeHaveToRemoveUrlAtStart(label)) { this.url = label.initUrl(); - this.label = label.removeHeadingUrl(url); + this.label = label.removeHeadingUrl(url).manageGuillemet(); } else { - this.label = label; + this.label = label.manageGuillemet(); } this.length = length; this.qualifier1 = qualifier1; diff --git a/src/net/sourceforge/plantuml/cucadiagram/Stereotype.java b/src/net/sourceforge/plantuml/cucadiagram/Stereotype.java index b229145ae..483768d1d 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/Stereotype.java +++ b/src/net/sourceforge/plantuml/cucadiagram/Stereotype.java @@ -154,7 +154,7 @@ public class Stereotype implements CharSequence, Hideable { public List getMultipleLabels() { final List result = new ArrayList(); if (label != null) { - final Pattern p = Pattern.compile("\\<\\<\\s?([^<>]+?)\\s?\\>\\>"); + final Pattern p = Pattern.compile("\\<\\<\\s?((?:\\<&\\w+\\>|[^<>])+?)\\s?\\>\\>"); final Matcher m = p.matcher(label); while (m.find()) { result.add(m.group(1)); diff --git a/src/net/sourceforge/plantuml/descdiagram/command/CommandCreateElementFull.java b/src/net/sourceforge/plantuml/descdiagram/command/CommandCreateElementFull.java index 7065fbf62..69258753e 100644 --- a/src/net/sourceforge/plantuml/descdiagram/command/CommandCreateElementFull.java +++ b/src/net/sourceforge/plantuml/descdiagram/command/CommandCreateElementFull.java @@ -55,7 +55,7 @@ import net.sourceforge.plantuml.graphic.color.Colors; public class CommandCreateElementFull extends SingleLineCommand2 { - public static final String ALL_TYPES = "artifact|actor|folder|package|rectangle|node|frame|cloud|database|queue|storage|agent|usecase|component|boundary|control|entity|interface"; + public static final String ALL_TYPES = "artifact|actor|folder|file|package|rectangle|node|frame|cloud|database|queue|storage|agent|usecase|component|boundary|control|entity|interface"; public CommandCreateElementFull() { super(getRegexConcat()); @@ -143,6 +143,9 @@ public class CommandCreateElementFull extends SingleLineCommand2 quotes = Arrays + static final List quotes = Arrays .asList(// "He's dead, Jim.", // "By Grabthar's hammer, by the sons of Worvan, you shall be avenged.", // @@ -154,7 +154,7 @@ public class QuoteUtils { "In space no one can hear you scream", // "I can't lie to you about your chances, but... you have my sympathies.", // "There is an explanation for this, you know.", // - "Bishop: I'm afraid I have some bad news.", // + "I'm afraid I have some bad news.", // "Do me a favour. Disconnect me. I could be reworked, but I'll never be top of the line again.", // "Take it easy, don't push the little button on the joystick!", // "I'm a very private person.", // @@ -164,7 +164,7 @@ public class QuoteUtils { "United we stand", // "We shall never surrender", // "Absolute honesty isn't always the most diplomatic nor the safest form of communication with emotional beings.", // - "Humor: seventy-five percent. [Confirmed] Self destruct sequence in T minus 10, 9... ", // + // "Humor: seventy-five percent. [Confirmed] Self destruct sequence in T minus 10, 9... ", // "It's... complicated.", // "Do not open until 1985", // "I still mess up but I'll just start again", // @@ -183,11 +183,19 @@ public class QuoteUtils { "Winter is coming", // "What fools these mortals be!", // "Something wicked this way comes.", // - "I think I get it, what was it? Poker Night? Bachelor Party?", // + "I think I get it, what was it? Poker Night? Bachelor Party?", // "It's alright to be scared. Remember, there is no courage without fear.", // "Through readiness and discipline we are masters of our fate.", // "With great power comes great responsibility", // - "If a machine can learn the value of human life, maybe we can too ?" // + "If a machine can learn the value of human life, maybe we can too ?", // + "Only going forward 'cause we can't find reverse.", // + "We're not gonna sit in silence, we're not gonna live with fear", // + "Bon, dans dix minutes je nous considere comme definitivement perdus.", // + "Ca sera surement bien quand ca sera fini.", // + "It's the last piece of the puzzle but you just can't make it fit", // + "Doctor says you're cured but you still feel the pain", // + "Is artificial intelligence the exact opposite of natural stupidity ?", // + "Forcement, ca depend, ca depasse..." // ); private QuoteUtils() { diff --git a/src/net/sourceforge/plantuml/graphic/SimpleTextBlockBordered.java b/src/net/sourceforge/plantuml/graphic/SimpleTextBlockBordered.java new file mode 100644 index 000000000..5008a1500 --- /dev/null +++ b/src/net/sourceforge/plantuml/graphic/SimpleTextBlockBordered.java @@ -0,0 +1,61 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2017, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * This file is part of PlantUML. + * + * PlantUML is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PlantUML distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.graphic; + +import java.awt.geom.Dimension2D; + +import net.sourceforge.plantuml.Dimension2DDouble; +import net.sourceforge.plantuml.ugraphic.UChangeColor; +import net.sourceforge.plantuml.ugraphic.UGraphic; +import net.sourceforge.plantuml.ugraphic.URectangle; +import net.sourceforge.plantuml.ugraphic.UTranslate; + +class SimpleTextBlockBordered extends AbstractTextBlock implements TextBlock { + + private final TextBlock textBlock; + private final HtmlColor color; + + public SimpleTextBlockBordered(TextBlock textBlock, HtmlColor color) { + this.textBlock = textBlock; + this.color = color; + } + + public Dimension2D calculateDimension(StringBounder stringBounder) { + final Dimension2D dim = textBlock.calculateDimension(stringBounder); + return Dimension2DDouble.delta(dim, 1, 1); + } + + public void drawU(UGraphic ug) { + final Dimension2D dim = textBlock.calculateDimension(ug.getStringBounder()); + textBlock.drawU(ug.apply(new UTranslate(1, 1))); + ug.apply(new UChangeColor(color)).draw(new URectangle(dim.getWidth(), dim.getHeight())); + } +} \ No newline at end of file diff --git a/src/net/sourceforge/plantuml/graphic/SkinParameter.java b/src/net/sourceforge/plantuml/graphic/SkinParameter.java index 3a0eddc8a..7adf8fca7 100644 --- a/src/net/sourceforge/plantuml/graphic/SkinParameter.java +++ b/src/net/sourceforge/plantuml/graphic/SkinParameter.java @@ -68,6 +68,9 @@ public class SkinParameter { public static final SkinParameter FOLDER = new SkinParameter("FOLDER", ColorParam.folderBackground, ColorParam.folderBorder, FontParam.FOLDER, FontParam.FOLDER_STEREOTYPE); + public static final SkinParameter FILE = new SkinParameter("FILE", ColorParam.fileBackground, + ColorParam.fileBorder, FontParam.FILE, FontParam.FILE_STEREOTYPE); + public static final SkinParameter PACKAGE = new SkinParameter("PACKAGE", ColorParam.packageBackground, ColorParam.packageBorder, FontParam.FOLDER, FontParam.FOLDER_STEREOTYPE); diff --git a/src/net/sourceforge/plantuml/graphic/TextBlockBordered.java b/src/net/sourceforge/plantuml/graphic/TextBlockBordered.java index 8ba35fc39..6deb63109 100644 --- a/src/net/sourceforge/plantuml/graphic/TextBlockBordered.java +++ b/src/net/sourceforge/plantuml/graphic/TextBlockBordered.java @@ -33,29 +33,79 @@ package net.sourceforge.plantuml.graphic; import java.awt.geom.Dimension2D; import net.sourceforge.plantuml.Dimension2DDouble; +import net.sourceforge.plantuml.ugraphic.Shadowable; +import net.sourceforge.plantuml.ugraphic.UChangeBackColor; import net.sourceforge.plantuml.ugraphic.UChangeColor; import net.sourceforge.plantuml.ugraphic.UGraphic; import net.sourceforge.plantuml.ugraphic.URectangle; +import net.sourceforge.plantuml.ugraphic.UStroke; import net.sourceforge.plantuml.ugraphic.UTranslate; -class TextBlockBordered extends AbstractTextBlock implements TextBlock { +public class TextBlockBordered extends AbstractTextBlock implements TextBlock { + + private final double cornersize; + private final HtmlColor backgroundColor; + private final HtmlColor borderColor; + private final int marginX = 6; + private final int marginY = 5; + private final UStroke stroke; + private final boolean withShadow; private final TextBlock textBlock; - private final HtmlColor color; - public TextBlockBordered(TextBlock textBlock, HtmlColor color) { + TextBlockBordered(TextBlock textBlock, UStroke stroke, HtmlColor borderColor, HtmlColor backgroundColor, + double cornersize) { + this.cornersize = cornersize; this.textBlock = textBlock; - this.color = color; + this.withShadow = false; + this.stroke = stroke; + this.borderColor = borderColor; + this.backgroundColor = backgroundColor; + } + + private double getTextHeight(StringBounder stringBounder) { + final Dimension2D size = textBlock.calculateDimension(stringBounder); + return size.getHeight() + 2 * marginY; + } + + private double getPureTextWidth(StringBounder stringBounder) { + final Dimension2D size = textBlock.calculateDimension(stringBounder); + return size.getWidth(); + } + + private double getTextWidth(StringBounder stringBounder) { + return getPureTextWidth(stringBounder) + 2 * marginX; } public Dimension2D calculateDimension(StringBounder stringBounder) { - final Dimension2D dim = textBlock.calculateDimension(stringBounder); - return Dimension2DDouble.delta(dim, 1, 1); + final double height = getTextHeight(stringBounder); + final double width = getTextWidth(stringBounder); + return new Dimension2DDouble(width + 1, height + 1); + } + + private UGraphic applyStroke(UGraphic ug) { + if (stroke == null) { + return ug; + } + return ug.apply(stroke); } public void drawU(UGraphic ug) { - final Dimension2D dim = textBlock.calculateDimension(ug.getStringBounder()); - textBlock.drawU(ug.apply(new UTranslate(1, 1))); - ug.apply(new UChangeColor(color)).draw(new URectangle(dim.getWidth(), dim.getHeight())); + final StringBounder stringBounder = ug.getStringBounder(); + final Shadowable polygon = getPolygonNormal(stringBounder); + if (withShadow) { + polygon.setDeltaShadow(4); + } + ug = ug.apply(new UChangeBackColor(backgroundColor)).apply(new UChangeColor(borderColor)); + ug = applyStroke(ug); + ug.draw(polygon); + textBlock.drawU(ug.apply(new UTranslate(marginX, marginY))); } -} \ No newline at end of file + + private Shadowable getPolygonNormal(final StringBounder stringBounder) { + final double height = getTextHeight(stringBounder); + final double width = getTextWidth(stringBounder); + return new URectangle(width, height, cornersize, cornersize); + } + +} diff --git a/src/net/sourceforge/plantuml/graphic/TextBlockHorizontal.java b/src/net/sourceforge/plantuml/graphic/TextBlockHorizontal.java index 49c59525d..98208cb41 100644 --- a/src/net/sourceforge/plantuml/graphic/TextBlockHorizontal.java +++ b/src/net/sourceforge/plantuml/graphic/TextBlockHorizontal.java @@ -42,7 +42,7 @@ class TextBlockHorizontal extends AbstractTextBlock implements TextBlock { private final TextBlock b2; private final VerticalAlignment alignment; - public TextBlockHorizontal(TextBlock b1, TextBlock b2, VerticalAlignment alignment) { + TextBlockHorizontal(TextBlock b1, TextBlock b2, VerticalAlignment alignment) { this.b1 = b1; this.b2 = b2; this.alignment = alignment; diff --git a/src/net/sourceforge/plantuml/graphic/TextBlockMarged.java b/src/net/sourceforge/plantuml/graphic/TextBlockMarged.java index 6d01f4187..77be4f1a3 100644 --- a/src/net/sourceforge/plantuml/graphic/TextBlockMarged.java +++ b/src/net/sourceforge/plantuml/graphic/TextBlockMarged.java @@ -47,7 +47,7 @@ class TextBlockMarged extends AbstractTextBlock implements TextBlock, WithPorts private final double y1; private final double y2; - public TextBlockMarged(TextBlock textBlock, double x1, double x2, double y1, double y2) { + TextBlockMarged(TextBlock textBlock, double x1, double x2, double y1, double y2) { this.textBlock = textBlock; this.x1 = x1; this.x2 = x2; diff --git a/src/net/sourceforge/plantuml/graphic/TextBlockMinWidth.java b/src/net/sourceforge/plantuml/graphic/TextBlockMinWidth.java index 04b7212fd..9e41bbd74 100644 --- a/src/net/sourceforge/plantuml/graphic/TextBlockMinWidth.java +++ b/src/net/sourceforge/plantuml/graphic/TextBlockMinWidth.java @@ -42,7 +42,7 @@ class TextBlockMinWidth extends AbstractTextBlock implements TextBlock { private final double minWidth; private final HorizontalAlignment horizontalAlignment; - public TextBlockMinWidth(TextBlock textBlock, double minWidth, HorizontalAlignment horizontalAlignment) { + TextBlockMinWidth(TextBlock textBlock, double minWidth, HorizontalAlignment horizontalAlignment) { this.textBlock = textBlock; this.minWidth = minWidth; this.horizontalAlignment = horizontalAlignment; diff --git a/src/net/sourceforge/plantuml/skin/rose/ComponentRoseTitle.java b/src/net/sourceforge/plantuml/graphic/TextBlockTitle.java similarity index 52% rename from src/net/sourceforge/plantuml/skin/rose/ComponentRoseTitle.java rename to src/net/sourceforge/plantuml/graphic/TextBlockTitle.java index b25ad8603..13143eaa8 100644 --- a/src/net/sourceforge/plantuml/skin/rose/ComponentRoseTitle.java +++ b/src/net/sourceforge/plantuml/graphic/TextBlockTitle.java @@ -28,42 +28,45 @@ * * */ -package net.sourceforge.plantuml.skin.rose; +package net.sourceforge.plantuml.graphic; +import java.awt.geom.Dimension2D; +import java.awt.geom.Rectangle2D; + +import net.sourceforge.plantuml.Dimension2DDouble; import net.sourceforge.plantuml.ISkinSimple; +import net.sourceforge.plantuml.creole.CreoleMode; import net.sourceforge.plantuml.cucadiagram.Display; -import net.sourceforge.plantuml.graphic.FontConfiguration; -import net.sourceforge.plantuml.graphic.HorizontalAlignment; -import net.sourceforge.plantuml.graphic.StringBounder; -import net.sourceforge.plantuml.graphic.TextBlock; -import net.sourceforge.plantuml.skin.AbstractTextualComponent; -import net.sourceforge.plantuml.skin.Area; import net.sourceforge.plantuml.ugraphic.UGraphic; import net.sourceforge.plantuml.ugraphic.UTranslate; -public class ComponentRoseTitle extends AbstractTextualComponent { +public class TextBlockTitle implements TextBlock { - private final int outMargin = 5; + private final double outMargin = 2; - public ComponentRoseTitle(FontConfiguration font, Display stringsToDisplay, ISkinSimple spriteContainer) { - super(stringsToDisplay, font, HorizontalAlignment.CENTER, 7, 7, 7, - spriteContainer, 0, false, null, null); + private final TextBlock textBlock; + + TextBlockTitle(FontConfiguration font, Display stringsToDisplay, ISkinSimple spriteContainer) { + if (stringsToDisplay.size() == 1 && stringsToDisplay.get(0).length() == 0) { + throw new IllegalArgumentException(); + } + textBlock = stringsToDisplay.create(font, HorizontalAlignment.CENTER, spriteContainer, 0, CreoleMode.FULL, + null, null); } - @Override - protected void drawInternalU(UGraphic ug, Area area) { - final TextBlock textBlock = getTextBlock(); - textBlock.drawU(ug.apply(new UTranslate(outMargin + getMarginX1(), getMarginY()))); + public final void drawU(UGraphic ug) { + textBlock.drawU(ug.apply(new UTranslate(outMargin, 0))); } - @Override - public double getPreferredHeight(StringBounder stringBounder) { - return getTextHeight(stringBounder); + public Dimension2D calculateDimension(StringBounder stringBounder) { + final Dimension2D textDim = textBlock.calculateDimension(stringBounder); + final double width = textDim.getWidth() + outMargin * 2; + final double height = textDim.getHeight(); + return new Dimension2DDouble(width, height); } - @Override - public double getPreferredWidth(StringBounder stringBounder) { - return getTextWidth(stringBounder) + outMargin * 2; + public Rectangle2D getInnerPosition(String member, StringBounder stringBounder) { + return null; } } diff --git a/src/net/sourceforge/plantuml/graphic/TextBlockUtils.java b/src/net/sourceforge/plantuml/graphic/TextBlockUtils.java index ab66e170e..bd9197de9 100644 --- a/src/net/sourceforge/plantuml/graphic/TextBlockUtils.java +++ b/src/net/sourceforge/plantuml/graphic/TextBlockUtils.java @@ -40,29 +40,59 @@ import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; +import net.sourceforge.plantuml.ColorParam; import net.sourceforge.plantuml.Dimension2DDouble; +import net.sourceforge.plantuml.ISkinParam; +import net.sourceforge.plantuml.LineParam; +import net.sourceforge.plantuml.cucadiagram.Display; import net.sourceforge.plantuml.posimo.Positionable; import net.sourceforge.plantuml.posimo.PositionableImpl; +import net.sourceforge.plantuml.skin.rose.Rose; import net.sourceforge.plantuml.ugraphic.LimitFinder; import net.sourceforge.plantuml.ugraphic.MinMax; import net.sourceforge.plantuml.ugraphic.UFont; import net.sourceforge.plantuml.ugraphic.UGraphic; +import net.sourceforge.plantuml.ugraphic.UStroke; public class TextBlockUtils { + public static TextBlock bordered(TextBlock textBlock, UStroke stroke, HtmlColor borderColor, + HtmlColor backgroundColor, double cornersize) { + return new TextBlockBordered(textBlock, stroke, borderColor, backgroundColor, cornersize); + } + + public static TextBlock title(FontConfiguration font, Display stringsToDisplay, ISkinParam skinParam) { + UStroke stroke = skinParam.getThickness(LineParam.titleBorder, null); + final Rose rose = new Rose(); + HtmlColor borderColor = rose.getHtmlColor(skinParam, ColorParam.titleBorder); + final HtmlColor backgroundColor = rose.getHtmlColor(skinParam, ColorParam.titleBackground); + final TextBlockTitle result = new TextBlockTitle(font, stringsToDisplay, skinParam); + if (stroke == null && borderColor == null) { + return result; + } + if (stroke == null) { + stroke = new UStroke(1.5); + } + if (borderColor == null) { + borderColor = HtmlColorUtils.BLACK; + } + final double corner = skinParam.getRoundCorner("titleBorder"); + return withMargin(bordered(result, stroke, borderColor, backgroundColor, corner), 2, 2); + } + public static TextBlock withMargin(TextBlock textBlock, double marginX, double marginY) { return new TextBlockMarged(textBlock, marginX, marginX, marginY, marginY); } - public static TextBlock withMinWidth(TextBlock textBlock, double minWidth, HorizontalAlignment horizontalAlignment) { - return new TextBlockMinWidth(textBlock, minWidth, horizontalAlignment); - } - public static TextBlock withMargin(TextBlock textBlock, double marginX1, double marginX2, double marginY1, double marginY2) { return new TextBlockMarged(textBlock, marginX1, marginX2, marginY1, marginY2); } + public static TextBlock withMinWidth(TextBlock textBlock, double minWidth, HorizontalAlignment horizontalAlignment) { + return new TextBlockMinWidth(textBlock, minWidth, horizontalAlignment); + } + public static TextBlock empty(final double width, final double height) { return new AbstractTextBlock() { public void drawU(UGraphic ug) { diff --git a/src/net/sourceforge/plantuml/graphic/TextBlockVertical2.java b/src/net/sourceforge/plantuml/graphic/TextBlockVertical2.java index 4a7fa07d0..0e49cc677 100644 --- a/src/net/sourceforge/plantuml/graphic/TextBlockVertical2.java +++ b/src/net/sourceforge/plantuml/graphic/TextBlockVertical2.java @@ -46,7 +46,7 @@ public class TextBlockVertical2 extends AbstractTextBlock implements TextBlock, private final List blocks = new ArrayList(); private final HorizontalAlignment horizontalAlignment; - public TextBlockVertical2(TextBlock b1, TextBlock b2, HorizontalAlignment horizontalAlignment) { + TextBlockVertical2(TextBlock b1, TextBlock b2, HorizontalAlignment horizontalAlignment) { this.blocks.add(b1); this.blocks.add(b2); this.horizontalAlignment = horizontalAlignment; diff --git a/src/net/sourceforge/plantuml/graphic/TileImageSvg.java b/src/net/sourceforge/plantuml/graphic/TileImageSvg.java index 09b90e3ad..2aca68008 100644 --- a/src/net/sourceforge/plantuml/graphic/TileImageSvg.java +++ b/src/net/sourceforge/plantuml/graphic/TileImageSvg.java @@ -31,12 +31,11 @@ package net.sourceforge.plantuml.graphic; import java.awt.geom.Dimension2D; -import java.io.BufferedReader; import java.io.File; -import java.io.FileReader; import java.io.IOException; import net.sourceforge.plantuml.Dimension2DDouble; +import net.sourceforge.plantuml.FileUtils; import net.sourceforge.plantuml.ugraphic.UGraphic; import net.sourceforge.plantuml.ugraphic.UImageSvg; @@ -49,14 +48,7 @@ public class TileImageSvg extends AbstractTextBlock implements TextBlock { } private UImageSvg createSvg(File svgFile) throws IOException { - final BufferedReader br = new BufferedReader(new FileReader(svgFile)); - final StringBuilder sb = new StringBuilder(); - String s; - while ((s = br.readLine()) != null) { - sb.append(s); - } - br.close(); - return new UImageSvg(sb.toString()); + return new UImageSvg(FileUtils.readSvg(svgFile)); } public Dimension2D calculateDimension(StringBounder stringBounder) { diff --git a/src/net/sourceforge/plantuml/graphic/USymbol.java b/src/net/sourceforge/plantuml/graphic/USymbol.java index 70f206fbf..4c8fc3e2f 100644 --- a/src/net/sourceforge/plantuml/graphic/USymbol.java +++ b/src/net/sourceforge/plantuml/graphic/USymbol.java @@ -54,6 +54,7 @@ public abstract class USymbol { public final static USymbol PACKAGE = record("PACKAGE", SkinParameter.PACKAGE, new USymbolFolder( SkinParameter.PACKAGE)); public final static USymbol FOLDER = record("FOLDER", SkinParameter.FOLDER, new USymbolFolder(SkinParameter.FOLDER)); + public final static USymbol FILE = record("FILE", SkinParameter.FILE, new USymbolFile()); public final static USymbol RECTANGLE = record("RECTANGLE", SkinParameter.CARD, new USymbolRect(SkinParameter.CARD, HorizontalAlignment.CENTER)); public final static USymbol AGENT = record("AGENT", SkinParameter.AGENT, new USymbolRect(SkinParameter.AGENT, diff --git a/src/net/sourceforge/plantuml/graphic/USymbolDatabase.java b/src/net/sourceforge/plantuml/graphic/USymbolDatabase.java index 39fcd38e4..5a382bfe1 100644 --- a/src/net/sourceforge/plantuml/graphic/USymbolDatabase.java +++ b/src/net/sourceforge/plantuml/graphic/USymbolDatabase.java @@ -106,7 +106,7 @@ class USymbolDatabase extends USymbol { } private Margin getMargin() { - return new Margin(10, 10, 20, 5); + return new Margin(10, 10, 24, 5); } public TextBlock asSmall(TextBlock name, final TextBlock label, final TextBlock stereotype, final SymbolContext symbolContext) { diff --git a/src/net/sourceforge/plantuml/graphic/USymbolFile.java b/src/net/sourceforge/plantuml/graphic/USymbolFile.java new file mode 100644 index 000000000..99d4d56c7 --- /dev/null +++ b/src/net/sourceforge/plantuml/graphic/USymbolFile.java @@ -0,0 +1,135 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2017, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * This file is part of PlantUML. + * + * PlantUML is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PlantUML distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.graphic; + +import java.awt.geom.Dimension2D; + +import net.sourceforge.plantuml.Dimension2DDouble; +import net.sourceforge.plantuml.ugraphic.UGraphic; +import net.sourceforge.plantuml.ugraphic.UGraphicStencil; +import net.sourceforge.plantuml.ugraphic.UPath; +import net.sourceforge.plantuml.ugraphic.UPolygon; +import net.sourceforge.plantuml.ugraphic.UStroke; +import net.sourceforge.plantuml.ugraphic.UTranslate; + +class USymbolFile extends USymbol { + + private final HorizontalAlignment stereotypeAlignement = HorizontalAlignment.CENTER; + + @Override + public SkinParameter getSkinParameter() { + return SkinParameter.FILE; + } + + private void drawFile(UGraphic ug, double width, double height, boolean shadowing) { + final UPolygon polygon = new UPolygon(); + final int cornersize = 10; + polygon.addPoint(0, 0); + polygon.addPoint(0, height); + polygon.addPoint(width, height); + polygon.addPoint(width, cornersize); + polygon.addPoint(width - cornersize, 0); + polygon.addPoint(0, 0); + + if (shadowing) { + polygon.setDeltaShadow(3.0); + } + ug.draw(polygon); + + final UPath path = new UPath(); + path.moveTo(width - cornersize, 0); + path.lineTo(width - cornersize, cornersize); + path.lineTo(width, cornersize); + ug.draw(path); + } + + private Margin getMargin() { + return new Margin(10, 10, 10, 10); + } + + public TextBlock asSmall(TextBlock name, final TextBlock label, final TextBlock stereotype, + final SymbolContext symbolContext) { + return new AbstractTextBlock() { + + public void drawU(UGraphic ug) { + final Dimension2D dim = calculateDimension(ug.getStringBounder()); + ug = new UGraphicStencil(ug, getRectangleStencil(dim), new UStroke()); + ug = symbolContext.apply(ug); + drawFile(ug, dim.getWidth(), dim.getHeight(), symbolContext.isShadowing()); + final Margin margin = getMargin(); + final TextBlock tb = TextBlockUtils.mergeTB(stereotype, label, HorizontalAlignment.CENTER); + tb.drawU(ug.apply(new UTranslate(margin.getX1(), margin.getY1()))); + } + + public Dimension2D calculateDimension(StringBounder stringBounder) { + final Dimension2D dimLabel = label.calculateDimension(stringBounder); + final Dimension2D dimStereo = stereotype.calculateDimension(stringBounder); + return getMargin().addDimension(Dimension2DDouble.mergeTB(dimStereo, dimLabel)); + } + }; + } + + public TextBlock asBig(final TextBlock title, final TextBlock stereotype, final double width, final double height, + final SymbolContext symbolContext) { + return new AbstractTextBlock() { + + public void drawU(UGraphic ug) { + final Dimension2D dim = calculateDimension(ug.getStringBounder()); + ug = symbolContext.apply(ug); + drawFile(ug, dim.getWidth(), dim.getHeight(), symbolContext.isShadowing()); + final Dimension2D dimStereo = stereotype.calculateDimension(ug.getStringBounder()); + final double posStereoX; + final double posStereoY; + if (stereotypeAlignement == HorizontalAlignment.RIGHT) { + posStereoX = width - dimStereo.getWidth() - getMargin().getX1() / 2; + posStereoY = getMargin().getY1() / 2; + } else { + posStereoX = (width - dimStereo.getWidth()) / 2; + posStereoY = 2; + } + stereotype.drawU(ug.apply(new UTranslate(posStereoX, posStereoY))); + final Dimension2D dimTitle = title.calculateDimension(ug.getStringBounder()); + final double posTitle = (width - dimTitle.getWidth()) / 2; + title.drawU(ug.apply(new UTranslate(posTitle, 2 + dimStereo.getHeight()))); + } + + public Dimension2D calculateDimension(StringBounder stringBounder) { + return new Dimension2DDouble(width, height); + } + }; + } + + @Override + public boolean manageHorizontalLine() { + return true; + } + +} \ No newline at end of file diff --git a/src/net/sourceforge/plantuml/graphic/USymbolTogether.java b/src/net/sourceforge/plantuml/graphic/USymbolTogether.java index 692a8161a..f756da77f 100644 --- a/src/net/sourceforge/plantuml/graphic/USymbolTogether.java +++ b/src/net/sourceforge/plantuml/graphic/USymbolTogether.java @@ -44,7 +44,7 @@ class USymbolTogether extends USymbol { public TextBlock asSmall(TextBlock name, final TextBlock label, final TextBlock stereotype, final SymbolContext symbolContext) { - throw new UnsupportedOperationException(); + return TextBlockUtils.empty(10, 10); } public TextBlock asBig(final TextBlock title, final TextBlock stereotype, final double width, final double height, diff --git a/src/net/sourceforge/plantuml/jdot/CucaDiagramFileMakerJDot.java b/src/net/sourceforge/plantuml/jdot/CucaDiagramFileMakerJDot.java index 8e9ee4370..b923d2c5a 100644 --- a/src/net/sourceforge/plantuml/jdot/CucaDiagramFileMakerJDot.java +++ b/src/net/sourceforge/plantuml/jdot/CucaDiagramFileMakerJDot.java @@ -427,9 +427,9 @@ public class CucaDiagramFileMakerJDot implements CucaDiagramFileMaker { final double scale = 1; - final ImageBuilder imageBuilder = new ImageBuilder(diagram.getSkinParam().getColorMapper(), scale, null, - fileFormatOption.isWithMetadata() ? diagram.getMetadata() : null, null, 0, 10, - diagram.getAnimation(), diagram.getSkinParam().handwritten()); + final ImageBuilder imageBuilder = new ImageBuilder(diagram.getSkinParam(), + scale, fileFormatOption.isWithMetadata() ? diagram.getMetadata() : null, null, 0, + 10, diagram.getAnimation()); imageBuilder.setUDrawable(new Drawing(null)); final Dimension2D dim = imageBuilder.getFinalDimension(stringBounder); diff --git a/src/net/sourceforge/plantuml/png/PngSplitter.java b/src/net/sourceforge/plantuml/png/PngSplitter.java index e2c45733f..e37863ee2 100644 --- a/src/net/sourceforge/plantuml/png/PngSplitter.java +++ b/src/net/sourceforge/plantuml/png/PngSplitter.java @@ -30,6 +30,7 @@ */ package net.sourceforge.plantuml.png; +import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; @@ -42,6 +43,8 @@ import javax.imageio.ImageIO; import net.sourceforge.plantuml.FileFormat; import net.sourceforge.plantuml.FileUtils; import net.sourceforge.plantuml.Log; +import net.sourceforge.plantuml.SplitParam; +import net.sourceforge.plantuml.graphic.HtmlColorSimple; public class PngSplitter { @@ -53,12 +56,12 @@ public class PngSplitter { final int y = Integer.parseInt(args[2]); final File cp = new File(f.getParent(), f.getName().replaceAll("\\.png$", "_000.png")); FileUtils.copyToFile(f, cp); - new PngSplitter(cp, x, y, "", 96, false); + new PngSplitter(cp, x, y, "", 96, false, new SplitParam()); } public PngSplitter(File pngFile, int horizontalPages, int verticalPages, String source, int dpi, - boolean isWithMetadata) throws IOException { + boolean isWithMetadata, SplitParam splitParam) throws IOException { if (horizontalPages == 1 && verticalPages == 1) { this.files.add(pngFile); return; @@ -66,18 +69,18 @@ public class PngSplitter { Log.info("Splitting " + horizontalPages + " x " + verticalPages); final File full = new File(pngFile.getParentFile(), pngFile.getName() + ".tmp"); - Thread.yield(); + // Thread.yield(); full.delete(); - Thread.yield(); + // Thread.yield(); final boolean ok = pngFile.renameTo(full); - Thread.yield(); + // Thread.yield(); if (ok == false) { throw new IOException("Cannot rename"); } - Thread.yield(); + // Thread.yield(); final BufferedImage im = ImageIO.read(full); - Thread.yield(); + // Thread.yield(); final PngSegment horizontalSegment = new PngSegment(im.getWidth(), horizontalPages); final PngSegment verticalSegment = new PngSegment(im.getHeight(), verticalPages); @@ -86,11 +89,33 @@ public class PngSplitter { for (int j = 0; j < verticalPages; j++) { final File f = FileFormat.PNG.computeFilename(pngFile, x++); this.files.add(f); - final BufferedImage imPiece = im.getSubimage(horizontalSegment.getStart(i), - verticalSegment.getStart(j), horizontalSegment.getLen(i), verticalSegment.getLen(j)); - Thread.yield(); - PngIO.write(imPiece, f, isWithMetadata ? source : null, dpi); - Thread.yield(); + final int width = horizontalSegment.getLen(i); + final int height = verticalSegment.getLen(j); + BufferedImage piece = im.getSubimage(horizontalSegment.getStart(i), verticalSegment.getStart(j), width, + height); + if (splitParam.isSet()) { + BufferedImage withMargin = new BufferedImage(width + 2 * splitParam.getExternalMargin(), height + 2 + * splitParam.getExternalMargin(), BufferedImage.TYPE_INT_ARGB); + final Graphics2D g2d = withMargin.createGraphics(); + if (splitParam.getExternalColor() != null) { + g2d.setColor(splitParam.getExternalColor()); + g2d.fillRect(0, 0, withMargin.getWidth(), withMargin.getHeight()); + } + g2d.drawImage(piece, splitParam.getExternalMargin(), splitParam.getExternalMargin(), null); + + if (splitParam.getBorderColor() != null) { + g2d.setColor(splitParam.getBorderColor()); + g2d.drawRect(splitParam.getExternalMargin() - 1, splitParam.getExternalMargin() - 1, + piece.getWidth() + 1, piece.getHeight() + 1); + } + + piece = withMargin; + + g2d.dispose(); + } + // Thread.yield(); + PngIO.write(piece, f, isWithMetadata ? source : null, dpi); + // Thread.yield(); } } diff --git a/src/net/sourceforge/plantuml/preproc/Define.java b/src/net/sourceforge/plantuml/preproc/Define.java new file mode 100644 index 000000000..6b09238fd --- /dev/null +++ b/src/net/sourceforge/plantuml/preproc/Define.java @@ -0,0 +1,76 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2017, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * This file is part of PlantUML. + * + * PlantUML is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PlantUML distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.preproc; + +import java.util.Iterator; +import java.util.List; +import java.util.regex.Matcher; + +public class Define { + + private final DefineSignature signature; + private final String definition; + private final String definitionQuoted; + + public Define(String key, List lines) { + this.signature = new DefineSignature(key); + if (lines == null) { + this.definition = null; + this.definitionQuoted = null; + } else { + final StringBuilder sb = new StringBuilder(); + for (final Iterator it = lines.iterator(); it.hasNext();) { + sb.append(it.next()); + if (it.hasNext()) { + sb.append('\n'); + } + } + this.definition = sb.toString(); + this.definitionQuoted = Matcher.quoteReplacement(definition); + } + } + + public String apply(String line) { + if (definition == null) { + return line; + } + if (signature.isMethod()) { + for (Variables vars : signature.getVariationVariables()) { + line = vars.applyOn(line, signature.getFonctionName(), definitionQuoted); + } + } else { + final String regex = "\\b" + signature.getKey() + "\\b"; + line = line.replaceAll(regex, definitionQuoted); + } + return line; + } + +} diff --git a/src/net/sourceforge/plantuml/preproc/DefineSignature.java b/src/net/sourceforge/plantuml/preproc/DefineSignature.java new file mode 100644 index 000000000..7625f4a9b --- /dev/null +++ b/src/net/sourceforge/plantuml/preproc/DefineSignature.java @@ -0,0 +1,77 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2017, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * This file is part of PlantUML. + * + * PlantUML is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PlantUML distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.preproc; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.StringTokenizer; + +public class DefineSignature { + + private final String key; + private final String fctName; + private final Variables vars = new Variables(); + + public DefineSignature(String key) { + this.key = key; + + final StringTokenizer st = new StringTokenizer(key, "(),"); + this.fctName = st.nextToken().trim(); + + while (st.hasMoreTokens()) { + final String var1 = st.nextToken().trim(); + this.vars.add(new DefineVariable(var1)); + } + } + + public boolean isMethod() { + return key.contains("("); + } + + public String getKey() { + return key; + } + + public List getVariationVariables() { + final List result = new ArrayList(); + final int count = vars.countDefaultValue(); + for (int i = 0; i <= count; i++) { + result.add(vars.removeSomeDefaultValues(i)); + } + return Collections.unmodifiableList(result); + } + + public String getFonctionName() { + return fctName; + } + +} diff --git a/src/net/sourceforge/plantuml/preproc/DefineVariable.java b/src/net/sourceforge/plantuml/preproc/DefineVariable.java new file mode 100644 index 000000000..a934bcb32 --- /dev/null +++ b/src/net/sourceforge/plantuml/preproc/DefineVariable.java @@ -0,0 +1,66 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2017, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * This file is part of PlantUML. + * + * PlantUML is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PlantUML distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.preproc; + +public class DefineVariable { + + private final String name; + private final String defaultValue; + + public DefineVariable(String name) { + name = name.trim(); + final int idx = name.indexOf('='); + if (idx == -1) { + this.name = name; + this.defaultValue = null; + } else { + this.name = name.substring(0, idx).trim(); + final String right = name.substring(idx + 1).trim(); + this.defaultValue = right.substring(1, right.length() - 1); + } + } + + public String getName() { + return name; + } + + public String getDefaultValue() { + return defaultValue; + } + + public DefineVariable removeDefault() { + if (defaultValue == null) { + throw new IllegalStateException(); + } + return new DefineVariable(name); + } + +} diff --git a/src/net/sourceforge/plantuml/preproc/Defines.java b/src/net/sourceforge/plantuml/preproc/Defines.java index ae306189c..cbb739f2e 100644 --- a/src/net/sourceforge/plantuml/preproc/Defines.java +++ b/src/net/sourceforge/plantuml/preproc/Defines.java @@ -30,35 +30,24 @@ */ package net.sourceforge.plantuml.preproc; +import gen.lib.pack.pack__c; + +import java.text.SimpleDateFormat; import java.util.Arrays; -import java.util.Iterator; +import java.util.Date; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import java.util.StringTokenizer; import java.util.regex.Matcher; +import java.util.regex.Pattern; public class Defines { - private final Map values = new LinkedHashMap(); - private final Map savedState = new LinkedHashMap(); + private final Map values = new LinkedHashMap(); + private final Map savedState = new LinkedHashMap(); public void define(String name, List value) { - values.put(name, addLineReturn(value)); - } - - private String addLineReturn(List value) { - if (value == null) { - return null; - } - final StringBuilder sb = new StringBuilder(); - for (final Iterator it = value.iterator(); it.hasNext();) { - sb.append(it.next()); - if (it.hasNext()) { - sb.append('\n'); - } - } - return sb.toString(); + values.put(name, new Define(name, value)); } public boolean isDefine(String name) { @@ -75,41 +64,33 @@ public class Defines { } public List applyDefines(String line) { - for (Map.Entry ent : values.entrySet()) { - final String key = ent.getKey(); - if (ent.getValue() == null) { - continue; - } - final String value = Matcher.quoteReplacement(ent.getValue()); - if (key.contains("(")) { - line = applyMethod(line, key, value); - } else { - final String regex = "\\b" + key + "\\b"; - line = line.replaceAll(regex, value); - } + line = manageDate(line); + for (Map.Entry ent : values.entrySet()) { + final Define def = ent.getValue(); + line = def.apply(line); } return Arrays.asList(line.split("\n")); } - private String applyMethod(String line, final String key, final String value) { - final StringTokenizer st = new StringTokenizer(key, "(),"); - final String fctName = st.nextToken(); - String newValue = value; - final StringBuilder regex = new StringBuilder("\\b" + fctName + "\\("); - int i = 1; + private static final String DATE = "(?i)%date(\\[(.+?)\\])?%"; + private final static Pattern datePattern = Pattern.compile(DATE); - while (st.hasMoreTokens()) { - regex.append("(?:(?:\\s*\"([^\"]*)\"\\s*)|(?:\\s*'([^']*)'\\s*)|\\s*" + "((?:\\([^()]*\\)|[^,])*?)" + ")"); - final String var1 = st.nextToken(); - final String var2 = "(##" + var1 + "\\b)|(\\b" + var1 + "##)|(\\b" + var1 + "\\b)"; - newValue = newValue.replaceAll(var2, "\\$" + i + "\\$" + (i + 1) + "\\$" + (i + 2)); - i += 3; - if (st.hasMoreTokens()) { - regex.append(","); + private String manageDate(String line) { + final Matcher m = datePattern.matcher(line); + if (m.find()) { + final String format = m.group(2); + String replace; + if (format == null) { + replace = new Date().toString(); + } else { + try { + replace = new SimpleDateFormat(format).format(new Date()); + } catch (Exception e) { + replace = "(BAD DATE PATTERN:" + format + ")"; + } } + line = line.replaceAll(DATE, replace); } - regex.append("\\)"); - line = line.replaceAll(regex.toString(), newValue); return line; } diff --git a/src/net/sourceforge/plantuml/preproc/Preprocessor.java b/src/net/sourceforge/plantuml/preproc/Preprocessor.java index 618e08ee5..9417bc866 100644 --- a/src/net/sourceforge/plantuml/preproc/Preprocessor.java +++ b/src/net/sourceforge/plantuml/preproc/Preprocessor.java @@ -48,7 +48,8 @@ import net.sourceforge.plantuml.utils.StartUtils; public class Preprocessor implements ReadLine { private static final String ID = "[A-Za-z_][A-Za-z_0-9]*"; - private static final String ARG = "(?:\\(" + ID + "(?:," + ID + ")*?\\))?"; + private static final String ID_ARG = "\\s*[A-Za-z_][A-Za-z_0-9]*\\s*(?:=\\s*(?:\"[^\"]*\"|'[^']*')\\s*)?"; + private static final String ARG = "(?:\\(" + ID_ARG + "(?:," + ID_ARG + ")*?\\))?"; private static final Pattern2 definePattern = MyPattern.cmpile("^[%s]*!define[%s]+(" + ID + ARG + ")" + "(?:[%s]+(.*))?$"); private static final Pattern2 undefPattern = MyPattern.cmpile("^[%s]*!undef[%s]+(" + ID + ")$"); diff --git a/src/net/sourceforge/plantuml/preproc/Variables.java b/src/net/sourceforge/plantuml/preproc/Variables.java new file mode 100644 index 000000000..b14ca5965 --- /dev/null +++ b/src/net/sourceforge/plantuml/preproc/Variables.java @@ -0,0 +1,103 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2017, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * This file is part of PlantUML. + * + * PlantUML is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PlantUML distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.preproc; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; + +public class Variables { + + private final List all = new ArrayList(); + + public void add(DefineVariable var) { + this.all.add(var); + } + + public int countDefaultValue() { + int result = 0; + for (DefineVariable var : all) { + if (var.getDefaultValue() != null) { + result++; + } + } + return result; + } + + public Variables removeSomeDefaultValues(int nb) { + if (nb == 0) { + return this; + } + final Variables result = new Variables(); + for (DefineVariable v : all) { + if (v.getDefaultValue() != null && nb > 0) { + result.add(v.removeDefault()); + nb--; + } else { + result.add(v); + } + } + if (nb != 0) { + throw new IllegalArgumentException(); + } + return result; + } + + public String applyOn(String line, String fonctionName, String newValue) { + // System.err.println("KEY="+key); + // final StringTokenizer st = new StringTokenizer(key, "(),"); + // final String fctName = st.nextToken(); + final StringBuilder regex = new StringBuilder("\\b" + fonctionName + "\\("); + + final List variables = all; + for (int j = 0; j < variables.size(); j++) { + final DefineVariable variable = variables.get(j); + final String varName = variable.getName(); + final String var2 = "(##" + varName + "\\b)|(\\b" + varName + "##)|(\\b" + varName + "\\b)"; + if (variable.getDefaultValue() == null) { + regex.append("(?:(?:\\s*\"([^\"]*)\"\\s*)|(?:\\s*'([^']*)'\\s*)|\\s*" + "((?:\\([^()]*\\)|[^,'\"])*?)" + + ")"); + final int i = 1 + 3 * j; + newValue = newValue.replaceAll(var2, "\\$" + i + "\\$" + (i + 1) + "\\$" + (i + 2)); + regex.append(","); + } else { + newValue = newValue.replaceAll(var2, Matcher.quoteReplacement(variable.getDefaultValue())); + } + } + regex.setLength(regex.length() - 1); + regex.append("\\)"); + // System.err.println("regex=" + regex); + // System.err.println("newValue=" + newValue); + line = line.replaceAll(regex.toString(), newValue); + return line; + } + +} diff --git a/src/net/sourceforge/plantuml/sequencediagram/AbstractMessage.java b/src/net/sourceforge/plantuml/sequencediagram/AbstractMessage.java index 09e4a41c9..2ccbec3a9 100644 --- a/src/net/sourceforge/plantuml/sequencediagram/AbstractMessage.java +++ b/src/net/sourceforge/plantuml/sequencediagram/AbstractMessage.java @@ -30,34 +30,28 @@ */ package net.sourceforge.plantuml.sequencediagram; +import java.util.ArrayList; import java.util.EnumSet; import java.util.HashSet; +import java.util.List; import java.util.Set; -import net.sourceforge.plantuml.ISkinParam; -import net.sourceforge.plantuml.SkinParamBackcolored; import net.sourceforge.plantuml.Url; import net.sourceforge.plantuml.cucadiagram.Display; -import net.sourceforge.plantuml.graphic.HtmlColor; -import net.sourceforge.plantuml.graphic.HtmlColorSet; import net.sourceforge.plantuml.skin.ArrowConfiguration; public abstract class AbstractMessage implements EventWithDeactivate { - final private Display label; - final private ArrowConfiguration arrowConfiguration; + private final Display label; + private final ArrowConfiguration arrowConfiguration; + private final Set lifeEventsType = EnumSet.noneOf(LifeEventType.class); - final private Set lifeEventsType = EnumSet.noneOf(LifeEventType.class); - - private Display notes; - private NotePosition notePosition; - private HtmlColor noteBackColor; - private Url urlNote; - private NoteStyle noteStyle; private final Url url; private final String messageNumber; private boolean parallel = false; + private List noteOnMessages = new ArrayList(); + public AbstractMessage(Display label, ArrowConfiguration arrowConfiguration, String messageNumber) { this.url = label.initUrl(); this.label = label.removeHeadingUrl(url); @@ -75,14 +69,20 @@ public abstract class AbstractMessage implements EventWithDeactivate { final public Url getUrl() { if (url == null) { - return urlNote; + for (NoteOnMessage n : noteOnMessages) { + if (n.getUrlNote() != null) { + return n.getUrlNote(); + } + } } return url; } public boolean hasUrl() { - if (notes != null && notes.hasUrl()) { - return true; + for (NoteOnMessage n : noteOnMessages) { + if (n.hasUrl()) { + return true; + } } if (label != null && label.hasUrl()) { return true; @@ -150,45 +150,22 @@ public abstract class AbstractMessage implements EventWithDeactivate { return arrowConfiguration; } - public final Display getNote() { - return notes == null ? notes : notes; - } - - public final NoteStyle getNoteStyle() { - return noteStyle; - } - - public final Url getUrlNote() { - return urlNote; + public final List getNoteOnMessages() { + return noteOnMessages; } public final void setNote(Display strings, NotePosition notePosition, NoteStyle noteStyle, String backcolor, Url url) { if (notePosition != NotePosition.LEFT && notePosition != NotePosition.RIGHT) { throw new IllegalArgumentException(); } - this.noteStyle = noteStyle; - this.notes = strings; - this.urlNote = url; - this.notePosition = overideNotePosition(notePosition); - this.noteBackColor = HtmlColorSet.getInstance().getColorIfValid(backcolor); + this.noteOnMessages + .add(new NoteOnMessage(strings, overideNotePosition(notePosition), noteStyle, backcolor, url)); } protected NotePosition overideNotePosition(NotePosition notePosition) { return notePosition; } - private final HtmlColor getSpecificBackColor() { - return noteBackColor; - } - - public SkinParamBackcolored getSkinParamNoteBackcolored(ISkinParam skinParam) { - return new SkinParamBackcolored(skinParam, getSpecificBackColor()); - } - - public final NotePosition getNotePosition() { - return notePosition; - } - public final String getMessageNumber() { return messageNumber; } diff --git a/src/net/sourceforge/plantuml/sequencediagram/NoteOnMessage.java b/src/net/sourceforge/plantuml/sequencediagram/NoteOnMessage.java new file mode 100644 index 000000000..5f2c79dd0 --- /dev/null +++ b/src/net/sourceforge/plantuml/sequencediagram/NoteOnMessage.java @@ -0,0 +1,90 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2017, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * This file is part of PlantUML. + * + * PlantUML is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PlantUML distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.sequencediagram; + +import net.sourceforge.plantuml.ISkinParam; +import net.sourceforge.plantuml.SkinParamBackcolored; +import net.sourceforge.plantuml.Url; +import net.sourceforge.plantuml.cucadiagram.Display; +import net.sourceforge.plantuml.graphic.HtmlColor; +import net.sourceforge.plantuml.graphic.HtmlColorSet; + +public class NoteOnMessage { + + private final Display notes; + private final NotePosition notePosition; + private final NoteStyle noteStyle; + private final HtmlColor noteBackColor; + private final Url urlNote; + + public NoteOnMessage(Display strings, NotePosition notePosition, NoteStyle noteStyle, String backcolor, Url url) { + if (notePosition != NotePosition.LEFT && notePosition != NotePosition.RIGHT) { + throw new IllegalArgumentException(); + } + this.noteStyle = noteStyle; + this.notes = strings; + this.urlNote = url; + this.notePosition = notePosition; + this.noteBackColor = HtmlColorSet.getInstance().getColorIfValid(backcolor); + } + + public SkinParamBackcolored getSkinParamNoteBackcolored(ISkinParam skinParam) { + return new SkinParamBackcolored(skinParam, noteBackColor); + } + + public boolean hasUrl() { + if (notes != null && notes.hasUrl()) { + return true; + } + // if (label != null && label.hasUrl()) { + // return true; + // } + // return getUrl() != null; + return urlNote != null; + } + + public Display getDisplay() { + return notes; + } + + public NotePosition getNotePosition() { + return notePosition; + } + + public NoteStyle getNoteStyle() { + return noteStyle; + } + + public Url getUrlNote() { + return urlNote; + } + +} diff --git a/src/net/sourceforge/plantuml/sequencediagram/graphic/ArrowAndNoteBox.java b/src/net/sourceforge/plantuml/sequencediagram/graphic/ArrowAndNoteBox.java index f704fba1a..f69d84405 100644 --- a/src/net/sourceforge/plantuml/sequencediagram/graphic/ArrowAndNoteBox.java +++ b/src/net/sourceforge/plantuml/sequencediagram/graphic/ArrowAndNoteBox.java @@ -30,6 +30,9 @@ */ package net.sourceforge.plantuml.sequencediagram.graphic; +import java.util.ArrayList; +import java.util.List; + import net.sourceforge.plantuml.graphic.StringBounder; import net.sourceforge.plantuml.sequencediagram.InGroupable; import net.sourceforge.plantuml.sequencediagram.NotePosition; @@ -39,24 +42,26 @@ import net.sourceforge.plantuml.ugraphic.UGraphic; class ArrowAndNoteBox extends Arrow implements InGroupable { private final Arrow arrow; - private final NoteBox noteBox; + private final List noteBoxes = new ArrayList(); - public ArrowAndNoteBox(StringBounder stringBounder, Arrow arrow, NoteBox noteBox) { + public ArrowAndNoteBox(StringBounder stringBounder, Arrow arrow, List noteBoxes) { super(arrow.getStartingY(), arrow.getSkin(), arrow.getArrowComponent(), arrow.getUrl()); this.arrow = arrow; - this.noteBox = noteBox; + this.noteBoxes.addAll(noteBoxes); - final double arrowHeight = arrow.getPreferredHeight(stringBounder); - final double noteHeight = noteBox.getPreferredHeight(stringBounder); - final double myHeight = getPreferredHeight(stringBounder); + for (NoteBox noteBox : noteBoxes) { + final double arrowHeight = arrow.getPreferredHeight(stringBounder); + final double noteHeight = noteBox.getPreferredHeight(stringBounder); + final double myHeight = getPreferredHeight(stringBounder); - final double diffHeightArrow = myHeight - arrowHeight; - final double diffHeightNote = myHeight - noteHeight; - if (diffHeightArrow > 0) { - arrow.pushToDown(diffHeightArrow / 2); - } - if (diffHeightNote > 0) { - noteBox.pushToDown(diffHeightNote / 2); + final double diffHeightArrow = myHeight - arrowHeight; + final double diffHeightNote = myHeight - noteHeight; + if (diffHeightArrow > 0) { + arrow.pushToDown(diffHeightArrow / 2); + } + if (diffHeightNote > 0) { + noteBox.pushToDown(diffHeightNote / 2); + } } } @@ -74,21 +79,30 @@ class ArrowAndNoteBox extends Arrow implements InGroupable { @Override protected void drawInternalU(UGraphic ug, double maxX, Context2D context) { arrow.drawU(ug, maxX, context); - noteBox.drawU(ug, maxX, context); + for (NoteBox noteBox : noteBoxes) { + noteBox.drawU(ug, maxX, context); + } } @Override public double getPreferredHeight(StringBounder stringBounder) { - return Math.max(arrow.getPreferredHeight(stringBounder), noteBox.getPreferredHeight(stringBounder)); + double result = arrow.getPreferredHeight(stringBounder); + for (NoteBox noteBox : noteBoxes) { + result = Math.max(result, noteBox.getPreferredHeight(stringBounder)); + } + return result; } @Override public double getPreferredWidth(StringBounder stringBounder) { double w = arrow.getPreferredWidth(stringBounder); w = Math.max(w, arrow.getActualWidth(stringBounder)); - double result = w + noteBox.getPreferredWidth(stringBounder); - if (noteBox.getNotePosition() == NotePosition.RIGHT) { - result += noteBox.getRightShift(arrow.getStartingY()); + double result = w; + for (NoteBox noteBox : noteBoxes) { + result += noteBox.getPreferredWidth(stringBounder); + if (noteBox.getNotePosition() == NotePosition.RIGHT) { + result += noteBox.getRightShift(arrow.getStartingY()); + } } return result; } @@ -100,7 +114,11 @@ class ArrowAndNoteBox extends Arrow implements InGroupable { @Override public double getStartingX(StringBounder stringBounder) { - return Math.min(arrow.getStartingX(stringBounder), noteBox.getStartingX(stringBounder)); + double result = arrow.getStartingX(stringBounder); + for (NoteBox noteBox : noteBoxes) { + result = Math.min(result, noteBox.getStartingX(stringBounder)); + } + return result; } @Override diff --git a/src/net/sourceforge/plantuml/sequencediagram/graphic/SequenceDiagramFileMakerPuma2.java b/src/net/sourceforge/plantuml/sequencediagram/graphic/SequenceDiagramFileMakerPuma2.java index 328551170..38819a9af 100644 --- a/src/net/sourceforge/plantuml/sequencediagram/graphic/SequenceDiagramFileMakerPuma2.java +++ b/src/net/sourceforge/plantuml/sequencediagram/graphic/SequenceDiagramFileMakerPuma2.java @@ -39,13 +39,13 @@ import java.util.List; import java.util.Map; import net.sourceforge.plantuml.AnnotatedWorker; -import net.sourceforge.plantuml.Dimension2DDouble; import net.sourceforge.plantuml.FileFormatOption; import net.sourceforge.plantuml.FontParam; import net.sourceforge.plantuml.activitydiagram3.ftile.EntityImageLegend; import net.sourceforge.plantuml.core.ImageData; import net.sourceforge.plantuml.cucadiagram.Display; import net.sourceforge.plantuml.cucadiagram.DisplayPositionned; +import net.sourceforge.plantuml.graphic.FontConfiguration; import net.sourceforge.plantuml.graphic.HorizontalAlignment; import net.sourceforge.plantuml.graphic.HtmlColor; import net.sourceforge.plantuml.graphic.StringBounder; @@ -58,10 +58,7 @@ import net.sourceforge.plantuml.sequencediagram.Event; import net.sourceforge.plantuml.sequencediagram.Newpage; import net.sourceforge.plantuml.sequencediagram.Participant; import net.sourceforge.plantuml.sequencediagram.SequenceDiagram; -import net.sourceforge.plantuml.skin.Area; -import net.sourceforge.plantuml.skin.Component; import net.sourceforge.plantuml.skin.ComponentType; -import net.sourceforge.plantuml.skin.SimpleContext2D; import net.sourceforge.plantuml.skin.Skin; import net.sourceforge.plantuml.ugraphic.ImageBuilder; import net.sourceforge.plantuml.ugraphic.UGraphic; @@ -143,16 +140,18 @@ public class SequenceDiagramFileMakerPuma2 implements FileMaker { final Page page = pages.get(index); final SequenceDiagramArea area = new SequenceDiagramArea(fullDimension.getWidth(), page.getHeight()); - final Component compTitle; + final TextBlock compTitle; final TextBlock caption = new AnnotatedWorker(diagram, diagram.getSkinParam()).getCaption(); area.setCaptionArea(caption.calculateDimension(stringBounder)); if (Display.isNull(page.getTitle())) { compTitle = null; } else { - compTitle = drawableSet.getSkin().createComponent(ComponentType.TITLE, null, drawableSet.getSkinParam(), - page.getTitle()); - area.setTitleArea(compTitle.getPreferredWidth(stringBounder), compTitle.getPreferredHeight(stringBounder)); + compTitle = TextBlockUtils.withMargin(TextBlockUtils.title(new FontConfiguration( + drawableSet.getSkinParam(), FontParam.SEQUENCE_TITLE, null), page.getTitle(), drawableSet + .getSkinParam()), 7, 7); + final Dimension2D dimTitle = compTitle.calculateDimension(stringBounder); + area.setTitleArea(dimTitle.getWidth(), dimTitle.getHeight()); } area.initFooter(getPngTitler(FontParam.FOOTER), stringBounder); area.initHeader(getPngTitler(FontParam.HEADER), stringBounder); @@ -174,9 +173,8 @@ public class SequenceDiagramFileMakerPuma2 implements FileMaker { final String metadata = fileFormatOption.isWithMetadata() ? diagram.getMetadata() : null; - final ImageBuilder imageBuilder = new ImageBuilder(diagram.getSkinParam().getColorMapper(), oneOf(scale, - dpiFactor), diagram.getSkinParam().getBackgroundColor(), metadata, null, 3, 10, diagram.getAnimation(), - diagram.getSkinParam().handwritten()); + final ImageBuilder imageBuilder = new ImageBuilder(diagram.getSkinParam(), oneOf(scale, dpiFactor), metadata, null, 3, + 10, diagram.getAnimation()); imageBuilder.setUDrawable(new UDrawable() { public void drawU(UGraphic ug) { @@ -192,11 +190,9 @@ public class SequenceDiagramFileMakerPuma2 implements FileMaker { double legendYdelta = 0; if (compTitle != null) { final StringBounder stringBounder = ug.getStringBounder(); - final double h = compTitle.getPreferredHeight(stringBounder); + final double h = compTitle.calculateDimension(stringBounder).getHeight(); legendYdelta += h; - final double w = compTitle.getPreferredWidth(stringBounder); - compTitle.drawU(ug.apply(new UTranslate(area.getTitleX(), area.getTitleY())), new Area( - new Dimension2DDouble(w, h)), new SimpleContext2D(false)); + compTitle.drawU(ug.apply(new UTranslate(area.getTitleX(), area.getTitleY()))); } caption.drawU(ug.apply(new UTranslate(area.getCaptionX(), area.getCaptionY()))); diff --git a/src/net/sourceforge/plantuml/sequencediagram/graphic/Step1Abstract.java b/src/net/sourceforge/plantuml/sequencediagram/graphic/Step1Abstract.java index 6bdafeff6..921968fc0 100644 --- a/src/net/sourceforge/plantuml/sequencediagram/graphic/Step1Abstract.java +++ b/src/net/sourceforge/plantuml/sequencediagram/graphic/Step1Abstract.java @@ -30,9 +30,12 @@ */ package net.sourceforge.plantuml.sequencediagram.graphic; -import net.sourceforge.plantuml.Url; +import java.util.ArrayList; +import java.util.List; + import net.sourceforge.plantuml.graphic.StringBounder; import net.sourceforge.plantuml.sequencediagram.AbstractMessage; +import net.sourceforge.plantuml.sequencediagram.NoteOnMessage; import net.sourceforge.plantuml.sequencediagram.NotePosition; import net.sourceforge.plantuml.skin.ArrowConfiguration; import net.sourceforge.plantuml.skin.Component; @@ -47,10 +50,9 @@ abstract class Step1Abstract { private Frontier freeY2; - // private ComponentType type; private ArrowConfiguration config; - private Component note; + private final List notes = new ArrayList(); private ParticipantRange range; @@ -80,12 +82,12 @@ abstract class Step1Abstract { this.config = config.withThickness(drawingSet.getArrowThickness()); } - protected final Component getNote() { - return note; + protected final List getNotes() { + return notes; } - protected final void setNote(Component note) { - this.note = note; + protected final void addNote(Component note) { + this.notes.add(note); } protected final StringBounder getStringBounder() { @@ -109,11 +111,12 @@ abstract class Step1Abstract { } protected final NoteBox createNoteBox(StringBounder stringBounder, Arrow arrow, Component noteComp, - NotePosition notePosition, Url url) { - final LivingParticipantBox p = arrow.getParticipantAt(stringBounder, notePosition); - final NoteBox noteBox = new NoteBox(arrow.getStartingY(), noteComp, p, null, notePosition, url); + NoteOnMessage noteOnMessage) { + final LivingParticipantBox p = arrow.getParticipantAt(stringBounder, noteOnMessage.getNotePosition()); + final NoteBox noteBox = new NoteBox(arrow.getStartingY(), noteComp, p, null, noteOnMessage.getNotePosition(), + noteOnMessage.getUrlNote()); - if (arrow instanceof MessageSelfArrow && notePosition == NotePosition.RIGHT) { + if (arrow instanceof MessageSelfArrow && noteOnMessage.getNotePosition() == NotePosition.RIGHT) { noteBox.pushToRight(arrow.getPreferredWidth(stringBounder)); } // if (arrow instanceof MessageExoArrow) { diff --git a/src/net/sourceforge/plantuml/sequencediagram/graphic/Step1Message.java b/src/net/sourceforge/plantuml/sequencediagram/graphic/Step1Message.java index ea1817814..e87a45263 100644 --- a/src/net/sourceforge/plantuml/sequencediagram/graphic/Step1Message.java +++ b/src/net/sourceforge/plantuml/sequencediagram/graphic/Step1Message.java @@ -30,12 +30,16 @@ */ package net.sourceforge.plantuml.sequencediagram.graphic; +import java.util.ArrayList; +import java.util.List; + import net.sourceforge.plantuml.ISkinParam; import net.sourceforge.plantuml.OptionFlags; import net.sourceforge.plantuml.cucadiagram.Display; import net.sourceforge.plantuml.graphic.StringBounder; import net.sourceforge.plantuml.sequencediagram.InGroupable; import net.sourceforge.plantuml.sequencediagram.Message; +import net.sourceforge.plantuml.sequencediagram.NoteOnMessage; import net.sourceforge.plantuml.sequencediagram.NotePosition; import net.sourceforge.plantuml.skin.ArrowBody; import net.sourceforge.plantuml.skin.ArrowConfiguration; @@ -68,10 +72,11 @@ class Step1Message extends Step1Abstract { getLivingParticipantBox1(), getLivingParticipantBox2(), message.getUrl(), compAliveBox); } - if (message.getNote() != null) { - final ISkinParam skinParam = message.getSkinParamNoteBackcolored(drawingSet.getSkinParam()); - setNote(drawingSet.getSkin().createComponent(message.getNoteStyle().getNoteComponentType(), null, - skinParam, message.getNote())); + final List noteOnMessages = message.getNoteOnMessages(); + for (NoteOnMessage noteOnMessage : noteOnMessages) { + final ISkinParam skinParam = noteOnMessage.getSkinParamNoteBackcolored(drawingSet.getSkinParam()); + addNote(drawingSet.getSkin().createComponent(noteOnMessage.getNoteStyle().getNoteComponentType(), null, + skinParam, noteOnMessage.getDisplay())); } } @@ -156,15 +161,23 @@ class Step1Message extends Step1Abstract { if (getMessage().isCreate()) { return createArrowCreate(); } - if (getMessage().getNote() != null && isSelfMessage()) { + if (getMessage().getNoteOnMessages().size() > 0 && isSelfMessage()) { final MessageSelfArrow messageSelfArrow = createMessageSelfArrow(); - final NoteBox noteBox = createNoteBox(getStringBounder(), messageSelfArrow, getNote(), getMessage() - .getNotePosition(), getMessage().getUrlNote()); - return new ArrowAndNoteBox(getStringBounder(), messageSelfArrow, noteBox); - } else if (getMessage().getNote() != null) { - final NoteBox noteBox = createNoteBox(getStringBounder(), messageArrow, getNote(), getMessage() - .getNotePosition(), getMessage().getUrlNote()); - return new ArrowAndNoteBox(getStringBounder(), messageArrow, noteBox); + final List noteBoxes = new ArrayList(); + for (int i = 0; i < getNotes().size(); i++) { + final Component note = getNotes().get(i); + final NoteOnMessage noteOnMessage = getMessage().getNoteOnMessages().get(i); + noteBoxes.add(createNoteBox(getStringBounder(), messageSelfArrow, note, noteOnMessage)); + } + return new ArrowAndNoteBox(getStringBounder(), messageSelfArrow, noteBoxes); + } else if (getMessage().getNoteOnMessages().size() > 0) { + final List noteBoxes = new ArrayList(); + for (int i = 0; i < getNotes().size(); i++) { + final Component note = getNotes().get(i); + final NoteOnMessage noteOnMessage = getMessage().getNoteOnMessages().get(i); + noteBoxes.add(createNoteBox(getStringBounder(), messageArrow, note, noteOnMessage)); + } + return new ArrowAndNoteBox(getStringBounder(), messageArrow, noteBoxes); } else if (isSelfMessage()) { return createMessageSelfArrow(); } else { @@ -203,13 +216,18 @@ class Step1Message extends Step1Abstract { throw new IllegalStateException(); } Arrow result = new ArrowAndParticipant(getStringBounder(), messageArrow, getParticipantBox2()); - if (getMessage().getNote() != null) { - final NoteBox noteBox = createNoteBox(getStringBounder(), result, getNote(), - getMessage().getNotePosition(), getMessage().getUrlNote()); - if (getMessage().getNotePosition() == NotePosition.RIGHT) { - noteBox.pushToRight(getParticipantBox2().getPreferredWidth(getStringBounder()) / 2); + if (getMessage().getNoteOnMessages().size() > 0) { + final List noteBoxes = new ArrayList(); + for (int i = 0; i < getNotes().size(); i++) { + final Component note = getNotes().get(i); + final NoteOnMessage noteOnMessage = getMessage().getNoteOnMessages().get(i); + final NoteBox noteBox = createNoteBox(getStringBounder(), result, note, noteOnMessage); + if (noteOnMessage.getNotePosition() == NotePosition.RIGHT) { + noteBox.pushToRight(getParticipantBox2().getPreferredWidth(getStringBounder()) / 2); + } + noteBoxes.add(noteBox); } - result = new ArrowAndNoteBox(getStringBounder(), result, noteBox); + result = new ArrowAndNoteBox(getStringBounder(), result, noteBoxes); } getLivingParticipantBox2().create( getFreeY().getFreeY(getParticipantRange()) + result.getPreferredHeight(getStringBounder()) / 2); diff --git a/src/net/sourceforge/plantuml/sequencediagram/graphic/Step1MessageExo.java b/src/net/sourceforge/plantuml/sequencediagram/graphic/Step1MessageExo.java index 2055cd26e..19a924118 100644 --- a/src/net/sourceforge/plantuml/sequencediagram/graphic/Step1MessageExo.java +++ b/src/net/sourceforge/plantuml/sequencediagram/graphic/Step1MessageExo.java @@ -30,12 +30,17 @@ */ package net.sourceforge.plantuml.sequencediagram.graphic; +import java.util.ArrayList; +import java.util.List; + import net.sourceforge.plantuml.ISkinParam; import net.sourceforge.plantuml.graphic.StringBounder; import net.sourceforge.plantuml.sequencediagram.InGroupable; import net.sourceforge.plantuml.sequencediagram.MessageExo; import net.sourceforge.plantuml.sequencediagram.MessageExoType; +import net.sourceforge.plantuml.sequencediagram.NoteOnMessage; import net.sourceforge.plantuml.skin.ArrowConfiguration; +import net.sourceforge.plantuml.skin.Component; import net.sourceforge.plantuml.skin.ComponentType; class Step1MessageExo extends Step1Abstract { @@ -53,9 +58,11 @@ class Step1MessageExo extends Step1Abstract { message.getLabelNumbered()), getLivingParticipantBox(), message.getType(), message.getUrl(), message.isShortArrow(), message.getArrowConfiguration()); - if (message.getNote() != null) { - final ISkinParam skinParam = message.getSkinParamNoteBackcolored(drawingSet.getSkinParam()); - setNote(drawingSet.getSkin().createComponent(ComponentType.NOTE, null, skinParam, message.getNote())); + final List noteOnMessages = message.getNoteOnMessages(); + for (NoteOnMessage noteOnMessage : noteOnMessages) { + final ISkinParam skinParam = noteOnMessage.getSkinParamNoteBackcolored(drawingSet.getSkinParam()); + addNote(drawingSet.getSkin().createComponent(ComponentType.NOTE, null, skinParam, + noteOnMessage.getDisplay())); // throw new UnsupportedOperationException(); } @@ -103,12 +110,16 @@ class Step1MessageExo extends Step1Abstract { } private Arrow createArrow() { - if (getMessage().getNote() == null) { + if (getMessage().getNoteOnMessages().size() == 0) { return messageArrow; } - final NoteBox toto = createNoteBox(getStringBounder(), messageArrow, getNote(), getMessage().getNotePosition(), - getMessage().getUrlNote()); - return new ArrowAndNoteBox(getStringBounder(), messageArrow, toto); + final List noteBoxes = new ArrayList(); + for (int i = 0; i < getNotes().size(); i++) { + final Component note = getNotes().get(i); + final NoteOnMessage noteOnMessage = getMessage().getNoteOnMessages().get(i); + noteBoxes.add(createNoteBox(getStringBounder(), messageArrow, note, noteOnMessage)); + } + return new ArrowAndNoteBox(getStringBounder(), messageArrow, noteBoxes); } private ArrowConfiguration getArrowType(MessageExo m) { diff --git a/src/net/sourceforge/plantuml/sequencediagram/teoz/CommunicationTileNoteLeft.java b/src/net/sourceforge/plantuml/sequencediagram/teoz/CommunicationTileNoteLeft.java index f912b2c5e..b94750501 100644 --- a/src/net/sourceforge/plantuml/sequencediagram/teoz/CommunicationTileNoteLeft.java +++ b/src/net/sourceforge/plantuml/sequencediagram/teoz/CommunicationTileNoteLeft.java @@ -33,11 +33,11 @@ package net.sourceforge.plantuml.sequencediagram.teoz; import java.awt.geom.Dimension2D; import net.sourceforge.plantuml.ISkinParam; -import net.sourceforge.plantuml.cucadiagram.Display; import net.sourceforge.plantuml.graphic.StringBounder; import net.sourceforge.plantuml.real.Real; import net.sourceforge.plantuml.sequencediagram.AbstractMessage; import net.sourceforge.plantuml.sequencediagram.Event; +import net.sourceforge.plantuml.sequencediagram.NoteOnMessage; import net.sourceforge.plantuml.skin.Area; import net.sourceforge.plantuml.skin.Component; import net.sourceforge.plantuml.skin.ComponentType; @@ -52,22 +52,20 @@ public class CommunicationTileNoteLeft implements TileWithUpdateStairs, TileWith private final AbstractMessage message; private final Skin skin; private final ISkinParam skinParam; - private final Display notes; - // private final NotePosition notePosition; private final LivingSpace livingSpace; + private final NoteOnMessage noteOnMessage; public Event getEvent() { return message; } public CommunicationTileNoteLeft(TileWithUpdateStairs tile, AbstractMessage message, Skin skin, - ISkinParam skinParam, LivingSpace livingSpace) { + ISkinParam skinParam, LivingSpace livingSpace, NoteOnMessage noteOnMessage) { this.tile = tile; this.message = message; this.skin = skin; this.skinParam = skinParam; - this.notes = message.getNote(); - // this.notePosition = message.getNotePosition(); + this.noteOnMessage = noteOnMessage; this.livingSpace = livingSpace; } @@ -77,7 +75,7 @@ public class CommunicationTileNoteLeft implements TileWithUpdateStairs, TileWith private Component getComponent(StringBounder stringBounder) { final Component comp = skin.createComponent(ComponentType.NOTE, null, - message.getSkinParamNoteBackcolored(skinParam), notes); + noteOnMessage.getSkinParamNoteBackcolored(skinParam), noteOnMessage.getDisplay()); return comp; } diff --git a/src/net/sourceforge/plantuml/sequencediagram/teoz/CommunicationTileNoteRight.java b/src/net/sourceforge/plantuml/sequencediagram/teoz/CommunicationTileNoteRight.java index c1fd339c4..f18ad135d 100644 --- a/src/net/sourceforge/plantuml/sequencediagram/teoz/CommunicationTileNoteRight.java +++ b/src/net/sourceforge/plantuml/sequencediagram/teoz/CommunicationTileNoteRight.java @@ -33,11 +33,11 @@ package net.sourceforge.plantuml.sequencediagram.teoz; import java.awt.geom.Dimension2D; import net.sourceforge.plantuml.ISkinParam; -import net.sourceforge.plantuml.cucadiagram.Display; import net.sourceforge.plantuml.graphic.StringBounder; import net.sourceforge.plantuml.real.Real; import net.sourceforge.plantuml.sequencediagram.AbstractMessage; import net.sourceforge.plantuml.sequencediagram.Event; +import net.sourceforge.plantuml.sequencediagram.NoteOnMessage; import net.sourceforge.plantuml.skin.Area; import net.sourceforge.plantuml.skin.Component; import net.sourceforge.plantuml.skin.ComponentType; @@ -52,8 +52,8 @@ public class CommunicationTileNoteRight implements TileWithUpdateStairs, TileWit private final AbstractMessage message; private final Skin skin; private final ISkinParam skinParam; - private final Display notes; private final LivingSpace livingSpace; + private final NoteOnMessage noteOnMessage; public Event getEvent() { return message; @@ -64,12 +64,12 @@ public class CommunicationTileNoteRight implements TileWithUpdateStairs, TileWit } public CommunicationTileNoteRight(TileWithUpdateStairs tile, AbstractMessage message, Skin skin, - ISkinParam skinParam, LivingSpace livingSpace) { + ISkinParam skinParam, LivingSpace livingSpace, NoteOnMessage noteOnMessage) { this.tile = tile; this.message = message; this.skin = skin; this.skinParam = skinParam; - this.notes = message.getNote(); + this.noteOnMessage = noteOnMessage; this.livingSpace = livingSpace; } @@ -79,7 +79,7 @@ public class CommunicationTileNoteRight implements TileWithUpdateStairs, TileWit private Component getComponent(StringBounder stringBounder) { final Component comp = skin.createComponent(ComponentType.NOTE, null, - message.getSkinParamNoteBackcolored(skinParam), notes); + noteOnMessage.getSkinParamNoteBackcolored(skinParam), noteOnMessage.getDisplay()); return comp; } diff --git a/src/net/sourceforge/plantuml/sequencediagram/teoz/CommunicationTileSelfNoteRight.java b/src/net/sourceforge/plantuml/sequencediagram/teoz/CommunicationTileSelfNoteRight.java index 1535890af..abe2d257a 100644 --- a/src/net/sourceforge/plantuml/sequencediagram/teoz/CommunicationTileSelfNoteRight.java +++ b/src/net/sourceforge/plantuml/sequencediagram/teoz/CommunicationTileSelfNoteRight.java @@ -33,11 +33,11 @@ package net.sourceforge.plantuml.sequencediagram.teoz; import java.awt.geom.Dimension2D; import net.sourceforge.plantuml.ISkinParam; -import net.sourceforge.plantuml.cucadiagram.Display; import net.sourceforge.plantuml.graphic.StringBounder; import net.sourceforge.plantuml.real.Real; import net.sourceforge.plantuml.sequencediagram.Event; import net.sourceforge.plantuml.sequencediagram.Message; +import net.sourceforge.plantuml.sequencediagram.NoteOnMessage; import net.sourceforge.plantuml.skin.Area; import net.sourceforge.plantuml.skin.Component; import net.sourceforge.plantuml.skin.ComponentType; @@ -52,32 +52,28 @@ public class CommunicationTileSelfNoteRight implements TileWithUpdateStairs { private final Message message; private final Skin skin; private final ISkinParam skinParam; - private final Display notes; + private final NoteOnMessage noteOnMessage; - // private final NotePosition notePosition; - // private final LivingSpace livingSpace; - public Event getEvent() { return message; } - - public CommunicationTileSelfNoteRight(CommunicationTileSelf tile, Message message, Skin skin, ISkinParam skinParam) { + public CommunicationTileSelfNoteRight(CommunicationTileSelf tile, Message message, Skin skin, ISkinParam skinParam, + NoteOnMessage noteOnMessage) { this.tile = tile; this.message = message; this.skin = skin; this.skinParam = skinParam; - this.notes = message.getNote(); - // this.notePosition = message.getNotePosition(); + this.noteOnMessage = noteOnMessage; } - + public void updateStairs(StringBounder stringBounder, double y) { tile.updateStairs(stringBounder, y); } - private Component getComponent(StringBounder stringBounder) { - final Component comp = skin.createComponent(ComponentType.NOTE, null, message.getSkinParamNoteBackcolored(skinParam), notes); + final Component comp = skin.createComponent(ComponentType.NOTE, null, + noteOnMessage.getSkinParamNoteBackcolored(skinParam), noteOnMessage.getDisplay()); return comp; } diff --git a/src/net/sourceforge/plantuml/sequencediagram/teoz/SequenceDiagramFileMakerTeoz.java b/src/net/sourceforge/plantuml/sequencediagram/teoz/SequenceDiagramFileMakerTeoz.java index 7c26a6ca3..5f5736259 100644 --- a/src/net/sourceforge/plantuml/sequencediagram/teoz/SequenceDiagramFileMakerTeoz.java +++ b/src/net/sourceforge/plantuml/sequencediagram/teoz/SequenceDiagramFileMakerTeoz.java @@ -34,6 +34,7 @@ import java.awt.geom.Dimension2D; import java.io.IOException; import java.io.OutputStream; +import net.sourceforge.plantuml.AnnotatedWorker; import net.sourceforge.plantuml.Dimension2DDouble; import net.sourceforge.plantuml.FileFormatOption; import net.sourceforge.plantuml.FontParam; @@ -42,6 +43,7 @@ import net.sourceforge.plantuml.activitydiagram3.ftile.EntityImageLegend; import net.sourceforge.plantuml.core.ImageData; import net.sourceforge.plantuml.cucadiagram.Display; import net.sourceforge.plantuml.cucadiagram.DisplayPositionned; +import net.sourceforge.plantuml.graphic.FontConfiguration; import net.sourceforge.plantuml.graphic.HorizontalAlignment; import net.sourceforge.plantuml.graphic.HtmlColor; import net.sourceforge.plantuml.graphic.StringBounder; @@ -56,8 +58,6 @@ import net.sourceforge.plantuml.real.RealUtils; import net.sourceforge.plantuml.sequencediagram.Participant; import net.sourceforge.plantuml.sequencediagram.SequenceDiagram; import net.sourceforge.plantuml.sequencediagram.graphic.FileMaker; -import net.sourceforge.plantuml.skin.Component; -import net.sourceforge.plantuml.skin.ComponentType; import net.sourceforge.plantuml.skin.SimpleContext2D; import net.sourceforge.plantuml.skin.Skin; import net.sourceforge.plantuml.ugraphic.ImageBuilder; @@ -70,6 +70,7 @@ public class SequenceDiagramFileMakerTeoz implements FileMaker { private final SequenceDiagram diagram; private final FileFormatOption fileFormatOption; private final Skin skin; + private final AnnotatedWorker annotatedWorker; public SequenceDiagramFileMakerTeoz(SequenceDiagram sequenceDiagram, Skin skin, FileFormatOption fileFormatOption) { this.stringBounder = fileFormatOption.getDefaultStringBounder(); @@ -78,12 +79,14 @@ public class SequenceDiagramFileMakerTeoz implements FileMaker { this.skin = skin; this.footer = getFooterOrHeader(FontParam.FOOTER); this.header = getFooterOrHeader(FontParam.HEADER); + this.annotatedWorker = new AnnotatedWorker(sequenceDiagram, sequenceDiagram.getSkinParam()); this.main = new MainTileAdapter(createMainTile()); this.min1 = ((MainTileAdapter) main).getMinX(stringBounder); this.title = getTitle(); this.legend = getLegend(); + this.caption = annotatedWorker.getCaption(); this.heightEnglober1 = englobers.getOffsetForEnglobers(stringBounder); this.heightEnglober2 = heightEnglober1 == 0 ? 0 : 10; @@ -111,13 +114,14 @@ public class SequenceDiagramFileMakerTeoz implements FileMaker { private final TextBlock title; private final TextBlock legend; + private final TextBlock caption; private final Dimension2D dimTotal; private final Real min1; private final LivingSpaces livingSpaces = new LivingSpaces(); private final double heightEnglober1; private final double heightEnglober2; - + private double oneOf(double a, double b) { if (a == 1) { return b; @@ -125,7 +129,6 @@ public class SequenceDiagramFileMakerTeoz implements FileMaker { return a; } - public ImageData createOne(OutputStream os, int index, boolean isWithMetadata) throws IOException { final UTranslate min1translate = new UTranslate(-min1.getCurrentValue(), 0); final double dpiFactor = diagram.getDpiFactor(fileFormatOption, dimTotal); @@ -133,12 +136,11 @@ public class SequenceDiagramFileMakerTeoz implements FileMaker { final double scale = 1; final String metadata = fileFormatOption.isWithMetadata() ? diagram.getMetadata() : null; - final ImageBuilder imageBuilder = new ImageBuilder(diagram.getSkinParam().getColorMapper(), oneOf(scale, - dpiFactor), diagram.getSkinParam().getBackgroundColor(), metadata, null, 3, 10, diagram.getAnimation(), - diagram.getSkinParam().handwritten()); - + final ImageBuilder imageBuilder = new ImageBuilder(diagram.getSkinParam(), oneOf(scale, dpiFactor), metadata, + null, 3, 10, diagram.getAnimation()); + imageBuilder.setUDrawable(new UDrawable() { - + public void drawU(UGraphic ug) { ug = ug.apply(min1translate); englobers.drawEnglobers(goDownForEnglobers(ug), main.calculateDimension(stringBounder).getHeight() @@ -146,28 +148,29 @@ public class SequenceDiagramFileMakerTeoz implements FileMaker { printAligned(ug, diagram.getFooterOrHeaderTeoz(FontParam.HEADER).getHorizontalAlignment(), header); ug = goDown(ug, header); - + printAligned(ug, HorizontalAlignment.CENTER, title); ug = goDown(ug, title); - + if (diagram.getLegend().getVerticalAlignment() == VerticalAlignment.TOP) { printAligned(ug, diagram.getLegend().getHorizontalAlignment(), legend); ug = goDown(ug, legend); } - + ug = ug.apply(new UTranslate(0, heightEnglober1)); printAligned(ug, HorizontalAlignment.CENTER, main); ug = goDown(ug, main); ug = ug.apply(new UTranslate(0, heightEnglober2)); - + + printAligned(ug, HorizontalAlignment.CENTER, caption); + if (diagram.getLegend().getVerticalAlignment() == VerticalAlignment.BOTTOM) { printAligned(ug, diagram.getLegend().getHorizontalAlignment(), legend); ug = goDown(ug, legend); } - + printAligned(ug, diagram.getFooterOrHeaderTeoz(FontParam.FOOTER).getHorizontalAlignment(), footer); - - + } }); return imageBuilder.writeImageTOBEMOVED(fileFormatOption, os); @@ -228,9 +231,9 @@ public class SequenceDiagramFileMakerTeoz implements FileMaker { if (DisplayPositionned.isNull(diagram.getTitle())) { return new ComponentAdapter(null); } - final Component compTitle = skin.createComponent(ComponentType.TITLE, null, getSkinParam(), diagram.getTitle() - .getDisplay()); - return new ComponentAdapter(compTitle); + final TextBlock compTitle = TextBlockUtils.title(new FontConfiguration(getSkinParam(), + FontParam.SEQUENCE_TITLE, null), diagram.getTitle().getDisplay(), getSkinParam()); + return TextBlockUtils.withMargin(compTitle, 7, 7); } private TextBlock getLegend() { diff --git a/src/net/sourceforge/plantuml/sequencediagram/teoz/TileBuilder.java b/src/net/sourceforge/plantuml/sequencediagram/teoz/TileBuilder.java index a217e7a40..4d66bb137 100644 --- a/src/net/sourceforge/plantuml/sequencediagram/teoz/TileBuilder.java +++ b/src/net/sourceforge/plantuml/sequencediagram/teoz/TileBuilder.java @@ -49,6 +49,7 @@ import net.sourceforge.plantuml.sequencediagram.LifeEvent; import net.sourceforge.plantuml.sequencediagram.Message; import net.sourceforge.plantuml.sequencediagram.MessageExo; import net.sourceforge.plantuml.sequencediagram.Note; +import net.sourceforge.plantuml.sequencediagram.NoteOnMessage; import net.sourceforge.plantuml.sequencediagram.NotePosition; import net.sourceforge.plantuml.sequencediagram.Notes; import net.sourceforge.plantuml.sequencediagram.Reference; @@ -90,16 +91,17 @@ public class TileBuilder { result = new CommunicationTile(livingSpace1, livingSpace2, msg, skin, skinParam); reverse = ((CommunicationTile) result).isReverse(stringBounder); } - if (msg.getNote() != null) { - final NotePosition notePosition = msg.getNotePosition(); + for (NoteOnMessage noteOnMessage : msg.getNoteOnMessages()) { + final NotePosition notePosition = noteOnMessage.getNotePosition(); if (notePosition == NotePosition.LEFT) { result = new CommunicationTileNoteLeft((TileWithUpdateStairs) result, msg, skin, skinParam, - reverse ? livingSpace2 : livingSpace1); + reverse ? livingSpace2 : livingSpace1, noteOnMessage); } else if (notePosition == NotePosition.RIGHT && msg.isSelfMessage()) { - result = new CommunicationTileSelfNoteRight((CommunicationTileSelf) result, msg, skin, skinParam); + result = new CommunicationTileSelfNoteRight((CommunicationTileSelf) result, msg, skin, skinParam, + noteOnMessage); } else if (notePosition == NotePosition.RIGHT) { result = new CommunicationTileNoteRight((TileWithUpdateStairs) result, msg, skin, skinParam, - reverse ? livingSpace1 : livingSpace2); + reverse ? livingSpace1 : livingSpace2, noteOnMessage); } } tiles.add(result); @@ -108,14 +110,14 @@ public class TileBuilder { final LivingSpace livingSpace1 = livingSpaces.get(exo.getParticipant()); Tile result = null; result = new CommunicationExoTile(livingSpace1, exo, skin, skinParam, tileArguments); - if (exo.getNote() != null) { - final NotePosition notePosition = exo.getNotePosition(); + for (NoteOnMessage noteOnMessage : exo.getNoteOnMessages()) { + final NotePosition notePosition = exo.getNoteOnMessages().get(0).getNotePosition(); if (notePosition == NotePosition.LEFT) { result = new CommunicationTileNoteLeft((TileWithUpdateStairs) result, exo, skin, skinParam, - livingSpace1); + livingSpace1, noteOnMessage); } else if (notePosition == NotePosition.RIGHT) { result = new CommunicationTileNoteRight((TileWithUpdateStairs) result, exo, skin, skinParam, - livingSpace1); + livingSpace1, noteOnMessage); } } tiles.add(result); diff --git a/src/net/sourceforge/plantuml/skin/ComponentType.java b/src/net/sourceforge/plantuml/skin/ComponentType.java index eadb403d3..0fba8de88 100644 --- a/src/net/sourceforge/plantuml/skin/ComponentType.java +++ b/src/net/sourceforge/plantuml/skin/ComponentType.java @@ -55,10 +55,10 @@ public enum ComponentType { NEWPAGE, NOTE, NOTE_HEXAGONAL, NOTE_BOX, DIVIDER, REFERENCE, ENGLOBER, // - PARTICIPANT_HEAD, PARTICIPANT_TAIL, + PARTICIPANT_HEAD, PARTICIPANT_TAIL // - TITLE, SIGNATURE; + /*TITLE, SIGNATURE*/; public boolean isArrow() { return this == ARROW; diff --git a/src/net/sourceforge/plantuml/skin/bluemodern/BlueModern.java b/src/net/sourceforge/plantuml/skin/bluemodern/BlueModern.java index 4fc3c6920..b1f1d0fd9 100644 --- a/src/net/sourceforge/plantuml/skin/bluemodern/BlueModern.java +++ b/src/net/sourceforge/plantuml/skin/bluemodern/BlueModern.java @@ -48,7 +48,6 @@ import net.sourceforge.plantuml.skin.rose.ComponentRoseDestroy; import net.sourceforge.plantuml.skin.rose.ComponentRoseGroupingElse; import net.sourceforge.plantuml.skin.rose.ComponentRoseGroupingSpace; import net.sourceforge.plantuml.skin.rose.ComponentRoseReference; -import net.sourceforge.plantuml.skin.rose.ComponentRoseTitle; import net.sourceforge.plantuml.skin.rose.Rose; import net.sourceforge.plantuml.ugraphic.UFont; @@ -146,10 +145,10 @@ public class BlueModern implements Skin { if (type == ComponentType.GROUPING_SPACE) { return new ComponentRoseGroupingSpace(7); } - if (type == ComponentType.TITLE) { - return new ComponentRoseTitle(bigFont.toFont2(HtmlColorUtils.BLACK, useUnderlineForHyperlink, - hyperlinkColor, param.getTabSize()), stringsToDisplay, param); - } + // if (type == ComponentType.TITLE) { + // return new ComponentRoseTitle(bigFont.toFont2(HtmlColorUtils.BLACK, useUnderlineForHyperlink, + // hyperlinkColor, param.getTabSize()), stringsToDisplay, param); + // } if (type == ComponentType.REFERENCE) { return new ComponentRoseReference(normalFont.toFont2(HtmlColorUtils.BLACK, useUnderlineForHyperlink, hyperlinkColor, param.getTabSize()), new SymbolContext(blue1, borderGroupColor).withStroke(Rose @@ -164,15 +163,15 @@ public class BlueModern implements Skin { return new ComponentBlueModernDivider(normalFont.toFont2(HtmlColorUtils.BLACK, useUnderlineForHyperlink, hyperlinkColor, param.getTabSize()), blue2, blue1, HtmlColorUtils.BLACK, stringsToDisplay, param); } - if (type == ComponentType.SIGNATURE) { - return new ComponentRoseTitle(smallFont.toFont2(HtmlColorUtils.BLACK, useUnderlineForHyperlink, - hyperlinkColor, param.getTabSize()), Display.create("This skin was created ", "in April 2009."), - param); - } + // if (type == ComponentType.SIGNATURE) { + // return new ComponentRoseTitle(smallFont.toFont2(HtmlColorUtils.BLACK, useUnderlineForHyperlink, + // hyperlinkColor, param.getTabSize()), Display.create("This skin was created ", "in April 2009."), + // param); + // } if (type == ComponentType.ENGLOBER) { - return new ComponentBlueModernEnglober(blue1, blue3, stringsToDisplay, param.getFont( - null, false, FontParam.SEQUENCE_BOX).toFont2(HtmlColorUtils.BLACK, useUnderlineForHyperlink, - hyperlinkColor, param.getTabSize()), param); + return new ComponentBlueModernEnglober(blue1, blue3, stringsToDisplay, param.getFont(null, false, + FontParam.SEQUENCE_BOX).toFont2(HtmlColorUtils.BLACK, useUnderlineForHyperlink, hyperlinkColor, + param.getTabSize()), param); } return null; diff --git a/src/net/sourceforge/plantuml/skin/rose/Rose.java b/src/net/sourceforge/plantuml/skin/rose/Rose.java index 21c6d8b91..ef832975d 100644 --- a/src/net/sourceforge/plantuml/skin/rose/Rose.java +++ b/src/net/sourceforge/plantuml/skin/rose/Rose.java @@ -41,7 +41,6 @@ import net.sourceforge.plantuml.cucadiagram.Stereotype; import net.sourceforge.plantuml.graphic.FontConfiguration; import net.sourceforge.plantuml.graphic.HorizontalAlignment; import net.sourceforge.plantuml.graphic.HtmlColor; -import net.sourceforge.plantuml.graphic.HtmlColorUtils; import net.sourceforge.plantuml.graphic.SymbolContext; import net.sourceforge.plantuml.skin.ArrowConfiguration; import net.sourceforge.plantuml.skin.ArrowDirection; @@ -68,9 +67,6 @@ public class Rose implements Skin { HtmlColor result = param.getHtmlColor(color, stereotype, false); if (result == null) { result = color.getDefaultValue(); - if (result == null) { - throw new IllegalArgumentException(); - } } return result; } @@ -96,32 +92,32 @@ public class Rose implements Skin { return new ComponentRoseSelfArrow(sequenceArrow, getUFont2(param, FontParam.SEQUENCE_ARROW), stringsToDisplay, config, param, param.maxMessageSize(), param.strictUmlStyle() == false); } - final HorizontalAlignment messageHorizontalAlignment = param - .getHorizontalAlignment(AlignParam.SEQUENCE_MESSAGE_ALIGN); - final HorizontalAlignment textHorizontalAlignment = param - .getHorizontalAlignment(AlignParam.SEQUENCE_MESSAGETEXT_ALIGN); + final HorizontalAlignment messageHorizontalAlignment = param.getHorizontalAlignment( + AlignParam.SEQUENCE_MESSAGE_ALIGN, config.getArrowDirection()); + final HorizontalAlignment textHorizontalAlignment = param.getHorizontalAlignment( + AlignParam.SEQUENCE_MESSAGETEXT_ALIGN, config.getArrowDirection()); return new ComponentRoseArrow(sequenceArrow, getUFont2(param, FontParam.SEQUENCE_ARROW), stringsToDisplay, config, messageHorizontalAlignment, param, textHorizontalAlignment, param.maxMessageSize(), param.strictUmlStyle() == false); } if (type == ComponentType.PARTICIPANT_HEAD) { return new ComponentRoseParticipant(getSymbolContext(param, ColorParam.participantBorder), getUFont2(param, - FontParam.PARTICIPANT), stringsToDisplay, param, param.getRoundCorner(), newFontForStereotype, + FontParam.PARTICIPANT), stringsToDisplay, param, param.getRoundCorner(""), newFontForStereotype, getFontColor(param, FontParam.SEQUENCE_STEREOTYPE), param.minClassWidth(), false); } if (type == ComponentType.PARTICIPANT_TAIL) { return new ComponentRoseParticipant(getSymbolContext(param, ColorParam.participantBorder), getUFont2(param, - FontParam.PARTICIPANT), stringsToDisplay, param, param.getRoundCorner(), newFontForStereotype, + FontParam.PARTICIPANT), stringsToDisplay, param, param.getRoundCorner(""), newFontForStereotype, getFontColor(param, FontParam.SEQUENCE_STEREOTYPE), param.minClassWidth(), false); } if (type == ComponentType.COLLECTIONS_HEAD) { return new ComponentRoseParticipant(getSymbolContext(param, ColorParam.participantBorder), getUFont2(param, - FontParam.PARTICIPANT), stringsToDisplay, param, param.getRoundCorner(), newFontForStereotype, + FontParam.PARTICIPANT), stringsToDisplay, param, param.getRoundCorner(""), newFontForStereotype, getFontColor(param, FontParam.SEQUENCE_STEREOTYPE), param.minClassWidth(), true); } if (type == ComponentType.COLLECTIONS_TAIL) { return new ComponentRoseParticipant(getSymbolContext(param, ColorParam.participantBorder), getUFont2(param, - FontParam.PARTICIPANT), stringsToDisplay, param, param.getRoundCorner(), newFontForStereotype, + FontParam.PARTICIPANT), stringsToDisplay, param, param.getRoundCorner(""), newFontForStereotype, getFontColor(param, FontParam.SEQUENCE_STEREOTYPE), param.minClassWidth(), true); } if (type == ComponentType.PARTICIPANT_LINE) { @@ -143,42 +139,42 @@ public class Rose implements Skin { FontParam.SEQUENCE_STEREOTYPE)); } if (type == ComponentType.BOUNDARY_HEAD) { - return new ComponentRoseBoundary(getSymbolContext(param, ColorParam.actorBorder), getUFont2(param, + return new ComponentRoseBoundary(getSymbolContext(param, ColorParam.boundaryBorder), getUFont2(param, FontParam.ACTOR), stringsToDisplay, true, param, newFontForStereotype, getFontColor(param, FontParam.SEQUENCE_STEREOTYPE)); } if (type == ComponentType.BOUNDARY_TAIL) { - return new ComponentRoseBoundary(getSymbolContext(param, ColorParam.actorBorder), getUFont2(param, + return new ComponentRoseBoundary(getSymbolContext(param, ColorParam.boundaryBorder), getUFont2(param, FontParam.ACTOR), stringsToDisplay, false, param, newFontForStereotype, getFontColor(param, FontParam.SEQUENCE_STEREOTYPE)); } if (type == ComponentType.CONTROL_HEAD) { - return new ComponentRoseControl(getSymbolContext(param, ColorParam.actorBorder), getUFont2(param, + return new ComponentRoseControl(getSymbolContext(param, ColorParam.controlBorder), getUFont2(param, FontParam.ACTOR), stringsToDisplay, true, param, newFontForStereotype, getFontColor(param, FontParam.SEQUENCE_STEREOTYPE)); } if (type == ComponentType.CONTROL_TAIL) { - return new ComponentRoseControl(getSymbolContext(param, ColorParam.actorBorder), getUFont2(param, + return new ComponentRoseControl(getSymbolContext(param, ColorParam.controlBorder), getUFont2(param, FontParam.ACTOR), stringsToDisplay, false, param, newFontForStereotype, getFontColor(param, FontParam.SEQUENCE_STEREOTYPE)); } if (type == ComponentType.ENTITY_HEAD) { - return new ComponentRoseEntity(getSymbolContext(param, ColorParam.actorBorder), getUFont2(param, + return new ComponentRoseEntity(getSymbolContext(param, ColorParam.entityBorder), getUFont2(param, FontParam.ACTOR), stringsToDisplay, true, param, newFontForStereotype, getFontColor(param, FontParam.SEQUENCE_STEREOTYPE)); } if (type == ComponentType.ENTITY_TAIL) { - return new ComponentRoseEntity(getSymbolContext(param, ColorParam.actorBorder), getUFont2(param, + return new ComponentRoseEntity(getSymbolContext(param, ColorParam.entityBorder), getUFont2(param, FontParam.ACTOR), stringsToDisplay, false, param, newFontForStereotype, getFontColor(param, FontParam.SEQUENCE_STEREOTYPE)); } if (type == ComponentType.DATABASE_HEAD) { - return new ComponentRoseDatabase(getSymbolContext(param, ColorParam.actorBorder), getUFont2(param, + return new ComponentRoseDatabase(getSymbolContext(param, ColorParam.databaseBorder), getUFont2(param, FontParam.ACTOR), stringsToDisplay, true, param, newFontForStereotype, getFontColor(param, FontParam.SEQUENCE_STEREOTYPE)); } if (type == ComponentType.DATABASE_TAIL) { - return new ComponentRoseDatabase(getSymbolContext(param, ColorParam.actorBorder), getUFont2(param, + return new ComponentRoseDatabase(getSymbolContext(param, ColorParam.databaseBorder), getUFont2(param, FontParam.ACTOR), stringsToDisplay, false, param, newFontForStereotype, getFontColor(param, FontParam.SEQUENCE_STEREOTYPE)); } @@ -242,18 +238,18 @@ public class Rose implements Skin { } if (type == ComponentType.REFERENCE) { return new ComponentRoseReference(getUFont2(param, FontParam.SEQUENCE_REFERENCE), getSymbolContext(param, - ColorParam.sequenceReferenceBorder), bigFont, stringsToDisplay, - param.getHorizontalAlignment(AlignParam.SEQUENCE_REFERENCE_ALIGN), param, getHtmlColor(param, - ColorParam.sequenceReferenceBackground)); - } - if (type == ComponentType.TITLE) { - return new ComponentRoseTitle(getUFont2(param, FontParam.SEQUENCE_TITLE), stringsToDisplay, param); - } - if (type == ComponentType.SIGNATURE) { - return new ComponentRoseTitle(fontGrouping.toFont2(HtmlColorUtils.BLACK, param.useUnderlineForHyperlink(), - param.getHyperlinkColor(), param.getTabSize()), Display.create("This skin was created ", - "in April 2009."), param); + ColorParam.sequenceReferenceBorder), bigFont, stringsToDisplay, param.getHorizontalAlignment( + AlignParam.SEQUENCE_REFERENCE_ALIGN, null), param, getHtmlColor(param, + ColorParam.sequenceReferenceBackground)); } + // if (type == ComponentType.TITLE) { + // return new ComponentRoseTitle(getUFont2(param, FontParam.SEQUENCE_TITLE), stringsToDisplay, param); + // } + // if (type == ComponentType.SIGNATURE) { + // return new ComponentRoseTitle(fontGrouping.toFont2(HtmlColorUtils.BLACK, param.useUnderlineForHyperlink(), + // param.getHyperlinkColor(), param.getTabSize()), Display.create("This skin was created ", + // "in April 2009."), param); + // } if (type == ComponentType.ENGLOBER) { return new ComponentRoseEnglober(getSymbolContext(param, ColorParam.sequenceBoxBorder), stringsToDisplay, getUFont2(param, FontParam.SEQUENCE_BOX), param); @@ -277,6 +273,26 @@ public class Rose implements Skin { ColorParam.actorBorder)).withStroke(getStroke(param, LineParam.sequenceActorBorder, 2)) .withDeltaShadow(deltaShadow(param)); } + if (color == ColorParam.boundaryBorder) { + return new SymbolContext(getHtmlColor(param, ColorParam.boundaryBackground), getHtmlColor(param, + ColorParam.boundaryBorder)).withStroke(getStroke(param, LineParam.sequenceActorBorder, 2)) + .withDeltaShadow(deltaShadow(param)); + } + if (color == ColorParam.controlBorder) { + return new SymbolContext(getHtmlColor(param, ColorParam.controlBackground), getHtmlColor(param, + ColorParam.controlBorder)).withStroke(getStroke(param, LineParam.sequenceActorBorder, 2)) + .withDeltaShadow(deltaShadow(param)); + } + if (color == ColorParam.entityBorder) { + return new SymbolContext(getHtmlColor(param, ColorParam.entityBackground), getHtmlColor(param, + ColorParam.entityBorder)).withStroke(getStroke(param, LineParam.sequenceActorBorder, 2)) + .withDeltaShadow(deltaShadow(param)); + } + if (color == ColorParam.databaseBorder) { + return new SymbolContext(getHtmlColor(param, ColorParam.databaseBackground), getHtmlColor(param, + ColorParam.databaseBorder)).withStroke(getStroke(param, LineParam.sequenceActorBorder, 2)) + .withDeltaShadow(deltaShadow(param)); + } if (color == ColorParam.sequenceLifeLineBorder) { return new SymbolContext(getHtmlColor(param, ColorParam.sequenceLifeLineBackground), getHtmlColor(param, ColorParam.sequenceLifeLineBorder)).withDeltaShadow(deltaShadow(param)); diff --git a/src/net/sourceforge/plantuml/suggest/SuggestEngine.java b/src/net/sourceforge/plantuml/suggest/SuggestEngine.java index 2a8135ffd..0ad6d8c8e 100644 --- a/src/net/sourceforge/plantuml/suggest/SuggestEngine.java +++ b/src/net/sourceforge/plantuml/suggest/SuggestEngine.java @@ -49,7 +49,7 @@ import net.sourceforge.plantuml.version.IteratorCounter2Impl; final public class SuggestEngine { - private static final int LIMIT = 500; + private static final int LIMIT = 120; private final UmlDiagramFactory systemFactory; diff --git a/src/net/sourceforge/plantuml/svek/Cluster.java b/src/net/sourceforge/plantuml/svek/Cluster.java index 8306bcabc..aa620d99b 100644 --- a/src/net/sourceforge/plantuml/svek/Cluster.java +++ b/src/net/sourceforge/plantuml/svek/Cluster.java @@ -555,7 +555,7 @@ public class Cluster implements Moveable { added = true; } - if (dotMode != DotMode.NO_LEFT_RIGHT) { + if (dotMode != DotMode.NO_LEFT_RIGHT_AND_XLABEL) { appendRankSame(sb, lines); } diff --git a/src/net/sourceforge/plantuml/svek/CucaDiagramFileMakerSvek.java b/src/net/sourceforge/plantuml/svek/CucaDiagramFileMakerSvek.java index 4098c3fda..2322b97c9 100644 --- a/src/net/sourceforge/plantuml/svek/CucaDiagramFileMakerSvek.java +++ b/src/net/sourceforge/plantuml/svek/CucaDiagramFileMakerSvek.java @@ -74,7 +74,8 @@ public final class CucaDiagramFileMakerSvek implements CucaDiagramFileMaker { diagram.getLeafsvalues(), diagram.getUmlDiagramType(), diagram.getSkinParam(), diagram, diagram, diagram.getColorMapper(), diagram.getEntityFactory(), diagram.isHideEmptyDescriptionForState(), dotMode, diagram.getNamespaceSeparator(), diagram.getPragma()); - return new DotDataImageBuilder(dotData, diagram.getEntityFactory(), diagram.getSource(), diagram.getPragma(), stringBounder); + return new DotDataImageBuilder(dotData, diagram.getEntityFactory(), diagram.getSource(), diagram.getPragma(), + stringBounder); } @@ -87,7 +88,8 @@ public final class CucaDiagramFileMakerSvek implements CucaDiagramFileMaker { } // System.err.println("FOO11 type=" + os.getClass()); - DotDataImageBuilder svek2 = createDotDataImageBuilder(DotMode.NORMAL, fileFormatOption.getDefaultStringBounder()); + DotDataImageBuilder svek2 = createDotDataImageBuilder(DotMode.NORMAL, + fileFormatOption.getDefaultStringBounder()); BaseFile basefile = null; if (fileFormatOption.isDebugSvek() && os instanceof NamedOutputStream) { basefile = ((NamedOutputStream) os).getBasefile(); @@ -96,7 +98,8 @@ public final class CucaDiagramFileMakerSvek implements CucaDiagramFileMaker { TextBlockBackcolored result = svek2.buildImage(basefile, diagram.getDotStringSkek()); if (result instanceof GraphvizCrash) { - svek2 = createDotDataImageBuilder(DotMode.NO_LEFT_RIGHT, fileFormatOption.getDefaultStringBounder()); + svek2 = createDotDataImageBuilder(DotMode.NO_LEFT_RIGHT_AND_XLABEL, + fileFormatOption.getDefaultStringBounder()); result = svek2.buildImage(basefile, diagram.getDotStringSkek()); } result = new AnnotatedWorker(diagram, diagram.getSkinParam()).addAdd(result); @@ -109,9 +112,9 @@ public final class CucaDiagramFileMakerSvek implements CucaDiagramFileMaker { final Dimension2D dim = result.calculateDimension(fileFormatOption.getDefaultStringBounder()); final double scale = getScale(fileFormatOption, dim); - final ImageBuilder imageBuilder = new ImageBuilder(diagram.getSkinParam().getColorMapper(), scale, - result.getBackcolor(), fileFormatOption.isWithMetadata() ? diagram.getMetadata() : null, - warningOrError, 0, 10, diagram.getAnimation(), diagram.getSkinParam().handwritten()); + final ImageBuilder imageBuilder = new ImageBuilder(diagram.getSkinParam(), + scale, fileFormatOption.isWithMetadata() ? diagram.getMetadata() : null, warningOrError, 0, + 10, diagram.getAnimation(), result.getBackcolor()); imageBuilder.setUDrawable(result); return imageBuilder.writeImageTOBEMOVED(fileFormatOption, os); diff --git a/src/net/sourceforge/plantuml/svek/DotDataImageBuilder.java b/src/net/sourceforge/plantuml/svek/DotDataImageBuilder.java index e8a8dab78..81d6b784c 100644 --- a/src/net/sourceforge/plantuml/svek/DotDataImageBuilder.java +++ b/src/net/sourceforge/plantuml/svek/DotDataImageBuilder.java @@ -386,7 +386,7 @@ public final class DotDataImageBuilder { // return new EntityImageCircleInterface(leaf, skinParam); // } if (leaf.getEntityType() == LeafType.OBJECT) { - return new EntityImageObject(leaf, skinParam); + return new EntityImageObject(leaf, skinParam, portionShower); } if (leaf.getEntityType() == LeafType.SYNCHRO_BAR || leaf.getEntityType() == LeafType.STATE_FORK_JOIN) { return new EntityImageSynchroBar(leaf, skinParam); diff --git a/src/net/sourceforge/plantuml/svek/DotMode.java b/src/net/sourceforge/plantuml/svek/DotMode.java index 3d1e0ea82..f77aea81a 100644 --- a/src/net/sourceforge/plantuml/svek/DotMode.java +++ b/src/net/sourceforge/plantuml/svek/DotMode.java @@ -31,6 +31,6 @@ package net.sourceforge.plantuml.svek; public enum DotMode { - NORMAL, NO_LEFT_RIGHT + NORMAL, NO_LEFT_RIGHT_AND_XLABEL } diff --git a/src/net/sourceforge/plantuml/svek/DotStringFactory.java b/src/net/sourceforge/plantuml/svek/DotStringFactory.java index 17d509725..7acf120a8 100644 --- a/src/net/sourceforge/plantuml/svek/DotStringFactory.java +++ b/src/net/sourceforge/plantuml/svek/DotStringFactory.java @@ -201,14 +201,14 @@ public class DotStringFactory implements Moveable { root.printCluster1(sb, bibliotekon.allLines(), stringBounder); for (Line line : bibliotekon.lines0()) { - line.appendLine(getGraphvizVersion(), sb); + line.appendLine(getGraphvizVersion(), sb, dotMode); } root.fillRankMin(rankMin); root.printCluster2(sb, bibliotekon.allLines(), stringBounder, dotMode, getGraphvizVersion(), umlDiagramType); printMinRanking(sb); for (Line line : bibliotekon.lines1()) { - line.appendLine(getGraphvizVersion(), sb); + line.appendLine(getGraphvizVersion(), sb, dotMode); } SvekUtils.println(sb); sb.append("}"); diff --git a/src/net/sourceforge/plantuml/svek/Line.java b/src/net/sourceforge/plantuml/svek/Line.java index 0573556fe..ca154c93f 100644 --- a/src/net/sourceforge/plantuml/svek/Line.java +++ b/src/net/sourceforge/plantuml/svek/Line.java @@ -317,7 +317,7 @@ public class Line implements Moveable, Hideable { return link.getLinkArrow(); } - public void appendLine(GraphvizVersion graphvizVersion, StringBuilder sb) { + public void appendLine(GraphvizVersion graphvizVersion, StringBuilder sb, DotMode dotMode) { // Log.println("inverted=" + isInverted()); // if (isInverted()) { // sb.append(endUid); @@ -349,7 +349,7 @@ public class Line implements Moveable, Hideable { sb.append("color=\"" + StringUtils.getAsHtml(lineColor) + "\""); if (labelText != null) { sb.append(","); - if (graphvizVersion.modeSafe()) { + if (graphvizVersion.modeSafe() || dotMode == DotMode.NO_LEFT_RIGHT_AND_XLABEL) { sb.append("xlabel=<"); } else { sb.append("label=<"); @@ -682,11 +682,11 @@ public class Line implements Moveable, Hideable { this.labelText.drawU(ug.apply(new UTranslate(x + this.labelXY.getPosition().getX(), y + this.labelXY.getPosition().getY()))); } - if (this.startTailText != null) { + if (this.startTailText != null && this.startTailLabelXY != null && this.startTailLabelXY.getPosition() != null) { this.startTailText.drawU(ug.apply(new UTranslate(x + this.startTailLabelXY.getPosition().getX(), y + this.startTailLabelXY.getPosition().getY()))); } - if (this.endHeadText != null) { + if (this.endHeadText != null && this.endHeadLabelXY != null && this.endHeadLabelXY.getPosition() != null) { this.endHeadText.drawU(ug.apply(new UTranslate(x + this.endHeadLabelXY.getPosition().getX(), y + this.endHeadLabelXY.getPosition().getY()))); } diff --git a/src/net/sourceforge/plantuml/svek/image/EntityImageClass.java b/src/net/sourceforge/plantuml/svek/image/EntityImageClass.java index 5d8baafaf..f5754f768 100644 --- a/src/net/sourceforge/plantuml/svek/image/EntityImageClass.java +++ b/src/net/sourceforge/plantuml/svek/image/EntityImageClass.java @@ -77,7 +77,7 @@ public class EntityImageClass extends AbstractEntityImage implements Stencil, Wi public EntityImageClass(GraphvizVersion version, ILeaf entity, ISkinParam skinParam, PortionShower portionShower) { super(entity, entity.getColors(skinParam).mute(skinParam)); this.lineConfig = entity; - this.roundCorner = getSkinParam().getRoundCorner(); + this.roundCorner = getSkinParam().getRoundCorner(""); this.shield = version != null && version.useShield() && entity.hasNearDecoration() ? 16 : 0; final boolean showMethods = portionShower.showPortion(EntityPortion.METHOD, entity); final boolean showFields = portionShower.showPortion(EntityPortion.FIELD, entity); diff --git a/src/net/sourceforge/plantuml/svek/image/EntityImageObject.java b/src/net/sourceforge/plantuml/svek/image/EntityImageObject.java index 01ab1f89e..87e07d54e 100644 --- a/src/net/sourceforge/plantuml/svek/image/EntityImageObject.java +++ b/src/net/sourceforge/plantuml/svek/image/EntityImageObject.java @@ -42,7 +42,9 @@ import net.sourceforge.plantuml.SkinParamUtils; import net.sourceforge.plantuml.Url; import net.sourceforge.plantuml.creole.Stencil; import net.sourceforge.plantuml.cucadiagram.Display; +import net.sourceforge.plantuml.cucadiagram.EntityPortion; import net.sourceforge.plantuml.cucadiagram.ILeaf; +import net.sourceforge.plantuml.cucadiagram.PortionShower; import net.sourceforge.plantuml.cucadiagram.Stereotype; import net.sourceforge.plantuml.graphic.FontConfiguration; import net.sourceforge.plantuml.graphic.HorizontalAlignment; @@ -76,15 +78,16 @@ public class EntityImageObject extends AbstractEntityImage implements Stencil { final private LineConfigurable lineConfig; - public EntityImageObject(ILeaf entity, ISkinParam skinParam) { + public EntityImageObject(ILeaf entity, ISkinParam skinParam, PortionShower portionShower) { super(entity, skinParam); this.lineConfig = entity; final Stereotype stereotype = entity.getStereotype(); - this.roundCorner = skinParam.getRoundCorner(); + this.roundCorner = skinParam.getRoundCorner(""); this.name = TextBlockUtils.withMargin( entity.getDisplay().create(new FontConfiguration(getSkinParam(), FontParam.OBJECT, stereotype), HorizontalAlignment.CENTER, skinParam), 2, 2); - if (stereotype == null || stereotype.getLabel(false) == null) { + if (stereotype == null || stereotype.getLabel(false) == null + || portionShower.showPortion(EntityPortion.STEREOTYPE, entity) == false) { this.stereo = null; } else { this.stereo = Display.create(stereotype.getLabels(skinParam.useGuillemet())).create( @@ -92,10 +95,14 @@ public class EntityImageObject extends AbstractEntityImage implements Stencil { HorizontalAlignment.CENTER, skinParam); } + // final boolean showMethods = portionShower.showPortion(EntityPortion.METHOD, entity); + final boolean showFields = portionShower.showPortion(EntityPortion.FIELD, entity); + if (entity.getBodier().getFieldsToDisplay().size() == 0) { this.fields = new TextBlockLineBefore(new TextBlockEmpty(10, 16)); } else { - this.fields = entity.getBodier().getBody(FontParam.OBJECT_ATTRIBUTE, skinParam, false, true, entity.getStereotype()); + this.fields = entity.getBodier().getBody(FontParam.OBJECT_ATTRIBUTE, skinParam, false, showFields, + entity.getStereotype()); } this.url = entity.getUrl99(); diff --git a/src/net/sourceforge/plantuml/ugraphic/ImageBuilder.java b/src/net/sourceforge/plantuml/ugraphic/ImageBuilder.java index 6c48cb139..b6896d6d7 100644 --- a/src/net/sourceforge/plantuml/ugraphic/ImageBuilder.java +++ b/src/net/sourceforge/plantuml/ugraphic/ImageBuilder.java @@ -49,11 +49,14 @@ import javax.swing.ImageIcon; import net.sourceforge.plantuml.AnimatedGifEncoder; import net.sourceforge.plantuml.CMapData; +import net.sourceforge.plantuml.ColorParam; import net.sourceforge.plantuml.Dimension2DDouble; import net.sourceforge.plantuml.EmptyImageBuilder; import net.sourceforge.plantuml.FileFormat; import net.sourceforge.plantuml.FileFormatOption; import net.sourceforge.plantuml.FileUtils; +import net.sourceforge.plantuml.ISkinParam; +import net.sourceforge.plantuml.LineParam; import net.sourceforge.plantuml.OptionFlags; import net.sourceforge.plantuml.StringUtils; import net.sourceforge.plantuml.Url; @@ -68,9 +71,11 @@ import net.sourceforge.plantuml.graphic.HtmlColor; import net.sourceforge.plantuml.graphic.HtmlColorGradient; import net.sourceforge.plantuml.graphic.HtmlColorSimple; import net.sourceforge.plantuml.graphic.HtmlColorTransparent; +import net.sourceforge.plantuml.graphic.HtmlColorUtils; import net.sourceforge.plantuml.graphic.StringBounder; import net.sourceforge.plantuml.graphic.UDrawable; import net.sourceforge.plantuml.mjpeg.MJPEGGenerator; +import net.sourceforge.plantuml.skin.rose.Rose; import net.sourceforge.plantuml.ugraphic.crossing.UGraphicCrossing; import net.sourceforge.plantuml.ugraphic.eps.UGraphicEps; import net.sourceforge.plantuml.ugraphic.g2d.UGraphicG2d; @@ -94,6 +99,12 @@ public class ImageBuilder { private UDrawable udrawable; + private final double externalMargin1; + private final double externalMargin2; + private UStroke borderStroke; + private HtmlColor borderColor; + private double borderCorner; + public ImageBuilder(ColorMapper colorMapper, double dpiFactor, HtmlColor mybackcolor, String metadata, String warningOrError, double margin1, double margin2, Animation animation, boolean useHandwritten) { this.colorMapper = colorMapper; @@ -105,6 +116,40 @@ public class ImageBuilder { this.margin2 = margin2; this.animation = animation; this.useHandwritten = useHandwritten; + this.externalMargin1 = 0; + this.externalMargin2 = 0; + this.borderStroke = null; + this.borderColor = null; + this.borderCorner = 0; + } + + public ImageBuilder(ISkinParam skinParam, double dpiFactor, String metadata, String warningOrError, double margin1, + double margin2, Animation animation) { + this(skinParam, dpiFactor, metadata, warningOrError, margin1, margin2, animation, skinParam + .getBackgroundColor()); + } + + public ImageBuilder(ISkinParam skinParam, double dpiFactor, String metadata, String warningOrError, double margin1, + double margin2, Animation animation, HtmlColor backColor) { + final Rose rose = new Rose(); + this.borderColor = rose.getHtmlColor(skinParam, ColorParam.diagramBorder); + this.borderStroke = skinParam.getThickness(LineParam.diagramBorder, null); + this.borderCorner = skinParam.getRoundCorner("diagramBorder"); + if (borderStroke == null && borderColor != null) { + this.borderStroke = new UStroke(); + } + + this.colorMapper = skinParam.getColorMapper(); + this.dpiFactor = dpiFactor; + this.mybackcolor = backColor; + this.metadata = metadata; + this.warningOrError = warningOrError; + this.margin1 = margin1; + this.margin2 = margin2; + this.animation = animation; + this.useHandwritten = skinParam.handwritten(); + this.externalMargin1 = 0; + this.externalMargin2 = 0; } public void setUDrawable(UDrawable udrawable) { @@ -121,16 +166,21 @@ public class ImageBuilder { return writeImageInternal(fileFormatOption, os, animation); } - private static Semaphore SEMAPHORE; + private static Semaphore SEMAPHORE_SMALL; + private static Semaphore SEMAPHORE_BIG; private static int MAX_PRICE = 0; public static void setMaxPixel(int max) { - MAX_PRICE = max; - SEMAPHORE = new Semaphore(MAX_PRICE, true); + MAX_PRICE = max / 2; + SEMAPHORE_SMALL = new Semaphore(MAX_PRICE, true); + SEMAPHORE_BIG = new Semaphore(MAX_PRICE, true); } private int getPrice(FileFormatOption fileFormatOption, Dimension2D dim) { - if (fileFormatOption.getFileFormat() != FileFormat.PNG) { + // if (fileFormatOption.getFileFormat() != FileFormat.PNG) { + // return 0; + // } + if (MAX_PRICE == 0) { return 0; } final int price = Math.min(MAX_PRICE, ((int) (dim.getHeight() * dpiFactor)) @@ -138,6 +188,16 @@ public class ImageBuilder { return price; } + private Semaphore getSemaphore(int price) { + if (price == 0) { + return null; + } + if (price == MAX_PRICE) { + return SEMAPHORE_BIG; + } + return SEMAPHORE_SMALL; + } + private ImageData writeImageInternal(FileFormatOption fileFormatOption, OutputStream os, Animation animationArg) throws IOException { Dimension2D dim = getFinalDimension(fileFormatOption.getDefaultStringBounder()); @@ -151,11 +211,11 @@ public class ImageBuilder { dy = -minmax.getMinY(); } - int price = 0; - if (SEMAPHORE != null) { - price = getPrice(fileFormatOption, dim); + final int price = getPrice(fileFormatOption, dim); + final Semaphore semaphore = getSemaphore(price); + if (semaphore != null) { try { - SEMAPHORE.acquire(price); + semaphore.acquire(price); } catch (InterruptedException e) { e.printStackTrace(); throw new IOException(e); @@ -163,7 +223,22 @@ public class ImageBuilder { } try { final UGraphic2 ug = createUGraphic(fileFormatOption, dim, animationArg, dx, dy); - final UGraphic ugDecored = handwritten(ug.apply(new UTranslate(margin1, margin1))); + UGraphic ug2 = ug; + if (externalMargin1 > 0) { + ug2 = ug2.apply(new UTranslate(externalMargin1, externalMargin1)); + } + if (borderStroke != null) { + final HtmlColor color = borderColor == null ? HtmlColorUtils.BLACK : borderColor; + final URectangle shape = new URectangle( + dim.getWidth() - externalMargin() - borderStroke.getThickness(), dim.getHeight() + - externalMargin() - borderStroke.getThickness(), borderCorner, borderCorner); + ug2.apply(new UChangeColor(color)).apply(borderStroke).draw(shape); + } + if (externalMargin1 > 0) { + ug2 = ug2.apply(new UTranslate(externalMargin2, externalMargin2)); + } + ug2 = ug2.apply(new UTranslate(margin1, margin1)); + final UGraphic ugDecored = handwritten(ug2); udrawable.drawU(ugDecored); ugDecored.flushUg(); ug.writeImageTOBEMOVED(os, metadata, 96); @@ -178,18 +253,22 @@ public class ImageBuilder { } return new ImageDataSimple(dim); } finally { - if (SEMAPHORE != null) { - SEMAPHORE.release(price); + if (semaphore != null) { + semaphore.release(price); } } } + private double externalMargin() { + return 2 * (externalMargin1 + externalMargin2); + } + public Dimension2D getFinalDimension(StringBounder stringBounder) { final LimitFinder limitFinder = new LimitFinder(stringBounder, true); udrawable.drawU(limitFinder); - Dimension2D dim = new Dimension2DDouble(limitFinder.getMaxX() + 1 + margin1 + margin2, limitFinder.getMaxY() - + 1 + margin1 + margin2); + Dimension2D dim = new Dimension2DDouble(limitFinder.getMaxX() + 1 + margin1 + margin2 + externalMargin(), + limitFinder.getMaxY() + 1 + margin1 + margin2 + externalMargin()); return dim; } diff --git a/src/net/sourceforge/plantuml/ugraphic/UGraphicUtils.java b/src/net/sourceforge/plantuml/ugraphic/UGraphicUtils.java index bd05310ef..330562d19 100644 --- a/src/net/sourceforge/plantuml/ugraphic/UGraphicUtils.java +++ b/src/net/sourceforge/plantuml/ugraphic/UGraphicUtils.java @@ -43,7 +43,6 @@ import net.sourceforge.plantuml.StringUtils; import net.sourceforge.plantuml.eps.EpsStrategy; import net.sourceforge.plantuml.graphic.HtmlColor; import net.sourceforge.plantuml.graphic.TextBlock; -import net.sourceforge.plantuml.graphic.UDrawable; import net.sourceforge.plantuml.png.PngIO; import net.sourceforge.plantuml.ugraphic.eps.UGraphicEps; import net.sourceforge.plantuml.ugraphic.g2d.UGraphicG2d; @@ -51,14 +50,14 @@ import net.sourceforge.plantuml.ugraphic.svg.UGraphicSvg; public abstract class UGraphicUtils { - public static UDrawable translate(final UDrawable d, final double dx, final double dy) { - return new UDrawable() { - public void drawU(UGraphic ug) { - d.drawU(ug.apply(new UTranslate(dx, dy))); - } - }; - - } + // public static UDrawable translate(final UDrawable d, final double dx, final double dy) { + // return new UDrawable() { + // public void drawU(UGraphic ug) { + // d.drawU(ug.apply(new UTranslate(dx, dy))); + // } + // }; + // + // } public static void writeImage(OutputStream os, String metadata, FileFormatOption fileFormatOption, ColorMapper colorMapper, HtmlColor background, TextBlock image) throws IOException { diff --git a/src/net/sourceforge/plantuml/ugraphic/sprite/SpriteSvg.java b/src/net/sourceforge/plantuml/ugraphic/sprite/SpriteSvg.java new file mode 100644 index 000000000..0f8faf85a --- /dev/null +++ b/src/net/sourceforge/plantuml/ugraphic/sprite/SpriteSvg.java @@ -0,0 +1,76 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2017, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * This file is part of PlantUML. + * + * PlantUML is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PlantUML distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.ugraphic.sprite; + +import java.awt.geom.Dimension2D; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; + +import net.sourceforge.plantuml.Dimension2DDouble; +import net.sourceforge.plantuml.FileUtils; +import net.sourceforge.plantuml.graphic.AbstractTextBlock; +import net.sourceforge.plantuml.graphic.HtmlColor; +import net.sourceforge.plantuml.graphic.StringBounder; +import net.sourceforge.plantuml.graphic.TextBlock; +import net.sourceforge.plantuml.ugraphic.UGraphic; +import net.sourceforge.plantuml.ugraphic.UImageSvg; + +public class SpriteSvg implements Sprite { + + private final UImageSvg img; + + public SpriteSvg(String svg) { + this.img = new UImageSvg(svg); + } + + public SpriteSvg(File svgFile) throws IOException { + this(FileUtils.readSvg(svgFile)); + } + + public SpriteSvg(InputStream is) throws IOException { + this(FileUtils.readSvg(is)); + } + + public TextBlock asTextBlock(final HtmlColor color, final double scale) { + return new AbstractTextBlock() { + + public void drawU(UGraphic ug) { + ug.draw(img); + } + + public Dimension2D calculateDimension(StringBounder stringBounder) { + return new Dimension2DDouble(img.getWidth() * scale, img.getHeight() * scale); + } + }; + } + +} diff --git a/src/net/sourceforge/plantuml/version/Version.java b/src/net/sourceforge/plantuml/version/Version.java index ae76c0586..73db10700 100644 --- a/src/net/sourceforge/plantuml/version/Version.java +++ b/src/net/sourceforge/plantuml/version/Version.java @@ -36,7 +36,7 @@ import java.util.Date; public class Version { public static int version() { - return 8048; + return 8049; } public static String versionString() { @@ -68,7 +68,7 @@ public class Version { } public static long compileTime() { - return 1475168642530L; + return 1478283413822L; } public static String compileTimeString() {