1
0
mirror of https://github.com/octoleo/plantuml.git synced 2024-12-22 10:59:01 +00:00
This commit is contained in:
Arnaud Roques 2022-08-26 18:00:28 +02:00
parent 7c576ed4ac
commit 6809546c65
39 changed files with 751 additions and 191 deletions

View File

@ -87,9 +87,9 @@ public class Dimension2DDouble extends Dimension2D {
}
public static Dimension2D delta(Dimension2D dim, double deltaWidth, double deltaHeight) {
if (deltaHeight == 0 && deltaWidth == 0) {
if (deltaHeight == 0 && deltaWidth == 0)
return dim;
}
return new Dimension2DDouble(dim.getWidth() + deltaWidth, dim.getHeight() + deltaHeight);
}
@ -124,15 +124,15 @@ public class Dimension2DDouble extends Dimension2D {
public static Dimension2D atLeast(Dimension2D dim, double minWidth, double minHeight) {
double h = dim.getHeight();
double w = dim.getWidth();
if (w > minWidth && h > minHeight) {
if (w > minWidth && h > minHeight)
return dim;
}
if (h < minHeight) {
if (h < minHeight)
h = minHeight;
}
if (w < minWidth) {
if (w < minWidth)
w = minWidth;
}
return new Dimension2DDouble(w, h);
}

View File

@ -212,7 +212,7 @@ public class ClassDiagram extends AbstractClassOrObjectDiagram {
}
private TextBlock getEntityImageClass(ILeaf entity) {
return new EntityImageClass(null, entity, getSkinParam(), this);
return new EntityImageClass(entity, getSkinParam(), this);
}
@Override

View File

@ -81,6 +81,7 @@ import net.sourceforge.plantuml.descdiagram.command.CommandPackageWithUSymbol;
import net.sourceforge.plantuml.objectdiagram.command.CommandCreateEntityObject;
import net.sourceforge.plantuml.objectdiagram.command.CommandCreateEntityObjectMultilines;
import net.sourceforge.plantuml.objectdiagram.command.CommandCreateJson;
import net.sourceforge.plantuml.objectdiagram.command.CommandCreateJsonSingleLine;
import net.sourceforge.plantuml.objectdiagram.command.CommandCreateMap;
public class ClassDiagramFactory extends PSystemCommandFactory {
@ -108,6 +109,7 @@ public class ClassDiagramFactory extends PSystemCommandFactory {
cmds.add(new CommandCreateEntityObjectMultilines());
cmds.add(new CommandCreateMap());
cmds.add(new CommandCreateJson());
cmds.add(new CommandCreateJsonSingleLine());
cmds.add(new CommandCreateClass());
cmds.add(new CommandCreateEntityObject());

View File

@ -80,7 +80,7 @@ public class CommandCreateClass extends SingleLineCommand2<ClassDiagram> {
private static IRegex getRegexConcat() {
return RegexConcat.build(CommandCreateClass.class.getName(), RegexLeaf.start(), //
new RegexLeaf("TYPE", //
"(interface|enum|annotation|abstract[%s]+class|abstract|class|entity|circle|diamond|protocol|struct|exception)"), //
"(interface|enum|annotation|abstract[%s]+class|static[%s]+class|abstract|class|entity|circle|diamond|protocol|struct|exception)"), //
RegexLeaf.spaceOneOrMore(), //
new RegexOr(//
new RegexConcat(//

View File

@ -94,7 +94,7 @@ public class CommandCreateClassMultilines extends CommandMultilines2<ClassDiagra
return RegexConcat.build(CommandCreateClassMultilines.class.getName(), RegexLeaf.start(), //
new RegexLeaf("VISIBILITY", "(" + VisibilityModifier.regexForVisibilityCharacterInClassName() + ")?"), //
new RegexLeaf("TYPE",
"(interface|enum|annotation|abstract[%s]+class|abstract|class|entity|protocol|struct|exception)"), //
"(interface|enum|annotation|abstract[%s]+class|static[%s]+class|abstract|class|entity|protocol|struct|exception)"), //
RegexLeaf.spaceOneOrMore(), //
new RegexOr(//
new RegexConcat(//

View File

@ -233,11 +233,12 @@ final public class CommandLinkClass extends SingleLineCommand2<AbstractClassOrOb
final Labels labels = new Labels(arg);
final String kal1 = arg.get("QUALIFIER1", 0);
final String kal2 = arg.get("QUALIFIER2", 0);
final LinkArg linkArg = LinkArg
.build(labels.getDisplay(), queue, diagram.getSkinParam().classAttributeIconSize() > 0)
.withQualifier(labels.getFirstLabel(), labels.getSecondLabel())
.withDistanceAngle(diagram.getLabeldistance(), diagram.getLabelangle()).withKal(kal1);
.withDistanceAngle(diagram.getLabeldistance(), diagram.getLabelangle()).withKal(kal1, kal2);
Link link = new Link(diagram.getSkinParam().getCurrentStyleBuilder(), cl1, cl2, linkType, linkArg);
if (arg.get("URL", 0) != null) {

View File

@ -35,7 +35,6 @@
*/
package net.sourceforge.plantuml.cucadiagram;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
@ -60,10 +59,6 @@ import net.sourceforge.plantuml.core.ImageData;
import net.sourceforge.plantuml.core.UmlSource;
import net.sourceforge.plantuml.creole.CreoleMode;
import net.sourceforge.plantuml.cucadiagram.dot.CucaDiagramTxtMaker;
import net.sourceforge.plantuml.cucadiagram.dot.Graphviz;
import net.sourceforge.plantuml.cucadiagram.dot.GraphvizUtils;
import net.sourceforge.plantuml.cucadiagram.dot.GraphvizVersion;
import net.sourceforge.plantuml.cucadiagram.dot.GraphvizVersions;
import net.sourceforge.plantuml.cucadiagram.entity.EntityFactory;
import net.sourceforge.plantuml.elk.CucaDiagramFileMakerElk;
import net.sourceforge.plantuml.graphic.USymbol;
@ -75,7 +70,6 @@ import net.sourceforge.plantuml.style.ClockwiseTopRightBottomLeft;
import net.sourceforge.plantuml.svek.CucaDiagramFileMaker;
import net.sourceforge.plantuml.svek.CucaDiagramFileMakerSvek;
import net.sourceforge.plantuml.ugraphic.color.ColorMapper;
import net.sourceforge.plantuml.vizjs.GraphvizJs;
import net.sourceforge.plantuml.xmi.CucaDiagramXmiMaker;
import net.sourceforge.plantuml.xmlsc.StateDiagramScxmlMaker;
@ -880,23 +874,4 @@ public abstract class CucaDiagram extends UmlDiagram implements GroupHierarchy,
return ClockwiseTopRightBottomLeft.topRightBottomLeft(0, 5, 5, 0);
}
private GraphvizVersion graphvizVersion;
public GraphvizVersion getGraphvizVersion() {
if (graphvizVersion == null)
graphvizVersion = getGraphvizVersionInternal();
return graphvizVersion;
}
private GraphvizVersion getGraphvizVersionInternal() {
final Graphviz graphviz = GraphvizUtils.create(getSkinParam(), "foo;", "svg");
if (graphviz instanceof GraphvizJs)
return GraphvizJs.getGraphvizVersion(false);
final File f = graphviz.getDotExe();
return GraphvizVersions.getInstance().getVersion(f);
}
}

View File

@ -65,12 +65,15 @@ public enum LeafType {
public static LeafType getLeafType(String type) {
type = StringUtils.goUpperCase(type);
if (type.startsWith("ABSTRACT")) {
if (type.startsWith("ABSTRACT"))
return LeafType.ABSTRACT_CLASS;
}
if (type.startsWith("DIAMOND")) {
if (type.startsWith("DIAMOND"))
return LeafType.STATE_CHOICE;
}
if (type.startsWith("STATIC"))
return LeafType.CLASS;
return LeafType.valueOf(type);
}

View File

@ -46,7 +46,6 @@ import net.sourceforge.plantuml.UmlDiagramType;
import net.sourceforge.plantuml.Url;
import net.sourceforge.plantuml.awt.geom.Dimension2D;
import net.sourceforge.plantuml.command.Position;
import net.sourceforge.plantuml.cucadiagram.entity.EntityImpl;
import net.sourceforge.plantuml.graphic.FontConfiguration;
import net.sourceforge.plantuml.graphic.HorizontalAlignment;
import net.sourceforge.plantuml.graphic.StringBounder;
@ -56,7 +55,6 @@ import net.sourceforge.plantuml.graphic.color.Colors;
import net.sourceforge.plantuml.skin.VisibilityModifier;
import net.sourceforge.plantuml.style.StyleBuilder;
import net.sourceforge.plantuml.svek.Bibliotekon;
import net.sourceforge.plantuml.svek.Margins;
import net.sourceforge.plantuml.ugraphic.UComment;
import net.sourceforge.plantuml.ugraphic.UFont;
import net.sourceforge.plantuml.utils.UniqueSequence;
@ -125,13 +123,6 @@ public class Link extends WithLinkType implements Hideable, Removeable {
this.type = type;
this.linkArg = linkArg;
if (linkArg.getQualifier1() != null)
((EntityImpl) cl1).ensureMargins(Margins.uniform(16));
if (linkArg.getQualifier2() != null)
((EntityImpl) cl2).ensureMargins(Margins.uniform(16));
}
public Link getInv() {

View File

@ -54,11 +54,11 @@ public class LinkArg {
public static LinkArg build(final Display label, int length) {
return build(label, length, true);
}
public static LinkArg noDisplay(int length) {
return build(Display.NULL, length, true);
}
public static LinkArg build(final Display label, int length, boolean manageVisibilityModifier) {
VisibilityModifier visibilityModifier = null;
final Display newLabel;
@ -77,7 +77,7 @@ public class LinkArg {
kal2);
}
public LinkArg withKal(String kal1) {
public LinkArg withKal(String kal1, String kal2) {
return new LinkArg(label, length, qualifier1, qualifier2, labeldistance, labelangle, visibilityModifier, kal1,
kal2);
}

View File

@ -74,7 +74,6 @@ final public class DotData implements PortionShower {
private final ColorMapper colorMapper;
private final EntityFactory entityFactory;
private final GraphvizVersion graphvizVersion;
public EntityFactory getEntityFactory() {
return entityFactory;
@ -83,7 +82,7 @@ final public class DotData implements PortionShower {
public DotData(IGroup topParent, List<Link> links, Collection<ILeaf> leafs, UmlDiagramType umlDiagramType,
ISkinParam skinParam, GroupHierarchy groupHierarchy, PortionShower portionShower, ColorMapper colorMapper,
EntityFactory entityFactory, boolean isHideEmptyDescriptionForState, DotMode dotMode,
String namespaceSeparator, Pragma pragma, GraphvizVersion graphvizVersion) {
String namespaceSeparator, Pragma pragma) {
this.namespaceSeparator = namespaceSeparator;
this.pragma = pragma;
this.topParent = Objects.requireNonNull(topParent);
@ -98,19 +97,16 @@ final public class DotData implements PortionShower {
this.groupHierarchy = groupHierarchy;
this.portionShower = portionShower;
this.entityFactory = entityFactory;
this.graphvizVersion = graphvizVersion;
}
public DotData(IGroup topParent, List<Link> links, Collection<ILeaf> leafs, UmlDiagramType umlDiagramType,
ISkinParam skinParam, GroupHierarchy groupHierarchy, ColorMapper colorMapper, EntityFactory entityFactory,
boolean isHideEmptyDescriptionForState, DotMode dotMode, String namespaceSeparator, Pragma pragma,
GraphvizVersion graphvizVersion) {
boolean isHideEmptyDescriptionForState, DotMode dotMode, String namespaceSeparator, Pragma pragma) {
this(topParent, links, leafs, umlDiagramType, skinParam, groupHierarchy, new PortionShower() {
public boolean showPortion(EntityPortion portion, IEntity entity) {
return true;
}
}, colorMapper, entityFactory, isHideEmptyDescriptionForState, dotMode, namespaceSeparator, pragma,
graphvizVersion);
}, colorMapper, entityFactory, isHideEmptyDescriptionForState, dotMode, namespaceSeparator, pragma);
}
public UmlDiagramType getUmlDiagramType() {
@ -236,8 +232,4 @@ final public class DotData implements PortionShower {
}
public GraphvizVersion getGraphvizVersion() {
return graphvizVersion;
}
}

View File

@ -36,7 +36,7 @@
package net.sourceforge.plantuml.cucadiagram.dot;
public interface GraphvizVersion {
public boolean useShield();
public boolean useShieldForQuantifier();
public boolean useProtectionWhenThereALinkFromOrToGroup();

View File

@ -45,7 +45,7 @@ public class GraphvizVersionFinder {
final private File dotExe;
final public static GraphvizVersion DEFAULT = new GraphvizVersion() {
public boolean useShield() {
public boolean useShieldForQuantifier() {
return true;
}
@ -82,7 +82,7 @@ public class GraphvizVersionFinder {
final int minor = Integer.parseInt(m.group(2));
final int v = 100 * major + minor;
return new GraphvizVersion() {
public boolean useShield() {
public boolean useShieldForQuantifier() {
return v <= 228;
}

View File

@ -39,6 +39,7 @@ package net.sourceforge.plantuml.cucadiagram.entity;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
@ -47,6 +48,7 @@ import java.util.Map;
import java.util.Objects;
import java.util.Set;
import net.sourceforge.plantuml.Direction;
import net.sourceforge.plantuml.FontParam;
import net.sourceforge.plantuml.Guillemet;
import net.sourceforge.plantuml.ISkinParam;
@ -77,6 +79,7 @@ import net.sourceforge.plantuml.graphic.color.ColorType;
import net.sourceforge.plantuml.graphic.color.Colors;
import net.sourceforge.plantuml.skin.VisibilityModifier;
import net.sourceforge.plantuml.svek.IEntityImage;
import net.sourceforge.plantuml.svek.Kal;
import net.sourceforge.plantuml.svek.Margins;
import net.sourceforge.plantuml.svek.PackageStyle;
import net.sourceforge.plantuml.svek.SingleStrategy;
@ -282,7 +285,6 @@ final public class EntityImpl implements ILeaf, IGroup {
public final Margins getMargins() {
checkNotGroup();
System.err.println("GETTING MARGIN!");
return margins;
}
@ -789,4 +791,23 @@ final public class EntityImpl implements ILeaf, IGroup {
return stereostyles;
}
private final Map<Direction, List<Kal>> kals = new EnumMap<>(Direction.class);
public void addKal(Kal kal) {
final Direction position = kal.getPosition();
List<Kal> list = kals.get(position);
if (list == null) {
list = new ArrayList<>();
kals.put(position, list);
}
list.add(kal);
}
public List<Kal> getKals(Direction position) {
final List<Kal> result = kals.get(position);
if (result == null)
return Collections.emptyList();
return Collections.unmodifiableList(result);
}
}

View File

@ -64,6 +64,7 @@ import net.sourceforge.plantuml.descdiagram.command.CommandLinkElement;
import net.sourceforge.plantuml.descdiagram.command.CommandNewpage;
import net.sourceforge.plantuml.descdiagram.command.CommandPackageWithUSymbol;
import net.sourceforge.plantuml.objectdiagram.command.CommandCreateJson;
import net.sourceforge.plantuml.objectdiagram.command.CommandCreateJsonSingleLine;
import net.sourceforge.plantuml.objectdiagram.command.CommandCreateMap;
public class DescriptionDiagramFactory extends PSystemCommandFactory {
@ -120,6 +121,7 @@ public class DescriptionDiagramFactory extends PSystemCommandFactory {
cmds.add(new CommandCreateMap());
cmds.add(new CommandCreateJson());
cmds.add(new CommandCreateJsonSingleLine());
// cmds.add(new CommandHideShowSpecificClass());
cmds.add(new CommandArchimate());

View File

@ -0,0 +1,135 @@
/* ========================================================================
* 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.objectdiagram.command;
import net.sourceforge.plantuml.FontParam;
import net.sourceforge.plantuml.LineLocation;
import net.sourceforge.plantuml.UrlBuilder;
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.cucadiagram.BodierJSon;
import net.sourceforge.plantuml.cucadiagram.Code;
import net.sourceforge.plantuml.cucadiagram.Display;
import net.sourceforge.plantuml.cucadiagram.IEntity;
import net.sourceforge.plantuml.cucadiagram.Ident;
import net.sourceforge.plantuml.cucadiagram.LeafType;
import net.sourceforge.plantuml.cucadiagram.Stereotype;
import net.sourceforge.plantuml.graphic.color.ColorParser;
import net.sourceforge.plantuml.graphic.color.ColorType;
import net.sourceforge.plantuml.json.Json.DefaultHandler;
import net.sourceforge.plantuml.json.JsonParser;
import net.sourceforge.plantuml.json.JsonValue;
import net.sourceforge.plantuml.objectdiagram.AbstractClassOrObjectDiagram;
import net.sourceforge.plantuml.ugraphic.color.NoSuchColorException;
public class CommandCreateJsonSingleLine extends SingleLineCommand2<AbstractClassOrObjectDiagram> {
public CommandCreateJsonSingleLine() {
super(getRegexConcat());
}
private static IRegex getRegexConcat() {
return RegexConcat.build(CommandCreateJsonSingleLine.class.getName(), RegexLeaf.start(), //
new RegexLeaf("TYPE", "json"), //
RegexLeaf.spaceOneOrMore(), //
new RegexLeaf("NAME", "(?:[%g]([^%g]+)[%g][%s]+as[%s]+)?([%pLN_.]+)"), //
RegexLeaf.spaceZeroOrMore(), //
new RegexLeaf("STEREO", "(\\<\\<.+\\>\\>)?"), //
RegexLeaf.spaceZeroOrMore(), //
new RegexLeaf("URL", "(" + UrlBuilder.getRegexp() + ")?"), //
RegexLeaf.spaceZeroOrMore(), //
ColorParser.exp1(), //
RegexLeaf.spaceZeroOrMore(), //
new RegexLeaf("DATA", "(\\{.*\\})"), //
RegexLeaf.end());
}
@Override
protected CommandExecutionResult executeArg(AbstractClassOrObjectDiagram diagram, LineLocation location,
RegexResult arg) throws NoSuchColorException {
final String name = arg.get("NAME", 1);
final String data = arg.get("DATA", 0);
final IEntity entity1 = executeArg0(diagram, arg);
if (entity1 == null)
return CommandExecutionResult.error("No such entity");
final JsonValue json = getJsonValue(data);
if (json == null)
return CommandExecutionResult.error("Bad data");
((BodierJSon) entity1.getBodier()).setJson(json);
return CommandExecutionResult.ok();
}
private JsonValue getJsonValue(String data) {
try {
final DefaultHandler handler = new DefaultHandler();
new JsonParser(handler).parse(data);
final JsonValue json = handler.getValue();
return json;
} catch (Exception e) {
return null;
}
}
private IEntity executeArg0(AbstractClassOrObjectDiagram diagram, RegexResult line0) throws NoSuchColorException {
final String name = line0.get("NAME", 1);
final Ident ident = diagram.buildLeafIdent(name);
final Code code = diagram.V1972() ? ident : diagram.buildCode(name);
final String display = line0.get("NAME", 0);
final String stereotype = line0.get("STEREO", 0);
final boolean leafExist = diagram.V1972() ? diagram.leafExistSmart(ident) : diagram.leafExist(code);
if (leafExist)
return diagram.getOrCreateLeaf(diagram.buildLeafIdent(name), code, LeafType.JSON, null);
final IEntity entity = diagram.createLeaf(ident, code, Display.getWithNewlines(display), LeafType.JSON, null);
if (stereotype != null)
entity.setStereotype(Stereotype.build(stereotype, diagram.getSkinParam().getCircledCharacterRadius(),
diagram.getSkinParam().getFont(null, false, FontParam.CIRCLED_CHARACTER),
diagram.getSkinParam().getIHtmlColorSet()));
final String s = line0.get("COLOR", 0);
entity.setSpecificColorTOBEREMOVED(ColorType.BACK, s == null ? null
: diagram.getSkinParam().getIHtmlColorSet().getColor(diagram.getSkinParam().getThemeStyle(), s));
return entity;
}
}

View File

@ -80,7 +80,6 @@ import net.sourceforge.plantuml.version.Version;
public class PicoWebServer implements Runnable {
private final Socket connect;
private static final AtomicBoolean stopRequested = new AtomicBoolean(false);
private static boolean enableStop;
public PicoWebServer(Socket c) {
@ -91,7 +90,8 @@ public class PicoWebServer implements Runnable {
startServer(8080, null, false);
}
public static void startServer(final int port, final String bindAddress, final boolean argEnableStop) throws IOException {
public static void startServer(final int port, final String bindAddress, final boolean argEnableStop)
throws IOException {
PicoWebServer.enableStop = argEnableStop;
final InetAddress bindAddress1 = bindAddress == null ? null : InetAddress.getByName(bindAddress);
final ServerSocket serverConnect = new ServerSocket(port, 50, bindAddress1);
@ -100,7 +100,7 @@ public class PicoWebServer implements Runnable {
}
public static void serverLoop(final ServerSocket serverConnect) throws IOException {
while (stopRequested.get() == false) {
while (true) {
final PicoWebServer myServer = new PicoWebServer(serverConnect.accept());
final Thread thread = new Thread(myServer);
thread.start();
@ -137,10 +137,10 @@ public class PicoWebServer implements Runnable {
return;
if (request.getPath().startsWith("/plantuml/serverinfo") && handleInfo(out))
return;
if (enableStop && request.getPath().startsWith("/stopserver")) {
stopRequested.set(true);
if (enableStop && (request.getPath().startsWith("/stopserver")
|| request.getPath().startsWith("/plantuml/stopserver")) && handleStop(out))
return;
}
} else if (request.getMethod().equals("POST") && request.getPath().equals("/render")) {
handleRenderRequest(request, out);
return;
@ -167,6 +167,32 @@ public class PicoWebServer implements Runnable {
}
}
private boolean handleStop(BufferedOutputStream out) throws IOException {
write(out, "HTTP/1.1 " + "200");
write(out, "Cache-Control: no-cache");
write(out, "Server: PlantUML PicoWebServer " + Version.versionString());
write(out, "Date: " + new Date());
write(out, "");
write(out, "<html>Stoping...</html>");
out.flush();
final Thread stop = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000L);
} catch (InterruptedException e) {
}
System.exit(0);
}
});
stop.start();
return true;
}
private boolean handleInfo(BufferedOutputStream out) throws IOException {
write(out, "HTTP/1.1 " + "200");
write(out, "Cache-Control: no-cache");

View File

@ -241,6 +241,14 @@ public class DotPath implements UShape, Moveable {
beziers.get(0).ctrly1 = y;
}
public void moveStartPoint(double dx, double dy) {
beziers.get(0).x1 += dx;
beziers.get(0).y1 += dy;
beziers.get(0).ctrlx1 += dx;
beziers.get(0).ctrly1 += dy;
}
public Point2D getEndPoint() {
return beziers.get(beziers.size() - 1).getP2();
}

View File

@ -162,7 +162,7 @@ public class SequenceDiagram extends UmlDiagram {
return participantsget(code) != null;
}
public String addMessage(AbstractMessage m) {
public CommandExecutionResult addMessage(AbstractMessage m) {
if (m.isParallel())
m.setParallelBrother(getLastAbstractMessage());
@ -171,12 +171,13 @@ public class SequenceDiagram extends UmlDiagram {
events.add(m);
if (pendingCreate != null) {
if (m.compatibleForCreate(pendingCreate.getParticipant()) == false)
return "After create command, you have to send a message to \"" + pendingCreate.getParticipant() + "\"";
return CommandExecutionResult.error("After create command, you have to send a message to \""
+ pendingCreate.getParticipant() + "\"");
m.addLifeEvent(pendingCreate);
pendingCreate = null;
}
return null;
return CommandExecutionResult.ok();
}
private AbstractMessage getLastAbstractMessage() {

View File

@ -320,9 +320,9 @@ public class CommandArrow extends SingleLineCommand2<SequenceDiagram> {
msg.setPart1Anchor(arg.get("PART1ANCHOR", 1));
msg.setPart2Anchor(arg.get("PART2ANCHOR", 1));
final String error = diagram.addMessage(msg);
if (error != null)
return CommandExecutionResult.error(error);
final CommandExecutionResult status = diagram.addMessage(msg);
if (status.isOk() == false)
return status;
final String s = arg.get("LIFECOLOR", 0);

View File

@ -149,9 +149,9 @@ abstract class CommandExoArrowAny extends SingleLineCommand2<SequenceDiagram> {
msg.setPart1Anchor(arg.get("PART1ANCHOR", 1));
msg.setPart2Anchor(arg.get("PART2ANCHOR", 1));
final String error = diagram.addMessage(msg);
if (error != null)
return CommandExecutionResult.error(error);
final CommandExecutionResult status = diagram.addMessage(msg);
if (status.isOk() == false)
return status;
final String s = arg.get("LIFECOLOR", 0);

View File

@ -83,18 +83,17 @@ public class CommandReturn extends SingleLineCommand2<SequenceDiagram> {
boolean doDeactivation = true;
if (message1 == null) {
final EventWithDeactivate last = diagram.getLastEventWithDeactivate();
if (last instanceof Message == false) {
if (last instanceof Message == false)
return CommandExecutionResult.error("Nowhere to return to.");
}
message1 = (Message) last;
doDeactivation = false;
}
ArrowConfiguration arrow = message1.getArrowConfiguration().withBody(ArrowBody.DOTTED);
final String color = arg.get("COLOR", 0);
if (color != null) {
if (color != null)
arrow = arrow.withColor(HColorSet.instance().getColor(diagram.getSkinParam().getThemeStyle(), color));
}
final Display display = Display.getWithNewlines(arg.get("MESSAGE", 0));
final AbstractMessage message2;
@ -106,17 +105,19 @@ public class CommandReturn extends SingleLineCommand2<SequenceDiagram> {
message2 = new Message(diagram.getSkinParam().getCurrentStyleBuilder(), message1.getParticipant2(),
message1.getParticipant1(), display, arrow, diagram.getNextMessageNumber());
final boolean parallel = arg.get("PARALLEL", 0) != null;
if (parallel) {
if (parallel)
message2.goParallel();
}
}
diagram.addMessage(message2);
final CommandExecutionResult status = diagram.addMessage(message2);
if (status.isOk() == false)
return status;
if (doDeactivation) {
final String error = diagram.activate(message1.getParticipant2(), LifeEventType.DEACTIVATE, null);
if (error != null) {
if (error != null)
return CommandExecutionResult.error(error);
}
}
return CommandExecutionResult.ok();

View File

@ -245,7 +245,7 @@ public class GroupingTile extends AbstractTile {
tiles = removeEmptyCloseToParallel(tiles);
final List<Tile> result = new ArrayList<>();
for (Tile tile : tiles) {
if (isParallel(tile)) {
if (result.size() > 0 && isParallel(tile)) {
if (pending == null) {
pending = new TileParallel(stringBounder);
final Tile tmp = result.get(result.size() - 1);

View File

@ -59,18 +59,18 @@ public class Bibliotekon {
private final List<SvekLine> lines1 = new ArrayList<>();
private final List<SvekLine> allLines = new ArrayList<>();
public SvekNode createNode(ILeaf ent, IEntityImage image, ColorSequence colorSequence, StringBounder stringBounder) {
public SvekNode createNode(ILeaf ent, IEntityImage image, ColorSequence colorSequence,
StringBounder stringBounder) {
final SvekNode node = new SvekNode(ent, image, colorSequence, stringBounder);
nodeMap.put(ent, node);
return node;
}
public Cluster getCluster(IGroup ent) {
for (Cluster cl : allCluster) {
if (cl.getGroups().contains(ent)) {
for (Cluster cl : allCluster)
if (cl.getGroups().contains(ent))
return cl;
}
}
return null;
}
@ -97,9 +97,9 @@ public class Bibliotekon {
private static boolean first(SvekLine line) {
final int length = line.getLength();
if (length == 1) {
if (length == 1)
return true;
}
return false;
}
@ -115,18 +115,16 @@ public class Bibliotekon {
final SvekNode result = getNode(ent);
if (result != null) {
String uid = result.getUid();
if (result.isShielded()) {
if (result.isShielded())
uid = uid + ":h";
}
return uid;
}
assert result == null;
if (ent.isGroup()) {
for (IEntity i : nodeMap.keySet()) {
if (ent.getCodeGetName().equals(i.getCodeGetName())) {
for (IEntity i : nodeMap.keySet())
if (ent.getCodeGetName().equals(i.getCodeGetName()))
return getNode(i).getUid();
}
}
return Cluster.getSpecialPointId(ent);
}
throw new IllegalStateException();
@ -180,39 +178,36 @@ public class Bibliotekon {
public List<SvekLine> getAllLineConnectedTo(IEntity leaf) {
final List<SvekLine> result = new ArrayList<>();
for (SvekLine line : allLines) {
if (line.isLinkFromOrTo(leaf)) {
for (SvekLine line : allLines)
if (line.isLinkFromOrTo(leaf))
result.add(line);
}
}
return Collections.unmodifiableList(result);
}
public SvekLine getLine(Link link) {
for (SvekLine line : allLines) {
if (line.isLink(link)) {
for (SvekLine line : allLines)
if (line.isLink(link))
return line;
}
}
throw new IllegalArgumentException();
}
public IEntity getOnlyOther(IEntity entity) {
for (SvekLine line : allLines) {
final IEntity other = line.getOther(entity);
if (other != null) {
if (other != null)
return other;
}
}
return null;
}
public ILeaf getLeaf(SvekNode node) {
for (Map.Entry<ILeaf, SvekNode> ent : nodeMap.entrySet()) {
if (ent.getValue() == node) {
for (Map.Entry<ILeaf, SvekNode> ent : nodeMap.entrySet())
if (ent.getValue() == node)
return ent.getKey();
}
}
throw new IllegalArgumentException();
}
}

View File

@ -76,7 +76,7 @@ public final class CucaDiagramFileMakerSvek implements CucaDiagramFileMaker {
final DotData dotData = new DotData(diagram.getEntityFactory().getRootGroup(), getOrderedLinks(),
diagram.getLeafsvalues(), diagram.getUmlDiagramType(), diagram.getSkinParam(), diagram, diagram,
diagram.getColorMapper(), diagram.getEntityFactory(), diagram.isHideEmptyDescriptionForState(), dotMode,
diagram.getNamespaceSeparator(), diagram.getPragma(), diagram.getGraphvizVersion());
diagram.getNamespaceSeparator(), diagram.getPragma());
final boolean intricated = diagram.mergeIntricated();
return new GeneralImageBuilder(intricated, dotData, diagram.getEntityFactory(), diagram.getSource(),
diagram.getPragma(), stringBounder, diagram.getUmlDiagramType().getStyleName());

View File

@ -60,6 +60,7 @@ import net.sourceforge.plantuml.cucadiagram.dot.DotSplines;
import net.sourceforge.plantuml.cucadiagram.dot.Graphviz;
import net.sourceforge.plantuml.cucadiagram.dot.GraphvizUtils;
import net.sourceforge.plantuml.cucadiagram.dot.GraphvizVersion;
import net.sourceforge.plantuml.cucadiagram.dot.GraphvizVersions;
import net.sourceforge.plantuml.cucadiagram.dot.ProcessState;
import net.sourceforge.plantuml.cucadiagram.entity.EntityFactory;
import net.sourceforge.plantuml.graphic.StringBounder;
@ -86,8 +87,6 @@ public class DotStringFactory implements Moveable {
private final StringBounder stringBounder;
private GraphvizVersion graphvizVersion;
public DotStringFactory(StringBounder stringBounder, DotData dotData) {
this.skinParam = dotData.getSkinParam();
this.umlDiagramType = dotData.getUmlDiagramType();
@ -97,7 +96,6 @@ public class DotStringFactory implements Moveable {
this.stringBounder = stringBounder;
this.root = new Cluster(colorSequence, skinParam, dotData.getRootGroup());
this.current = root;
this.graphvizVersion = dotData.getGraphvizVersion();
}
public DotStringFactory(StringBounder stringBounder, CucaDiagram diagram) {
@ -109,7 +107,6 @@ public class DotStringFactory implements Moveable {
this.stringBounder = stringBounder;
this.root = new Cluster(colorSequence, skinParam, diagram.getEntityFactory().getRootGroup());
this.current = root;
this.graphvizVersion = diagram.getGraphvizVersion();
}
public void addNode(SvekNode node) {
@ -215,14 +212,14 @@ public class DotStringFactory implements Moveable {
root.printCluster1(sb, bibliotekon.allLines(), stringBounder);
for (SvekLine line : bibliotekon.lines0())
line.appendLine(graphvizVersion, sb, dotMode, dotSplines);
line.appendLine(getGraphvizVersion(), sb, dotMode, dotSplines);
root.fillRankMin(rankMin);
root.printCluster2(sb, bibliotekon.allLines(), stringBounder, dotMode, graphvizVersion, umlDiagramType);
root.printCluster2(sb, bibliotekon.allLines(), stringBounder, dotMode, getGraphvizVersion(), umlDiagramType);
printMinRanking(sb);
for (SvekLine line : bibliotekon.lines1())
line.appendLine(graphvizVersion, sb, dotMode, dotSplines);
line.appendLine(getGraphvizVersion(), sb, dotMode, dotSplines);
SvekUtils.println(sb);
sb.append("}");
@ -281,6 +278,24 @@ public class DotStringFactory implements Moveable {
return 35;
}
private GraphvizVersion graphvizVersion;
public GraphvizVersion getGraphvizVersion() {
if (graphvizVersion == null)
graphvizVersion = getGraphvizVersionInternal();
return graphvizVersion;
}
private GraphvizVersion getGraphvizVersionInternal() {
final Graphviz graphviz = GraphvizUtils.create(skinParam, "foo;", "svg");
if (graphviz instanceof GraphvizJs)
return GraphvizJs.getGraphvizVersion(false);
final File f = graphviz.getDotExe();
return GraphvizVersions.getInstance().getVersion(f);
}
public String getSvg(BaseFile basefile, String[] dotOptions) throws IOException {
String dotString = createDotString(dotOptions);
@ -299,7 +314,7 @@ public class DotStringFactory implements Moveable {
}
} catch (GraphvizJsRuntimeException e) {
System.err.println("GraphvizJsRuntimeException");
this.graphvizVersion = GraphvizJs.getGraphvizVersion(true);
graphvizVersion = GraphvizJs.getGraphvizVersion(true);
dotString = createDotString(dotOptions);
graphviz = GraphvizUtils.create(skinParam, dotString, "svg");
baos = new ByteArrayOutputStream();

View File

@ -155,8 +155,7 @@ public final class GeneralImageBuilder {
throw new IllegalStateException();
if (leaf.getLeafType().isLikeClass()) {
final EntityImageClass entityImageClass = new EntityImageClass(graphvizVersion, (ILeaf) leaf, skinParam,
portionShower);
final EntityImageClass entityImageClass = new EntityImageClass((ILeaf) leaf, skinParam, portionShower);
final Neighborhood neighborhood = leaf.getNeighborhood();
if (neighborhood != null)
return new EntityImageProtected(entityImageClass, 20, neighborhood, bibliotekon);
@ -418,7 +417,7 @@ public final class GeneralImageBuilder {
final FontConfiguration labelFont = getFontForLink(link, skinParam);
final SvekLine line = new SvekLine(link, dotStringFactory.getColorSequence(), skinParam, stringBounder,
labelFont, dotStringFactory.getBibliotekon(), pragma);
labelFont, dotStringFactory.getBibliotekon(), pragma, dotStringFactory.getGraphvizVersion());
dotStringFactory.getBibliotekon().addLine(line);
@ -556,8 +555,8 @@ public final class GeneralImageBuilder {
}
return createEntityImageBlock(ent, skinParam, dotData.isHideEmptyDescriptionForState(), dotData,
dotStringFactory.getBibliotekon(), dotData.getGraphvizVersion(), dotData.getUmlDiagramType(),
dotData.getLinks());
dotStringFactory.getBibliotekon(), dotStringFactory.getGraphvizVersion(),
dotData.getUmlDiagramType(), dotData.getLinks());
}
return ent.getSvekImage();
}
@ -568,8 +567,7 @@ public final class GeneralImageBuilder {
if (ent.getLeafType().isLikeClass() == false)
continue;
final IEntityImage im = new EntityImageClass(dotData.getGraphvizVersion(), ent, dotData.getSkinParam(),
dotData);
final IEntityImage im = new EntityImageClass(ent, dotData.getSkinParam(), dotData);
final double w = im.calculateDimension(stringBounder).getWidth();
if (w > result)
result = w;

View File

@ -128,7 +128,7 @@ public final class GroupPngMakerActivity {
final DotData dotData = new DotData(group, links, group.getLeafsDirect(), diagram.getUmlDiagramType(),
skinParam, new InnerGroupHierarchy(), diagram.getColorMapper(), diagram.getEntityFactory(), false,
DotMode.NORMAL, diagram.getNamespaceSeparator(), diagram.getPragma(), diagram.getGraphvizVersion());
DotMode.NORMAL, diagram.getNamespaceSeparator(), diagram.getPragma());
final GeneralImageBuilder svek2 = new GeneralImageBuilder(false, dotData, diagram.getEntityFactory(),
diagram.getSource(), diagram.getPragma(), stringBounder, SName.activityDiagram);

View File

@ -151,7 +151,7 @@ public final class GroupPngMakerState {
final DotData dotData = new DotData(group, links, group.getLeafsDirect(), diagram.getUmlDiagramType(),
skinParam, new InnerGroupHierarchy(), diagram.getColorMapper(), diagram.getEntityFactory(),
diagram.isHideEmptyDescriptionForState(), DotMode.NORMAL, diagram.getNamespaceSeparator(),
diagram.getPragma(), diagram.getGraphvizVersion());
diagram.getPragma());
final GeneralImageBuilder svek2 = new GeneralImageBuilder(false, dotData, diagram.getEntityFactory(),
diagram.getSource(), diagram.getPragma(), stringBounder, SName.stateDiagram);

View File

@ -0,0 +1,174 @@
/* ========================================================================
* 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.svek;
import net.sourceforge.plantuml.Dimension2DDouble;
import net.sourceforge.plantuml.Direction;
import net.sourceforge.plantuml.ISkinParam;
import net.sourceforge.plantuml.awt.geom.Dimension2D;
import net.sourceforge.plantuml.creole.CreoleMode;
import net.sourceforge.plantuml.cucadiagram.Display;
import net.sourceforge.plantuml.cucadiagram.Link;
import net.sourceforge.plantuml.cucadiagram.entity.EntityImpl;
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.UDrawable;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.URectangle;
import net.sourceforge.plantuml.ugraphic.UStroke;
import net.sourceforge.plantuml.ugraphic.UTranslate;
import net.sourceforge.plantuml.ugraphic.color.HColors;
public class Kal implements UDrawable {
private final TextBlock textBlock;
private final Direction position;
private Dimension2D dim;
private UTranslate translate;
private final SvekLine svekLine;
private final EntityImpl entity;
private final Link link;
public Kal(SvekLine svekLine, String text, FontConfiguration font, ISkinParam skinParam, EntityImpl entity,
Link link, StringBounder stringBounder) {
this.svekLine = svekLine;
this.entity = entity;
this.link = link;
this.textBlock = Display.getWithNewlines(text).create7(font, HorizontalAlignment.LEFT, skinParam,
CreoleMode.SIMPLE_LINE);
this.dim = Dimension2DDouble.delta(this.textBlock.calculateDimension(stringBounder), 4, 2);
if (link.getLength() == 1 && link.getEntity1() == entity) {
this.position = Direction.RIGHT;
entity.ensureMargins(new Margins(0, dim.getWidth(), 0, 0));
} else if (link.getLength() == 1 && link.getEntity2() == entity) {
this.position = Direction.LEFT;
entity.ensureMargins(new Margins(dim.getWidth(), 0, 0, 0));
} else if (link.getEntity1() == entity) {
this.position = Direction.DOWN;
entity.ensureMargins(new Margins(0, 0, dim.getHeight(), 0));
} else if (link.getEntity2() == entity) {
this.position = Direction.UP;
entity.ensureMargins(new Margins(0, 0, 0, dim.getHeight()));
} else {
throw new IllegalStateException();
}
entity.addKal(this);
}
public Dimension2D getDimension() {
return dim;
}
@Override
public void drawU(UGraphic ug) {
final URectangle rect = new URectangle(dim);
ug = ug.apply(getTranslate());
ug.apply(HColors.WHITE.bg()).apply(HColors.BLACK).apply(new UStroke(0.5)).draw(rect);
textBlock.drawU(ug.apply(new UTranslate(2, 1)));
}
private UTranslate getTranslate() {
return getTextDelta().compose(translate);
}
public double getX1() {
return getTranslate().getDx() - 5;
}
public double getX2() {
return getX1() + dim.getWidth() + 10;
}
private UTranslate getTextDelta() {
switch (position) {
case RIGHT:
return UTranslate.dy(-dim.getHeight() / 2);
case LEFT:
return new UTranslate(-dim.getWidth() + 0.5, -dim.getHeight() / 2);
case DOWN:
return UTranslate.dx(-dim.getWidth() / 2);
case UP:
return new UTranslate(-dim.getWidth() / 2, -dim.getHeight() + 0.5);
default:
throw new IllegalStateException();
}
}
public final Direction getPosition() {
return position;
}
public void setTranslate(UTranslate translate) {
this.translate = translate;
}
public double overlapx(Kal other) {
if (this.position != other.position)
throw new IllegalArgumentException();
if (other.getX1() >= this.getX1() && other.getX1() <= this.getX2())
return this.getX2() - other.getX1();
if (other.getX2() >= this.getX1() && other.getX2() <= this.getX2())
return this.getX1() - other.getX2();
if (this.getX1() >= other.getX1() && this.getX1() <= other.getX2())
return other.getX2() - this.getX1();
if (this.getX2() >= other.getX1() && this.getX2() <= other.getX2())
return other.getX1() - this.getX2();
return 0;
}
public void moveX(double dx) {
if (dx == 0)
return;
this.translate = this.translate.compose(UTranslate.dx(dx));
if (link.getEntity1() == entity)
svekLine.moveStartPoint(dx, 0);
}
}

View File

@ -0,0 +1,128 @@
/* ========================================================================
* 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.svek;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class LineOfSegments {
static private class Segment implements Comparable<Segment> {
private final int idx;
private double middle;
private final double halfSize;
private Segment(int idx, double x1, double x2) {
this.idx = idx;
this.middle = (x1 + x2) / 2;
this.halfSize = (x2 - x1) / 2;
}
@Override
public int compareTo(Segment other) {
return Double.compare(this.middle, other.middle);
}
private double overlap(Segment other) {
final double distance = other.middle - this.middle;
if (distance < 0)
throw new IllegalArgumentException();
final double diff = distance - this.halfSize - other.halfSize;
if (diff > 0)
return 0;
return -diff;
}
private void push(double delta) {
middle += delta;
}
}
private final List<Segment> all = new ArrayList<>();
public void addSegment(double x1, double x2) {
all.add(new Segment(all.size(), x1, x2));
}
public double getMean() {
double sum = 0;
for (Segment seg : all)
sum += seg.middle;
return sum / all.size();
}
void solveOverlapsInternal() {
if (all.size() < 2)
return;
Collections.sort(all);
for (int i = 0; i < all.size(); i++)
if (oneLoop() == false)
return;
}
private boolean oneLoop() {
for (int i = all.size() - 2; i >= 0; i--) {
final Segment seg1 = all.get(i);
final Segment seg2 = all.get(i + 1);
final double overlap = seg1.overlap(seg2);
if (overlap > 0) {
for (int k = i + 1; k < all.size(); k++)
all.get(k).push(overlap);
return true;
}
}
return false;
}
public double[] solveOverlaps() {
final double mean1 = getMean();
solveOverlapsInternal();
final double mean2 = getMean();
final double diff = mean1 - mean2;
if (diff != 0)
for (Segment seg : all)
seg.push(diff);
final double[] result = new double[all.size()];
for (Segment seg : all)
result[seg.idx] = seg.middle - seg.halfSize;
return result;
}
}

View File

@ -73,6 +73,7 @@ import net.sourceforge.plantuml.cucadiagram.NoteLinkStrategy;
import net.sourceforge.plantuml.cucadiagram.Stereotype;
import net.sourceforge.plantuml.cucadiagram.dot.DotSplines;
import net.sourceforge.plantuml.cucadiagram.dot.GraphvizVersion;
import net.sourceforge.plantuml.cucadiagram.entity.EntityImpl;
import net.sourceforge.plantuml.descdiagram.command.StringWithArrow;
import net.sourceforge.plantuml.graphic.FontConfiguration;
import net.sourceforge.plantuml.graphic.HorizontalAlignment;
@ -211,7 +212,21 @@ public class SvekLine implements Moveable, Hideable, GuideLine {
}
public SvekLine(Link link, ColorSequence colorSequence, ISkinParam skinParam, StringBounder stringBounder,
FontConfiguration font, Bibliotekon bibliotekon, Pragma pragma) {
FontConfiguration font, Bibliotekon bibliotekon, Pragma pragma, GraphvizVersion graphvizVersion) {
if (graphvizVersion.useShieldForQuantifier() && link.getLinkArg().getQualifier1() != null)
((EntityImpl) link.getEntity1()).ensureMargins(Margins.uniform(16));
if (graphvizVersion.useShieldForQuantifier() && link.getLinkArg().getQualifier2() != null)
((EntityImpl) link.getEntity2()).ensureMargins(Margins.uniform(16));
if (link.getLinkArg().getKal1() != null)
this.kal1 = new Kal(this, link.getLinkArg().getKal1(), font, skinParam, (EntityImpl) link.getEntity1(),
link, stringBounder);
if (link.getLinkArg().getKal2() != null)
this.kal2 = new Kal(this, link.getLinkArg().getKal2(), font, skinParam, (EntityImpl) link.getEntity2(),
link, stringBounder);
this.link = Objects.requireNonNull(link);
this.skinParam = skinParam;
@ -308,15 +323,10 @@ public class SvekLine implements Moveable, Hideable, GuideLine {
else
this.labelShield = 7;
if (link.getLinkArg().getKal1() != null) {
this.kal1 = Display.getWithNewlines(link.getLinkArg().getKal1()).create7(font, HorizontalAlignment.LEFT,
skinParam, CreoleMode.SIMPLE_LINE);
}
}
private TextBlock kal1;
private Kal kal1;
private Kal kal2;
private TextBlock addVisibilityModifier(TextBlock block, Link link, ISkinParam skinParam) {
final VisibilityModifier visibilityModifier = link.getVisibilityModifier();
@ -766,17 +776,18 @@ public class SvekLine implements Moveable, Hideable, GuideLine {
link.getLinkConstraint().drawMe(ug, skinParam);
}
if (kal1 != null) {
final Dimension2D dim1 = kal1.calculateDimension(stringBounder);
final URectangle rect = new URectangle(dim1);
final UTranslate tr = new UTranslate(dotPath.getStartPoint()).compose(new UTranslate(dx, dy))
.compose(UTranslate.dx(-dim1.getWidth() / 2));
final UGraphic ug1 = ug.apply(tr);
ug1.apply(HColors.WHITE.bg()).draw(rect);
kal1.drawU(ug1);
ug.closeGroup();
}
ug.closeGroup();
public void computeKal() {
if (kal1 != null) {
final UTranslate tr = new UTranslate(dotPath.getStartPoint()).compose(new UTranslate(dx, dy));
kal1.setTranslate(tr);
}
if (kal2 != null) {
final UTranslate tr = new UTranslate(dotPath.getEndPoint()).compose(new UTranslate(dx, dy));
kal2.setTranslate(tr);
}
}
private List<Point2D> getSquare(double x, double y) {
@ -1053,4 +1064,12 @@ public class SvekLine implements Moveable, Hideable, GuideLine {
return link.getStereotype();
}
public void moveStartPoint(double dx, double dy) {
dotPath.moveStartPoint(dx, dy);
}
public void moveEndPoint(double dx, double dy) {
dotPath.moveEndPoint(dx, dy);
}
}

View File

@ -38,7 +38,7 @@ package net.sourceforge.plantuml.svek;
import java.awt.geom.Point2D;
import java.util.List;
import net.sourceforge.plantuml.Dimension2DDouble;
import net.sourceforge.plantuml.Direction;
import net.sourceforge.plantuml.Hideable;
import net.sourceforge.plantuml.StringUtils;
import net.sourceforge.plantuml.awt.geom.Dimension2D;
@ -52,23 +52,24 @@ import net.sourceforge.plantuml.svek.image.AbstractEntityImageBorder;
import net.sourceforge.plantuml.svek.image.EntityImageDescription;
import net.sourceforge.plantuml.svek.image.EntityImageLollipopInterface;
import net.sourceforge.plantuml.ugraphic.Shadowable;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.UPolygon;
public class SvekNode implements Positionable, IShapePseudo, Hideable {
private final ShapeType type;
private final double width;
private final double height;
private Dimension2D dimImage;
private final String uid;
private final int color;
private double minX;
private double minY;
private final Margins shield;
private Margins shield;
private final EntityPosition entityPosition;
private final IEntityImage image;
private final StringBounder stringBounder;
public EntityPosition getEntityPosition() {
return entityPosition;
@ -95,19 +96,14 @@ public class SvekNode implements Positionable, IShapePseudo, Hideable {
private final IGroup group;
SvekNode(ILeaf ent, IEntityImage image, ColorSequence colorSequence, StringBounder stringBounder) {
final Dimension2D dim = image.calculateDimension(stringBounder);
this.stringBounder = stringBounder;
this.entityPosition = ent.getEntityPosition();
this.image = image;
this.top = ent.isTop();
this.type = image.getShapeType();
this.width = dim.getWidth();
this.height = dim.getHeight();
this.color = colorSequence.getValue();
this.uid = String.format("sh%04d", color);
this.shield = image.getShield(stringBounder);
if (shield.isZero() == false && type != ShapeType.RECTANGLE && type != ShapeType.RECTANGLE_HTML_FOR_PORTS
&& type != ShapeType.RECTANGLE_WITH_CIRCLE_INSIDE)
throw new IllegalArgumentException();
if (((EntityImpl) ent).getOriginalGroup() == null) {
this.group = null;
@ -118,16 +114,22 @@ public class SvekNode implements Positionable, IShapePseudo, Hideable {
}
}
private Dimension2D getDimImage() {
if (dimImage == null)
this.dimImage = image.calculateDimension(stringBounder);
return dimImage;
}
public final ShapeType getType() {
return type;
}
public final double getWidth() {
return width;
return getDimImage().getWidth();
}
public final double getHeight() {
return height;
return getDimImage().getHeight();
}
public void appendShape(StringBuilder sb, StringBounder stringBounder) {
@ -139,7 +141,7 @@ public class SvekNode implements Positionable, IShapePseudo, Hideable {
appendHtml(sb);
return;
}
if (type == ShapeType.RECTANGLE && shield.isZero() == false) {
if (type == ShapeType.RECTANGLE && shield().isZero() == false) {
appendHtml(sb);
return;
}
@ -158,6 +160,17 @@ public class SvekNode implements Positionable, IShapePseudo, Hideable {
SvekUtils.println(sb);
}
private Margins shield() {
if (shield == null) {
this.shield = image.getShield(stringBounder);
if (shield.isZero() == false && type != ShapeType.RECTANGLE && type != ShapeType.RECTANGLE_HTML_FOR_PORTS
&& type != ShapeType.RECTANGLE_WITH_CIRCLE_INSIDE)
throw new IllegalStateException();
}
return shield;
}
private void appendHtml(StringBuilder sb) {
sb.append(uid);
sb.append(" [");
@ -175,20 +188,20 @@ public class SvekNode implements Positionable, IShapePseudo, Hideable {
sb.append("<TABLE BORDER=\"0\" CELLBORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"0\">");
sb.append("<TR>");
appendTd(sb);
appendTd(sb, 1, shield.getY1());
appendTd(sb, 1, shield().getY1());
appendTd(sb);
sb.append("</TR>");
sb.append("<TR>");
appendTd(sb, shield.getX1(), 1);
appendTd(sb, shield().getX1(), 1);
sb.append("<TD BGCOLOR=\"" + StringUtils.sharp000000(color) + "\"");
sb.append(" FIXEDSIZE=\"TRUE\" WIDTH=\"" + getWidth() + "\" HEIGHT=\"" + getHeight() + "\"");
sb.append(" PORT=\"h\">");
sb.append("</TD>");
appendTd(sb, shield.getX2(), 1);
appendTd(sb, shield().getX2(), 1);
sb.append("</TR>");
sb.append("<TR>");
appendTd(sb);
appendTd(sb, 1, shield.getY2());
appendTd(sb, 1, shield().getY2());
appendTd(sb);
sb.append("</TR>");
sb.append("</TABLE>");
@ -247,7 +260,7 @@ public class SvekNode implements Positionable, IShapePseudo, Hideable {
}
private void appendShapeInternal(StringBuilder sb) {
if (type == ShapeType.RECTANGLE && shield.isZero() == false)
if (type == ShapeType.RECTANGLE && shield().isZero() == false)
throw new UnsupportedOperationException();
else if (type == ShapeType.RECTANGLE || type == ShapeType.RECTANGLE_WITH_CIRCLE_INSIDE
|| type == ShapeType.FOLDER)
@ -301,15 +314,15 @@ public class SvekNode implements Positionable, IShapePseudo, Hideable {
}
public Dimension2D getSize() {
return new Dimension2DDouble(width, height);
return getDimImage();
}
public ClusterPosition getClusterPosition() {
return new ClusterPosition(minX, minY, minX + width, minY + height);
return new ClusterPosition(minX, minY, minX + getWidth(), minY + getHeight());
}
public boolean isShielded() {
return shield.isZero() == false;
return shield().isZero() == false;
}
public void moveSvek(double deltaX, double deltaY) {
@ -349,7 +362,7 @@ public class SvekNode implements Positionable, IShapePseudo, Hideable {
if (getType() != ShapeType.FOLDER)
return pt;
final ClusterPosition clusterPosition = new ClusterPosition(minX, minY, minX + width, minY + height);
final ClusterPosition clusterPosition = new ClusterPosition(minX, minY, minX + getWidth(), minY + getHeight());
if (clusterPosition.isPointJustUpper(pt)) {
final Dimension2D dimName = ((EntityImageDescription) image).getNameDimension(stringBounder);
if (pt.getX() < minX + dimName.getWidth())
@ -367,4 +380,41 @@ public class SvekNode implements Positionable, IShapePseudo, Hideable {
public void addImpact(double angle) {
((EntityImageLollipopInterface) image).addImpact(angle);
}
public void drawKals(UGraphic ug) {
if (leaf instanceof EntityImpl == false)
return;
drawList(ug, ((EntityImpl) leaf).getKals(Direction.DOWN));
drawList(ug, ((EntityImpl) leaf).getKals(Direction.UP));
drawList(ug, ((EntityImpl) leaf).getKals(Direction.LEFT));
drawList(ug, ((EntityImpl) leaf).getKals(Direction.RIGHT));
}
public void fixOverlap() {
if (leaf instanceof EntityImpl == false)
return;
fixHoverlap(((EntityImpl) leaf).getKals(Direction.DOWN));
fixHoverlap(((EntityImpl) leaf).getKals(Direction.UP));
}
private void fixHoverlap(final List<Kal> list) {
final LineOfSegments los = new LineOfSegments();
for (Kal kal : list)
los.addSegment(kal.getX1(), kal.getX2());
final double[] res = los.solveOverlaps();
for (int i = 0; i < list.size(); i++) {
final Kal kal = list.get(i);
final double diff = res[i] - kal.getX1();
kal.moveX(diff);
}
}
private void drawList(UGraphic ug, final List<Kal> list) {
for (Kal kal : list)
kal.drawU(ug);
}
}

View File

@ -93,6 +93,8 @@ public final class SvekResult extends AbstractTextBlock implements IEntityImage
final Set<String> ids = new HashSet<>();
computeKal();
for (SvekLine line : dotStringFactory.getBibliotekon().allLines()) {
final UGraphic ug2 = line.isHidden() ? ug.apply(UHidden.HIDDEN) : ug;
@ -105,6 +107,16 @@ public final class SvekResult extends AbstractTextBlock implements IEntityImage
line.drawU(ug2, styleLine.getStroke(), color, ids);
}
for (SvekNode node : dotStringFactory.getBibliotekon().allNodes())
node.drawKals(ug);
}
private void computeKal() {
for (SvekLine line : dotStringFactory.getBibliotekon().allLines())
line.computeKal();
for (SvekNode node : dotStringFactory.getBibliotekon().allNodes())
node.fixOverlap();
}
private StyleSignature getDefaultStyleDefinition(Stereotype stereotype) {

View File

@ -40,6 +40,7 @@ import java.util.EnumMap;
import java.util.Map;
import net.sourceforge.plantuml.Dimension2DDouble;
import net.sourceforge.plantuml.Direction;
import net.sourceforge.plantuml.FontParam;
import net.sourceforge.plantuml.ISkinParam;
import net.sourceforge.plantuml.LineConfigurable;
@ -50,7 +51,7 @@ import net.sourceforge.plantuml.cucadiagram.EntityPortion;
import net.sourceforge.plantuml.cucadiagram.ILeaf;
import net.sourceforge.plantuml.cucadiagram.LeafType;
import net.sourceforge.plantuml.cucadiagram.PortionShower;
import net.sourceforge.plantuml.cucadiagram.dot.GraphvizVersion;
import net.sourceforge.plantuml.cucadiagram.entity.EntityImpl;
import net.sourceforge.plantuml.graphic.InnerStrategy;
import net.sourceforge.plantuml.graphic.StringBounder;
import net.sourceforge.plantuml.graphic.TextBlock;
@ -60,6 +61,7 @@ import net.sourceforge.plantuml.style.SName;
import net.sourceforge.plantuml.style.Style;
import net.sourceforge.plantuml.style.StyleSignatureBasic;
import net.sourceforge.plantuml.svek.AbstractEntityImage;
import net.sourceforge.plantuml.svek.Kal;
import net.sourceforge.plantuml.svek.Margins;
import net.sourceforge.plantuml.svek.Ports;
import net.sourceforge.plantuml.svek.ShapeType;
@ -78,8 +80,7 @@ import net.sourceforge.plantuml.ugraphic.color.HColors;
public class EntityImageClass extends AbstractEntityImage implements Stencil, WithPorts {
final private TextBlock body;
// final private Margins shield;
final private GraphvizVersion version;
final private EntityImageClassHeader header;
final private Url url;
final private double roundCorner;
@ -87,13 +88,12 @@ public class EntityImageClass extends AbstractEntityImage implements Stencil, Wi
final private LineConfigurable lineConfig;
public EntityImageClass(GraphvizVersion version, ILeaf entity, ISkinParam skinParam, PortionShower portionShower) {
public EntityImageClass(ILeaf entity, ISkinParam skinParam, PortionShower portionShower) {
super(entity, entity.getColors().mute(skinParam));
this.leafType = entity.getLeafType();
this.lineConfig = entity;
this.roundCorner = getStyle().value(PName.RoundCorner).asDouble();
this.version = version;
final boolean showMethods = portionShower.showPortion(EntityPortion.METHOD, entity);
final boolean showFields = portionShower.showPortion(EntityPortion.FIELD, entity);
@ -112,7 +112,21 @@ public class EntityImageClass extends AbstractEntityImage implements Stencil, Wi
width = getSkinParam().minClassWidth();
final double height = dimBody.getHeight() + dimHeader.getHeight();
return new Dimension2DDouble(width, height);
return new Dimension2DDouble(Math.max(width, getKalWidth() * 1.3), height);
// return new Dimension2DDouble(width + getKalWidth(), height);
}
private double getKalWidth() {
double widthUp = 0;
double widthDown = 0;
for (Kal kal : ((EntityImpl) getEntity()).getKals(Direction.UP))
widthUp += kal.getDimension().getWidth();
for (Kal kal : ((EntityImpl) getEntity()).getKals(Direction.DOWN))
widthDown += kal.getDimension().getWidth();
return Math.max(widthUp, widthDown);
}
@Override
@ -241,10 +255,7 @@ public class EntityImageClass extends AbstractEntityImage implements Stencil, Wi
@Override
public Margins getShield(StringBounder stringBounder) {
if (version != null && version.useShield())
return ((ILeaf) getEntity()).getMargins();
return Margins.NONE;
}
public double getStartingX(StringBounder stringBounder, double y) {

View File

@ -186,7 +186,7 @@ public class TContext {
functionsSet.addFunction(new Dec2hex());
functionsSet.addFunction(new HslColor());
functionsSet.addFunction(new LoadJson());
functionsSet.addFunction(new LoadJsonLegacy());
// functionsSet.addFunction(new LoadJsonLegacy());
functionsSet.addFunction(new Chr());
functionsSet.addFunction(new Size());
functionsSet.addFunction(new GetJsonKey());

View File

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

View File

@ -122,7 +122,7 @@ public class GraphvizJs implements Graphviz {
public static GraphvizVersion getGraphvizVersion(final boolean modeSafe) {
return new GraphvizVersion() {
public boolean useShield() {
public boolean useShieldForQuantifier() {
return true;
}