1
0
mirror of https://github.com/octoleo/plantuml.git synced 2025-04-02 00:01:52 +00:00

version 8056

This commit is contained in:
Arnaud Roques 2017-02-15 22:34:36 +01:00
parent a2cbfb5712
commit c7252cdf63
65 changed files with 1090 additions and 183 deletions

View File

@ -30,13 +30,12 @@
Script Author: Julien Eluard Script Author: Julien Eluard
--> -->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>net.sourceforge.plantuml</groupId> <groupId>net.sourceforge.plantuml</groupId>
<artifactId>plantuml</artifactId> <artifactId>plantuml</artifactId>
<version>8055-SNAPSHOT</version> <version>8057-SNAPSHOT</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>PlantUML</name> <name>PlantUML</name>

View File

@ -81,7 +81,7 @@ public class BlockUml {
this.data = new ArrayList<CharSequence2>(strings); this.data = new ArrayList<CharSequence2>(strings);
} }
public String getFileOrDirname() { public String getFileOrDirname(FileFormat defaultFileFormat) {
if (OptionFlags.getInstance().isWord()) { if (OptionFlags.getInstance().isWord()) {
return null; return null;
} }
@ -104,6 +104,9 @@ public class BlockUml {
if (result.startsWith("file://")) { if (result.startsWith("file://")) {
result = result.substring("file://".length()); result = result.substring("file://".length());
} }
if (result.contains(".") == false) {
result = result + defaultFileFormat.getFileSuffix();
}
return result; return result;
} }

View File

@ -44,16 +44,16 @@ public enum ColorParam {
activityStart(HtmlColorUtils.BLACK), activityStart(HtmlColorUtils.BLACK),
activityEnd(HtmlColorUtils.BLACK), activityEnd(HtmlColorUtils.BLACK),
activityBar(HtmlColorUtils.BLACK), activityBar(HtmlColorUtils.BLACK),
activityArrow(HtmlColorUtils.MY_RED, ColorType.ARROW), // activityArrow(HtmlColorUtils.MY_RED, ColorType.ARROW),
swimlaneBorder(HtmlColorUtils.BLACK), swimlaneBorder(HtmlColorUtils.BLACK),
usecaseBorder(HtmlColorUtils.MY_RED, ColorType.LINE), usecaseBorder(HtmlColorUtils.MY_RED, ColorType.LINE),
usecaseBackground(HtmlColorUtils.MY_YELLOW, true, ColorType.BACK), usecaseBackground(HtmlColorUtils.MY_YELLOW, true, ColorType.BACK),
usecaseArrow(HtmlColorUtils.MY_RED, ColorType.ARROW), // usecaseArrow(HtmlColorUtils.MY_RED, ColorType.ARROW),
objectBackground(HtmlColorUtils.MY_YELLOW, true, ColorType.BACK), objectBackground(HtmlColorUtils.MY_YELLOW, true, ColorType.BACK),
objectBorder(HtmlColorUtils.MY_RED, ColorType.LINE), objectBorder(HtmlColorUtils.MY_RED, ColorType.LINE),
objectArrow(HtmlColorUtils.MY_RED, ColorType.ARROW), // objectArrow(HtmlColorUtils.MY_RED, ColorType.ARROW),
classHeaderBackground(null, true, ColorType.BACK), classHeaderBackground(null, true, ColorType.BACK),
classBackground(HtmlColorUtils.MY_YELLOW, true, ColorType.BACK), classBackground(HtmlColorUtils.MY_YELLOW, true, ColorType.BACK),
@ -63,7 +63,7 @@ public enum ColorParam {
stereotypeABackground(HtmlColorUtils.COL_A9DCDF), stereotypeABackground(HtmlColorUtils.COL_A9DCDF),
stereotypeIBackground(HtmlColorUtils.COL_B4A7E5), stereotypeIBackground(HtmlColorUtils.COL_B4A7E5),
stereotypeEBackground(HtmlColorUtils.COL_EB937F), stereotypeEBackground(HtmlColorUtils.COL_EB937F),
classArrow(HtmlColorUtils.MY_RED, ColorType.ARROW), // classArrow(HtmlColorUtils.MY_RED, ColorType.ARROW),
packageBackground(HtmlColorUtils.MY_YELLOW, true, ColorType.BACK), packageBackground(HtmlColorUtils.MY_YELLOW, true, ColorType.BACK),
packageBorder(HtmlColorUtils.BLACK, ColorType.LINE), packageBorder(HtmlColorUtils.BLACK, ColorType.LINE),
@ -79,7 +79,7 @@ public enum ColorParam {
stateBackground(HtmlColorUtils.MY_YELLOW, true, ColorType.BACK), stateBackground(HtmlColorUtils.MY_YELLOW, true, ColorType.BACK),
stateBorder(HtmlColorUtils.MY_RED, ColorType.LINE), stateBorder(HtmlColorUtils.MY_RED, ColorType.LINE),
stateArrow(HtmlColorUtils.MY_RED, ColorType.ARROW), // stateArrow(HtmlColorUtils.MY_RED, ColorType.ARROW),
stateStart(HtmlColorUtils.BLACK), stateStart(HtmlColorUtils.BLACK),
stateEnd(HtmlColorUtils.BLACK), stateEnd(HtmlColorUtils.BLACK),
@ -109,7 +109,7 @@ public enum ColorParam {
sequenceLifeLineBackground(HtmlColorUtils.WHITE, true, ColorType.BACK), sequenceLifeLineBackground(HtmlColorUtils.WHITE, true, ColorType.BACK),
sequenceLifeLineBorder(HtmlColorUtils.MY_RED, ColorType.LINE), sequenceLifeLineBorder(HtmlColorUtils.MY_RED, ColorType.LINE),
sequenceNewpageSeparator(HtmlColorUtils.BLACK, ColorType.LINE), sequenceNewpageSeparator(HtmlColorUtils.BLACK, ColorType.LINE),
sequenceArrow(HtmlColorUtils.MY_RED), // sequenceArrow(HtmlColorUtils.MY_RED),
sequenceBoxBorder(HtmlColorUtils.MY_RED, ColorType.LINE), sequenceBoxBorder(HtmlColorUtils.MY_RED, ColorType.LINE),
sequenceBoxBackground(HtmlColorUtils.COL_DDDDDD, true, ColorType.BACK), sequenceBoxBackground(HtmlColorUtils.COL_DDDDDD, true, ColorType.BACK),

View File

@ -49,9 +49,10 @@ public class FileFormatOption implements Serializable {
private final boolean withMetadata; private final boolean withMetadata;
private final boolean useRedForError; private final boolean useRedForError;
private final String svgLinkTarget; private final String svgLinkTarget;
private final String hoverColor;
public FileFormatOption(FileFormat fileFormat) { public FileFormatOption(FileFormat fileFormat) {
this(fileFormat, null, true, false, "_top", false); this(fileFormat, null, true, false, "_top", false, null);
} }
public StringBounder getDefaultStringBounder() { public StringBounder getDefaultStringBounder() {
@ -67,11 +68,12 @@ public class FileFormatOption implements Serializable {
} }
public FileFormatOption(FileFormat fileFormat, boolean withMetadata) { public FileFormatOption(FileFormat fileFormat, boolean withMetadata) {
this(fileFormat, null, false, false, "_top", false); this(fileFormat, null, false, false, "_top", false, null);
} }
private FileFormatOption(FileFormat fileFormat, AffineTransform at, boolean withMetadata, boolean useRedForError, private FileFormatOption(FileFormat fileFormat, AffineTransform at, boolean withMetadata, boolean useRedForError,
String svgLinkTarget, boolean debugsvek) { String svgLinkTarget, boolean debugsvek, String hoverColor) {
this.hoverColor = hoverColor;
this.fileFormat = fileFormat; this.fileFormat = fileFormat;
this.affineTransform = at; this.affineTransform = at;
this.withMetadata = withMetadata; this.withMetadata = withMetadata;
@ -81,11 +83,15 @@ public class FileFormatOption implements Serializable {
} }
public FileFormatOption withUseRedForError() { public FileFormatOption withUseRedForError() {
return new FileFormatOption(fileFormat, affineTransform, withMetadata, true, svgLinkTarget, debugsvek); return new FileFormatOption(fileFormat, affineTransform, withMetadata, true, svgLinkTarget, debugsvek, hoverColor);
} }
public FileFormatOption withSvgLinkTarget(String target) { public FileFormatOption withSvgLinkTarget(String svgLinkTarget) {
return new FileFormatOption(fileFormat, affineTransform, withMetadata, useRedForError, target, debugsvek); return new FileFormatOption(fileFormat, affineTransform, withMetadata, useRedForError, svgLinkTarget, debugsvek, hoverColor);
}
public FileFormatOption withHoverColor(String hoverColor) {
return new FileFormatOption(fileFormat, affineTransform, withMetadata, useRedForError, svgLinkTarget, debugsvek, hoverColor);
} }
@Override @Override
@ -115,4 +121,8 @@ public class FileFormatOption implements Serializable {
return debugsvek; return debugsvek;
} }
public final String getHoverColor() {
return hoverColor;
}
} }

View File

@ -42,8 +42,9 @@ interface FontParamConstant {
public enum FontParam { public enum FontParam {
ACTIVITY(12, Font.PLAIN), // ACTIVITY(12, Font.PLAIN), //
ACTIVITY_DIAMOND(11, Font.PLAIN), // ACTIVITY_DIAMOND(11, Font.PLAIN), //
ACTIVITY_ARROW(11, Font.PLAIN), // // ACTIVITY_ARROW(11, Font.PLAIN), //
GENERIC_ARROW(13, Font.PLAIN), // // GENERIC_ARROW(13, Font.PLAIN), //
ARROW(13, Font.PLAIN), //
CIRCLED_CHARACTER(17, Font.BOLD, FontParamConstant.COLOR, "Monospaced"), // CIRCLED_CHARACTER(17, Font.BOLD, FontParamConstant.COLOR, "Monospaced"), //
OBJECT_ATTRIBUTE(10, Font.PLAIN), // OBJECT_ATTRIBUTE(10, Font.PLAIN), //
OBJECT(12, Font.PLAIN), // OBJECT(12, Font.PLAIN), //
@ -73,7 +74,7 @@ public enum FontParam {
NODE(14, Font.PLAIN), // NODE(14, Font.PLAIN), //
DATABASE(14, Font.PLAIN), // DATABASE(14, Font.PLAIN), //
QUEUE(14, Font.PLAIN), // QUEUE(14, Font.PLAIN), //
SEQUENCE_ARROW(13, Font.PLAIN), // // SEQUENCE_ARROW(13, Font.PLAIN), //
SEQUENCE_BOX(13, Font.BOLD), // SEQUENCE_BOX(13, Font.BOLD), //
SEQUENCE_DIVIDER(13, Font.BOLD), // SEQUENCE_DIVIDER(13, Font.BOLD), //
SEQUENCE_REFERENCE(13, Font.PLAIN), // SEQUENCE_REFERENCE(13, Font.PLAIN), //
@ -110,7 +111,6 @@ public enum FontParam {
SEQUENCE_STEREOTYPE(14, Font.ITALIC), // SEQUENCE_STEREOTYPE(14, Font.ITALIC), //
PARTITION(14, Font.PLAIN); // PARTITION(14, Font.PLAIN); //
private final int defaultSize; private final int defaultSize;
private final int fontStyle; private final int fontStyle;
private final String defaultColor; private final String defaultColor;
@ -128,6 +128,9 @@ public enum FontParam {
} }
public final int getDefaultSize(ISkinParam skinParam) { public final int getDefaultSize(ISkinParam skinParam) {
if (this == ARROW && skinParam.getUmlDiagramType() == UmlDiagramType.ACTIVITY) {
return 11;
}
if (this == CLASS_ATTRIBUTE) { if (this == CLASS_ATTRIBUTE) {
return 11; return 11;
} }

View File

@ -130,4 +130,9 @@ public interface ISkinParam extends ISkinSimple {
public int swimlaneWidth(); public int swimlaneWidth();
public UmlDiagramType getUmlDiagramType();
public HtmlColor getHoverPathColor();
} }

View File

@ -30,8 +30,6 @@
*/ */
package net.sourceforge.plantuml; package net.sourceforge.plantuml;
import h.stack;
import java.awt.Font; import java.awt.Font;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@ -76,6 +74,7 @@ public class SkinParam implements ISkinParam {
private final Map<String, String> params = new HashMap<String, String>(); private final Map<String, String> params = new HashMap<String, String>();
private Rankdir rankdir = Rankdir.TOP_TO_BOTTOM; private Rankdir rankdir = Rankdir.TOP_TO_BOTTOM;
private String dotExecutable; private String dotExecutable;
private final UmlDiagramType type;
public String getDotExecutable() { public String getDotExecutable() {
return dotExecutable; return dotExecutable;
@ -89,8 +88,16 @@ public class SkinParam implements ISkinParam {
params.put(cleanForKey(key), StringUtils.trin(value)); params.put(cleanForKey(key), StringUtils.trin(value));
} }
public static SkinParam noShadowing() { private SkinParam(UmlDiagramType type) {
final SkinParam result = new SkinParam(); this.type = type;
}
public static SkinParam create(UmlDiagramType type) {
return new SkinParam(type);
}
public static SkinParam noShadowing(UmlDiagramType type) {
final SkinParam result = new SkinParam(type);
result.setParam("shadowing", "false"); result.setParam("shadowing", "false");
return result; return result;
} }
@ -101,16 +108,17 @@ public class SkinParam implements ISkinParam {
// key = replaceSmart(key, "partition", "package"); // key = replaceSmart(key, "partition", "package");
key = replaceSmart(key, "sequenceparticipant", "participant"); key = replaceSmart(key, "sequenceparticipant", "participant");
key = replaceSmart(key, "sequenceactor", "actor"); key = replaceSmart(key, "sequenceactor", "actor");
if (key.contains("arrow")) { // if (key.contains("arrow")) {
key = key.replaceAll("activityarrow|objectarrow|classarrow|componentarrow|statearrow|usecasearrow", // key = key.replaceAll("activityarrow|objectarrow|classarrow|componentarrow|statearrow|usecasearrow",
"genericarrow"); // "genericarrow");
} // }
// // key = key.replaceAll("activityarrow", "genericarrow"); key = key.replaceAll("activityarrow", "arrow");
// // key = key.replaceAll("objectarrow", "genericarrow"); key = key.replaceAll("objectarrow", "arrow");
// // key = key.replaceAll("classarrow", "genericarrow"); key = key.replaceAll("classarrow", "arrow");
// // key = key.replaceAll("componentarrow", "genericarrow"); key = key.replaceAll("componentarrow", "arrow");
// // key = key.replaceAll("statearrow", "genericarrow"); key = key.replaceAll("statearrow", "arrow");
// // key = key.replaceAll("usecasearrow", "genericarrow"); key = key.replaceAll("usecasearrow", "arrow");
key = key.replaceAll("sequencearrow", "arrow");
final Matcher2 m = stereoPattern.matcher(key); final Matcher2 m = stereoPattern.matcher(key);
if (m.find()) { if (m.find()) {
final String s = m.group(1); final String s = m.group(1);
@ -819,4 +827,16 @@ public class SkinParam implements ISkinParam {
return 0; return 0;
} }
public UmlDiagramType getUmlDiagramType() {
return type;
}
public HtmlColor getHoverPathColor() {
final String value = getValue("pathhovercolor");
if (value == null) {
return null;
}
return getIHtmlColorSet().getColorIfValid(value, false);
}
} }

View File

@ -246,4 +246,12 @@ public class SkinParamDelegator implements ISkinParam {
return skinParam.swimlaneWidth(); return skinParam.swimlaneWidth();
} }
public UmlDiagramType getUmlDiagramType() {
return skinParam.getUmlDiagramType();
}
public HtmlColor getHoverPathColor() {
return skinParam.getHoverPathColor();
}
} }

View File

@ -164,7 +164,7 @@ public class SourceFileReader implements ISourceFileReader {
final List<GeneratedImage> result = new ArrayList<GeneratedImage>(); final List<GeneratedImage> result = new ArrayList<GeneratedImage>();
for (BlockUml blockUml : builder.getBlockUmls()) { for (BlockUml blockUml : builder.getBlockUmls()) {
String newName = blockUml.getFileOrDirname(); String newName = blockUml.getFileOrDirname(fileFormatOption.getFileFormat());
Log.info("name from block=" + newName); Log.info("name from block=" + newName);
File suggested = null; File suggested = null;
if (newName != null) { if (newName != null) {

View File

@ -62,6 +62,7 @@ import net.sourceforge.plantuml.fun.IconLoader;
import net.sourceforge.plantuml.graphic.GraphicPosition; import net.sourceforge.plantuml.graphic.GraphicPosition;
import net.sourceforge.plantuml.graphic.GraphicStrings; import net.sourceforge.plantuml.graphic.GraphicStrings;
import net.sourceforge.plantuml.graphic.HorizontalAlignment; import net.sourceforge.plantuml.graphic.HorizontalAlignment;
import net.sourceforge.plantuml.graphic.HtmlColor;
import net.sourceforge.plantuml.graphic.HtmlColorUtils; import net.sourceforge.plantuml.graphic.HtmlColorUtils;
import net.sourceforge.plantuml.graphic.UDrawable; import net.sourceforge.plantuml.graphic.UDrawable;
import net.sourceforge.plantuml.graphic.VerticalAlignment; import net.sourceforge.plantuml.graphic.VerticalAlignment;
@ -95,7 +96,7 @@ public abstract class UmlDiagram extends AbstractPSystem implements Diagram, Ann
private Scale scale; private Scale scale;
private Animation animation; private Animation animation;
private final SkinParam skinParam = new SkinParam(); private final SkinParam skinParam = SkinParam.create(getUmlDiagramType());
final public void setTitle(DisplayPositionned title) { final public void setTitle(DisplayPositionned title) {
this.title = title; this.title = title;
@ -215,7 +216,12 @@ public abstract class UmlDiagram extends AbstractPSystem implements Diagram, Ann
final protected ImageData exportDiagramNow(OutputStream os, int index, FileFormatOption fileFormatOption) final protected ImageData exportDiagramNow(OutputStream os, int index, FileFormatOption fileFormatOption)
throws IOException { throws IOException {
final HtmlColor hover = getSkinParam().getHoverPathColor();
fileFormatOption = fileFormatOption.withSvgLinkTarget(getSkinParam().getSvgLinkTarget()); fileFormatOption = fileFormatOption.withSvgLinkTarget(getSkinParam().getSvgLinkTarget());
if (hover != null) {
fileFormatOption = fileFormatOption.withHoverColor(StringUtils.getAsHtml(getSkinParam().getColorMapper()
.getMappedColor(hover)));
}
if (fileFormatOption.getFileFormat() == FileFormat.PDF) { if (fileFormatOption.getFileFormat() == FileFormat.PDF) {
return exportDiagramInternalPdf(os, index); return exportDiagramInternalPdf(os, index);

View File

@ -52,7 +52,7 @@ public class CommandWhile3 extends SingleLineCommand2<ActivityDiagram3> {
new RegexLeaf("^"), // new RegexLeaf("^"), //
ColorParser.exp4(), // ColorParser.exp4(), //
new RegexLeaf("while"), // new RegexLeaf("while"), //
new RegexLeaf("TEST", "[%s]*\\((.+?)\\)"), // new RegexLeaf("TEST", "[%s]*\\((.*?)\\)"), //
new RegexOptional(new RegexConcat(// new RegexOptional(new RegexConcat(//
new RegexLeaf("[%s]*(is|equals?)[%s]*"), // new RegexLeaf("[%s]*(is|equals?)[%s]*"), //
new RegexLeaf("YES", "\\((.+?)\\)"))), // new RegexLeaf("YES", "\\((.+?)\\)"))), //

View File

@ -77,7 +77,7 @@ public class FtileFactoryDelegator implements FtileFactory {
if (Display.isNull(display)) { if (Display.isNull(display)) {
return null; return null;
} }
final FontConfiguration fontConfiguration = new FontConfiguration(skinParam(), FontParam.ACTIVITY_ARROW, null); final FontConfiguration fontConfiguration = new FontConfiguration(skinParam(), FontParam.ARROW, null);
return display.create(fontConfiguration, HorizontalAlignment.LEFT, skinParam(), CreoleMode.SIMPLE_LINE); return display.create(fontConfiguration, HorizontalAlignment.LEFT, skinParam(), CreoleMode.SIMPLE_LINE);
} }

View File

@ -52,7 +52,7 @@ public class FtileFactoryDelegatorCreateGroup extends FtileFactoryDelegator {
@Override @Override
public Ftile createGroup(Ftile list, Display name, HtmlColor backColor, HtmlColor titleColor, PositionedNote note, public Ftile createGroup(Ftile list, Display name, HtmlColor backColor, HtmlColor titleColor, PositionedNote note,
HtmlColor borderColor) { HtmlColor borderColor) {
final HtmlColor arrowColor = rose.getHtmlColor(skinParam(), ColorParam.activityArrow); final HtmlColor arrowColor = rose.getHtmlColor(skinParam(), ColorParam.arrow);
Ftile result = new FtileGroup(list, name, null, arrowColor, backColor, titleColor, skinParam(), borderColor); Ftile result = new FtileGroup(list, name, null, arrowColor, backColor, titleColor, skinParam(), borderColor);
if (note != null) { if (note != null) {
result = new FtileWithNotes(result, Collections.singleton(note), skinParam()); result = new FtileWithNotes(result, Collections.singleton(note), skinParam());

View File

@ -69,7 +69,7 @@ public class FtileFactoryDelegatorIf extends FtileFactoryDelegator {
ColorParam.activityBackground) : branch0.getColor(); ColorParam.activityBackground) : branch0.getColor();
final Rainbow arrowColor = HtmlColorAndStyle.build(skinParam()); final Rainbow arrowColor = HtmlColorAndStyle.build(skinParam());
final FontConfiguration fcArrow = new FontConfiguration(skinParam(), FontParam.ACTIVITY_ARROW, null); final FontConfiguration fcArrow = new FontConfiguration(skinParam(), FontParam.ARROW, null);
// .changeColor(fontColor(FontParam.ACTIVITY_DIAMOND)); // .changeColor(fontColor(FontParam.ACTIVITY_DIAMOND));
if (thens.size() > 1) { if (thens.size() > 1) {
if (pragma.useVerticalIf()/* OptionFlags.USE_IF_VERTICAL */) if (pragma.useVerticalIf()/* OptionFlags.USE_IF_VERTICAL */)
@ -79,7 +79,7 @@ public class FtileFactoryDelegatorIf extends FtileFactoryDelegator {
conditionStyle, thens, elseBranch, fcArrow, topInlinkRendering, afterEndwhile); conditionStyle, thens, elseBranch, fcArrow, topInlinkRendering, afterEndwhile);
} }
final FontParam testParam = conditionStyle == ConditionStyle.INSIDE ? FontParam.ACTIVITY_DIAMOND final FontParam testParam = conditionStyle == ConditionStyle.INSIDE ? FontParam.ACTIVITY_DIAMOND
: FontParam.ACTIVITY_ARROW; : FontParam.ARROW;
final FontConfiguration fcTest = new FontConfiguration(skinParam(), testParam, null) final FontConfiguration fcTest = new FontConfiguration(skinParam(), testParam, null)
.changeColor(fontColor(FontParam.ACTIVITY_DIAMOND)); .changeColor(fontColor(FontParam.ACTIVITY_DIAMOND));

View File

@ -78,7 +78,7 @@ public class FtileFactoryDelegatorRepeat extends FtileFactoryDelegator {
final Rainbow endRepeatLinkColor = endRepeatLinkRendering == null ? null : endRepeatLinkRendering.getRainbow(); final Rainbow endRepeatLinkColor = endRepeatLinkRendering == null ? null : endRepeatLinkRendering.getRainbow();
final FontConfiguration fcDiamond = new FontConfiguration(skinParam(), FontParam.ACTIVITY_DIAMOND, null); final FontConfiguration fcDiamond = new FontConfiguration(skinParam(), FontParam.ACTIVITY_DIAMOND, null);
final FontConfiguration fcArrow = new FontConfiguration(skinParam(), FontParam.ACTIVITY_ARROW, null); final FontConfiguration fcArrow = new FontConfiguration(skinParam(), FontParam.ARROW, null);
Ftile result = FtileRepeat.create(backRepeatLinkRendering, swimlane, swimlaneOut, repeat, test, yes, out, Ftile result = FtileRepeat.create(backRepeatLinkRendering, swimlane, swimlaneOut, repeat, test, yes, out,
borderColor, backColor, arrowColor, endRepeatLinkColor, conditionStyle, this.skinParam(), fcDiamond, borderColor, backColor, arrowColor, endRepeatLinkColor, conditionStyle, this.skinParam(), fcDiamond,

View File

@ -60,14 +60,14 @@ public class FtileFactoryDelegatorWhile extends FtileFactoryDelegator {
final ConditionStyle conditionStyle = skinParam().getConditionStyle(); final ConditionStyle conditionStyle = skinParam().getConditionStyle();
final FontParam testParam = conditionStyle == ConditionStyle.INSIDE ? FontParam.ACTIVITY_DIAMOND final FontParam testParam = conditionStyle == ConditionStyle.INSIDE ? FontParam.ACTIVITY_DIAMOND
: FontParam.ACTIVITY_ARROW; : FontParam.ARROW;
final FontConfiguration fcTest = new FontConfiguration(skinParam(), testParam, null); final FontConfiguration fcTest = new FontConfiguration(skinParam(), testParam, null);
final LinkRendering endInlinkRendering = whileBlock.getOutLinkRendering(); final LinkRendering endInlinkRendering = whileBlock.getOutLinkRendering();
final Rainbow endInlinkColor = endInlinkRendering == null || endInlinkRendering.getRainbow().size() == 0 ? arrowColor final Rainbow endInlinkColor = endInlinkRendering == null || endInlinkRendering.getRainbow().size() == 0 ? arrowColor
: endInlinkRendering.getRainbow(); : endInlinkRendering.getRainbow();
final FontConfiguration fontArrow = new FontConfiguration(skinParam(), FontParam.ACTIVITY_ARROW, null); final FontConfiguration fontArrow = new FontConfiguration(skinParam(), FontParam.ARROW, null);
return FtileWhile.create(swimlane, whileBlock, test, borderColor, backColor, arrowColor, yes, out, return FtileWhile.create(swimlane, whileBlock, test, borderColor, backColor, arrowColor, yes, out,
endInlinkColor, afterEndwhile, fontArrow, getFactory(), conditionStyle, fcTest); endInlinkColor, afterEndwhile, fontArrow, getFactory(), conditionStyle, fcTest);

View File

@ -33,6 +33,8 @@ package net.sourceforge.plantuml.activitydiagram3.ftile.vcompact;
import java.awt.geom.Dimension2D; import java.awt.geom.Dimension2D;
import java.awt.geom.Point2D; import java.awt.geom.Point2D;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@ -464,6 +466,14 @@ class FtileIfLongHorizontal extends AbstractFtile {
} }
} }
@Override
public Collection<Ftile> getMyChildren() {
final List<Ftile> result = new ArrayList<Ftile>(tiles);
result.add(tile2);
return Collections.unmodifiableList(result);
}
@Override @Override
public UTranslate getTranslateFor(Ftile child, StringBounder stringBounder) { public UTranslate getTranslateFor(Ftile child, StringBounder stringBounder) {
if (child == tile2) { if (child == tile2) {
@ -472,6 +482,9 @@ class FtileIfLongHorizontal extends AbstractFtile {
if (couples.contains(child)) { if (couples.contains(child)) {
return getTranslateCouple1(child, stringBounder); return getTranslateCouple1(child, stringBounder);
} }
if (tiles.contains(child)) {
return getTranslate1(child, stringBounder);
}
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }

View File

@ -162,8 +162,8 @@ public class FtileWithNotes extends AbstractFtile {
public void drawU(UGraphic ug) { public void drawU(UGraphic ug) {
final StringBounder stringBounder = ug.getStringBounder(); final StringBounder stringBounder = ug.getStringBounder();
ug.apply(getTranslateForLeft(stringBounder)).draw(left); left.drawU(ug.apply(getTranslateForLeft(stringBounder)));
ug.apply(getTranslateForRight(stringBounder)).draw(right); right.drawU(ug.apply(getTranslateForRight(stringBounder)));
ug.apply(getTranslate(stringBounder)).draw(tile); ug.apply(getTranslate(stringBounder)).draw(tile);
} }

View File

@ -97,7 +97,7 @@ public abstract class ParallelFtilesBuilder {
if (Display.isNull(display)) { if (Display.isNull(display)) {
return null; return null;
} }
final FontConfiguration fontConfiguration = new FontConfiguration(skinParam(), FontParam.ACTIVITY_ARROW, null); final FontConfiguration fontConfiguration = new FontConfiguration(skinParam(), FontParam.ARROW, null);
return display.create(fontConfiguration, HorizontalAlignment.LEFT, skinParam(), CreoleMode.SIMPLE_LINE); return display.create(fontConfiguration, HorizontalAlignment.LEFT, skinParam(), CreoleMode.SIMPLE_LINE);
} }

View File

@ -30,11 +30,13 @@
*/ */
package net.sourceforge.plantuml.activitydiagram3.ftile.vertical; package net.sourceforge.plantuml.activitydiagram3.ftile.vertical;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Set; import java.util.Set;
import net.sourceforge.plantuml.ISkinParam; import net.sourceforge.plantuml.ISkinParam;
import net.sourceforge.plantuml.activitydiagram3.ftile.AbstractFtile; import net.sourceforge.plantuml.activitydiagram3.ftile.AbstractFtile;
import net.sourceforge.plantuml.activitydiagram3.ftile.Ftile;
import net.sourceforge.plantuml.activitydiagram3.ftile.FtileGeometry; import net.sourceforge.plantuml.activitydiagram3.ftile.FtileGeometry;
import net.sourceforge.plantuml.activitydiagram3.ftile.Swimlane; import net.sourceforge.plantuml.activitydiagram3.ftile.Swimlane;
import net.sourceforge.plantuml.graphic.HtmlColor; import net.sourceforge.plantuml.graphic.HtmlColor;
@ -55,6 +57,11 @@ public class FtileCircleEnd extends AbstractFtile {
private final HtmlColor backColor; private final HtmlColor backColor;
private final Swimlane swimlane; private final Swimlane swimlane;
@Override
public Collection<Ftile> getMyChildren() {
return Collections.emptyList();
}
public FtileCircleEnd(ISkinParam skinParam, HtmlColor backColor, Swimlane swimlane) { public FtileCircleEnd(ISkinParam skinParam, HtmlColor backColor, Swimlane swimlane) {
super(skinParam); super(skinParam);
this.backColor = backColor; this.backColor = backColor;

View File

@ -30,11 +30,13 @@
*/ */
package net.sourceforge.plantuml.activitydiagram3.ftile.vertical; package net.sourceforge.plantuml.activitydiagram3.ftile.vertical;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Set; import java.util.Set;
import net.sourceforge.plantuml.ISkinParam; import net.sourceforge.plantuml.ISkinParam;
import net.sourceforge.plantuml.activitydiagram3.ftile.AbstractFtile; import net.sourceforge.plantuml.activitydiagram3.ftile.AbstractFtile;
import net.sourceforge.plantuml.activitydiagram3.ftile.Ftile;
import net.sourceforge.plantuml.activitydiagram3.ftile.FtileGeometry; import net.sourceforge.plantuml.activitydiagram3.ftile.FtileGeometry;
import net.sourceforge.plantuml.activitydiagram3.ftile.Swimlane; import net.sourceforge.plantuml.activitydiagram3.ftile.Swimlane;
import net.sourceforge.plantuml.graphic.HtmlColor; import net.sourceforge.plantuml.graphic.HtmlColor;
@ -57,6 +59,11 @@ public class FtileCircleStart extends AbstractFtile {
this.swimlane = swimlane; this.swimlane = swimlane;
} }
@Override
public Collection<Ftile> getMyChildren() {
return Collections.emptyList();
}
public Set<Swimlane> getSwimlanes() { public Set<Swimlane> getSwimlanes() {
if (swimlane == null) { if (swimlane == null) {
return Collections.emptySet(); return Collections.emptySet();

View File

@ -30,11 +30,13 @@
*/ */
package net.sourceforge.plantuml.activitydiagram3.ftile.vertical; package net.sourceforge.plantuml.activitydiagram3.ftile.vertical;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Set; import java.util.Set;
import net.sourceforge.plantuml.ISkinParam; import net.sourceforge.plantuml.ISkinParam;
import net.sourceforge.plantuml.activitydiagram3.ftile.AbstractFtile; import net.sourceforge.plantuml.activitydiagram3.ftile.AbstractFtile;
import net.sourceforge.plantuml.activitydiagram3.ftile.Ftile;
import net.sourceforge.plantuml.activitydiagram3.ftile.FtileGeometry; import net.sourceforge.plantuml.activitydiagram3.ftile.FtileGeometry;
import net.sourceforge.plantuml.activitydiagram3.ftile.Swimlane; import net.sourceforge.plantuml.activitydiagram3.ftile.Swimlane;
import net.sourceforge.plantuml.graphic.HtmlColor; import net.sourceforge.plantuml.graphic.HtmlColor;
@ -52,6 +54,11 @@ public class FtileCircleStop extends AbstractFtile {
private final HtmlColor backColor; private final HtmlColor backColor;
private final Swimlane swimlane; private final Swimlane swimlane;
@Override
public Collection<Ftile> getMyChildren() {
return Collections.emptyList();
}
public FtileCircleStop(ISkinParam skinParam, HtmlColor backColor, Swimlane swimlane) { public FtileCircleStop(ISkinParam skinParam, HtmlColor backColor, Swimlane swimlane) {
super(skinParam); super(skinParam);
this.backColor = backColor; this.backColor = backColor;

View File

@ -164,14 +164,17 @@ public class LinkType {
sb.append("arrowtail=empty"); sb.append("arrowtail=empty");
sb.append(",arrowhead=none"); sb.append(",arrowhead=none");
sb.append(",dir=back"); sb.append(",dir=back");
} else if (isEmpty1 == false && isEmpty2) { // } else if (isEmpty1 == false && isEmpty2) {
sb.append("arrowtail=none"); // sb.append("arrowtail=none");
sb.append(",arrowhead=empty"); // sb.append(",arrowhead=empty");
} }
final double arrowsize = Math.max(decor1.getArrowSize(), decor2.getArrowSize()); final double arrowsize = Math.max(decor1.getArrowSize(), decor2.getArrowSize());
if (arrowsize > 0) { if (arrowsize > 0) {
sb.append(",arrowsize=" + arrowsize); if (sb.length() > 0) {
sb.append(",");
}
sb.append("arrowsize=" + arrowsize);
} }
return sb.toString(); return sb.toString();
} }

View File

@ -55,7 +55,7 @@ public class HtmlColorAndStyle {
} }
public static Rainbow build(ISkinParam skinParam) { public static Rainbow build(ISkinParam skinParam) {
return fromColor(rose.getHtmlColor(skinParam, ColorParam.activityArrow)); return fromColor(rose.getHtmlColor(skinParam, ColorParam.arrow));
} }
private HtmlColorAndStyle(HtmlColor color) { private HtmlColorAndStyle(HtmlColor color) {

View File

@ -199,7 +199,11 @@ public class QuoteUtils {
"Vf guvf n aba-mreb-fhz tnzr?", "Abj gung'f n cebcre vagebqhpgvba.", "Vf guvf n aba-mreb-fhz tnzr?", "Abj gung'f n cebcre vagebqhpgvba.",
"Rirelguvat unf punatrq naq vg jba'g fgbc punatvat nalgvzr fbba.", "Rirelguvat unf punatrq naq vg jba'g fgbc punatvat nalgvzr fbba.",
"Jung znxrf lbh qvssrerag znxrf lbh qnatrebhf", "Qviretrapr vf rkgerzryl qnatrebhf", "Jung znxrf lbh qvssrerag znxrf lbh qnatrebhf", "Qviretrapr vf rkgerzryl qnatrebhf",
"V'z Qviretrag. Naq V pna'g or pbagebyyrq", "Znl gur bqqf or rire va lbhe snibe"); "V'z Qviretrag. Naq V pna'g or pbagebyyrq", "Znl gur bqqf or rire va lbhe snibe",
"Ab WninFpevcg senzrjbexf jrer perngrq qhevat gur jevgvat bs guvf zrffntr.",
"P'rfg cerffr-cherr dhv g'nf vagreebtr ?",
"Ybbx, nygreangvir snpgf ner abg snpgf. Gurl'er snyfrubbqf",
"Guvf vf abg n penfu, guvf vf zber bs na nygreangvir erfhyg.");
private QuoteUtils() { private QuoteUtils() {
} }

View File

@ -94,6 +94,10 @@ public class SymbolContext {
return new SymbolContext(backColor, foreColor, stroke, shadowing, deltaShadow, roundCorner); return new SymbolContext(backColor, foreColor, stroke, shadowing, deltaShadow, roundCorner);
} }
public SymbolContext withForeColor(HtmlColor foreColor) {
return new SymbolContext(backColor, foreColor, stroke, shadowing, deltaShadow, roundCorner);
}
public SymbolContext withRoundCorner(double roundCorner) { public SymbolContext withRoundCorner(double roundCorner) {
return new SymbolContext(backColor, foreColor, stroke, shadowing, deltaShadow, roundCorner); return new SymbolContext(backColor, foreColor, stroke, shadowing, deltaShadow, roundCorner);
} }

View File

@ -150,7 +150,7 @@ public class CucaDiagramFileMakerHectorB1 implements CucaDiagramFileMaker {
final double y2 = getY(pinLink.getPin2()); final double y2 = getY(pinLink.getPin2());
final Rose rose = new Rose(); final Rose rose = new Rose();
final HtmlColor color = rose.getHtmlColor(diagram.getSkinParam(), ColorParam.classArrow); final HtmlColor color = rose.getHtmlColor(diagram.getSkinParam(), ColorParam.arrow);
final List<Box2D> b = new ArrayList<Box2D>(); final List<Box2D> b = new ArrayList<Box2D>();
final SmartConnection connection = new SmartConnection(x1, y1, x2, y2, b); final SmartConnection connection = new SmartConnection(x1, y1, x2, y2, b);
connection.draw(ug, color); connection.draw(ug, color);

View File

@ -480,7 +480,7 @@ public class CucaDiagramFileMakerJDot implements CucaDiagramFileMaker {
private TextBlock getLabel(Link link) { private TextBlock getLabel(Link link) {
final double marginLabel = 1; // startUid.equals(endUid) ? 6 : 1; final double marginLabel = 1; // startUid.equals(endUid) ? 6 : 1;
ISkinParam skinParam = diagram.getSkinParam(); ISkinParam skinParam = diagram.getSkinParam();
final FontConfiguration labelFont = new FontConfiguration(skinParam, FontParam.GENERIC_ARROW, null); final FontConfiguration labelFont = new FontConfiguration(skinParam, FontParam.ARROW, null);
final TextBlock label = link.getLabel().create(labelFont, final TextBlock label = link.getLabel().create(labelFont,
skinParam.getDefaultTextAlignment(HorizontalAlignment.CENTER), skinParam); skinParam.getDefaultTextAlignment(HorizontalAlignment.CENTER), skinParam);
if (TextBlockUtils.isEmpty(label, stringBounder)) { if (TextBlockUtils.isEmpty(label, stringBounder)) {

View File

@ -79,15 +79,15 @@ public class JDotPath implements UDrawable {
private ColorParam getArrowColorParam() { private ColorParam getArrowColorParam() {
if (diagram.getUmlDiagramType() == UmlDiagramType.CLASS) { if (diagram.getUmlDiagramType() == UmlDiagramType.CLASS) {
return ColorParam.classArrow; return ColorParam.arrow;
} else if (diagram.getUmlDiagramType() == UmlDiagramType.OBJECT) { } else if (diagram.getUmlDiagramType() == UmlDiagramType.OBJECT) {
return ColorParam.objectArrow; return ColorParam.arrow;
} else if (diagram.getUmlDiagramType() == UmlDiagramType.DESCRIPTION) { } else if (diagram.getUmlDiagramType() == UmlDiagramType.DESCRIPTION) {
return ColorParam.usecaseArrow; return ColorParam.arrow;
} else if (diagram.getUmlDiagramType() == UmlDiagramType.ACTIVITY) { } else if (diagram.getUmlDiagramType() == UmlDiagramType.ACTIVITY) {
return ColorParam.activityArrow; return ColorParam.arrow;
} else if (diagram.getUmlDiagramType() == UmlDiagramType.STATE) { } else if (diagram.getUmlDiagramType() == UmlDiagramType.STATE) {
return ColorParam.stateArrow; return ColorParam.arrow;
} }
throw new IllegalStateException(); throw new IllegalStateException();
} }

View File

@ -68,7 +68,7 @@ public class GTileNode extends AbstractTextBlock implements GTile {
public static SheetBlock1 getTextBlock(final Display display) { public static SheetBlock1 getTextBlock(final Display display) {
final Rose rose = new Rose(); final Rose rose = new Rose();
final SkinParam skinParam = new SkinParam(); final SkinParam skinParam = SkinParam.create(null);
final HtmlColor fontColor = rose.getFontColor(skinParam, FontParam.NOTE); final HtmlColor fontColor = rose.getFontColor(skinParam, FontParam.NOTE);
final UFont fontNote = skinParam.getFont(null, false, FontParam.NOTE); final UFont fontNote = skinParam.getFont(null, false, FontParam.NOTE);

View File

@ -107,7 +107,7 @@ public class PostIt {
final HtmlColor noteBackgroundColor = new HtmlColorSetSimple().getColorIfValid("#FBFB77"); final HtmlColor noteBackgroundColor = new HtmlColorSetSimple().getColorIfValid("#FBFB77");
final HtmlColor borderColor = HtmlColorUtils.MY_RED; final HtmlColor borderColor = HtmlColorUtils.MY_RED;
final SkinParam param = SkinParam.noShadowing(); final SkinParam param = SkinParam.noShadowing(null);
final UFont fontNote = param.getFont(null, false, FontParam.NOTE); final UFont fontNote = param.getFont(null, false, FontParam.NOTE);
final FontConfiguration font2 = fontNote.toFont2(HtmlColorUtils.BLACK, true, HtmlColorUtils.BLUE, 8); final FontConfiguration font2 = fontNote.toFont2(HtmlColorUtils.BLACK, true, HtmlColorUtils.BLUE, 8);
final ComponentRoseNote note = new ComponentRoseNote( final ComponentRoseNote note = new ComponentRoseNote(

View File

@ -124,7 +124,7 @@ class PrintSkin extends AbstractPSystem {
private void printComponent(ComponentType type) { private void printComponent(ComponentType type) {
println(type.name()); println(type.name());
final Component comp = skin.createComponent(type, ArrowConfiguration.withDirectionNormal(), final Component comp = skin.createComponent(type, ArrowConfiguration.withDirectionNormal(),
SkinParam.noShadowing(), Display.create(toPrint)); SkinParam.noShadowing(null), Display.create(toPrint));
if (comp == null) { if (comp == null) {
println("null"); println("null");
return; return;

View File

@ -78,7 +78,7 @@ public class PSystemProject extends AbstractPSystem {
PngIO.write(im, os, fileFormatOption.isWithMetadata() ? getMetadata() : null, 96); PngIO.write(im, os, fileFormatOption.isWithMetadata() ? getMetadata() : null, 96);
} else if (fileFormat == FileFormat.SVG) { } else if (fileFormat == FileFormat.SVG) {
final UGraphicSvg svg = new UGraphicSvg(colorMapper, StringUtils.getAsHtml(background), false, 1.0, final UGraphicSvg svg = new UGraphicSvg(colorMapper, StringUtils.getAsHtml(background), false, 1.0,
fileFormatOption.getSvgLinkTarget()); fileFormatOption.getSvgLinkTarget(), fileFormatOption.getHoverColor());
diagram.draw(svg, 0, 0); diagram.draw(svg, 0, 0);
svg.createXml(os); svg.createXml(os);
} else if (fileFormat == FileFormat.EPS) { } else if (fileFormat == FileFormat.EPS) {

View File

@ -77,7 +77,7 @@ public class PSystemProject2 extends AbstractPSystem {
PngIO.write(im, os, fileFormatOption.isWithMetadata() ? getMetadata() : null, 96); PngIO.write(im, os, fileFormatOption.isWithMetadata() ? getMetadata() : null, 96);
} else if (fileFormat == FileFormat.SVG) { } else if (fileFormat == FileFormat.SVG) {
final UGraphicSvg svg = new UGraphicSvg(colorMapper, StringUtils.getAsHtml(background), false, 1.0, final UGraphicSvg svg = new UGraphicSvg(colorMapper, StringUtils.getAsHtml(background), false, 1.0,
fileFormatOption.getSvgLinkTarget()); fileFormatOption.getSvgLinkTarget(), fileFormatOption.getHoverColor());
diagram.draw(svg, 0, 0); diagram.draw(svg, 0, 0);
svg.createXml(os); svg.createXml(os);
} else if (fileFormat == FileFormat.EPS) { } else if (fileFormat == FileFormat.EPS) {

View File

@ -86,17 +86,17 @@ public class Rose implements Skin {
// final FontConfiguration fc = new FontConfiguration(fontArrow, HtmlColorUtils.BLACK); // final FontConfiguration fc = new FontConfiguration(fontArrow, HtmlColorUtils.BLACK);
// stringsToDisplay = DisplayUtils.breakLines(stringsToDisplay, fc, param, param.maxMessageSize()); // stringsToDisplay = DisplayUtils.breakLines(stringsToDisplay, fc, param, param.maxMessageSize());
// } // }
final HtmlColor sequenceArrow = config.getColor() == null ? getHtmlColor(param, ColorParam.sequenceArrow) final HtmlColor sequenceArrow = config.getColor() == null ? getHtmlColor(param, ColorParam.arrow)
: config.getColor(); : config.getColor();
if (config.getArrowDirection() == ArrowDirection.SELF) { if (config.getArrowDirection() == ArrowDirection.SELF) {
return new ComponentRoseSelfArrow(sequenceArrow, getUFont2(param, FontParam.SEQUENCE_ARROW), return new ComponentRoseSelfArrow(sequenceArrow, getUFont2(param, FontParam.ARROW),
stringsToDisplay, config, param, param.maxMessageSize(), param.strictUmlStyle() == false); stringsToDisplay, config, param, param.maxMessageSize(), param.strictUmlStyle() == false);
} }
final HorizontalAlignment messageHorizontalAlignment = param.getHorizontalAlignment( final HorizontalAlignment messageHorizontalAlignment = param.getHorizontalAlignment(
AlignParam.SEQUENCE_MESSAGE_ALIGN, config.getArrowDirection()); AlignParam.SEQUENCE_MESSAGE_ALIGN, config.getArrowDirection());
final HorizontalAlignment textHorizontalAlignment = param.getHorizontalAlignment( final HorizontalAlignment textHorizontalAlignment = param.getHorizontalAlignment(
AlignParam.SEQUENCE_MESSAGETEXT_ALIGN, config.getArrowDirection()); AlignParam.SEQUENCE_MESSAGETEXT_ALIGN, config.getArrowDirection());
return new ComponentRoseArrow(sequenceArrow, getUFont2(param, FontParam.SEQUENCE_ARROW), stringsToDisplay, return new ComponentRoseArrow(sequenceArrow, getUFont2(param, FontParam.ARROW), stringsToDisplay,
config, messageHorizontalAlignment, param, textHorizontalAlignment, param.maxMessageSize(), config, messageHorizontalAlignment, param, textHorizontalAlignment, param.maxMessageSize(),
param.strictUmlStyle() == false); param.strictUmlStyle() == false);
} }

View File

@ -143,7 +143,7 @@ public final class DotDataImageBuilder {
} }
try { try {
final ISkinParam skinParam = dotData.getSkinParam(); final ISkinParam skinParam = dotData.getSkinParam();
final FontConfiguration labelFont = new FontConfiguration(skinParam, FontParam.GENERIC_ARROW, null); final FontConfiguration labelFont = new FontConfiguration(skinParam, FontParam.ARROW, null);
final Line line = new Line(link, dotStringFactory.getColorSequence(), skinParam, stringBounder, final Line line = new Line(link, dotStringFactory.getColorSequence(), skinParam, stringBounder,
labelFont, dotStringFactory.getBibliotekon(), dotData.getPragma()); labelFont, dotStringFactory.getBibliotekon(), dotData.getPragma());

View File

@ -89,15 +89,15 @@ public final class SvekResult extends AbstractTextBlock implements IEntityImage,
private ColorParam getArrowColorParam() { private ColorParam getArrowColorParam() {
if (dotData.getUmlDiagramType() == UmlDiagramType.CLASS) { if (dotData.getUmlDiagramType() == UmlDiagramType.CLASS) {
return ColorParam.classArrow; return ColorParam.arrow;
} else if (dotData.getUmlDiagramType() == UmlDiagramType.OBJECT) { } else if (dotData.getUmlDiagramType() == UmlDiagramType.OBJECT) {
return ColorParam.objectArrow; return ColorParam.arrow;
} else if (dotData.getUmlDiagramType() == UmlDiagramType.DESCRIPTION) { } else if (dotData.getUmlDiagramType() == UmlDiagramType.DESCRIPTION) {
return ColorParam.usecaseArrow; return ColorParam.arrow;
} else if (dotData.getUmlDiagramType() == UmlDiagramType.ACTIVITY) { } else if (dotData.getUmlDiagramType() == UmlDiagramType.ACTIVITY) {
return ColorParam.activityArrow; return ColorParam.arrow;
} else if (dotData.getUmlDiagramType() == UmlDiagramType.STATE) { } else if (dotData.getUmlDiagramType() == UmlDiagramType.STATE) {
return ColorParam.stateArrow; return ColorParam.arrow;
} }
throw new IllegalStateException(); throw new IllegalStateException();
} }

View File

@ -81,7 +81,7 @@ public class EntityImageDescription extends AbstractEntityImage {
final Display codeDisplay = Display.getWithNewlines(entity.getCode()); final Display codeDisplay = Display.getWithNewlines(entity.getCode());
final TextBlock desc = (entity.getDisplay().equals(codeDisplay) && symbol instanceof USymbolFolder) final TextBlock desc = (entity.getDisplay().equals(codeDisplay) && symbol instanceof USymbolFolder)
|| entity.getDisplay().isWhite() ? TextBlockUtils.empty(0, 0) : new BodyEnhanced(entity.getDisplay(), || entity.getDisplay().isWhite() ? TextBlockUtils.empty(0, 0) : new BodyEnhanced(entity.getDisplay(),
symbol.getFontParam(), getSkinParam(), HorizontalAlignment.CENTER, stereotype, symbol.getFontParam(), getSkinParam(), HorizontalAlignment.LEFT, stereotype,
symbol.manageHorizontalLine(), false, false, entity); symbol.manageHorizontalLine(), false, false, entity);
this.url = entity.getUrl99(); this.url = entity.getUrl99();

View File

@ -62,6 +62,7 @@ import net.sourceforge.plantuml.ugraphic.UPath;
import net.sourceforge.plantuml.ugraphic.USegment; import net.sourceforge.plantuml.ugraphic.USegment;
import net.sourceforge.plantuml.ugraphic.USegmentType; import net.sourceforge.plantuml.ugraphic.USegmentType;
import org.w3c.dom.CDATASection;
import org.w3c.dom.Comment; import org.w3c.dom.Comment;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;
@ -109,11 +110,11 @@ public class SvgGraphics {
} }
} }
public SvgGraphics(double scale) { public SvgGraphics(double scale, String hover) {
this(null, scale); this(null, scale, hover);
} }
public SvgGraphics(String backcolor, double scale) { public SvgGraphics(String backcolor, double scale, String hover) {
try { try {
this.scale = scale; this.scale = scale;
this.document = getDocument(); this.document = getDocument();
@ -130,12 +131,23 @@ public class SvgGraphics {
this.filterUid = "b" + getRandomString(rnd); this.filterUid = "b" + getRandomString(rnd);
this.shadowId = "f" + getRandomString(rnd); this.shadowId = "f" + getRandomString(rnd);
this.gradientId = "g" + getRandomString(rnd); this.gradientId = "g" + getRandomString(rnd);
if (hover != null) {
defs.appendChild(getPathHover(hover));
}
} catch (ParserConfigurationException e) { } catch (ParserConfigurationException e) {
e.printStackTrace(); e.printStackTrace();
throw new IllegalStateException(e); throw new IllegalStateException(e);
} }
} }
private Element getPathHover(String hover) {
final Element style = simpleElement("style");
final CDATASection cdata = document.createCDATASection("path:hover { stroke: " + hover + " !important;}");
style.setAttribute("type", "text/css");
style.appendChild(cdata);
return style;
}
private static String getRandomString(final Random rnd) { private static String getRandomString(final Random rnd) {
String result = Integer.toString(Math.abs(rnd.nextInt()), 36); String result = Integer.toString(Math.abs(rnd.nextInt()), 36);
while (result.length() < 6) { while (result.length() < 6) {

View File

@ -34,10 +34,12 @@ public class ChangeState implements Comparable<ChangeState> {
private final TimeTick when; private final TimeTick when;
private final String state; private final String state;
private final String comment;
public ChangeState(TimeTick when, String state) { public ChangeState(TimeTick when, String state, String comment) {
this.when = when; this.when = when;
this.state = state; this.state = state;
this.comment = comment;
} }
public int compareTo(ChangeState other) { public int compareTo(ChangeState other) {
@ -52,4 +54,8 @@ public class ChangeState implements Comparable<ChangeState> {
return state; return state;
} }
public String getComment() {
return comment;
}
} }

View File

@ -0,0 +1,63 @@
/* ========================================================================
* 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.timingdiagram;
import net.sourceforge.plantuml.command.CommandExecutionResult;
import net.sourceforge.plantuml.command.SingleLineCommand2;
import net.sourceforge.plantuml.command.regex.RegexConcat;
import net.sourceforge.plantuml.command.regex.RegexLeaf;
import net.sourceforge.plantuml.command.regex.RegexResult;
public class CommandAtPlayer extends SingleLineCommand2<TimingDiagram> {
public CommandAtPlayer() {
super(getRegexConcat());
}
private static RegexConcat getRegexConcat() {
return new RegexConcat(new RegexLeaf("^"), //
new RegexLeaf("@"), //
new RegexLeaf("PLAYER", CommandTimeMessage.PLAYER_CODE), //
new RegexLeaf("[%s]*$"));
}
@Override
final protected CommandExecutionResult executeArg(TimingDiagram diagram, RegexResult arg) {
final String code = arg.get("PLAYER", 0);
final Player player = diagram.getPlayer(code);
if (player == null) {
return CommandExecutionResult.error("No such participant " + code);
}
diagram.setLastPlayer(player);
return CommandExecutionResult.ok();
}
}

View File

@ -44,7 +44,7 @@ public class CommandAtTime extends SingleLineCommand2<TimingDiagram> {
private static RegexConcat getRegexConcat() { private static RegexConcat getRegexConcat() {
return new RegexConcat(new RegexLeaf("^"), // return new RegexConcat(new RegexLeaf("^"), //
TimeTickBuilder.expressionAt("TIME"), // TimeTickBuilder.expressionAtWithArobase("TIME"), //
new RegexLeaf("[%s]*$")); new RegexLeaf("[%s]*$"));
} }

View File

@ -36,17 +36,18 @@ import net.sourceforge.plantuml.command.regex.RegexConcat;
import net.sourceforge.plantuml.command.regex.RegexLeaf; import net.sourceforge.plantuml.command.regex.RegexLeaf;
import net.sourceforge.plantuml.command.regex.RegexResult; import net.sourceforge.plantuml.command.regex.RegexResult;
public class CommandChangeState extends SingleLineCommand2<TimingDiagram> { public class CommandChangeState1 extends SingleLineCommand2<TimingDiagram> {
public CommandChangeState() { public CommandChangeState1() {
super(getRegexConcat()); super(getRegexConcat());
} }
private static RegexConcat getRegexConcat() { private static RegexConcat getRegexConcat() {
return new RegexConcat(new RegexLeaf("^"), // return new RegexConcat(new RegexLeaf("^"), //
new RegexLeaf("CODE", "([\\p{L}0-9_.@]+)"), // new RegexLeaf("CODE", CommandTimeMessage.PLAYER_CODE), //
new RegexLeaf("[%s]*is[%s]*"), // new RegexLeaf("[%s]*is[%s]*"), //
new RegexLeaf("STATE", "(.*?)"), // new RegexLeaf("STATE", "([^:]*?)"), //
new RegexLeaf("COMMENT", "(?:[%s]*:[%s]*(.*?))?"), //
new RegexLeaf("[%s]*$")); new RegexLeaf("[%s]*$"));
} }
@ -57,8 +58,9 @@ public class CommandChangeState extends SingleLineCommand2<TimingDiagram> {
if (player == null) { if (player == null) {
return CommandExecutionResult.error("Unkown \"" + code + "\""); return CommandExecutionResult.error("Unkown \"" + code + "\"");
} }
final String comment = arg.get("COMMENT", 0);
final TimeTick now = diagram.getNow(); final TimeTick now = diagram.getNow();
player.setState(now, arg.get("STATE", 0)); player.setState(now, arg.get("STATE", 0), comment);
return CommandExecutionResult.ok(); return CommandExecutionResult.ok();
} }

View File

@ -0,0 +1,68 @@
/* ========================================================================
* 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.timingdiagram;
import net.sourceforge.plantuml.command.CommandExecutionResult;
import net.sourceforge.plantuml.command.SingleLineCommand2;
import net.sourceforge.plantuml.command.regex.RegexConcat;
import net.sourceforge.plantuml.command.regex.RegexLeaf;
import net.sourceforge.plantuml.command.regex.RegexResult;
public class CommandChangeState2 extends SingleLineCommand2<TimingDiagram> {
public CommandChangeState2() {
super(getRegexConcat());
}
private static RegexConcat getRegexConcat() {
return new RegexConcat(new RegexLeaf("^"), //
new RegexLeaf("[%s]*"), //
TimeTickBuilder.expressionAtWithoutArobase("TIME"), //
new RegexLeaf("[%s]*is[%s]*"), //
new RegexLeaf("STATE", "([^:]*?)"), //
new RegexLeaf("COMMENT", "(?:[%s]*:[%s]*(.*?))?"), //
new RegexLeaf("[%s]*$"));
}
@Override
final protected CommandExecutionResult executeArg(TimingDiagram diagram, RegexResult arg) {
final Player player = diagram.getLastPlayer();
if (player == null) {
return CommandExecutionResult.error("Missing @ line before this");
}
final TimeTick tick = TimeTickBuilder.parseTimeTick("TIME", arg, diagram);
final String comment = arg.get("COMMENT", 0);
player.setState(tick, arg.get("STATE", 0), comment);
diagram.addTime(tick);
return CommandExecutionResult.ok();
}
}

View File

@ -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.timingdiagram;
import net.sourceforge.plantuml.command.CommandExecutionResult;
import net.sourceforge.plantuml.command.SingleLineCommand2;
import net.sourceforge.plantuml.command.regex.RegexConcat;
import net.sourceforge.plantuml.command.regex.RegexLeaf;
import net.sourceforge.plantuml.command.regex.RegexResult;
public class CommandConstraint extends SingleLineCommand2<TimingDiagram> {
public CommandConstraint() {
super(getRegexConcat());
}
private static RegexConcat getRegexConcat() {
return new RegexConcat(new RegexLeaf("^"), //
new RegexLeaf("PART1", "(" + CommandTimeMessage.PLAYER_CODE + ")?"), //
TimeTickBuilder.expressionAtWithArobase("TIME1"), //
new RegexLeaf("[%s]*"), //
new RegexLeaf("ARROW", "\\<(-+)\\>"), //
new RegexLeaf("[%s]*"), //
TimeTickBuilder.expressionAtWithArobase("TIME2"), //
new RegexLeaf("[%s]*"), //
new RegexLeaf("MESSAGE", "(?::[%s]*(.*))?"), //
new RegexLeaf("[%s]*$"));
}
@Override
final protected CommandExecutionResult executeArg(TimingDiagram diagram, RegexResult arg) {
final String part1 = arg.get("PART1", 0);
final Player player1;
if (part1 == null) {
player1 = diagram.getLastPlayer();
if (player1 == null) {
return CommandExecutionResult.error("You have to provide a participant");
}
} else {
player1 = diagram.getPlayer(part1);
}
final TimeTick tick1 = TimeTickBuilder.parseTimeTick("TIME1", arg, diagram);
diagram.updateNow(tick1);
final TimeTick tick2 = TimeTickBuilder.parseTimeTick("TIME2", arg, diagram);
player1.createConstraint(tick1, tick2, arg.get("MESSAGE", 0));
return CommandExecutionResult.ok();
}
}

View File

@ -38,21 +38,24 @@ import net.sourceforge.plantuml.command.regex.RegexResult;
public class CommandTimeMessage extends SingleLineCommand2<TimingDiagram> { public class CommandTimeMessage extends SingleLineCommand2<TimingDiagram> {
public static final String PLAYER_CODE = "([\\p{L}_][\\p{L}0-9_.]*)";
public CommandTimeMessage() { public CommandTimeMessage() {
super(getRegexConcat()); super(getRegexConcat());
} }
private static RegexConcat getRegexConcat() { private static RegexConcat getRegexConcat() {
return new RegexConcat(new RegexLeaf("^"), // return new RegexConcat(new RegexLeaf("^"), //
new RegexLeaf("PART1", "([\\p{L}0-9_.]+)"), // new RegexLeaf("PART1", PLAYER_CODE), //
TimeTickBuilder.optionalExpressionAt("TIME1"), // TimeTickBuilder.optionalExpressionAtWithArobase("TIME1"), //
new RegexLeaf("[%s]*"), // new RegexLeaf("[%s]*"), //
new RegexLeaf("ARROW", "(-+)\\>"), // new RegexLeaf("ARROW", "(-+)\\>"), //
new RegexLeaf("[%s]*"), // new RegexLeaf("[%s]*"), //
new RegexLeaf("PART2", "([\\p{L}0-9_.]+)"), // new RegexLeaf("PART2", PLAYER_CODE), //
TimeTickBuilder.optionalExpressionAt("TIME2"), // TimeTickBuilder.optionalExpressionAtWithArobase("TIME2"), //
new RegexLeaf("[%s]*"), // new RegexLeaf("[%s]*"), //
new RegexLeaf("MESSAGE", "(?::[%s]*(.*))?"), new RegexLeaf("[%s]*$")); new RegexLeaf("MESSAGE", "(?::[%s]*(.*))?"), //
new RegexLeaf("[%s]*$"));
} }
@Override @Override

View File

@ -0,0 +1,68 @@
/* ========================================================================
* 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.timingdiagram;
import net.sourceforge.plantuml.graphic.SymbolContext;
import net.sourceforge.plantuml.graphic.UDrawable;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.UPolygon;
public class HexaShape implements UDrawable {
private final double width;
private final double height;
private final SymbolContext context;
private final double delta = 12;
private HexaShape(double width, double height, SymbolContext context) {
this.width = width;
this.height = height;
this.context = context;
}
public static HexaShape create(double width, double height, SymbolContext context) {
return new HexaShape(width, height, context);
}
public void drawU(UGraphic ug) {
ug = context.apply(ug);
final UPolygon polygon = new UPolygon();
polygon.addPoint(delta, 0);
polygon.addPoint(width - delta, 0);
polygon.addPoint(width, height / 2);
polygon.addPoint(width - delta, height);
polygon.addPoint(delta, height);
polygon.addPoint(0, height / 2);
ug.draw(polygon);
}
}

View File

@ -31,11 +31,14 @@ package net.sourceforge.plantuml.timingdiagram;
import java.awt.geom.Dimension2D; import java.awt.geom.Dimension2D;
import java.awt.geom.Point2D; import java.awt.geom.Point2D;
import java.awt.geom.Point2D.Double;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import net.sourceforge.plantuml.Dimension2DDouble;
import net.sourceforge.plantuml.FontParam; import net.sourceforge.plantuml.FontParam;
import net.sourceforge.plantuml.ISkinParam; import net.sourceforge.plantuml.ISkinParam;
import net.sourceforge.plantuml.cucadiagram.Display; import net.sourceforge.plantuml.cucadiagram.Display;
@ -43,22 +46,25 @@ import net.sourceforge.plantuml.graphic.FontConfiguration;
import net.sourceforge.plantuml.graphic.HorizontalAlignment; import net.sourceforge.plantuml.graphic.HorizontalAlignment;
import net.sourceforge.plantuml.graphic.HtmlColorUtils; import net.sourceforge.plantuml.graphic.HtmlColorUtils;
import net.sourceforge.plantuml.graphic.StringBounder; import net.sourceforge.plantuml.graphic.StringBounder;
import net.sourceforge.plantuml.graphic.SymbolContext;
import net.sourceforge.plantuml.graphic.TextBlock; import net.sourceforge.plantuml.graphic.TextBlock;
import net.sourceforge.plantuml.ugraphic.UChangeColor;
import net.sourceforge.plantuml.ugraphic.UGraphic; import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.ULine; import net.sourceforge.plantuml.ugraphic.ULine;
import net.sourceforge.plantuml.ugraphic.URectangle;
import net.sourceforge.plantuml.ugraphic.UStroke; import net.sourceforge.plantuml.ugraphic.UStroke;
import net.sourceforge.plantuml.ugraphic.UTranslate; import net.sourceforge.plantuml.ugraphic.UTranslate;
public class Histogram implements TimeDrawing { public class Histogram implements TimeDrawing {
private final List<ChangeState> changes = new ArrayList<ChangeState>(); private final List<ChangeState> changes = new ArrayList<ChangeState>();
private final List<TimeConstraint> constraints = new ArrayList<TimeConstraint>();
private List<String> allStates = new ArrayList<String>(); private List<String> allStates = new ArrayList<String>();
private final double stepHeight = 20; private final double stepHeight = 20;
private final ISkinParam skinParam; private final ISkinParam skinParam;
private final TimingRuler ruler; private final TimingRuler ruler;
private String initialState;
public Histogram(TimingRuler ruler, ISkinParam skinParam) { public Histogram(TimingRuler ruler, ISkinParam skinParam) {
this.ruler = ruler; this.ruler = ruler;
@ -69,30 +75,29 @@ public class Histogram implements TimeDrawing {
final double x = ruler.getPosInPixel(tick); final double x = ruler.getPosInPixel(tick);
final List<String> states = getStatesAt(tick); final List<String> states = getStatesAt(tick);
if (states.size() == 1) { if (states.size() == 1) {
final int num = getStateNumFor(states.get(0)); final double y = getStateYFor(states.get(0));
return new IntricatedPoint(new Point2D.Double(x, num * stepHeight), new Point2D.Double(x, num * stepHeight)); return new IntricatedPoint(new Point2D.Double(x, y), new Point2D.Double(x, y));
} }
assert states.size() == 2; assert states.size() == 2;
final int num1 = getStateNumFor(states.get(0)); final double y1 = getStateYFor(states.get(0));
final int num2 = getStateNumFor(states.get(1)); final double y2 = getStateYFor(states.get(1));
assert num1 != num2; assert y1 != y2;
return new IntricatedPoint(new Point2D.Double(x, num1 * stepHeight), new Point2D.Double(x, num2 * stepHeight)); return new IntricatedPoint(new Point2D.Double(x, y1), new Point2D.Double(x, y2));
// if (isTransition(tick)) {
// return new IntricatedPoint(new Point2D.Double(x, state * stepHeight), new Point2D.Double(x, state
// * stepHeight + stepHeight));
// }
// return new IntricatedPoint(new Point2D.Double(x, state * stepHeight), new Point2D.Double(x, state *
// stepHeight));
} }
private int getStateNumFor(String state) { private double getStateYFor(String state) {
// final String state = getStateAt(tick); return (allStates.size() - 1 - allStates.indexOf(state)) * stepHeight;
return allStates.size() - 1 - allStates.indexOf(state);
} }
private List<String> getStatesAt(TimeTick tick) { private List<String> getStatesAt(TimeTick tick) {
for (int i = 0; i < changes.size(); i++) { for (int i = 0; i < changes.size(); i++) {
if (changes.get(i).getWhen().compareTo(tick) == 0) { if (changes.get(i).getWhen().compareTo(tick) == 0) {
if (i == 0 && initialState == null) {
return Arrays.asList(changes.get(i).getState());
}
if (i == 0 && initialState != null) {
return Arrays.asList(initialState, changes.get(i).getState());
}
return Arrays.asList(changes.get(i - 1).getState(), changes.get(i).getState()); return Arrays.asList(changes.get(i - 1).getState(), changes.get(i).getState());
} }
if (changes.get(i).getWhen().compareTo(tick) > 0) { if (changes.get(i).getWhen().compareTo(tick) > 0) {
@ -120,20 +125,31 @@ public class Histogram implements TimeDrawing {
return -stepHeight * allStates.indexOf(state); return -stepHeight * allStates.indexOf(state);
} }
private SymbolContext getContext() {
return new SymbolContext(HtmlColorUtils.COL_D7E0F2, HtmlColorUtils.COL_038048).withStroke(new UStroke(1.5));
}
public void drawU(UGraphic ug) { public void drawU(UGraphic ug) {
ug = ug.apply(new UChangeColor(HtmlColorUtils.COL_038048)).apply(new UStroke(1.5)); ug = getContext().apply(ug);
final UTranslate deltaY = new UTranslate(0, stepHeight * (allStates.size() - 1)); final UTranslate deltaY = new UTranslate(0, getFullDeltaY());
// System.err.println("changes=" + changes); if (initialState != null) {
drawHLine(ug, getInitialPoint(), getInitialWidth());
}
for (int i = 0; i < changes.size() - 1; i++) { for (int i = 0; i < changes.size() - 1; i++) {
final Point2D pt = getPoint(i); final Point2D pt = getPoint(i);
final Point2D pt2 = getPoint(i + 1); final Point2D pt2 = getPoint(i + 1);
final double len = pt2.getX() - pt.getX(); final double len = pt2.getX() - pt.getX();
ug.apply(new UTranslate(pt).compose(deltaY)).draw(new ULine(len, 0)); drawHLine(ug, pt, len);
} }
final Point2D pt = getPoint(changes.size() - 1); final Point2D pt = getPoint(changes.size() - 1);
final double len = ruler.getWidth() - pt.getX(); final double len = ruler.getWidth() - pt.getX();
ug.apply(new UTranslate(pt).compose(deltaY)).draw(new ULine(len, 0)); drawHLine(ug, pt, len);
if (initialState != null) {
final Point2D before = getInitialPoint();
final Point2D current = getPoint(0);
ug.apply(new UTranslate(current).compose(deltaY)).draw(new ULine(0, before.getY() - current.getY()));
}
for (int i = 1; i < changes.size(); i++) { for (int i = 1; i < changes.size(); i++) {
final Point2D before = getPoint(i - 1); final Point2D before = getPoint(i - 1);
final Point2D current = getPoint(i); final Point2D current = getPoint(i);
@ -142,19 +158,55 @@ public class Histogram implements TimeDrawing {
for (int i = 0; i < changes.size(); i++) { for (int i = 0; i < changes.size(); i++) {
final Point2D ptLabel = getPoint(i); final Point2D ptLabel = getPoint(i);
final TextBlock label = getStateTextBlock(changes.get(i).getState()); final String comment = changes.get(i).getComment();
if (comment == null) {
continue;
}
final TextBlock label = getTextBlock(comment);
final Dimension2D dim = label.calculateDimension(ug.getStringBounder()); final Dimension2D dim = label.calculateDimension(ug.getStringBounder());
label.drawU(ug.apply(new UTranslate(ptLabel).compose(deltaY).compose(new UTranslate(2, -dim.getHeight())))); label.drawU(ug.apply(new UTranslate(ptLabel).compose(deltaY).compose(new UTranslate(2, -dim.getHeight()))));
} }
for (TimeConstraint constraint : constraints) {
final String state1 = last(getStatesAt(constraint.getTick1()));
final String state2 = getStatesAt(constraint.getTick2()).get(0);
final double y1 = getStateYFor(state1);
final double y2 = getStateYFor(state2);
constraint.drawU(ug.apply(new UTranslate(0, y1 - stepHeight / 2)), ruler, skinParam);
}
}
private static String last(List<String> list) {
return list.get(list.size() - 1);
}
private Double getInitialPoint() {
return new Point2D.Double(-getInitialWidth(), yOfState(initialState));
}
private void drawHLine(UGraphic ug, final Point2D pt, final double len) {
final UTranslate deltaY = new UTranslate(0, getFullDeltaY());
final UTranslate pos = new UTranslate(pt).compose(deltaY);
ug = ug.apply(pos);
final SymbolContext context = getContext();
final double height = -pt.getY();
if (height > 0) {
context.withForeColor(context.getBackColor()).apply(ug).draw(new URectangle(len, height));
}
ug.draw(new ULine(len, 0));
}
private double getFullDeltaY() {
return stepHeight * (allStates.size() - 1);
} }
private FontConfiguration getFontConfiguration() { private FontConfiguration getFontConfiguration() {
return new FontConfiguration(skinParam, FontParam.ACTIVITY, null); return new FontConfiguration(skinParam, FontParam.ACTIVITY, null);
} }
private TextBlock getStateTextBlock(String state) { private TextBlock getTextBlock(String value) {
final Display display = Display.getWithNewlines(state); final Display display = Display.getWithNewlines(value);
return display.create(getFontConfiguration(), HorizontalAlignment.LEFT, skinParam); return display.create(getFontConfiguration(), HorizontalAlignment.LEFT, skinParam);
} }
@ -162,4 +214,50 @@ public class Histogram implements TimeDrawing {
return stepHeight * allStates.size() + 10; return stepHeight * allStates.size() + 10;
} }
public TextBlock getWidthHeader(StringBounder stringBounder) {
return new TextBlock() {
public void drawU(UGraphic ug) {
for (String state : allStates) {
final TextBlock label = getTextBlock(state);
final Dimension2D dim = label.calculateDimension(ug.getStringBounder());
label.drawU(ug.apply(new UTranslate(0, getFullDeltaY() + yOfState(state) - dim.getHeight())));
}
}
public Dimension2D calculateDimension(StringBounder stringBounder) {
double width = 0;
for (String state : allStates) {
final TextBlock label = getTextBlock(state);
final Dimension2D dim = label.calculateDimension(stringBounder);
width = Math.max(width, dim.getWidth());
}
if (initialState != null) {
width += getInitialWidth();
}
return new Dimension2DDouble(width, getFullDeltaY());
}
public Rectangle2D getInnerPosition(String member, StringBounder stringBounder) {
return null;
}
};
}
public void setInitialState(String initialState) {
this.initialState = initialState;
if (initialState != null) {
allStates.add(initialState);
}
}
private double getInitialWidth() {
return stepHeight * 2;
}
public void addConstraint(TimeConstraint constraint) {
this.constraints.add(constraint);
}
} }

View File

@ -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.timingdiagram;
import net.sourceforge.plantuml.graphic.SymbolContext;
import net.sourceforge.plantuml.graphic.UDrawable;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.UPath;
import net.sourceforge.plantuml.ugraphic.UPolygon;
public class PentaAShape implements UDrawable {
private final double width;
private final double height;
private final SymbolContext context;
private final double delta = 12;
private PentaAShape(double width, double height, SymbolContext context) {
this.width = width;
this.height = height;
this.context = context;
}
public static PentaAShape create(double width, double height, SymbolContext context) {
return new PentaAShape(width, height, context);
}
public void drawU(UGraphic ug) {
final UPolygon polygon = new UPolygon();
polygon.addPoint(0, 0);
polygon.addPoint(width - delta, 0);
polygon.addPoint(width, height / 2);
polygon.addPoint(width - delta, height);
polygon.addPoint(0, height);
context.withForeColor(context.getBackColor()).apply(ug).draw(polygon);
final UPath path = new UPath();
path.moveTo(0, 0);
path.lineTo(width - delta, 0);
path.lineTo(width, height / 2);
path.lineTo(width - delta, height);
path.lineTo(0, height);
context.apply(ug).draw(path);
}
}

View File

@ -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.timingdiagram;
import net.sourceforge.plantuml.graphic.SymbolContext;
import net.sourceforge.plantuml.graphic.UDrawable;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.UPath;
import net.sourceforge.plantuml.ugraphic.UPolygon;
public class PentaBShape implements UDrawable {
private final double width;
private final double height;
private final SymbolContext context;
private final double delta = 12;
private PentaBShape(double width, double height, SymbolContext context) {
this.width = width;
this.height = height;
this.context = context;
}
public static PentaBShape create(double width, double height, SymbolContext context) {
return new PentaBShape(width, height, context);
}
public void drawU(UGraphic ug) {
final UPolygon polygon = new UPolygon();
polygon.addPoint(delta, 0);
polygon.addPoint(width, 0);
polygon.addPoint(width, height);
polygon.addPoint(delta, height);
polygon.addPoint(0, height / 2);
context.withForeColor(context.getBackColor()).apply(ug).draw(polygon);
final UPath path = new UPath();
path.moveTo(width, 0);
path.lineTo(delta, 0);
path.lineTo(0, height / 2);
path.lineTo(delta, height);
path.lineTo(width, height);
context.apply(ug).draw(path);
}
}

View File

@ -31,6 +31,8 @@ package net.sourceforge.plantuml.timingdiagram;
import java.awt.geom.Dimension2D; import java.awt.geom.Dimension2D;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.TreeSet; import java.util.TreeSet;
@ -56,8 +58,10 @@ public class Player implements TextBlock, TimeProjected {
private final TimingStyle type; private final TimingStyle type;
private final ISkinParam skinParam; private final ISkinParam skinParam;
private final TimingRuler ruler; private final TimingRuler ruler;
private String initialState;
private final Set<ChangeState> changes = new TreeSet<ChangeState>(); private final Set<ChangeState> changes = new TreeSet<ChangeState>();
private final List<TimeConstraint> constraints = new ArrayList<TimeConstraint>();
public Player(String code, String full, TimingStyle type, ISkinParam skinParam, TimingRuler ruler) { public Player(String code, String full, TimingStyle type, ISkinParam skinParam, TimingRuler ruler) {
this.code = code; this.code = code;
@ -78,8 +82,20 @@ public class Player implements TextBlock, TimeProjected {
drawLine(ug.apply(new UChangeColor(HtmlColorUtils.BLACK)).apply(new UStroke(1.0)), -TimingDiagram.marginX1, drawLine(ug.apply(new UChangeColor(HtmlColorUtils.BLACK)).apply(new UStroke(1.0)), -TimingDiagram.marginX1,
dimTitle.getHeight() + 1, dimTitle.getWidth() + 1, dimTitle.getHeight() + 1, dimTitle.getHeight() + 1, dimTitle.getWidth() + 1, dimTitle.getHeight() + 1,
dimTitle.getWidth() + 1 + 10, 0); dimTitle.getWidth() + 1 + 10, 0);
}
getTimeDrawing().drawU(ug.apply(getTranslateForTimeDrawing(ug.getStringBounder()))); public void drawContent(UGraphic ug) {
ug = ug.apply(getTranslateForTimeDrawing(ug.getStringBounder()));
getTimeDrawing().drawU(ug);
}
public void drawWidthHeader(UGraphic ug) {
ug = ug.apply(getTranslateForTimeDrawing(ug.getStringBounder()));
getTimeDrawing().getWidthHeader(ug.getStringBounder()).drawU(ug);
}
public double getGetWidthHeader(StringBounder stringBounder) {
return getTimeDrawing().getWidthHeader(stringBounder).calculateDimension(stringBounder).getWidth();
} }
private void drawLine(UGraphic ug, double... coord) { private void drawLine(UGraphic ug, double... coord) {
@ -102,18 +118,31 @@ public class Player implements TextBlock, TimeProjected {
return full.create(getFontConfiguration(), HorizontalAlignment.LEFT, skinParam); return full.create(getFontConfiguration(), HorizontalAlignment.LEFT, skinParam);
} }
private TimeDrawing cached;
private TimeDrawing getTimeDrawing() { private TimeDrawing getTimeDrawing() {
if (cached == null) {
cached = computeTimeDrawing();
}
return cached;
}
private TimeDrawing computeTimeDrawing() {
final TimeDrawing result; final TimeDrawing result;
if (type == TimingStyle.ROBUST) { if (type == TimingStyle.CONCISE) {
result = new Ribbon(ruler, skinParam); result = new Ribbon(ruler, skinParam);
} else if (type == TimingStyle.CONCISE) { } else if (type == TimingStyle.ROBUST) {
result = new Histogram(ruler, skinParam); result = new Histogram(ruler, skinParam);
} else { } else {
throw new IllegalStateException(); throw new IllegalStateException();
} }
result.setInitialState(initialState);
for (ChangeState change : changes) { for (ChangeState change : changes) {
result.addChange(change); result.addChange(change);
} }
for (TimeConstraint constraint : constraints) {
result.addConstraint(constraint);
}
return result; return result;
} }
@ -132,8 +161,12 @@ public class Player implements TextBlock, TimeProjected {
return null; return null;
} }
public void setState(TimeTick now, String state) { public void setState(TimeTick now, String state, String comment) {
this.changes.add(new ChangeState(now, state)); if (now == null) {
this.initialState = state;
} else {
this.changes.add(new ChangeState(now, state, comment));
}
} }
@ -143,4 +176,8 @@ public class Player implements TextBlock, TimeProjected {
return point.translated(translation); return point.translated(translation);
} }
public void createConstraint(TimeTick tick1, TimeTick tick2, String message) {
this.constraints.add(new TimeConstraint(tick1, tick2, message));
}
} }

View File

@ -41,20 +41,22 @@ import net.sourceforge.plantuml.graphic.FontConfiguration;
import net.sourceforge.plantuml.graphic.HorizontalAlignment; import net.sourceforge.plantuml.graphic.HorizontalAlignment;
import net.sourceforge.plantuml.graphic.HtmlColorUtils; import net.sourceforge.plantuml.graphic.HtmlColorUtils;
import net.sourceforge.plantuml.graphic.StringBounder; import net.sourceforge.plantuml.graphic.StringBounder;
import net.sourceforge.plantuml.graphic.SymbolContext;
import net.sourceforge.plantuml.graphic.TextBlock; import net.sourceforge.plantuml.graphic.TextBlock;
import net.sourceforge.plantuml.ugraphic.UChangeColor; import net.sourceforge.plantuml.graphic.TextBlockUtils;
import net.sourceforge.plantuml.ugraphic.UGraphic; import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.ULine;
import net.sourceforge.plantuml.ugraphic.UStroke; import net.sourceforge.plantuml.ugraphic.UStroke;
import net.sourceforge.plantuml.ugraphic.UTranslate; import net.sourceforge.plantuml.ugraphic.UTranslate;
public class Ribbon implements TimeDrawing { public class Ribbon implements TimeDrawing {
private final List<ChangeState> changes = new ArrayList<ChangeState>(); private final List<ChangeState> changes = new ArrayList<ChangeState>();
private final List<TimeConstraint> constraints = new ArrayList<TimeConstraint>();
private final double delta = 12; private final double delta = 12;
private final ISkinParam skinParam; private final ISkinParam skinParam;
private final TimingRuler ruler; private final TimingRuler ruler;
private String initialState;
public Ribbon(TimingRuler ruler, ISkinParam skinParam) { public Ribbon(TimingRuler ruler, ISkinParam skinParam) {
this.ruler = ruler; this.ruler = ruler;
@ -63,7 +65,7 @@ public class Ribbon implements TimeDrawing {
public IntricatedPoint getTimeProjection(StringBounder stringBounder, TimeTick tick) { public IntricatedPoint getTimeProjection(StringBounder stringBounder, TimeTick tick) {
final double x = ruler.getPosInPixel(tick); final double x = ruler.getPosInPixel(tick);
final double y = delta * 0.5; final double y = delta * 0.5 + getHeightForConstraints();
for (ChangeState change : changes) { for (ChangeState change : changes) {
if (change.getWhen().compareTo(tick) == 0) { if (change.getWhen().compareTo(tick) == 0) {
return new IntricatedPoint(new Point2D.Double(x, y), new Point2D.Double(x, y)); return new IntricatedPoint(new Point2D.Double(x, y), new Point2D.Double(x, y));
@ -84,59 +86,110 @@ public class Ribbon implements TimeDrawing {
return new FontConfiguration(skinParam, FontParam.ACTIVITY, null); return new FontConfiguration(skinParam, FontParam.ACTIVITY, null);
} }
private TextBlock getStateTextBlock(ChangeState state) { private TextBlock getTextBlock(String value) {
final Display display = Display.getWithNewlines(state.getState()); final Display display = Display.getWithNewlines(value);
return display.create(getFontConfiguration(), HorizontalAlignment.LEFT, skinParam); return display.create(getFontConfiguration(), HorizontalAlignment.LEFT, skinParam);
} }
public void drawU(UGraphic ug) { public void drawU(UGraphic ug) {
ug = ug.apply(new UTranslate(0, 0.5 * delta));
// System.err.println("changes=" + changes); UGraphic ugDown = ug.apply(new UTranslate(0, getHeightForConstraints()));
final TextBlock inital;
final StringBounder stringBounder = ugDown.getStringBounder();
if (initialState == null) {
inital = null;
} else {
inital = getTextBlock(initialState);
drawPentaA(ugDown.apply(new UTranslate(-getInitialWidth(stringBounder), -delta / 2)),
getInitialWidth(stringBounder));
}
for (int i = 0; i < changes.size() - 1; i++) { for (int i = 0; i < changes.size() - 1; i++) {
final double a = getPosInPixel(changes.get(i)); final double a = getPosInPixel(changes.get(i));
final double b = getPosInPixel(changes.get(i + 1)); final double b = getPosInPixel(changes.get(i + 1));
assert b > a; assert b > a;
draw1(ug.apply(new UTranslate(a, 0)), b - a, true); drawHexa(ugDown.apply(new UTranslate(a, -delta / 2)), b - a);
draw2(ug.apply(new UTranslate(a, 0)), b - a, true);
} }
final double a = getPosInPixel(changes.get(changes.size() - 1)); final double a = getPosInPixel(changes.get(changes.size() - 1));
draw1(ug.apply(new UTranslate(a, 0)), ruler.getWidth() - a, false); drawPentaB(ugDown.apply(new UTranslate(a, -delta / 2)), ruler.getWidth() - a);
draw2(ug.apply(new UTranslate(a, 0)), ruler.getWidth() - a, false);
ugDown = ugDown.apply(new UTranslate(0, delta / 2));
if (inital != null) {
final Dimension2D dimInital = inital.calculateDimension(stringBounder);
inital.drawU(ugDown.apply(new UTranslate(-getDelta() - dimInital.getWidth(), -dimInital.getHeight() / 2)));
}
for (ChangeState change : changes) { for (ChangeState change : changes) {
final TextBlock state = getStateTextBlock(change); final TextBlock state = getTextBlock(change.getState());
final Dimension2D dim = state.calculateDimension(ug.getStringBounder()); final Dimension2D dim = state.calculateDimension(stringBounder);
final double x = ruler.getPosInPixel(change.getWhen()); final double x = ruler.getPosInPixel(change.getWhen());
state.drawU(ug.apply(new UTranslate(x + getDelta(), -dim.getHeight() / 2))); state.drawU(ugDown.apply(new UTranslate(x + getDelta(), -dim.getHeight() / 2)));
final String commentString = change.getComment();
if (commentString != null) {
final TextBlock comment = getTextBlock(commentString);
final Dimension2D dimComment = comment.calculateDimension(stringBounder);
comment.drawU(ugDown.apply(new UTranslate(x + getDelta(), -delta - dimComment.getHeight())));
}
}
for (TimeConstraint constraint : constraints) {
constraint.drawU(ug.apply(new UTranslate(0, 15)), ruler, skinParam);
} }
} }
private void draw1(UGraphic ug, double len, boolean withEnd) { private double getInitialWidth(final StringBounder stringBounder) {
ug = ug.apply(new UChangeColor(HtmlColorUtils.COL_038048)).apply(new UStroke(1.5)); return getTextBlock(initialState).calculateDimension(stringBounder).getWidth() + 2 * delta;
ug.draw(new ULine(delta, delta));
ug.apply(new UTranslate(delta, delta)).draw(new ULine(len - 2 * delta, 0));
if (withEnd) {
ug.apply(new UTranslate(len - delta, delta)).draw(new ULine(delta, -delta));
}
} }
private void draw2(UGraphic ug, double len, boolean withEnd) { private SymbolContext getContext() {
ug = ug.apply(new UChangeColor(HtmlColorUtils.COL_038048)).apply(new UStroke(1.5)); return new SymbolContext(HtmlColorUtils.COL_D7E0F2, HtmlColorUtils.COL_038048).withStroke(new UStroke(1.5));
ug.draw(new ULine(delta, -delta)); }
ug.apply(new UTranslate(delta, -delta)).draw(new ULine(len - 2 * delta, 0));
if (withEnd) { private void drawHexa(UGraphic ug, double len) {
ug.apply(new UTranslate(len - delta, -delta)).draw(new ULine(delta, delta)); final HexaShape shape = HexaShape.create(len, 2 * delta, getContext());
shape.drawU(ug);
}
private void drawPentaB(UGraphic ug, double len) {
final PentaBShape shape = PentaBShape.create(len, 2 * delta, getContext());
shape.drawU(ug);
}
private void drawPentaA(UGraphic ug, double len) {
final PentaAShape shape = PentaAShape.create(len, 2 * delta, getContext());
shape.drawU(ug);
}
private double getHeightForConstraints() {
if (constraints.size() == 0) {
return 0;
} }
return 30;
} }
public double getHeight() { public double getHeight() {
return 3 * delta; return 3 * delta + getHeightForConstraints();
} }
public double getDelta() { public double getDelta() {
return delta; return delta;
} }
public TextBlock getWidthHeader(StringBounder stringBounder) {
if (initialState != null) {
return TextBlockUtils.empty(getInitialWidth(stringBounder), 2 * delta);
}
return TextBlockUtils.empty(0, 0);
}
public void setInitialState(String initialState) {
this.initialState = initialState;
}
public void addConstraint(TimeConstraint constraint) {
this.constraints.add(constraint);
}
} }

View File

@ -94,9 +94,10 @@ public class TimeArrow implements UDrawable {
return new TimeArrow(translate.getTranslated(start), translate.getTranslated(end), label, spriteContainer); return new TimeArrow(translate.getTranslated(start), translate.getTranslated(end), label, spriteContainer);
} }
private Point2D onCircle(double alpha, double radius) { public static Point2D onCircle(Point2D pt, double alpha) {
final double x = end.getX() - Math.sin(alpha) * radius; final double radius = 8;
final double y = end.getY() - Math.cos(alpha) * radius; final double x = pt.getX() - Math.sin(alpha) * radius;
final double y = pt.getY() - Math.cos(alpha) * radius;
return new Point2D.Double(x, y); return new Point2D.Double(x, y);
} }
@ -107,13 +108,13 @@ public class TimeArrow implements UDrawable {
public void drawU(UGraphic ug) { public void drawU(UGraphic ug) {
final double angle = getAngle(); final double angle = getAngle();
ug = ug.apply(new UChangeColor(HtmlColorUtils.BLUE)).apply(new UStroke(1.5)); ug = ug.apply(new UChangeColor(HtmlColorUtils.BLUE)).apply(new UStroke());
final ULine line = new ULine(end.getX() - start.getX(), end.getY() - start.getY()); final ULine line = new ULine(end.getX() - start.getX(), end.getY() - start.getY());
ug.apply(new UTranslate(start)).draw(line); ug.apply(new UTranslate(start)).draw(line);
final double delta = 20.0 * Math.PI / 180.0; final double delta = 20.0 * Math.PI / 180.0;
final Point2D pt1 = onCircle(angle + delta, 8); final Point2D pt1 = onCircle(end, angle + delta);
final Point2D pt2 = onCircle(angle - delta, 8); final Point2D pt2 = onCircle(end, angle - delta);
final UPolygon polygon = new UPolygon(); final UPolygon polygon = new UPolygon();
polygon.addPoint(pt1.getX(), pt1.getY()); polygon.addPoint(pt1.getX(), pt1.getY());

View File

@ -0,0 +1,116 @@
/* ========================================================================
* 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.timingdiagram;
import java.awt.Font;
import java.awt.geom.Dimension2D;
import java.awt.geom.Point2D;
import net.sourceforge.plantuml.ISkinParam;
import net.sourceforge.plantuml.cucadiagram.Display;
import net.sourceforge.plantuml.graphic.FontConfiguration;
import net.sourceforge.plantuml.graphic.HorizontalAlignment;
import net.sourceforge.plantuml.graphic.HtmlColorUtils;
import net.sourceforge.plantuml.graphic.TextBlock;
import net.sourceforge.plantuml.ugraphic.UChangeBackColor;
import net.sourceforge.plantuml.ugraphic.UChangeColor;
import net.sourceforge.plantuml.ugraphic.UFont;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.ULine;
import net.sourceforge.plantuml.ugraphic.UPolygon;
import net.sourceforge.plantuml.ugraphic.UTranslate;
public class TimeConstraint {
private final TimeTick tick1;
private final TimeTick tick2;
private final Display label;
public TimeConstraint(TimeTick tick1, TimeTick tick2, String label) {
this.tick1 = tick1;
this.tick2 = tick2;
this.label = Display.getWithNewlines(label);
}
public final TimeTick getTick1() {
return tick1;
}
public final TimeTick getTick2() {
return tick2;
}
public final Display getLabel() {
return label;
}
private TextBlock getTextBlock(Display display, ISkinParam skinParam) {
return display.create(getFontConfiguration(), HorizontalAlignment.LEFT, skinParam);
}
private FontConfiguration getFontConfiguration() {
final UFont font = new UFont("Serif", Font.PLAIN, 14);
return new FontConfiguration(font, HtmlColorUtils.BLACK, HtmlColorUtils.BLUE, false);
}
public void drawU(UGraphic ug, TimingRuler ruler, ISkinParam skinParam) {
ug = ug.apply(new UChangeColor(HtmlColorUtils.RED)).apply(new UChangeBackColor(HtmlColorUtils.RED));
final double x1 = ruler.getPosInPixel(tick1);
final double x2 = ruler.getPosInPixel(tick2);
final ULine line = new ULine(x2 - x1, 0);
ug = ug.apply(new UTranslate(x1, 0));
ug.draw(line);
ug.draw(getPolygon(-Math.PI / 2, new Point2D.Double(0, 0)));
ug.draw(getPolygon(Math.PI / 2, new Point2D.Double(x2 - x1, 0)));
final TextBlock text = getTextBlock(label, skinParam);
final Dimension2D dimText = text.calculateDimension(ug.getStringBounder());
final double x = (x2 - x1 - dimText.getWidth()) / 2;
final UTranslate tr = new UTranslate(x, -5 - dimText.getHeight());
text.drawU(ug.apply(tr));
}
private UPolygon getPolygon(final double angle, final Point2D end) {
final double delta = 20.0 * Math.PI / 180.0;
final Point2D pt1 = TimeArrow.onCircle(end, angle + delta);
final Point2D pt2 = TimeArrow.onCircle(end, angle - delta);
final UPolygon polygon = new UPolygon();
polygon.addPoint(pt1.getX(), pt1.getY());
polygon.addPoint(pt2.getX(), pt2.getY());
polygon.addPoint(end.getX(), end.getY());
return polygon;
}
}

View File

@ -29,6 +29,8 @@
*/ */
package net.sourceforge.plantuml.timingdiagram; package net.sourceforge.plantuml.timingdiagram;
import net.sourceforge.plantuml.graphic.StringBounder;
import net.sourceforge.plantuml.graphic.TextBlock;
import net.sourceforge.plantuml.graphic.UDrawable; import net.sourceforge.plantuml.graphic.UDrawable;
public interface TimeDrawing extends TimeProjected, UDrawable { public interface TimeDrawing extends TimeProjected, UDrawable {
@ -37,4 +39,10 @@ public interface TimeDrawing extends TimeProjected, UDrawable {
public void addChange(ChangeState change); public void addChange(ChangeState change);
public TextBlock getWidthHeader(StringBounder stringBounder);
public void setInitialState(String initialState);
public void addConstraint(TimeConstraint constraint);
} }

View File

@ -34,14 +34,19 @@ import net.sourceforge.plantuml.command.regex.RegexResult;
public class TimeTickBuilder { public class TimeTickBuilder {
private static final String REGEX = "@(\\+?)(\\d+)"; private static final String WITHOUT_AROBASE = "(\\+?)(\\d+)";
private static final String WITH_AROBASE = "@" + WITHOUT_AROBASE;
public static RegexLeaf expressionAt(String name) { public static RegexLeaf expressionAtWithoutArobase(String name) {
return new RegexLeaf(name, REGEX); return new RegexLeaf(name, WITHOUT_AROBASE);
} }
public static RegexLeaf optionalExpressionAt(String name) { public static RegexLeaf expressionAtWithArobase(String name) {
return new RegexLeaf(name, "(?:" + REGEX + ")?"); return new RegexLeaf(name, WITH_AROBASE);
}
public static RegexLeaf optionalExpressionAtWithArobase(String name) {
return new RegexLeaf(name, "(?:" + WITH_AROBASE + ")?");
} }
public static TimeTick parseTimeTick(String name, RegexResult arg, Clock clock) { public static TimeTick parseTimeTick(String name, RegexResult arg, Clock clock) {

View File

@ -59,6 +59,7 @@ public class TimingDiagram extends UmlDiagram implements Clock {
private final List<TimeMessage> messages = new ArrayList<TimeMessage>(); private final List<TimeMessage> messages = new ArrayList<TimeMessage>();
private final TimingRuler ruler = new TimingRuler(getSkinParam()); private final TimingRuler ruler = new TimingRuler(getSkinParam());
private TimeTick now; private TimeTick now;
private Player lastPlayer;
public DiagramDescription getDescription() { public DiagramDescription getDescription() {
return new DiagramDescriptionImpl("(Timing Diagram)", getClass()); return new DiagramDescriptionImpl("(Timing Diagram)", getClass());
@ -94,29 +95,43 @@ public class TimingDiagram extends UmlDiagram implements Clock {
private final double marginX2 = 5; private final double marginX2 = 5;
private void drawInternal(UGraphic ug) { private void drawInternal(UGraphic ug) {
final UTranslate lastTranslate = getUTranslateForPlayer(null, ug.getStringBounder()); final StringBounder stringBounder = ug.getStringBounder();
final double totalWith = ruler.getWidth() + marginX1 + marginX2; final UTranslate lastTranslate = getUTranslateForPlayer(null, stringBounder);
final double withBeforeRuler = getWithBeforeRuler(stringBounder);
final double totalWith = withBeforeRuler + ruler.getWidth() + marginX1 + marginX2;
final ULine border = new ULine(0, lastTranslate.getDy()); final ULine border = new ULine(0, lastTranslate.getDy());
final UStroke borderStroke = new UStroke(1.7); final UStroke borderStroke = new UStroke(1.7);
ug.apply(new UChangeColor(HtmlColorUtils.BLACK)).apply(borderStroke).draw(border); ug.apply(new UChangeColor(HtmlColorUtils.BLACK)).apply(borderStroke).draw(border);
ug.apply(new UChangeColor(HtmlColorUtils.BLACK)).apply(borderStroke).apply(new UTranslate(totalWith, 0)) ug.apply(new UChangeColor(HtmlColorUtils.BLACK)).apply(borderStroke).apply(new UTranslate(totalWith, 0))
.draw(border); .draw(border);
// ug.apply(new UChangeColor(HtmlColorUtils.BLACK)).apply(new UStroke(2.0)).draw(border);
ug = ug.apply(new UTranslate(marginX1, 0)); ug = ug.apply(new UTranslate(marginX1, 0));
for (Player player : players.values()) { for (Player player : players.values()) {
final UGraphic playerUg = ug.apply(getUTranslateForPlayer(player, ug.getStringBounder())); final UGraphic playerUg = ug.apply(getUTranslateForPlayer(player, stringBounder));
player.drawU(playerUg); player.drawU(playerUg);
player.drawContent(playerUg.apply(new UTranslate(withBeforeRuler, 0)));
player.drawWidthHeader(playerUg);
playerUg.apply(new UChangeColor(HtmlColorUtils.BLACK)).apply(borderStroke) playerUg.apply(new UChangeColor(HtmlColorUtils.BLACK)).apply(borderStroke)
.apply(new UTranslate(-marginX1, 0)).draw(new ULine(totalWith, 0)); .apply(new UTranslate(-marginX1, 0)).draw(new ULine(totalWith, 0));
} }
ug = ug.apply(new UTranslate(withBeforeRuler, 0));
ruler.draw(ug.apply(lastTranslate)); ruler.draw(ug.apply(lastTranslate));
for (TimeMessage timeMessage : messages) { for (TimeMessage timeMessage : messages) {
drawMessages(ug, timeMessage); drawMessages(ug, timeMessage);
} }
} }
private double getWithBeforeRuler(StringBounder stringBounder) {
double width = 0;
for (Player player : players.values()) {
width = Math.max(width, player.getGetWidthHeader(stringBounder));
}
return width;
}
private void drawMessages(UGraphic ug, TimeMessage message) { private void drawMessages(UGraphic ug, TimeMessage message) {
final Player player1 = message.getPlayer1(); final Player player1 = message.getPlayer1();
final Player player2 = message.getPlayer2(); final Player player2 = message.getPlayer2();
@ -149,7 +164,9 @@ public class TimingDiagram extends UmlDiagram implements Clock {
} }
public void createLifeLine(String code, String full, TimingStyle type) { public void createLifeLine(String code, String full, TimingStyle type) {
players.put(code, new Player(code, full, type, getSkinParam(), ruler)); final Player player = new Player(code, full, type, getSkinParam(), ruler);
players.put(code, player);
lastPlayer = player;
} }
public void createTimeMessage(Player player1, TimeTick time1, Player player2, TimeTick time2, String label) { public void createTimeMessage(Player player1, TimeTick time1, Player player2, TimeTick time2, String label) {
@ -163,15 +180,27 @@ public class TimingDiagram extends UmlDiagram implements Clock {
ruler.addTime(time); ruler.addTime(time);
} }
public void updateNow(TimeTick time) {
this.now = time;
}
public Player getPlayer(String code) { public Player getPlayer(String code) {
return players.get(code); return players.get(code);
} }
public TimeTick getNow() { public TimeTick getNow() {
// if (now == null) { // if (now == null) {
// throw new IllegalStateException(); // throw new IllegalStateException();
// } // }
return now; return now;
} }
public void setLastPlayer(Player player) {
this.lastPlayer = player;
}
public Player getLastPlayer() {
return lastPlayer;
}
} }

View File

@ -51,9 +51,12 @@ public class TimingDiagramFactory extends UmlDiagramFactory {
addCommonCommands(cmds); addCommonCommands(cmds);
cmds.add(new CommandLifeLine()); cmds.add(new CommandLifeLine());
cmds.add(new CommandChangeState()); cmds.add(new CommandChangeState1());
cmds.add(new CommandChangeState2());
cmds.add(new CommandAtTime()); cmds.add(new CommandAtTime());
cmds.add(new CommandAtPlayer());
cmds.add(new CommandTimeMessage()); cmds.add(new CommandTimeMessage());
cmds.add(new CommandConstraint());
return cmds; return cmds;
} }

View File

@ -106,6 +106,9 @@ public class TimingRuler {
} }
private TimeTick getMax() { private TimeTick getMax() {
if (times.size() == 0) {
throw new IllegalStateException("Empty list!");
}
return times.get(times.size() - 1); return times.get(times.size() - 1);
} }

View File

@ -151,7 +151,7 @@ public class FontChecker {
} }
private String getSvgImage(char c) throws IOException, TransformerException { private String getSvgImage(char c) throws IOException, TransformerException {
final SvgGraphics svg = new SvgGraphics(1.0); final SvgGraphics svg = new SvgGraphics(1.0, null);
svg.setStrokeColor("black"); svg.setStrokeColor("black");
svg.svgImage(getBufferedImage(c), 0, 0); svg.svgImage(getBufferedImage(c), 0, 0);
final ByteArrayOutputStream os = new ByteArrayOutputStream(); final ByteArrayOutputStream os = new ByteArrayOutputStream();

View File

@ -359,7 +359,8 @@ public class ImageBuilder {
case PNG: case PNG:
return createUGraphicPNG(colorMapper, dpiFactor, dim, mybackcolor, animationArg, dx, dy); return createUGraphicPNG(colorMapper, dpiFactor, dim, mybackcolor, animationArg, dx, dy);
case SVG: case SVG:
return createUGraphicSVG(colorMapper, dpiFactor, dim, mybackcolor, fileFormatOption.getSvgLinkTarget()); return createUGraphicSVG(colorMapper, dpiFactor, dim, mybackcolor, fileFormatOption.getSvgLinkTarget(),
fileFormatOption.getHoverColor());
case EPS: case EPS:
return new UGraphicEps(colorMapper, EpsStrategy.getDefault2()); return new UGraphicEps(colorMapper, EpsStrategy.getDefault2());
case EPS_TEXT: case EPS_TEXT:
@ -380,18 +381,18 @@ public class ImageBuilder {
} }
private UGraphic2 createUGraphicSVG(ColorMapper colorMapper, double scale, Dimension2D dim, HtmlColor mybackcolor, private UGraphic2 createUGraphicSVG(ColorMapper colorMapper, double scale, Dimension2D dim, HtmlColor mybackcolor,
String svgLinkTarget) { String svgLinkTarget, String hover) {
Color backColor = Color.WHITE; Color backColor = Color.WHITE;
if (mybackcolor instanceof HtmlColorSimple) { if (mybackcolor instanceof HtmlColorSimple) {
backColor = colorMapper.getMappedColor(mybackcolor); backColor = colorMapper.getMappedColor(mybackcolor);
} }
final UGraphicSvg ug; final UGraphicSvg ug;
if (mybackcolor instanceof HtmlColorGradient) { if (mybackcolor instanceof HtmlColorGradient) {
ug = new UGraphicSvg(colorMapper, (HtmlColorGradient) mybackcolor, false, scale, svgLinkTarget); ug = new UGraphicSvg(colorMapper, (HtmlColorGradient) mybackcolor, false, scale, svgLinkTarget, hover);
} else if (backColor == null || backColor.equals(Color.WHITE)) { } else if (backColor == null || backColor.equals(Color.WHITE)) {
ug = new UGraphicSvg(colorMapper, false, scale, svgLinkTarget); ug = new UGraphicSvg(colorMapper, false, scale, svgLinkTarget, hover);
} else { } else {
ug = new UGraphicSvg(colorMapper, StringUtils.getAsHtml(backColor), false, scale, svgLinkTarget); ug = new UGraphicSvg(colorMapper, StringUtils.getAsHtml(backColor), false, scale, svgLinkTarget, hover);
} }
return ug; return ug;

View File

@ -67,7 +67,8 @@ public abstract class UGraphicUtils {
PngIO.write(im, os, fileFormatOption.isWithMetadata() ? metadata : null, 96); PngIO.write(im, os, fileFormatOption.isWithMetadata() ? metadata : null, 96);
} else if (fileFormat == FileFormat.SVG) { } else if (fileFormat == FileFormat.SVG) {
final UGraphicSvg svg = new UGraphicSvg(colorMapper, StringUtils.getAsHtml(colorMapper final UGraphicSvg svg = new UGraphicSvg(colorMapper, StringUtils.getAsHtml(colorMapper
.getMappedColor(background)), false, 1.0, fileFormatOption.getSvgLinkTarget()); .getMappedColor(background)), false, 1.0, fileFormatOption.getSvgLinkTarget(),
fileFormatOption.getHoverColor());
image.drawU(svg); image.drawU(svg);
svg.createXml(os); svg.createXml(os);
} else if (fileFormat == FileFormat.EPS) { } else if (fileFormat == FileFormat.EPS) {

View File

@ -76,16 +76,16 @@ public class UGraphicSvg extends AbstractUGraphic<SvgGraphics> implements ClipCo
register(); register();
} }
public UGraphicSvg(ColorMapper colorMapper, String backcolor, boolean textAsPath, double scale, String linkTarget) { public UGraphicSvg(ColorMapper colorMapper, String backcolor, boolean textAsPath, double scale, String linkTarget, String hover) {
this(colorMapper, new SvgGraphics(backcolor, scale), textAsPath, linkTarget); this(colorMapper, new SvgGraphics(backcolor, scale, hover), textAsPath, linkTarget);
} }
public UGraphicSvg(ColorMapper colorMapper, boolean textAsPath, double scale, String linkTarget) { public UGraphicSvg(ColorMapper colorMapper, boolean textAsPath, double scale, String linkTarget, String hover) {
this(colorMapper, new SvgGraphics(scale), textAsPath, linkTarget); this(colorMapper, new SvgGraphics(scale, hover), textAsPath, linkTarget);
} }
public UGraphicSvg(ColorMapper mapper, HtmlColorGradient gr, boolean textAsPath, double scale, String linkTarget) { public UGraphicSvg(ColorMapper mapper, HtmlColorGradient gr, boolean textAsPath, double scale, String linkTarget, String hover) {
this(mapper, new SvgGraphics(scale), textAsPath, linkTarget); this(mapper, new SvgGraphics(scale, hover), textAsPath, linkTarget);
final SvgGraphics svg = getGraphicObject(); final SvgGraphics svg = getGraphicObject();
svg.paintBackcolorGradient(mapper, gr); svg.paintBackcolorGradient(mapper, gr);

View File

@ -175,7 +175,8 @@ public class PSystemVersion extends AbstractPSystem {
add(strings, "<u>Word Macro</u>: Alain Bertucat & Matthieu Sabatier", withTag); add(strings, "<u>Word Macro</u>: Alain Bertucat & Matthieu Sabatier", withTag);
add(strings, "<u>Word Add-in</u>: Adriaan van den Brand", withTag); add(strings, "<u>Word Add-in</u>: Adriaan van den Brand", withTag);
add(strings, "<u>J2V8 & viz.js integration</u>: Andreas Studer", withTag); add(strings, "<u>J2V8 & viz.js integration</u>: Andreas Studer", withTag);
add(strings, "<u>Eclipse Plugin</u>: Claude Durif & Anne Pecoil", withTag); add(strings, "<u>Official Eclipse Plugin</u>: Hallvard Tr\u00E6tteberg", withTag);
add(strings, "<u>Original Eclipse Plugin</u>: Claude Durif & Anne Pecoil", withTag);
add(strings, "<u>Servlet & XWiki</u>: Maxime Sinclair", withTag); add(strings, "<u>Servlet & XWiki</u>: Maxime Sinclair", withTag);
add(strings, "<u>Site design</u>: Raphael Cotisson", withTag); add(strings, "<u>Site design</u>: Raphael Cotisson", withTag);
add(strings, "<u>Logo</u>: Benjamin Croizet", withTag); add(strings, "<u>Logo</u>: Benjamin Croizet", withTag);

View File

@ -36,7 +36,7 @@ import java.util.Date;
public class Version { public class Version {
public static int version() { public static int version() {
return 8055; return 8056;
} }
public static String versionString() { public static String versionString() {
@ -68,7 +68,7 @@ public class Version {
} }
public static long compileTime() { public static long compileTime() {
return 1485969540264L; return 1487187608733L;
} }
public static String compileTimeString() { public static String compileTimeString() {