1
0
mirror of https://github.com/octoleo/plantuml.git synced 2024-12-22 10:59:01 +00:00

version 2017.09

This commit is contained in:
Arnaud Roques 2017-04-05 19:37:42 +02:00
parent 091a95bd82
commit e3a5d8f744
242 changed files with 2851 additions and 920 deletions

View File

@ -35,7 +35,7 @@
<groupId>net.sourceforge.plantuml</groupId> <groupId>net.sourceforge.plantuml</groupId>
<artifactId>plantuml</artifactId> <artifactId>plantuml</artifactId>
<version>2017.09-SNAPSHOT</version> <version>2017.10-SNAPSHOT</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>PlantUML</name> <name>PlantUML</name>

View File

@ -38,11 +38,13 @@ package net.sourceforge.plantuml;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.List; import java.util.List;
import net.sourceforge.plantuml.code.AsciiEncoder; import net.sourceforge.plantuml.code.AsciiEncoder;
import net.sourceforge.plantuml.command.regex.Matcher2; import net.sourceforge.plantuml.command.regex.Matcher2;
import net.sourceforge.plantuml.core.Diagram; import net.sourceforge.plantuml.core.Diagram;
import net.sourceforge.plantuml.preproc.Defines;
import net.sourceforge.plantuml.utils.StartUtils; import net.sourceforge.plantuml.utils.StartUtils;
import net.sourceforge.plantuml.version.Version; import net.sourceforge.plantuml.version.Version;
@ -51,9 +53,10 @@ public class BlockUml {
private final List<CharSequence2> data; private final List<CharSequence2> data;
private final int startLine; private final int startLine;
private Diagram system; private Diagram system;
private final Defines localDefines;
BlockUml(String... strings) { BlockUml(String... strings) {
this(convert(strings), 0); this(convert(strings), 0, Defines.createEmpty());
} }
public String getFlashData() { public String getFlashData() {
@ -80,8 +83,9 @@ public class BlockUml {
return result; return result;
} }
public BlockUml(List<CharSequence2> strings, int startLine) { public BlockUml(List<CharSequence2> strings, int startLine, Defines defines) {
this.startLine = startLine; this.startLine = startLine;
this.localDefines = defines;
final CharSequence2 s0 = strings.get(0).trin(); final CharSequence2 s0 = strings.get(0).trin();
if (StartUtils.startsWithSymbolAnd("start", s0) == false) { if (StartUtils.startsWithSymbolAnd("start", s0) == false) {
throw new IllegalArgumentException(); throw new IllegalArgumentException();
@ -156,4 +160,20 @@ public class BlockUml {
return (Version.compileTime() / 1000L / 60) * 1000L * 60 + Version.beta() * 1000L * 3600; return (Version.compileTime() / 1000L / 60) * 1000L * 60 + Version.beta() * 1000L * 3600;
} }
public boolean isStartDef(String name) {
final String signature = "@startdef(id=" + name + ")";
return data.get(0).toString().equalsIgnoreCase(signature);
}
public List<? extends CharSequence> getDefinition() {
if (data.get(0).toString().startsWith("@startdef") == false) {
throw new IllegalStateException();
}
return Collections.unmodifiableList(data.subList(1, data.size() - 1));
}
public Defines getLocalDefines() {
return localDefines;
}
} }

View File

@ -52,18 +52,20 @@ import net.sourceforge.plantuml.preproc.ReadLineReader;
import net.sourceforge.plantuml.preproc.UncommentReadLine; import net.sourceforge.plantuml.preproc.UncommentReadLine;
import net.sourceforge.plantuml.utils.StartUtils; import net.sourceforge.plantuml.utils.StartUtils;
final public class BlockUmlBuilder { public final class BlockUmlBuilder implements DefinitionsContainer {
private final List<BlockUml> blocks = new ArrayList<BlockUml>(); private final List<BlockUml> blocks = new ArrayList<BlockUml>();
private Set<FileWithSuffix> usedFiles = new HashSet<FileWithSuffix>(); private Set<FileWithSuffix> usedFiles = new HashSet<FileWithSuffix>();
private final UncommentReadLine reader2; private final UncommentReadLine reader2;
private final Defines defines;
public BlockUmlBuilder(List<String> config, String charset, Defines defines, Reader reader, File newCurrentDir, public BlockUmlBuilder(List<String> config, String charset, Defines defines, Reader reader, File newCurrentDir,
String desc) throws IOException { String desc) throws IOException {
Preprocessor includer = null; Preprocessor includer = null;
this.defines = defines;
try { try {
reader2 = new UncommentReadLine(new ReadLineReader(reader, desc)); reader2 = new UncommentReadLine(new ReadLineReader(reader, desc));
includer = new Preprocessor(reader2, charset, defines, newCurrentDir); includer = new Preprocessor(reader2, charset, defines, newCurrentDir, this);
init(includer, config); init(includer, config);
} finally { } finally {
if (includer != null) { if (includer != null) {
@ -107,7 +109,7 @@ final public class BlockUmlBuilder {
} }
if (StartUtils.isArobaseEndDiagram(s) && current2 != null) { if (StartUtils.isArobaseEndDiagram(s) && current2 != null) {
current2.addAll(1, convert(config, s.getLocation())); current2.addAll(1, convert(config, s.getLocation()));
blocks.add(new BlockUml(current2, startLine)); blocks.add(new BlockUml(current2, startLine, defines.cloneMe()));
current2 = null; current2 = null;
reader2.setPaused(false); reader2.setPaused(false);
} }
@ -130,10 +132,14 @@ final public class BlockUmlBuilder {
return Collections.unmodifiableSet(usedFiles); return Collections.unmodifiableSet(usedFiles);
} }
/* public List<? extends CharSequence> getDefinition(String name) {
* private List<String> getStrings(Reader reader) throws IOException { final List<String> result = new for (BlockUml block : blocks) {
* ArrayList<String>(); Preprocessor includer = null; try { includer = new Preprocessor(reader, defines); String s = if (block.isStartDef(name)) {
* null; while ((s = includer.readLine()) != null) { result.add(s); } } finally { if (includer != null) { this.defines.importFrom(block.getLocalDefines());
* includer.close(); } } return Collections.unmodifiableList(result); } return block.getDefinition();
*/ }
}
return Collections.emptyList();
}
} }

View File

@ -0,0 +1,44 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2017, Arnaud Roques
*
* Project Info: http://plantuml.com
*
* If you like this project or if you find it useful, you can support us at:
*
* http://plantuml.com/patreon (only 1$ per month!)
* http://plantuml.com/paypal
*
* This file is part of PlantUML.
*
* PlantUML is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PlantUML distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
* License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
*
* Original Author: Arnaud Roques
*
*
*/
package net.sourceforge.plantuml;
import java.util.List;
public interface DefinitionsContainer {
public List<? extends CharSequence> getDefinition(String name);
}

View File

@ -78,8 +78,8 @@ public class DirWatcher {
final FileWatcher watcher = modifieds.get(f); final FileWatcher watcher = modifieds.get(f);
if (watcher == null || watcher.hasChanged()) { if (watcher == null || watcher.hasChanged()) {
final SourceFileReader sourceFileReader = new SourceFileReader(new Defines(), f, option.getOutputDir(), final SourceFileReader sourceFileReader = new SourceFileReader(Defines.createWithFileName(f), f,
option.getConfig(), option.getCharset(), option.getFileFormatOption()); option.getOutputDir(), option.getConfig(), option.getCharset(), option.getFileFormatOption());
final Set<File> files = FileWithSuffix.convert(sourceFileReader.getIncludedFiles()); final Set<File> files = FileWithSuffix.convert(sourceFileReader.getIncludedFiles());
files.add(f); files.add(f);
for (GeneratedImage g : sourceFileReader.getGeneratedImages()) { for (GeneratedImage g : sourceFileReader.getGeneratedImages()) {
@ -106,8 +106,8 @@ public class DirWatcher {
final FileWatcher watcher = modifieds.get(f); final FileWatcher watcher = modifieds.get(f);
if (watcher == null || watcher.hasChanged()) { if (watcher == null || watcher.hasChanged()) {
final SourceFileReader sourceFileReader = new SourceFileReader(new Defines(), f, option.getOutputDir(), final SourceFileReader sourceFileReader = new SourceFileReader(Defines.createWithFileName(f), f,
option.getConfig(), option.getCharset(), option.getFileFormatOption()); option.getOutputDir(), option.getConfig(), option.getCharset(), option.getFileFormatOption());
if (sourceFileReader.hasError()) { if (sourceFileReader.hasError()) {
return f; return f;
} }

View File

@ -82,7 +82,7 @@ public class DirWatcher2 {
final FileWatcher watcher = modifieds.get(f); final FileWatcher watcher = modifieds.get(f);
if (watcher == null || watcher.hasChanged()) { if (watcher == null || watcher.hasChanged()) {
final SourceFileReader sourceFileReader = new SourceFileReader(option.getDefaultDefines(), f, final SourceFileReader sourceFileReader = new SourceFileReader(option.getDefaultDefines(f), f,
option.getOutputDir(), option.getConfig(), option.getCharset(), option.getOutputDir(), option.getConfig(), option.getCharset(),
option.getFileFormatOption()); option.getFileFormatOption());
modifieds.put(f, new FileWatcher(Collections.singleton(f))); modifieds.put(f, new FileWatcher(Collections.singleton(f)));

View File

@ -37,6 +37,7 @@ package net.sourceforge.plantuml;
import java.awt.geom.AffineTransform; import java.awt.geom.AffineTransform;
import java.io.Serializable; import java.io.Serializable;
import java.util.Random;
import net.sourceforge.plantuml.graphic.StringBounder; import net.sourceforge.plantuml.graphic.StringBounder;
@ -55,9 +56,10 @@ public class FileFormatOption implements Serializable {
private final boolean useRedForError; private final boolean useRedForError;
private final String svgLinkTarget; private final String svgLinkTarget;
private final String hoverColor; private final String hoverColor;
private final Random rnd;
public FileFormatOption(FileFormat fileFormat) { public FileFormatOption(FileFormat fileFormat) {
this(fileFormat, null, true, false, "_top", false, null); this(fileFormat, null, true, false, "_top", false, null, new Random());
} }
public StringBounder getDefaultStringBounder() { public StringBounder getDefaultStringBounder() {
@ -72,12 +74,16 @@ public class FileFormatOption implements Serializable {
return withMetadata; return withMetadata;
} }
public final Random getRandom() {
return rnd;
}
public FileFormatOption(FileFormat fileFormat, boolean withMetadata) { public FileFormatOption(FileFormat fileFormat, boolean withMetadata) {
this(fileFormat, null, false, false, "_top", false, null); this(fileFormat, null, false, false, "_top", false, null, new Random());
} }
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 hoverColor) { String svgLinkTarget, boolean debugsvek, String hoverColor, Random rnd) {
this.hoverColor = hoverColor; this.hoverColor = hoverColor;
this.fileFormat = fileFormat; this.fileFormat = fileFormat;
this.affineTransform = at; this.affineTransform = at;
@ -85,18 +91,27 @@ public class FileFormatOption implements Serializable {
this.useRedForError = useRedForError; this.useRedForError = useRedForError;
this.svgLinkTarget = svgLinkTarget; this.svgLinkTarget = svgLinkTarget;
this.debugsvek = debugsvek; this.debugsvek = debugsvek;
this.rnd = rnd;
} }
public FileFormatOption withUseRedForError() { public FileFormatOption withUseRedForError() {
return new FileFormatOption(fileFormat, affineTransform, withMetadata, true, svgLinkTarget, debugsvek, hoverColor); return new FileFormatOption(fileFormat, affineTransform, withMetadata, true, svgLinkTarget, debugsvek,
hoverColor, rnd);
} }
public FileFormatOption withSvgLinkTarget(String svgLinkTarget) { public FileFormatOption withSvgLinkTarget(String svgLinkTarget) {
return new FileFormatOption(fileFormat, affineTransform, withMetadata, useRedForError, svgLinkTarget, debugsvek, hoverColor); return new FileFormatOption(fileFormat, affineTransform, withMetadata, useRedForError, svgLinkTarget,
debugsvek, hoverColor, rnd);
} }
public FileFormatOption withHoverColor(String hoverColor) { public FileFormatOption withHoverColor(String hoverColor) {
return new FileFormatOption(fileFormat, affineTransform, withMetadata, useRedForError, svgLinkTarget, debugsvek, hoverColor); return new FileFormatOption(fileFormat, affineTransform, withMetadata, useRedForError, svgLinkTarget,
debugsvek, hoverColor, rnd);
}
public FileFormatOption withFixedRandom() {
return new FileFormatOption(fileFormat, affineTransform, withMetadata, useRedForError, svgLinkTarget,
debugsvek, hoverColor, new Random(42));
} }
@Override @Override

View File

@ -46,6 +46,7 @@ import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import net.sourceforge.plantuml.api.ApiWarning;
import net.sourceforge.plantuml.command.regex.Matcher2; import net.sourceforge.plantuml.command.regex.Matcher2;
import net.sourceforge.plantuml.command.regex.MyPattern; import net.sourceforge.plantuml.command.regex.MyPattern;
import net.sourceforge.plantuml.command.regex.Pattern2; import net.sourceforge.plantuml.command.regex.Pattern2;
@ -64,6 +65,7 @@ public class Option {
private boolean pipe = false; private boolean pipe = false;
private String pipeDelimitor; private String pipeDelimitor;
private boolean pipeMap = false; private boolean pipeMap = false;
private boolean pipeNoStdErr = false;
private boolean syntax = false; private boolean syntax = false;
private boolean checkOnly = false; private boolean checkOnly = false;
private boolean failfast = false; private boolean failfast = false;
@ -84,14 +86,16 @@ public class Option {
public Option() { public Option() {
} }
private FileFormat fileFormat = FileFormat.PNG; private FileFormatOption fileFormatOption = new FileFormatOption(FileFormat.PNG);
public FileFormat getFileFormat() { @Deprecated
return fileFormat; @ApiWarning(willBeRemoved = "in next major release")
final public void setFileFormat(FileFormat fileFormat) {
setFileFormatOption(new FileFormatOption(fileFormat));
} }
public void setFileFormat(FileFormat fileFormat) { final public void setFileFormatOption(FileFormatOption newFormat) {
this.fileFormat = fileFormat; this.fileFormatOption = newFormat;
} }
public Option(String... arg) throws InterruptedException, IOException { public Option(String... arg) throws InterruptedException, IOException {
@ -101,39 +105,41 @@ public class Option {
for (int i = 0; i < arg.length; i++) { for (int i = 0; i < arg.length; i++) {
String s = arg[i]; String s = arg[i];
if (s.equalsIgnoreCase("-tsvg") || s.equalsIgnoreCase("-svg")) { if (s.equalsIgnoreCase("-tsvg") || s.equalsIgnoreCase("-svg")) {
setFileFormat(FileFormat.SVG); setFileFormatOption(new FileFormatOption(FileFormat.SVG));
} else if (s.equalsIgnoreCase("-tsvg:nornd") || s.equalsIgnoreCase("-svg:nornd")) {
setFileFormatOption(new FileFormatOption(FileFormat.SVG).withFixedRandom());
} else if (s.equalsIgnoreCase("-thtml") || s.equalsIgnoreCase("-html")) { } else if (s.equalsIgnoreCase("-thtml") || s.equalsIgnoreCase("-html")) {
setFileFormat(FileFormat.HTML); setFileFormatOption(new FileFormatOption(FileFormat.HTML));
} else if (s.equalsIgnoreCase("-tscxml") || s.equalsIgnoreCase("-scxml")) { } else if (s.equalsIgnoreCase("-tscxml") || s.equalsIgnoreCase("-scxml")) {
setFileFormat(FileFormat.SCXML); setFileFormatOption(new FileFormatOption(FileFormat.SCXML));
} else if (s.equalsIgnoreCase("-txmi") || s.equalsIgnoreCase("-xmi")) { } else if (s.equalsIgnoreCase("-txmi") || s.equalsIgnoreCase("-xmi")) {
setFileFormat(FileFormat.XMI_STANDARD); setFileFormatOption(new FileFormatOption(FileFormat.XMI_STANDARD));
} else if (s.equalsIgnoreCase("-txmi:argo") || s.equalsIgnoreCase("-xmi:argo")) { } else if (s.equalsIgnoreCase("-txmi:argo") || s.equalsIgnoreCase("-xmi:argo")) {
setFileFormat(FileFormat.XMI_ARGO); setFileFormatOption(new FileFormatOption(FileFormat.XMI_ARGO));
} else if (s.equalsIgnoreCase("-txmi:star") || s.equalsIgnoreCase("-xmi:star")) { } else if (s.equalsIgnoreCase("-txmi:star") || s.equalsIgnoreCase("-xmi:star")) {
setFileFormat(FileFormat.XMI_STAR); setFileFormatOption(new FileFormatOption(FileFormat.XMI_STAR));
} else if (s.equalsIgnoreCase("-teps") || s.equalsIgnoreCase("-eps")) { } else if (s.equalsIgnoreCase("-teps") || s.equalsIgnoreCase("-eps")) {
setFileFormat(FileFormat.EPS); setFileFormatOption(new FileFormatOption(FileFormat.EPS));
} else if (s.equalsIgnoreCase("-teps:text") || s.equalsIgnoreCase("-eps:text")) { } else if (s.equalsIgnoreCase("-teps:text") || s.equalsIgnoreCase("-eps:text")) {
setFileFormat(FileFormat.EPS_TEXT); setFileFormatOption(new FileFormatOption(FileFormat.EPS_TEXT));
} else if (s.equalsIgnoreCase("-ttxt") || s.equalsIgnoreCase("-txt")) { } else if (s.equalsIgnoreCase("-ttxt") || s.equalsIgnoreCase("-txt")) {
setFileFormat(FileFormat.ATXT); setFileFormatOption(new FileFormatOption(FileFormat.ATXT));
} else if (s.equalsIgnoreCase("-tutxt") || s.equalsIgnoreCase("-utxt")) { } else if (s.equalsIgnoreCase("-tutxt") || s.equalsIgnoreCase("-utxt")) {
setFileFormat(FileFormat.UTXT); setFileFormatOption(new FileFormatOption(FileFormat.UTXT));
} else if (s.equalsIgnoreCase("-braille") || s.equalsIgnoreCase("-tbraille")) { } else if (s.equalsIgnoreCase("-braille") || s.equalsIgnoreCase("-tbraille")) {
setFileFormat(FileFormat.BRAILLE_PNG); setFileFormatOption(new FileFormatOption(FileFormat.BRAILLE_PNG));
} else if (s.equalsIgnoreCase("-png") || s.equalsIgnoreCase("-tpng")) { } else if (s.equalsIgnoreCase("-png") || s.equalsIgnoreCase("-tpng")) {
setFileFormat(FileFormat.PNG); setFileFormatOption(new FileFormatOption(FileFormat.PNG));
} else if (s.equalsIgnoreCase("-vdx") || s.equalsIgnoreCase("-tvdx")) { } else if (s.equalsIgnoreCase("-vdx") || s.equalsIgnoreCase("-tvdx")) {
setFileFormat(FileFormat.VDX); setFileFormatOption(new FileFormatOption(FileFormat.VDX));
} else if (s.equalsIgnoreCase("-latex") || s.equalsIgnoreCase("-tlatex")) { } else if (s.equalsIgnoreCase("-latex") || s.equalsIgnoreCase("-tlatex")) {
setFileFormat(FileFormat.LATEX); setFileFormatOption(new FileFormatOption(FileFormat.LATEX));
} else if (s.equalsIgnoreCase("-latex:nopreamble") || s.equalsIgnoreCase("-tlatex:nopreamble")) { } else if (s.equalsIgnoreCase("-latex:nopreamble") || s.equalsIgnoreCase("-tlatex:nopreamble")) {
setFileFormat(FileFormat.LATEX_NO_PREAMBLE); setFileFormatOption(new FileFormatOption(FileFormat.LATEX_NO_PREAMBLE));
} else if (s.equalsIgnoreCase("-base64") || s.equalsIgnoreCase("-tbase64")) { } else if (s.equalsIgnoreCase("-base64") || s.equalsIgnoreCase("-tbase64")) {
setFileFormat(FileFormat.BASE64); setFileFormatOption(new FileFormatOption(FileFormat.BASE64));
} else if (s.equalsIgnoreCase("-pdf") || s.equalsIgnoreCase("-tpdf")) { } else if (s.equalsIgnoreCase("-pdf") || s.equalsIgnoreCase("-tpdf")) {
setFileFormat(FileFormat.PDF); setFileFormatOption(new FileFormatOption(FileFormat.PDF));
} else if (s.equalsIgnoreCase("-overwrite")) { } else if (s.equalsIgnoreCase("-overwrite")) {
OptionFlags.getInstance().setOverwrite(true); OptionFlags.getInstance().setOverwrite(true);
} else if (s.equalsIgnoreCase("-output") || s.equalsIgnoreCase("-o")) { } else if (s.equalsIgnoreCase("-output") || s.equalsIgnoreCase("-o")) {
@ -182,6 +188,15 @@ public class Option {
} else if (nb.matches("\\d+")) { } else if (nb.matches("\\d+")) {
this.nbThreads = Integer.parseInt(nb); this.nbThreads = Integer.parseInt(nb);
} }
} else if (s.equalsIgnoreCase("-timeout")) {
i++;
if (i == arg.length) {
continue;
}
final String timeSeconds = arg[i];
if (timeSeconds.matches("\\d+")) {
OptionFlags.getInstance().setTimeoutMs(Integer.parseInt(timeSeconds) * 1000L);
}
} else if (s.equalsIgnoreCase("-failfast")) { } else if (s.equalsIgnoreCase("-failfast")) {
this.failfast = true; this.failfast = true;
} else if (s.equalsIgnoreCase("-failfast2")) { } else if (s.equalsIgnoreCase("-failfast2")) {
@ -213,6 +228,8 @@ public class Option {
pipeDelimitor = arg[i]; pipeDelimitor = arg[i];
} else if (s.equalsIgnoreCase("-pipemap")) { } else if (s.equalsIgnoreCase("-pipemap")) {
pipeMap = true; pipeMap = true;
} else if (s.equalsIgnoreCase("-pipenostderr")) {
pipeNoStdErr = true;
} else if (s.equalsIgnoreCase("-pattern")) { } else if (s.equalsIgnoreCase("-pattern")) {
pattern = true; pattern = true;
} else if (s.equalsIgnoreCase("-syntax")) { } else if (s.equalsIgnoreCase("-syntax")) {
@ -377,8 +394,8 @@ public class Option {
return Collections.unmodifiableList(excludes); return Collections.unmodifiableList(excludes);
} }
public Defines getDefaultDefines() { public Defines getDefaultDefines(File f) {
final Defines result = new Defines(); final Defines result = Defines.createWithFileName(f);
for (Map.Entry<String, String> ent : defines.entrySet()) { for (Map.Entry<String, String> ent : defines.entrySet()) {
result.define(ent.getKey(), Arrays.asList(ent.getValue())); result.define(ent.getKey(), Arrays.asList(ent.getValue()));
@ -432,7 +449,7 @@ public class Option {
} }
public FileFormatOption getFileFormatOption() { public FileFormatOption getFileFormatOption() {
final FileFormatOption fileFormatOption = new FileFormatOption(getFileFormat()); // final FileFormatOption fileFormatOption = new FileFormatOption(getFileFormat());
if (debugsvek) { if (debugsvek) {
fileFormatOption.setDebugSvek(true); fileFormatOption.setDebugSvek(true);
} }
@ -507,4 +524,8 @@ public class Option {
return pipeDelimitor; return pipeDelimitor;
} }
public final boolean isPipeNoStdErr() {
return pipeNoStdErr;
}
} }

View File

@ -120,6 +120,7 @@ public class OptionFlags {
private boolean overwrite; private boolean overwrite;
private boolean enableStats = defaultForStats(); private boolean enableStats = defaultForStats();
private String fileSeparator = "_"; private String fileSeparator = "_";
private long timeoutMs = 15 * 60 * 1000L; // 15 minutes
private File logData; private File logData;
private OptionFlags() { private OptionFlags() {
@ -321,4 +322,11 @@ public class OptionFlags {
this.enableStats = enableStats; this.enableStats = enableStats;
} }
public final long getTimeoutMs() {
return timeoutMs;
}
public final void setTimeoutMs(long timeoutMs) {
this.timeoutMs = timeoutMs;
}
} }

View File

@ -126,6 +126,8 @@ public class OptionPrint {
System.out.println(" -duration\t\tTo print the duration of complete diagrams processing"); System.out.println(" -duration\t\tTo print the duration of complete diagrams processing");
System.out.println(" -nbthread N\t\tTo use (N) threads for processing"); System.out.println(" -nbthread N\t\tTo use (N) threads for processing");
System.out.println(" -nbthread auto\tTo use " + Option.defaultNbThreads() + " threads for processing"); System.out.println(" -nbthread auto\tTo use " + Option.defaultNbThreads() + " threads for processing");
System.out
.println(" -timeout N\t\tProcessing timeout in (N) seconds. Defaults to 15 minutes (900 seconds).");
System.out.println(" -author[s]\t\tTo print information about PlantUML authors"); System.out.println(" -author[s]\t\tTo print information about PlantUML authors");
System.out.println(" -overwrite\t\tTo allow to overwrite read only files"); System.out.println(" -overwrite\t\tTo allow to overwrite read only files");
System.out.println(" -printfonts\t\tTo print fonts available on your system"); System.out.println(" -printfonts\t\tTo print fonts available on your system");

View File

@ -52,6 +52,7 @@ import net.sourceforge.plantuml.core.UmlSource;
import net.sourceforge.plantuml.creole.PSystemCreoleFactory; import net.sourceforge.plantuml.creole.PSystemCreoleFactory;
import net.sourceforge.plantuml.cute.PSystemCuteFactory; import net.sourceforge.plantuml.cute.PSystemCuteFactory;
import net.sourceforge.plantuml.dedication.PSystemDedicationFactory; import net.sourceforge.plantuml.dedication.PSystemDedicationFactory;
import net.sourceforge.plantuml.definition.PSystemDefinitionFactory;
import net.sourceforge.plantuml.descdiagram.DescriptionDiagramFactory; import net.sourceforge.plantuml.descdiagram.DescriptionDiagramFactory;
import net.sourceforge.plantuml.directdot.PSystemDotFactory; import net.sourceforge.plantuml.directdot.PSystemDotFactory;
import net.sourceforge.plantuml.ditaa.PSystemDitaaFactory; import net.sourceforge.plantuml.ditaa.PSystemDitaaFactory;
@ -171,6 +172,7 @@ public class PSystemBuilder {
factories.add(new PSystemLogoFactory()); factories.add(new PSystemLogoFactory());
factories.add(new PSystemSudokuFactory()); factories.add(new PSystemSudokuFactory());
} }
factories.add(new PSystemDefinitionFactory());
factories.add(new PSystemMathFactory(DiagramType.MATH)); factories.add(new PSystemMathFactory(DiagramType.MATH));
factories.add(new PSystemLatexFactory(DiagramType.LATEX)); factories.add(new PSystemLatexFactory(DiagramType.LATEX));
// factories.add(new PSystemStatsFactory()); // factories.add(new PSystemStatsFactory());

View File

@ -57,6 +57,7 @@ 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.HtmlColor;
import net.sourceforge.plantuml.graphic.HtmlColorSimple; import net.sourceforge.plantuml.graphic.HtmlColorSimple;
import net.sourceforge.plantuml.graphic.InnerStrategy;
import net.sourceforge.plantuml.graphic.StringBounder; import net.sourceforge.plantuml.graphic.StringBounder;
import net.sourceforge.plantuml.graphic.TextBlock; import net.sourceforge.plantuml.graphic.TextBlock;
import net.sourceforge.plantuml.graphic.TextBlockUtils; import net.sourceforge.plantuml.graphic.TextBlockUtils;
@ -175,7 +176,7 @@ public class PSystemError extends AbstractPSystem {
ug.apply(new UTranslate(1, 1)).draw(message); ug.apply(new UTranslate(1, 1)).draw(message);
} }
public Rectangle2D getInnerPosition(String member, StringBounder stringBounder) { public Rectangle2D getInnerPosition(String member, StringBounder stringBounder, InnerStrategy strategy) {
return null; return null;
} }

View File

@ -38,6 +38,7 @@ package net.sourceforge.plantuml;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream; import java.io.PrintStream;
import net.sourceforge.plantuml.core.Diagram; import net.sourceforge.plantuml.core.Diagram;
@ -61,6 +62,7 @@ public class Pipe {
public boolean managePipe() throws IOException { public boolean managePipe() throws IOException {
boolean error = false; boolean error = false;
final boolean noStdErr = option.isPipeNoStdErr();
do { do {
final String source = readOneDiagram(); final String source = readOneDiagram();
@ -68,7 +70,7 @@ public class Pipe {
ps.flush(); ps.flush();
return error; return error;
} }
final SourceStringReader sourceStringReader = new SourceStringReader(new Defines(), source, final SourceStringReader sourceStringReader = new SourceStringReader(Defines.createEmpty(), source,
option.getConfig()); option.getConfig());
if (option.isSyntax()) { if (option.isSyntax()) {
@ -78,12 +80,7 @@ public class Pipe {
ps.println(system.getDescription()); ps.println(system.getDescription());
} else if (system instanceof PSystemError) { } else if (system instanceof PSystemError) {
error = true; error = true;
ps.println("ERROR"); printErrorText(ps, (PSystemError) system);
final PSystemError sys = (PSystemError) system;
ps.println(sys.getHigherErrorPosition());
for (ErrorUml er : sys.getErrorsUml()) {
ps.println(er.getError());
}
} else { } else {
ps.println("OTHER"); ps.println("OTHER");
ps.println(system.getDescription()); ps.println(system.getDescription());
@ -92,19 +89,18 @@ public class Pipe {
final String result = sourceStringReader.getCMapData(0, option.getFileFormatOption()); final String result = sourceStringReader.getCMapData(0, option.getFileFormatOption());
ps.println(result); ps.println(result);
} else { } else {
final DiagramDescription result = sourceStringReader.generateImage(ps, 0, option.getFileFormatOption()); final OutputStream os = noStdErr ? new ByteArrayOutputStream() : ps;
if (option.getPipeDelimitor() != null) { final DiagramDescription result = sourceStringReader.generateImage(os, 0, option.getFileFormatOption());
ps.println(option.getPipeDelimitor());
}
if (result != null && "(error)".equalsIgnoreCase(result.getDescription())) { if (result != null && "(error)".equalsIgnoreCase(result.getDescription())) {
error = true; error = true;
System.err.println("ERROR"); manageErrors(noStdErr ? ps : System.err, sourceStringReader);
final Diagram system = sourceStringReader.getBlocks().get(0).getDiagram(); } else if (noStdErr) {
final PSystemError sys = (PSystemError) system; final ByteArrayOutputStream baos = (ByteArrayOutputStream) os;
System.err.println(sys.getHigherErrorPosition()); baos.close();
for (ErrorUml er : sys.getErrorsUml()) { ps.write(baos.toByteArray());
System.err.println(er.getError()); }
} if (option.getPipeDelimitor() != null) {
ps.println(option.getPipeDelimitor());
} }
} }
ps.flush(); ps.flush();
@ -112,6 +108,22 @@ public class Pipe {
return error; return error;
} }
private void manageErrors(final PrintStream output, final SourceStringReader sourceStringReader) {
// if (option.getPipeDelimitor() != null) {
// output.println(option.getPipeDelimitor());
// }
printErrorText(output, (PSystemError) sourceStringReader.getBlocks().get(0).getDiagram());
}
private void printErrorText(final PrintStream output, final PSystemError sys) {
output.println("ERROR");
output.println(sys.getHigherErrorPosition());
for (ErrorUml er : sys.getErrorsUml()) {
output.println(er.getError());
}
output.flush();
}
private boolean isFinished(String s) { private boolean isFinished(String s) {
return s == null || s.startsWith("@end"); return s == null || s.startsWith("@end");
} }
@ -150,7 +162,7 @@ public class Pipe {
} }
break; break;
} }
if (read != '\r') { if (read != '\r' && read != '\n') {
baos.write(read); baos.write(read);
} }
if (read == '\n') { if (read == '\n') {

View File

@ -74,6 +74,7 @@ public class Run {
public static void main(String[] argsArray) throws IOException, InterruptedException { public static void main(String[] argsArray) throws IOException, InterruptedException {
final long start = System.currentTimeMillis(); final long start = System.currentTimeMillis();
saveCommandLine(argsArray);
final Option option = new Option(argsArray); final Option option = new Option(argsArray);
ProgressBar.setEnable(option.isTextProgressBar()); ProgressBar.setEnable(option.isTextProgressBar());
if (OptionFlags.getInstance().isDumpStats()) { if (OptionFlags.getInstance().isDumpStats()) {
@ -173,6 +174,21 @@ public class Run {
} }
} }
private static String commandLine = "";
public static final String getCommandLine() {
return commandLine;
}
private static void saveCommandLine(String[] argsArray) {
final StringBuilder sb = new StringBuilder();
for (String s : argsArray) {
sb.append(s);
sb.append(" ");
}
commandLine = sb.toString();
}
public static void forceOpenJdkResourceLoad() { public static void forceOpenJdkResourceLoad() {
final BufferedImage imDummy = new BufferedImage(10, 10, BufferedImage.TYPE_INT_RGB); final BufferedImage imDummy = new BufferedImage(10, 10, BufferedImage.TYPE_INT_RGB);
final Graphics2D gg = imDummy.createGraphics(); final Graphics2D gg = imDummy.createGraphics();
@ -228,7 +244,7 @@ public class Run {
private static void goFtp(Option option) throws IOException { private static void goFtp(Option option) throws IOException {
final int ftpPort = option.getFtpPort(); final int ftpPort = option.getFtpPort();
System.err.println("ftpPort=" + ftpPort); System.err.println("ftpPort=" + ftpPort);
final FtpServer ftpServer = new FtpServer(ftpPort, option.getFileFormat()); final FtpServer ftpServer = new FtpServer(ftpPort, option.getFileFormatOption().getFileFormat());
ftpServer.go(); ftpServer.go();
} }
@ -379,10 +395,10 @@ public class Run {
} }
final ISourceFileReader sourceFileReader; final ISourceFileReader sourceFileReader;
if (option.getOutputFile() == null) { if (option.getOutputFile() == null) {
sourceFileReader = new SourceFileReader(option.getDefaultDefines(), f, option.getOutputDir(), sourceFileReader = new SourceFileReader(option.getDefaultDefines(f), f, option.getOutputDir(),
option.getConfig(), option.getCharset(), option.getFileFormatOption()); option.getConfig(), option.getCharset(), option.getFileFormatOption());
} else { } else {
sourceFileReader = new SourceFileReader2(option.getDefaultDefines(), f, option.getOutputFile(), sourceFileReader = new SourceFileReader2(option.getDefaultDefines(f), f, option.getOutputFile(),
option.getConfig(), option.getCharset(), option.getFileFormatOption()); option.getConfig(), option.getCharset(), option.getFileFormatOption());
} }
if (option.isComputeurl()) { if (option.isComputeurl()) {
@ -414,4 +430,5 @@ public class Run {
return result; return result;
} }
} }

View File

@ -189,7 +189,8 @@ public class SkinParam implements ISkinParam {
if (value == null) { if (value == null) {
return null; return null;
} }
final boolean acceptTransparent = param == ColorParam.background; final boolean acceptTransparent = param == ColorParam.background
|| param == ColorParam.sequenceGroupBodyBackground;
return getIHtmlColorSet().getColorIfValid(value, acceptTransparent); return getIHtmlColorSet().getColorIfValid(value, acceptTransparent);
} }

View File

@ -70,18 +70,19 @@ public class SourceFileReader implements ISourceFileReader {
} }
public SourceFileReader(File file, File outputDirectory, String charset) throws IOException { public SourceFileReader(File file, File outputDirectory, String charset) throws IOException {
this(new Defines(), file, outputDirectory, Collections.<String> emptyList(), charset, new FileFormatOption( this(Defines.createWithFileName(file), file, outputDirectory, Collections.<String> emptyList(), charset,
FileFormat.PNG)); new FileFormatOption(FileFormat.PNG));
} }
public SourceFileReader(final File file, File outputDirectory) throws IOException { public SourceFileReader(final File file, File outputDirectory) throws IOException {
this(new Defines(), file, outputDirectory, Collections.<String> emptyList(), null, new FileFormatOption( this(Defines.createWithFileName(file), file, outputDirectory, Collections.<String> emptyList(), null,
FileFormat.PNG)); new FileFormatOption(FileFormat.PNG));
} }
public SourceFileReader(final File file, File outputDirectory, FileFormatOption fileFormatOption) public SourceFileReader(final File file, File outputDirectory, FileFormatOption fileFormatOption)
throws IOException { throws IOException {
this(new Defines(), file, outputDirectory, Collections.<String> emptyList(), null, fileFormatOption); this(Defines.createWithFileName(file), file, outputDirectory, Collections.<String> emptyList(), null,
fileFormatOption);
} }
public SourceFileReader(Defines defines, final File file, File outputDirectory, List<String> config, public SourceFileReader(Defines defines, final File file, File outputDirectory, List<String> config,
@ -210,6 +211,9 @@ public class SourceFileReader implements ISourceFileReader {
} }
final List<FileImageData> exportDiagrams = PSystemUtils.exportDiagrams(system, suggested, fileFormatOption); final List<FileImageData> exportDiagrams = PSystemUtils.exportDiagrams(system, suggested, fileFormatOption);
if (exportDiagrams.size() > 1) {
cpt += exportDiagrams.size() - 1;
}
OptionFlags.getInstance().logData(file, system); OptionFlags.getInstance().logData(file, system);
for (FileImageData fdata : exportDiagrams) { for (FileImageData fdata : exportDiagrams) {

View File

@ -59,11 +59,11 @@ public class SourceStringReader {
final private List<BlockUml> blocks; final private List<BlockUml> blocks;
public SourceStringReader(String source) { public SourceStringReader(String source) {
this(new Defines(), source, Collections.<String> emptyList()); this(Defines.createEmpty(), source, Collections.<String> emptyList());
} }
public SourceStringReader(String source, String charset) { public SourceStringReader(String source, String charset) {
this(new Defines(), source, "UTF-8", Collections.<String> emptyList()); this(Defines.createEmpty(), source, "UTF-8", Collections.<String> emptyList());
} }
public SourceStringReader(Defines defines, String source, List<String> config) { public SourceStringReader(Defines defines, String source, List<String> config) {
@ -71,7 +71,7 @@ public class SourceStringReader {
} }
public SourceStringReader(String source, File newCurrentDir) { public SourceStringReader(String source, File newCurrentDir) {
this(new Defines(), source, "UTF-8", Collections.<String> emptyList(), newCurrentDir); this(Defines.createEmpty(), source, "UTF-8", Collections.<String> emptyList(), newCurrentDir);
} }
public SourceStringReader(Defines defines, String source, String charset, List<String> config) { public SourceStringReader(Defines defines, String source, String charset, List<String> config) {

View File

@ -276,6 +276,9 @@ public class StringUtils {
} }
public static String eventuallyRemoveStartingAndEndingDoubleQuote(String s) { public static String eventuallyRemoveStartingAndEndingDoubleQuote(String s) {
if (s == null) {
return s;
}
return eventuallyRemoveStartingAndEndingDoubleQuote(s, "\"([:"); return eventuallyRemoveStartingAndEndingDoubleQuote(s, "\"([:");
} }

View File

@ -0,0 +1,81 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2017, Arnaud Roques
*
* Project Info: http://plantuml.com
*
* If you like this project or if you find it useful, you can support us at:
*
* http://plantuml.com/patreon (only 1$ per month!)
* http://plantuml.com/paypal
*
* This file is part of PlantUML.
*
* PlantUML is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PlantUML distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
* License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
*
* Original Author: Arnaud Roques
*
*
*/
package net.sourceforge.plantuml;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class SvgString {
private final String svg;
private final double scale;
public SvgString(String svg, double scale) {
this.svg = svg;
this.scale = scale;
}
public String getSvg() {
String result = svg;
if (result.startsWith("<?xml")) {
final int idx = result.indexOf("<svg");
result = result.substring(idx);
}
if (result.startsWith("<svg")) {
final int idx = result.indexOf(">");
result = "<svg>" + result.substring(idx + 1);
}
if (result.startsWith("<svg>") == false) {
throw new IllegalArgumentException();
}
return result;
}
public int getData(String name) {
final Pattern p = Pattern.compile("(?i)" + name + "\\W+(\\d+)");
final Matcher m = p.matcher(svg);
if (m.find()) {
final String s = m.group(1);
return Integer.parseInt(s);
}
throw new IllegalStateException("Cannot find " + name);
}
public double getScale() {
return scale;
}
}

View File

@ -69,7 +69,7 @@ public class ActivityDiagram extends CucaDiagram {
final IEntity result; final IEntity result;
if (leafExist(code)) { if (leafExist(code)) {
result = getOrCreateLeafDefault(code, type, null); result = getOrCreateLeafDefault(code, type, null);
if (result.getEntityType() != type) { if (result.getLeafType() != type) {
// throw new IllegalArgumentException("Already known: " + code + " " + result.getType() + " " + type); // throw new IllegalArgumentException("Already known: " + code + " " + result.getType() + " " + type);
return null; return null;
} }
@ -100,11 +100,11 @@ public class ActivityDiagram extends CucaDiagram {
} }
private void updateLasts(final IEntity result) { private void updateLasts(final IEntity result) {
if (result.getEntityType() == LeafType.NOTE) { if (result.getLeafType() == LeafType.NOTE) {
return; return;
} }
this.lastEntityConsulted = result; this.lastEntityConsulted = result;
if (result.getEntityType() == LeafType.BRANCH) { if (result.getLeafType() == LeafType.BRANCH) {
lastEntityBrancheConsulted = result; lastEntityBrancheConsulted = result;
} }
} }

View File

@ -46,7 +46,7 @@ public class ConditionalContext {
private final ConditionalContext parent; private final ConditionalContext parent;
public ConditionalContext(ConditionalContext parent, IEntity branch, Direction direction) { public ConditionalContext(ConditionalContext parent, IEntity branch, Direction direction) {
if (branch.getEntityType() != LeafType.BRANCH) { if (branch.getLeafType() != LeafType.BRANCH) {
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }
this.branch = branch; this.branch = branch;

View File

@ -250,7 +250,7 @@ public class CommandLinkActivity extends SingleLineCommand2<ActivityDiagram> {
static LeafType getTypeIfExisting(ActivityDiagram system, Code code) { static LeafType getTypeIfExisting(ActivityDiagram system, Code code) {
if (system.leafExist(code)) { if (system.leafExist(code)) {
final IEntity ent = system.getLeafsget(code); final IEntity ent = system.getLeafsget(code);
if (ent.getEntityType() == LeafType.BRANCH) { if (ent.getLeafType() == LeafType.BRANCH) {
return LeafType.BRANCH; return LeafType.BRANCH;
} }
} }

View File

@ -315,10 +315,10 @@ public class ActivityDiagram3 extends UmlDiagram {
return CommandExecutionResult.error("Cannot find if"); return CommandExecutionResult.error("Cannot find if");
} }
public void startRepeat(HtmlColor color) { public void startRepeat(HtmlColor color, Display label) {
manageSwimlaneStrategy(); manageSwimlaneStrategy();
final InstructionRepeat instructionRepeat = new InstructionRepeat(swinlanes.getCurrentSwimlane(), current(), final InstructionRepeat instructionRepeat = new InstructionRepeat(swinlanes.getCurrentSwimlane(), current(),
nextLinkRenderer(), color); nextLinkRenderer(), color, label);
current().add(instructionRepeat); current().add(instructionRepeat);
setCurrent(instructionRepeat); setCurrent(instructionRepeat);
setNextLinkRendererInternal(LinkRendering.none()); setNextLinkRendererInternal(LinkRendering.none());
@ -340,6 +340,20 @@ public class ActivityDiagram3 extends UmlDiagram {
} }
public CommandExecutionResult backwardWhile(Display label) {
manageSwimlaneStrategy();
if (current() instanceof InstructionRepeat) {
final InstructionRepeat instructionRepeat = (InstructionRepeat) current();
// final LinkRendering back = new LinkRendering(linkColor).withDisplay(linkLabel);
instructionRepeat.setBackward(label);
// setCurrent(instructionRepeat.getParent());
// this.setNextLinkRendererInternal(LinkRendering.none());
return CommandExecutionResult.ok();
}
return CommandExecutionResult.error("Cannot find repeat");
}
public void doWhile(Display test, Display yes, HtmlColor color) { public void doWhile(Display test, Display yes, HtmlColor color) {
manageSwimlaneStrategy(); manageSwimlaneStrategy();
final InstructionWhile instructionWhile = new InstructionWhile(swinlanes.getCurrentSwimlane(), current(), test, final InstructionWhile instructionWhile = new InstructionWhile(swinlanes.getCurrentSwimlane(), current(), test,

View File

@ -43,6 +43,7 @@ import net.sourceforge.plantuml.activitydiagram3.command.CommandActivityLegacy1;
import net.sourceforge.plantuml.activitydiagram3.command.CommandActivityLong3; import net.sourceforge.plantuml.activitydiagram3.command.CommandActivityLong3;
import net.sourceforge.plantuml.activitydiagram3.command.CommandArrow3; import net.sourceforge.plantuml.activitydiagram3.command.CommandArrow3;
import net.sourceforge.plantuml.activitydiagram3.command.CommandArrowLong3; import net.sourceforge.plantuml.activitydiagram3.command.CommandArrowLong3;
import net.sourceforge.plantuml.activitydiagram3.command.CommandBackward3;
import net.sourceforge.plantuml.activitydiagram3.command.CommandBreak; import net.sourceforge.plantuml.activitydiagram3.command.CommandBreak;
import net.sourceforge.plantuml.activitydiagram3.command.CommandElse3; import net.sourceforge.plantuml.activitydiagram3.command.CommandElse3;
import net.sourceforge.plantuml.activitydiagram3.command.CommandElseIf2; import net.sourceforge.plantuml.activitydiagram3.command.CommandElseIf2;
@ -112,6 +113,7 @@ public class ActivityDiagramFactory3 extends UmlDiagramFactory {
cmds.add(new CommandRepeat3()); cmds.add(new CommandRepeat3());
cmds.add(new CommandRepeatWhile3()); cmds.add(new CommandRepeatWhile3());
cmds.add(new CommandRepeatWhile3Multilines()); cmds.add(new CommandRepeatWhile3Multilines());
cmds.add(new CommandBackward3());
cmds.add(new CommandWhile3()); cmds.add(new CommandWhile3());
cmds.add(new CommandWhileEnd3()); cmds.add(new CommandWhileEnd3());
cmds.add(new CommandFork3()); cmds.add(new CommandFork3());

View File

@ -37,6 +37,7 @@ package net.sourceforge.plantuml.activitydiagram3;
import java.util.Set; import java.util.Set;
import net.sourceforge.plantuml.activitydiagram3.ftile.BoxStyle;
import net.sourceforge.plantuml.activitydiagram3.ftile.Ftile; import net.sourceforge.plantuml.activitydiagram3.ftile.Ftile;
import net.sourceforge.plantuml.activitydiagram3.ftile.FtileFactory; import net.sourceforge.plantuml.activitydiagram3.ftile.FtileFactory;
import net.sourceforge.plantuml.activitydiagram3.ftile.FtileKilled; import net.sourceforge.plantuml.activitydiagram3.ftile.FtileKilled;
@ -56,14 +57,18 @@ public class InstructionRepeat implements Instruction {
private final HtmlColor color; private final HtmlColor color;
private boolean killed = false; private boolean killed = false;
private Display backward = Display.NULL;
private Display test = Display.NULL; private Display test = Display.NULL;
private Display yes = Display.NULL; private Display yes = Display.NULL;
private Display out = Display.NULL; private Display out = Display.NULL;
private final Display startLabel;
private boolean testCalled = false; private boolean testCalled = false;
private LinkRendering endRepeatLinkRendering = LinkRendering.none(); private LinkRendering endRepeatLinkRendering = LinkRendering.none();
private LinkRendering backRepeatLinkRendering = LinkRendering.none(); private LinkRendering backRepeatLinkRendering = LinkRendering.none();
public InstructionRepeat(Swimlane swimlane, Instruction parent, LinkRendering nextLinkRenderer, HtmlColor color) { public InstructionRepeat(Swimlane swimlane, Instruction parent, LinkRendering nextLinkRenderer, HtmlColor color,
Display startLabel) {
this.startLabel = startLabel;
this.parent = parent; this.parent = parent;
this.swimlane = swimlane; this.swimlane = swimlane;
this.nextLinkRenderer = nextLinkRenderer; this.nextLinkRenderer = nextLinkRenderer;
@ -73,14 +78,20 @@ public class InstructionRepeat implements Instruction {
this.color = color; this.color = color;
} }
public void setBackward(Display label) {
this.backward = label;
}
public void add(Instruction ins) { public void add(Instruction ins) {
repeatList.add(ins); repeatList.add(ins);
} }
public Ftile createFtile(FtileFactory factory) { public Ftile createFtile(FtileFactory factory) {
final Ftile back = Display.isNull(backward) ? null : factory.activity(backward, swimlane, BoxStyle.PLAIN,
Colors.empty());
final Ftile result = factory.repeat(swimlane, repeatList.getSwimlaneOut(), final Ftile result = factory.repeat(swimlane, repeatList.getSwimlaneOut(),
factory.decorateOut(repeatList.createFtile(factory), endRepeatLinkRendering), test, yes, out, color, startLabel, factory.decorateOut(repeatList.createFtile(factory), endRepeatLinkRendering), test, yes, out,
backRepeatLinkRendering); color, backRepeatLinkRendering, back);
if (killed) { if (killed) {
return new FtileKilled(result); return new FtileKilled(result);
} }

View File

@ -0,0 +1,67 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2017, Arnaud Roques
*
* Project Info: http://plantuml.com
*
* If you like this project or if you find it useful, you can support us at:
*
* http://plantuml.com/patreon (only 1$ per month!)
* http://plantuml.com/paypal
*
* This file is part of PlantUML.
*
* PlantUML is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PlantUML distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
* License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
*
* Original Author: Arnaud Roques
*
*
*/
package net.sourceforge.plantuml.activitydiagram3.command;
import net.sourceforge.plantuml.activitydiagram3.ActivityDiagram3;
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;
import net.sourceforge.plantuml.cucadiagram.Display;
public class CommandBackward3 extends SingleLineCommand2<ActivityDiagram3> {
public CommandBackward3() {
super(getRegexConcat());
}
static RegexConcat getRegexConcat() {
return new RegexConcat(new RegexLeaf("^"), //
new RegexLeaf("backward"), //
new RegexLeaf("[%s]*"), //
new RegexLeaf(":"), //
new RegexLeaf("LABEL", "(.*)"), //
new RegexLeaf(";$"));
}
@Override
protected CommandExecutionResult executeArg(ActivityDiagram3 diagram, RegexResult arg) {
final Display label = Display.getWithNewlines(arg.get("LABEL", 0));
return diagram.backwardWhile(label);
}
}

View File

@ -41,6 +41,7 @@ import net.sourceforge.plantuml.command.SingleLineCommand2;
import net.sourceforge.plantuml.command.regex.RegexConcat; 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;
import net.sourceforge.plantuml.cucadiagram.Display;
import net.sourceforge.plantuml.graphic.HtmlColor; import net.sourceforge.plantuml.graphic.HtmlColor;
import net.sourceforge.plantuml.graphic.color.ColorParser; import net.sourceforge.plantuml.graphic.color.ColorParser;
@ -54,14 +55,17 @@ public class CommandRepeat3 extends SingleLineCommand2<ActivityDiagram3> {
return new RegexConcat(new RegexLeaf("^"), // return new RegexConcat(new RegexLeaf("^"), //
ColorParser.exp4(), // ColorParser.exp4(), //
new RegexLeaf("repeat"), // new RegexLeaf("repeat"), //
new RegexLeaf("[%s]*"), //
new RegexLeaf("LABEL", "(?::(.*?))?"), //
new RegexLeaf(";?$")); new RegexLeaf(";?$"));
} }
@Override @Override
protected CommandExecutionResult executeArg(ActivityDiagram3 diagram, RegexResult arg) { protected CommandExecutionResult executeArg(ActivityDiagram3 diagram, RegexResult arg) {
final HtmlColor color = diagram.getSkinParam().getIHtmlColorSet().getColorIfValid(arg.get("COLOR", 0)); final HtmlColor color = diagram.getSkinParam().getIHtmlColorSet().getColorIfValid(arg.get("COLOR", 0));
final Display label = Display.getWithNewlines(arg.get("LABEL", 0));
diagram.startRepeat(color); diagram.startRepeat(color, label);
return CommandExecutionResult.ok(); return CommandExecutionResult.ok();
} }

View File

@ -74,8 +74,8 @@ public interface FtileFactory {
public Ftile assembly(Ftile tile1, Ftile tile2); public Ftile assembly(Ftile tile1, Ftile tile2);
public Ftile repeat(Swimlane swimlane, Swimlane swimlaneOut, Ftile repeat, Display test, Display yes, Display out, public Ftile repeat(Swimlane swimlane, Swimlane swimlaneOut, Display startLabel, Ftile repeat, Display test, Display yes,
HtmlColor color, LinkRendering backRepeatLinkRendering); Display out, HtmlColor color, LinkRendering backRepeatLinkRendering, Ftile backward);
public Ftile createWhile(Swimlane swimlane, Ftile whileBlock, Display test, Display yes, Display out, public Ftile createWhile(Swimlane swimlane, Ftile whileBlock, Display test, Display yes, Display out,
LinkRendering afterEndwhile, HtmlColor color, Instruction specialOut); LinkRendering afterEndwhile, HtmlColor color, Instruction specialOut);

View File

@ -141,9 +141,10 @@ public class FtileFactoryDelegator implements FtileFactory {
return factory.assembly(tile1, tile2); return factory.assembly(tile1, tile2);
} }
public Ftile repeat(Swimlane swimlane, Swimlane swimlaneOut, Ftile repeat, Display test, Display yes, Display out, public Ftile repeat(Swimlane swimlane, Swimlane swimlaneOut, Display startLabel, Ftile repeat, Display test, Display yes,
HtmlColor color, LinkRendering backRepeatLinkRendering) { Display out, HtmlColor color, LinkRendering backRepeatLinkRendering, Ftile backward) {
return factory.repeat(swimlane, swimlaneOut, repeat, test, yes, out, color, backRepeatLinkRendering); return factory.repeat(swimlane, swimlaneOut, startLabel, repeat, test, yes, out, color, backRepeatLinkRendering,
backward);
} }
public Ftile createWhile(Swimlane swimlane, Ftile whileBlock, Display test, Display yes, Display out, public Ftile createWhile(Swimlane swimlane, Ftile whileBlock, Display test, Display yes, Display out,

View File

@ -42,6 +42,7 @@ import net.sourceforge.plantuml.ColorParam;
import net.sourceforge.plantuml.FontParam; import net.sourceforge.plantuml.FontParam;
import net.sourceforge.plantuml.activitydiagram3.LinkRendering; import net.sourceforge.plantuml.activitydiagram3.LinkRendering;
import net.sourceforge.plantuml.activitydiagram3.ftile.Arrows; import net.sourceforge.plantuml.activitydiagram3.ftile.Arrows;
import net.sourceforge.plantuml.activitydiagram3.ftile.BoxStyle;
import net.sourceforge.plantuml.activitydiagram3.ftile.Connection; import net.sourceforge.plantuml.activitydiagram3.ftile.Connection;
import net.sourceforge.plantuml.activitydiagram3.ftile.Ftile; import net.sourceforge.plantuml.activitydiagram3.ftile.Ftile;
import net.sourceforge.plantuml.activitydiagram3.ftile.FtileBreak; import net.sourceforge.plantuml.activitydiagram3.ftile.FtileBreak;
@ -58,6 +59,7 @@ import net.sourceforge.plantuml.graphic.FontConfiguration;
import net.sourceforge.plantuml.graphic.HtmlColor; import net.sourceforge.plantuml.graphic.HtmlColor;
import net.sourceforge.plantuml.graphic.HtmlColorAndStyle; import net.sourceforge.plantuml.graphic.HtmlColorAndStyle;
import net.sourceforge.plantuml.graphic.Rainbow; import net.sourceforge.plantuml.graphic.Rainbow;
import net.sourceforge.plantuml.graphic.color.Colors;
import net.sourceforge.plantuml.svek.ConditionStyle; import net.sourceforge.plantuml.svek.ConditionStyle;
import net.sourceforge.plantuml.ugraphic.UGraphic; import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.UTranslate; import net.sourceforge.plantuml.ugraphic.UTranslate;
@ -69,8 +71,8 @@ public class FtileFactoryDelegatorRepeat extends FtileFactoryDelegator {
} }
@Override @Override
public Ftile repeat(Swimlane swimlane, Swimlane swimlaneOut, final Ftile repeat, Display test, Display yes, public Ftile repeat(Swimlane swimlane, Swimlane swimlaneOut, Display startLabel, final Ftile repeat, Display test,
Display out, HtmlColor color, LinkRendering backRepeatLinkRendering) { Display yes, Display out, HtmlColor color, LinkRendering backRepeatLinkRendering, Ftile backward) {
final ConditionStyle conditionStyle = skinParam().getConditionStyle(); final ConditionStyle conditionStyle = skinParam().getConditionStyle();
@ -85,9 +87,12 @@ public class FtileFactoryDelegatorRepeat extends FtileFactoryDelegator {
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.ARROW, null); final FontConfiguration fcArrow = new FontConfiguration(skinParam(), FontParam.ARROW, null);
Ftile result = FtileRepeat.create(backRepeatLinkRendering, swimlane, swimlaneOut, repeat, test, yes, out, final Ftile backStart = Display.isNull(startLabel) ? null : this.activity(startLabel, swimlane, BoxStyle.PLAIN,
borderColor, backColor, arrowColor, endRepeatLinkColor, conditionStyle, this.skinParam(), fcDiamond, Colors.empty());
fcArrow);
Ftile result = FtileRepeat.create(backRepeatLinkRendering, swimlane, swimlaneOut, backStart, repeat, test, yes,
out, borderColor, backColor, arrowColor, endRepeatLinkColor, conditionStyle, this.skinParam(),
fcDiamond, fcArrow, backward);
final List<WeldingPoint> weldingPoints = repeat.getWeldingPoints(); final List<WeldingPoint> weldingPoints = repeat.getWeldingPoints();
if (weldingPoints.size() > 0) { if (weldingPoints.size() > 0) {

View File

@ -79,6 +79,7 @@ class FtileRepeat extends AbstractFtile {
private final Ftile repeat; private final Ftile repeat;
private final Ftile diamond1; private final Ftile diamond1;
private final Ftile diamond2; private final Ftile diamond2;
private final Ftile backward;
private final TextBlock tbTest; private final TextBlock tbTest;
@Override @Override
@ -86,12 +87,13 @@ class FtileRepeat extends AbstractFtile {
return Arrays.asList(repeat, diamond1, diamond2); return Arrays.asList(repeat, diamond1, diamond2);
} }
private FtileRepeat(Ftile repeat, Ftile diamond1, Ftile diamond2, TextBlock tbTest) { private FtileRepeat(Ftile repeat, Ftile diamond1, Ftile diamond2, TextBlock tbTest, Ftile backward) {
super(repeat.skinParam()); super(repeat.skinParam());
this.repeat = repeat; this.repeat = repeat;
this.diamond1 = diamond1; this.diamond1 = diamond1;
this.diamond2 = diamond2; this.diamond2 = diamond2;
this.tbTest = tbTest; this.tbTest = tbTest;
this.backward = backward;
} }
public Swimlane getSwimlaneIn() { public Swimlane getSwimlaneIn() {
@ -100,7 +102,6 @@ class FtileRepeat extends AbstractFtile {
public Swimlane getSwimlaneOut() { public Swimlane getSwimlaneOut() {
return diamond2.getSwimlaneOut(); return diamond2.getSwimlaneOut();
// return getSwimlaneIn();
} }
public Set<Swimlane> getSwimlanes() { public Set<Swimlane> getSwimlanes() {
@ -108,9 +109,9 @@ class FtileRepeat extends AbstractFtile {
} }
public static Ftile create(LinkRendering backRepeatLinkRendering, Swimlane swimlane, Swimlane swimlaneOut, public static Ftile create(LinkRendering backRepeatLinkRendering, Swimlane swimlane, Swimlane swimlaneOut,
Ftile repeat, Display test, Display yes, Display out, HtmlColor borderColor, HtmlColor backColor, Ftile backStart, Ftile repeat, Display test, Display yes, Display out, HtmlColor borderColor,
Rainbow arrowColor, Rainbow endRepeatLinkColor, ConditionStyle conditionStyle, ISkinSimple spriteContainer, HtmlColor backColor, Rainbow arrowColor, Rainbow endRepeatLinkColor, ConditionStyle conditionStyle,
FontConfiguration fcDiamond, FontConfiguration fcArrow) { ISkinSimple spriteContainer, FontConfiguration fcDiamond, FontConfiguration fcArrow, Ftile backward) {
final FontConfiguration fontConfiguration1 = conditionStyle == ConditionStyle.INSIDE ? fcDiamond : fcArrow; final FontConfiguration fontConfiguration1 = conditionStyle == ConditionStyle.INSIDE ? fcDiamond : fcArrow;
@ -120,19 +121,24 @@ class FtileRepeat extends AbstractFtile {
final TextBlock yesTb = yes.create(fcArrow, HorizontalAlignment.LEFT, spriteContainer); final TextBlock yesTb = yes.create(fcArrow, HorizontalAlignment.LEFT, spriteContainer);
final TextBlock outTb = out.create(fcArrow, HorizontalAlignment.LEFT, spriteContainer); final TextBlock outTb = out.create(fcArrow, HorizontalAlignment.LEFT, spriteContainer);
final Ftile diamond1 = new FtileDiamond(repeat.skinParam(), backColor, borderColor, swimlane); final Ftile diamond1;
if (backStart == null) {
diamond1 = new FtileDiamond(repeat.skinParam(), backColor, borderColor, swimlane);
} else {
diamond1 = backStart;
}
final FtileRepeat result; final FtileRepeat result;
if (conditionStyle == ConditionStyle.INSIDE) { if (conditionStyle == ConditionStyle.INSIDE) {
final Ftile diamond2 = new FtileDiamondInside(repeat.skinParam(), backColor, borderColor, swimlaneOut, final Ftile diamond2 = new FtileDiamondInside(repeat.skinParam(), backColor, borderColor, swimlaneOut,
tbTest).withEast(yesTb).withSouth(outTb); tbTest).withEast(yesTb).withSouth(outTb);
result = new FtileRepeat(repeat, diamond1, diamond2, TextBlockUtils.empty(0, 0)); result = new FtileRepeat(repeat, diamond1, diamond2, TextBlockUtils.empty(0, 0), backward);
} else if (conditionStyle == ConditionStyle.DIAMOND) { } else if (conditionStyle == ConditionStyle.DIAMOND) {
final Ftile diamond2 = new FtileDiamond(repeat.skinParam(), backColor, borderColor, swimlane) final Ftile diamond2 = new FtileDiamond(repeat.skinParam(), backColor, borderColor, swimlane)
.withEast(tbTest); .withEast(tbTest);
result = new FtileRepeat(repeat, diamond1, diamond2, tbTest); result = new FtileRepeat(repeat, diamond1, diamond2, tbTest, backward);
} else if (conditionStyle == ConditionStyle.FOO1) { } else if (conditionStyle == ConditionStyle.FOO1) {
final Ftile diamond2 = new FtileDiamondFoo1(repeat.skinParam(), backColor, borderColor, swimlane, tbTest); final Ftile diamond2 = new FtileDiamondFoo1(repeat.skinParam(), backColor, borderColor, swimlane, tbTest);
result = new FtileRepeat(repeat, diamond1, diamond2, TextBlockUtils.empty(0, 0)); result = new FtileRepeat(repeat, diamond1, diamond2, TextBlockUtils.empty(0, 0), backward);
} else { } else {
throw new IllegalStateException(); throw new IllegalStateException();
} }
@ -147,7 +153,13 @@ class FtileRepeat extends AbstractFtile {
final TextBlock tbbackLink1 = backLink1 == null ? null : backLink1.create(fcArrow, HorizontalAlignment.LEFT, final TextBlock tbbackLink1 = backLink1 == null ? null : backLink1.create(fcArrow, HorizontalAlignment.LEFT,
spriteContainer, CreoleMode.SIMPLE_LINE); spriteContainer, CreoleMode.SIMPLE_LINE);
if (repeat.getSwimlaneIn() == repeat.getSwimlaneOut()) { if (repeat.getSwimlaneIn() == repeat.getSwimlaneOut()) {
conns.add(result.new ConnectionBackSimple(backRepeatLinkRendering.getRainbow(arrowColor), tbbackLink1)); if (backward == null) {
conns.add(result.new ConnectionBackSimple(backRepeatLinkRendering.getRainbow(arrowColor), tbbackLink1));
} else {
conns.add(result.new ConnectionBackBackward1(backRepeatLinkRendering.getRainbow(arrowColor),
tbbackLink1));
conns.add(result.new ConnectionBackBackward2(backRepeatLinkRendering.getRainbow(arrowColor)));
}
} else { } else {
conns.add(result.new ConnectionBackComplex1(backRepeatLinkRendering.getRainbow(arrowColor))); conns.add(result.new ConnectionBackComplex1(backRepeatLinkRendering.getRainbow(arrowColor)));
conns.add(result.new ConnectionBackComplexHorizontalOnly(backRepeatLinkRendering.getRainbow(arrowColor), conns.add(result.new ConnectionBackComplexHorizontalOnly(backRepeatLinkRendering.getRainbow(arrowColor),
@ -335,6 +347,86 @@ class FtileRepeat extends AbstractFtile {
} }
class ConnectionBackBackward1 extends AbstractConnection {
private final Rainbow arrowColor;
private final TextBlock tbback;
public ConnectionBackBackward1(Rainbow arrowColor, TextBlock tbback) {
super(diamond2, backward);
this.arrowColor = arrowColor;
this.tbback = tbback;
}
private Point2D getP1(final StringBounder stringBounder) {
return getTranslateDiamond2(stringBounder).getTranslated(new Point2D.Double(0, 0));
}
private Point2D getP2(final StringBounder stringBounder) {
final FtileGeometry dim = backward.calculateDimension(stringBounder);
return getTranslateBackward(stringBounder).getTranslated(new Point2D.Double(dim.getLeft(), dim.getOutY()));
}
public void drawU(UGraphic ug) {
final StringBounder stringBounder = ug.getStringBounder();
final Snake snake = new Snake(arrowColor, Arrows.asToUp());
snake.setLabel(tbback);
final Point2D p1 = getP1(stringBounder);
final Point2D p2 = getP2(stringBounder);
final Dimension2D dimDiamond2 = diamond2.calculateDimension(stringBounder);
final double x1 = p1.getX() + dimDiamond2.getWidth();
final double y1 = p1.getY() + dimDiamond2.getHeight() / 2;
final double x2 = p2.getX();
final double y2 = p2.getY();
snake.addPoint(x1, y1);
snake.addPoint(x2, y1);
snake.addPoint(x2, y2);
ug.draw(snake);
}
}
class ConnectionBackBackward2 extends AbstractConnection {
private final Rainbow arrowColor;
public ConnectionBackBackward2(Rainbow arrowColor) {
super(backward, diamond1);
this.arrowColor = arrowColor;
}
private Point2D getP1(final StringBounder stringBounder) {
final FtileGeometry dim = backward.calculateDimension(stringBounder);
return getTranslateBackward(stringBounder).getTranslated(new Point2D.Double(dim.getLeft(), dim.getInY()));
}
private Point2D getP2(final StringBounder stringBounder) {
return getTranslateDiamond1(stringBounder).getTranslated(new Point2D.Double(0, 0));
}
public void drawU(UGraphic ug) {
final StringBounder stringBounder = ug.getStringBounder();
final Snake snake = new Snake(arrowColor, Arrows.asToLeft());
snake.emphasizeDirection(Direction.UP);
final Point2D p1 = getP1(stringBounder);
final Point2D p2 = getP2(stringBounder);
final Dimension2D dimDiamond1 = diamond1.calculateDimension(stringBounder);
final double x1 = p1.getX();
final double y1 = p1.getY();
final double x2 = p2.getX() + dimDiamond1.getWidth();
final double y2 = p2.getY() + dimDiamond1.getHeight() / 2;
snake.addPoint(x1, y1);
snake.addPoint(x1, y2);
snake.addPoint(x2, y2);
ug.draw(snake);
}
}
class ConnectionBackSimple extends AbstractConnection { class ConnectionBackSimple extends AbstractConnection {
private final Rainbow arrowColor; private final Rainbow arrowColor;
private final TextBlock tbback; private final TextBlock tbback;
@ -385,6 +477,9 @@ class FtileRepeat extends AbstractFtile {
ug.apply(getTranslateForRepeat(stringBounder)).draw(repeat); ug.apply(getTranslateForRepeat(stringBounder)).draw(repeat);
ug.apply(getTranslateDiamond1(stringBounder)).draw(diamond1); ug.apply(getTranslateDiamond1(stringBounder)).draw(diamond1);
ug.apply(getTranslateDiamond2(stringBounder)).draw(diamond2); ug.apply(getTranslateDiamond2(stringBounder)).draw(diamond2);
if (backward != null) {
ug.apply(getTranslateBackward(stringBounder)).draw(backward);
}
} }
@ -402,6 +497,9 @@ class FtileRepeat extends AbstractFtile {
double width = getLeft(stringBounder) + getRight(stringBounder); double width = getLeft(stringBounder) + getRight(stringBounder);
width = Math.max(width, w + 2 * Diamond.diamondHalfSize); width = Math.max(width, w + 2 * Diamond.diamondHalfSize);
if (backward != null) {
width += backward.calculateDimension(stringBounder).getWidth();
}
final double height = dimDiamond1.getHeight() + dimRepeat.getHeight() + dimDiamond2.getHeight() + 8 final double height = dimDiamond1.getHeight() + dimRepeat.getHeight() + dimDiamond2.getHeight() + 8
* Diamond.diamondHalfSize; * Diamond.diamondHalfSize;
return new Dimension2DDouble(width + 2 * Diamond.diamondHalfSize, height); return new Dimension2DDouble(width + 2 * Diamond.diamondHalfSize, height);
@ -439,6 +537,15 @@ class FtileRepeat extends AbstractFtile {
return new UTranslate(left - dimDiamond1.getWidth() / 2, 0); return new UTranslate(left - dimDiamond1.getWidth() / 2, 0);
} }
private UTranslate getTranslateBackward(StringBounder stringBounder) {
final Dimension2D dimTotal = calculateDimensionInternal(stringBounder);
final Dimension2D dimBackward = backward.calculateDimension(stringBounder);
final double x = dimTotal.getWidth() - dimBackward.getWidth();
final double y = (dimTotal.getHeight() - dimBackward.getHeight()) / 2;
return new UTranslate(x, y);
}
private UTranslate getTranslateDiamond2(StringBounder stringBounder) { private UTranslate getTranslateDiamond2(StringBounder stringBounder) {
final Dimension2D dimTotal = calculateDimensionInternal(stringBounder); final Dimension2D dimTotal = calculateDimensionInternal(stringBounder);
final Dimension2D dimDiamond2 = diamond2.calculateDimension(stringBounder); final Dimension2D dimDiamond2 = diamond2.calculateDimension(stringBounder);

View File

@ -116,8 +116,8 @@ public class VCompactFactory implements FtileFactory {
return new FtileAssemblySimple(tile1, tile2); return new FtileAssemblySimple(tile1, tile2);
} }
public Ftile repeat(Swimlane swimlane, Swimlane swimlaneOut, Ftile repeat, Display test, Display yes, Display out, public Ftile repeat(Swimlane swimlane, Swimlane swimlaneOut, Display startLabel, Ftile repeat, Display test, Display yes,
HtmlColor color, LinkRendering backRepeatLinkRendering) { Display out, HtmlColor color, LinkRendering backRepeatLinkRendering, Ftile backward) {
return repeat; return repeat;
} }

View File

@ -47,6 +47,7 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import net.sourceforge.plantuml.FileFormat; import net.sourceforge.plantuml.FileFormat;
import net.sourceforge.plantuml.FileFormatOption;
import net.sourceforge.plantuml.GeneratedImage; import net.sourceforge.plantuml.GeneratedImage;
import net.sourceforge.plantuml.Option; import net.sourceforge.plantuml.Option;
import net.sourceforge.plantuml.OptionFlags; import net.sourceforge.plantuml.OptionFlags;
@ -190,8 +191,8 @@ public class PlantUmlTask extends Task {
if (OptionFlags.getInstance().isVerbose()) { if (OptionFlags.getInstance().isVerbose()) {
this.log("Processing " + f.getAbsolutePath()); this.log("Processing " + f.getAbsolutePath());
} }
final SourceFileReader sourceFileReader = new SourceFileReader(new Defines(), f, option.getOutputDir(), final SourceFileReader sourceFileReader = new SourceFileReader(Defines.createWithFileName(f), f,
option.getConfig(), option.getCharset(), option.getFileFormatOption()); option.getOutputDir(), option.getConfig(), option.getCharset(), option.getFileFormatOption());
if (option.isCheckOnly()) { if (option.isCheckOnly()) {
return sourceFileReader.hasError(); return sourceFileReader.hasError();
@ -300,43 +301,43 @@ public class PlantUmlTask extends Task {
public void setFormat(String s) { public void setFormat(String s) {
if ("scxml".equalsIgnoreCase(s)) { if ("scxml".equalsIgnoreCase(s)) {
option.setFileFormat(FileFormat.SCXML); option.setFileFormatOption(new FileFormatOption(FileFormat.SCXML));
} }
if ("xmi".equalsIgnoreCase(s)) { if ("xmi".equalsIgnoreCase(s)) {
option.setFileFormat(FileFormat.XMI_STANDARD); option.setFileFormatOption(new FileFormatOption(FileFormat.XMI_STANDARD));
} }
if ("xmi:argo".equalsIgnoreCase(s)) { if ("xmi:argo".equalsIgnoreCase(s)) {
option.setFileFormat(FileFormat.XMI_ARGO); option.setFileFormatOption(new FileFormatOption(FileFormat.XMI_ARGO));
} }
if ("xmi:start".equalsIgnoreCase(s)) { if ("xmi:start".equalsIgnoreCase(s)) {
option.setFileFormat(FileFormat.XMI_STAR); option.setFileFormatOption(new FileFormatOption(FileFormat.XMI_STAR));
} }
if ("eps".equalsIgnoreCase(s)) { if ("eps".equalsIgnoreCase(s)) {
option.setFileFormat(FileFormat.EPS); option.setFileFormatOption(new FileFormatOption(FileFormat.EPS));
} }
if ("braille".equalsIgnoreCase(s)) { if ("braille".equalsIgnoreCase(s)) {
option.setFileFormat(FileFormat.BRAILLE_PNG); option.setFileFormatOption(new FileFormatOption(FileFormat.BRAILLE_PNG));
} }
if ("pdf".equalsIgnoreCase(s)) { if ("pdf".equalsIgnoreCase(s)) {
option.setFileFormat(FileFormat.PDF); option.setFileFormatOption(new FileFormatOption(FileFormat.PDF));
} }
if ("latex".equalsIgnoreCase(s)) { if ("latex".equalsIgnoreCase(s)) {
option.setFileFormat(FileFormat.LATEX); option.setFileFormatOption(new FileFormatOption(FileFormat.LATEX));
} }
if ("latex:nopreamble".equalsIgnoreCase(s)) { if ("latex:nopreamble".equalsIgnoreCase(s)) {
option.setFileFormat(FileFormat.LATEX_NO_PREAMBLE); option.setFileFormatOption(new FileFormatOption(FileFormat.LATEX_NO_PREAMBLE));
} }
if ("eps:text".equalsIgnoreCase(s)) { if ("eps:text".equalsIgnoreCase(s)) {
option.setFileFormat(FileFormat.EPS_TEXT); option.setFileFormatOption(new FileFormatOption(FileFormat.EPS_TEXT));
} }
if ("svg".equalsIgnoreCase(s)) { if ("svg".equalsIgnoreCase(s)) {
option.setFileFormat(FileFormat.SVG); option.setFileFormatOption(new FileFormatOption(FileFormat.SVG));
} }
if ("txt".equalsIgnoreCase(s)) { if ("txt".equalsIgnoreCase(s)) {
option.setFileFormat(FileFormat.ATXT); option.setFileFormatOption(new FileFormatOption(FileFormat.ATXT));
} }
if ("utxt".equalsIgnoreCase(s)) { if ("utxt".equalsIgnoreCase(s)) {
option.setFileFormat(FileFormat.UTXT); option.setFileFormatOption(new FileFormatOption(FileFormat.UTXT));
} }
} }

View File

@ -0,0 +1,13 @@
package net.sourceforge.plantuml.api;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.SOURCE)
@Target({ ElementType.CONSTRUCTOR, ElementType.METHOD })
public @interface ApiWarning {
String willBeRemoved() default "";
}

View File

@ -0,0 +1,75 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2017, Arnaud Roques
*
* Project Info: http://plantuml.com
*
* If you like this project or if you find it useful, you can support us at:
*
* http://plantuml.com/patreon (only 1$ per month!)
* http://plantuml.com/paypal
*
* This file is part of PlantUML.
*
* PlantUML is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PlantUML distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
* License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
*
* Original Author: Arnaud Roques
*
*/
package net.sourceforge.plantuml.bpm;
public class BpmBranch {
private final int uid;
private int counter = 1;
public BpmBranch(int uid) {
this.uid = uid;
}
public int incAndGetCounter() {
counter++;
return counter;
}
private String getEntryId() {
return "$branchA" + uid;
}
private String getExitId() {
return "$branchB" + uid;
}
public BpmElement getEntryElement() {
return new BpmElement(getEntryId(), BpmElementType.MERGE, null);
}
public BpmElement getElseElement() {
return new BpmElement(getExitId(), BpmElementType.MERGE, null);
}
public BpmEvent getResumeEntryEvent() {
return new BpmEventResume(getEntryId());
}
public BpmEvent getGoToEndEvent() {
return new BpmEventGoto(getExitId());
}
}

View File

@ -36,7 +36,9 @@ package net.sourceforge.plantuml.bpm;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.ArrayDeque;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Deque;
import java.util.List; import java.util.List;
import net.sourceforge.plantuml.FileFormatOption; import net.sourceforge.plantuml.FileFormatOption;
@ -52,9 +54,9 @@ import net.sourceforge.plantuml.ugraphic.ImageBuilder;
public class BpmDiagram extends UmlDiagram { public class BpmDiagram extends UmlDiagram {
private final BpmElement start = new BpmElement(null, BpmElementType.START); private final BpmElement start = new BpmElement(null, BpmElementType.START);
private BpmElement last = start;
private List<BpmEvent> events = new ArrayList<BpmEvent>(); private List<BpmEvent> events = new ArrayList<BpmEvent>();
private Deque<BpmBranch> branches = new ArrayDeque<BpmBranch>();
public DiagramDescription getDescription() { public DiagramDescription getDescription() {
return new DiagramDescription("(Bpm Diagram)"); return new DiagramDescription("(Bpm Diagram)");
@ -80,69 +82,112 @@ public class BpmDiagram extends UmlDiagram {
private UDrawable getUDrawable() { private UDrawable getUDrawable() {
final Grid grid = createGrid(); final Grid grid = createGrid();
cleanGrid(grid);
final GridArray gridArray = grid.toArray(SkinParam.create(getUmlDiagramType())); final GridArray gridArray = grid.toArray(SkinParam.create(getUmlDiagramType()));
gridArray.addEdges(edges); // gridArray.addEdges(edges);
System.err.println("gridArray=" + gridArray); System.err.println("gridArray=" + gridArray);
return gridArray; return gridArray;
} }
private void cleanGrid(Grid grid) {
// while (true) {
// final boolean v1 = new CleanerEmptyLine().clean(grid);
// final boolean v2 = new CleanerInterleavingLines().clean(grid);
// if (v1 == false && v2 == false) {
// return;
// }
// }
}
public CommandExecutionResult addEvent(BpmEvent event) { public CommandExecutionResult addEvent(BpmEvent event) {
this.events.add(event); this.events.add(event);
return CommandExecutionResult.ok(); return CommandExecutionResult.ok();
} }
private Coord current; private Coord current;
private final List<BpmEdge> edges = new ArrayList<BpmEdge>(); private Cell last;
private Grid createGrid() { private Grid createGrid() {
final Grid grid = new Grid(); final Grid grid = new Grid();
this.current = grid.getRoot(); this.current = grid.getRoot();
this.edges.clear(); // this.edges.clear();
last = grid.getCell(current);
grid.getCell(current).setData(start); grid.getCell(current).setData(start);
for (BpmEvent event : events) { for (BpmEvent event : events) {
if (event instanceof BpmEventAdd) { if (event instanceof BpmEventAdd) {
addInGrid(grid, ((BpmEventAdd) event).getElement()); final BpmEventAdd tmp = (BpmEventAdd) event;
addInGrid(grid, tmp.getElement());
} else if (event instanceof BpmEventResume) { } else if (event instanceof BpmEventResume) {
final String idDestination = ((BpmEventResume) event).getId(); final String idDestination = ((BpmEventResume) event).getId();
current = grid.getById(idDestination); current = grid.getById(idDestination);
last = (BpmElement) grid.getCell(current).getData(); last = grid.getCell(current);
if (last == null) { if (last == null) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
final Navigator<Line> nav = grid.linesOf(current); final Navigator<Line> nav = grid.linesOf(current);
final Line newLine = new Line(); final Line newLine = new Line();
nav.insertAfter(newLine); nav.insertAfter(newLine);
final Row row = current.getRow(); final Col row = current.getCol();
current = new Coord(row, newLine); current = new Coord(newLine, row);
} else if (event instanceof BpmEventGoto) { } else if (event instanceof BpmEventGoto) {
final String idDestination = ((BpmEventGoto) event).getId(); final BpmEventGoto tmp = (BpmEventGoto) event;
edges.add(new BpmEdge(last, (BpmElement) grid.getCell(grid.getById(idDestination)).getData())); final String idDestination = tmp.getId();
current = grid.getById(idDestination); current = grid.getById(idDestination);
last = (BpmElement) grid.getCell(current).getData(); final Cell src = last;
last = grid.getCell(current);
if (last == null) { if (last == null) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
final Navigator<Line> nav = grid.linesOf(current); final Navigator<Line> nav = grid.linesOf(current);
final Line newLine = new Line(); final Line newLine = new Line();
nav.insertAfter(newLine); nav.insertAfter(newLine);
final Row row = current.getRow(); final Col row = current.getCol();
current = new Coord(row, newLine); current = new Coord(newLine, row);
src.addConnectionTo(last);
} else { } else {
throw new IllegalStateException(); throw new IllegalStateException();
} }
} }
grid.addConnections();
// for (GridEdge edge : edges) {
// System.err.println("EDGE=" + edge.getEdgeDirection());
// edge.addLineIn(grid);
// }
// grid.addEdge(edges);
return grid; return grid;
} }
private void addInGrid(Grid grid, BpmElement element) { private void addInGrid(Grid grid, BpmElement element) {
final Navigator<Row> nav = grid.rowsOf(current); final Navigator<Col> nav = grid.colsOf(current);
final Row newRow = new Row(); final Col newRow = new Col();
nav.insertAfter(newRow); nav.insertAfter(newRow);
current = new Coord(newRow, current.getLine()); current = new Coord(current.getLine(), newRow);
grid.getCell(current).setData(element); grid.getCell(current).setData(element);
edges.add(new BpmEdge(last, element)); last.addConnectionTo(grid.getCell(current));
last = element; last = grid.getCell(current);
} }
public CommandExecutionResult newBranch() {
final BpmBranch branch = new BpmBranch(events.size());
branches.addLast(branch);
return addEvent(new BpmEventAdd(branch.getEntryElement()));
}
public CommandExecutionResult elseBranch() {
final BpmBranch branch = branches.getLast();
final int counter = branch.incAndGetCounter();
if (counter == 2) {
addEvent(new BpmEventAdd(branch.getElseElement()));
return addEvent(branch.getResumeEntryEvent());
}
addEvent(branch.getGoToEndEvent());
return addEvent(branch.getResumeEntryEvent());
}
public CommandExecutionResult endBranch() {
final BpmBranch branch = branches.removeLast();
return addEvent(branch.getGoToEndEvent());
}
} }

View File

@ -56,6 +56,9 @@ public class BpmDiagramFactory extends UmlDiagramFactory {
result.add(new CommandMerge()); result.add(new CommandMerge());
result.add(new CommandResume()); result.add(new CommandResume());
result.add(new CommandGoto()); result.add(new CommandGoto());
result.add(new CommandNewBranch());
result.add(new CommandElseBranch());
result.add(new CommandEndBranch());
return result; return result;
} }

View File

@ -71,6 +71,9 @@ public class BpmElement implements Placeable {
@Override @Override
public String toString() { public String toString() {
if (id == null) {
return type.toString() + "(" + display + ")";
}
return type.toString() + "(" + id + ")"; return type.toString() + "(" + id + ")";
} }
@ -92,10 +95,10 @@ public class BpmElement implements Placeable {
return new FtileDiamond(skinParam, backColor, borderColor, null); return new FtileDiamond(skinParam, backColor, borderColor, null);
} }
if (type == BpmElementType.DOCKED_EVENT) { if (type == BpmElementType.DOCKED_EVENT) {
final UFont font = new UFont("Serif", Font.PLAIN, 14); final UFont font = UFont.serif(14);
return new FtileBox(skinParam, display, font, null, BoxStyle.PLAIN); return new FtileBox(skinParam, display, font, null, BoxStyle.PLAIN);
} }
final UFont font = new UFont("Serif", Font.PLAIN, 14); final UFont font = UFont.serif(14);
final FontConfiguration fc = new FontConfiguration(font, HtmlColorUtils.RED, HtmlColorUtils.RED, false); final FontConfiguration fc = new FontConfiguration(font, HtmlColorUtils.RED, HtmlColorUtils.RED, false);
if (Display.isNull(display)) { if (Display.isNull(display)) {
return Display.getWithNewlines(type.toString()).create(fc, HorizontalAlignment.LEFT, skinParam); return Display.getWithNewlines(type.toString()).create(fc, HorizontalAlignment.LEFT, skinParam);

View File

@ -45,4 +45,5 @@ public class BpmEventAdd implements BpmEvent {
public final BpmElement getElement() { public final BpmElement getElement() {
return element; return element;
} }
} }

View File

@ -35,9 +35,14 @@
*/ */
package net.sourceforge.plantuml.bpm; package net.sourceforge.plantuml.bpm;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Cell { public class Cell {
private Placeable data; private Placeable data;
private final List<Cell> destinations = new ArrayList<Cell>();
public final Placeable getData() { public final Placeable getData() {
return data; return data;
@ -55,4 +60,12 @@ public class Cell {
return super.toString() + " " + data; return super.toString() + " " + data;
} }
public void addConnectionTo(Cell other) {
this.destinations.add(other);
}
public List<Cell> getDestinations() {
return Collections.unmodifiableList(destinations);
}
} }

View File

@ -46,4 +46,6 @@ public interface Chain<O> extends Comparator<O> {
public List<O> toList(); public List<O> toList();
public boolean remove(O data);
} }

View File

@ -46,6 +46,38 @@ public class ChainImpl<O> implements Chain<O> {
private final List<O> negative = new ArrayList<O>(); private final List<O> negative = new ArrayList<O>();
private int currentVersion; private int currentVersion;
public boolean remove(O data) {
updateStructuralVersion();
boolean result = positive.remove(data);
if (result == false) {
result = negative.remove(data);
}
return result;
}
public int compare(O a, O b) {
if (a.equals(b)) {
return 0;
}
for (int i = negative.size() - 1; i >= 0; i--) {
if (a.equals(negative.get(i))) {
return -1;
}
if (b.equals(negative.get(i))) {
return 1;
}
}
for (O cur : positive) {
if (a.equals(cur)) {
return -1;
}
if (b.equals(cur)) {
return 1;
}
}
throw new UnsupportedOperationException();
}
public List<O> toList() { public List<O> toList() {
final List<O> result = new ArrayList<O>(); final List<O> result = new ArrayList<O>();
for (O element : negative) { for (O element : negative) {
@ -207,8 +239,4 @@ public class ChainImpl<O> implements Chain<O> {
} }
} }
public int compare(O a, O b) {
throw new UnsupportedOperationException();
}
} }

View File

@ -31,28 +31,22 @@
* *
* Original Author: Arnaud Roques * Original Author: Arnaud Roques
* *
*
*/ */
package net.sourceforge.plantuml.applet; package net.sourceforge.plantuml.bpm;
import java.applet.Applet; public class CleanerEmptyLine implements GridCleaner {
import java.awt.Graphics;
import net.sourceforge.plantuml.version.Version; public boolean clean(Grid grid) {
boolean result = false;
for (Line line : grid.lines().toList()) {
if (grid.usedColsOf(line).isEmpty()) {
grid.removeLine(line);
result = true;
}
public class VersionApplet extends Applet { }
return result;
@Override
public void init() {
super.init();
} }
@Override
public void start() {
super.start();
}
@Override
public void paint(Graphics g) {
g.drawString(Version.versionString(), 0, 10);
}
} }

View File

@ -0,0 +1,78 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2017, Arnaud Roques
*
* Project Info: http://plantuml.com
*
* If you like this project or if you find it useful, you can support us at:
*
* http://plantuml.com/patreon (only 1$ per month!)
* http://plantuml.com/paypal
*
* This file is part of PlantUML.
*
* PlantUML is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PlantUML distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
* License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
*
* Original Author: Arnaud Roques
*
*
*/
package net.sourceforge.plantuml.bpm;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.SortedSet;
public class CleanerInterleavingLines implements GridCleaner {
public boolean clean(Grid grid) {
boolean result = false;
Line previous = null;
for (Line line : grid.lines().toList()) {
if (previous != null) {
final Collection<Col> cols1 = grid.usedColsOf(previous);
final Collection<Col> cols2 = grid.usedColsOf(line);
if (Collections.disjoint(cols1, cols2)) {
// final SortedSet<Col> used1 = grid.colsConnectedTo(previous);
// final SortedSet<Col> used2 = grid.colsConnectedTo(line);
// if (mergeable(used1, used2)) {
// System.err.println("CAN BE MERGE!");
// grid.mergeLines(previous, line);
// result = true;
// }
}
}
previous = line;
}
return result;
}
private boolean mergeable(SortedSet<Col> used1, SortedSet<Col> used2) {
final Comparator<? super Col> s = used1.comparator();
assert s == used2.comparator();
if (s.compare(used1.last(), used2.first()) <= 0) {
return true;
}
if (s.compare(used2.last(), used1.first()) <= 0) {
return true;
}
return false;
}
}

View File

@ -35,6 +35,6 @@
*/ */
package net.sourceforge.plantuml.bpm; package net.sourceforge.plantuml.bpm;
public class Row { public class Col {
} }

View File

@ -59,7 +59,8 @@ public class CommandDockedEvent extends SingleLineCommand2<BpmDiagram> {
protected CommandExecutionResult executeArg(BpmDiagram diagram, RegexResult arg) { protected CommandExecutionResult executeArg(BpmDiagram diagram, RegexResult arg) {
final String label = arg.get("LABEL", 0); final String label = arg.get("LABEL", 0);
final BpmEvent event = new BpmEventAdd(new BpmElement(null, BpmElementType.DOCKED_EVENT, label)); final BpmElement element = new BpmElement(null, BpmElementType.DOCKED_EVENT, label);
final BpmEvent event = new BpmEventAdd(element);
return diagram.addEvent(event); return diagram.addEvent(event);
} }

View File

@ -0,0 +1,61 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2017, Arnaud Roques
*
* Project Info: http://plantuml.com
*
* If you like this project or if you find it useful, you can support us at:
*
* http://plantuml.com/patreon (only 1$ per month!)
* http://plantuml.com/paypal
*
* This file is part of PlantUML.
*
* PlantUML is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PlantUML distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
* License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
*
* Original Author: Arnaud Roques
*
*
*/
package net.sourceforge.plantuml.bpm;
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 CommandElseBranch extends SingleLineCommand2<BpmDiagram> {
public CommandElseBranch() {
super(getRegexConcat());
}
static RegexConcat getRegexConcat() {
return new RegexConcat(new RegexLeaf("^"), //
new RegexLeaf("else"), //
new RegexLeaf("$"));
}
@Override
protected CommandExecutionResult executeArg(BpmDiagram diagram, RegexResult arg) {
return diagram.elseBranch();
}
}

View File

@ -0,0 +1,61 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2017, Arnaud Roques
*
* Project Info: http://plantuml.com
*
* If you like this project or if you find it useful, you can support us at:
*
* http://plantuml.com/patreon (only 1$ per month!)
* http://plantuml.com/paypal
*
* This file is part of PlantUML.
*
* PlantUML is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PlantUML distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
* License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
*
* Original Author: Arnaud Roques
*
*
*/
package net.sourceforge.plantuml.bpm;
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 CommandEndBranch extends SingleLineCommand2<BpmDiagram> {
public CommandEndBranch() {
super(getRegexConcat());
}
static RegexConcat getRegexConcat() {
return new RegexConcat(new RegexLeaf("^"), //
new RegexLeaf("end branch"), //
new RegexLeaf("$"));
}
@Override
protected CommandExecutionResult executeArg(BpmDiagram diagram, RegexResult arg) {
return diagram.endBranch();
}
}

View File

@ -0,0 +1,61 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2017, Arnaud Roques
*
* Project Info: http://plantuml.com
*
* If you like this project or if you find it useful, you can support us at:
*
* http://plantuml.com/patreon (only 1$ per month!)
* http://plantuml.com/paypal
*
* This file is part of PlantUML.
*
* PlantUML is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PlantUML distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
* License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
*
* Original Author: Arnaud Roques
*
*
*/
package net.sourceforge.plantuml.bpm;
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 CommandNewBranch extends SingleLineCommand2<BpmDiagram> {
public CommandNewBranch() {
super(getRegexConcat());
}
static RegexConcat getRegexConcat() {
return new RegexConcat(new RegexLeaf("^"), //
new RegexLeaf("new branch"), //
new RegexLeaf("$"));
}
@Override
protected CommandExecutionResult executeArg(BpmDiagram diagram, RegexResult arg) {
return diagram.newBranch();
}
}

View File

@ -0,0 +1,160 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2017, Arnaud Roques
*
* Project Info: http://plantuml.com
*
* If you like this project or if you find it useful, you can support us at:
*
* http://plantuml.com/patreon (only 1$ per month!)
* http://plantuml.com/paypal
*
* This file is part of PlantUML.
*
* PlantUML is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PlantUML distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
* License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
*
* Original Author: Arnaud Roques
*
*
*/
package net.sourceforge.plantuml.bpm;
import java.awt.geom.Dimension2D;
import java.awt.geom.Rectangle2D;
import net.sourceforge.plantuml.Dimension2DDouble;
import net.sourceforge.plantuml.ISkinParam;
import net.sourceforge.plantuml.graphic.HtmlColorUtils;
import net.sourceforge.plantuml.graphic.InnerStrategy;
import net.sourceforge.plantuml.graphic.StringBounder;
import net.sourceforge.plantuml.graphic.TextBlock;
import net.sourceforge.plantuml.ugraphic.UChangeColor;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.ULine;
import net.sourceforge.plantuml.ugraphic.UTranslate;
public class ConnectorPuzzle implements Placeable, TextBlock {
public static enum Where {
NORTH(1), EAST(2), SOUTH(4), WEST(8);
private int coding;
private Where(int coding) {
this.coding = coding;
}
String toShortString() {
return name().substring(0, 1);
}
}
private static final ConnectorPuzzle all[] = new ConnectorPuzzle[16];
private final int type;
static {
for (int i = 0; i < all.length; i++) {
all[i] = new ConnectorPuzzle(i);
}
}
public ConnectorPuzzle append(ConnectorPuzzle before) {
return all[this.type | before.type];
}
public static ConnectorPuzzle get(String value) {
int num = 0;
for (Where w : Where.values()) {
if (value.contains(w.toShortString())) {
num += w.coding;
}
}
return all[num];
}
public boolean have(Where where) {
return (type & where.coding) != 0;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
for (Where w : Where.values()) {
if (have(w)) {
sb.append(w.toShortString());
}
}
if (sb.length() == 0) {
sb.append("NONE");
}
return sb.toString();
}
private ConnectorPuzzle(int type) {
this.type = type;
}
public Dimension2D getDimension(StringBounder stringBounder, ISkinParam skinParam) {
return new Dimension2DDouble(20, 20);
}
public TextBlock toTextBlock(ISkinParam skinParam) {
return this;
}
public String getId() {
throw new UnsupportedOperationException();
}
public void drawU(UGraphic ug) {
// System.err.println("DRAWING " + toString());
ug = ug.apply(new UChangeColor(HtmlColorUtils.BLUE));
for (Where w : Where.values()) {
if (have(w)) {
drawLine(ug, w);
}
}
}
private void drawLine(UGraphic ug, Where w) {
if (w == Where.WEST) {
ug.apply(new UTranslate(0, 10)).draw(new ULine(10, 0));
}
if (w == Where.EAST) {
ug.apply(new UTranslate(10, 10)).draw(new ULine(10, 0));
}
if (w == Where.NORTH) {
ug.apply(new UTranslate(10, 0)).draw(new ULine(0, 10));
}
if (w == Where.SOUTH) {
ug.apply(new UTranslate(10, 10)).draw(new ULine(0, 10));
}
}
public Dimension2D calculateDimension(StringBounder stringBounder) {
return new Dimension2DDouble(20, 20);
}
public Rectangle2D getInnerPosition(String member, StringBounder stringBounder, InnerStrategy strategy) {
return null;
}
}

View File

@ -37,19 +37,24 @@ package net.sourceforge.plantuml.bpm;
public class Coord { public class Coord {
private final Row row;
private final Line line; private final Line line;
private final Col col;
public Coord(Row row, Line line) { public Coord(Line line, Col row) {
if (line == null || row == null) { if (line == null || row == null) {
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }
this.line = line; this.line = line;
this.row = row; this.col = row;
} }
public final Row getRow() { public final Col getCol() {
return row; return col;
}
@Override
public String toString() {
return "line=" + line + " col=" + col;
} }
public final Line getLine() { public final Line getLine() {
@ -58,13 +63,13 @@ public class Coord {
@Override @Override
public int hashCode() { public int hashCode() {
return row.hashCode() + line.hashCode(); return line.hashCode() + col.hashCode();
} }
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
final Coord other = (Coord) obj; final Coord other = (Coord) obj;
return this.row == other.row && this.line == other.line; return this.line == other.line && this.col == other.col;
} }
} }

View File

@ -35,38 +35,42 @@
*/ */
package net.sourceforge.plantuml.bpm; package net.sourceforge.plantuml.bpm;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import net.sourceforge.plantuml.ISkinParam; import net.sourceforge.plantuml.ISkinParam;
public class Grid { public class Grid {
private final Chain<Row> rows;
private final Chain<Line> lines; private final Chain<Line> lines;
private final Chain<Col> cols;
private final Coord root; private final Coord root;
private final Map<Coord, Cell> cells = new HashMap<Coord, Cell>(); private final Map<Coord, Cell> cells = new HashMap<Coord, Cell>();
public Grid() { public Grid() {
this.root = new Coord(new Row(), new Line()); this.root = new Coord(new Line(), new Col());
this.rows = new ChainImpl<Row>(root.getRow());
this.lines = new ChainImpl<Line>(root.getLine()); this.lines = new ChainImpl<Line>(root.getLine());
this.cols = new ChainImpl<Col>(root.getCol());
this.cells.put(root, new Cell()); this.cells.put(root, new Cell());
} }
public Cell getCell(Coord coord) { public Cell getCell(Coord coord) {
return getCell(coord.getRow(), coord.getLine()); return getCell(coord.getLine(), coord.getCol());
} }
public Cell getCell(Row row, Line line) { public Cell getCell(Line line, Col col) {
if (rows.contains(row) == false) {
throw new IllegalArgumentException();
}
if (lines.contains(line) == false) { if (lines.contains(line) == false) {
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }
final Coord coord = new Coord(row, line); if (cols.contains(col) == false) {
throw new IllegalArgumentException();
}
final Coord coord = new Coord(line, col);
Cell result = cells.get(coord); Cell result = cells.get(coord);
if (result == null) { if (result == null) {
result = new Cell(); result = new Cell();
@ -75,6 +79,62 @@ public class Grid {
return result; return result;
} }
// private Set<GridEdge> edgeWith(Cell someCell) {
// // final Set<GridEdge> result = new HashSet<GridEdge>();
// // for (GridEdge edge : edges) {
// // if (edge.match(someCell)) {
// // result.add(edge);
// // }
// // }
// // return Collections.unmodifiableSet(result);
// throw new UnsupportedOperationException();
//
// }
//
// private Collection<Cell> getCellsConnectedTo(Cell someCell) {
// final Set<Cell> result = new HashSet<Cell>();
// final Set<GridEdge> myEdges = edgeWith(someCell);
// for (Cell cell : cells.values()) {
// for (GridEdge edge : myEdges) {
// assert edge.match(someCell);
// if (edge.match(cell)) {
// result.add(cell);
// }
// }
// }
// return Collections.unmodifiableSet(result);
// }
//
// private SortedSet<Col> getColsConnectedTo(Cell someCell) {
// final SortedSet<Col> result = new TreeSet<Col>(cols);
// final Set<GridEdge> myEdges = edgeWith(someCell);
// for (Map.Entry<Coord, Cell> ent : cells.entrySet()) {
// for (GridEdge edge : myEdges) {
// assert edge.match(someCell);
// if (edge.match(ent.getValue())) {
// result.add(ent.getKey().getCol());
// }
// }
// }
// return Collections.unmodifiableSortedSet(result);
// }
// public SortedSet<Col> colsConnectedTo(Line line) {
// final SortedSet<Col> result = new TreeSet<Col>(cols);
// for (Map.Entry<Coord, Cell> ent : cells.entrySet()) {
// final Cell cell = ent.getValue();
// if (cell == null || cell.getData() == null) {
// continue;
// }
// if (ent.getKey().getLine() != line) {
// continue;
// }
// result.addAll(getColsConnectedTo(ent.getValue()));
//
// }
// return Collections.unmodifiableSortedSet(result);
// }
public Coord getById(String id) { public Coord getById(String id) {
for (Map.Entry<Coord, Cell> ent : cells.entrySet()) { for (Map.Entry<Coord, Cell> ent : cells.entrySet()) {
final Cell cell = ent.getValue(); final Cell cell = ent.getValue();
@ -92,15 +152,15 @@ public class Grid {
return root; return root;
} }
public final Chain<Row> rows() {
return rows;
}
public final Chain<Line> lines() { public final Chain<Line> lines() {
return lines; return lines;
} }
private final Coord getCoord(Cell cell) { public final Chain<Col> cols() {
return cols;
}
public final Coord getCoord(Cell cell) {
for (Map.Entry<Coord, Cell> ent : cells.entrySet()) { for (Map.Entry<Coord, Cell> ent : cells.entrySet()) {
if (ent.getValue() == cell) { if (ent.getValue() == cell) {
return ent.getKey(); return ent.getKey();
@ -109,35 +169,173 @@ public class Grid {
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }
public final Navigator<Row> rowsOf(Coord coord) {
return rows.navigator(coord.getRow());
}
public final Navigator<Line> linesOf(Coord coord) { public final Navigator<Line> linesOf(Coord coord) {
return lines.navigator(coord.getLine()); return lines.navigator(coord.getLine());
} }
public final Navigator<Row> rowsOf(Cell cell) { public final Navigator<Col> colsOf(Coord coord) {
return rowsOf(getCoord(cell)); return cols.navigator(coord.getCol());
} }
public final Navigator<Line> linesOf(Cell cell) { public final Navigator<Line> linesOf(Cell cell) {
return linesOf(getCoord(cell)); return linesOf(getCoord(cell));
} }
public final Navigator<Col> colsOf(Cell cell) {
return colsOf(getCoord(cell));
}
public final GridArray toArray(ISkinParam skinParam) { public final GridArray toArray(ISkinParam skinParam) {
final List<Row> rows = this.rows.toList();
final List<Line> lines = this.lines.toList(); final List<Line> lines = this.lines.toList();
final GridArray result = new GridArray(skinParam, rows.size(), lines.size()); final List<Col> cols = this.cols.toList();
final GridArray result = new GridArray(skinParam, lines.size(), cols.size());
for (Map.Entry<Coord, Cell> ent : cells.entrySet()) { for (Map.Entry<Coord, Cell> ent : cells.entrySet()) {
final int r = rows.indexOf(ent.getKey().getRow());
final int l = lines.indexOf(ent.getKey().getLine()); final int l = lines.indexOf(ent.getKey().getLine());
final int r = cols.indexOf(ent.getKey().getCol());
if (r == -1 || l == -1) { if (r == -1 || l == -1) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
result.setData(r, l, ent.getValue().getData()); result.setData(l, r, ent.getValue().getData());
} }
return result; return result;
} }
// public boolean isRowEmpty(Col row) {
// System.err.println("Testing Row " + row);
// for (Map.Entry<Coord, Cell> ent : cells.entrySet()) {
// final Cell cell = ent.getValue();
// if (cell == null || cell.getData() == null) {
// continue;
// }
// if (ent.getKey().getCol() == row) {
// System.err.println("Not empty " + cell + " " + cell.getData());
// return false;
// }
// }
// System.err.println("EMPTY!!!");
// return true;
// }
// public boolean isLineEmpty(Line line) {
// for (Map.Entry<Coord, Cell> ent : cells.entrySet()) {
// final Cell cell = ent.getValue();
// if (cell == null || cell.getData() == null) {
// continue;
// }
// if (ent.getKey().getLine() == line) {
// return false;
// }
// }
// return true;
// }
public Set<Col> usedColsOf(Line line) {
final Set<Col> result = new HashSet<Col>();
for (Map.Entry<Coord, Cell> ent : cells.entrySet()) {
final Cell cell = ent.getValue();
if (cell == null || cell.getData() == null) {
continue;
}
if (ent.getKey().getLine() == line) {
result.add(ent.getKey().getCol());
}
}
return Collections.unmodifiableSet(result);
}
public void removeLine(Line line) {
assert usedColsOf(line).isEmpty();
final boolean done = lines.remove(line);
if (done == false) {
throw new IllegalArgumentException();
}
}
// public void addEdge(Collection<GridEdge> other) {
// this.edges.addAll(other);
// }
public void mergeLines(Line source, Line dest) {
final Map<Coord, Cell> supp = new HashMap<Coord, Cell>();
for (Iterator<Map.Entry<Coord, Cell>> it = cells.entrySet().iterator(); it.hasNext();) {
final Map.Entry<Coord, Cell> ent = it.next();
final Cell cell = ent.getValue();
if (cell == null || cell.getData() == null) {
continue;
}
if (ent.getKey().getLine() == source) {
supp.put(new Coord(dest, ent.getKey().getCol()), cell);
it.remove();
}
}
cells.putAll(supp);
removeLine(source);
}
public void addConnections() {
for (Map.Entry<Coord, Cell> ent : new HashMap<Coord, Cell>(cells).entrySet()) {
final List<Cell> dests = ent.getValue().getDestinations();
final Coord src = ent.getKey();
for (int i = 0; i < dests.size(); i++) {
final Coord dest = getCoord(dests.get(i));
final boolean startHorizontal = i == 0;
if (startHorizontal) {
System.err.println("DrawingHorizontal " + ent.getValue() + " --> " + dests.get(i) + " " + i);
drawHorizontal(src, dest);
} else {
// drawVertical(src, dest);
}
}
}
}
private void drawVertical(final Coord src, final Coord dest) {
for (Navigator<Line> itLine = Navigators.iterate(lines, src.getLine(), dest.getLine()); itLine.get() != dest
.getLine();) {
final Line cur = itLine.next();
if (cur != dest.getLine()) {
Cell tmp = getCell(cur, src.getCol());
addPuzzle(tmp, "NS");
}
}
for (Navigator<Col> itCol = Navigators.iterate(cols, src.getCol(), dest.getCol()); itCol.get() != dest.getCol();) {
final Col cur = itCol.next();
if (cur != dest.getCol()) {
Cell tmp = getCell(dest.getLine(), cur);
addPuzzle(tmp, "EW");
}
}
}
private void drawHorizontal(final Coord src, final Coord dest) {
for (Navigator<Col> itCol = Navigators.iterate(cols, src.getCol(), dest.getCol()); itCol.get() != dest.getCol();) {
final Col cur = itCol.next();
if (cur != dest.getCol()) {
Cell tmp = getCell(src.getLine(), cur);
addPuzzle(tmp, "EW");
}
}
System.err.println("src=" + src + " " + getCell(src));
System.err.println("dest=" + dest + " " + getCell(dest));
for (Navigator<Line> itLine = Navigators.iterate(lines, src.getLine(), dest.getLine()); itLine.get() != dest
.getLine();) {
final Line cur = itLine.next();
if (cur != dest.getLine()) {
Cell tmp = getCell(cur, src.getCol());
addPuzzle(tmp, "NS");
}
}
}
private void addPuzzle(Cell tmp, String direction) {
ConnectorPuzzle after = ConnectorPuzzle.get(direction);
final ConnectorPuzzle before = (ConnectorPuzzle) tmp.getData();
if (before != null) {
after = after.append(before);
}
tmp.setData(after);
}
} }

View File

@ -37,8 +37,6 @@ package net.sourceforge.plantuml.bpm;
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.List;
import net.sourceforge.plantuml.ISkinParam; import net.sourceforge.plantuml.ISkinParam;
import net.sourceforge.plantuml.graphic.HtmlColorUtils; import net.sourceforge.plantuml.graphic.HtmlColorUtils;
@ -51,34 +49,35 @@ import net.sourceforge.plantuml.ugraphic.UTranslate;
public class GridArray implements UDrawable { public class GridArray implements UDrawable {
private final int rows;
private final int lines; private final int lines;
private final int cols;
private final Placeable data[][]; private final Placeable data[][];
private final ISkinParam skinParam; private final ISkinParam skinParam;
private final List<BpmEdge> edges = new ArrayList<BpmEdge>();
public GridArray(ISkinParam skinParam, int rows, int lines) { // private final List<GridEdge> edges = new ArrayList<GridEdge>();
public GridArray(ISkinParam skinParam, int lines, int cols) {
this.skinParam = skinParam; this.skinParam = skinParam;
this.rows = rows;
this.lines = lines; this.lines = lines;
this.data = new Placeable[rows][lines]; this.cols = cols;
this.data = new Placeable[lines][cols];
} }
@Override @Override
public String toString() { public String toString() {
return "" + lines + "x" + rows; return "" + lines + "x" + cols;
} }
public void setData(int r, int l, Placeable element) { public void setData(int l, int c, Placeable element) {
data[r][l] = element; data[l][c] = element;
} }
public Placeable getData(int r, int l) { public Placeable getData(int l, int c) {
return data[r][l]; return data[l][c];
} }
public final int getRows() { public final int getRows() {
return rows; return cols;
} }
public final int getLines() { public final int getLines() {
@ -87,8 +86,8 @@ public class GridArray implements UDrawable {
private double getHeightOfLine(StringBounder stringBounder, int line) { private double getHeightOfLine(StringBounder stringBounder, int line) {
double height = 0; double height = 0;
for (int i = 0; i < rows; i++) { for (int i = 0; i < cols; i++) {
final Placeable cell = data[i][line]; final Placeable cell = data[line][i];
if (cell == null) { if (cell == null) {
continue; continue;
} }
@ -97,10 +96,10 @@ public class GridArray implements UDrawable {
return height; return height;
} }
private double getWidthOfRow(StringBounder stringBounder, int row) { private double getWidthOfCol(StringBounder stringBounder, int col) {
double width = 0; double width = 0;
for (int i = 0; i < lines; i++) { for (int i = 0; i < lines; i++) {
final Placeable cell = data[row][i]; final Placeable cell = data[i][col];
if (cell == null) { if (cell == null) {
continue; continue;
} }
@ -115,48 +114,74 @@ public class GridArray implements UDrawable {
// printMe(); // printMe();
final StringBounder stringBounder = ug.getStringBounder(); final StringBounder stringBounder = ug.getStringBounder();
for (BpmEdge edge : edges) {
// System.err.println("Drawing " + edge); // for (GridEdge edge : edges) {
final int from[] = getCoord(edge.getFrom()); // // System.err.println("Drawing " + edge);
final int to[] = getCoord(edge.getTo()); // final int from[] = getCoord(edge.getFrom());
final Point2D pt1 = getCenterOf(stringBounder, from[0], from[1]); // final int to[] = getCoord(edge.getTo());
final Point2D pt2 = getCenterOf(stringBounder, to[0], to[1]); // final Point2D pt1 = getCenterOf(stringBounder, from[0], from[1]);
drawArrow(ug, pt1, pt2); // final Point2D pt2 = getCenterOf(stringBounder, to[0], to[1]);
} // drawArrow(ug, pt1, pt2);
// }
double dy = 0; double dy = 0;
drawInternalGrid(ug);
for (int l = 0; l < lines; l++) { for (int l = 0; l < lines; l++) {
double dx = 0; double dx = 0;
final double heightOfLine = getHeightOfLine(stringBounder, l); final double heightOfLine = getHeightOfLine(stringBounder, l);
for (int r = 0; r < rows; r++) { for (int r = 0; r < cols; r++) {
final double widthOfRow = getWidthOfRow(stringBounder, r); final double widthOfCol = getWidthOfCol(stringBounder, r);
final Placeable cell = data[r][l]; final Placeable cell = data[l][r];
if (cell != null) { if (cell != null) {
final Dimension2D dim = cell.getDimension(stringBounder, skinParam); final Dimension2D dim = cell.getDimension(stringBounder, skinParam);
cell.toTextBlock(skinParam).drawU( cell.toTextBlock(skinParam).drawU(
ug.apply(new UTranslate(dx + (widthOfRow - dim.getWidth()) / 2, dy ug.apply(new UTranslate(dx + (widthOfCol + margin - dim.getWidth()) / 2, dy
+ (heightOfLine - dim.getHeight()) / 2))); + (heightOfLine + margin - dim.getHeight()) / 2)));
} }
dx += widthOfRow + margin; dx += widthOfCol + margin;
} }
dy += heightOfLine + margin; dy += heightOfLine + margin;
} }
} }
private void drawInternalGrid(UGraphic ug) {
double heightMax = 0;
for (int l = 0; l < lines; l++) {
heightMax += getHeightOfLine(ug.getStringBounder(), l) + margin;
}
double widthMax = 0;
for (int c = 0; c < cols; c++) {
widthMax += getWidthOfCol(ug.getStringBounder(), c) + margin;
}
ug = ug.apply(new UChangeColor(HtmlColorUtils.BLACK));
double y = 0;
for (int l = 0; l < lines; l++) {
ug.apply(new UTranslate(0, y)).draw(new ULine(widthMax, 0));
y += getHeightOfLine(ug.getStringBounder(), l) + margin;
}
double x = 0;
for (int c = 0; c < cols; c++) {
ug.apply(new UTranslate(x, 0)).draw(new ULine(0, heightMax));
x += getWidthOfCol(ug.getStringBounder(), c) + margin;
}
}
private void drawArrow(UGraphic ug, Point2D pt1, Point2D pt2) { private void drawArrow(UGraphic ug, Point2D pt1, Point2D pt2) {
ug = ug.apply(new UChangeColor(HtmlColorUtils.BLUE)); ug = ug.apply(new UChangeColor(HtmlColorUtils.BLUE));
final ULine line = new ULine(pt2.getX() - pt1.getX(), pt2.getY() - pt1.getY()); final ULine line = new ULine(pt2.getX() - pt1.getX(), pt2.getY() - pt1.getY());
ug.apply(new UTranslate(pt1)).draw(line); ug.apply(new UTranslate(pt1)).draw(line);
} }
private Point2D getCenterOf(StringBounder stringBounder, int r, int l) { private Point2D getCenterOf(StringBounder stringBounder, int c, int l) {
double x = getWidthOfRow(stringBounder, r) / 2; double x = getWidthOfCol(stringBounder, c) / 2 + margin / 2;
for (int i = 0; i < r; i++) { for (int i = 0; i < c; i++) {
final double widthOfRow = getWidthOfRow(stringBounder, i); final double widthOfCol = getWidthOfCol(stringBounder, i);
x += widthOfRow + margin; x += widthOfCol + margin;
} }
double y = getHeightOfLine(stringBounder, l) / 2; double y = getHeightOfLine(stringBounder, l) / 2 + margin / 2;
for (int i = 0; i < l; i++) { for (int i = 0; i < l; i++) {
final double heightOfLine = getHeightOfLine(stringBounder, i); final double heightOfLine = getHeightOfLine(stringBounder, i);
y += heightOfLine + margin; y += heightOfLine + margin;
@ -164,12 +189,12 @@ public class GridArray implements UDrawable {
return new Point2D.Double(x, y); return new Point2D.Double(x, y);
} }
private int[] getCoord(Placeable element) { private int[] getCoord(Cell someCell) {
for (int l = 0; l < lines; l++) { for (int l = 0; l < lines; l++) {
for (int r = 0; r < rows; r++) { for (int c = 0; c < cols; c++) {
final Placeable cell = data[r][l]; final Placeable cell = data[l][c];
if (cell == element) { if (cell == someCell.getData()) {
return new int[] { r, l }; return new int[] { c, l };
} }
} }
} }
@ -178,8 +203,8 @@ public class GridArray implements UDrawable {
private void printMe() { private void printMe() {
for (int l = 0; l < lines; l++) { for (int l = 0; l < lines; l++) {
for (int r = 0; r < rows; r++) { for (int c = 0; c < cols; c++) {
final Placeable cell = data[r][l]; final Placeable cell = data[l][c];
System.err.print(cell); System.err.print(cell);
System.err.print(" ; "); System.err.print(" ; ");
} }
@ -187,8 +212,8 @@ public class GridArray implements UDrawable {
} }
} }
public void addEdges(List<BpmEdge> edges) { // void addEdgesInternal(List<GridEdge> edges) {
this.edges.addAll(edges); // this.edges.addAll(edges);
} // }
} }

View File

@ -31,33 +31,12 @@
* *
* Original Author: Arnaud Roques * Original Author: Arnaud Roques
* *
*
*/ */
package net.sourceforge.plantuml.bpm; package net.sourceforge.plantuml.bpm;
public class BpmEdge { public interface GridCleaner {
private final BpmElement from; public boolean clean(Grid grid);
private final BpmElement to;
public BpmEdge(BpmElement from, BpmElement to) {
if (from == null || to == null) {
throw new IllegalArgumentException();
}
this.from = from;
this.to = to;
}
public final BpmElement getFrom() {
return from;
}
public final BpmElement getTo() {
return to;
}
@Override
public String toString() {
return from.toString() + "-->" + to.toString();
}
} }

View File

@ -0,0 +1,80 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2017, Arnaud Roques
*
* Project Info: http://plantuml.com
*
* If you like this project or if you find it useful, you can support us at:
*
* http://plantuml.com/patreon (only 1$ per month!)
* http://plantuml.com/paypal
*
* This file is part of PlantUML.
*
* PlantUML is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PlantUML distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
* License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
*
* Original Author: Arnaud Roques
*
*
*/
package net.sourceforge.plantuml.bpm;
public final class Navigators {
private Navigators() {
}
public static <O> Navigator<O> iterate(final Chain<O> orig, final O from, final O to) {
if (orig.compare(from, to) <= 0) {
return orig.navigator(from);
}
return reverse(orig.navigator(to));
}
public static <O> Navigator<O> reverse(final Navigator<O> orig) {
return new Navigator<O>() {
public O next() {
return orig.previous();
}
public O previous() {
return orig.next();
}
public O get() {
return orig.get();
}
public void set(O data) {
orig.set(data);
}
public void insertBefore(O data) {
throw new UnsupportedOperationException();
}
public void insertAfter(O data) {
throw new UnsupportedOperationException();
}
};
}
}

View File

@ -58,7 +58,16 @@ public abstract class AbstractEntityDiagram extends CucaDiagram {
} }
final public DiagramDescription getDescription() { final public DiagramDescription getDescription() {
return new DiagramDescription("(" + getLeafssize() + " entities)"); final StringBuilder result = new StringBuilder("(" + getLeafssize() + " entities");
final String id = getSource().getId();
if (id == null) {
result.append(")");
} else {
result.append(", ");
result.append(id);
result.append(")");
}
return new DiagramDescription(result.toString());
} }
} }

View File

@ -117,7 +117,7 @@ public class ClassDiagramFactory extends UmlDiagramFactory {
cmds.add(new CommandImport()); cmds.add(new CommandImport());
final FactoryTipOnEntityCommand factoryTipOnEntityCommand = new FactoryTipOnEntityCommand(new RegexLeaf( final FactoryTipOnEntityCommand factoryTipOnEntityCommand = new FactoryTipOnEntityCommand(new RegexLeaf(
"ENTITY", "(" + CommandCreateClass.CODE_NO_DOTDOT + "|[%g][^%g]+[%g])::([^%s]+)")); "ENTITY", "(" + CommandCreateClass.CODE_NO_DOTDOT + "|[%g][^%g]+[%g])::([%g][^%g]+[%g]|[^%s]+)"));
cmds.add(factoryTipOnEntityCommand.createMultiLine(true)); cmds.add(factoryTipOnEntityCommand.createMultiLine(true));
cmds.add(factoryTipOnEntityCommand.createMultiLine(false)); cmds.add(factoryTipOnEntityCommand.createMultiLine(false));

View File

@ -73,7 +73,7 @@ public class CommandCreateClass extends SingleLineCommand2<ClassDiagram> {
private static RegexConcat getRegexConcat() { private static RegexConcat getRegexConcat() {
return new RegexConcat(new RegexLeaf("^"), // return new RegexConcat(new RegexLeaf("^"), //
new RegexLeaf("TYPE", // new RegexLeaf("TYPE", //
"(interface|enum|annotation|abstract[%s]+class|abstract|class|entity)[%s]+"), // "(interface|enum|annotation|abstract[%s]+class|abstract|class|entity|circle)[%s]+"), //
new RegexOr(// new RegexOr(//
new RegexConcat(// new RegexConcat(//
new RegexLeaf("DISPLAY1", "[%g](.+)[%g]"), // new RegexLeaf("DISPLAY1", "[%g](.+)[%g]"), //

View File

@ -160,7 +160,7 @@ public class CommandCreateClassMultilines extends CommandMultilines2<ClassDiagra
if (mode == Mode.IMPLEMENTS) { if (mode == Mode.IMPLEMENTS) {
type2 = LeafType.INTERFACE; type2 = LeafType.INTERFACE;
} }
if (mode == Mode.EXTENDS && entity.getEntityType() == LeafType.INTERFACE) { if (mode == Mode.EXTENDS && entity.getLeafType() == LeafType.INTERFACE) {
type2 = LeafType.INTERFACE; type2 = LeafType.INTERFACE;
} }
final String codes = arg.get(keyword, 2); final String codes = arg.get(keyword, 2);
@ -168,7 +168,7 @@ public class CommandCreateClassMultilines extends CommandMultilines2<ClassDiagra
final Code other = Code.of(StringUtils.trin(s)); final Code other = Code.of(StringUtils.trin(s));
final IEntity cl2 = system.getOrCreateLeaf(other, type2, null); final IEntity cl2 = system.getOrCreateLeaf(other, type2, null);
LinkType typeLink = new LinkType(LinkDecor.NONE, LinkDecor.EXTENDS); LinkType typeLink = new LinkType(LinkDecor.NONE, LinkDecor.EXTENDS);
if (type2 == LeafType.INTERFACE && entity.getEntityType() != LeafType.INTERFACE) { if (type2 == LeafType.INTERFACE && entity.getLeafType() != LeafType.INTERFACE) {
typeLink = typeLink.getDashed(); typeLink = typeLink.getDashed();
} }
final Link link = new Link(cl2, entity, typeLink, Display.NULL, 2, null, null, final Link link = new Link(cl2, entity, typeLink, Display.NULL, 2, null, null,

View File

@ -443,7 +443,7 @@ final public class CommandLinkClass extends SingleLineCommand2<AbstractClassOrOb
return LinkDecor.COMPOSITION; return LinkDecor.COMPOSITION;
} }
if ("#".equals(s)) { if ("#".equals(s)) {
return LinkDecor.SQUARRE; return LinkDecor.SQUARE;
} }
if (")".equals(s)) { if (")".equals(s)) {
return LinkDecor.PARENTHESIS; return LinkDecor.PARENTHESIS;
@ -493,7 +493,7 @@ final public class CommandLinkClass extends SingleLineCommand2<AbstractClassOrOb
return LinkDecor.COMPOSITION; return LinkDecor.COMPOSITION;
} }
if ("#".equals(s)) { if ("#".equals(s)) {
return LinkDecor.SQUARRE; return LinkDecor.SQUARE;
} }
if ("(".equals(s)) { if ("(".equals(s)) {
return LinkDecor.PARENTHESIS; return LinkDecor.PARENTHESIS;

View File

@ -78,7 +78,7 @@ public abstract class PSystemBasicFactory<P extends AbstractPSystem> extends PSy
} }
first = false; first = false;
if (StartUtils.isArobaseEndDiagram(s)) { if (StartUtils.isArobaseEndDiagram(s)) {
if (source.getTotalLineCount() == 2) { if (source.getTotalLineCount() == 2 && source.isStartDef() == false) {
return buildEmptyError(source, s.getLocation()); return buildEmptyError(source, s.getLocation());
} }
if (system != null) { if (system != null) {

View File

@ -106,7 +106,8 @@ public final class FactoryTipOnEntityCommand implements SingleMultiFactoryComman
Url url = null; Url url = null;
if (line0.get("URL", 0) != null) { if (line0.get("URL", 0) != null) {
final UrlBuilder urlBuilder = new UrlBuilder(system.getSkinParam().getValue("topurl"), ModeUrl.STRICT); final UrlBuilder urlBuilder = new UrlBuilder(system.getSkinParam().getValue("topurl"),
ModeUrl.STRICT);
url = urlBuilder.getUrl(line0.get("URL", 0)); url = urlBuilder.getUrl(line0.get("URL", 0));
} }
@ -121,7 +122,7 @@ public final class FactoryTipOnEntityCommand implements SingleMultiFactoryComman
final String pos = line0.get("POSITION", 0); final String pos = line0.get("POSITION", 0);
final Code code = Code.of(line0.get("ENTITY", 0)); final Code code = Code.of(line0.get("ENTITY", 0));
final String member = line0.get("ENTITY", 1); final String member = StringUtils.eventuallyRemoveStartingAndEndingDoubleQuote(line0.get("ENTITY", 1));
if (code == null) { if (code == null) {
return CommandExecutionResult.error("Nothing to note to"); return CommandExecutionResult.error("Nothing to note to");
} }
@ -143,33 +144,6 @@ public final class FactoryTipOnEntityCommand implements SingleMultiFactoryComman
diagram.addLink(link); diagram.addLink(link);
} }
tips.putTip(member, lines.toDisplay()); tips.putTip(member, lines.toDisplay());
// final IEntity note = diagram.createLeaf(UniqueSequence.getCode("GMN"), Display.create(s), LeafType.NOTE,
// null);
// note.setSpecificBackcolor(diagram.getSkinParam().getIHtmlColorSet().getColorIfValid(line0.get("COLOR", 0)));
// if (url != null) {
// note.addUrl(url);
// }
//
// final Position position = Position.valueOf(StringUtils.goUpperCase(pos)).withRankdir(
// diagram.getSkinParam().getRankdir());
// final Link link;
//
// final LinkType type = new LinkType(LinkDecor.NONE, LinkDecor.NONE).getDashed();
// if (position == Position.RIGHT) {
// link = new Link(cl1, note, type, null, 1);
// link.setHorizontalSolitary(true);
// } else if (position == Position.LEFT) {
// link = new Link(note, cl1, type, null, 1);
// link.setHorizontalSolitary(true);
// } else if (position == Position.BOTTOM) {
// link = new Link(cl1, note, type, null, 2);
// } else if (position == Position.TOP) {
// link = new Link(note, cl1, type, null, 2);
// } else {
// throw new IllegalArgumentException();
// }
// diagram.addLink(link);
return CommandExecutionResult.ok(); return CommandExecutionResult.ok();
} }

View File

@ -54,7 +54,7 @@ public interface Diagram {
* @param os * @param os
* where to write the image * where to write the image
* @param num * @param num
* useually 0 (index of the image to be exported for this diagram). * usually 0 (index of the image to be exported for this diagram).
* @param fileFormat * @param fileFormat
* file format to use * file format to use
* *

View File

@ -38,7 +38,7 @@ package net.sourceforge.plantuml.core;
import net.sourceforge.plantuml.utils.StartUtils; import net.sourceforge.plantuml.utils.StartUtils;
public enum DiagramType { public enum DiagramType {
UML, BPM, DITAA, DOT, PROJECT, JCCKIT, SALT, FLOW, CREOLE, JUNGLE, CUTE, MATH, LATEX, UNKNOWN; UML, BPM, DITAA, DOT, PROJECT, JCCKIT, SALT, FLOW, CREOLE, JUNGLE, CUTE, MATH, LATEX, DEFINITION, UNKNOWN;
static public DiagramType getTypeFromArobaseStart(String s) { static public DiagramType getTypeFromArobaseStart(String s) {
s = s.toLowerCase(); s = s.toLowerCase();
@ -84,6 +84,9 @@ public enum DiagramType {
if (StartUtils.startsWithSymbolAnd("startlatex", s)) { if (StartUtils.startsWithSymbolAnd("startlatex", s)) {
return LATEX; return LATEX;
} }
if (StartUtils.startsWithSymbolAnd("startdef", s)) {
return DEFINITION;
}
return UNKNOWN; return UNKNOWN;
} }
} }

View File

@ -38,6 +38,8 @@ package net.sourceforge.plantuml.core;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.sourceforge.plantuml.CharSequence2; import net.sourceforge.plantuml.CharSequence2;
import net.sourceforge.plantuml.CharSequence2Impl; import net.sourceforge.plantuml.CharSequence2Impl;
@ -192,4 +194,16 @@ final public class UmlSource {
return Display.empty(); return Display.empty();
} }
public boolean isStartDef() {
return source.get(0).startsWith("@startdef");
}
public String getId() {
final Pattern p = Pattern.compile("id=([\\w]+)\\b");
final Matcher m = p.matcher(source.get(0));
if (m.find()) {
return m.group(1);
}
return null;
}
} }

View File

@ -52,6 +52,7 @@ import net.sourceforge.plantuml.FileFormat;
import net.sourceforge.plantuml.FileFormatOption; import net.sourceforge.plantuml.FileFormatOption;
import net.sourceforge.plantuml.core.Diagram; import net.sourceforge.plantuml.core.Diagram;
import net.sourceforge.plantuml.graphic.StringBounder; import net.sourceforge.plantuml.graphic.StringBounder;
import net.sourceforge.plantuml.preproc.Defines;
import net.sourceforge.plantuml.ugraphic.UGraphic; import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.UImage; import net.sourceforge.plantuml.ugraphic.UImage;
import net.sourceforge.plantuml.ugraphic.UShape; import net.sourceforge.plantuml.ugraphic.UShape;
@ -109,7 +110,7 @@ class AtomEmbededSystem implements Atom {
// } // }
// //
private Diagram getSystem() throws IOException, InterruptedException { private Diagram getSystem() throws IOException, InterruptedException {
final BlockUml blockUml = new BlockUml(lines2, 0); final BlockUml blockUml = new BlockUml(lines2, 0, Defines.createEmpty());
return blockUml.getDiagram(); return blockUml.getDiagram();
} }

View File

@ -71,7 +71,7 @@ public class AtomImg implements Atom {
} }
public static Atom create(String src, final ImgValign valign, final int vspace, final double scale) { public static Atom create(String src, final ImgValign valign, final int vspace, final double scale) {
final UFont font = new UFont("Monospaced", Font.PLAIN, 14); final UFont font = UFont.monospaced(14);
final FontConfiguration fc = FontConfiguration.blackBlueTrue(font); final FontConfiguration fc = FontConfiguration.blackBlueTrue(font);
if (src.startsWith(DATA_IMAGE_PNG_BASE64)) { if (src.startsWith(DATA_IMAGE_PNG_BASE64)) {

View File

@ -40,6 +40,7 @@ import java.awt.geom.Dimension2D;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import net.sourceforge.plantuml.Dimension2DDouble; import net.sourceforge.plantuml.Dimension2DDouble;
import net.sourceforge.plantuml.SvgString;
import net.sourceforge.plantuml.graphic.HtmlColor; import net.sourceforge.plantuml.graphic.HtmlColor;
import net.sourceforge.plantuml.graphic.HtmlColorSimple; import net.sourceforge.plantuml.graphic.HtmlColorSimple;
import net.sourceforge.plantuml.graphic.StringBounder; import net.sourceforge.plantuml.graphic.StringBounder;
@ -90,7 +91,7 @@ public class AtomMath implements Atom {
} }
final Color fore = getColor(foreground, Color.BLACK); final Color fore = getColor(foreground, Color.BLACK);
if (isSvg) { if (isSvg) {
final String svg = math.getSvg(fore, back); final SvgString svg = math.getSvg(scale, fore, back);
ug.draw(new UImageSvg(svg)); ug.draw(new UImageSvg(svg));
} else { } else {
ug.draw(new UImage(math.getImage(scale, fore, back))); ug.draw(new UImage(math.getImage(scale, fore, back)));

View File

@ -72,7 +72,7 @@ public class PSystemCreole extends AbstractPSystem {
final protected ImageData exportDiagramNow(OutputStream os, int num, FileFormatOption fileFormat) final protected ImageData exportDiagramNow(OutputStream os, int num, FileFormatOption fileFormat)
throws IOException { throws IOException {
final Display display = Display.create(lines); final Display display = Display.create(lines);
final UFont font = new UFont("Serif", Font.PLAIN, 14); final UFont font = UFont.serif(14);
final FontConfiguration fontConfiguration = FontConfiguration.blackBlueTrue(font); final FontConfiguration fontConfiguration = FontConfiguration.blackBlueTrue(font);
final Sheet sheet = new CreoleParser(fontConfiguration, HorizontalAlignment.LEFT, null, CreoleMode.FULL) final Sheet sheet = new CreoleParser(fontConfiguration, HorizontalAlignment.LEFT, null, CreoleMode.FULL)
.createSheet(display); .createSheet(display);

View File

@ -46,6 +46,7 @@ import net.sourceforge.plantuml.Dimension2DDouble;
import net.sourceforge.plantuml.LineBreakStrategy; import net.sourceforge.plantuml.LineBreakStrategy;
import net.sourceforge.plantuml.graphic.AbstractTextBlock; import net.sourceforge.plantuml.graphic.AbstractTextBlock;
import net.sourceforge.plantuml.graphic.HorizontalAlignment; import net.sourceforge.plantuml.graphic.HorizontalAlignment;
import net.sourceforge.plantuml.graphic.InnerStrategy;
import net.sourceforge.plantuml.graphic.StringBounder; import net.sourceforge.plantuml.graphic.StringBounder;
import net.sourceforge.plantuml.graphic.TextBlock; import net.sourceforge.plantuml.graphic.TextBlock;
import net.sourceforge.plantuml.ugraphic.MinMax; import net.sourceforge.plantuml.ugraphic.MinMax;
@ -154,7 +155,7 @@ public class SheetBlock1 extends AbstractTextBlock implements TextBlock, Atom, S
} }
@Override @Override
public Rectangle2D getInnerPosition(String member, StringBounder stringBounder) { public Rectangle2D getInnerPosition(String member, StringBounder stringBounder, InnerStrategy strategy) {
return null; return null;
} }

View File

@ -39,6 +39,7 @@ import java.awt.geom.Dimension2D;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
import net.sourceforge.plantuml.graphic.AbstractTextBlock; import net.sourceforge.plantuml.graphic.AbstractTextBlock;
import net.sourceforge.plantuml.graphic.InnerStrategy;
import net.sourceforge.plantuml.graphic.StringBounder; import net.sourceforge.plantuml.graphic.StringBounder;
import net.sourceforge.plantuml.graphic.TextBlock; import net.sourceforge.plantuml.graphic.TextBlock;
import net.sourceforge.plantuml.ugraphic.UGraphic; import net.sourceforge.plantuml.ugraphic.UGraphic;
@ -81,8 +82,8 @@ public class SheetBlock2 extends AbstractTextBlock implements TextBlock, Atom {
} }
@Override @Override
public Rectangle2D getInnerPosition(String member, StringBounder stringBounder) { public Rectangle2D getInnerPosition(String member, StringBounder stringBounder, InnerStrategy strategy) {
return block.getInnerPosition(member, stringBounder); return block.getInnerPosition(member, stringBounder, strategy);
} }
} }

View File

@ -207,4 +207,8 @@ public class Bodier {
return TextBlockUtils.mergeTB(bb1, bb2, HorizontalAlignment.LEFT); return TextBlockUtils.mergeTB(bb1, bb2, HorizontalAlignment.LEFT);
} }
public List<String> getRawBody() {
return Collections.unmodifiableList(rawBody);
}
} }

View File

@ -52,6 +52,7 @@ import net.sourceforge.plantuml.creole.CreoleParser;
import net.sourceforge.plantuml.graphic.AbstractTextBlock; import net.sourceforge.plantuml.graphic.AbstractTextBlock;
import net.sourceforge.plantuml.graphic.FontConfiguration; import net.sourceforge.plantuml.graphic.FontConfiguration;
import net.sourceforge.plantuml.graphic.HorizontalAlignment; import net.sourceforge.plantuml.graphic.HorizontalAlignment;
import net.sourceforge.plantuml.graphic.InnerStrategy;
import net.sourceforge.plantuml.graphic.StringBounder; import net.sourceforge.plantuml.graphic.StringBounder;
import net.sourceforge.plantuml.graphic.TextBlock; import net.sourceforge.plantuml.graphic.TextBlock;
import net.sourceforge.plantuml.graphic.TextBlockLineBefore; import net.sourceforge.plantuml.graphic.TextBlockLineBefore;
@ -85,7 +86,7 @@ public class BodyEnhanced extends AbstractTextBlock implements TextBlock, WithPo
this.titleConfig = new FontConfiguration(skinParam, fontParam, stereotype); this.titleConfig = new FontConfiguration(skinParam, fontParam, stereotype);
this.lineFirst = true; this.lineFirst = true;
this.align = HorizontalAlignment.LEFT; this.align = skinParam.getDefaultTextAlignment(HorizontalAlignment.LEFT);
this.manageHorizontalLine = true; this.manageHorizontalLine = true;
this.manageModifier = manageModifier; this.manageModifier = manageModifier;
this.entity = entity; this.entity = entity;
@ -104,7 +105,7 @@ public class BodyEnhanced extends AbstractTextBlock implements TextBlock, WithPo
this.titleConfig = new FontConfiguration(skinParam, fontParam, stereotype); this.titleConfig = new FontConfiguration(skinParam, fontParam, stereotype);
this.lineFirst = false; this.lineFirst = false;
this.align = align; this.align = skinParam.getDefaultTextAlignment(align);
this.manageHorizontalLine = manageHorizontalLine; this.manageHorizontalLine = manageHorizontalLine;
this.manageModifier = manageModifier; this.manageModifier = manageModifier;
@ -163,8 +164,8 @@ public class BodyEnhanced extends AbstractTextBlock implements TextBlock, WithPo
} }
} }
} }
blocks.add(decorate(stringBounder, new MethodsOrFieldsArea(members, fontParam, skinParam, align, stereotype, entity), blocks.add(decorate(stringBounder, new MethodsOrFieldsArea(members, fontParam, skinParam, align, stereotype,
separator, title)); entity), separator, title));
if (blocks.size() == 1) { if (blocks.size() == 1) {
this.area2 = blocks.get(0); this.area2 = blocks.get(0);
@ -231,8 +232,8 @@ public class BodyEnhanced extends AbstractTextBlock implements TextBlock, WithPo
return Collections.unmodifiableList(urls); return Collections.unmodifiableList(urls);
} }
public Rectangle2D getInnerPosition(String member, StringBounder stringBounder) { public Rectangle2D getInnerPosition(String member, StringBounder stringBounder, InnerStrategy strategy) {
return getArea(stringBounder).getInnerPosition(member, stringBounder); return getArea(stringBounder).getInnerPosition(member, stringBounder, strategy);
} }
} }

View File

@ -116,7 +116,7 @@ public abstract class CucaDiagram extends UmlDiagram implements GroupHierarchy,
result = createLeafInternal(code, Display.getWithNewlines(code), type, getCurrentGroup(), symbol); result = createLeafInternal(code, Display.getWithNewlines(code), type, getCurrentGroup(), symbol);
result.setUSymbol(symbol); result.setUSymbol(symbol);
} }
if (result.getEntityType() == LeafType.CLASS && type == LeafType.OBJECT) { if (result.getLeafType() == LeafType.CLASS && type == LeafType.OBJECT) {
if (result.muteToType(type, symbol) == false) { if (result.muteToType(type, symbol) == false) {
return null; return null;
} }
@ -286,6 +286,10 @@ public abstract class CucaDiagram extends UmlDiagram implements GroupHierarchy,
if (aspect != null) { if (aspect != null) {
result.add("aspect=" + aspect + ";"); result.add("aspect=" + aspect + ";");
} }
final String ratio = getPragma().getValue("ratio");
if (ratio != null) {
result.add("ratio=" + ratio + ";");
}
return result.toArray(new String[result.size()]); return result.toArray(new String[result.size()]);
} }
@ -547,8 +551,7 @@ public abstract class CucaDiagram extends UmlDiagram implements GroupHierarchy,
final List<Link> links = getLinks(); final List<Link> links = getLinks();
for (int i = links.size() - 1; i >= 0; i--) { for (int i = links.size() - 1; i >= 0; i--) {
final Link link = links.get(i); final Link link = links.get(i);
if (link.getEntity1().getEntityType() != LeafType.NOTE if (link.getEntity1().getLeafType() != LeafType.NOTE && link.getEntity2().getLeafType() != LeafType.NOTE) {
&& link.getEntity2().getEntityType() != LeafType.NOTE) {
return link; return link;
} }
} }

View File

@ -80,12 +80,6 @@ public class Display implements Iterable<CharSequence> {
private final boolean isNull; private final boolean isNull;
private final CreoleMode defaultCreoleMode; private final CreoleMode defaultCreoleMode;
// public Display removeUrlHiddenNewLineUrl() {
// final String full = UrlBuilder.purgeUrl(asStringWithHiddenNewLine());
// return new Display(StringUtils.splitHiddenNewLine(full), this.naturalHorizontalAlignment, this.isNull,
// this.defaultCreoleMode);
// }
public final static Display NULL = new Display(null, null, true, CreoleMode.FULL); public final static Display NULL = new Display(null, null, true, CreoleMode.FULL);
public boolean isWhite() { public boolean isWhite() {
@ -116,9 +110,16 @@ public class Display implements Iterable<CharSequence> {
final List<String> result = new ArrayList<String>(); final List<String> result = new ArrayList<String>();
final StringBuilder current = new StringBuilder(); final StringBuilder current = new StringBuilder();
HorizontalAlignment naturalHorizontalAlignment = null; HorizontalAlignment naturalHorizontalAlignment = null;
boolean mathMode = false;
for (int i = 0; i < s.length(); i++) { for (int i = 0; i < s.length(); i++) {
final char c = s.charAt(i); final char c = s.charAt(i);
if (c == '\\' && i < s.length() - 1) { final String sub = s.substring(i);
if (sub.startsWith("<math>") || sub.startsWith("<latex>")) {
mathMode = true;
} else if (sub.startsWith("</math>") || sub.startsWith("</latex>")) {
mathMode = false;
}
if (mathMode == false && c == '\\' && i < s.length() - 1) {
final char c2 = s.charAt(i + 1); final char c2 = s.charAt(i + 1);
i++; i++;
if (c2 == 'n' || c2 == 'r' || c2 == 'l') { if (c2 == 'n' || c2 == 'r' || c2 == 'l') {
@ -300,27 +301,6 @@ public class Display implements Iterable<CharSequence> {
return Collections.unmodifiableList(result); return Collections.unmodifiableList(result);
} }
// public Url initUrl() {
// if (this.size() == 0) {
// return null;
// }
// final UrlBuilder urlBuilder = new UrlBuilder(null, ModeUrl.AT_START);
// return urlBuilder.getUrl(StringUtils.trin(this.get(0).toString()));
// }
// public Display removeHeadingUrl(Url url) {
// if (url == null) {
// return this;
// }
// final Display result = new Display(this.naturalHorizontalAlignment, this.isNull, this.defaultCreoleMode);
// result.display.add(UrlBuilder.purgeUrl(this.get(0).toString()));
// result.display.addAll(this.subList(1, this.size()).display);
// if (result.isWhite() && url.getLabel() != null) {
// return Display.getWithNewlines(url.getLabel());
// }
// return result;
// }
public boolean hasUrl() { public boolean hasUrl() {
final UrlBuilder urlBuilder = new UrlBuilder(null, ModeUrl.ANYWHERE); final UrlBuilder urlBuilder = new UrlBuilder(null, ModeUrl.ANYWHERE);
for (CharSequence s : this) { for (CharSequence s : this) {
@ -376,7 +356,8 @@ public class Display implements Iterable<CharSequence> {
public TextBlock create(FontConfiguration fontConfiguration, HorizontalAlignment horizontalAlignment, public TextBlock create(FontConfiguration fontConfiguration, HorizontalAlignment horizontalAlignment,
ISkinSimple spriteContainer, CreoleMode modeSimpleLine) { ISkinSimple spriteContainer, CreoleMode modeSimpleLine) {
return create(fontConfiguration, horizontalAlignment, spriteContainer, LineBreakStrategy.NONE, modeSimpleLine, null, null); return create(fontConfiguration, horizontalAlignment, spriteContainer, LineBreakStrategy.NONE, modeSimpleLine,
null, null);
} }
public TextBlock create(FontConfiguration fontConfiguration, HorizontalAlignment horizontalAlignment, public TextBlock create(FontConfiguration fontConfiguration, HorizontalAlignment horizontalAlignment,

View File

@ -46,24 +46,24 @@ class Election {
private final Map<String, Member> all = new HashMap<String, Member>(); private final Map<String, Member> all = new HashMap<String, Member>();
public void addCandidat(String display, Member candidat) { public void addCandidate(String display, Member candidate) {
all.put(display, candidat); all.put(display, candidate);
} }
private Member getCandidat(String shortName) { private Member getCandidate(String shortName) {
List<Member> list = getAllCandidatContains(shortName); List<Member> list = getAllCandidateContains(shortName);
if (list.size() == 1) { if (list.size() == 1) {
return list.get(0); return list.get(0);
} }
list = getAllCandidatContainsStrict(shortName); list = getAllCandidateContainsStrict(shortName);
if (list.size() == 1) { if (list.size() == 1) {
return list.get(0); return list.get(0);
} }
return null; return null;
} }
private List<Member> getAllCandidatContains(String shortName) { private List<Member> getAllCandidateContains(String shortName) {
final List<Member> result = new ArrayList<Member>(); final List<Member> result = new ArrayList<Member>();
for (Map.Entry<String, Member> ent : all.entrySet()) { for (Map.Entry<String, Member> ent : all.entrySet()) {
if (ent.getKey().contains(shortName)) { if (ent.getKey().contains(shortName)) {
@ -73,7 +73,7 @@ class Election {
return result; return result;
} }
private List<Member> getAllCandidatContainsStrict(String shortName) { private List<Member> getAllCandidateContainsStrict(String shortName) {
final List<Member> result = new ArrayList<Member>(); final List<Member> result = new ArrayList<Member>();
for (Map.Entry<String, Member> ent : all.entrySet()) { for (Map.Entry<String, Member> ent : all.entrySet()) {
final String key = ent.getKey(); final String key = ent.getKey();
@ -87,7 +87,7 @@ class Election {
public Map<Member, String> getAllElected(Collection<String> shortNames) { public Map<Member, String> getAllElected(Collection<String> shortNames) {
final Map<Member, String> memberWithPort = new HashMap<Member, String>(); final Map<Member, String> memberWithPort = new HashMap<Member, String>();
for (String shortName : shortNames) { for (String shortName : shortNames) {
final Member m = getCandidat(shortName); final Member m = getCandidate(shortName);
if (m != null) { if (m != null) {
memberWithPort.put(m, shortName); memberWithPort.put(m, shortName);
} }

View File

@ -40,7 +40,7 @@ public class EntityGenderUtils {
static public EntityGender byEntityType(final LeafType type) { static public EntityGender byEntityType(final LeafType type) {
return new EntityGender() { return new EntityGender() {
public boolean contains(IEntity test) { public boolean contains(IEntity test) {
return test.getEntityType() == type; return test.getLeafType() == type;
} }
}; };
} }

View File

@ -89,7 +89,7 @@ public class GroupRoot implements IGroup {
} }
public LeafType getEntityType() { public LeafType getLeafType() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@ -172,7 +172,7 @@ public class GroupRoot implements IGroup {
} }
public void overideImage(IEntityImage img, LeafType state) { public void overrideImage(IEntityImage img, LeafType state) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }

View File

@ -54,7 +54,7 @@ public interface IEntity extends SpecificBackcolorable, Hideable, Removeable, Li
public void setUSymbol(USymbol symbol); public void setUSymbol(USymbol symbol);
public LeafType getEntityType(); public LeafType getLeafType();
public Display getDisplay(); public Display getDisplay();

View File

@ -61,7 +61,7 @@ public interface IGroup extends IEntity {
public PackageStyle getPackageStyle(); public PackageStyle getPackageStyle();
public void overideImage(IEntityImage img, LeafType state); public void overrideImage(IEntityImage img, LeafType state);
public SingleStrategy getSingleStrategy(); public SingleStrategy getSingleStrategy();

View File

@ -41,7 +41,7 @@ public enum LeafType {
EMPTY_PACKAGE, EMPTY_PACKAGE,
ABSTRACT_CLASS, CLASS, INTERFACE, ANNOTATION, LOLLIPOP, NOTE, TIPS, OBJECT, ASSOCIATION, ENUM, ABSTRACT_CLASS, CLASS, INTERFACE, ANNOTATION, LOLLIPOP, NOTE, TIPS, OBJECT, ASSOCIATION, ENUM, CIRCLE,
USECASE, USECASE,
@ -57,12 +57,12 @@ public enum LeafType {
STILL_UNKNOWN; STILL_UNKNOWN;
public static LeafType getLeafType(String arg0) { public static LeafType getLeafType(String type) {
arg0 = StringUtils.goUpperCase(arg0); type = StringUtils.goUpperCase(type);
if (arg0.startsWith("ABSTRACT")) { if (type.startsWith("ABSTRACT")) {
return LeafType.ABSTRACT_CLASS; return LeafType.ABSTRACT_CLASS;
} }
return LeafType.valueOf(arg0); return LeafType.valueOf(type);
} }
public boolean isLikeClass() { public boolean isLikeClass() {

View File

@ -374,7 +374,7 @@ public class Link implements Hideable, Removeable {
} }
public boolean containsType(LeafType type) { public boolean containsType(LeafType type) {
if (getEntity1().getEntityType() == type || getEntity2().getEntityType() == type) { if (getEntity1().getLeafType() == type || getEntity2().getLeafType() == type) {
return true; return true;
} }
return false; return false;

View File

@ -66,7 +66,7 @@ public enum LinkDecor {
ARROW(10, true, 0.5), ARROW_TRIANGLE(10, true, 0.8), ARROW_AND_CIRCLE(10, false, 0.5), ARROW(10, true, 0.5), ARROW_TRIANGLE(10, true, 0.8), ARROW_AND_CIRCLE(10, false, 0.5),
CIRCLE(0, false, 0.5), CIRCLE_CONNECT(0, false, 0.5), PARENTHESIS(0, false, OptionFlags.USE_INTERFACE_EYE2 ? 0.5 CIRCLE(0, false, 0.5), CIRCLE_CONNECT(0, false, 0.5), PARENTHESIS(0, false, OptionFlags.USE_INTERFACE_EYE2 ? 0.5
: 1.0), SQUARRE(0, false, 0.5), : 1.0), SQUARE(0, false, 0.5),
CIRCLE_CROSS(0, false, 0.5), PLUS(0, false, 1.5), SQUARRE_toberemoved(30, false, 0); CIRCLE_CROSS(0, false, 0.5), PLUS(0, false, 1.5), SQUARRE_toberemoved(30, false, 0);
@ -121,7 +121,7 @@ public enum LinkDecor {
return new ExtremityFactoryDiamond(true, backgroundColor); return new ExtremityFactoryDiamond(true, backgroundColor);
} else if (this == LinkDecor.CIRCLE) { } else if (this == LinkDecor.CIRCLE) {
return new ExtremityFactoryCircle(); return new ExtremityFactoryCircle();
} else if (this == LinkDecor.SQUARRE) { } else if (this == LinkDecor.SQUARE) {
return new ExtremityFactorySquarre(); return new ExtremityFactorySquarre();
} else if (this == LinkDecor.PARENTHESIS) { } else if (this == LinkDecor.PARENTHESIS) {
return new ExtremityFactoryParenthesis(); return new ExtremityFactoryParenthesis();

View File

@ -38,7 +38,7 @@ package net.sourceforge.plantuml.cucadiagram;
public enum LinkHat { public enum LinkHat {
NONE /*, SQUARRE, CIRCLE, CIRCLE_CONNECT; NONE /*, SQUARE, CIRCLE, CIRCLE_CONNECT;
public ExtremityFactory getExtremityFactory() { public ExtremityFactory getExtremityFactory() {
if (this == LinkHat.CIRCLE) { if (this == LinkHat.CIRCLE) {

View File

@ -196,8 +196,8 @@ public class LinkType {
return decor2; return decor2;
} }
public boolean isExtendsOrAgregationOrCompositionOrPlus() { public boolean isExtendsOrAggregationOrCompositionOrPlus() {
return isExtends() || isAgregationOrComposition() || isPlus(); return isExtends() || isAggregationOrComposition() || isPlus();
} }
private boolean isExtends() { private boolean isExtends() {
@ -208,7 +208,7 @@ public class LinkType {
return decor1 == LinkDecor.PLUS || decor2 == LinkDecor.PLUS; return decor1 == LinkDecor.PLUS || decor2 == LinkDecor.PLUS;
} }
private boolean isAgregationOrComposition() { private boolean isAggregationOrComposition() {
return decor1 == LinkDecor.AGREGATION || decor2 == LinkDecor.AGREGATION || decor1 == LinkDecor.COMPOSITION return decor1 == LinkDecor.AGREGATION || decor2 == LinkDecor.AGREGATION || decor1 == LinkDecor.COMPOSITION
|| decor2 == LinkDecor.COMPOSITION; || decor2 == LinkDecor.COMPOSITION;
} }

View File

@ -50,6 +50,7 @@ import net.sourceforge.plantuml.graphic.AbstractTextBlock;
import net.sourceforge.plantuml.graphic.FontConfiguration; import net.sourceforge.plantuml.graphic.FontConfiguration;
import net.sourceforge.plantuml.graphic.HorizontalAlignment; import net.sourceforge.plantuml.graphic.HorizontalAlignment;
import net.sourceforge.plantuml.graphic.HtmlColor; import net.sourceforge.plantuml.graphic.HtmlColor;
import net.sourceforge.plantuml.graphic.InnerStrategy;
import net.sourceforge.plantuml.graphic.StringBounder; import net.sourceforge.plantuml.graphic.StringBounder;
import net.sourceforge.plantuml.graphic.TextBlock; import net.sourceforge.plantuml.graphic.TextBlock;
import net.sourceforge.plantuml.graphic.TextBlockLineBefore; import net.sourceforge.plantuml.graphic.TextBlockLineBefore;
@ -137,7 +138,7 @@ public class MethodsOrFieldsArea extends AbstractTextBlock implements TextBlockW
double y = 0; double y = 0;
final Election election = new Election(); final Election election = new Election();
for (Member m : members) { for (Member m : members) {
election.addCandidat(m.getDisplay(false), m); election.addCandidate(m.getDisplay(false), m);
} }
final Map<Member, String> memberWithPort = election.getAllElected(leaf.getPortShortNames()); final Map<Member, String> memberWithPort = election.getAllElected(leaf.getPortShortNames());
for (Member m : members) { for (Member m : members) {
@ -196,8 +197,8 @@ public class MethodsOrFieldsArea extends AbstractTextBlock implements TextBlockW
} }
@Override @Override
public Rectangle2D getInnerPosition(String member, StringBounder stringBounder) { public Rectangle2D getInnerPosition(String member, StringBounder stringBounder, InnerStrategy strategy) {
return bloc.getInnerPosition(member, stringBounder); return bloc.getInnerPosition(member, stringBounder, strategy);
} }
} }
@ -236,7 +237,7 @@ public class MethodsOrFieldsArea extends AbstractTextBlock implements TextBlockW
} }
@Override @Override
public Rectangle2D getInnerPosition(String member, StringBounder stringBounder) { public Rectangle2D getInnerPosition(String member, StringBounder stringBounder, InnerStrategy strategy) {
final ULayoutGroup group = getLayout(stringBounder); final ULayoutGroup group = getLayout(stringBounder);
final Dimension2D dim = calculateDimension(stringBounder); final Dimension2D dim = calculateDimension(stringBounder);
return group.getInnerPosition(member, dim.getWidth(), dim.getHeight(), stringBounder); return group.getInnerPosition(member, dim.getWidth(), dim.getHeight(), stringBounder);

View File

@ -72,7 +72,7 @@ public final class CucaDiagramSimplifierActivity {
// } // }
final IEntityImage img = computeImage(g); final IEntityImage img = computeImage(g);
g.overideImage(img, LeafType.ACTIVITY); g.overrideImage(img, LeafType.ACTIVITY);
changed = true; changed = true;
} }

View File

@ -66,7 +66,7 @@ public final class CucaDiagramSimplifierState {
for (IGroup g : groups) { for (IGroup g : groups) {
if (diagram.isAutarkic(g)) { if (diagram.isAutarkic(g)) {
final IEntityImage img = computeImage(g); final IEntityImage img = computeImage(g);
g.overideImage(img, g.getGroupType() == GroupType.CONCURRENT_STATE ? LeafType.STATE_CONCURRENT g.overrideImage(img, g.getGroupType() == GroupType.CONCURRENT_STATE ? LeafType.STATE_CONCURRENT
: LeafType.STATE); : LeafType.STATE);
changed = true; changed = true;

View File

@ -42,12 +42,11 @@ import java.io.OutputStream;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
import net.sourceforge.plantuml.OptionFlags;
import net.sourceforge.plantuml.api.MyRunnable; import net.sourceforge.plantuml.api.MyRunnable;
import net.sourceforge.plantuml.api.TimeoutExecutor; import net.sourceforge.plantuml.api.TimeoutExecutor;
public class ProcessRunner { public class ProcessRunner {
// http://steveliles.github.io/invoking_processes_from_java.html
public static long TIMEOUT = 15 * 60 * 1000L;
private final String[] cmd; private final String[] cmd;
@ -72,7 +71,9 @@ public class ProcessRunner {
this.state = ProcessState.RUNNING(); this.state = ProcessState.RUNNING();
final MainThread mainThread = new MainThread(cmd, dir, redirection, in); final MainThread mainThread = new MainThread(cmd, dir, redirection, in);
try { try {
final boolean done = new TimeoutExecutor(TIMEOUT).executeNow(mainThread); // http://steveliles.github.io/invoking_processes_from_java.html
final long timeoutMs = OptionFlags.getInstance().getTimeoutMs();
final boolean done = new TimeoutExecutor(timeoutMs).executeNow(mainThread);
} finally { } finally {
changeState.lock(); changeState.lock();
try { try {
@ -216,7 +217,7 @@ public class ProcessRunner {
} }
public String getString() { public String getString() {
if (sb==null) { if (sb == null) {
return ""; return "";
} }
return sb.toString(); return sb.toString();

View File

@ -74,7 +74,7 @@ public class EntityFactory {
} }
public boolean isHidden(ILeaf leaf) { public boolean isHidden(ILeaf leaf) {
if (hiddenTypes.contains(leaf.getEntityType())) { if (hiddenTypes.contains(leaf.getLeafType())) {
return true; return true;
} }
final Stereotype stereotype = leaf.getStereotype(); final Stereotype stereotype = leaf.getStereotype();

View File

@ -156,7 +156,7 @@ final class EntityImpl implements ILeaf, IGroup {
this.parentContainer = container; this.parentContainer = container;
} }
public LeafType getEntityType() { public LeafType getLeafType() {
return leafType; return leafType;
} }
@ -417,7 +417,7 @@ final class EntityImpl implements ILeaf, IGroup {
// ---- other // ---- other
public void overideImage(IEntityImage img, LeafType leafType) { public void overrideImage(IEntityImage img, LeafType leafType) {
checkGroup(); checkGroup();
this.svekImage = img; this.svekImage = img;
this.url = null; this.url = null;
@ -462,6 +462,9 @@ final class EntityImpl implements ILeaf, IGroup {
} }
public USymbol getUSymbol() { public USymbol getUSymbol() {
if (getLeafType() == LeafType.CIRCLE) {
return USymbol.INTERFACE;
}
if (symbol != null && stereotype != null && stereotype.getSprite() != null) { if (symbol != null && stereotype != null && stereotype.getSprite() != null) {
return symbol.withStereoAlignment(HorizontalAlignment.RIGHT); return symbol.withStereoAlignment(HorizontalAlignment.RIGHT);
} }

View File

@ -0,0 +1,91 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2017, Arnaud Roques
*
* Project Info: http://plantuml.com
*
* If you like this project or if you find it useful, you can support us at:
*
* http://plantuml.com/patreon (only 1$ per month!)
* http://plantuml.com/paypal
*
* This file is part of PlantUML.
*
* PlantUML is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PlantUML distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
* License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
*
* Original Author: Arnaud Roques
*
*
*/
package net.sourceforge.plantuml.definition;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import net.sourceforge.plantuml.AbstractPSystem;
import net.sourceforge.plantuml.FileFormatOption;
import net.sourceforge.plantuml.SpriteContainerEmpty;
import net.sourceforge.plantuml.core.DiagramDescription;
import net.sourceforge.plantuml.core.ImageData;
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.UDrawable;
import net.sourceforge.plantuml.ugraphic.ColorMapperIdentity;
import net.sourceforge.plantuml.ugraphic.ImageBuilder;
import net.sourceforge.plantuml.ugraphic.UFont;
import net.sourceforge.plantuml.ugraphic.UGraphic;
public class PSystemDefinition extends AbstractPSystem implements UDrawable {
private final List<String> lines = new ArrayList<String>();
private final String startLine;
public PSystemDefinition(String startLine) {
this.startLine = startLine;
}
public DiagramDescription getDescription() {
return new DiagramDescription("(Definition)");
}
@Override
final protected ImageData exportDiagramNow(OutputStream os, int num, FileFormatOption fileFormatOption)
throws IOException {
final ImageBuilder imageBuilder = new ImageBuilder(new ColorMapperIdentity(), 1, null, "", "", 0, 0, null,
false);
imageBuilder.setUDrawable(this);
return imageBuilder.writeImageTOBEMOVED(fileFormatOption, os);
}
public void drawU(UGraphic ug) {
final UFont font = UFont.sansSerif(14);
final FontConfiguration fc = new FontConfiguration(font, HtmlColorUtils.BLACK, HtmlColorUtils.BLACK, false);
Display.getWithNewlines(startLine).create(fc, HorizontalAlignment.LEFT, new SpriteContainerEmpty()).drawU(ug);
}
public void doCommandLine(String line) {
this.lines.add(line);
}
}

View File

@ -0,0 +1,60 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2017, Arnaud Roques
*
* Project Info: http://plantuml.com
*
* If you like this project or if you find it useful, you can support us at:
*
* http://plantuml.com/patreon (only 1$ per month!)
* http://plantuml.com/paypal
*
* This file is part of PlantUML.
*
* PlantUML is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PlantUML distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
* License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
*
* Original Author: Arnaud Roques
*
*
*/
package net.sourceforge.plantuml.definition;
import net.sourceforge.plantuml.command.PSystemBasicFactory;
import net.sourceforge.plantuml.core.DiagramType;
public class PSystemDefinitionFactory extends PSystemBasicFactory<PSystemDefinition> {
public PSystemDefinitionFactory() {
super(DiagramType.DEFINITION);
}
public PSystemDefinition init(String startLine) {
if (getDiagramType() == DiagramType.DEFINITION) {
return new PSystemDefinition(startLine);
}
return null;
}
@Override
public PSystemDefinition executeLine(PSystemDefinition system, String line) {
system.doCommandLine(line);
return system;
}
}

View File

@ -106,7 +106,7 @@ public class DescriptionDiagram extends AbstractEntityDiagram {
private boolean isUsecase() { private boolean isUsecase() {
for (ILeaf leaf : getLeafsvalues()) { for (ILeaf leaf : getLeafsvalues()) {
final LeafType type = leaf.getEntityType(); final LeafType type = leaf.getLeafType();
final USymbol usymbol = leaf.getUSymbol(); final USymbol usymbol = leaf.getUSymbol();
if (type == LeafType.USECASE || usymbol == USymbol.ACTOR) { if (type == LeafType.USECASE || usymbol == USymbol.ACTOR) {
return true; return true;
@ -121,7 +121,7 @@ public class DescriptionDiagram extends AbstractEntityDiagram {
final LeafType defaultType = isUsecase() ? LeafType.DESCRIPTION : LeafType.DESCRIPTION; final LeafType defaultType = isUsecase() ? LeafType.DESCRIPTION : LeafType.DESCRIPTION;
final USymbol defaultSymbol = isUsecase() ? USymbol.ACTOR : USymbol.INTERFACE; final USymbol defaultSymbol = isUsecase() ? USymbol.ACTOR : USymbol.INTERFACE;
for (ILeaf leaf : getLeafsvalues()) { for (ILeaf leaf : getLeafsvalues()) {
if (leaf.getEntityType() == LeafType.STILL_UNKNOWN) { if (leaf.getLeafType() == LeafType.STILL_UNKNOWN) {
leaf.muteToType(defaultType, defaultSymbol); leaf.muteToType(defaultType, defaultSymbol);
} }
} }

View File

@ -49,6 +49,7 @@ import net.sourceforge.plantuml.command.regex.RegexResult;
import net.sourceforge.plantuml.cucadiagram.Code; import net.sourceforge.plantuml.cucadiagram.Code;
import net.sourceforge.plantuml.cucadiagram.Display; import net.sourceforge.plantuml.cucadiagram.Display;
import net.sourceforge.plantuml.cucadiagram.IEntity; import net.sourceforge.plantuml.cucadiagram.IEntity;
import net.sourceforge.plantuml.cucadiagram.ILeaf;
import net.sourceforge.plantuml.cucadiagram.LeafType; import net.sourceforge.plantuml.cucadiagram.LeafType;
import net.sourceforge.plantuml.cucadiagram.Stereotype; import net.sourceforge.plantuml.cucadiagram.Stereotype;
import net.sourceforge.plantuml.descdiagram.DescriptionDiagram; import net.sourceforge.plantuml.descdiagram.DescriptionDiagram;
@ -163,6 +164,9 @@ public class CommandCreateElementFull extends SingleLineCommand2<DescriptionDiag
} }
display = StringUtils.eventuallyRemoveStartingAndEndingDoubleQuote(display); display = StringUtils.eventuallyRemoveStartingAndEndingDoubleQuote(display);
final String stereotype = arg.getLazzy("STEREOTYPE", 0); final String stereotype = arg.getLazzy("STEREOTYPE", 0);
if (existsWithBadType(diagram, code, type, usymbol)) {
return CommandExecutionResult.error("This element (" + code.getFullName() + ") is already defined");
}
final IEntity entity = diagram.getOrCreateLeaf(code, type, usymbol); final IEntity entity = diagram.getOrCreateLeaf(code, type, usymbol);
entity.setDisplay(Display.getWithNewlines(display)); entity.setDisplay(Display.getWithNewlines(display));
entity.setUSymbol(usymbol); entity.setUSymbol(usymbol);
@ -192,6 +196,20 @@ public class CommandCreateElementFull extends SingleLineCommand2<DescriptionDiag
return CommandExecutionResult.ok(); return CommandExecutionResult.ok();
} }
public static boolean existsWithBadType(DescriptionDiagram diagram, final Code code, LeafType type, USymbol usymbol) {
if (diagram.leafExist(code) == false) {
return false;
}
final ILeaf other = diagram.getLeafsget(code);
if (other.getLeafType() != type) {
return true;
}
if (other.getUSymbol() != usymbol) {
return true;
}
return false;
}
private char getCharEncoding(final String codeRaw) { private char getCharEncoding(final String codeRaw) {
return codeRaw != null && codeRaw.length() > 2 ? codeRaw.charAt(0) : 0; return codeRaw != null && codeRaw.length() > 2 ? codeRaw.charAt(0) : 0;
} }

View File

@ -141,6 +141,9 @@ public class CommandCreateElementMultilines extends CommandMultilines2<Descripti
final String stereotype = line0.get("STEREO", 0); final String stereotype = line0.get("STEREO", 0);
if (CommandCreateElementFull.existsWithBadType(diagram, code, type, usymbol)) {
return CommandExecutionResult.error("This element (" + code.getFullName() + ") is already defined");
}
final ILeaf result = diagram.createLeaf(code, display, type, usymbol); final ILeaf result = diagram.createLeaf(code, display, type, usymbol);
result.setUSymbol(usymbol); result.setUSymbol(usymbol);
if (stereotype != null) { if (stereotype != null) {

View File

@ -109,7 +109,7 @@ public class CommandLinkElement extends SingleLineCommand2<DescriptionDiagram> {
if (head1.equals("(0")) { if (head1.equals("(0")) {
d1 = LinkDecor.CIRCLE_CONNECT; d1 = LinkDecor.CIRCLE_CONNECT;
} else if (head1.equals("#")) { } else if (head1.equals("#")) {
d1 = LinkDecor.SQUARRE; d1 = LinkDecor.SQUARE;
} else if (head1.equals("0")) { } else if (head1.equals("0")) {
d1 = LinkDecor.CIRCLE; d1 = LinkDecor.CIRCLE;
} else if (head1.equals("(")) { } else if (head1.equals("(")) {
@ -133,7 +133,7 @@ public class CommandLinkElement extends SingleLineCommand2<DescriptionDiagram> {
if (head2.equals("0)")) { if (head2.equals("0)")) {
d2 = LinkDecor.CIRCLE_CONNECT; d2 = LinkDecor.CIRCLE_CONNECT;
} else if (head2.equals("#")) { } else if (head2.equals("#")) {
d2 = LinkDecor.SQUARRE; d2 = LinkDecor.SQUARE;
} else if (head2.equals("0")) { } else if (head2.equals("0")) {
d2 = LinkDecor.CIRCLE; d2 = LinkDecor.CIRCLE;
} else if (head2.equals(")")) { } else if (head2.equals(")")) {

View File

@ -42,6 +42,7 @@ import net.sourceforge.plantuml.command.CommandExecutionResult;
import net.sourceforge.plantuml.command.SingleLineCommand2; import net.sourceforge.plantuml.command.SingleLineCommand2;
import net.sourceforge.plantuml.command.regex.RegexConcat; 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.RegexOr;
import net.sourceforge.plantuml.command.regex.RegexResult; import net.sourceforge.plantuml.command.regex.RegexResult;
import net.sourceforge.plantuml.cucadiagram.Code; import net.sourceforge.plantuml.cucadiagram.Code;
import net.sourceforge.plantuml.cucadiagram.Display; import net.sourceforge.plantuml.cucadiagram.Display;
@ -62,10 +63,31 @@ public class CommandPackageWithUSymbol extends SingleLineCommand2<AbstractEntity
private static RegexConcat getRegexConcat() { private static RegexConcat getRegexConcat() {
return new RegexConcat(new RegexLeaf("^"), // return new RegexConcat(new RegexLeaf("^"), //
new RegexLeaf("SYMBOL", "(package|rectangle|node|artifact|folder|file|frame|cloud|database|storage|component|card|together)"), // new RegexLeaf("SYMBOL",
"(package|rectangle|node|artifact|folder|file|frame|cloud|database|storage|component|card|together)"), //
new RegexLeaf("[%s]+"), // new RegexLeaf("[%s]+"), //
new RegexLeaf("NAME", "([%g][^%g]+[%g]|[^#%s{}]*)"), // new RegexOr(//
new RegexLeaf("AS", "(?:[%s]+as[%s]+([\\p{L}0-9_.]+))?"), // new RegexConcat( //
new RegexLeaf("DISPLAY1", "([%g][^%g]+[%g])"), //
new RegexLeaf("STEREOTYPE1", "(?:[%s]+(\\<\\<.+\\>\\>))?"), //
new RegexLeaf("[%s]*as[%s]+"), //
new RegexLeaf("CODE1", "([^#%s{}]+)") //
), //
new RegexConcat( //
new RegexLeaf("CODE2", "([^#%s{}%g]+)"), //
new RegexLeaf("STEREOTYPE2", "(?:[%s]+(\\<\\<.+\\>\\>))?"), //
new RegexLeaf("[%s]*as[%s]+"), //
new RegexLeaf("DISPLAY2", "([%g][^%g]+[%g])") //
), //
new RegexConcat( //
new RegexLeaf("DISPLAY3", "([^#%s{}%g]+)"), //
new RegexLeaf("STEREOTYPE3", "(?:[%s]+(\\<\\<.+\\>\\>))?"), //
new RegexLeaf("[%s]*as[%s]+"), //
new RegexLeaf("CODE3", "([^#%s{}%g]+)") //
), //
new RegexLeaf("CODE8", "([%g][^%g]+[%g])"), //
new RegexLeaf("CODE9", "([^#%s{}%g]*)") //
), //
new RegexLeaf("[%s]*"), // new RegexLeaf("[%s]*"), //
new RegexLeaf("STEREOTYPE", "(\\<\\<.*\\>\\>)?"), // new RegexLeaf("STEREOTYPE", "(\\<\\<.*\\>\\>)?"), //
new RegexLeaf("[%s]*"), // new RegexLeaf("[%s]*"), //
@ -77,24 +99,25 @@ public class CommandPackageWithUSymbol extends SingleLineCommand2<AbstractEntity
@Override @Override
protected CommandExecutionResult executeArg(AbstractEntityDiagram diagram, RegexResult arg) { protected CommandExecutionResult executeArg(AbstractEntityDiagram diagram, RegexResult arg) {
final String codeRaw = StringUtils.eventuallyRemoveStartingAndEndingDoubleQuote(arg.getLazzy("CODE", 0));
final String displayRaw = StringUtils.eventuallyRemoveStartingAndEndingDoubleQuote(arg.getLazzy("DISPLAY", 0));
final Code code; final Code code;
final String display; final String display;
final String name = StringUtils.eventuallyRemoveStartingAndEndingDoubleQuote(arg.get("NAME", 0)); if (codeRaw.length() == 0) {
if (arg.get("AS", 0) == null) { code = UniqueSequence.getCode("##");
if (name.length() == 0) { display = null;
code = UniqueSequence.getCode("##");
display = null;
} else {
code = Code.of(name);
display = code.getFullName();
}
} else { } else {
display = name; code = Code.of(codeRaw);
code = Code.of(arg.get("AS", 0)); if (displayRaw == null) {
display = code.getFullName();
} else {
display = displayRaw;
}
} }
final IGroup currentPackage = diagram.getCurrentGroup(); final IGroup currentPackage = diagram.getCurrentGroup();
final IEntity p = diagram.getOrCreateGroup(code, Display.getWithNewlines(display), final IEntity p = diagram.getOrCreateGroup(code, Display.getWithNewlines(display), GroupType.PACKAGE,
GroupType.PACKAGE, currentPackage); currentPackage);
p.setUSymbol(USymbol.getFromString(arg.get("SYMBOL", 0))); p.setUSymbol(USymbol.getFromString(arg.get("SYMBOL", 0)));
final String stereotype = arg.get("STEREOTYPE", 0); final String stereotype = arg.get("STEREOTYPE", 0);
if (stereotype != null) { if (stereotype != null) {
@ -102,7 +125,8 @@ public class CommandPackageWithUSymbol extends SingleLineCommand2<AbstractEntity
} }
final String color = arg.get("COLOR", 0); final String color = arg.get("COLOR", 0);
if (color != null) { if (color != null) {
p.setSpecificColorTOBEREMOVED(ColorType.BACK, diagram.getSkinParam().getIHtmlColorSet().getColorIfValid(color)); p.setSpecificColorTOBEREMOVED(ColorType.BACK,
diagram.getSkinParam().getIHtmlColorSet().getColorIfValid(color));
} }
return CommandExecutionResult.ok(); return CommandExecutionResult.ok();
} }

View File

@ -159,7 +159,7 @@ public class PSystemColors extends AbstractPSystem implements UDrawable {
ug = ug.apply(new UTranslate(centerHexa(i, j))); ug = ug.apply(new UTranslate(centerHexa(i, j)));
ug.draw(hexa); ug.draw(hexa);
final UFont font = new UFont("SansSerif", Font.BOLD, 14); final UFont font = UFont.sansSerif(14).bold();
TextBlock tt = getTextName(font, colorName, color); TextBlock tt = getTextName(font, colorName, color);
Dimension2D dimText = tt.calculateDimension(ug.getStringBounder()); Dimension2D dimText = tt.calculateDimension(ug.getStringBounder());
@ -246,7 +246,7 @@ public class PSystemColors extends AbstractPSystem implements UDrawable {
} }
private void drawFull(UGraphic ug) { private void drawFull(UGraphic ug) {
final UFont font = new UFont("SansSerif", Font.BOLD, 14); final UFont font = UFont.sansSerif(14).bold();
ug = ug.apply(new UChangeColor(HtmlColorUtils.BLACK)); ug = ug.apply(new UChangeColor(HtmlColorUtils.BLACK));
int i = 0; int i = 0;

View File

@ -71,7 +71,7 @@ public class ActivityBox extends AbstractTextBlock {
this.tile = tile; this.tile = tile;
this.id = id; this.id = id;
this.label = label; this.label = label;
final UFont font = new UFont("Serif", Font.PLAIN, 14); final UFont font = UFont.serif(14);
final FontConfiguration fc = FontConfiguration.blackBlueTrue(font); final FontConfiguration fc = FontConfiguration.blackBlueTrue(font);
tb = Display.create(label).create(fc, HorizontalAlignment.LEFT, new SpriteContainerEmpty()); tb = Display.create(label).create(fc, HorizontalAlignment.LEFT, new SpriteContainerEmpty());
} }

Some files were not shown because too many files have changed in this diff Show More