diff --git a/src/net/sourceforge/plantuml/OptionFlags.java b/src/net/sourceforge/plantuml/OptionFlags.java index 24211dc90..09c2a5cf1 100644 --- a/src/net/sourceforge/plantuml/OptionFlags.java +++ b/src/net/sourceforge/plantuml/OptionFlags.java @@ -47,6 +47,8 @@ import net.sourceforge.plantuml.security.SecurityUtils; public class OptionFlags { + static public final boolean USE_KERMOR = false; + private static final OptionFlags singleton = new OptionFlags(); // static public final boolean PBBACK = false; diff --git a/src/net/sourceforge/plantuml/activitydiagram/command/CommandLinkActivity.java b/src/net/sourceforge/plantuml/activitydiagram/command/CommandLinkActivity.java index 4e53cbf09..3b451e1d4 100644 --- a/src/net/sourceforge/plantuml/activitydiagram/command/CommandLinkActivity.java +++ b/src/net/sourceforge/plantuml/activitydiagram/command/CommandLinkActivity.java @@ -197,9 +197,8 @@ public class CommandLinkActivity extends SingleLineCommand2 { if (arg.get("STAR" + suf, 0) != null) { final String suppId = arg.get("STAR" + suf, 1); if (start) { - if (suppId != null) - diagram.getStart().setTop(true); - +// if (suppId != null) +// diagram.getStart().setTop(true); return diagram.getStart(); } return diagram.getEnd(suppId); diff --git a/src/net/sourceforge/plantuml/command/note/CommandFactoryNoteOnEntity.java b/src/net/sourceforge/plantuml/command/note/CommandFactoryNoteOnEntity.java index 092053f00..690d68814 100644 --- a/src/net/sourceforge/plantuml/command/note/CommandFactoryNoteOnEntity.java +++ b/src/net/sourceforge/plantuml/command/note/CommandFactoryNoteOnEntity.java @@ -37,6 +37,7 @@ package net.sourceforge.plantuml.command.note; import net.sourceforge.plantuml.ColorParam; import net.sourceforge.plantuml.LineLocation; +import net.sourceforge.plantuml.OptionFlags; import net.sourceforge.plantuml.StringUtils; import net.sourceforge.plantuml.Url; import net.sourceforge.plantuml.UrlBuilder; @@ -227,6 +228,24 @@ public final class CommandFactoryNoteOnEntity implements SingleMultiFactoryComma } } + final Position position = Position.valueOf(StringUtils.goUpperCase(pos)) + .withRankdir(diagram.getSkinParam().getRankdir()); + Colors colors = color().getColor(diagram.getSkinParam().getThemeStyle(), line0, + diagram.getSkinParam().getIHtmlColorSet()); + + final String stereotypeString = line0.get("STEREO", 0); + Stereotype stereotype = null; + if (stereotypeString != null) { + stereotype = Stereotype.build(stereotypeString); + colors = colors.applyStereotypeForNote(stereotype, diagram.getSkinParam(), ColorParam.noteBackground, + ColorParam.noteBorder); + } + + if (OptionFlags.USE_KERMOR && cl1.isGroup()) { + cl1.addNote(strings.toDisplay(), position, colors); + return CommandExecutionResult.ok(); + } + final String tmp = diagram.getUniqueSequence("GMN"); final Ident idNewLong = diagram.buildLeafIdent(tmp); final IEntity note; @@ -235,16 +254,8 @@ public final class CommandFactoryNoteOnEntity implements SingleMultiFactoryComma else note = diagram.createLeaf(idNewLong, diagram.buildCode(tmp), strings.toDisplay(), LeafType.NOTE, null); - Colors colors = color().getColor(diagram.getSkinParam().getThemeStyle(), line0, - diagram.getSkinParam().getIHtmlColorSet()); - - final String stereotypeString = line0.get("STEREO", 0); - if (stereotypeString != null) { - final Stereotype stereotype = Stereotype.build(stereotypeString); - colors = colors.applyStereotypeForNote(stereotype, diagram.getSkinParam(), ColorParam.noteBackground, - ColorParam.noteBorder); + if (stereotypeString != null) note.setStereotype(stereotype); - } note.setColors(colors); if (url != null) @@ -252,8 +263,6 @@ public final class CommandFactoryNoteOnEntity implements SingleMultiFactoryComma CommandCreateClassMultilines.addTags(note, line0.get("TAGS", 0)); - final Position position = Position.valueOf(StringUtils.goUpperCase(pos)) - .withRankdir(diagram.getSkinParam().getRankdir()); final Link link; final LinkType type = new LinkType(LinkDecor.NONE, LinkDecor.NONE).goDashed(); diff --git a/src/net/sourceforge/plantuml/command/note/CommandFactoryNoteOnLink.java b/src/net/sourceforge/plantuml/command/note/CommandFactoryNoteOnLink.java index a7ade9117..94d7519c8 100644 --- a/src/net/sourceforge/plantuml/command/note/CommandFactoryNoteOnLink.java +++ b/src/net/sourceforge/plantuml/command/note/CommandFactoryNoteOnLink.java @@ -52,6 +52,7 @@ 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.CucaDiagram; +import net.sourceforge.plantuml.cucadiagram.CucaNote; import net.sourceforge.plantuml.cucadiagram.Link; import net.sourceforge.plantuml.graphic.color.ColorParser; import net.sourceforge.plantuml.graphic.color.ColorType; @@ -132,13 +133,13 @@ public final class CommandFactoryNoteOnLink implements SingleMultiFactoryCommand private CommandExecutionResult executeInternal(CucaDiagram diagram, BlocLines note, final RegexResult arg) throws NoSuchColorException { final Link link = diagram.getLastLink(); - if (link == null) { + if (link == null) return CommandExecutionResult.error("No link defined"); - } + Position position = Position.BOTTOM; - if (arg.get("POSITION", 0) != null) { + if (arg.get("POSITION", 0) != null) position = Position.valueOf(StringUtils.goUpperCase(arg.get("POSITION", 0))); - } + Url url = null; if (arg.get("URL", 0) != null) { final UrlBuilder urlBuilder = new UrlBuilder(diagram.getSkinParam().getValue("topurl"), UrlMode.STRICT); @@ -146,7 +147,7 @@ public final class CommandFactoryNoteOnLink implements SingleMultiFactoryCommand } final Colors colors = color().getColor(diagram.getSkinParam().getThemeStyle(), arg, diagram.getSkinParam().getIHtmlColorSet()); - link.addNote(note.toDisplay(), position, colors); + link.addNote(CucaNote.build(note.toDisplay(), position, colors)); return CommandExecutionResult.ok(); } diff --git a/src/net/sourceforge/plantuml/cucadiagram/CucaNote.java b/src/net/sourceforge/plantuml/cucadiagram/CucaNote.java new file mode 100644 index 000000000..33dee16fc --- /dev/null +++ b/src/net/sourceforge/plantuml/cucadiagram/CucaNote.java @@ -0,0 +1,79 @@ +/* ======================================================================== + * 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.cucadiagram; + +import net.sourceforge.plantuml.command.Position; +import net.sourceforge.plantuml.graphic.color.Colors; + +public class CucaNote { + + private final Display display; + private final Position position; + private final Colors colors; + private final NoteLinkStrategy strategy; + + private CucaNote(Display display, Position position, Colors colors, NoteLinkStrategy strategy) { + this.display = display; + this.position = position; + this.colors = colors; + this.strategy = strategy; + } + + public static CucaNote build(Display display, Position position, Colors colors) { + return new CucaNote(display, position, colors, NoteLinkStrategy.NORMAL); + } + + public CucaNote withStrategy(NoteLinkStrategy strategy) { + return new CucaNote(display, position, colors, strategy); + } + + public final Display getDisplay() { + return display; + } + + public final NoteLinkStrategy getStrategy() { + return strategy; + } + + public final Colors getColors() { + return colors; + } + + public final Position getPosition() { + return position; + } + +} diff --git a/src/net/sourceforge/plantuml/cucadiagram/EntityPosition.java b/src/net/sourceforge/plantuml/cucadiagram/EntityPosition.java index a083fb2fd..f7f44f010 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/EntityPosition.java +++ b/src/net/sourceforge/plantuml/cucadiagram/EntityPosition.java @@ -55,6 +55,30 @@ public enum EntityPosition { public static final double RADIUS = 6; + public static EnumSet getInputs() { + return EnumSet.of(ENTRY_POINT, INPUT_PIN, EXPANSION_INPUT, PORTIN); + } + + public static EnumSet getOutputs() { + return EnumSet.of(EXIT_POINT, OUTPUT_PIN, EXPANSION_OUTPUT, PORTOUT); + } + + public static EnumSet getNormals() { + return EnumSet.of(NORMAL); + } + + public boolean isNormal() { + return this == NORMAL; + } + + public boolean isInput() { + return getInputs().contains(this); + } + + public boolean isOutput() { + return getOutputs().contains(this); + } + public void drawSymbol(UGraphic ug, Rankdir rankdir) { if (this == NORMAL) { throw new IllegalStateException(); @@ -70,7 +94,7 @@ public enum EntityPosition { drawLine(ug, getPointOnCircle(xc, yc, -Math.PI / 4, radius), getPointOnCircle(xc, yc, Math.PI - Math.PI / 4, radius)); } - } else if (this == INPUT_PIN || this == OUTPUT_PIN /*|| this == PORT*/) { + } else if (this == INPUT_PIN || this == OUTPUT_PIN /* || this == PORT */) { final Shadowable rectangle = new URectangle(RADIUS * 2, RADIUS * 2); ug.draw(rectangle); } else if (this == EXPANSION_INPUT || this == EXPANSION_OUTPUT) { @@ -151,20 +175,12 @@ public enum EntityPosition { return EntityPosition.NORMAL; } - public static EnumSet getInputs() { - return EnumSet.of(ENTRY_POINT, INPUT_PIN, EXPANSION_INPUT, PORTIN); - } - - public static EnumSet getOutputs() { - return EnumSet.of(EXIT_POINT, OUTPUT_PIN, EXPANSION_OUTPUT, PORTOUT); - } - // public static EnumSet getSame() { // return EnumSet.of(PORT); // } // public boolean isPort() { - return /*this == PORT ||*/ this == PORTIN || this == PORTOUT; + return /* this == PORT || */ this == PORTIN || this == PORTOUT; } public boolean usePortP() { diff --git a/src/net/sourceforge/plantuml/cucadiagram/GroupRoot.java b/src/net/sourceforge/plantuml/cucadiagram/GroupRoot.java index 6f6363ece..bdc9e5cba 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/GroupRoot.java +++ b/src/net/sourceforge/plantuml/cucadiagram/GroupRoot.java @@ -45,6 +45,7 @@ import java.util.Set; import net.sourceforge.plantuml.ISkinParam; import net.sourceforge.plantuml.LineLocation; import net.sourceforge.plantuml.Url; +import net.sourceforge.plantuml.command.Position; import net.sourceforge.plantuml.cucadiagram.entity.EntityFactory; import net.sourceforge.plantuml.graphic.FontConfiguration; import net.sourceforge.plantuml.graphic.USymbol; @@ -334,4 +335,19 @@ public class GroupRoot implements IGroup { public Stereostyles getStereostyles() { throw new UnsupportedOperationException(); } + + @Override + public void addNote(Display note, Position position, Colors colors) { + throw new UnsupportedOperationException(); + } + + @Override + public EntityPosition getEntityPosition() { + throw new UnsupportedOperationException(); + } + + @Override + public List getNotes() { + throw new UnsupportedOperationException(); + } } diff --git a/src/net/sourceforge/plantuml/cucadiagram/IEntity.java b/src/net/sourceforge/plantuml/cucadiagram/IEntity.java index 296feceb5..1d76d4c4c 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/IEntity.java +++ b/src/net/sourceforge/plantuml/cucadiagram/IEntity.java @@ -35,6 +35,7 @@ */ package net.sourceforge.plantuml.cucadiagram; +import java.util.List; import java.util.Map; import java.util.Set; @@ -44,7 +45,9 @@ import net.sourceforge.plantuml.LineLocation; import net.sourceforge.plantuml.Removeable; import net.sourceforge.plantuml.SpecificBackcolorable; import net.sourceforge.plantuml.Url; +import net.sourceforge.plantuml.command.Position; import net.sourceforge.plantuml.graphic.USymbol; +import net.sourceforge.plantuml.graphic.color.Colors; public interface IEntity extends SpecificBackcolorable, Hideable, Removeable, LineConfigurable { @@ -104,4 +107,10 @@ public interface IEntity extends SpecificBackcolorable, Hideable, Removeable, Li public Stereostyles getStereostyles(); + public void addNote(Display note, Position position, Colors colors); + + public EntityPosition getEntityPosition(); + + public List getNotes(); + } diff --git a/src/net/sourceforge/plantuml/cucadiagram/ILeaf.java b/src/net/sourceforge/plantuml/cucadiagram/ILeaf.java index 900c083a3..c2a2247d0 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/ILeaf.java +++ b/src/net/sourceforge/plantuml/cucadiagram/ILeaf.java @@ -49,10 +49,6 @@ public interface ILeaf extends IEntity { public void setContainer(IGroup container); - public boolean isTop(); - - public void setTop(boolean top); - public Margins getMargins(); public int getXposition(); diff --git a/src/net/sourceforge/plantuml/cucadiagram/Link.java b/src/net/sourceforge/plantuml/cucadiagram/Link.java index 5cf6417ae..c909934e4 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/Link.java +++ b/src/net/sourceforge/plantuml/cucadiagram/Link.java @@ -45,14 +45,12 @@ import net.sourceforge.plantuml.Removeable; 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; import net.sourceforge.plantuml.graphic.TextBlock; import net.sourceforge.plantuml.graphic.USymbolInterface; -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; @@ -75,10 +73,7 @@ public class Link extends WithLinkType implements Hideable, Removeable { final private String uid; - private Display note; - private Position notePosition; - private Colors noteColors; - private NoteLinkStrategy noteLinkStrategy; + private CucaNote note; private boolean invis = false; private double weight = 1.0; @@ -125,6 +120,11 @@ public class Link extends WithLinkType implements Hideable, Removeable { this.uid = "LNK" + ((EntityImpl) cl1).getDiagram().getUniqueSequence(); this.linkArg = linkArg; + + if (OptionFlags.USE_KERMOR) { + if (cl1.getEntityPosition().isNormal() == false ^ cl2.getEntityPosition().isNormal() == false) + setConstraint(false); + } } public Link getInv() { @@ -293,34 +293,17 @@ public class Link extends WithLinkType implements Hideable, Removeable { this.weight = weight; } - public final Display getNote() { + public final CucaNote getNote() { return note; } - public final NoteLinkStrategy getNoteLinkStrategy() { - return noteLinkStrategy; - } - - public final Colors getNoteColors() { - return noteColors; - } - - public final Position getNotePosition() { - return notePosition; - } - - public final void addNote(Display note, Position position, Colors colors) { + public final void addNote(CucaNote note) { this.note = note; - this.notePosition = position; - this.noteColors = colors; - this.noteLinkStrategy = NoteLinkStrategy.NORMAL; } public final void addNoteFrom(Link other, NoteLinkStrategy strategy) { - this.note = other.note; - this.notePosition = other.notePosition; - this.noteColors = other.noteColors; - this.noteLinkStrategy = strategy; + if (other.note != null) + this.note = other.note.withStrategy(strategy); } public boolean isAutoLinkOfAGroup() { @@ -419,15 +402,14 @@ public class Link extends WithLinkType implements Hideable, Removeable { } public boolean hasEntryPoint() { - return (getEntity1().isGroup() == false && ((ILeaf) getEntity1()).getEntityPosition() != EntityPosition.NORMAL) - || (getEntity2().isGroup() == false - && ((ILeaf) getEntity2()).getEntityPosition() != EntityPosition.NORMAL); + return (getEntity1().isGroup() == false && getEntity1().getEntityPosition() != EntityPosition.NORMAL) + || (getEntity2().isGroup() == false && getEntity2().getEntityPosition() != EntityPosition.NORMAL); } public boolean hasTwoEntryPointsSameContainer() { return getEntity1().isGroup() == false && getEntity2().isGroup() == false - && ((ILeaf) getEntity1()).getEntityPosition() != EntityPosition.NORMAL - && ((ILeaf) getEntity2()).getEntityPosition() != EntityPosition.NORMAL + && getEntity1().getEntityPosition() != EntityPosition.NORMAL + && getEntity2().getEntityPosition() != EntityPosition.NORMAL && getEntity1().getParentContainer() == getEntity2().getParentContainer(); } diff --git a/src/net/sourceforge/plantuml/cucadiagram/entity/EntityImpl.java b/src/net/sourceforge/plantuml/cucadiagram/entity/EntityImpl.java index f91a21dc8..8b47c4a29 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/entity/EntityImpl.java +++ b/src/net/sourceforge/plantuml/cucadiagram/entity/EntityImpl.java @@ -55,9 +55,11 @@ import net.sourceforge.plantuml.ISkinParam; import net.sourceforge.plantuml.LineLocation; import net.sourceforge.plantuml.StringUtils; import net.sourceforge.plantuml.Url; +import net.sourceforge.plantuml.command.Position; import net.sourceforge.plantuml.cucadiagram.Bodier; import net.sourceforge.plantuml.cucadiagram.Code; import net.sourceforge.plantuml.cucadiagram.CucaDiagram; +import net.sourceforge.plantuml.cucadiagram.CucaNote; import net.sourceforge.plantuml.cucadiagram.Display; import net.sourceforge.plantuml.cucadiagram.DisplayPositioned; import net.sourceforge.plantuml.cucadiagram.EntityPosition; @@ -108,8 +110,6 @@ final public class EntityImpl implements ILeaf, IGroup { private String generic; private IGroup parentContainer; - private boolean top; - // Group private Code namespace; @@ -127,6 +127,17 @@ final public class EntityImpl implements ILeaf, IGroup { private LineLocation codeLine; private Set tags = new LinkedHashSet<>(); + private final List notes = new ArrayList<>(); + + @Override + public void addNote(Display note, Position position, Colors colors) { + notes.add(CucaNote.build(note, position, colors)); + } + + @Override + public List getNotes() { + return Collections.unmodifiableList(notes); + } public void addStereotag(Stereotag tag) { this.tags.add(tag); @@ -137,16 +148,6 @@ final public class EntityImpl implements ILeaf, IGroup { } // Back to Entity - public final boolean isTop() { - checkNotGroup(); - return top; - } - - public final void setTop(boolean top) { - checkNotGroup(); - this.top = top; - } - private EntityImpl(Ident ident, EntityFactory entityFactory, Code code, Bodier bodier, IGroup parentContainer, String namespaceSeparator, int rawLayout) { this.ident = Objects.requireNonNull(ident); diff --git a/src/net/sourceforge/plantuml/svek/Cluster.java b/src/net/sourceforge/plantuml/svek/Cluster.java index 9c9aae7f6..30f467965 100644 --- a/src/net/sourceforge/plantuml/svek/Cluster.java +++ b/src/net/sourceforge/plantuml/svek/Cluster.java @@ -52,11 +52,13 @@ import java.util.Set; import net.sourceforge.plantuml.AlignmentParam; import net.sourceforge.plantuml.Dimension2DDouble; import net.sourceforge.plantuml.ISkinParam; +import net.sourceforge.plantuml.OptionFlags; import net.sourceforge.plantuml.UmlDiagramType; import net.sourceforge.plantuml.Url; import net.sourceforge.plantuml.api.ThemeStyle; import net.sourceforge.plantuml.awt.geom.Dimension2D; import net.sourceforge.plantuml.cucadiagram.CucaDiagram; +import net.sourceforge.plantuml.cucadiagram.CucaNote; import net.sourceforge.plantuml.cucadiagram.EntityPosition; import net.sourceforge.plantuml.cucadiagram.EntityUtils; import net.sourceforge.plantuml.cucadiagram.IEntity; @@ -76,6 +78,7 @@ import net.sourceforge.plantuml.style.Style; import net.sourceforge.plantuml.style.StyleBuilder; import net.sourceforge.plantuml.style.StyleSignature; import net.sourceforge.plantuml.style.StyleSignatureBasic; +import net.sourceforge.plantuml.svek.image.EntityImageNoteLink; import net.sourceforge.plantuml.svek.image.EntityImageState; import net.sourceforge.plantuml.ugraphic.UComment; import net.sourceforge.plantuml.ugraphic.UGraphic; @@ -101,6 +104,8 @@ public class Cluster implements Moveable { private final List children = new ArrayList<>(); private final int color; private final int colorTitle; + private final int colorNoteUp; + private final int colorNoteDown; private final ISkinParam skinParam; protected final CucaDiagram diagram; @@ -112,17 +117,22 @@ public class Cluster implements Moveable { private double xTitle; private double yTitle; + private double xNoteup; + private double yNoteup; + private double minX; private double minY; private double maxX; private double maxY; public void moveSvek(double deltaX, double deltaY) { + this.xNoteup += deltaX; + this.yNoteup += deltaY; this.xTitle += deltaX; - this.minX += deltaX; - this.maxX += deltaX; this.yTitle += deltaY; + this.minX += deltaX; this.minY += deltaY; + this.maxX += deltaX; this.maxY += deltaY; } @@ -151,6 +161,8 @@ public class Cluster implements Moveable { this.color = colorSequence.getValue(); this.colorTitle = colorSequence.getValue(); + this.colorNoteUp = colorSequence.getValue(); + this.colorNoteDown = colorSequence.getValue(); this.skinParam = group.getColors().mute(skinParam); } @@ -172,27 +184,24 @@ public class Cluster implements Moveable { return Collections.unmodifiableList(nodes); } + public final List getNodes(EnumSet position) { + final List result = new ArrayList<>(); + for (SvekNode node : nodes) + if (position.contains(node.getEntityPosition())) + result.add(node); + return Collections.unmodifiableList(result); + } + private List getNodesOrderedTop(Collection lines) { final List firsts = new ArrayList<>(); - final Set tops = new HashSet<>(); final Map shs = new HashMap(); for (final Iterator it = nodes.iterator(); it.hasNext();) { final SvekNode node = it.next(); shs.put(node.getUid(), node); - if (node.isTop() && node.getEntityPosition() == EntityPosition.NORMAL) { - firsts.add(node); - tops.add(node.getUid()); - } } for (SvekLine l : lines) { - if (tops.contains(l.getStartUidPrefix())) { - final SvekNode sh = shs.get(l.getEndUidPrefix()); - if (sh != null && sh.getEntityPosition() == EntityPosition.NORMAL) - firsts.add(0, sh); - } - if (l.isInverted()) { final SvekNode sh = shs.get(l.getStartUidPrefix()); if (sh != null && sh.getEntityPosition() == EntityPosition.NORMAL) @@ -205,7 +214,6 @@ public class Cluster implements Moveable { private List getNodesOrderedWithoutTop(Collection lines) { final List all = new ArrayList<>(nodes); - final Set tops = new HashSet<>(); final Map shs = new HashMap(); for (final Iterator it = all.iterator(); it.hasNext();) { @@ -215,19 +223,9 @@ public class Cluster implements Moveable { continue; } shs.put(sh.getUid(), sh); - if (sh.isTop()) { - tops.add(sh.getUid()); - it.remove(); - } } for (SvekLine l : lines) { - if (tops.contains(l.getStartUidPrefix())) { - final SvekNode sh = shs.get(l.getEndUidPrefix()); - if (sh != null) - all.remove(sh); - } - if (l.isInverted()) { final SvekNode sh = shs.get(l.getStartUidPrefix()); if (sh != null) @@ -281,9 +279,14 @@ public class Cluster implements Moveable { return new ClusterPosition(minX, minY, maxX, maxY); } - public void setTitlePosition(double x, double y) { - this.xTitle = x; - this.yTitle = y; + public void setTitlePosition(Point2D pos) { + this.xTitle = pos.getX(); + this.yTitle = pos.getY(); + } + + public void setNoteUpPosition(Point2D pos) { + this.xNoteup = pos.getX(); + this.yNoteup = pos.getY(); } static public StyleSignatureBasic getDefaultStyleDefinition(SName diagramStyleName, USymbol symbol) { @@ -305,6 +308,12 @@ public class Cluster implements Moveable { if (group.isHidden()) return; + if (OptionFlags.USE_KERMOR) { + if (xNoteup > 0 && yNoteup > 0) { + getCucaNote().drawU(ug.apply(new UTranslate(xNoteup, yNoteup))); + } + } + final String fullName = group.getCodeGetName(); if (fullName.startsWith("##") == false) ug.draw(new UComment("cluster " + fullName)); @@ -371,6 +380,14 @@ public class Cluster implements Moveable { } } + EntityImageNoteLink getCucaNote() { + if (getGroup().getNotes().size() == 0) + return null; + final CucaNote note = getGroup().getNotes().get(0); + return new EntityImageNoteLink(note.getDisplay(), note.getColors(), skinParam, + skinParam.getCurrentStyleBuilder()); + } + static public UStroke getStrokeInternal(IGroup group, Style style) { final Colors colors = group.getColors(); if (colors.getSpecificLineStroke() != null) @@ -496,6 +513,14 @@ public class Cluster implements Moveable { } + public void setPosition(Point2D min, Point2D max) { + this.minX = min.getX(); + this.minY = min.getY(); + this.maxX = max.getX(); + this.maxY = max.getY(); + } + + @Deprecated public void setPosition(double minX, double minY, double maxX, double maxY) { this.minX = minX; this.maxX = maxX; @@ -503,9 +528,13 @@ public class Cluster implements Moveable { this.maxY = maxY; } - public void printCluster1(StringBuilder sb, Collection lines, StringBounder stringBounder) { - for (SvekNode node : getNodesOrderedTop(lines)) + public boolean printCluster1(StringBuilder sb, Collection lines, StringBounder stringBounder) { + final List tmp = getNodesOrderedTop(lines); + if (tmp.size() == 0) + return false; + for (SvekNode node : tmp) node.appendShape(sb, stringBounder); + return true; } @@ -528,6 +557,22 @@ public class Cluster implements Moveable { return added; } + public void printCluster3_forKermor(StringBuilder sb, Collection lines, StringBounder stringBounder, + DotMode dotMode, GraphvizVersion graphvizVersion, UmlDiagramType type) { + final List tmp = getNodes(EntityPosition.getNormals()); + + if (tmp.size() == 0) { + sb.append(getClusterId() + "empty [shape=point,label=\"\"];"); + SvekUtils.println(sb); + } else + for (SvekNode node : tmp) { + node.appendShape(sb, stringBounder); + } + + for (Cluster child : getChildren()) + child.printInternal(sb, lines, stringBounder, dotMode, graphvizVersion, type); + } + private void printInternal(StringBuilder sb, Collection lines, StringBounder stringBounder, DotMode dotMode, GraphvizVersion graphvizVersion, UmlDiagramType type) { new ClusterDotString(this, skinParam).printInternal(sb, lines, stringBounder, dotMode, graphvizVersion, type); @@ -558,16 +603,6 @@ public class Cluster implements Moveable { return rankSame; } - void fillRankMin(Set rankMin) { - for (SvekNode sh : getNodes()) - if (sh.isTop()) - rankMin.add(sh.getUid()); - - for (Cluster child : getChildren()) - child.fillRankMin(rankMin); - - } - private boolean isInCluster(String uid) { for (SvekNode node : nodes) if (node.getUid().equals(uid)) @@ -670,6 +705,14 @@ public class Cluster implements Moveable { return 0; } + public final int getColorNoteUp() { + return colorNoteUp; + } + + public final int getColorNoteDown() { + return colorNoteDown; + } + // public Point2D projection(double x, double y) { // final double v1 = Math.abs(minX - x); // final double v2 = Math.abs(maxX - x); diff --git a/src/net/sourceforge/plantuml/svek/ClusterDotString.java b/src/net/sourceforge/plantuml/svek/ClusterDotString.java index 7d27af9cb..b2771fecc 100644 --- a/src/net/sourceforge/plantuml/svek/ClusterDotString.java +++ b/src/net/sourceforge/plantuml/svek/ClusterDotString.java @@ -46,6 +46,7 @@ import java.util.Set; import net.sourceforge.plantuml.AlignmentParam; import net.sourceforge.plantuml.ISkinParam; +import net.sourceforge.plantuml.OptionFlags; import net.sourceforge.plantuml.StringUtils; import net.sourceforge.plantuml.UmlDiagramType; import net.sourceforge.plantuml.cucadiagram.EntityPosition; @@ -67,6 +68,11 @@ public class ClusterDotString { void printInternal(StringBuilder sb, Collection lines, StringBounder stringBounder, DotMode dotMode, GraphvizVersion graphvizVersion, UmlDiagramType type) { + if (OptionFlags.USE_KERMOR) { + new ClusterDotStringKermor(cluster, skinParam).printInternal(sb, lines, stringBounder, dotMode, + graphvizVersion, type); + return; + } final boolean thereALinkFromOrToGroup2 = isThereALinkFromOrToGroup(lines); boolean thereALinkFromOrToGroup1 = thereALinkFromOrToGroup2; final boolean useProtectionWhenThereALinkFromOrToGroup = graphvizVersion @@ -112,7 +118,8 @@ public class ClusterDotString { } if (entityPositionsExceptNormal.size() > 0) { - printClusterEntryExit(sb, stringBounder); + printRanks(Cluster.RANK_SOURCE, withPosition(EntityPosition.getInputs()), sb, stringBounder); + printRanks(Cluster.RANK_SINK, withPosition(EntityPosition.getOutputs()), sb, stringBounder); if (hasPort()) subgraphClusterNoLabel(sb, ID_EE); else @@ -225,13 +232,6 @@ public class ClusterDotString { sb.append("label=" + label + ";"); } - private void printClusterEntryExit(StringBuilder sb, StringBounder stringBounder) { - printRanks(Cluster.RANK_SOURCE, withPosition(EntityPosition.getInputs()), sb, stringBounder); - // printRanks(Cluster.RANK_SAME, withPosition(EntityPosition.getSame()), sb, - // stringBounder); - printRanks(Cluster.RANK_SINK, withPosition(EntityPosition.getOutputs()), sb, stringBounder); - } - private void printRanks(String rank, List entries, StringBuilder sb, StringBounder stringBounder) { if (entries.size() > 0) { diff --git a/src/net/sourceforge/plantuml/svek/ClusterDotStringKermor.java b/src/net/sourceforge/plantuml/svek/ClusterDotStringKermor.java new file mode 100644 index 000000000..f02c931e9 --- /dev/null +++ b/src/net/sourceforge/plantuml/svek/ClusterDotStringKermor.java @@ -0,0 +1,267 @@ +/* ======================================================================== + * 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 + * Contribution : Hisashi Miyashita + * + * + */ +package net.sourceforge.plantuml.svek; + +import java.util.Collection; +import java.util.Collections; +import java.util.EnumSet; +import java.util.List; +import java.util.Set; + +import net.sourceforge.plantuml.AlignmentParam; +import net.sourceforge.plantuml.ISkinParam; +import net.sourceforge.plantuml.StringUtils; +import net.sourceforge.plantuml.UmlDiagramType; +import net.sourceforge.plantuml.awt.geom.Dimension2D; +import net.sourceforge.plantuml.cucadiagram.CucaNote; +import net.sourceforge.plantuml.cucadiagram.EntityPosition; +import net.sourceforge.plantuml.cucadiagram.dot.GraphvizVersion; +import net.sourceforge.plantuml.graphic.HorizontalAlignment; +import net.sourceforge.plantuml.graphic.StringBounder; +import net.sourceforge.plantuml.graphic.TextBlock; +import net.sourceforge.plantuml.graphic.USymbols; +import net.sourceforge.plantuml.style.StyleBuilder; +import net.sourceforge.plantuml.svek.image.EntityImageNoteLink; + +public class ClusterDotStringKermor { + + private final Cluster cluster; + private final ISkinParam skinParam; + private static final String ID_EE = "ee"; + + public ClusterDotStringKermor(Cluster cluster, ISkinParam skinParam) { + this.cluster = cluster; + this.skinParam = skinParam; + } + + void printInternal(StringBuilder sb, Collection lines, StringBounder stringBounder, DotMode dotMode, + GraphvizVersion graphvizVersion, UmlDiagramType type) { + + final Set entityPositionsExceptNormal = entityPositionsExceptNormal(); + if (entityPositionsExceptNormal.size() > 0) + for (SvekLine line : lines) + if (line.isLinkFromOrTo(cluster.getGroup())) + line.setProjectionCluster(cluster); + + final boolean useAlphaAndBeta = useAlphaAndBeta(); + + if (useAlphaAndBeta) { + sb.append("subgraph " + cluster.getClusterId() + "alpha {"); + SvekUtils.println(sb); + + final TextBlock noteOnly = cluster.getCucaNote(); + if (noteOnly == null) { + sb.append("label=\"\";color=\"#FFFF00\";"); + SvekUtils.println(sb); + } else { + + final Dimension2D dim = noteOnly.calculateDimension(stringBounder); + System.err.println("dim=" + dim); + + final StringBuilder sblabel = new StringBuilder("<"); + SvekLine.appendTable(sblabel, (int) dim.getWidth(), (int) dim.getHeight(), cluster.getColorNoteUp()); + sblabel.append(">"); + sb.append("label=" + sblabel + ";"); + sb.append("color=\"#FFFF00\";"); + } + + } + + sb.append("subgraph " + cluster.getClusterId() + "beta {"); + SvekUtils.println(sb); + sb.append("label=\"\";color=\"#FFFF00\";"); + // sb.append("label=\"NOTEDOWN\";labelloc=\"b\";"); + SvekUtils.println(sb); + printRanks(Cluster.RANK_SOURCE, cluster.getNodes(EntityPosition.getInputs()), sb, stringBounder); + SvekUtils.println(sb); + + sb.append("subgraph " + cluster.getClusterId() + "gamma {"); + SvekUtils.println(sb); + sb.append("labelloc=\"t\";"); + SvekUtils.println(sb); + sb.append("style=solid;"); + SvekUtils.println(sb); + sb.append("color=\"" + StringUtils.sharp000000(cluster.getColor()) + "\";"); + + final String label; + if (cluster.isLabel()) { + final StringBuilder sblabel = new StringBuilder("<"); + SvekLine.appendTable(sblabel, cluster.getTitleAndAttributeWidth(), cluster.getTitleAndAttributeHeight() - 5, + cluster.getTitleColor()); + sblabel.append(">"); + label = sblabel.toString(); + final HorizontalAlignment align = skinParam.getHorizontalAlignment(AlignmentParam.packageTitleAlignment, + null, false, null); + sb.append("labeljust=\"" + align.getGraphVizValue() + "\";"); + } else { + label = "\"\""; + } + + sb.append("label=" + label + ";"); + SvekUtils.println(sb); + + cluster.printCluster3_forKermor(sb, lines, stringBounder, dotMode, graphvizVersion, type); + + SvekUtils.println(sb); + printRanks(Cluster.RANK_SINK, cluster.getNodes(EntityPosition.getOutputs()), sb, stringBounder); + SvekUtils.println(sb); + + sb.append("}"); + sb.append("}"); + if (useAlphaAndBeta) { + sb.append("}"); + } + + SvekUtils.println(sb); + + } + + private boolean useAlphaAndBeta() { + if (cluster.getGroup().getNotes().size() > 0) + return true; + + return false; + } + + private String getSourceInPoint(UmlDiagramType type) { + if (skinParam.useSwimlanes(type)) + return "sourceIn" + cluster.getColor(); + + return null; + } + + private String getSinkInPoint(UmlDiagramType type) { + if (skinParam.useSwimlanes(type)) + return "sinkIn" + cluster.getColor(); + + return null; + } + + private String empty() { + // return "empty" + color; + // We use the same node with one for thereALinkFromOrToGroup2 as an empty + // because we cannot put a new node in the nested inside of the cluster + // if thereALinkFromOrToGroup2 is enabled. + return Cluster.getSpecialPointId(cluster.getGroup()); + } + + private boolean hasPort() { + for (EntityPosition pos : entityPositionsExceptNormal()) + if (pos.isPort()) + return true; + + return false; + } + + private Set entityPositionsExceptNormal() { + final Set result = EnumSet.noneOf(EntityPosition.class); + for (SvekNode sh : cluster.getNodes()) + if (sh.getEntityPosition() != EntityPosition.NORMAL) + result.add(sh.getEntityPosition()); + + return Collections.unmodifiableSet(result); + } + + private void subgraphClusterNoLabel(StringBuilder sb, String id) { + subgraphClusterWithLabel(sb, id, "\"\""); + } + + private void subgraphClusterWithLabel(StringBuilder sb, String id, String label) { + sb.append("subgraph " + cluster.getClusterId() + id + " {"); + sb.append("label=" + label + ";"); + } + +// private void printClusterEntryExit(StringBuilder sb, StringBounder stringBounder) { +// printRanks(Cluster.RANK_SOURCE, withPosition(EntityPosition.getInputs()), sb, stringBounder); +// // printRanks(Cluster.RANK_SAME, withPosition(EntityPosition.getSame()), sb, +// // stringBounder); +// printRanks(Cluster.RANK_SINK, withPosition(EntityPosition.getOutputs()), sb, stringBounder); +// } + + private void printRanks(String rank, List entries, StringBuilder sb, + StringBounder stringBounder) { + if (entries.size() > 0) { + sb.append("{rank=" + rank + ";"); + for (SvekNode sh1 : entries) + sb.append(sh1.getUid() + ";"); + + sb.append("}"); + SvekUtils.println(sb); + for (SvekNode sh2 : entries) + sh2.appendShape(sb, stringBounder); + + SvekUtils.println(sb); + } + } + +// private List withPosition(Set positions) { +// final List result = new ArrayList<>(); +// for (final Iterator it = cluster.getNodes().iterator(); it.hasNext();) { +// final SvekNode sh = it.next(); +// if (positions.contains(sh.getEntityPosition())) +// result.add(sh); +// +// } +// return result; +// } + + private boolean protection0(UmlDiagramType type) { + if (skinParam.useSwimlanes(type)) + return false; + + return true; + } + + private boolean protection1(UmlDiagramType type) { + if (cluster.getGroup().getUSymbol() == USymbols.NODE) + return true; + + if (skinParam.useSwimlanes(type)) + return false; + + return true; + } + + private boolean isThereALinkFromOrToGroup(Collection lines) { + for (SvekLine line : lines) + if (line.isLinkFromOrTo(cluster.getGroup())) + return true; + + return false; + } + +} diff --git a/src/net/sourceforge/plantuml/svek/DotStringFactory.java b/src/net/sourceforge/plantuml/svek/DotStringFactory.java index 0d3986aec..eb4a5c548 100644 --- a/src/net/sourceforge/plantuml/svek/DotStringFactory.java +++ b/src/net/sourceforge/plantuml/svek/DotStringFactory.java @@ -42,14 +42,13 @@ import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.util.ArrayList; -import java.util.HashSet; import java.util.List; -import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import net.sourceforge.plantuml.BaseFile; import net.sourceforge.plantuml.ISkinParam; +import net.sourceforge.plantuml.OptionFlags; import net.sourceforge.plantuml.StringUtils; import net.sourceforge.plantuml.UmlDiagramType; import net.sourceforge.plantuml.cucadiagram.CucaDiagram; @@ -74,8 +73,6 @@ public class DotStringFactory implements Moveable { private final Bibliotekon bibliotekon = new Bibliotekon(); - final private Set rankMin = new HashSet<>(); - private final ColorSequence colorSequence; private final Cluster root; @@ -114,19 +111,6 @@ public class DotStringFactory implements Moveable { current.addNode(node); } - private void printMinRanking(StringBuilder sb) { - if (rankMin.size() == 0) - return; - - sb.append("{ rank = min;"); - for (String id : rankMin) { - sb.append(id); - sb.append(";"); - } - sb.append("}"); - - } - private double getHorizontalDzeta() { double max = 0; for (SvekLine l : bibliotekon.allLines()) { @@ -146,6 +130,8 @@ public class DotStringFactory implements Moveable { max = c; } + if (OptionFlags.USE_KERMOR) + return max / 100; return max / 10; } @@ -211,16 +197,28 @@ public class DotStringFactory implements Moveable { manageMinMaxCluster(sb); - root.printCluster1(sb, bibliotekon.allLines(), stringBounder); - for (SvekLine line : bibliotekon.lines0()) - line.appendLine(getGraphvizVersion(), sb, dotMode, dotSplines); + if (OptionFlags.USE_KERMOR) { + for (SvekLine line : bibliotekon.lines0()) + line.appendLine(getGraphvizVersion(), sb, dotMode, dotSplines); + for (SvekLine line : bibliotekon.lines1()) + line.appendLine(getGraphvizVersion(), sb, dotMode, dotSplines); - root.fillRankMin(rankMin); - root.printCluster2(sb, bibliotekon.allLines(), stringBounder, dotMode, getGraphvizVersion(), umlDiagramType); - printMinRanking(sb); + root.printCluster3_forKermor(sb, bibliotekon.allLines(), stringBounder, dotMode, getGraphvizVersion(), + umlDiagramType); - for (SvekLine line : bibliotekon.lines1()) - line.appendLine(getGraphvizVersion(), sb, dotMode, dotSplines); + } else { + root.printCluster1(sb, bibliotekon.allLines(), stringBounder); + + for (SvekLine line : bibliotekon.lines0()) + line.appendLine(getGraphvizVersion(), sb, dotMode, dotSplines); + + root.printCluster2(sb, bibliotekon.allLines(), stringBounder, dotMode, getGraphvizVersion(), + umlDiagramType); + + for (SvekLine line : bibliotekon.lines1()) + line.appendLine(getGraphvizVersion(), sb, dotMode, dotSplines); + + } SvekUtils.println(sb); sb.append("}"); @@ -268,6 +266,8 @@ public class DotStringFactory implements Moveable { // return 29; return 40; } + if (OptionFlags.USE_KERMOR) + return 40; return 60; } @@ -370,11 +370,8 @@ public class DotStringFactory implements Moveable { || node.getType() == ShapeType.RECTANGLE_WITH_CIRCLE_INSIDE || node.getType() == ShapeType.FOLDER || node.getType() == ShapeType.DIAMOND || node.getType() == ShapeType.RECTANGLE_PORT) { final List points = svgResult.substring(idx).extractList(SvgResult.POINTS_EQUALS); - final double minY = SvekUtils.getMinY(points); - final double overscanX = node.getOverscanX(stringBounder); - final double minX = SvekUtils.getMinX(points); -// corner1.manage(minX - overscanX, minY); - node.moveSvek(minX, minY); + final Point2D min = SvekUtils.getMinXY(points); + node.moveSvek(min.getX(), min.getY()); } else if (node.getType() == ShapeType.ROUND_RECTANGLE) { final int idx2 = svg.indexOf("d=\"", idx + 1); idx = svg.indexOf("points=\"", idx + 1); @@ -389,19 +386,16 @@ public class DotStringFactory implements Moveable { points.addAll(svgResult.substring(idx).extractList(SvgResult.POINTS_EQUALS)); } } - final double minX = SvekUtils.getMinX(points); - final double minY = SvekUtils.getMinY(points); -// corner1.manage(minX, minY); - node.moveSvek(minX, minY); + final Point2D min = SvekUtils.getMinXY(points); + node.moveSvek(min.getX(), min.getY()); } else if (node.getType() == ShapeType.OCTAGON || node.getType() == ShapeType.HEXAGON) { idx = svg.indexOf("points=\"", idx + 1); final int starting = idx; final List points = svgResult.substring(starting).extractList(SvgResult.POINTS_EQUALS); - final double minX = SvekUtils.getMinX(points); - final double minY = SvekUtils.getMinY(points); + final Point2D min = SvekUtils.getMinXY(points); // corner1.manage(minX, minY); - node.moveSvek(minX, minY); - node.setPolygon(minX, minY, points); + node.moveSvek(min.getX(), min.getY()); + node.setPolygon(min.getX(), min.getY(), points); } else if (node.getType() == ShapeType.CIRCLE || node.getType() == ShapeType.OVAL) { final double cx = SvekUtils.getValue(svg, idx, "cx"); final double cy = SvekUtils.getValue(svg, idx, "cy") + fullHeight; @@ -423,23 +417,24 @@ public class DotStringFactory implements Moveable { int idx = getClusterIndex(svg, cluster.getColor()); final int starting = idx; final List points = svgResult.substring(starting).extractList(SvgResult.POINTS_EQUALS); - final double minX = SvekUtils.getMinX(points); - final double minY = SvekUtils.getMinY(points); - final double maxX = SvekUtils.getMaxX(points); - final double maxY = SvekUtils.getMaxY(points); - cluster.setPosition(minX, minY, maxX, maxY); - // corner1.manage(minX, minY); + final Point2D min = SvekUtils.getMinXY(points); + final Point2D max = SvekUtils.getMaxXY(points); + cluster.setPosition(min, max); if (cluster.getTitleAndAttributeWidth() == 0 || cluster.getTitleAndAttributeHeight() == 0) continue; idx = getClusterIndex(svg, cluster.getTitleColor()); - final int starting1 = idx; - final List pointsTitle = svgResult.substring(starting1) - .extractList(SvgResult.POINTS_EQUALS); - final double minXtitle = SvekUtils.getMinX(pointsTitle); - final double minYtitle = SvekUtils.getMinY(pointsTitle); - cluster.setTitlePosition(minXtitle, minYtitle); + final List pointsTitle = svgResult.substring(idx).extractList(SvgResult.POINTS_EQUALS); + cluster.setTitlePosition(SvekUtils.getMinXY(pointsTitle)); + + if (OptionFlags.USE_KERMOR) { + if (cluster.getGroup().getNotes().size() > 0) { + idx = getClusterIndex(svg, cluster.getColorNoteUp()); + final List noteUp = svgResult.substring(idx).extractList(SvgResult.POINTS_EQUALS); + cluster.setNoteUpPosition(SvekUtils.getMinXY(noteUp)); + } + } } for (SvekLine line : bibliotekon.allLines()) diff --git a/src/net/sourceforge/plantuml/svek/SvekLine.java b/src/net/sourceforge/plantuml/svek/SvekLine.java index 1503fbfde..5f9968d29 100644 --- a/src/net/sourceforge/plantuml/svek/SvekLine.java +++ b/src/net/sourceforge/plantuml/svek/SvekLine.java @@ -59,6 +59,7 @@ import net.sourceforge.plantuml.Url; import net.sourceforge.plantuml.awt.geom.Dimension2D; import net.sourceforge.plantuml.command.Position; import net.sourceforge.plantuml.creole.CreoleMode; +import net.sourceforge.plantuml.cucadiagram.CucaNote; import net.sourceforge.plantuml.cucadiagram.Display; import net.sourceforge.plantuml.cucadiagram.EntityPort; import net.sourceforge.plantuml.cucadiagram.IEntity; @@ -285,25 +286,26 @@ public class SvekLine implements Moveable, Hideable, GuideLine { } - final TextBlock noteOnly; - if (link.getNote() == null) { - noteOnly = TextBlockUtils.EMPTY_TEXT_BLOCK; + final CucaNote note = link.getNote(); + if (note == null) { + labelText = labelOnly; } else { - noteOnly = new EntityImageNoteLink(link.getNote(), link.getNoteColors(), skinParam, link.getStyleBuilder()); - if (link.getNoteLinkStrategy() == NoteLinkStrategy.HALF_NOT_PRINTED - || link.getNoteLinkStrategy() == NoteLinkStrategy.HALF_PRINTED_FULL) + final TextBlock noteOnly = new EntityImageNoteLink(note.getDisplay(), note.getColors(), skinParam, + link.getStyleBuilder()); + if (note.getStrategy() == NoteLinkStrategy.HALF_NOT_PRINTED + || note.getStrategy() == NoteLinkStrategy.HALF_PRINTED_FULL) divideLabelWidthByTwo = true; - } + if (note.getPosition() == Position.LEFT) + labelText = TextBlockUtils.mergeLR(noteOnly, labelOnly, VerticalAlignment.CENTER); + else if (note.getPosition() == Position.RIGHT) + labelText = TextBlockUtils.mergeLR(labelOnly, noteOnly, VerticalAlignment.CENTER); + else if (note.getPosition() == Position.TOP) + labelText = TextBlockUtils.mergeTB(noteOnly, labelOnly, HorizontalAlignment.CENTER); + else + labelText = TextBlockUtils.mergeTB(labelOnly, noteOnly, HorizontalAlignment.CENTER); - if (link.getNotePosition() == Position.LEFT) - labelText = TextBlockUtils.mergeLR(noteOnly, labelOnly, VerticalAlignment.CENTER); - else if (link.getNotePosition() == Position.RIGHT) - labelText = TextBlockUtils.mergeLR(labelOnly, noteOnly, VerticalAlignment.CENTER); - else if (link.getNotePosition() == Position.TOP) - labelText = TextBlockUtils.mergeTB(noteOnly, labelOnly, HorizontalAlignment.CENTER); - else - labelText = TextBlockUtils.mergeTB(labelOnly, noteOnly, HorizontalAlignment.CENTER); + } if (link.getQualifier1() == null) startTailText = null; @@ -632,7 +634,7 @@ public class SvekLine implements Moveable, Hideable, GuideLine { return dotPath.getBeziers().size() <= 1; } - private Point2D.Double getXY(SvgResult svgResult, int color) { + private Point2D getXY(SvgResult svgResult, int color) { final int idx = svgResult.getIndexFromColor(color); if (idx == -1) return null; @@ -730,7 +732,7 @@ public class SvekLine implements Moveable, Hideable, GuideLine { ug = ug.apply(new UStroke()).apply(color); if (hasNoteLabelText() && this.labelXY != null - && link.getNoteLinkStrategy() != NoteLinkStrategy.HALF_NOT_PRINTED) + && (link.getNote() == null || link.getNote().getStrategy() != NoteLinkStrategy.HALF_NOT_PRINTED)) this.labelText.drawU(ug.apply(new UTranslate(x + this.labelXY.getPosition().getX() + labelShield, y + this.labelXY.getPosition().getY() + labelShield))); diff --git a/src/net/sourceforge/plantuml/svek/SvekNode.java b/src/net/sourceforge/plantuml/svek/SvekNode.java index 91e8643d8..b1b815646 100644 --- a/src/net/sourceforge/plantuml/svek/SvekNode.java +++ b/src/net/sourceforge/plantuml/svek/SvekNode.java @@ -78,8 +78,6 @@ public class SvekNode implements Positionable, Hideable { private Cluster cluster; - private final boolean top; - public final Cluster getCluster() { return cluster; } @@ -100,7 +98,6 @@ public class SvekNode implements Positionable, Hideable { this.stringBounder = stringBounder; this.entityPosition = ent.getEntityPosition(); this.image = image; - this.top = ent.isTop(); this.type = image.getShapeType(); this.color = colorSequence.getValue(); @@ -136,18 +133,22 @@ public class SvekNode implements Positionable, Hideable { public void appendShape(StringBuilder sb, StringBounder stringBounder) { if (type == ShapeType.RECTANGLE_HTML_FOR_PORTS) { appendLabelHtmlSpecialForLink(sb, stringBounder); + SvekUtils.println(sb); return; } if (type == ShapeType.RECTANGLE_PORT) { appendLabelHtmlSpecialForPort(sb, stringBounder); + SvekUtils.println(sb); return; } if (type == ShapeType.RECTANGLE_WITH_CIRCLE_INSIDE) { appendHtml(sb); + SvekUtils.println(sb); return; } if (type == ShapeType.RECTANGLE && shield().isZero() == false) { appendHtml(sb); + SvekUtils.println(sb); return; } sb.append(uid); @@ -362,10 +363,6 @@ public class SvekNode implements Positionable, Hideable { return image; } - public final boolean isTop() { - return top; - } - public Point2D getPosition() { return new Point2D.Double(minX, minY); } diff --git a/src/net/sourceforge/plantuml/svek/SvekUtils.java b/src/net/sourceforge/plantuml/svek/SvekUtils.java index f2821acfe..2dbb572be 100644 --- a/src/net/sourceforge/plantuml/svek/SvekUtils.java +++ b/src/net/sourceforge/plantuml/svek/SvekUtils.java @@ -65,48 +65,29 @@ public class SvekUtils { } - public static double getMaxX(List points) { - double result = points.get(0).x; + public static Point2D getMinXY(List points) { + double minx = points.get(0).x; + double miny = points.get(0).y; for (int i = 1; i < points.size(); i++) { - if (points.get(i).x > result) { - result = points.get(i).x; - } + if (points.get(i).x < minx) + minx = points.get(i).x; + if (points.get(i).y < miny) + miny = points.get(i).y; } - return result; + return new Point2D.Double(minx, miny); } - public static double getMinX(List points) { - double result = points.get(0).x; + public static Point2D getMaxXY(List points) { + double maxx = points.get(0).x; + double maxy = points.get(0).y; for (int i = 1; i < points.size(); i++) { - if (points.get(i).x < result) { - result = points.get(i).x; - } + if (points.get(i).x > maxx) + maxx = points.get(i).x; + if (points.get(i).y > maxy) + maxy = points.get(i).y; } - return result; - } - public static Point2D.Double getMinXY(List points) { - return new Point2D.Double(getMinX(points), getMinY(points)); - } - - public static double getMaxY(List points) { - double result = points.get(0).y; - for (int i = 1; i < points.size(); i++) { - if (points.get(i).y > result) { - result = points.get(i).y; - } - } - return result; - } - - public static double getMinY(List points) { - double result = points.get(0).y; - for (int i = 1; i < points.size(); i++) { - if (points.get(i).y < result) { - result = points.get(i).y; - } - } - return result; + return new Point2D.Double(maxx, maxy); } public static void println(StringBuilder sb) { diff --git a/src/net/sourceforge/plantuml/xmlsc/ScxmlStateDiagramStandard.java b/src/net/sourceforge/plantuml/xmlsc/ScxmlStateDiagramStandard.java index 5f12e5258..3fea315d5 100644 --- a/src/net/sourceforge/plantuml/xmlsc/ScxmlStateDiagramStandard.java +++ b/src/net/sourceforge/plantuml/xmlsc/ScxmlStateDiagramStandard.java @@ -49,6 +49,7 @@ import javax.xml.transform.TransformerException; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; +import org.w3c.dom.Comment; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -119,15 +120,33 @@ public class ScxmlStateDiagramStandard { } private Element createState(IEntity entity) { + final LeafType type = entity.getLeafType(); + final Element state = document.createElement("state"); - state.setAttribute("id", getId(entity)); - final Stereotype stereotype = entity.getStereotype(); - if (stereotype != null) { - state.setAttribute("stereotype", stereotype.getLabels(Guillemet.NONE).get(0)); + if (type == LeafType.NOTE) { + state.setAttribute("stereotype", "note"); + state.setAttribute("id", entity.getCode().getName()); + final Display display = entity.getDisplay(); + final StringBuilder sb = new StringBuilder(); + for (CharSequence s : display) { + sb.append(s); + sb.append("\n"); + } + if (sb.length() > 0) + sb.setLength(sb.length() - 1); + final Comment comment = document.createComment(sb.toString()); + state.appendChild(comment); + + } else { + state.setAttribute("id", getId(entity)); + final Stereotype stereotype = entity.getStereotype(); + if (stereotype != null) + state.setAttribute("stereotype", stereotype.getLabels(Guillemet.NONE).get(0)); + + for (final Link link : diagram.getLinks()) + if (link.getEntity1() == entity) + addLink(state, link); } - for (final Link link : diagram.getLinks()) - if (link.getEntity1() == entity) - addLink(state, link); return state; } diff --git a/test/nonreg/scxml/SCXML0005_Test.java b/test/nonreg/scxml/SCXML0005_Test.java new file mode 100644 index 000000000..05ff25a09 --- /dev/null +++ b/test/nonreg/scxml/SCXML0005_Test.java @@ -0,0 +1,49 @@ +package nonreg.scxml; + +import java.io.IOException; + +import org.junit.jupiter.api.Test; + +/* + + +https://github.com/plantuml/plantuml/issues/1111 + + +Test diagram MUST be put between triple quotes + +""" +@startuml + +state module { +} + +note as PARAMETERS +localparam MAX_VAL 10 +parameter COUNT_WIDTH 4 +end note + + +@enduml +""" + +Expected result MUST be put between triple brackets + +{{{ + + + + + + +}}} + */ +public class SCXML0005_Test extends ScXmlTest { + + @Test + void testSimple() throws IOException { + checkXmlAndDescription("(1 entities)"); + } + +}