mirror of
https://github.com/octoleo/plantuml.git
synced 2024-11-15 17:57:10 +00:00
Improve ELK support
This commit is contained in:
parent
dfdec8820f
commit
320ab186b4
@ -59,15 +59,19 @@ import org.eclipse.elk.graph.ElkNode;
|
|||||||
import org.eclipse.elk.graph.util.ElkGraphUtil;
|
import org.eclipse.elk.graph.util.ElkGraphUtil;
|
||||||
|
|
||||||
import net.sourceforge.plantuml.FileFormatOption;
|
import net.sourceforge.plantuml.FileFormatOption;
|
||||||
|
import net.sourceforge.plantuml.FontParam;
|
||||||
import net.sourceforge.plantuml.ISkinParam;
|
import net.sourceforge.plantuml.ISkinParam;
|
||||||
import net.sourceforge.plantuml.StringUtils;
|
import net.sourceforge.plantuml.StringUtils;
|
||||||
import net.sourceforge.plantuml.UmlDiagram;
|
import net.sourceforge.plantuml.UmlDiagram;
|
||||||
import net.sourceforge.plantuml.api.ImageDataSimple;
|
import net.sourceforge.plantuml.api.ImageDataSimple;
|
||||||
import net.sourceforge.plantuml.core.ImageData;
|
import net.sourceforge.plantuml.core.ImageData;
|
||||||
import net.sourceforge.plantuml.cucadiagram.CucaDiagram;
|
import net.sourceforge.plantuml.cucadiagram.CucaDiagram;
|
||||||
|
import net.sourceforge.plantuml.cucadiagram.Display;
|
||||||
import net.sourceforge.plantuml.cucadiagram.ILeaf;
|
import net.sourceforge.plantuml.cucadiagram.ILeaf;
|
||||||
import net.sourceforge.plantuml.cucadiagram.Link;
|
import net.sourceforge.plantuml.cucadiagram.Link;
|
||||||
import net.sourceforge.plantuml.graphic.AbstractTextBlock;
|
import net.sourceforge.plantuml.graphic.AbstractTextBlock;
|
||||||
|
import net.sourceforge.plantuml.graphic.FontConfiguration;
|
||||||
|
import net.sourceforge.plantuml.graphic.HorizontalAlignment;
|
||||||
import net.sourceforge.plantuml.graphic.QuoteUtils;
|
import net.sourceforge.plantuml.graphic.QuoteUtils;
|
||||||
import net.sourceforge.plantuml.graphic.StringBounder;
|
import net.sourceforge.plantuml.graphic.StringBounder;
|
||||||
import net.sourceforge.plantuml.graphic.TextBlock;
|
import net.sourceforge.plantuml.graphic.TextBlock;
|
||||||
@ -91,6 +95,7 @@ public class CucaDiagramFileMakerElk implements CucaDiagramFileMaker {
|
|||||||
private final DotStringFactory dotStringFactory;
|
private final DotStringFactory dotStringFactory;
|
||||||
|
|
||||||
private final Map<ILeaf, ElkNode> nodes = new LinkedHashMap<ILeaf, ElkNode>();
|
private final Map<ILeaf, ElkNode> nodes = new LinkedHashMap<ILeaf, ElkNode>();
|
||||||
|
private final Map<Link, ElkEdge> edges = new LinkedHashMap<Link, ElkEdge>();
|
||||||
|
|
||||||
public CucaDiagramFileMakerElk(CucaDiagram diagram, StringBounder stringBounder) {
|
public CucaDiagramFileMakerElk(CucaDiagram diagram, StringBounder stringBounder) {
|
||||||
this.diagram = diagram;
|
this.diagram = diagram;
|
||||||
@ -99,6 +104,36 @@ public class CucaDiagramFileMakerElk implements CucaDiagramFileMaker {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unused right now
|
||||||
|
private TextBlock getLabel(Link link) {
|
||||||
|
final double marginLabel = 1; // startUid.equals(endUid) ? 6 : 1;
|
||||||
|
ISkinParam skinParam = diagram.getSkinParam();
|
||||||
|
final FontConfiguration labelFont = new FontConfiguration(skinParam, FontParam.ARROW, null);
|
||||||
|
final TextBlock label = link.getLabel().create(labelFont,
|
||||||
|
skinParam.getDefaultTextAlignment(HorizontalAlignment.CENTER), skinParam);
|
||||||
|
if (TextBlockUtils.isEmpty(label, stringBounder)) {
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
return TextBlockUtils.withMargin(label, marginLabel, marginLabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unused right now
|
||||||
|
private TextBlock getQualifier(Link link, int n) {
|
||||||
|
final String tmp = n == 1 ? link.getQualifier1() : link.getQualifier2();
|
||||||
|
if (tmp == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final double marginLabel = 1; // startUid.equals(endUid) ? 6 : 1;
|
||||||
|
ISkinParam skinParam = diagram.getSkinParam();
|
||||||
|
final FontConfiguration labelFont = new FontConfiguration(skinParam, FontParam.ARROW, null);
|
||||||
|
final TextBlock label = Display.getWithNewlines(tmp).create(labelFont,
|
||||||
|
skinParam.getDefaultTextAlignment(HorizontalAlignment.CENTER), skinParam);
|
||||||
|
if (TextBlockUtils.isEmpty(label, stringBounder)) {
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
return TextBlockUtils.withMargin(label, marginLabel, marginLabel);
|
||||||
|
}
|
||||||
|
|
||||||
// The Drawing class does the real drawing
|
// The Drawing class does the real drawing
|
||||||
class Drawing extends AbstractTextBlock implements TextBlockBackcolored {
|
class Drawing extends AbstractTextBlock implements TextBlockBackcolored {
|
||||||
|
|
||||||
@ -125,6 +160,17 @@ public class CucaDiagramFileMakerElk implements CucaDiagramFileMaker {
|
|||||||
image.drawU(ug.apply(new UTranslate(corner)));
|
image.drawU(ug.apply(new UTranslate(corner)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Draw all edges
|
||||||
|
for (Entry<Link, ElkEdge> ent : edges.entrySet()) {
|
||||||
|
final Link link = ent.getKey();
|
||||||
|
if (link.isInvis()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
final ElkEdge edge = ent.getValue();
|
||||||
|
new ElkPath(link, edge, diagram, getLabel(link), getQualifier(link, 1), getQualifier(link, 2))
|
||||||
|
.drawU(ug);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Dimension2D calculateDimension(StringBounder stringBounder) {
|
public Dimension2D calculateDimension(StringBounder stringBounder) {
|
||||||
@ -146,7 +192,9 @@ public class CucaDiagramFileMakerElk implements CucaDiagramFileMaker {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
final ElkNode root = ElkGraphUtil.createGraph();
|
final ElkNode root = ElkGraphUtil.createGraph();
|
||||||
final ElkPadding labelPadding = new ElkPadding(2.0);
|
|
||||||
|
// This padding setting have no impact ?
|
||||||
|
final ElkPadding labelPadding = new ElkPadding(100.0);
|
||||||
|
|
||||||
// Convert all "leaf" to ELK node
|
// Convert all "leaf" to ELK node
|
||||||
for (ILeaf leaf : diagram.getLeafsvalues()) {
|
for (ILeaf leaf : diagram.getLeafsvalues()) {
|
||||||
@ -162,7 +210,11 @@ public class CucaDiagramFileMakerElk implements CucaDiagramFileMaker {
|
|||||||
// There is no real "label" here
|
// There is no real "label" here
|
||||||
// We just would like to force node dimension
|
// We just would like to force node dimension
|
||||||
final ElkLabel label = ElkGraphUtil.createLabel(node);
|
final ElkLabel label = ElkGraphUtil.createLabel(node);
|
||||||
label.setDimensions(dimension.getWidth(), dimension.getHeight());
|
label.setText("X");
|
||||||
|
|
||||||
|
// I don't know why we have to do this hack, but somebody has to fix it
|
||||||
|
final double VERY_STRANGE_OFFSET = 10;
|
||||||
|
label.setDimensions(dimension.getWidth() - VERY_STRANGE_OFFSET, dimension.getHeight());
|
||||||
|
|
||||||
// No idea of what we are doing here :-)
|
// No idea of what we are doing here :-)
|
||||||
label.setProperty(CoreOptions.NODE_LABELS_PLACEMENT, EnumSet.of(NodeLabelPlacement.INSIDE,
|
label.setProperty(CoreOptions.NODE_LABELS_PLACEMENT, EnumSet.of(NodeLabelPlacement.INSIDE,
|
||||||
@ -175,22 +227,31 @@ public class CucaDiagramFileMakerElk implements CucaDiagramFileMaker {
|
|||||||
nodes.put(leaf, node);
|
nodes.put(leaf, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://www.eclipse.org/forums/index.php/t/1095737/
|
||||||
|
|
||||||
for (final Link link : diagram.getLinks()) {
|
for (final Link link : diagram.getLinks()) {
|
||||||
final ElkEdge edge = ElkGraphUtil.createEdge(root);
|
final ElkEdge edge = ElkGraphUtil.createEdge(root);
|
||||||
System.err.println("edge=" + edge);
|
|
||||||
edge.getSources().add(nodes.get(link.getEntity1()));
|
edge.getSources().add(nodes.get(link.getEntity1()));
|
||||||
edge.getTargets().add(nodes.get(link.getEntity2()));
|
edge.getTargets().add(nodes.get(link.getEntity2()));
|
||||||
|
edges.put(link, edge);
|
||||||
}
|
}
|
||||||
|
|
||||||
final RecursiveGraphLayoutEngine engine = new RecursiveGraphLayoutEngine();
|
final RecursiveGraphLayoutEngine engine = new RecursiveGraphLayoutEngine();
|
||||||
engine.layout(root, new NullElkProgressMonitor());
|
engine.layout(root, new NullElkProgressMonitor());
|
||||||
|
|
||||||
// Debug
|
// Debug
|
||||||
for (final ElkNode node : nodes.values()) {
|
// for (final ElkNode node : nodes.values()) {
|
||||||
final String name = node.getLabels().get(0).getText();
|
// final String name = node.getLabels().get(0).getText();
|
||||||
System.out.println("node " + name + " : " + node.getX() + ", " + node.getY() + " (" + node.getWidth()
|
// System.out.println("node " + name + " : " + node.getX() + ", " + node.getY() + " (" + node.getWidth()
|
||||||
+ ", " + node.getHeight() + ")");
|
// + ", " + node.getHeight() + ")");
|
||||||
}
|
// }
|
||||||
|
// for (final ElkEdge edge : edges.values()) {
|
||||||
|
// final EList<ElkEdgeSection> sections = edge.getSections();
|
||||||
|
// System.out.println("edge=" + edge.getSections());
|
||||||
|
// System.out.println("edge=" + edge.getProperty(LayeredOptions.JUNCTION_POINTS));
|
||||||
|
// for (ElkEdgeSection s : sections)
|
||||||
|
// System.out.println(s.getBendPoints());
|
||||||
|
// }
|
||||||
|
|
||||||
final MinMax minMax = TextBlockUtils.getMinMax(new Drawing(null), stringBounder, false);
|
final MinMax minMax = TextBlockUtils.getMinMax(new Drawing(null), stringBounder, false);
|
||||||
|
|
||||||
|
147
src/net/sourceforge/plantuml/elk/ElkPath.java
Normal file
147
src/net/sourceforge/plantuml/elk/ElkPath.java
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
/* ========================================================================
|
||||||
|
* PlantUML : a free UML diagram generator
|
||||||
|
* ========================================================================
|
||||||
|
*
|
||||||
|
* (C) Copyright 2009-2020, Arnaud Roques
|
||||||
|
*
|
||||||
|
* Project Info: http://plantuml.com
|
||||||
|
*
|
||||||
|
* If you like this project or if you find it useful, you can support us at:
|
||||||
|
*
|
||||||
|
* http://plantuml.com/patreon (only 1$ per month!)
|
||||||
|
* http://plantuml.com/paypal
|
||||||
|
*
|
||||||
|
* This file is part of PlantUML.
|
||||||
|
*
|
||||||
|
* PlantUML is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* PlantUML distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
* License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||||
|
* USA.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Original Author: Arnaud Roques
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package net.sourceforge.plantuml.elk;
|
||||||
|
|
||||||
|
import org.eclipse.elk.graph.ElkBendPoint;
|
||||||
|
import org.eclipse.elk.graph.ElkEdge;
|
||||||
|
import org.eclipse.elk.graph.ElkEdgeSection;
|
||||||
|
import org.eclipse.emf.common.util.EList;
|
||||||
|
|
||||||
|
import net.sourceforge.plantuml.ColorParam;
|
||||||
|
import net.sourceforge.plantuml.LineParam;
|
||||||
|
import net.sourceforge.plantuml.UmlDiagramType;
|
||||||
|
import net.sourceforge.plantuml.cucadiagram.CucaDiagram;
|
||||||
|
import net.sourceforge.plantuml.cucadiagram.Link;
|
||||||
|
import net.sourceforge.plantuml.cucadiagram.LinkType;
|
||||||
|
import net.sourceforge.plantuml.graphic.TextBlock;
|
||||||
|
import net.sourceforge.plantuml.graphic.UDrawable;
|
||||||
|
import net.sourceforge.plantuml.graphic.color.ColorType;
|
||||||
|
import net.sourceforge.plantuml.skin.rose.Rose;
|
||||||
|
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
||||||
|
import net.sourceforge.plantuml.ugraphic.ULine;
|
||||||
|
import net.sourceforge.plantuml.ugraphic.UStroke;
|
||||||
|
import net.sourceforge.plantuml.ugraphic.UTranslate;
|
||||||
|
import net.sourceforge.plantuml.ugraphic.color.HColor;
|
||||||
|
|
||||||
|
public class ElkPath implements UDrawable {
|
||||||
|
|
||||||
|
private final Link link;
|
||||||
|
private final ElkEdge edge;
|
||||||
|
|
||||||
|
private final CucaDiagram diagram;
|
||||||
|
private final TextBlock label;
|
||||||
|
private final TextBlock headLabel;
|
||||||
|
private final TextBlock tailLabel;
|
||||||
|
private final Rose rose = new Rose();
|
||||||
|
|
||||||
|
public ElkPath(Link link, ElkEdge edge, CucaDiagram diagram, TextBlock label, TextBlock tailLabel,
|
||||||
|
TextBlock headLabel) {
|
||||||
|
this.link = link;
|
||||||
|
this.edge = edge;
|
||||||
|
|
||||||
|
this.diagram = diagram;
|
||||||
|
this.label = label;
|
||||||
|
this.tailLabel = tailLabel;
|
||||||
|
this.headLabel = headLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ColorParam getArrowColorParam() {
|
||||||
|
if (diagram.getUmlDiagramType() == UmlDiagramType.CLASS) {
|
||||||
|
return ColorParam.arrow;
|
||||||
|
} else if (diagram.getUmlDiagramType() == UmlDiagramType.OBJECT) {
|
||||||
|
return ColorParam.arrow;
|
||||||
|
} else if (diagram.getUmlDiagramType() == UmlDiagramType.DESCRIPTION) {
|
||||||
|
return ColorParam.arrow;
|
||||||
|
} else if (diagram.getUmlDiagramType() == UmlDiagramType.ACTIVITY) {
|
||||||
|
return ColorParam.arrow;
|
||||||
|
} else if (diagram.getUmlDiagramType() == UmlDiagramType.STATE) {
|
||||||
|
return ColorParam.arrow;
|
||||||
|
}
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void drawU(UGraphic ug) {
|
||||||
|
|
||||||
|
if (link.isHidden()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
HColor color = rose.getHtmlColor(diagram.getSkinParam(), null, getArrowColorParam());
|
||||||
|
|
||||||
|
if (this.link.getColors() != null) {
|
||||||
|
final HColor newColor = this.link.getColors().getColor(ColorType.ARROW, ColorType.LINE);
|
||||||
|
if (newColor != null) {
|
||||||
|
color = newColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (this.link.getSpecificColor() != null) {
|
||||||
|
color = this.link.getSpecificColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
final LinkType linkType = link.getType();
|
||||||
|
UStroke stroke = linkType.getStroke3(diagram.getSkinParam().getThickness(LineParam.arrow, null));
|
||||||
|
if (link.getColors() != null && link.getColors().getSpecificLineStroke() != null) {
|
||||||
|
stroke = link.getColors().getSpecificLineStroke();
|
||||||
|
}
|
||||||
|
ug = ug.apply(stroke).apply(color);
|
||||||
|
|
||||||
|
final EList<ElkEdgeSection> sections = edge.getSections();
|
||||||
|
|
||||||
|
for (ElkEdgeSection section : sections) {
|
||||||
|
|
||||||
|
final EList<ElkBendPoint> points = section.getBendPoints();
|
||||||
|
|
||||||
|
double x1 = section.getStartX();
|
||||||
|
double y1 = section.getStartY();
|
||||||
|
|
||||||
|
for (ElkBendPoint pt : points) {
|
||||||
|
drawLine(ug, x1, y1, pt.getX(), pt.getY());
|
||||||
|
x1 = pt.getX();
|
||||||
|
y1 = pt.getY();
|
||||||
|
}
|
||||||
|
|
||||||
|
drawLine(ug, x1, y1, section.getEndX(), section.getEndY());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void drawLine(UGraphic ug, final double x1, final double y1, final double x2, final double y2) {
|
||||||
|
final ULine line = new ULine(x2 - x1, y2 - y1);
|
||||||
|
ug.apply(new UTranslate(x1, y1)).draw(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user