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-12-04 19:59:49 +01:00
parent 0d7f2eea2c
commit 3cf5e15bb4
24 changed files with 447 additions and 129 deletions

View File

@ -65,13 +65,8 @@ public class PSystemUtils {
FileFormatOption fileFormatOption, boolean checkMetadata) throws IOException { FileFormatOption fileFormatOption, boolean checkMetadata) throws IOException {
final SFile existingFile = suggestedFile.getFile(0); final SFile existingFile = suggestedFile.getFile(0);
if (checkMetadata && fileFormatOption.getFileFormat().doesSupportMetadata() && existingFile.exists() if (checkMetadata && fileFormatOption.getFileFormat().doesSupportMetadata() && existingFile.exists()) {
&& system.getNbImages() == 1) { // && system.getNbImages() == 1) {
// final String version = Version.versionString();
// System.out.println(system.getMetadata());
// System.out.println(data);
// System.out.println(version);
// System.out.println(data.contains(version));
final boolean sameMetadata = fileFormatOption.getFileFormat().equalsMetadata(system.getMetadata(), final boolean sameMetadata = fileFormatOption.getFileFormat().equalsMetadata(system.getMetadata(),
existingFile); existingFile);
if (sameMetadata) { if (sameMetadata) {
@ -80,15 +75,14 @@ public class PSystemUtils {
} }
} }
if (system instanceof NewpagedDiagram) { if (system instanceof NewpagedDiagram)
return exportDiagramsNewpaged((NewpagedDiagram) system, suggestedFile, fileFormatOption); return exportDiagramsNewpaged((NewpagedDiagram) system, suggestedFile, fileFormatOption);
}
if (system instanceof SequenceDiagram) { if (system instanceof SequenceDiagram)
return exportDiagramsSequence((SequenceDiagram) system, suggestedFile, fileFormatOption); return exportDiagramsSequence((SequenceDiagram) system, suggestedFile, fileFormatOption);
}
if (system instanceof CucaDiagram && fileFormatOption.getFileFormat() == FileFormat.HTML) { if (system instanceof CucaDiagram && fileFormatOption.getFileFormat() == FileFormat.HTML)
return createFilesHtml((CucaDiagram) system, suggestedFile); return createFilesHtml((CucaDiagram) system, suggestedFile);
}
return exportDiagramsDefault(system, suggestedFile, fileFormatOption); return exportDiagramsDefault(system, suggestedFile, fileFormatOption);
} }
@ -100,9 +94,9 @@ public class PSystemUtils {
for (int i = 0; i < nbImages; i++) { for (int i = 0; i < nbImages; i++) {
final SFile f = suggestedFile.getFile(i); final SFile f = suggestedFile.getFile(i);
if (canFileBeWritten(f) == false) { if (canFileBeWritten(f) == false)
return result; return result;
}
final OutputStream fos = f.createBufferedOutputStream(); final OutputStream fos = f.createBufferedOutputStream();
ImageData cmap = null; ImageData cmap = null;
try { try {
@ -141,9 +135,9 @@ public class PSystemUtils {
for (int i = 0; i < nbImages; i++) { for (int i = 0; i < nbImages; i++) {
final SFile f = suggestedFile.getFile(i); final SFile f = suggestedFile.getFile(i);
if (PSystemUtils.canFileBeWritten(suggestedFile.getFile(i)) == false) { if (PSystemUtils.canFileBeWritten(suggestedFile.getFile(i)) == false)
return result; return result;
}
final OutputStream fos = f.createBufferedOutputStream(); final OutputStream fos = f.createBufferedOutputStream();
ImageData cmap = null; ImageData cmap = null;
try { try {
@ -151,9 +145,9 @@ public class PSystemUtils {
} finally { } finally {
fos.close(); fos.close();
} }
if (cmap != null && cmap.containsCMapData()) { if (cmap != null && cmap.containsCMapData())
system.exportCmap(suggestedFile, i, cmap); system.exportCmap(suggestedFile, i, cmap);
}
Log.info("File size : " + f.length()); Log.info("File size : " + f.length());
result.add(new FileImageData(f, cmap)); result.add(new FileImageData(f, cmap));
} }
@ -179,9 +173,9 @@ public class PSystemUtils {
: diagram.getSkinParam().getSplitParam()).getFiles(); : diagram.getSkinParam().getSplitParam()).getFiles();
final List<FileImageData> result = new ArrayList<>(); final List<FileImageData> result = new ArrayList<>();
for (SFile f : files) { for (SFile f : files)
result.add(new FileImageData(f, imageData)); result.add(new FileImageData(f, imageData));
}
return result; return result;
} }
@ -190,13 +184,11 @@ public class PSystemUtils {
final SFile outputFile = suggestedFile.getFile(0); final SFile outputFile = suggestedFile.getFile(0);
if (outputFile.isDirectory()) { if (outputFile.isDirectory())
throw new IllegalArgumentException("File is a directory " + suggestedFile); throw new IllegalArgumentException("File is a directory " + suggestedFile);
}
if (!canFileBeWritten(outputFile)) { if (!canFileBeWritten(outputFile))
return emptyList(); return emptyList();
}
final ImageData imageData; final ImageData imageData;
@ -204,17 +196,14 @@ public class PSystemUtils {
imageData = system.exportDiagram(os, 0, fileFormatOption); imageData = system.exportDiagram(os, 0, fileFormatOption);
} }
if (imageData == null) { if (imageData == null)
return emptyList(); return emptyList();
}
if (imageData.containsCMapData() && system instanceof UmlDiagram) { if (imageData.containsCMapData() && system instanceof UmlDiagram)
((UmlDiagram) system).exportCmap(suggestedFile, 0, imageData); ((UmlDiagram) system).exportCmap(suggestedFile, 0, imageData);
}
if (system instanceof TitledDiagram && fileFormatOption.getFileFormat() == FileFormat.PNG) { if (system instanceof TitledDiagram && fileFormatOption.getFileFormat() == FileFormat.PNG)
return splitPng((TitledDiagram) system, suggestedFile, imageData, fileFormatOption); return splitPng((TitledDiagram) system, suggestedFile, imageData, fileFormatOption);
}
return singletonList(new FileImageData(outputFile, imageData)); return singletonList(new FileImageData(outputFile, imageData));
} }

View File

@ -65,23 +65,22 @@ public class ComponentTextNote extends AbstractComponentText {
final int height = (int) dimensionToUse.getHeight(); final int height = (int) dimensionToUse.getHeight();
charArea.fillRect(' ', 2, 1, width - 3, height - 2); charArea.fillRect(' ', 2, 1, width - 3, height - 2);
if (type == ComponentType.NOTE) { if (type == ComponentType.NOTE) {
if (fileFormat == FileFormat.UTXT) { if (fileFormat == FileFormat.UTXT)
charArea.drawNoteSimpleUnicode(2, 0, width - 2, height); charArea.drawNoteSimpleUnicode(2, 0, width - 2, height);
} else { else
charArea.drawNoteSimple(2, 0, width - 2, height); charArea.drawNoteSimple(2, 0, width - 2, height);
} } else if (type == ComponentType.NOTE_BOX || type == ComponentType.NOTE_HEXAGONAL) {
} else if (type == ComponentType.NOTE_BOX) { if (fileFormat == FileFormat.UTXT)
if (fileFormat == FileFormat.UTXT) {
charArea.drawBoxSimpleUnicode(2, 0, width - 2, height); charArea.drawBoxSimpleUnicode(2, 0, width - 2, height);
} else { else
charArea.drawBoxSimple(2, 0, width - 2, height); charArea.drawBoxSimple(2, 0, width - 2, height);
}
} }
if (fileFormat == FileFormat.UTXT) {
if (fileFormat == FileFormat.UTXT)
charArea.drawStringsLRUnicode(stringsToDisplay.asList(), 3, 1); charArea.drawStringsLRUnicode(stringsToDisplay.asList(), 3, 1);
} else { else
charArea.drawStringsLRSimple(stringsToDisplay.asList(), 3, 1); charArea.drawStringsLRSimple(stringsToDisplay.asList(), 3, 1);
}
} }
public double getPreferredHeight(StringBounder stringBounder) { public double getPreferredHeight(StringBounder stringBounder) {

View File

@ -75,7 +75,7 @@ public class TextSkin extends Rose {
@Override @Override
public Component createComponentNote(Style[] styles, ComponentType type, ISkinParam param, Display stringsToDisplay, public Component createComponentNote(Style[] styles, ComponentType type, ISkinParam param, Display stringsToDisplay,
Colors colors, NotePosition notePosition) { Colors colors, NotePosition notePosition) {
if (type == ComponentType.NOTE || type == ComponentType.NOTE_BOX) if (type == ComponentType.NOTE || type == ComponentType.NOTE_BOX || type == ComponentType.NOTE_HEXAGONAL)
return new ComponentTextNote(type, stringsToDisplay, fileFormat); return new ComponentTextNote(type, stringsToDisplay, fileFormat);
throw new UnsupportedOperationException(type.toString()); throw new UnsupportedOperationException(type.toString());

View File

@ -1,8 +1,12 @@
package net.sourceforge.plantuml.awt.geom; package net.sourceforge.plantuml.awt.geom;
import net.sourceforge.plantuml.awt.XShape; import net.sourceforge.plantuml.awt.XShape;
import net.sourceforge.plantuml.graphic.UDrawable;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.ULine;
import net.sourceforge.plantuml.ugraphic.UTranslate;
public class XLine2D implements XShape { public class XLine2D implements XShape, UDrawable {
final public double x1; final public double x1;
final public double y1; final public double y1;
@ -18,7 +22,10 @@ public class XLine2D implements XShape {
this.y1 = y1; this.y1 = y1;
this.x2 = x2; this.x2 = x2;
this.y2 = y2; this.y2 = y2;
}
public XLine2D(XPoint2D p1, XPoint2D p2) {
this(p1.getX(), p1.getY(), p2.getX(), p2.getY());
} }
public XPoint2D getMiddle() { public XPoint2D getMiddle() {
@ -27,10 +34,6 @@ public class XLine2D implements XShape {
return new XPoint2D(mx, my); return new XPoint2D(mx, my);
} }
public XLine2D(XPoint2D p1, XPoint2D p2) {
this(p1.getX(), p1.getY(), p2.getX(), p2.getY());
}
public final double getX1() { public final double getX1() {
return x1; return x1;
} }
@ -129,4 +132,31 @@ public class XLine2D implements XShape {
} }
return lenSq; return lenSq;
} }
public XPoint2D intersect(XLine2D line2) {
final double s1x = this.x2 - this.x1;
final double s1y = this.y2 - this.y1;
final double s2x = line2.x2 - line2.x1;
final double s2y = line2.y2 - line2.y1;
final double s = (-s1y * (this.x1 - line2.x1) + s1x * (this.y1 - line2.y1)) / (-s2x * s1y + s1x * s2y);
final double t = (s2x * (this.y1 - line2.y1) - s2y * (this.x1 - line2.x1)) / (-s2x * s1y + s1x * s2y);
if (s >= 0 && s <= 1 && t >= 0 && t <= 1)
return new XPoint2D(this.x1 + (t * s1x), this.y1 + (t * s1y));
return null;
}
public void drawU(UGraphic ug) {
ug = ug.apply(new UTranslate(x1, y1));
final ULine line = new ULine(x2 - x1, y2 - y1);
ug.draw(line);
}
public double getAngle() {
return Math.atan2(y2 - y1, x2 - x1);
}
} }

View File

@ -76,4 +76,30 @@ public class XRectangle2D implements XShape {
return xp >= getMinX() && xp < getMaxX() && yp >= getMinY() && yp < getMaxY(); return xp >= getMinX() && xp < getMaxX() && yp >= getMinY() && yp < getMaxY();
} }
public XPoint2D intersect(XLine2D line) {
final XPoint2D a = new XPoint2D(x, y);
final XPoint2D b = new XPoint2D(x + width, y);
final XPoint2D c = new XPoint2D(x + width, y + height);
final XPoint2D d = new XPoint2D(x, y + height);
final XLine2D line1 = new XLine2D(a, b);
final XLine2D line2 = new XLine2D(b, c);
final XLine2D line3 = new XLine2D(c, d);
final XLine2D line4 = new XLine2D(d, a);
XPoint2D result = line.intersect(line1);
if (result != null)
return result;
result = line.intersect(line2);
if (result != null)
return result;
result = line.intersect(line3);
if (result != null)
return result;
result = line.intersect(line4);
if (result != null)
return result;
return null;
}
} }

View File

@ -154,10 +154,12 @@ public class ETileBox extends ETile {
final URectangle rect = new URectangle(dimBox); final URectangle rect = new URectangle(dimBox);
ug.apply(new UTranslate(posxBox, posy)).apply(lineColor).apply(new UStroke(0.5)).draw(rect); ug.apply(new UTranslate(posxBox, posy)).apply(lineColor).apply(new UStroke(0.5)).draw(rect);
} else if (symbol == Symbol.SPECIAL_SEQUENCE) { } else if (symbol == Symbol.SPECIAL_SEQUENCE) {
final URectangle rect1 = new URectangle(dimBox.delta(2)).rounded(12); final URectangle rect = new URectangle(dimBox);
final URectangle rect2 = new URectangle(dimBox.delta(-2)).rounded(8); ug.apply(new UTranslate(posxBox, posy)).apply(lineColor).apply(new UStroke(5, 5, 1)).draw(rect);
ug.apply(new UTranslate(posxBox - 1, posy - 1)).apply(lineColor).apply(new UStroke(1.0, 1.0, 1.0)).draw(rect1); // final URectangle rect1 = new URectangle(dimBox.delta(2)).rounded(12);
ug.apply(new UTranslate(posxBox + 1, posy + 1)).apply(lineColor).apply(new UStroke(0.5)).draw(rect2); // final URectangle rect2 = new URectangle(dimBox.delta(-2)).rounded(8);
// ug.apply(new UTranslate(posxBox - 1, posy - 1)).apply(lineColor).apply(new UStroke(5.0, 5.0, 1.0)).draw(rect1);
// ug.apply(new UTranslate(posxBox + 1, posy + 1)).apply(lineColor).apply(new UStroke(0.5)).draw(rect2);
} else { } else {
final URectangle rect = new URectangle(dimBox).rounded(10); final URectangle rect = new URectangle(dimBox).rounded(10);
ug.apply(new UTranslate(posxBox, posy)).apply(lineColor).apply(backgroundColor.bg()).apply(new UStroke(1.5)) ug.apply(new UTranslate(posxBox, posy)).apply(lineColor).apply(backgroundColor.bg()).apply(new UStroke(1.5))

View File

@ -48,7 +48,7 @@ import net.sourceforge.plantuml.security.SImageIO;
public class IconLoader { public class IconLoader {
private static final int NUMBER_OF_ICONS = 30; private static final int NUMBER_OF_ICONS = 31;
private final static Map<String, BufferedImage> all = new ConcurrentHashMap<String, BufferedImage>(); private final static Map<String, BufferedImage> all = new ConcurrentHashMap<String, BufferedImage>();
static private final List<String> tmp = new ArrayList<>(); static private final List<String> tmp = new ArrayList<>();
@ -61,9 +61,9 @@ public class IconLoader {
private static String getSomeQuote() { private static String getSomeQuote() {
synchronized (tmp) { synchronized (tmp) {
if (tmp.size() == 0) { if (tmp.size() == 0) {
for (int i = 0; i < NUMBER_OF_ICONS; i++) { for (int i = 0; i < NUMBER_OF_ICONS; i++)
tmp.add("sprite" + String.format("%03d", i) + ".png"); tmp.add("sprite" + String.format("%03d", i) + ".png");
}
Collections.shuffle(tmp); Collections.shuffle(tmp);
} }
final int size = tmp.size(); final int size = tmp.size();
@ -77,9 +77,9 @@ public class IconLoader {
BufferedImage result = all.get(name); BufferedImage result = all.get(name);
if (result == null) { if (result == null) {
result = getIconSlow(name); result = getIconSlow(name);
if (result != null) { if (result != null)
all.put(name, result); all.put(name, result);
}
} }
return result; return result;
} }
@ -87,9 +87,9 @@ public class IconLoader {
private static BufferedImage getIconSlow(String name) { private static BufferedImage getIconSlow(String name) {
try { try {
final InputStream is = IconLoader.class.getResourceAsStream(name); final InputStream is = IconLoader.class.getResourceAsStream(name);
if (is == null) { if (is == null)
return null; return null;
}
final BufferedImage image = SImageIO.read(is); final BufferedImage image = SImageIO.read(is);
is.close(); is.close();
return image; return image;
@ -100,19 +100,18 @@ public class IconLoader {
} }
private static BufferedImage addTransparent(BufferedImage ico) { private static BufferedImage addTransparent(BufferedImage ico) {
if (ico == null) { if (ico == null)
return null; return null;
}
final BufferedImage transparentIcon = new BufferedImage(ico.getWidth(), ico.getHeight(), final BufferedImage transparentIcon = new BufferedImage(ico.getWidth(), ico.getHeight(),
BufferedImage.TYPE_INT_ARGB_PRE); BufferedImage.TYPE_INT_ARGB_PRE);
for (int i = 0; i < ico.getWidth(); i++) { for (int i = 0; i < ico.getWidth(); i++)
for (int j = 0; j < ico.getHeight(); j++) { for (int j = 0; j < ico.getHeight(); j++) {
final int col = ico.getRGB(i, j); final int col = ico.getRGB(i, j);
if (col != ico.getRGB(0, 0)) { if (col != ico.getRGB(0, 0))
transparentIcon.setRGB(i, j, col); transparentIcon.setRGB(i, j, col);
}
} }
}
return transparentIcon; return transparentIcon;
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@ -57,7 +57,8 @@ public class CommandLinkAnchor extends SingleLineCommand2<SequenceDiagram> {
new RegexLeaf("LINK", "\\<-\\>"), // new RegexLeaf("LINK", "\\<-\\>"), //
RegexLeaf.spaceZeroOrMore(), // RegexLeaf.spaceZeroOrMore(), //
new RegexLeaf("ANCHOR2", "\\{([%pLN_]+)\\}"), // new RegexLeaf("ANCHOR2", "\\{([%pLN_]+)\\}"), //
RegexLeaf.spaceZeroOrMore(), new RegexLeaf("MESSAGE", "(?::[%s]*(.*))?"), RegexLeaf.end()); RegexLeaf.spaceZeroOrMore(), //
new RegexLeaf("MESSAGE", "(?::[%s]*(.*))?"), RegexLeaf.end());
} }
@Override @Override

View File

@ -43,28 +43,28 @@ public abstract class Extremity implements UDrawable {
protected double manageround(double angle) { protected double manageround(double angle) {
final double deg = angle * 180.0 / Math.PI; final double deg = angle * 180.0 / Math.PI;
if (isCloseTo(0, deg)) { if (isCloseTo(0, deg))
return 0; return 0;
}
if (isCloseTo(90, deg)) { if (isCloseTo(90, deg))
return 90.0 * Math.PI / 180.0; return 90.0 * Math.PI / 180.0;
}
if (isCloseTo(180, deg)) { if (isCloseTo(180, deg))
return 180.0 * Math.PI / 180.0; return 180.0 * Math.PI / 180.0;
}
if (isCloseTo(270, deg)) { if (isCloseTo(270, deg))
return 270.0 * Math.PI / 180.0; return 270.0 * Math.PI / 180.0;
}
if (isCloseTo(360, deg)) { if (isCloseTo(360, deg))
return 0; return 0;
}
return angle; return angle;
} }
private boolean isCloseTo(double value, double variable) { private boolean isCloseTo(double value, double variable) {
if (Math.abs(value - variable) < 0.05) { if (Math.abs(value - variable) < 0.05)
return true; return true;
}
return false; return false;
} }

View File

@ -36,7 +36,6 @@
package net.sourceforge.plantuml.svek.extremity; package net.sourceforge.plantuml.svek.extremity;
import net.sourceforge.plantuml.awt.geom.XPoint2D; import net.sourceforge.plantuml.awt.geom.XPoint2D;
import net.sourceforge.plantuml.graphic.UDrawable;
import net.sourceforge.plantuml.ugraphic.UGraphic; import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.ULine; import net.sourceforge.plantuml.ugraphic.ULine;
import net.sourceforge.plantuml.ugraphic.UPolygon; import net.sourceforge.plantuml.ugraphic.UPolygon;

View File

@ -196,4 +196,8 @@ public abstract class AbstractCommonUGraphic implements UGraphic {
return false; return false;
} }
public final UTranslate getTranslate() {
return translate;
}
} }

View File

@ -50,9 +50,9 @@ public class UFont {
private static final Set<String> names = new HashSet<>(); private static final Set<String> names = new HashSet<>();
static { static {
for (String name : GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames()) { for (String name : GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames())
names.add(name.toLowerCase()); names.add(name.toLowerCase());
}
} }
public String toStringDebug() { public String toStringDebug() {
@ -71,9 +71,9 @@ public class UFont {
if (fontFamily.contains(",")) { if (fontFamily.contains(",")) {
for (String name : fontFamily.split(",")) { for (String name : fontFamily.split(",")) {
name = StringUtils.eventuallyRemoveStartingAndEndingDoubleQuote(name).trim(); name = StringUtils.eventuallyRemoveStartingAndEndingDoubleQuote(name).trim();
if (doesFamilyExists(name)) { if (doesFamilyExists(name))
return new Font(fontFamily, fontStyle, fontSize); return new Font(fontFamily, fontStyle, fontSize);
}
} }
} }
return new Font(fontFamily, fontStyle, fontSize); return new Font(fontFamily, fontStyle, fontSize);
@ -154,21 +154,22 @@ public class UFont {
public String getFamily(UFontContext context) { public String getFamily(UFontContext context) {
if (context == UFontContext.EPS) { if (context == UFontContext.EPS) {
if (family == null) { if (family == null)
return "Times-Roman"; return "Times-Roman";
}
return font.getPSName(); return font.getPSName();
} }
if (context == UFontContext.SVG) { if (context == UFontContext.SVG) {
if (family.equalsIgnoreCase("sansserif")) { if (family.equalsIgnoreCase("sansserif"))
return "sans-serif"; return "sans-serif";
}
return family; return family;
} }
return family; return family;
} }
// Kludge for testing because font names on some machines (only macOS?) do not end with <DOT><STYLE> // Kludge for testing because font names on some machines (only macOS?) do not
// end with <DOT><STYLE>
// See https://github.com/plantuml/plantuml/issues/720 // See https://github.com/plantuml/plantuml/issues/720
private String getPortableFontName() { private String getPortableFontName() {
final String name = font.getFontName(); final String name = font.getFontName();
@ -194,9 +195,9 @@ public class UFont {
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (obj instanceof UFont == false) { if (obj instanceof UFont == false)
return false; return false;
}
return this.font.equals(((UFont) obj).font); return this.font.equals(((UFont) obj).font);
} }

View File

@ -132,6 +132,15 @@ public class DriverTextG2d implements UDriver<UText, Graphics2D> {
visible.ensureVisible(x + width, y + 1.5); visible.ensureVisible(x + width, y + 1.5);
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
// https://stackoverflow.com/questions/31536952/how-to-fix-text-quality-in-java-graphics
// https://stackoverflow.com/questions/72818320/improve-java2d-drawing-quality-on-hi-resolution-monitors
/*
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
*/
g2d.setFont(font.getUnderlayingFont()); g2d.setFont(font.getUnderlayingFont());
g2d.setColor(fontConfiguration.getColor().toColor(mapper)); g2d.setColor(fontConfiguration.getColor().toColor(mapper));
g2d.drawString(text, (float) x, (float) y); g2d.drawString(text, (float) x, (float) y);

View File

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

View File

@ -50,18 +50,34 @@ import net.sourceforge.plantuml.ugraphic.color.NoSuchColorException;
public class CommandWBSItem extends SingleLineCommand2<WBSDiagram> { public class CommandWBSItem extends SingleLineCommand2<WBSDiagram> {
public CommandWBSItem() { public CommandWBSItem(int mode) {
super(false, getRegexConcat()); super(false, getRegexConcat(mode));
} }
static IRegex getRegexConcat() { static IRegex getRegexConcat(int mode) {
return RegexConcat.build(CommandWBSItem.class.getName(), RegexLeaf.start(), // if (mode == 0)
return RegexConcat.build(CommandWBSItem.class.getName() + mode, RegexLeaf.start(), //
new RegexLeaf("TYPE", "([ \t]*[*+-]+)"), //
new RegexOptional(new RegexLeaf("BACKCOLOR", "\\[(#\\w+)\\]")), //
new RegexOptional(new RegexLeaf("CODE", "\\(([%pLN_]+)\\)")), //
new RegexLeaf("SHAPE", "(_)?"), //
new RegexLeaf("DIRECTION", "([<>])?"), //
RegexLeaf.spaceOneOrMore(), //
new RegexLeaf("LABEL", "([^%s].*)"), //
RegexLeaf.end());
return RegexConcat.build(CommandWBSItem.class.getName() + mode, RegexLeaf.start(), //
new RegexLeaf("TYPE", "([ \t]*[*+-]+)"), // new RegexLeaf("TYPE", "([ \t]*[*+-]+)"), //
new RegexOptional(new RegexLeaf("BACKCOLOR", "\\[(#\\w+)\\]")), // new RegexOptional(new RegexLeaf("BACKCOLOR", "\\[(#\\w+)\\]")), //
new RegexLeaf("SHAPE", "(_)?"), // new RegexLeaf("SHAPE", "(_)?"), //
new RegexLeaf("DIRECTION", "([<>])?"), // new RegexLeaf("DIRECTION", "([<>])?"), //
RegexLeaf.spaceOneOrMore(), // RegexLeaf.spaceOneOrMore(), //
new RegexLeaf("LABEL", "([^%s].*)"), RegexLeaf.end()); new RegexLeaf("LABEL", "[%g](.*)[%g]"), //
RegexLeaf.spaceOneOrMore(), //
new RegexLeaf("as"), //
RegexLeaf.spaceOneOrMore(), //
new RegexLeaf("CODE", "([%pLN_]+)"), //
RegexLeaf.end());
} }
@Override @Override
@ -69,6 +85,7 @@ public class CommandWBSItem extends SingleLineCommand2<WBSDiagram> {
throws NoSuchColorException { throws NoSuchColorException {
final String type = arg.get("TYPE", 0); final String type = arg.get("TYPE", 0);
final String label = arg.get("LABEL", 0); final String label = arg.get("LABEL", 0);
final String code = arg.get("CODE", 0);
final String stringColor = arg.get("BACKCOLOR", 0); final String stringColor = arg.get("BACKCOLOR", 0);
HColor backColor = null; HColor backColor = null;
if (stringColor != null) if (stringColor != null)
@ -81,7 +98,7 @@ public class CommandWBSItem extends SingleLineCommand2<WBSDiagram> {
else if (">".equals(direction)) else if (">".equals(direction))
dir = Direction.RIGHT; dir = Direction.RIGHT;
return diagram.addIdea(backColor, diagram.getSmartLevel(type), label, dir, return diagram.addIdea(code, backColor, diagram.getSmartLevel(type), label, dir,
IdeaShape.fromDesc(arg.get("SHAPE", 0))); IdeaShape.fromDesc(arg.get("SHAPE", 0)));
} }

View File

@ -94,20 +94,18 @@ public class CommandWBSItemMultiline extends CommandMultilines2<WBSDiagram> {
lines = lines.removeStartingAndEnding(line0.get("DATA", 0), 1); lines = lines.removeStartingAndEnding(line0.get("DATA", 0), 1);
final String stereotype = lineLast.get(1); final String stereotype = lineLast.get(1);
if (stereotype != null) { if (stereotype != null)
lines = lines.overrideLastLine(lineLast.get(0)); lines = lines.overrideLastLine(lineLast.get(0));
}
final String type = line0.get("TYPE", 0); final String type = line0.get("TYPE", 0);
final String stringColor = line0.get("BACKCOLOR", 0); final String stringColor = line0.get("BACKCOLOR", 0);
HColor backColor = null; HColor backColor = null;
if (stringColor != null) { if (stringColor != null)
backColor = diagram.getSkinParam().getIHtmlColorSet().getColor(stringColor); backColor = diagram.getSkinParam().getIHtmlColorSet().getColor(stringColor);
}
Direction dir = Direction.RIGHT; Direction dir = Direction.RIGHT;
return diagram.addIdea(backColor, diagram.getSmartLevel(type), lines.toDisplay(), stereotype, dir, return diagram.addIdea(null, backColor, diagram.getSmartLevel(type), lines.toDisplay(), stereotype, dir,
IdeaShape.fromDesc(line0.get("SHAPE", 0))); IdeaShape.fromDesc(line0.get("SHAPE", 0)));
} }

View File

@ -0,0 +1,71 @@
/* ========================================================================
* 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.wbs;
import net.sourceforge.plantuml.LineLocation;
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;
public class CommandWBSLink extends SingleLineCommand2<WBSDiagram> {
public CommandWBSLink() {
super(getRegexConcat());
}
static IRegex getRegexConcat() {
return RegexConcat.build(CommandWBSLink.class.getName(), RegexLeaf.start(), //
new RegexLeaf("CODE1", "([%pLN_]+)"), //
RegexLeaf.spaceZeroOrMore(), //
new RegexLeaf("LINK", "-+\\>"), //
RegexLeaf.spaceZeroOrMore(), //
new RegexLeaf("CODE2", "([%pLN_]+)"), //
RegexLeaf.spaceZeroOrMore(), //
new RegexLeaf("MESSAGE", "(?::[%s]*(.*))?"), RegexLeaf.end());
}
@Override
protected CommandExecutionResult executeArg(WBSDiagram diagram, LineLocation location, RegexResult arg) {
final String code1 = arg.get("CODE1", 0);
final String code2 = arg.get("CODE2", 0);
// final String message = arg.get("MESSAGE", 0);
return diagram.link(code1, code2);
}
}

View File

@ -46,6 +46,7 @@ import net.sourceforge.plantuml.awt.geom.XPoint2D;
import net.sourceforge.plantuml.graphic.StringBounder; import net.sourceforge.plantuml.graphic.StringBounder;
import net.sourceforge.plantuml.graphic.TextBlock; import net.sourceforge.plantuml.graphic.TextBlock;
import net.sourceforge.plantuml.style.Style; import net.sourceforge.plantuml.style.Style;
import net.sourceforge.plantuml.ugraphic.AbstractCommonUGraphic;
import net.sourceforge.plantuml.ugraphic.UGraphic; import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.UTranslate; import net.sourceforge.plantuml.ugraphic.UTranslate;
@ -58,9 +59,11 @@ class ITFComposed extends WBSTextBlock implements ITF {
final private double delta1x = 10; final private double delta1x = 10;
final private double marginBottom;// = 15; final private double marginBottom;// = 15;
private final WElement idea;
private ITFComposed(ISkinParam skinParam, WElement idea, List<ITF> left, List<ITF> right) { private ITFComposed(ISkinParam skinParam, WElement idea, List<ITF> left, List<ITF> right) {
super(skinParam, idea.getStyleBuilder(), idea.getLevel()); super(skinParam, idea.getStyleBuilder(), idea.getLevel());
this.idea = idea;
this.left = left; this.left = left;
this.right = right; this.right = right;
this.main = buildMain(idea); this.main = buildMain(idea);
@ -69,17 +72,17 @@ class ITFComposed extends WBSTextBlock implements ITF {
} }
public static ITF build2(ISkinParam skinParam, WElement idea) { public static ITF build2(ISkinParam skinParam, WElement idea) {
if (idea.isLeaf()) { if (idea.isLeaf())
return new ITFLeaf(idea.getStyle(), idea.withBackColor(skinParam), idea.getLabel(), idea.getShape()); return new ITFLeaf(idea, idea.withBackColor(skinParam));
}
final List<ITF> left = new ArrayList<>(); final List<ITF> left = new ArrayList<>();
final List<ITF> right = new ArrayList<>(); final List<ITF> right = new ArrayList<>();
for (WElement child : idea.getChildren(Direction.LEFT)) { for (WElement child : idea.getChildren(Direction.LEFT))
left.add(build2(skinParam, child)); left.add(build2(skinParam, child));
}
for (WElement child : idea.getChildren(Direction.RIGHT)) { for (WElement child : idea.getChildren(Direction.RIGHT))
right.add(build2(skinParam, child)); right.add(build2(skinParam, child));
}
return new ITFComposed(skinParam, idea, left, right); return new ITFComposed(skinParam, idea, left, right);
} }
@ -128,7 +131,14 @@ class ITFComposed extends WBSTextBlock implements ITF {
public void drawU(final UGraphic ug) { public void drawU(final UGraphic ug) {
final StringBounder stringBounder = ug.getStringBounder(); final StringBounder stringBounder = ug.getStringBounder();
final XDimension2D mainDim = main.calculateDimension(stringBounder); final XDimension2D mainDim = main.calculateDimension(stringBounder);
if (ug instanceof AbstractCommonUGraphic) {
final UTranslate translate = ((AbstractCommonUGraphic) ug).getTranslate();
idea.setGeometry(translate, mainDim);
}
final double wx = getw1(stringBounder) - mainDim.getWidth() / 2; final double wx = getw1(stringBounder) - mainDim.getWidth() / 2;
main.drawU(ug.apply(UTranslate.dx(wx))); main.drawU(ug.apply(UTranslate.dx(wx)));
final double x = getw1(stringBounder); final double x = getw1(stringBounder);
@ -159,18 +169,18 @@ class ITFComposed extends WBSTextBlock implements ITF {
final private double getCollWidth(StringBounder stringBounder, Collection<? extends TextBlock> all) { final private double getCollWidth(StringBounder stringBounder, Collection<? extends TextBlock> all) {
double result = 0; double result = 0;
for (TextBlock child : all) { for (TextBlock child : all)
result = Math.max(result, child.calculateDimension(stringBounder).getWidth()); result = Math.max(result, child.calculateDimension(stringBounder).getWidth());
}
return result; return result;
} }
final private double getCollHeight(StringBounder stringBounder, Collection<? extends TextBlock> all, final private double getCollHeight(StringBounder stringBounder, Collection<? extends TextBlock> all,
double deltay) { double deltay) {
double result = 0; double result = 0;
for (TextBlock child : all) { for (TextBlock child : all)
result += deltay + child.calculateDimension(stringBounder).getHeight(); result += deltay + child.calculateDimension(stringBounder).getHeight();
}
return result; return result;
} }

View File

@ -47,18 +47,24 @@ import net.sourceforge.plantuml.graphic.TextBlock;
import net.sourceforge.plantuml.graphic.TextBlockUtils; import net.sourceforge.plantuml.graphic.TextBlockUtils;
import net.sourceforge.plantuml.mindmap.IdeaShape; import net.sourceforge.plantuml.mindmap.IdeaShape;
import net.sourceforge.plantuml.style.Style; import net.sourceforge.plantuml.style.Style;
import net.sourceforge.plantuml.ugraphic.AbstractCommonUGraphic;
import net.sourceforge.plantuml.ugraphic.UGraphic; import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.UTranslate;
class ITFLeaf extends AbstractTextBlock implements ITF { class ITFLeaf extends AbstractTextBlock implements ITF {
private final TextBlock box; private final TextBlock box;
private final WElement idea;
public ITFLeaf(Style style, ISkinParam skinParam, Display label, IdeaShape shape) { public ITFLeaf(WElement idea, ISkinParam skinParam) {
final IdeaShape shape = idea.getShape();
final Style style = idea.getStyle();
final Display label = idea.getLabel();
this.idea = idea;
if (shape == IdeaShape.BOX) { if (shape == IdeaShape.BOX) {
this.box = FtileBoxOld.createWbs(style, skinParam, label); this.box = FtileBoxOld.createWbs(style, skinParam, label);
} else { } else {
final TextBlock text = label.create0( final TextBlock text = label.create0(style.getFontConfiguration(skinParam.getIHtmlColorSet()),
style.getFontConfiguration(skinParam.getIHtmlColorSet()),
style.getHorizontalAlignment(), skinParam, style.wrapWidth(), CreoleMode.FULL, null, null); style.getHorizontalAlignment(), skinParam, style.wrapWidth(), CreoleMode.FULL, null, null);
this.box = TextBlockUtils.withMargin(text, 0, 3, 1, 1); this.box = TextBlockUtils.withMargin(text, 0, 3, 1, 1);
} }
@ -69,6 +75,10 @@ class ITFLeaf extends AbstractTextBlock implements ITF {
} }
public void drawU(UGraphic ug) { public void drawU(UGraphic ug) {
if (ug instanceof AbstractCommonUGraphic) {
final UTranslate translate = ((AbstractCommonUGraphic) ug).getTranslate();
idea.setGeometry(translate, calculateDimension(ug.getStringBounder()));
}
box.drawU(ug); box.drawU(ug);
} }

View File

@ -37,6 +37,10 @@ package net.sourceforge.plantuml.wbs;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import net.sourceforge.plantuml.Direction; import net.sourceforge.plantuml.Direction;
import net.sourceforge.plantuml.FileFormatOption; import net.sourceforge.plantuml.FileFormatOption;
@ -54,16 +58,23 @@ import net.sourceforge.plantuml.core.UmlSource;
import net.sourceforge.plantuml.cucadiagram.Display; import net.sourceforge.plantuml.cucadiagram.Display;
import net.sourceforge.plantuml.graphic.InnerStrategy; import net.sourceforge.plantuml.graphic.InnerStrategy;
import net.sourceforge.plantuml.graphic.StringBounder; import net.sourceforge.plantuml.graphic.StringBounder;
import net.sourceforge.plantuml.graphic.TextBlock;
import net.sourceforge.plantuml.mindmap.IdeaShape; import net.sourceforge.plantuml.mindmap.IdeaShape;
import net.sourceforge.plantuml.style.NoStyleAvailableException; import net.sourceforge.plantuml.style.NoStyleAvailableException;
import net.sourceforge.plantuml.svek.TextBlockBackcolored; import net.sourceforge.plantuml.svek.TextBlockBackcolored;
import net.sourceforge.plantuml.ugraphic.AbstractCommonUGraphic;
import net.sourceforge.plantuml.ugraphic.MinMax; import net.sourceforge.plantuml.ugraphic.MinMax;
import net.sourceforge.plantuml.ugraphic.UGraphic; import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.UTranslate;
import net.sourceforge.plantuml.ugraphic.color.HColor; import net.sourceforge.plantuml.ugraphic.color.HColor;
public class WBSDiagram extends UmlDiagram { public class WBSDiagram extends UmlDiagram {
private WElement root;
private WElement last;
private String first;
private final Map<String, WElement> codes = new LinkedHashMap<>();
private final List<WBSLink> links = new ArrayList<>();
public DiagramDescription getDescription() { public DiagramDescription getDescription() {
return new DiagramDescription("Work Breakdown Structure"); return new DiagramDescription("Work Breakdown Structure");
} }
@ -106,18 +117,30 @@ public class WBSDiagram extends UmlDiagram {
} }
private void drawMe(UGraphic ug) { private void drawMe(UGraphic ug) {
getDrawingElement().drawU(ug); UTranslate translate = null;
if (ug instanceof AbstractCommonUGraphic)
translate = ((AbstractCommonUGraphic) ug).getTranslate();
final Fork fork = getDrawingElement();
fork.drawU(ug);
if (translate == null)
return;
ug = ug.apply(translate.reverse());
for (WBSLink link : links)
link.drawU(ug);
} }
private TextBlock getDrawingElement() { private Fork getDrawingElement() {
return new Fork(getSkinParam(), root); return new Fork(getSkinParam(), root);
} }
public final static Pattern2 patternStereotype = MyPattern public final static Pattern2 patternStereotype = MyPattern
.cmpile("^\\s*(.*?)(?:\\s*\\<\\<\\s*(.*)\\s*\\>\\>)\\s*$"); .cmpile("^\\s*(.*?)(?:\\s*\\<\\<\\s*(.*)\\s*\\>\\>)\\s*$");
public CommandExecutionResult addIdea(HColor backColor, int level, String label, Direction direction, public CommandExecutionResult addIdea(String code, HColor backColor, int level, String label, Direction direction,
IdeaShape shape) { IdeaShape shape) {
final Matcher2 m = patternStereotype.matcher(label); final Matcher2 m = patternStereotype.matcher(label);
String stereotype = null; String stereotype = null;
@ -126,10 +149,10 @@ public class WBSDiagram extends UmlDiagram {
stereotype = m.group(2); stereotype = m.group(2);
} }
final Display display = Display.getWithNewlines(label); final Display display = Display.getWithNewlines(label);
return addIdea(backColor, level, display, stereotype, direction, shape); return addIdea(code, backColor, level, display, stereotype, direction, shape);
} }
public CommandExecutionResult addIdea(HColor backColor, int level, Display display, String stereotype, public CommandExecutionResult addIdea(String code, HColor backColor, int level, Display display, String stereotype,
Direction direction, IdeaShape shape) { Direction direction, IdeaShape shape) {
try { try {
if (level == 0) { if (level == 0) {
@ -139,17 +162,13 @@ public class WBSDiagram extends UmlDiagram {
initRoot(backColor, display, stereotype, shape); initRoot(backColor, display, stereotype, shape);
return CommandExecutionResult.ok(); return CommandExecutionResult.ok();
} }
return add(backColor, level, display, stereotype, direction, shape); return add(code, backColor, level, display, stereotype, direction, shape);
} catch (NoStyleAvailableException e) { } catch (NoStyleAvailableException e) {
// Logme.error(e); // Logme.error(e);
return CommandExecutionResult.error("General failure: no style available."); return CommandExecutionResult.error("General failure: no style available.");
} }
} }
private WElement root;
private WElement last;
private String first;
private void initRoot(HColor backColor, Display display, String stereotype, IdeaShape shape) { private void initRoot(HColor backColor, Display display, String stereotype, IdeaShape shape) {
root = new WElement(backColor, display, stereotype, getSkinParam().getCurrentStyleBuilder(), shape); root = new WElement(backColor, display, stereotype, getSkinParam().getCurrentStyleBuilder(), shape);
last = root; last = root;
@ -185,13 +204,15 @@ public class WBSDiagram extends UmlDiagram {
throw new UnsupportedOperationException("type=<" + type + ">[" + first + "]"); throw new UnsupportedOperationException("type=<" + type + ">[" + first + "]");
} }
private CommandExecutionResult add(HColor backColor, int level, Display display, String stereotype, private CommandExecutionResult add(String code, HColor backColor, int level, Display display, String stereotype,
Direction direction, IdeaShape shape) { Direction direction, IdeaShape shape) {
try { try {
if (level == last.getLevel() + 1) { if (level == last.getLevel() + 1) {
final WElement newIdea = last.createElement(backColor, level, display, stereotype, direction, shape, final WElement newIdea = last.createElement(backColor, level, display, stereotype, direction, shape,
getSkinParam().getCurrentStyleBuilder()); getSkinParam().getCurrentStyleBuilder());
last = newIdea; last = newIdea;
if (code != null)
codes.put(code, newIdea);
return CommandExecutionResult.ok(); return CommandExecutionResult.ok();
} }
if (level <= last.getLevel()) { if (level <= last.getLevel()) {
@ -199,6 +220,8 @@ public class WBSDiagram extends UmlDiagram {
final WElement newIdea = getParentOfLast(diff).createElement(backColor, level, display, stereotype, final WElement newIdea = getParentOfLast(diff).createElement(backColor, level, display, stereotype,
direction, shape, getSkinParam().getCurrentStyleBuilder()); direction, shape, getSkinParam().getCurrentStyleBuilder());
last = newIdea; last = newIdea;
if (code != null)
codes.put(code, newIdea);
return CommandExecutionResult.ok(); return CommandExecutionResult.ok();
} }
return CommandExecutionResult.error("Bad tree structure"); return CommandExecutionResult.error("Bad tree structure");
@ -208,4 +231,17 @@ public class WBSDiagram extends UmlDiagram {
} }
} }
public CommandExecutionResult link(String code1, String code2) {
final WElement element1 = codes.get(code1);
if (element1 == null)
return CommandExecutionResult.error("No such node " + code1);
final WElement element2 = codes.get(code2);
if (element2 == null)
return CommandExecutionResult.error("No such node " + code2);
links.add(new WBSLink(element1, element2));
return CommandExecutionResult.ok();
}
} }

View File

@ -56,8 +56,10 @@ public class WBSDiagramFactory extends PSystemCommandFactory {
final List<Command> cmds = new ArrayList<>(); final List<Command> cmds = new ArrayList<>();
CommonCommands.addCommonCommands1(cmds); CommonCommands.addCommonCommands1(cmds);
cmds.add(new CommandWBSItem()); cmds.add(new CommandWBSItem(1));
cmds.add(new CommandWBSItem(0));
cmds.add(new CommandWBSItemMultiline()); cmds.add(new CommandWBSItemMultiline());
cmds.add(new CommandWBSLink());
return cmds; return cmds;
} }

View File

@ -0,0 +1,97 @@
/* ========================================================================
* 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.wbs;
import net.sourceforge.plantuml.awt.geom.XDimension2D;
import net.sourceforge.plantuml.awt.geom.XLine2D;
import net.sourceforge.plantuml.awt.geom.XPoint2D;
import net.sourceforge.plantuml.awt.geom.XRectangle2D;
import net.sourceforge.plantuml.graphic.UDrawable;
import net.sourceforge.plantuml.svek.extremity.ExtremityArrow;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.UTranslate;
import net.sourceforge.plantuml.ugraphic.color.HColors;
class WBSLink implements UDrawable {
private final WElement element1;
private final WElement element2;
public WBSLink(WElement element1, WElement element2) {
this.element1 = element1;
this.element2 = element2;
}
public final WElement getElement1() {
return element1;
}
public final WElement getElement2() {
return element2;
}
public void drawU(UGraphic ug) {
final WElement element1 = getElement1();
final WElement element2 = getElement2();
final UTranslate position1 = element1.getPosition();
final UTranslate position2 = element2.getPosition();
final XDimension2D dim1 = element1.getDimension();
final XDimension2D dim2 = element2.getDimension();
if (position1 != null && position2 != null) {
final XRectangle2D rect1 = new XRectangle2D(position1.getDx(), position1.getDy(), dim1.getWidth(),
dim1.getHeight());
final XRectangle2D rect2 = new XRectangle2D(position2.getDx(), position2.getDy(), dim2.getWidth(),
dim2.getHeight());
XLine2D line = new XLine2D(rect1.getCenterX(), rect1.getCenterY(), rect2.getCenterX(), rect2.getCenterY());
final XPoint2D c1 = rect1.intersect(line);
final XPoint2D c2 = rect2.intersect(line);
line = new XLine2D(c1, c2);
ug = ug.apply(HColors.RED);
line.drawU(ug);
final double angle = line.getAngle();
final ExtremityArrow arrow = new ExtremityArrow(c2, angle);
arrow.drawU(ug);
}
}
}

View File

@ -43,6 +43,7 @@ import java.util.List;
import net.sourceforge.plantuml.Direction; import net.sourceforge.plantuml.Direction;
import net.sourceforge.plantuml.ISkinParam; import net.sourceforge.plantuml.ISkinParam;
import net.sourceforge.plantuml.SkinParamColors; import net.sourceforge.plantuml.SkinParamColors;
import net.sourceforge.plantuml.awt.geom.XDimension2D;
import net.sourceforge.plantuml.cucadiagram.Display; import net.sourceforge.plantuml.cucadiagram.Display;
import net.sourceforge.plantuml.graphic.color.ColorType; import net.sourceforge.plantuml.graphic.color.ColorType;
import net.sourceforge.plantuml.graphic.color.Colors; import net.sourceforge.plantuml.graphic.color.Colors;
@ -52,6 +53,7 @@ import net.sourceforge.plantuml.style.SName;
import net.sourceforge.plantuml.style.Style; import net.sourceforge.plantuml.style.Style;
import net.sourceforge.plantuml.style.StyleBuilder; import net.sourceforge.plantuml.style.StyleBuilder;
import net.sourceforge.plantuml.style.StyleSignatureBasic; import net.sourceforge.plantuml.style.StyleSignatureBasic;
import net.sourceforge.plantuml.ugraphic.UTranslate;
import net.sourceforge.plantuml.ugraphic.color.HColor; import net.sourceforge.plantuml.ugraphic.color.HColor;
final public class WElement { final public class WElement {
@ -65,6 +67,8 @@ final public class WElement {
private final List<WElement> childrenLeft = new ArrayList<>(); private final List<WElement> childrenLeft = new ArrayList<>();
private final List<WElement> childrenRight = new ArrayList<>(); private final List<WElement> childrenRight = new ArrayList<>();
private final IdeaShape shape; private final IdeaShape shape;
private UTranslate position;
private XDimension2D dimension;
private StyleSignatureBasic getDefaultStyleDefinitionNode(int level) { private StyleSignatureBasic getDefaultStyleDefinitionNode(int level) {
final String depth = SName.depth(level); final String depth = SName.depth(level);
@ -85,7 +89,8 @@ final public class WElement {
return StyleSignatureBasic.of(SName.root, SName.element, SName.wbsDiagram, SName.node, SName.boxless) return StyleSignatureBasic.of(SName.root, SName.element, SName.wbsDiagram, SName.node, SName.boxless)
.addS(stereotype).add(depth); .addS(stereotype).add(depth);
return StyleSignatureBasic.of(SName.root, SName.element, SName.wbsDiagram, SName.node).addS(stereotype).add(depth); return StyleSignatureBasic.of(SName.root, SName.element, SName.wbsDiagram, SName.node).addS(stereotype)
.add(depth);
} }
public ISkinParam withBackColor(ISkinParam skinParam) { public ISkinParam withBackColor(ISkinParam skinParam) {
@ -172,4 +177,17 @@ final public class WElement {
return styleBuilder; return styleBuilder;
} }
public final void setGeometry(UTranslate position, XDimension2D dimension) {
this.position = position;
this.dimension = dimension;
}
public final UTranslate getPosition() {
return position;
}
public final XDimension2D getDimension() {
return dimension;
}
} }