2011-08-08 17:48:29 +00:00
|
|
|
/* ========================================================================
|
|
|
|
* PlantUML : a free UML diagram generator
|
|
|
|
* ========================================================================
|
|
|
|
*
|
2016-01-09 12:15:40 +00:00
|
|
|
* (C) Copyright 2009-2017, Arnaud Roques
|
2011-08-08 17:48:29 +00:00
|
|
|
*
|
|
|
|
* Project Info: http://plantuml.sourceforge.net
|
|
|
|
*
|
|
|
|
* 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
|
2013-12-10 19:36:50 +00:00
|
|
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
2011-08-08 17:48:29 +00:00
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
* [Java is a trademark or registered trademark of Sun Microsystems, Inc.
|
|
|
|
* in the United States and other countries.]
|
|
|
|
*
|
|
|
|
* Original Author: Arnaud Roques
|
|
|
|
*
|
|
|
|
* Revision $Revision: 4236 $
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
package net.sourceforge.plantuml.svek;
|
|
|
|
|
|
|
|
import java.awt.geom.Dimension2D;
|
|
|
|
import java.awt.geom.Point2D;
|
2013-12-10 19:36:50 +00:00
|
|
|
import java.util.Collection;
|
2011-08-08 17:48:29 +00:00
|
|
|
import java.util.List;
|
|
|
|
|
2013-12-10 19:36:50 +00:00
|
|
|
import net.sourceforge.plantuml.Direction;
|
|
|
|
import net.sourceforge.plantuml.Hideable;
|
2011-08-08 17:48:29 +00:00
|
|
|
import net.sourceforge.plantuml.ISkinParam;
|
2013-12-10 19:36:50 +00:00
|
|
|
import net.sourceforge.plantuml.Log;
|
2016-01-09 12:15:40 +00:00
|
|
|
import net.sourceforge.plantuml.OptionFlags;
|
2015-04-07 18:18:37 +00:00
|
|
|
import net.sourceforge.plantuml.Pragma;
|
2011-08-08 17:48:29 +00:00
|
|
|
import net.sourceforge.plantuml.StringUtils;
|
2013-12-10 19:36:50 +00:00
|
|
|
import net.sourceforge.plantuml.Url;
|
2011-09-07 20:41:58 +00:00
|
|
|
import net.sourceforge.plantuml.command.Position;
|
2013-12-10 19:36:50 +00:00
|
|
|
import net.sourceforge.plantuml.cucadiagram.Display;
|
2011-09-08 10:42:27 +00:00
|
|
|
import net.sourceforge.plantuml.cucadiagram.IEntity;
|
2013-12-10 19:36:50 +00:00
|
|
|
import net.sourceforge.plantuml.cucadiagram.IGroup;
|
2011-08-08 17:48:29 +00:00
|
|
|
import net.sourceforge.plantuml.cucadiagram.Link;
|
2013-12-10 19:36:50 +00:00
|
|
|
import net.sourceforge.plantuml.cucadiagram.LinkArrow;
|
2011-08-08 17:48:29 +00:00
|
|
|
import net.sourceforge.plantuml.cucadiagram.LinkDecor;
|
2013-12-10 19:36:50 +00:00
|
|
|
import net.sourceforge.plantuml.cucadiagram.LinkHat;
|
|
|
|
import net.sourceforge.plantuml.cucadiagram.LinkMiddleDecor;
|
2015-04-07 18:18:37 +00:00
|
|
|
import net.sourceforge.plantuml.cucadiagram.LinkType;
|
2016-01-09 12:15:40 +00:00
|
|
|
import net.sourceforge.plantuml.cucadiagram.dot.DotData;
|
2013-12-10 19:36:50 +00:00
|
|
|
import net.sourceforge.plantuml.cucadiagram.dot.GraphvizVersion;
|
2015-06-07 10:23:10 +00:00
|
|
|
import net.sourceforge.plantuml.graphic.AbstractTextBlock;
|
2011-08-08 17:48:29 +00:00
|
|
|
import net.sourceforge.plantuml.graphic.FontConfiguration;
|
2013-12-10 19:36:50 +00:00
|
|
|
import net.sourceforge.plantuml.graphic.HorizontalAlignment;
|
2011-08-08 17:48:29 +00:00
|
|
|
import net.sourceforge.plantuml.graphic.HtmlColor;
|
|
|
|
import net.sourceforge.plantuml.graphic.StringBounder;
|
|
|
|
import net.sourceforge.plantuml.graphic.TextBlock;
|
2013-12-10 19:36:50 +00:00
|
|
|
import net.sourceforge.plantuml.graphic.TextBlockArrow;
|
2011-08-08 17:48:29 +00:00
|
|
|
import net.sourceforge.plantuml.graphic.TextBlockUtils;
|
2013-12-10 19:36:50 +00:00
|
|
|
import net.sourceforge.plantuml.graphic.UDrawable;
|
2015-04-07 18:18:37 +00:00
|
|
|
import net.sourceforge.plantuml.graphic.USymbolFolder;
|
2013-12-10 19:36:50 +00:00
|
|
|
import net.sourceforge.plantuml.graphic.VerticalAlignment;
|
2015-09-28 20:42:17 +00:00
|
|
|
import net.sourceforge.plantuml.graphic.color.ColorType;
|
2011-08-08 17:48:29 +00:00
|
|
|
import net.sourceforge.plantuml.posimo.BezierUtils;
|
|
|
|
import net.sourceforge.plantuml.posimo.DotPath;
|
2011-09-08 10:42:27 +00:00
|
|
|
import net.sourceforge.plantuml.posimo.Moveable;
|
2011-08-08 17:48:29 +00:00
|
|
|
import net.sourceforge.plantuml.posimo.Positionable;
|
2011-09-07 20:41:58 +00:00
|
|
|
import net.sourceforge.plantuml.posimo.PositionableUtils;
|
2011-08-08 17:48:29 +00:00
|
|
|
import net.sourceforge.plantuml.svek.SvekUtils.PointListIterator;
|
2013-12-10 19:36:50 +00:00
|
|
|
import net.sourceforge.plantuml.svek.extremity.ExtremityFactory;
|
|
|
|
import net.sourceforge.plantuml.svek.image.EntityImageNoteLink;
|
|
|
|
import net.sourceforge.plantuml.ugraphic.UChangeBackColor;
|
|
|
|
import net.sourceforge.plantuml.ugraphic.UChangeColor;
|
2011-08-08 17:48:29 +00:00
|
|
|
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
|
|
|
import net.sourceforge.plantuml.ugraphic.UPolygon;
|
|
|
|
import net.sourceforge.plantuml.ugraphic.UShape;
|
|
|
|
import net.sourceforge.plantuml.ugraphic.UStroke;
|
2013-12-10 19:36:50 +00:00
|
|
|
import net.sourceforge.plantuml.ugraphic.UTranslate;
|
2011-08-08 17:48:29 +00:00
|
|
|
|
2013-12-10 19:36:50 +00:00
|
|
|
public class Line implements Moveable, Hideable {
|
2011-08-08 17:48:29 +00:00
|
|
|
|
2016-01-09 12:15:40 +00:00
|
|
|
private final Cluster ltail;
|
|
|
|
private final Cluster lhead;
|
2011-08-08 17:48:29 +00:00
|
|
|
private final Link link;
|
|
|
|
|
|
|
|
private final String startUid;
|
|
|
|
private final String endUid;
|
|
|
|
|
|
|
|
private final TextBlock startTailText;
|
|
|
|
private final TextBlock endHeadText;
|
2015-09-28 20:42:17 +00:00
|
|
|
private final TextBlock labelText;
|
2011-08-08 17:48:29 +00:00
|
|
|
|
|
|
|
private final int lineColor;
|
2011-09-07 20:41:58 +00:00
|
|
|
private final int noteLabelColor;
|
2011-08-08 17:48:29 +00:00
|
|
|
private final int startTailColor;
|
|
|
|
private final int endHeadColor;
|
|
|
|
|
2013-12-10 19:36:50 +00:00
|
|
|
private final StringBounder stringBounder;
|
|
|
|
private final Bibliotekon bibliotekon;
|
|
|
|
|
|
|
|
private DotPath dotPath;
|
|
|
|
|
2011-09-07 20:41:58 +00:00
|
|
|
private Positionable startTailLabelXY;
|
|
|
|
private Positionable endHeadLabelXY;
|
2015-09-28 20:42:17 +00:00
|
|
|
private Positionable labelXY;
|
2011-08-08 17:48:29 +00:00
|
|
|
|
2013-12-10 19:36:50 +00:00
|
|
|
private UDrawable extremity2;
|
|
|
|
private UDrawable extremity1;
|
2011-08-08 17:48:29 +00:00
|
|
|
|
2013-12-10 19:36:50 +00:00
|
|
|
private double dx;
|
|
|
|
private double dy;
|
|
|
|
|
|
|
|
private boolean opale;
|
|
|
|
private Cluster projectionCluster;
|
|
|
|
private final GraphvizVersion graphvizVersion;
|
|
|
|
|
2015-04-07 18:18:37 +00:00
|
|
|
private final Pragma pragma;
|
|
|
|
|
2013-12-10 19:36:50 +00:00
|
|
|
// private GraphvizVersion getGraphvizVersion() {
|
|
|
|
// if (pragma.isDefine("graphviz")==false) {
|
|
|
|
// return GraphvizVersion.COMMON;
|
|
|
|
// }
|
|
|
|
// final String value = pragma.getValue("graphviz");
|
|
|
|
// if ("2.34".equals(value)) {
|
|
|
|
// return GraphvizVersion.V2_34_0;
|
|
|
|
// }
|
|
|
|
// return GraphvizVersion.COMMON;
|
|
|
|
// }
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public String toString() {
|
|
|
|
return super.toString() + " color=" + lineColor;
|
|
|
|
}
|
|
|
|
|
2015-06-07 10:23:10 +00:00
|
|
|
class DirectionalTextBlock extends AbstractTextBlock implements TextBlock {
|
2013-12-10 19:36:50 +00:00
|
|
|
|
|
|
|
private final TextBlock right;
|
|
|
|
private final TextBlock left;
|
|
|
|
private final TextBlock up;
|
|
|
|
private final TextBlock down;
|
|
|
|
|
|
|
|
DirectionalTextBlock(TextBlock right, TextBlock left, TextBlock up, TextBlock down) {
|
|
|
|
this.right = right;
|
|
|
|
this.left = left;
|
|
|
|
this.up = up;
|
|
|
|
this.down = down;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void drawU(UGraphic ug) {
|
|
|
|
Direction dir = getDirection();
|
|
|
|
if (getLinkArrow() == LinkArrow.BACKWARD) {
|
|
|
|
dir = dir.getInv();
|
|
|
|
}
|
|
|
|
switch (dir) {
|
|
|
|
case RIGHT:
|
|
|
|
right.drawU(ug);
|
|
|
|
break;
|
|
|
|
case LEFT:
|
|
|
|
left.drawU(ug);
|
|
|
|
break;
|
|
|
|
case UP:
|
|
|
|
up.drawU(ug);
|
|
|
|
break;
|
|
|
|
case DOWN:
|
|
|
|
down.drawU(ug);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
throw new UnsupportedOperationException();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public Dimension2D calculateDimension(StringBounder stringBounder) {
|
|
|
|
return right.calculateDimension(stringBounder);
|
|
|
|
}
|
|
|
|
|
|
|
|
private Direction getDirection() {
|
|
|
|
if (isAutolink()) {
|
|
|
|
final double startAngle = dotPath.getStartAngle();
|
|
|
|
return Direction.LEFT;
|
|
|
|
}
|
|
|
|
final Point2D start = dotPath.getStartPoint();
|
|
|
|
final Point2D end = dotPath.getEndPoint();
|
|
|
|
final double ang = Math.atan2(end.getX() - start.getX(), end.getY() - start.getY());
|
|
|
|
if (ang > -Math.PI / 4 && ang < Math.PI / 4) {
|
|
|
|
return Direction.DOWN;
|
|
|
|
}
|
|
|
|
if (ang > Math.PI * 3 / 4 || ang < -Math.PI * 3 / 4) {
|
|
|
|
return Direction.UP;
|
|
|
|
}
|
|
|
|
return end.getX() > start.getX() ? Direction.RIGHT : Direction.LEFT;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// private boolean projectionStart() {
|
|
|
|
// return startUid.startsWith(Cluster.CENTER_ID);
|
|
|
|
// }
|
2011-08-08 17:48:29 +00:00
|
|
|
|
2016-01-09 12:15:40 +00:00
|
|
|
public Line(String startUid, String endUid, Link link, ColorSequence colorSequence, Cluster ltail, Cluster lhead,
|
2013-12-10 19:36:50 +00:00
|
|
|
ISkinParam skinParam, StringBounder stringBounder, FontConfiguration labelFont, Bibliotekon bibliotekon,
|
2015-04-07 18:18:37 +00:00
|
|
|
GraphvizVersion graphvizVersion, Pragma pragma) {
|
2011-08-08 17:48:29 +00:00
|
|
|
if (startUid == null || endUid == null || link == null) {
|
|
|
|
throw new IllegalArgumentException();
|
|
|
|
}
|
2015-09-28 20:42:17 +00:00
|
|
|
if (link.getColors() != null) {
|
|
|
|
skinParam = link.getColors().mute(skinParam);
|
|
|
|
labelFont = labelFont.mute(link.getColors());
|
|
|
|
}
|
2013-12-10 19:36:50 +00:00
|
|
|
this.graphvizVersion = graphvizVersion;
|
2015-04-07 18:18:37 +00:00
|
|
|
this.pragma = pragma;
|
2013-12-10 19:36:50 +00:00
|
|
|
this.bibliotekon = bibliotekon;
|
2011-08-08 17:48:29 +00:00
|
|
|
this.stringBounder = stringBounder;
|
|
|
|
this.link = link;
|
|
|
|
this.startUid = startUid;
|
|
|
|
this.endUid = endUid;
|
|
|
|
this.ltail = ltail;
|
|
|
|
this.lhead = lhead;
|
|
|
|
|
|
|
|
this.lineColor = colorSequence.getValue();
|
2011-09-07 20:41:58 +00:00
|
|
|
this.noteLabelColor = colorSequence.getValue();
|
2011-08-08 17:48:29 +00:00
|
|
|
this.startTailColor = colorSequence.getValue();
|
|
|
|
this.endHeadColor = colorSequence.getValue();
|
|
|
|
|
2011-09-07 20:41:58 +00:00
|
|
|
final TextBlock labelOnly;
|
2015-07-11 09:32:49 +00:00
|
|
|
if (Display.isNull(link.getLabel())) {
|
2013-12-10 19:36:50 +00:00
|
|
|
if (getLinkArrow() == LinkArrow.NONE) {
|
|
|
|
labelOnly = null;
|
|
|
|
} else {
|
|
|
|
final TextBlockArrow right = new TextBlockArrow(Direction.RIGHT, labelFont);
|
|
|
|
final TextBlockArrow left = new TextBlockArrow(Direction.LEFT, labelFont);
|
|
|
|
final TextBlockArrow up = new TextBlockArrow(Direction.UP, labelFont);
|
|
|
|
final TextBlockArrow down = new TextBlockArrow(Direction.DOWN, labelFont);
|
|
|
|
labelOnly = new DirectionalTextBlock(right, left, up, down);
|
|
|
|
}
|
2011-08-08 17:48:29 +00:00
|
|
|
} else {
|
2013-12-10 19:36:50 +00:00
|
|
|
final double marginLabel = startUid.equals(endUid) ? 6 : 1;
|
|
|
|
final TextBlock label = TextBlockUtils.withMargin(
|
2015-09-28 20:42:17 +00:00
|
|
|
link.getLabel().create(labelFont, skinParam.getDefaultTextAlignment(), skinParam), marginLabel,
|
|
|
|
marginLabel);
|
2013-12-10 19:36:50 +00:00
|
|
|
if (getLinkArrow() == LinkArrow.NONE) {
|
|
|
|
labelOnly = label;
|
|
|
|
} else {
|
|
|
|
TextBlock right = new TextBlockArrow(Direction.RIGHT, labelFont);
|
|
|
|
right = TextBlockUtils.mergeLR(label, right, VerticalAlignment.CENTER);
|
|
|
|
TextBlock left = new TextBlockArrow(Direction.LEFT, labelFont);
|
|
|
|
left = TextBlockUtils.mergeLR(left, label, VerticalAlignment.CENTER);
|
|
|
|
TextBlock up = new TextBlockArrow(Direction.UP, labelFont);
|
|
|
|
up = TextBlockUtils.mergeTB(up, label, HorizontalAlignment.CENTER);
|
|
|
|
TextBlock down = new TextBlockArrow(Direction.DOWN, labelFont);
|
|
|
|
down = TextBlockUtils.mergeTB(label, down, HorizontalAlignment.CENTER);
|
|
|
|
labelOnly = new DirectionalTextBlock(right, left, up, down);
|
|
|
|
}
|
2011-08-08 17:48:29 +00:00
|
|
|
}
|
|
|
|
|
2011-09-07 20:41:58 +00:00
|
|
|
final TextBlock noteOnly;
|
|
|
|
if (link.getNote() == null) {
|
|
|
|
noteOnly = null;
|
|
|
|
} else {
|
2015-09-28 20:42:17 +00:00
|
|
|
noteOnly = new EntityImageNoteLink(link.getNote(), link.getNoteColors(), skinParam);
|
2011-09-07 20:41:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (labelOnly != null && noteOnly != null) {
|
|
|
|
if (link.getNotePosition() == Position.LEFT) {
|
2015-09-28 20:42:17 +00:00
|
|
|
labelText = TextBlockUtils.mergeLR(noteOnly, labelOnly, VerticalAlignment.CENTER);
|
2011-09-07 20:41:58 +00:00
|
|
|
} else if (link.getNotePosition() == Position.RIGHT) {
|
2015-09-28 20:42:17 +00:00
|
|
|
labelText = TextBlockUtils.mergeLR(labelOnly, noteOnly, VerticalAlignment.CENTER);
|
2011-09-07 20:41:58 +00:00
|
|
|
} else if (link.getNotePosition() == Position.TOP) {
|
2015-09-28 20:42:17 +00:00
|
|
|
labelText = TextBlockUtils.mergeTB(noteOnly, labelOnly, HorizontalAlignment.CENTER);
|
2011-09-07 20:41:58 +00:00
|
|
|
} else {
|
2015-09-28 20:42:17 +00:00
|
|
|
labelText = TextBlockUtils.mergeTB(labelOnly, noteOnly, HorizontalAlignment.CENTER);
|
2011-09-07 20:41:58 +00:00
|
|
|
}
|
|
|
|
} else if (labelOnly != null) {
|
2015-09-28 20:42:17 +00:00
|
|
|
labelText = labelOnly;
|
2011-09-07 20:41:58 +00:00
|
|
|
} else if (noteOnly != null) {
|
2015-09-28 20:42:17 +00:00
|
|
|
labelText = noteOnly;
|
2011-09-07 20:41:58 +00:00
|
|
|
} else {
|
2015-09-28 20:42:17 +00:00
|
|
|
labelText = null;
|
2011-09-07 20:41:58 +00:00
|
|
|
}
|
|
|
|
|
2011-08-08 17:48:29 +00:00
|
|
|
if (link.getQualifier1() == null) {
|
|
|
|
startTailText = null;
|
|
|
|
} else {
|
2015-09-28 20:42:17 +00:00
|
|
|
startTailText = Display.getWithNewlines(link.getQualifier1()).create(labelFont, HorizontalAlignment.CENTER,
|
|
|
|
skinParam);
|
2011-08-08 17:48:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (link.getQualifier2() == null) {
|
|
|
|
endHeadText = null;
|
|
|
|
} else {
|
2015-09-28 20:42:17 +00:00
|
|
|
endHeadText = Display.getWithNewlines(link.getQualifier2()).create(labelFont, HorizontalAlignment.CENTER,
|
|
|
|
skinParam);
|
2011-08-08 17:48:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2013-12-10 19:36:50 +00:00
|
|
|
public boolean hasNoteLabelText() {
|
2015-09-28 20:42:17 +00:00
|
|
|
return labelText != null;
|
2013-12-10 19:36:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private LinkArrow getLinkArrow() {
|
|
|
|
return link.getLinkArrow();
|
|
|
|
}
|
|
|
|
|
2011-08-08 17:48:29 +00:00
|
|
|
public void appendLine(StringBuilder sb) {
|
2013-12-10 19:36:50 +00:00
|
|
|
// Log.println("inverted=" + isInverted());
|
|
|
|
// if (isInverted()) {
|
|
|
|
// sb.append(endUid);
|
|
|
|
// sb.append("->");
|
|
|
|
// sb.append(startUid);
|
|
|
|
// } else {
|
2011-08-08 17:48:29 +00:00
|
|
|
sb.append(startUid);
|
|
|
|
sb.append("->");
|
|
|
|
sb.append(endUid);
|
2013-12-10 19:36:50 +00:00
|
|
|
// }
|
2011-08-08 17:48:29 +00:00
|
|
|
sb.append("[");
|
2016-01-30 12:20:07 +00:00
|
|
|
final LinkType linkType = link.getTypePatchCluster();
|
2015-04-07 18:18:37 +00:00
|
|
|
String decoration = linkType.getSpecificDecorationSvek();
|
2011-08-08 17:48:29 +00:00
|
|
|
if (decoration.endsWith(",") == false) {
|
|
|
|
decoration += ",";
|
|
|
|
}
|
|
|
|
sb.append(decoration);
|
|
|
|
|
2013-12-10 19:36:50 +00:00
|
|
|
int length = link.getLength();
|
|
|
|
// if (graphvizVersion == GraphvizVersion.V2_34_0 && length == 1) {
|
|
|
|
// length = 2;
|
|
|
|
// }
|
2015-04-07 18:18:37 +00:00
|
|
|
if (pragma.horizontalLineBetweenDifferentPackageAllowed() || link.isInvis() || length != 1) {
|
2013-12-10 19:36:50 +00:00
|
|
|
sb.append("minlen=" + (length - 1));
|
2011-08-08 17:48:29 +00:00
|
|
|
sb.append(",");
|
|
|
|
}
|
|
|
|
sb.append("color=\"" + StringUtils.getAsHtml(lineColor) + "\"");
|
2015-09-28 20:42:17 +00:00
|
|
|
if (labelText != null) {
|
2011-08-08 17:48:29 +00:00
|
|
|
sb.append(",");
|
|
|
|
sb.append("label=<");
|
2015-09-28 20:42:17 +00:00
|
|
|
appendTable(sb, labelText.calculateDimension(stringBounder), noteLabelColor);
|
2011-08-08 17:48:29 +00:00
|
|
|
sb.append(">");
|
2013-12-10 19:36:50 +00:00
|
|
|
// sb.append(",labelfloat=true");
|
2011-08-08 17:48:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (startTailText != null) {
|
|
|
|
sb.append(",");
|
|
|
|
sb.append("taillabel=<");
|
|
|
|
appendTable(sb, startTailText.calculateDimension(stringBounder), startTailColor);
|
|
|
|
sb.append(">");
|
2013-12-10 19:36:50 +00:00
|
|
|
// sb.append(",labelangle=0");
|
2011-08-08 17:48:29 +00:00
|
|
|
}
|
|
|
|
if (endHeadText != null) {
|
|
|
|
sb.append(",");
|
|
|
|
sb.append("headlabel=<");
|
|
|
|
appendTable(sb, endHeadText.calculateDimension(stringBounder), endHeadColor);
|
|
|
|
sb.append(">");
|
2013-12-10 19:36:50 +00:00
|
|
|
// sb.append(",labelangle=0");
|
2011-08-08 17:48:29 +00:00
|
|
|
}
|
|
|
|
|
2016-01-09 12:15:40 +00:00
|
|
|
if (OptionFlags.USE_COMPOUND && ltail != null) {
|
2011-08-08 17:48:29 +00:00
|
|
|
sb.append(",");
|
|
|
|
sb.append("ltail=");
|
2016-01-09 12:15:40 +00:00
|
|
|
sb.append(ltail.getClusterId());
|
2011-08-08 17:48:29 +00:00
|
|
|
}
|
2016-01-09 12:15:40 +00:00
|
|
|
if (OptionFlags.USE_COMPOUND && lhead != null) {
|
2011-08-08 17:48:29 +00:00
|
|
|
sb.append(",");
|
|
|
|
sb.append("lhead=");
|
2016-01-09 12:15:40 +00:00
|
|
|
sb.append(lhead.getClusterId());
|
2011-08-08 17:48:29 +00:00
|
|
|
}
|
|
|
|
if (link.isInvis()) {
|
|
|
|
sb.append(",");
|
|
|
|
sb.append("style=invis");
|
|
|
|
}
|
2013-12-10 19:36:50 +00:00
|
|
|
|
|
|
|
if (link.isConstraint() == false || link.hasTwoEntryPointsSameContainer()) {
|
2015-04-07 18:18:37 +00:00
|
|
|
sb.append(",constraint=false");
|
2013-12-10 19:36:50 +00:00
|
|
|
}
|
|
|
|
|
2015-04-07 18:18:37 +00:00
|
|
|
if (link.getSametail() != null) {
|
|
|
|
sb.append(",sametail=" + link.getSametail());
|
|
|
|
}
|
2013-12-10 19:36:50 +00:00
|
|
|
|
2011-08-08 17:48:29 +00:00
|
|
|
sb.append("];");
|
|
|
|
SvekUtils.println(sb);
|
|
|
|
}
|
|
|
|
|
|
|
|
public String rankSame() {
|
2013-12-10 19:36:50 +00:00
|
|
|
// if (graphvizVersion == GraphvizVersion.V2_34_0) {
|
|
|
|
// return null;
|
|
|
|
// }
|
2015-04-07 18:18:37 +00:00
|
|
|
if (pragma.horizontalLineBetweenDifferentPackageAllowed() == false && link.getLength() == 1) {
|
2011-09-07 20:41:58 +00:00
|
|
|
return "{rank=same; " + getStartUid() + "; " + getEndUid() + "}";
|
2011-08-08 17:48:29 +00:00
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void appendTable(StringBuilder sb, Dimension2D dim, int col) {
|
|
|
|
final int w = (int) dim.getWidth();
|
|
|
|
final int h = (int) dim.getHeight();
|
|
|
|
appendTable(sb, w, h, col);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void appendTable(StringBuilder sb, int w, int h, int col) {
|
|
|
|
sb.append("<TABLE ");
|
|
|
|
sb.append("BGCOLOR=\"" + StringUtils.getAsHtml(col) + "\" ");
|
|
|
|
sb.append("FIXEDSIZE=\"TRUE\" WIDTH=\"" + w + "\" HEIGHT=\"" + h + "\">");
|
|
|
|
sb.append("<TR");
|
|
|
|
sb.append(">");
|
|
|
|
sb.append("<TD");
|
|
|
|
// sb.append(" FIXEDSIZE=\"TRUE\" WIDTH=\"" + 0 + "\" HEIGHT=\"" + 0 +
|
|
|
|
// "\"");
|
|
|
|
sb.append(">");
|
|
|
|
sb.append("</TD>");
|
|
|
|
sb.append("</TR>");
|
|
|
|
sb.append("</TABLE>");
|
|
|
|
}
|
|
|
|
|
|
|
|
public final String getStartUid() {
|
2011-09-07 20:41:58 +00:00
|
|
|
if (startUid.endsWith(":h")) {
|
|
|
|
return startUid.substring(0, startUid.length() - 2);
|
|
|
|
}
|
2011-08-08 17:48:29 +00:00
|
|
|
return startUid;
|
|
|
|
}
|
|
|
|
|
|
|
|
public final String getEndUid() {
|
2011-09-07 20:41:58 +00:00
|
|
|
if (endUid.endsWith(":h")) {
|
|
|
|
return endUid.substring(0, endUid.length() - 2);
|
|
|
|
}
|
2011-08-08 17:48:29 +00:00
|
|
|
return endUid;
|
|
|
|
}
|
|
|
|
|
2016-01-09 12:15:40 +00:00
|
|
|
private UDrawable getExtremity(LinkHat hat, LinkDecor decor, PointListIterator pointListIterator, Point2D center,
|
2016-01-30 12:20:07 +00:00
|
|
|
double angle, Cluster cluster, boolean isGroup) {
|
2013-12-10 19:36:50 +00:00
|
|
|
final ExtremityFactory extremityFactory = decor.getExtremityFactory();
|
|
|
|
|
2016-01-09 12:15:40 +00:00
|
|
|
if (OptionFlags.USE_COMPOUND == false && cluster != null) {
|
|
|
|
if (extremityFactory != null) {
|
|
|
|
// System.err.println("angle=" + angle * 180 / Math.PI);
|
|
|
|
return extremityFactory.createUDrawable(center, angle);
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2013-12-10 19:36:50 +00:00
|
|
|
if (extremityFactory != null) {
|
|
|
|
final List<Point2D.Double> points = pointListIterator.next();
|
|
|
|
final Point2D p0 = points.get(0);
|
|
|
|
final Point2D p1 = points.get(1);
|
|
|
|
final Point2D p2 = points.get(2);
|
|
|
|
return extremityFactory.createUDrawable(p0, p1, p2);
|
|
|
|
} else if (decor != LinkDecor.NONE) {
|
|
|
|
final UShape sh = new UPolygon(pointListIterator.next());
|
|
|
|
return new UDrawable() {
|
|
|
|
public void drawU(UGraphic ug) {
|
|
|
|
ug.draw(sh);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2016-01-09 12:15:40 +00:00
|
|
|
public void solveLine(final String svg, final int fullHeight, MinFinder corner1, DotData dotData) {
|
2011-08-08 17:48:29 +00:00
|
|
|
if (this.link.isInvis()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-12-10 19:36:50 +00:00
|
|
|
int idx = getIndexFromColor(svg, this.lineColor);
|
2011-08-08 17:48:29 +00:00
|
|
|
if (idx == -1) {
|
2013-12-10 19:36:50 +00:00
|
|
|
return;
|
|
|
|
// throw new IllegalStateException();
|
2011-08-08 17:48:29 +00:00
|
|
|
}
|
|
|
|
idx = svg.indexOf("d=\"", idx);
|
|
|
|
if (idx == -1) {
|
|
|
|
throw new IllegalStateException();
|
|
|
|
}
|
|
|
|
final int end = svg.indexOf("\"", idx + 3);
|
|
|
|
final String path = svg.substring(idx + 3, end);
|
2016-01-30 12:20:07 +00:00
|
|
|
|
2011-08-08 17:48:29 +00:00
|
|
|
dotPath = new DotPath(path, fullHeight);
|
2016-01-09 12:15:40 +00:00
|
|
|
if (OptionFlags.USE_COMPOUND == false) {
|
|
|
|
if (projectionCluster != null) {
|
|
|
|
System.err.println("Line::solveLine1 projectionCluster=" + projectionCluster.getClusterPosition());
|
|
|
|
projectionCluster.manageEntryExitPoint(dotData, TextBlockUtils.getDummyStringBounder());
|
|
|
|
System.err.println("Line::solveLine2 projectionCluster=" + projectionCluster.getClusterPosition());
|
|
|
|
if (lhead != null)
|
|
|
|
System.err.println("Line::solveLine ltail=" + lhead.getClusterPosition());
|
|
|
|
if (ltail != null)
|
|
|
|
System.err.println("Line::solveLine ltail=" + ltail.getClusterPosition());
|
|
|
|
}
|
|
|
|
dotPath = dotPath.simulateCompound(lhead, ltail);
|
|
|
|
}
|
2011-08-08 17:48:29 +00:00
|
|
|
|
|
|
|
final PointListIterator pointListIterator = new PointListIterator(svg.substring(end), fullHeight);
|
|
|
|
|
2015-04-07 18:18:37 +00:00
|
|
|
final LinkType linkType = link.getType();
|
2016-01-09 12:15:40 +00:00
|
|
|
this.extremity2 = getExtremity(linkType.getHat2(), linkType.getDecor2(), pointListIterator,
|
2016-01-30 12:20:07 +00:00
|
|
|
dotPath.getStartPoint(), dotPath.getStartAngle() + Math.PI, ltail, link.getEntity1().isGroup());
|
2016-01-09 12:15:40 +00:00
|
|
|
this.extremity1 = getExtremity(linkType.getHat1(), linkType.getDecor1(), pointListIterator,
|
2016-01-30 12:20:07 +00:00
|
|
|
dotPath.getEndPoint(), dotPath.getEndAngle(), lhead, link.getEntity2().isGroup());
|
2011-09-07 20:41:58 +00:00
|
|
|
|
2015-09-28 20:42:17 +00:00
|
|
|
if (this.labelText != null) {
|
2013-12-10 19:36:50 +00:00
|
|
|
final Point2D pos = getXY(svg, this.noteLabelColor, fullHeight);
|
|
|
|
if (pos != null) {
|
|
|
|
corner1.manage(pos);
|
2015-09-28 20:42:17 +00:00
|
|
|
this.labelXY = TextBlockUtils.asPositionable(labelText, stringBounder, pos);
|
2013-12-10 19:36:50 +00:00
|
|
|
}
|
2011-08-08 17:48:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (this.startTailText != null) {
|
2013-12-10 19:36:50 +00:00
|
|
|
final Point2D pos = getXY(svg, this.startTailColor, fullHeight);
|
|
|
|
if (pos != null) {
|
|
|
|
corner1.manage(pos);
|
|
|
|
this.startTailLabelXY = TextBlockUtils.asPositionable(startTailText, stringBounder, pos);
|
|
|
|
}
|
2011-08-08 17:48:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (this.endHeadText != null) {
|
2013-12-10 19:36:50 +00:00
|
|
|
final Point2D pos = getXY(svg, this.endHeadColor, fullHeight);
|
|
|
|
if (pos != null) {
|
|
|
|
corner1.manage(pos);
|
|
|
|
this.endHeadLabelXY = TextBlockUtils.asPositionable(endHeadText, stringBounder, pos);
|
2016-01-09 12:15:40 +00:00
|
|
|
corner1.manage(pos.getX() - 15, pos.getY());
|
2013-12-10 19:36:50 +00:00
|
|
|
}
|
2011-08-08 17:48:29 +00:00
|
|
|
}
|
|
|
|
|
2011-09-08 10:42:27 +00:00
|
|
|
if (isOpalisable() == false) {
|
|
|
|
setOpale(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private boolean isOpalisable() {
|
|
|
|
return dotPath.getBeziers().size() <= 1;
|
2011-08-08 17:48:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private Point2D.Double getXY(String svg, int color, int height) {
|
2013-12-10 19:36:50 +00:00
|
|
|
final int idx = getIndexFromColor(svg, color);
|
2011-08-08 17:48:29 +00:00
|
|
|
if (idx == -1) {
|
2013-12-10 19:36:50 +00:00
|
|
|
return null;
|
2011-08-08 17:48:29 +00:00
|
|
|
}
|
|
|
|
return SvekUtils.getMinXY(SvekUtils.extractPointsList(svg, idx, height));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2013-12-10 19:36:50 +00:00
|
|
|
private int getIndexFromColor(String svg, int color) {
|
2015-04-07 18:18:37 +00:00
|
|
|
String s = "stroke=\"" + StringUtils.goLowerCase(StringUtils.getAsHtml(color)) + "\"";
|
2013-12-10 19:36:50 +00:00
|
|
|
int idx = svg.indexOf(s);
|
|
|
|
if (idx != -1) {
|
|
|
|
return idx;
|
|
|
|
}
|
2015-04-07 18:18:37 +00:00
|
|
|
s = ";stroke:" + StringUtils.goLowerCase(StringUtils.getAsHtml(color)) + ";";
|
2013-12-10 19:36:50 +00:00
|
|
|
idx = svg.indexOf(s);
|
|
|
|
if (idx != -1) {
|
|
|
|
return idx;
|
|
|
|
}
|
2015-04-07 18:18:37 +00:00
|
|
|
s = "fill=\"" + StringUtils.goLowerCase(StringUtils.getAsHtml(color)) + "\"";
|
2013-12-10 19:36:50 +00:00
|
|
|
idx = svg.indexOf(s);
|
|
|
|
if (idx != -1) {
|
|
|
|
return idx;
|
|
|
|
}
|
2015-04-07 18:18:37 +00:00
|
|
|
Log.info("Cannot find color=" + color + " " + StringUtils.goLowerCase(StringUtils.getAsHtml(color)));
|
2013-12-10 19:36:50 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
2011-09-08 10:42:27 +00:00
|
|
|
|
2015-04-07 18:18:37 +00:00
|
|
|
public void drawU(UGraphic ug, HtmlColor color) {
|
2011-09-08 10:42:27 +00:00
|
|
|
if (opale) {
|
|
|
|
return;
|
|
|
|
}
|
2013-12-10 19:36:50 +00:00
|
|
|
|
2015-04-07 18:18:37 +00:00
|
|
|
double x = 0;
|
|
|
|
double y = 0;
|
2013-12-10 19:36:50 +00:00
|
|
|
final Url url = link.getUrl();
|
|
|
|
if (url != null) {
|
|
|
|
ug.startUrl(url);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (link.isAutoLinkOfAGroup()) {
|
|
|
|
final Cluster cl = bibliotekon.getCluster((IGroup) link.getEntity1());
|
|
|
|
x += cl.getWidth();
|
|
|
|
x -= dotPath.getStartPoint().getX() - cl.getMinX();
|
|
|
|
}
|
|
|
|
|
2011-09-08 10:42:27 +00:00
|
|
|
x += dx;
|
|
|
|
y += dy;
|
|
|
|
|
2011-08-08 17:48:29 +00:00
|
|
|
if (link.isInvis()) {
|
|
|
|
return;
|
|
|
|
}
|
2015-09-28 20:42:17 +00:00
|
|
|
|
|
|
|
if (this.link.getColors() != null) {
|
|
|
|
final HtmlColor newColor = this.link.getColors().getColor(ColorType.ARROW, ColorType.LINE);
|
|
|
|
if (newColor != null) {
|
|
|
|
color = newColor;
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if (this.link.getSpecificColor() != null) {
|
2011-08-08 17:48:29 +00:00
|
|
|
color = this.link.getSpecificColor();
|
|
|
|
}
|
2011-09-08 10:42:27 +00:00
|
|
|
|
2013-12-10 19:36:50 +00:00
|
|
|
ug = ug.apply(new UChangeBackColor(null)).apply(new UChangeColor(color));
|
2015-04-07 18:18:37 +00:00
|
|
|
final LinkType linkType = link.getType();
|
2015-09-28 20:42:17 +00:00
|
|
|
UStroke stroke = linkType.getStroke();
|
|
|
|
if (link.getColors() != null && link.getColors().getSpecificLineStroke() != null) {
|
|
|
|
stroke = link.getColors().getSpecificLineStroke();
|
|
|
|
}
|
|
|
|
ug = ug.apply(stroke);
|
2013-12-10 19:36:50 +00:00
|
|
|
double moveStartX = 0;
|
|
|
|
double moveStartY = 0;
|
|
|
|
double moveEndX = 0;
|
|
|
|
double moveEndY = 0;
|
2016-01-09 12:15:40 +00:00
|
|
|
if (OptionFlags.USE_COMPOUND && projectionCluster != null && link.getEntity1() == projectionCluster.getGroup()) {
|
2013-12-10 19:36:50 +00:00
|
|
|
final DotPath copy = new DotPath(dotPath);
|
|
|
|
final Point2D start = copy.getStartPoint();
|
|
|
|
final Point2D proj = projectionCluster.getClusterPosition().getProjectionOnFrontier(start);
|
|
|
|
moveStartX = proj.getX() - start.getX();
|
|
|
|
moveStartY = proj.getY() - start.getY();
|
|
|
|
copy.forceStartPoint(proj.getX(), proj.getY());
|
|
|
|
ug.apply(new UTranslate(x, y)).draw(copy);
|
2016-01-09 12:15:40 +00:00
|
|
|
} else if (OptionFlags.USE_COMPOUND && projectionCluster != null
|
|
|
|
&& link.getEntity2() == projectionCluster.getGroup()) {
|
2013-12-10 19:36:50 +00:00
|
|
|
final DotPath copy = new DotPath(dotPath);
|
|
|
|
final Point2D end = copy.getEndPoint();
|
|
|
|
final Point2D proj = projectionCluster.getClusterPosition().getProjectionOnFrontier(end);
|
|
|
|
moveEndX = proj.getX() - end.getX();
|
|
|
|
moveEndY = proj.getY() - end.getY();
|
|
|
|
copy.forceEndPoint(proj.getX(), proj.getY());
|
|
|
|
ug.apply(new UTranslate(x, y)).draw(copy);
|
|
|
|
} else {
|
|
|
|
if (dotPath == null) {
|
|
|
|
Log.info("DotPath is null for " + this);
|
|
|
|
return;
|
|
|
|
}
|
2015-04-07 18:18:37 +00:00
|
|
|
DotPath todraw = dotPath;
|
|
|
|
if (link.getEntity2().isGroup() && link.getEntity2().getUSymbol() instanceof USymbolFolder) {
|
|
|
|
final Cluster endCluster = bibliotekon.getCluster((IGroup) link.getEntity2());
|
|
|
|
if (endCluster != null) {
|
|
|
|
final double deltaFolderH = endCluster.checkFolderPosition(dotPath.getEndPoint(),
|
|
|
|
ug.getStringBounder());
|
|
|
|
todraw = new DotPath(dotPath);
|
|
|
|
todraw.moveEndPoint(0, deltaFolderH);
|
|
|
|
moveEndY = deltaFolderH;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ug.apply(new UTranslate(x, y)).draw(todraw);
|
|
|
|
}
|
2013-12-10 19:36:50 +00:00
|
|
|
|
|
|
|
ug = ug.apply(new UStroke()).apply(new UChangeColor(color));
|
2011-08-08 17:48:29 +00:00
|
|
|
|
2013-12-10 19:36:50 +00:00
|
|
|
if (this.extremity1 != null) {
|
2015-04-07 18:18:37 +00:00
|
|
|
if (linkType.getDecor1().isFill()) {
|
2013-12-10 19:36:50 +00:00
|
|
|
ug = ug.apply(new UChangeBackColor(color));
|
2011-08-08 17:48:29 +00:00
|
|
|
} else {
|
2013-12-10 19:36:50 +00:00
|
|
|
ug = ug.apply(new UChangeBackColor(null));
|
2011-08-08 17:48:29 +00:00
|
|
|
}
|
2016-01-09 12:15:40 +00:00
|
|
|
if (OptionFlags.USE_COMPOUND || lhead == null) {
|
|
|
|
this.extremity1.drawU(ug.apply(new UTranslate(x + moveEndX, y + moveEndY)));
|
|
|
|
} else {
|
|
|
|
// System.err.println("Line::draw EXTREMITY1");
|
|
|
|
this.extremity1.drawU(ug.apply(new UTranslate(x, y)));
|
|
|
|
}
|
2011-08-08 17:48:29 +00:00
|
|
|
}
|
2013-12-10 19:36:50 +00:00
|
|
|
if (this.extremity2 != null) {
|
2015-04-07 18:18:37 +00:00
|
|
|
if (linkType.getDecor2().isFill()) {
|
2013-12-10 19:36:50 +00:00
|
|
|
ug = ug.apply(new UChangeBackColor(color));
|
2011-08-08 17:48:29 +00:00
|
|
|
} else {
|
2013-12-10 19:36:50 +00:00
|
|
|
ug = ug.apply(new UChangeBackColor(null));
|
2011-08-08 17:48:29 +00:00
|
|
|
}
|
2016-01-09 12:15:40 +00:00
|
|
|
if (OptionFlags.USE_COMPOUND || ltail == null) {
|
|
|
|
this.extremity2.drawU(ug.apply(new UTranslate(x + moveStartX, y + moveStartY)));
|
|
|
|
} else {
|
|
|
|
// System.err.println("Line::draw EXTREMITY2");
|
|
|
|
this.extremity2.drawU(ug.apply(new UTranslate(x, y)));
|
|
|
|
// this.extremity2.drawU(ug.apply(new UTranslate(dotPath.getStartPoint())));
|
|
|
|
|
|
|
|
}
|
2011-08-08 17:48:29 +00:00
|
|
|
}
|
2015-09-28 20:42:17 +00:00
|
|
|
if (this.labelText != null && this.labelXY != null) {
|
|
|
|
this.labelText.drawU(ug.apply(new UTranslate(x + this.labelXY.getPosition().getX(), y
|
|
|
|
+ this.labelXY.getPosition().getY())));
|
2011-08-08 17:48:29 +00:00
|
|
|
}
|
|
|
|
if (this.startTailText != null) {
|
2013-12-10 19:36:50 +00:00
|
|
|
this.startTailText.drawU(ug.apply(new UTranslate(x + this.startTailLabelXY.getPosition().getX(), y
|
|
|
|
+ this.startTailLabelXY.getPosition().getY())));
|
2011-08-08 17:48:29 +00:00
|
|
|
}
|
|
|
|
if (this.endHeadText != null) {
|
2013-12-10 19:36:50 +00:00
|
|
|
this.endHeadText.drawU(ug.apply(new UTranslate(x + this.endHeadLabelXY.getPosition().getX(), y
|
|
|
|
+ this.endHeadLabelXY.getPosition().getY())));
|
|
|
|
}
|
|
|
|
|
2015-04-07 18:18:37 +00:00
|
|
|
if (linkType.getMiddleDecor() != LinkMiddleDecor.NONE) {
|
2013-12-10 19:36:50 +00:00
|
|
|
final PointAndAngle middle = dotPath.getMiddle();
|
|
|
|
final double angleRad = middle.getAngle();
|
|
|
|
final double angleDeg = -angleRad * 180.0 / Math.PI;
|
2015-04-07 18:18:37 +00:00
|
|
|
final UDrawable mi = linkType.getMiddleDecor().getMiddleFactory().createUDrawable(angleDeg - 45);
|
2013-12-10 19:36:50 +00:00
|
|
|
mi.drawU(ug.apply(new UTranslate(x + middle.getX(), y + middle.getY())));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (url != null) {
|
|
|
|
ug.closeAction();
|
2011-08-08 17:48:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isInverted() {
|
|
|
|
return link.isInverted();
|
|
|
|
}
|
|
|
|
|
|
|
|
private double getDecorDzeta() {
|
2015-04-07 18:18:37 +00:00
|
|
|
final LinkType linkType = link.getType();
|
|
|
|
final int size1 = linkType.getDecor1().getMargin();
|
|
|
|
final int size2 = linkType.getDecor2().getMargin();
|
2011-08-08 17:48:29 +00:00
|
|
|
return size1 + size2;
|
|
|
|
}
|
|
|
|
|
|
|
|
public double getHorizontalDzeta(StringBounder stringBounder) {
|
|
|
|
if (startUid.equals(endUid)) {
|
|
|
|
return getDecorDzeta();
|
|
|
|
}
|
|
|
|
final ArithmeticStrategy strategy;
|
|
|
|
if (isHorizontal()) {
|
|
|
|
strategy = new ArithmeticStrategySum();
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
2015-09-28 20:42:17 +00:00
|
|
|
if (labelText != null) {
|
|
|
|
strategy.eat(labelText.calculateDimension(stringBounder).getWidth());
|
2011-08-08 17:48:29 +00:00
|
|
|
}
|
|
|
|
if (startTailText != null) {
|
|
|
|
strategy.eat(startTailText.calculateDimension(stringBounder).getWidth());
|
|
|
|
}
|
|
|
|
if (endHeadText != null) {
|
|
|
|
strategy.eat(endHeadText.calculateDimension(stringBounder).getWidth());
|
|
|
|
}
|
|
|
|
return strategy.getResult() + getDecorDzeta();
|
|
|
|
}
|
|
|
|
|
|
|
|
private boolean isHorizontal() {
|
|
|
|
return link.getLength() == 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
public double getVerticalDzeta(StringBounder stringBounder) {
|
|
|
|
if (startUid.equals(endUid)) {
|
|
|
|
return getDecorDzeta();
|
|
|
|
}
|
|
|
|
if (isHorizontal()) {
|
|
|
|
return 0;
|
|
|
|
}
|
2013-12-10 19:36:50 +00:00
|
|
|
final ArithmeticStrategy strategy = new ArithmeticStrategySum();
|
2015-09-28 20:42:17 +00:00
|
|
|
if (labelText != null) {
|
|
|
|
strategy.eat(labelText.calculateDimension(stringBounder).getHeight());
|
2011-08-08 17:48:29 +00:00
|
|
|
}
|
|
|
|
if (startTailText != null) {
|
|
|
|
strategy.eat(startTailText.calculateDimension(stringBounder).getHeight());
|
|
|
|
}
|
|
|
|
if (endHeadText != null) {
|
|
|
|
strategy.eat(endHeadText.calculateDimension(stringBounder).getHeight());
|
|
|
|
}
|
|
|
|
return strategy.getResult() + getDecorDzeta();
|
|
|
|
}
|
|
|
|
|
2013-12-10 19:36:50 +00:00
|
|
|
public void manageCollision(Collection<Shape> allShapes) {
|
2011-08-08 17:48:29 +00:00
|
|
|
|
2011-09-07 20:41:58 +00:00
|
|
|
for (Shape sh : allShapes) {
|
|
|
|
final Positionable cl = PositionableUtils.addMargin(sh, 8, 8);
|
2013-12-10 19:36:50 +00:00
|
|
|
if (startTailText != null && startTailLabelXY != null && PositionableUtils.intersect(cl, startTailLabelXY)) {
|
2011-09-07 20:41:58 +00:00
|
|
|
startTailLabelXY = PositionableUtils.moveAwayFrom(cl, startTailLabelXY);
|
2011-08-08 17:48:29 +00:00
|
|
|
}
|
2013-12-10 19:36:50 +00:00
|
|
|
if (endHeadText != null && endHeadLabelXY != null && PositionableUtils.intersect(cl, endHeadLabelXY)) {
|
2011-09-07 20:41:58 +00:00
|
|
|
endHeadLabelXY = PositionableUtils.moveAwayFrom(cl, endHeadLabelXY);
|
2011-08-08 17:48:29 +00:00
|
|
|
}
|
2011-09-07 20:41:58 +00:00
|
|
|
}
|
2011-08-08 17:48:29 +00:00
|
|
|
|
2011-09-07 20:41:58 +00:00
|
|
|
// final Positionable start = getStartTailPositionnable();
|
|
|
|
// if (start != null) {
|
|
|
|
// for (Shape sh : allShapes) {
|
|
|
|
// if (cut(start, sh)) {
|
|
|
|
// avoid(startTailLabelXY, start, sh);
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// final Positionable end = getEndHeadPositionnable();
|
|
|
|
// if (end != null) {
|
|
|
|
// for (Shape sh : allShapes) {
|
|
|
|
// if (cut(end, sh)) {
|
|
|
|
// avoid(endHeadLabelXY, end, sh);
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// }
|
2011-08-08 17:48:29 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
private void avoid(Point2D.Double move, Positionable pos, Shape sh) {
|
|
|
|
final Oscillator oscillator = new Oscillator();
|
|
|
|
final Point2D.Double orig = new Point2D.Double(move.x, move.y);
|
|
|
|
while (cut(pos, sh)) {
|
|
|
|
final Point2D.Double m = oscillator.nextPosition();
|
|
|
|
move.setLocation(orig.x + m.x, orig.y + m.y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private boolean cut(Positionable pos, Shape sh) {
|
|
|
|
return BezierUtils.intersect(pos, sh) || tooClose(pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
private boolean tooClose(Positionable pos) {
|
|
|
|
final double dist = dotPath.getMinDist(BezierUtils.getCenter(pos));
|
|
|
|
final Dimension2D dim = pos.getSize();
|
2013-12-10 19:36:50 +00:00
|
|
|
// Log.println("dist=" + dist);
|
2011-08-08 17:48:29 +00:00
|
|
|
return dist < (dim.getWidth() / 2 + 2) || dist < (dim.getHeight() / 2 + 2);
|
|
|
|
}
|
|
|
|
|
2011-09-08 10:42:27 +00:00
|
|
|
public void moveSvek(double deltaX, double deltaY) {
|
|
|
|
this.dx += deltaX;
|
|
|
|
this.dy += deltaY;
|
|
|
|
}
|
|
|
|
|
|
|
|
public final DotPath getDotPath() {
|
|
|
|
final DotPath result = new DotPath(dotPath);
|
|
|
|
result.moveSvek(dx, dy);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getLength() {
|
|
|
|
return link.getLength();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setOpale(boolean opale) {
|
|
|
|
this.link.setOpale(opale);
|
|
|
|
this.opale = opale;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isOpale() {
|
|
|
|
return opale;
|
|
|
|
}
|
|
|
|
|
2013-12-10 19:36:50 +00:00
|
|
|
public boolean isHorizontalSolitary() {
|
|
|
|
return link.isHorizontalSolitary();
|
|
|
|
}
|
|
|
|
|
2015-04-07 18:18:37 +00:00
|
|
|
public boolean isLinkFromOrTo(IEntity group) {
|
2013-12-10 19:36:50 +00:00
|
|
|
return link.getEntity1() == group || link.getEntity2() == group;
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean hasEntryPoint() {
|
|
|
|
return link.hasEntryPoint();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setProjectionCluster(Cluster cluster) {
|
|
|
|
this.projectionCluster = cluster;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isHidden() {
|
|
|
|
return link.isHidden();
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean sameConnections(Line other) {
|
|
|
|
return link.sameConnections(other.link);
|
|
|
|
}
|
|
|
|
|
|
|
|
private boolean isAutolink() {
|
|
|
|
return link.getEntity1() == link.getEntity2();
|
|
|
|
}
|
2011-09-08 10:42:27 +00:00
|
|
|
|
2015-04-07 18:18:37 +00:00
|
|
|
public Point2D getMyPoint(IEntity entity) {
|
|
|
|
if (link.getEntity1() == entity) {
|
|
|
|
return moveDelta(dotPath.getStartPoint());
|
|
|
|
}
|
|
|
|
if (link.getEntity2() == entity) {
|
|
|
|
return moveDelta(dotPath.getEndPoint());
|
|
|
|
}
|
|
|
|
throw new IllegalArgumentException();
|
|
|
|
}
|
|
|
|
|
|
|
|
private Point2D moveDelta(Point2D pt) {
|
|
|
|
return new Point2D.Double(pt.getX() + dx, pt.getY() + dy);
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isLink(Link link) {
|
|
|
|
return this.link == link;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Point2D getStartContactPoint() {
|
|
|
|
final Point2D start = dotPath.getStartPoint();
|
|
|
|
if (start == null) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
return new Point2D.Double(dx + start.getX(), dy + start.getY());
|
|
|
|
}
|
|
|
|
|
|
|
|
public Point2D getEndContactPoint() {
|
|
|
|
final Point2D end = dotPath.getEndPoint();
|
|
|
|
if (end == null) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
return new Point2D.Double(dx + end.getX(), dy + end.getY());
|
|
|
|
}
|
|
|
|
|
2015-05-31 18:56:03 +00:00
|
|
|
public IEntity getOther(IEntity entity) {
|
|
|
|
if (link.contains(entity)) {
|
|
|
|
return link.getOther(entity);
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2011-08-08 17:48:29 +00:00
|
|
|
}
|