This commit is contained in:
Arnaud Roques 2022-12-13 18:30:41 +01:00
parent 117102bb65
commit 80217d8c90
34 changed files with 1057 additions and 72 deletions

View File

@ -85,6 +85,7 @@ import net.sourceforge.plantuml.openiconic.PSystemListOpenIconicFactory;
import net.sourceforge.plantuml.openiconic.PSystemOpenIconicFactory;
import net.sourceforge.plantuml.oregon.PSystemOregonFactory;
import net.sourceforge.plantuml.project.GanttDiagramFactory;
import net.sourceforge.plantuml.regex.PSystemRegexFactory;
import net.sourceforge.plantuml.salt.PSystemSaltFactory2;
import net.sourceforge.plantuml.security.SecurityProfile;
import net.sourceforge.plantuml.security.SecurityUtils;
@ -212,7 +213,6 @@ public class PSystemBuilder {
factories.add(new PSystemXearthFactory());
}
factories.add(new GanttDiagramFactory(DiagramType.GANTT));
// factories.add(new GanttDiagramFactory(DiagramType.UML));
GanttDiagramFactory.clearCache();
factories.add(new FlowDiagramFactory());
// factories.add(new PSystemTreeFactory(DiagramType.JUNGLE));
@ -227,6 +227,7 @@ public class PSystemBuilder {
factories.add(new YamlDiagramFactory());
factories.add(new HclDiagramFactory());
factories.add(new PSystemEbnfFactory());
factories.add(new PSystemRegexFactory());
}
private boolean isOk(Diagram ps) {

View File

@ -41,12 +41,12 @@ abstract class ScaleProtected implements Scale {
final public double getScale(double width, double height) {
final double result = getScaleInternal(width, height);
if (result <= 0) {
if (result <= 0)
return 1;
}
if (result > 4) {
if (result > 4)
return 4;
}
return result;
}

View File

@ -39,7 +39,7 @@ import net.sourceforge.plantuml.style.SName;
public enum UmlDiagramType {
SEQUENCE, STATE, CLASS, OBJECT, ACTIVITY, DESCRIPTION, COMPOSITE, FLOW, TIMING, BPM, NWDIAG, MINDMAP, WBS, WIRE,
HELP, GANTT, SALT, JSON, GIT, BOARD, YAML, HCL, EBNF;
HELP, GANTT, SALT, JSON, GIT, BOARD, YAML, HCL, EBNF, REGEX;
public SName getStyleName() {
if (this == SEQUENCE)
@ -93,6 +93,9 @@ public enum UmlDiagramType {
if (this == EBNF)
return SName.ebnf;
if (this == REGEX)
return SName.regex;
return SName.activityDiagram;
}
}

View File

@ -67,14 +67,14 @@ public class CommandScale extends SingleLineCommand2<AbstractPSystem> {
@Override
protected CommandExecutionResult executeArg(AbstractPSystem diagram, LineLocation location, RegexResult arg) {
double scale = Double.parseDouble(arg.get("SCALE", 0));
if (scale == 0) {
if (scale == 0)
return CommandExecutionResult.error("Scale cannot be zero");
}
if (arg.get("DIV", 0) != null) {
final double div = Double.parseDouble(arg.get("DIV", 0));
if (div == 0) {
if (div == 0)
return CommandExecutionResult.error("Scale cannot be zero");
}
scale /= div;
}
diagram.setScale(new ScaleSimple(scale));

View File

@ -39,7 +39,7 @@ import net.sourceforge.plantuml.utils.StartUtils;
public enum DiagramType {
UML, BPM, DITAA, DOT, PROJECT, JCCKIT, SALT, FLOW, CREOLE, JUNGLE, CUTE, MATH, LATEX, DEFINITION, GANTT, NW,
MINDMAP, WBS, WIRE, JSON, GIT, BOARD, YAML, HCL, EBNF, UNKNOWN;
MINDMAP, WBS, WIRE, JSON, GIT, BOARD, YAML, HCL, EBNF, REGEX, UNKNOWN;
static public DiagramType getTypeFromArobaseStart(String s) {
s = s.toLowerCase();
@ -121,6 +121,9 @@ public enum DiagramType {
if (StartUtils.startsWithSymbolAnd("startebnf", s))
return EBNF;
if (StartUtils.startsWithSymbolAnd("startregex", s))
return REGEX;
return UNKNOWN;
}
}

View File

@ -84,9 +84,9 @@ public class AtomImg extends AbstractAtom implements Atom {
public static Atom createQrcode(String flash, double scale) {
final FlashCodeUtils utils = FlashCodeFactory.getFlashCodeUtils();
BufferedImage im = utils.exportFlashcode(flash, Color.BLACK, Color.WHITE);
if (im == null) {
if (im == null)
im = new BufferedImage(10, 10, BufferedImage.TYPE_INT_RGB);
}
return new AtomImg(
new UImage(new PixelImage(im, AffineTransformType.TYPE_NEAREST_NEIGHBOR)).scale(scale).getImage(1), 1,
null, null);
@ -120,38 +120,38 @@ public class AtomImg extends AbstractAtom implements Atom {
try {
// Check if valid URL
if (src.startsWith("http:") || src.startsWith("https:")) {
if (src.endsWith(".svg"))
if (src.endsWith(".svg"))
return buildSvgFromUrl(src, fc, SURL.create(src), scale, url);
return buildRasterFromUrl(src, fc, SURL.create(src), scale, url);
}
final SFile f = FileSystem.getInstance().getFile(src);
if (f.exists() == false) {
if (SecurityUtils.getSecurityProfile() == SecurityProfile.UNSECURE)
if (SecurityUtils.getSecurityProfile() == SecurityProfile.UNSECURE)
return AtomTextUtils.createLegacy("(File not found: " + f.getPrintablePath() + ")", fc);
return AtomTextUtils.createLegacy("(Cannot decode)", fc);
}
if (f.getName().endsWith(".svg")) {
final String tmp = FileUtils.readSvg(f);
if (tmp == null)
if (tmp == null)
return AtomTextUtils.createLegacy("(Cannot decode)", fc);
return new AtomImgSvg(new TileImageSvg(tmp, scale));
}
final BufferedImage read = f.readRasterImageFromFile();
if (read == null) {
if (SecurityUtils.getSecurityProfile() == SecurityProfile.UNSECURE)
if (SecurityUtils.getSecurityProfile() == SecurityProfile.UNSECURE)
return AtomTextUtils.createLegacy("(Cannot decode: " + f.getPrintablePath() + ")", fc);
return AtomTextUtils.createLegacy("(Cannot decode)", fc);
}
return new AtomImg(f.readRasterImageFromFile(), scale, url, src);
} catch (IOException e) {
Logme.error(e);
if (SecurityUtils.getSecurityProfile() == SecurityProfile.UNSECURE)
if (SecurityUtils.getSecurityProfile() == SecurityProfile.UNSECURE)
return AtomTextUtils.createLegacy("ERROR " + e.toString(), fc);
return AtomTextUtils.createLegacy("ERROR", fc);
}
}
@ -159,33 +159,33 @@ public class AtomImg extends AbstractAtom implements Atom {
private static Atom buildRasterFromData(String source, final FontConfiguration fc, final byte[] data, double scale,
Url url) throws IOException {
final BufferedImage read = SImageIO.read(data);
if (read == null) {
if (read == null)
return AtomTextUtils.createLegacy("(Cannot decode: " + source + ")", fc);
}
return new AtomImg(read, scale, url, null);
}
private static Atom buildRasterFromUrl(String text, final FontConfiguration fc, SURL source, double scale, Url url)
throws IOException {
if (source == null) {
if (source == null)
return AtomTextUtils.createLegacy("(Cannot decode: " + text + ")", fc);
}
final BufferedImage read = source.readRasterImageFromURL();
if (read == null) {
if (read == null)
return AtomTextUtils.createLegacy("(Cannot decode: " + text + ")", fc);
}
return new AtomImg(read, scale, url, "http");
}
private static Atom buildSvgFromUrl(String text, final FontConfiguration fc, SURL source, double scale, Url url)
throws IOException {
if (source == null) {
if (source == null)
return AtomTextUtils.createLegacy("(Cannot decode SVG: " + text + ")", fc);
}
final byte[] read = source.getBytes();
if (read == null) {
if (read == null)
return AtomTextUtils.createLegacy("(Cannot decode SVG: " + text + ")", fc);
}
return new AtomImgSvg(new TileImageSvg(new String(read, UTF_8), scale));
}
@ -200,14 +200,15 @@ public class AtomImg extends AbstractAtom implements Atom {
}
public void drawU(UGraphic ug) {
if (url != null) {
if (url != null)
ug.startUrl(url);
}
ug.draw(new UImage(new PixelImage(image, AffineTransformType.TYPE_BILINEAR)).withRawFileName(rawFileName)
.scale(scale));
if (url != null) {
if (url != null)
ug.closeUrl();
}
}
}

View File

@ -35,7 +35,7 @@
*/
package net.sourceforge.plantuml.ebnf;
interface CharIterator {
public interface CharIterator {
char peek(int ahead);
void next();

View File

@ -37,7 +37,7 @@ package net.sourceforge.plantuml.ebnf;
import net.sourceforge.plantuml.command.BlocLines;
class CharIteratorImpl implements CharIterator {
public class CharIteratorImpl implements CharIterator {
final private BlocLines data;
private int line = 0;

View File

@ -42,6 +42,7 @@ import net.sourceforge.plantuml.awt.geom.XDimension2D;
import net.sourceforge.plantuml.graphic.StringBounder;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.UTranslate;
import net.sourceforge.plantuml.ugraphic.color.HColor;
public class ETileAlternation extends ETile {

View File

@ -68,6 +68,10 @@ public class ETileBox extends ETile {
private String commentAbove;
private String commentBelow;
public ETileBox mergeWith(ETileBox other) {
return new ETileBox(this.value + other.value, symbol, fc, style, colorSet, skinParam);
}
public ETileBox(String value, Symbol symbol, FontConfiguration fc, Style style, HColorSet colorSet,
ISkinParam skinParam) {
this.symbol = symbol;
@ -225,4 +229,8 @@ public class ETileBox extends ETile {
return value;
}
public final Symbol getSymbol() {
return symbol;
}
}

View File

@ -52,6 +52,10 @@ public class ETileConcatenation extends ETile {
tiles.add(0, tile);
}
public void overideFirst(ETile tile) {
tiles.set(0, tile);
}
@Override
public void drawU(UGraphic ug) {
final StringBounder stringBounder = ug.getStringBounder();
@ -104,4 +108,8 @@ public class ETileConcatenation extends ETile {
return width;
}
public ETile getFirst() {
return tiles.get(0);
}
}

View File

@ -39,15 +39,11 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import net.sourceforge.plantuml.Direction;
import net.sourceforge.plantuml.ISkinParam;
import net.sourceforge.plantuml.activitydiagram3.ftile.vcompact.FloatingNote;
import net.sourceforge.plantuml.awt.geom.XDimension2D;
import net.sourceforge.plantuml.awt.geom.XPoint2D;
import net.sourceforge.plantuml.cucadiagram.Display;
import net.sourceforge.plantuml.graphic.FontConfiguration;
import net.sourceforge.plantuml.graphic.HorizontalAlignment;
import net.sourceforge.plantuml.graphic.StringBounder;
import net.sourceforge.plantuml.graphic.TextBlock;
import net.sourceforge.plantuml.graphic.TextBlockUtils;
import net.sourceforge.plantuml.style.PName;

View File

@ -85,9 +85,9 @@ public class PSystemWelcome extends PlainDiagram {
}
public TextBlockBackcolored getGraphicStrings() {
if (position != null) {
if (position != null)
return GraphicStrings.createBlackOnWhite(strings, PSystemVersion.getPlantumlImage(), position);
}
return GraphicStrings.createBlackOnWhite(strings);
}

View File

@ -78,7 +78,7 @@ public class HclDiagramFactory extends PSystemAbstractFactory {
} catch (Exception e) {
Logme.error(e);
}
final JsonDiagram result = new JsonDiagram(source, UmlDiagramType.HCL, data, highlighted);
final JsonDiagram result = new JsonDiagram(source, UmlDiagramType.HCL, data, highlighted, styleExtractor);
// if (styleExtractor != null) {
// styleExtractor.applyStyles(result.getSkinParam());
// final String title = styleExtractor.getTitle();

View File

@ -49,6 +49,7 @@ import net.sourceforge.plantuml.json.JsonObject;
import net.sourceforge.plantuml.json.JsonString;
import net.sourceforge.plantuml.json.JsonValue;
// https://github.com/hashicorp/hcl
public class HclParser {
private final List<HclTerm> terms = new ArrayList<HclTerm>();

View File

@ -39,6 +39,7 @@ import java.io.OutputStream;
import java.util.List;
import net.sourceforge.plantuml.FileFormatOption;
import net.sourceforge.plantuml.ScaleSimple;
import net.sourceforge.plantuml.TitledDiagram;
import net.sourceforge.plantuml.UmlDiagramType;
import net.sourceforge.plantuml.awt.geom.XDimension2D;
@ -60,14 +61,18 @@ import net.sourceforge.plantuml.ugraphic.MinMax;
import net.sourceforge.plantuml.ugraphic.UFont;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.color.HColor;
import net.sourceforge.plantuml.ugraphic.hand.UGraphicHandwritten;
public class JsonDiagram extends TitledDiagram {
private final JsonValue root;
private final List<String> highlighted;
private final boolean handwritten;
public JsonDiagram(UmlSource source, UmlDiagramType type, JsonValue json, List<String> highlighted) {
public JsonDiagram(UmlSource source, UmlDiagramType type, JsonValue json, List<String> highlighted,
StyleExtractor styleExtractor) {
super(source, type, null);
this.handwritten = styleExtractor.isHandwritten();
if (json != null && (json.isString() || json.isBoolean() || json.isNumber())) {
this.root = new JsonArray();
((JsonArray) this.root).add(json);
@ -75,6 +80,7 @@ public class JsonDiagram extends TitledDiagram {
this.root = json;
}
this.highlighted = highlighted;
setScale(new ScaleSimple(styleExtractor.getScale()));
}
public DiagramDescription getDescription() {
@ -95,6 +101,8 @@ public class JsonDiagram extends TitledDiagram {
}
private void drawInternal(UGraphic ug) {
if (handwritten)
ug = new UGraphicHandwritten(ug);
if (root == null) {
final Display display = Display
.getWithNewlines("Your data does not sound like " + getUmlDiagramType() + " data");

View File

@ -85,7 +85,7 @@ public class JsonDiagramFactory extends PSystemAbstractFactory {
} catch (ParseException e) {
json = null;
}
final JsonDiagram result = new JsonDiagram(source, UmlDiagramType.JSON, json, highlighted);
final JsonDiagram result = new JsonDiagram(source, UmlDiagramType.JSON, json, highlighted, styleExtractor);
if (styleExtractor != null)
styleExtractor.applyStyles(result.getSkinParam());

View File

@ -51,27 +51,42 @@ public class StyleExtractor {
private final List<String> list = new ArrayList<>();
private final List<StringLocated> style = new ArrayList<>();
private String title = null;
private boolean handwritten = false;
private double scale = 1;
public StyleExtractor(Iterator<StringLocated> data) {
while (data.hasNext()) {
StringLocated line = data.next();
if (startStyle(line)) {
final String s = line.getString().trim();
if (s.length() == 0)
continue;
if (startStyle(s)) {
while (data.hasNext()) {
style.add(line);
if (endStyle(line))
break;
line = data.next();
}
} else if (line.getString().trim().startsWith("!assume ")) {
} else if (list.size() >= 1 && s.startsWith("!assume ")) {
// Ignore
} else if (line.getString().trim().startsWith("!pragma ")) {
} else if (list.size() >= 1 && s.startsWith("!pragma ")) {
// Ignore
} else if (line.getString().trim().startsWith("hide ")) {
} else if (list.size() >= 1 && s.startsWith("hide ")) {
// Ignore
} else if (line.getString().trim().startsWith("title ")) {
this.title = line.getString().trim().substring("title ".length()).trim();
} else if (line.getString().trim().startsWith("skinparam ")) {
if (line.getString().trim().contains("{")) {
} else if (list.size() >= 1 && s.startsWith("scale ")) {
// Ignore
try {
final double v = Double.parseDouble(s.replaceAll("\\D", ""));
if (v > 0)
scale = v;
} catch (Exception e) {
}
} else if (list.size() >= 1 && s.startsWith("title ")) {
this.title = s.substring("title ".length()).trim();
} else if (list.size() >= 1 && s.startsWith("skinparam ")) {
if (s.contains("handwritten") && s.contains("true"))
handwritten = true;
if (s.contains("{")) {
while (data.hasNext()) {
if (line.getString().trim().equals("}"))
break;
@ -82,10 +97,11 @@ public class StyleExtractor {
list.add(line.getString());
}
}
}
private boolean startStyle(StringLocated line) {
return line.getString().trim().equals("<style>");
private boolean startStyle(String line) {
return line.equals("<style>");
}
private boolean endStyle(StringLocated line) {
@ -110,4 +126,12 @@ public class StyleExtractor {
return title;
}
public final boolean isHandwritten() {
return handwritten;
}
public double getScale() {
return scale;
}
}

View File

@ -0,0 +1,72 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2023, 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.regex;
import java.util.Collections;
import net.sourceforge.plantuml.LineLocation;
import net.sourceforge.plantuml.StringLocated;
import net.sourceforge.plantuml.command.BlocLines;
import net.sourceforge.plantuml.command.CommandExecutionResult;
import net.sourceforge.plantuml.command.SingleLineCommand2;
import net.sourceforge.plantuml.command.regex.IRegex;
import net.sourceforge.plantuml.command.regex.RegexConcat;
import net.sourceforge.plantuml.command.regex.RegexLeaf;
import net.sourceforge.plantuml.command.regex.RegexResult;
import net.sourceforge.plantuml.ugraphic.color.NoSuchColorException;
public class CommandRegexfSingleLine extends SingleLineCommand2<PSystemRegex> {
public CommandRegexfSingleLine() {
super(true, getRegexConcat());
}
static IRegex getRegexConcat() {
return RegexConcat.build(CommandRegexfSingleLine.class.getName(), RegexLeaf.start(), //
RegexLeaf.spaceZeroOrMore(), //
new RegexLeaf("LINE", "(.*)"), //
RegexLeaf.end());
}
@Override
protected CommandExecutionResult executeArg(PSystemRegex diagram, LineLocation location, RegexResult arg)
throws NoSuchColorException {
final String line = arg.get("LINE", 0);
final StringLocated string = new StringLocated(line, location);
return diagram.addBlocLines(BlocLines.from(Collections.singletonList(string)));
}
}

View File

@ -0,0 +1,284 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2023, 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.regex;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;
import net.sourceforge.plantuml.FileFormatOption;
import net.sourceforge.plantuml.ISkinParam;
import net.sourceforge.plantuml.TitledDiagram;
import net.sourceforge.plantuml.UmlDiagramType;
import net.sourceforge.plantuml.awt.geom.XDimension2D;
import net.sourceforge.plantuml.command.BlocLines;
import net.sourceforge.plantuml.command.CommandExecutionResult;
import net.sourceforge.plantuml.core.DiagramDescription;
import net.sourceforge.plantuml.core.ImageData;
import net.sourceforge.plantuml.core.UmlSource;
import net.sourceforge.plantuml.ebnf.CharIterator;
import net.sourceforge.plantuml.ebnf.CharIteratorImpl;
import net.sourceforge.plantuml.ebnf.ETile;
import net.sourceforge.plantuml.ebnf.ETileAlternation;
import net.sourceforge.plantuml.ebnf.ETileBox;
import net.sourceforge.plantuml.ebnf.ETileConcatenation;
import net.sourceforge.plantuml.ebnf.ETileOneOrMore;
import net.sourceforge.plantuml.ebnf.ETileOptional;
import net.sourceforge.plantuml.ebnf.ETileZeroOrMore;
import net.sourceforge.plantuml.ebnf.Symbol;
import net.sourceforge.plantuml.ebnf.TextBlockable;
import net.sourceforge.plantuml.graphic.AbstractTextBlock;
import net.sourceforge.plantuml.graphic.FontConfiguration;
import net.sourceforge.plantuml.graphic.StringBounder;
import net.sourceforge.plantuml.graphic.TextBlock;
import net.sourceforge.plantuml.graphic.TextBlockUtils;
import net.sourceforge.plantuml.style.PName;
import net.sourceforge.plantuml.style.Style;
import net.sourceforge.plantuml.svek.TextBlockBackcolored;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.color.HColor;
import net.sourceforge.plantuml.ugraphic.color.HColorSet;
import net.sourceforge.plantuml.ugraphic.color.HColors;
public class PSystemRegex extends TitledDiagram {
private final List<TextBlockable> expressions = new ArrayList<>();
public PSystemRegex(UmlSource source) {
super(source, UmlDiagramType.REGEX, null);
final ISkinParam skinParam = getSkinParam();
this.style = ETile.getStyleSignature().getMergedStyle(skinParam.getCurrentStyleBuilder());
this.fontConfiguration = style.getFontConfiguration(skinParam.getIHtmlColorSet());
this.colorSet = skinParam.getIHtmlColorSet();
this.lineColor = style.value(PName.LineColor).asColor(skinParam.getIHtmlColorSet());
}
public DiagramDescription getDescription() {
return new DiagramDescription("(Regular Expression)");
}
private final Deque<ETile> stack = new ArrayDeque<>();
private final FontConfiguration fontConfiguration;
private final Style style;
private final HColorSet colorSet;
private final HColor lineColor;
// public CommandExecutionResult addBlocLines(BlocLines blines, String commentAbove, String commentBelow) {
// final boolean isCompact = getPragma().isDefine("compact");
// final CharIterator it = new CharIteratorImpl(blines);
// final EbnfExpression tmp1 = EbnfExpression.create(it, isCompact, commentAbove, commentBelow);
// if (tmp1.isEmpty())
// return CommandExecutionResult.error("Unparsable expression");
// expressions.add(tmp1);
// return CommandExecutionResult.ok();
//
// }
//
// public CommandExecutionResult addNote(final Display note, Colors colors) {
// expressions.add(new TextBlockable() {
// @Override
// public TextBlock getUDrawable(ISkinParam skinParam) {
// final FloatingNote f = FloatingNote.create(note, skinParam, SName.ebnf);
// return TextBlockUtils.withMargin(f, 0, 0, 5, 15);
// }
// });
// return CommandExecutionResult.ok();
// }
@Override
protected ImageData exportDiagramNow(OutputStream os, int index, FileFormatOption fileFormatOption)
throws IOException {
return createImageBuilder(fileFormatOption).drawable(getTextBlock()).write(os);
}
private TextBlockBackcolored getTextBlock() {
// while (stack.size() > 1)
// concatenation();
final ETile peekFirst = stack.peekFirst();
final TextBlock tb = new AbstractTextBlock() {
@Override
public void drawU(UGraphic ug) {
peekFirst.drawU(ug.apply(HColors.BLACK));
}
@Override
public XDimension2D calculateDimension(StringBounder stringBounder) {
return peekFirst.calculateDimension(stringBounder);
}
};
return TextBlockUtils.addBackcolor(tb, null);
}
public CommandExecutionResult addBlocLines(BlocLines from) {
final CharIterator it = new CharIteratorImpl(from);
final List<ReToken> parsed1 = RegexExpression.parse(it);
System.err.println("parsed1=" + parsed1);
final List<ReToken> parsed2 = addImplicitConcatenation(parsed1);
System.err.println("parsed2=" + parsed2);
final ShuntingYard shuntingYard = new ShuntingYard(parsed2.iterator());
final List<ReToken> result = shuntingYard.getOuputQueue();
System.err.println("result=" + result);
for (ReToken token : result)
if (token.getType() == ReTokenType.SIMPLE_CHAR)
push(token, Symbol.TERMINAL_STRING1);
else if (token.getType() == ReTokenType.ESCAPED_CHAR)
push(token, Symbol.TERMINAL_STRING1);
else if (token.getType() == ReTokenType.GROUP)
push(token, Symbol.SPECIAL_SEQUENCE);
else if (token.getType() == ReTokenType.CLASS)
push(token, Symbol.LITTERAL);
else if (token.getType() == ReTokenType.ANCHOR)
push(token, Symbol.LITTERAL);
else if (token.getType() == ReTokenType.CONCATENATION_IMPLICIT)
concatenation();
else if (token.getType() == ReTokenType.ALTERNATIVE)
alternation();
else if (token.getType() == ReTokenType.QUANTIFIER && token.getData().equals("*"))
repetitionZeroOrMore(false);
else if (token.getType() == ReTokenType.QUANTIFIER && token.getData().equals("+"))
repetitionOneOrMore();
else if (token.getType() == ReTokenType.QUANTIFIER && token.getData().equals("?"))
optional();
else
throw new UnsupportedOperationException(token.toString());
return CommandExecutionResult.ok();
}
private List<ReToken> addImplicitConcatenation(List<ReToken> list) {
final List<ReToken> result = new ArrayList<>();
for (ReToken token : list) {
if (result.size() > 0
&& ReTokenType.needImplicitConcatenation(result.get(result.size() - 1).getType(), token.getType()))
result.add(new ReToken(ReTokenType.CONCATENATION_IMPLICIT, ""));
result.add(token);
}
return result;
}
private void push(ReToken element, Symbol type) {
// final Symbol type = Symbol.LITTERAL;
stack.addFirst(new ETileBox(element.getData(), type, fontConfiguration, style, colorSet, getSkinParam()));
}
private void repetitionZeroOrMore(boolean isCompact) {
final ETile arg1 = stack.removeFirst();
if (isCompact)
stack.addFirst(new ETileZeroOrMore(arg1));
else
stack.addFirst(new ETileOptional(new ETileOneOrMore(arg1), getSkinParam()));
}
private void optional() {
final ETile arg1 = stack.removeFirst();
stack.addFirst(new ETileOptional(arg1, getSkinParam()));
}
private void repetitionOneOrMore() {
final ETile arg1 = stack.removeFirst();
stack.addFirst(new ETileOneOrMore(arg1));
}
private void alternation() {
final ETile arg1 = stack.removeFirst();
final ETile arg2 = stack.removeFirst();
if (arg1 instanceof ETileAlternation) {
arg1.push(arg2);
stack.addFirst(arg1);
} else if (arg2 instanceof ETileAlternation) {
arg2.push(arg1);
stack.addFirst(arg2);
} else {
final ETile concat = new ETileAlternation();
concat.push(arg1);
concat.push(arg2);
stack.addFirst(concat);
}
}
private void concatenation() {
final ETile arg1 = stack.removeFirst();
final ETile arg2 = stack.removeFirst();
if (isBoxMergeable(arg1) && isBoxMergeable(arg2)) {
final ETileBox box1 = (ETileBox) arg1;
final ETileBox box2 = (ETileBox) arg2;
stack.addFirst(box2.mergeWith(box1));
return;
}
if (isConcatenation1Mergeable(arg1) && isBoxMergeable(arg2)) {
final ETileConcatenation concat1 = (ETileConcatenation) arg1;
final ETileBox box1 = (ETileBox) concat1.getFirst();
final ETileBox box2 = (ETileBox) arg2;
concat1.overideFirst(box2.mergeWith(box1));
stack.addFirst(concat1);
return;
}
if (arg1 instanceof ETileConcatenation) {
arg1.push(arg2);
stack.addFirst(arg1);
} else if (arg2 instanceof ETileConcatenation) {
arg2.push(arg1);
stack.addFirst(arg2);
} else {
final ETile concat = new ETileConcatenation();
concat.push(arg1);
concat.push(arg2);
stack.addFirst(concat);
}
}
private boolean isConcatenation1Mergeable(ETile tile) {
if (tile instanceof ETileConcatenation) {
final ETileConcatenation concat = (ETileConcatenation) tile;
return isBoxMergeable(concat.getFirst());
}
return false;
}
private boolean isBoxMergeable(ETile tile) {
if (tile instanceof ETileBox) {
final ETileBox box = (ETileBox) tile;
return box.getSymbol() == Symbol.TERMINAL_STRING1;
}
return false;
}
}

View File

@ -0,0 +1,69 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2023, 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.regex;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import net.sourceforge.plantuml.command.Command;
import net.sourceforge.plantuml.command.CommonCommands;
import net.sourceforge.plantuml.command.PSystemCommandFactory;
import net.sourceforge.plantuml.core.DiagramType;
import net.sourceforge.plantuml.core.UmlSource;
public class PSystemRegexFactory extends PSystemCommandFactory {
public PSystemRegexFactory() {
super(DiagramType.REGEX);
}
@Override
protected List<Command> createCommands() {
final List<Command> cmds = new ArrayList<>();
CommonCommands.addCommonCommands1(cmds);
cmds.add(new CommandRegexfSingleLine());
return cmds;
}
@Override
public PSystemRegex createEmptyDiagram(UmlSource source, Map<String, String> skinParam) {
return new PSystemRegex(source);
}
}

View File

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

View File

@ -0,0 +1,65 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2020, Arnaud Roques
*
* Project Info: http://plantuml.com
*
* If you like this project or if you find it useful, you can support us at:
*
* http://plantuml.com/patreon (only 1$ per month!)
* http://plantuml.com/paypal
*
* This file is part of PlantUML.
*
* PlantUML is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PlantUML distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
* License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
*
* Original Author: Arnaud Roques
*
*
*/
package net.sourceforge.plantuml.regex;
public enum ReTokenType {
SIMPLE_CHAR, //
ESCAPED_CHAR, //
CLASS, //
QUANTIFIER, //
ANCHOR, //
GROUP, //
ALTERNATIVE, //
PARENTHESIS_OPEN, //
PARENTHESIS_CLOSE, //
CONCATENATION_IMPLICIT;
static public boolean needImplicitConcatenation(ReTokenType token1, ReTokenType token2) {
if (token1 == ALTERNATIVE)
return false;
if (token2 == ALTERNATIVE)
return false;
if (token2 == QUANTIFIER)
return false;
if (token1 == PARENTHESIS_OPEN)
return false;
if (token2 == PARENTHESIS_CLOSE)
return false;
return true;
}
}

View File

@ -0,0 +1,223 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2020, Arnaud Roques
*
* Project Info: http://plantuml.com
*
* If you like this project or if you find it useful, you can support us at:
*
* http://plantuml.com/patreon (only 1$ per month!)
* http://plantuml.com/paypal
*
* This file is part of PlantUML.
*
* PlantUML is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PlantUML distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
* License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
*
* Original Author: Arnaud Roques
*
*
*/
package net.sourceforge.plantuml.regex;
import java.util.ArrayList;
import java.util.List;
import net.sourceforge.plantuml.ebnf.CharIterator;
public class RegexExpression {
public static List<ReToken> parse(CharIterator it) {
final List<ReToken> result = new ArrayList<>();
while (true) {
final char current = it.peek(0);
if (current == '\0')
break;
// System.err.println("current=" + current);
if (isStartAnchor(it)) {
final String s = readAnchor(it);
result.add(new ReToken(ReTokenType.ANCHOR, s));
} else if (isEscapedChar(it)) {
result.add(new ReToken(ReTokenType.ESCAPED_CHAR, "" + it.peek(1)));
it.next();
it.next();
} else if (current == '|') {
result.add(new ReToken(ReTokenType.ALTERNATIVE, "|"));
it.next();
} else if (current == '[') {
final String s = readGroup(it);
result.add(new ReToken(ReTokenType.GROUP, s));
} else if (isStartOpenParenthesis(it)) {
final String s = readOpenParenthesis(it);
result.add(new ReToken(ReTokenType.PARENTHESIS_OPEN, s));
} else if (current == ')') {
result.add(new ReToken(ReTokenType.PARENTHESIS_CLOSE, ")"));
it.next();
} else if (isStartQuantifier(it)) {
final String s = readQuantifier(it);
result.add(new ReToken(ReTokenType.QUANTIFIER, s));
} else if (isStartClass(it)) {
final String s = readClass(it);
result.add(new ReToken(ReTokenType.CLASS, s));
} else if (isSimpleLetter(current)) {
result.add(new ReToken(ReTokenType.SIMPLE_CHAR, "" + current));
it.next();
} else {
throw new IllegalStateException();
}
}
// System.err.println("result=" + result);
return result;
}
private static boolean isStartOpenParenthesis(CharIterator it) {
final char current0 = it.peek(0);
if (current0 == '(')
return true;
return false;
}
private static String readOpenParenthesis(CharIterator it) {
final char current0 = it.peek(0);
it.next();
final StringBuilder result = new StringBuilder();
result.append(current0);
return result.toString();
}
private static boolean isStartQuantifier(CharIterator it) {
final char current0 = it.peek(0);
if (current0 == '*' || current0 == '+' || current0 == '?' || current0 == '{')
return true;
return false;
}
private static String readQuantifier(CharIterator it) {
final char current0 = it.peek(0);
it.next();
final StringBuilder result = new StringBuilder();
result.append(current0);
if (current0 == '{')
while (it.peek(0) != 0) {
final char ch = it.peek(0);
result.append(ch);
it.next();
if (ch == '}')
break;
}
if (it.peek(0) == '?') {
result.append('?');
it.next();
}
return result.toString();
}
private static boolean isEscapedChar(CharIterator it) {
final char current0 = it.peek(0);
if (current0 == '\\') {
final char current1 = it.peek(1);
if (current1 == '.' || current1 == '*' || current1 == '\\' || current1 == '?' || current1 == '^'
|| current1 == '$' || current1 == '|' || current1 == '(' || current1 == ')' || current1 == '['
|| current1 == ']' || current1 == '{' || current1 == '}')
return true;
}
return false;
}
private static String readGroup(CharIterator it) {
final char current0 = it.peek(0);
if (current0 != '[')
throw new IllegalStateException();
it.next();
final StringBuilder result = new StringBuilder();
while (it.peek(0) != 0) {
char ch = it.peek(0);
it.next();
if (ch == ']')
break;
result.append(ch);
if (ch == '\\') {
ch = it.peek(0);
it.next();
result.append(ch);
}
}
return result.toString();
}
private static String readClass(CharIterator it) {
final char current0 = it.peek(0);
if (current0 == '.') {
it.next();
return "" + current0;
}
if (current0 == '\\') {
it.next();
final String result = "" + current0 + it.peek(0);
it.next();
return result;
}
throw new IllegalStateException();
}
private static boolean isStartClass(CharIterator it) {
final char current0 = it.peek(0);
if (current0 == '.')
return true;
if (current0 == '\\')
return true;
return false;
}
private static boolean isSimpleLetter(char ch) {
if (ch == '\\' || ch == '.')
return false;
return true;
}
private static boolean isStartAnchor(CharIterator it) {
final char current0 = it.peek(0);
if (current0 == '^' || current0 == '$')
return true;
if (current0 == '\\') {
final char current1 = it.peek(1);
if (current1 == 'A' || current1 == 'Z' || current1 == 'z' || current1 == 'G' || current1 == 'b'
|| current1 == 'B')
return true;
}
return false;
}
private static String readAnchor(CharIterator it) {
final char current0 = it.peek(0);
if (current0 == '^' || current0 == '$') {
it.next();
return "" + current0;
}
if (current0 == '\\') {
it.next();
final String result = "" + current0 + it.peek(0);
it.next();
return result;
}
throw new IllegalStateException();
}
}

View File

@ -0,0 +1,108 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2020, Arnaud Roques
*
* Project Info: http://plantuml.com
*
* If you like this project or if you find it useful, you can support us at:
*
* http://plantuml.com/patreon (only 1$ per month!)
* http://plantuml.com/paypal
*
* This file is part of PlantUML.
*
* PlantUML is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PlantUML distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
* License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
*
* Original Author: Arnaud Roques
*
*
*/
package net.sourceforge.plantuml.regex;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
public class ShuntingYard {
final private List<ReToken> ouputQueue = new ArrayList<>();
final private Deque<ReToken> operatorStack = new ArrayDeque<>();
public ShuntingYard(Iterator<ReToken> it) {
while (it.hasNext()) {
final ReToken token = it.next();
// System.err.println("token=" + token);
// System.err.println("ouputQueue=" + ouputQueue);
// System.err.println("operatorStack=" + operatorStack);
if (token.getType() == ReTokenType.SIMPLE_CHAR) {
ouputQueue.add(token);
} else if (token.getType() == ReTokenType.ESCAPED_CHAR) {
ouputQueue.add(token);
} else if (token.getType() == ReTokenType.GROUP) {
ouputQueue.add(token);
} else if (token.getType() == ReTokenType.CLASS) {
ouputQueue.add(token);
} else if (token.getType() == ReTokenType.ANCHOR) {
ouputQueue.add(token);
} else if (token.getType() == ReTokenType.QUANTIFIER) {
ouputQueue.add(token);
} else if (token.getType() == ReTokenType.CONCATENATION_IMPLICIT) {
// push it onto the operator stack.
operatorStack.addFirst(token);
} else if (token.getType() == ReTokenType.ALTERNATIVE) {
while (thereIsAConcatenationAtTheTopOfTheOperatorStack())
ouputQueue.add(operatorStack.removeFirst());
// push it onto the operator stack.
operatorStack.addFirst(token);
} else if (token.getType() == ReTokenType.PARENTHESIS_OPEN) {
operatorStack.addFirst(token);
} else if (token.getType() == ReTokenType.PARENTHESIS_CLOSE) {
while (operatorStack.peekFirst() != null
&& operatorStack.peekFirst().getType() != ReTokenType.PARENTHESIS_OPEN)
ouputQueue.add(operatorStack.removeFirst());
final ReToken first = operatorStack.removeFirst();
// ouputQueue.add(first);
} else {
throw new UnsupportedOperationException(token.toString());
}
}
while (operatorStack.isEmpty() == false) {
final ReToken token = operatorStack.removeFirst();
ouputQueue.add(token);
}
// System.err.println("ouputQueue=" + ouputQueue);
}
private boolean thereIsAConcatenationAtTheTopOfTheOperatorStack() {
final ReToken top = operatorStack.peekFirst();
return top != null && top.getType() == ReTokenType.CONCATENATION_IMPLICIT;
}
public final List<ReToken> getOuputQueue() {
return Collections.unmodifiableList(ouputQueue);
}
}

View File

@ -115,6 +115,7 @@ public enum SName {
rectangle, //
reference, //
referenceHeader, //
regex, //
requirement, //
root, //
rootNode, //

View File

@ -260,11 +260,14 @@ public class SvgGraphics {
private static String getData(final String name) {
try {
final InputStream is = SvgGraphics.class.getResourceAsStream("/svg/" + name);
return FileUtils.readText(is);
if (is == null)
Log.error("Cannot retrieve " + name);
else
return FileUtils.readText(is);
} catch (IOException e) {
Logme.error(e);
return null;
}
return null;
}
private Element getPathHover(String hover) {

View File

@ -81,7 +81,7 @@ public class Version {
}
public static int beta() {
final int beta = 0;
final int beta = 1;
return beta;
}

View File

@ -42,6 +42,11 @@ import net.sourceforge.plantuml.command.regex.IRegex;
import net.sourceforge.plantuml.command.regex.RegexConcat;
import net.sourceforge.plantuml.command.regex.RegexLeaf;
import net.sourceforge.plantuml.command.regex.RegexResult;
import net.sourceforge.plantuml.cucadiagram.Stereotype;
import net.sourceforge.plantuml.graphic.color.ColorParser;
import net.sourceforge.plantuml.graphic.color.ColorType;
import net.sourceforge.plantuml.graphic.color.Colors;
import net.sourceforge.plantuml.ugraphic.color.NoSuchColorException;
public class CommandWBSLink extends SingleLineCommand2<WBSDiagram> {
@ -53,19 +58,38 @@ public class CommandWBSLink extends SingleLineCommand2<WBSDiagram> {
return RegexConcat.build(CommandWBSLink.class.getName(), RegexLeaf.start(), //
new RegexLeaf("CODE1", "([%pLN_]+)"), //
RegexLeaf.spaceZeroOrMore(), //
new RegexLeaf("LINK", "-+\\>"), //
new RegexLeaf("LINK", "[.-]+\\>"), //
RegexLeaf.spaceZeroOrMore(), //
new RegexLeaf("CODE2", "([%pLN_]+)"), //
RegexLeaf.spaceZeroOrMore(), //
new RegexLeaf("MESSAGE", "(?::[%s]*(.*))?"), RegexLeaf.end());
color().getRegex(), //
RegexLeaf.spaceZeroOrMore(), //
new RegexLeaf("STEREOTYPE", "(\\<\\<.*\\>\\>)?"), //
RegexLeaf.spaceZeroOrMore(), //
new RegexLeaf("LABEL_LINK", "(?::[%s]*(.+))?"), //
RegexLeaf.end());
}
private static ColorParser color() {
return ColorParser.simpleColor(ColorType.LINE);
}
@Override
protected CommandExecutionResult executeArg(WBSDiagram diagram, LineLocation location, RegexResult arg) {
protected CommandExecutionResult executeArg(WBSDiagram diagram, LineLocation location, RegexResult arg)
throws NoSuchColorException {
final String code1 = arg.get("CODE1", 0);
final String code2 = arg.get("CODE2", 0);
// final String message = arg.get("MESSAGE", 0);
return diagram.link(code1, code2);
// final String message = arg.get("LABEL_LINK", 0);
final Colors colors = color().getColor(arg, diagram.getSkinParam().getIHtmlColorSet());
// link.setColors(color);
// link.applyStyle(arg.getLazzy("ARROW_STYLE", 0));
Stereotype stereotype = null;
if (arg.get("STEREOTYPE", 0) != null) {
stereotype = Stereotype.build(arg.get("STEREOTYPE", 0));
}
return diagram.link(code1, code2, colors, stereotype);
}
}

View File

@ -46,6 +46,7 @@ import net.sourceforge.plantuml.Direction;
import net.sourceforge.plantuml.FileFormatOption;
import net.sourceforge.plantuml.UmlDiagram;
import net.sourceforge.plantuml.UmlDiagramType;
import net.sourceforge.plantuml.activitydiagram3.ftile.vcompact.FtileGroup;
import net.sourceforge.plantuml.awt.geom.XDimension2D;
import net.sourceforge.plantuml.awt.geom.XRectangle2D;
import net.sourceforge.plantuml.command.CommandExecutionResult;
@ -56,10 +57,18 @@ import net.sourceforge.plantuml.core.DiagramDescription;
import net.sourceforge.plantuml.core.ImageData;
import net.sourceforge.plantuml.core.UmlSource;
import net.sourceforge.plantuml.cucadiagram.Display;
import net.sourceforge.plantuml.cucadiagram.Stereotype;
import net.sourceforge.plantuml.graphic.InnerStrategy;
import net.sourceforge.plantuml.graphic.StringBounder;
import net.sourceforge.plantuml.graphic.color.ColorType;
import net.sourceforge.plantuml.graphic.color.Colors;
import net.sourceforge.plantuml.mindmap.IdeaShape;
import net.sourceforge.plantuml.style.NoStyleAvailableException;
import net.sourceforge.plantuml.style.PName;
import net.sourceforge.plantuml.style.SName;
import net.sourceforge.plantuml.style.Style;
import net.sourceforge.plantuml.style.StyleSignature;
import net.sourceforge.plantuml.style.StyleSignatureBasic;
import net.sourceforge.plantuml.svek.TextBlockBackcolored;
import net.sourceforge.plantuml.ugraphic.AbstractCommonUGraphic;
import net.sourceforge.plantuml.ugraphic.MinMax;
@ -231,15 +240,23 @@ public class WBSDiagram extends UmlDiagram {
}
}
public CommandExecutionResult link(String code1, String code2) {
public CommandExecutionResult link(String code1, String code2, Colors colors, Stereotype stereotype) {
final WElement element1 = codes.get(code1);
if (element1 == null)
return CommandExecutionResult.error("No such node " + code1);
final WElement element2 = codes.get(code2);
if (element2 == null)
return CommandExecutionResult.error("No such node " + code2);
HColor color = colors.getColor(ColorType.LINE);
links.add(new WBSLink(element1, element2));
if (color == null) {
final Style style = StyleSignatureBasic.of(SName.root, SName.element, SName.wbsDiagram, SName.arrow)
.withTOBECHANGED(stereotype).getMergedStyle(getCurrentStyleBuilder());
color = style.value(PName.LineColor).asColor(getSkinParam().getIHtmlColorSet());
}
links.add(new WBSLink(element1, element2, color));
return CommandExecutionResult.ok();
}

View File

@ -43,16 +43,20 @@ import net.sourceforge.plantuml.graphic.UDrawable;
import net.sourceforge.plantuml.svek.extremity.ExtremityArrow;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.UTranslate;
import net.sourceforge.plantuml.ugraphic.color.HColors;
import net.sourceforge.plantuml.ugraphic.color.HColor;
class WBSLink implements UDrawable {
private final WElement element1;
private final WElement element2;
private final HColor color;
public WBSLink(WElement element1, WElement element2) {
public WBSLink(WElement element1, WElement element2, HColor color) {
this.element1 = element1;
this.element2 = element2;
this.color = color;
if (color == null)
throw new IllegalArgumentException();
}
public final WElement getElement1() {
@ -83,7 +87,7 @@ class WBSLink implements UDrawable {
final XPoint2D c2 = rect2.intersect(line);
line = new XLine2D(c1, c2);
ug = ug.apply(HColors.RED);
ug = ug.apply(color);
line.drawU(ug);
final double angle = line.getAngle();

View File

@ -85,7 +85,7 @@ public class YamlDiagramFactory extends PSystemAbstractFactory {
} catch (Exception e) {
Logme.error(e);
}
final JsonDiagram result = new JsonDiagram(source, UmlDiagramType.YAML, yaml, highlighted);
final JsonDiagram result = new JsonDiagram(source, UmlDiagramType.YAML, yaml, highlighted, styleExtractor);
if (styleExtractor != null) {
styleExtractor.applyStyles(result.getSkinParam());
final String title = styleExtractor.getTitle();

Binary file not shown.

Binary file not shown.