*******************************************************************************/\r
package org.simantics.sysdyn.ui.elements2.connections;\r
\r
-import java.awt.Shape;\r
import java.awt.geom.Arc2D;\r
import java.awt.geom.Path2D;\r
import java.awt.geom.Point2D;\r
// }\r
// \r
\r
- private static Shape createArrow(double x, double y, double dx, double dy) {\r
- Path2D path = new Path2D.Double();\r
- path.moveTo(x+ARROW_LENGTH1*dx, y+ARROW_LENGTH1*dy);\r
+ private static Path2D createArrow(Path2D shape, double x, double y, double dx, double dy) {\r
+ if(shape == null)\r
+ shape = new Path2D.Double();\r
+ else\r
+ shape.reset();\r
+ \r
+ shape.moveTo(x+ARROW_LENGTH1*dx, y+ARROW_LENGTH1*dy);\r
x -= ARROW_LENGTH2*dx;\r
y -= ARROW_LENGTH2*dy;\r
- path.lineTo(x-ARROW_WIDTH*dy, y+ARROW_WIDTH*dx);\r
- path.lineTo(x+ARROW_WIDTH*dy, y-ARROW_WIDTH*dx);\r
- path.closePath();\r
- return path;\r
+ shape.lineTo(x-ARROW_WIDTH*dy, y+ARROW_WIDTH*dx);\r
+ shape.lineTo(x+ARROW_WIDTH*dy, y-ARROW_WIDTH*dx);\r
+ shape.closePath();\r
+ return shape;\r
}\r
\r
- public static Point2D computeCenter(Rectangle2D tail, Rectangle2D head, double angle) {\r
-\r
- double x0 = tail.getCenterX();\r
- double y0 = tail.getCenterY();\r
- double x1 = head.getCenterX();\r
- double y1 = head.getCenterY();\r
- \r
-// System.out.println("createArrowShape " + x0 + " " + y0 + " " + x1 + " " + y1);\r
- \r
- double offset = \r
- Math.abs(angle) < 1.0e-6\r
- ? 1e3 * Math.signum(angle)\r
- : Math.tan(Math.PI*0.5-angle)*0.5;\r
- \r
- double cx = 0.5*(x0+x1) + offset * (y1-y0);\r
- double cy = 0.5*(y0+y1) + offset * (x0-x1);\r
- \r
- return new Point2D.Double(cx, cy);\r
- \r
- }\r
- \r
- public static Pair<Shape, Shape> createArrowShape(Rectangle2D tail, Rectangle2D head, double angle) {\r
-\r
+ public static Arc2D createArc(Arc2D arc, Rectangle2D tail, Rectangle2D head, double angle) {\r
double x0 = tail.getCenterX();\r
double y0 = tail.getCenterY();\r
double x1 = head.getCenterX();\r
extent += Math.PI*2.0;\r
else if(extent >= 360.0)\r
extent -= Math.PI*2.0;\r
- Shape shape1 = new Arc2D.Double(cx-r, cy-r, 2*r, 2*r, \r
+ if(arc == null)\r
+ arc = new Arc2D.Double();\r
+ arc.setArc(cx-r, cy-r, 2*r, 2*r, \r
Math.toDegrees(angle0), \r
Math.toDegrees(extent), \r
Arc2D.OPEN);\r
// \r
- double xx = Math.cos(angle > 0.0 ? angle1 : angle0);\r
- double yy = -Math.sin(angle > 0.0 ? angle1 : angle0);\r
+ return arc;\r
+ }\r
+ \r
+ public static Point2D computeCenter(Rectangle2D tail, Rectangle2D head, double angle) {\r
+\r
+ double x0 = tail.getCenterX();\r
+ double y0 = tail.getCenterY();\r
+ double x1 = head.getCenterX();\r
+ double y1 = head.getCenterY();\r
+ \r
+// System.out.println("createArrowShape " + x0 + " " + y0 + " " + x1 + " " + y1);\r
+ \r
+ double offset = \r
+ Math.abs(angle) < 1.0e-6\r
+ ? 1e3 * Math.signum(angle)\r
+ : Math.tan(Math.PI*0.5-angle)*0.5;\r
+ \r
+ double cx = 0.5*(x0+x1) + offset * (y1-y0);\r
+ double cy = 0.5*(y0+y1) + offset * (x0-x1);\r
+ \r
+ return new Point2D.Double(cx, cy);\r
+ \r
+ }\r
+ \r
+ public static Pair<Arc2D, Path2D> createArrowShape(Pair<Arc2D, Path2D> shapes, Rectangle2D tail, Rectangle2D head, double angle) {\r
+ if(shapes == null || shapes.first == null || shapes.second == null) {\r
+ shapes = new Pair<Arc2D, Path2D>(new Arc2D.Double(), new Path2D.Double());\r
+ }\r
\r
- Shape arrowShape = createArrow(cx + r*xx, cy + r*yy, \r
- angle < 0.0 ? -yy : yy, \r
- angle > 0.0 ? -xx : xx);\r
+ createArc(shapes.first, tail, head, angle);\r
+ \r
+ double angle0 = Math.toRadians(shapes.first.getAngleStart());\r
+ double angle1 = Math.toRadians(shapes.first.getAngleStart() + shapes.first.getAngleExtent());\r
+ double x = Math.cos(angle > 0.0 ? angle1 : angle0);\r
+ double y = -Math.sin(angle > 0.0 ? angle1 : angle0);\r
+ double r = shapes.first.getHeight() / 2;\r
+ \r
+ createArrow(shapes.second, shapes.first.getCenterX() + r*x, shapes.first.getCenterY() + r*y, \r
+ angle < 0.0 ? -y : y, \r
+ angle > 0.0 ? -x : x);\r
\r
- return Pair.make(shape1, arrowShape);\r
+ return shapes;\r
\r
}\r
// \r
import java.awt.Color;\r
import java.awt.Shape;\r
import java.awt.Stroke;\r
+import java.awt.geom.Arc2D;\r
import java.awt.geom.Path2D;\r
import java.awt.geom.Rectangle2D;\r
import java.beans.PropertyChangeEvent;\r
import org.simantics.g2d.diagram.DiagramMutator;\r
import org.simantics.g2d.diagram.DiagramUtils;\r
import org.simantics.g2d.diagram.IDiagram;\r
-import org.simantics.g2d.diagram.handler.Topology;\r
import org.simantics.g2d.diagram.handler.PickRequest.PickPolicy;\r
+import org.simantics.g2d.diagram.handler.Topology;\r
import org.simantics.g2d.diagram.handler.Topology.Connection;\r
import org.simantics.g2d.element.ElementClass;\r
import org.simantics.g2d.element.ElementUtils;\r
import org.simantics.g2d.element.IElement;\r
import org.simantics.g2d.element.SceneGraphNodeKey;\r
import org.simantics.g2d.element.handler.EdgeVisuals;\r
+import org.simantics.g2d.element.handler.EdgeVisuals.EdgeEnd;\r
import org.simantics.g2d.element.handler.Pick;\r
import org.simantics.g2d.element.handler.SceneGraph;\r
import org.simantics.g2d.element.handler.TerminalLayout;\r
import org.simantics.g2d.element.handler.Transform;\r
-import org.simantics.g2d.element.handler.EdgeVisuals.EdgeEnd;\r
import org.simantics.g2d.element.handler.impl.ConfigurableEdgeVisuals;\r
import org.simantics.g2d.element.handler.impl.ConnectionSelectionOutline;\r
import org.simantics.g2d.element.handler.impl.FillColorImpl;\r
\r
public static final Key KEY_SG_NODE = new SceneGraphNodeKey(DependencyNode.class, "EDGE_NODE");\r
\r
+ private transient Arc2D arc = new Arc2D.Double();\r
+ \r
@Override\r
public void init(IElement e, G2DParentNode parent) {\r
ElementUtils.getOrCreateNode(e, parent, KEY_SG_NODE, "edge_" + e.hashCode(), DependencyNode.class);\r
// System.out.println("setProperty " + entry.getKey() + " => " + entry.getValue().second);\r
}\r
}\r
- \r
- Pair<Shape, Shape> shapes = Dependencies.createArrowShape(beginTerminalShape.getBounds2D(), endTerminalShape.getBounds2D(), node.getAngle());\r
EdgeHandler eh = e.getElementClass().getAtMostOneItemOfClass(EdgeHandler.class);\r
- Path2D path = new Path2D.Double(shapes.first);\r
+ Path2D path = eh.getPath(e);\r
+ if(path == null)\r
+ path = new Path2D.Double();\r
+ else\r
+ path.reset();\r
+ Dependencies.createArc(arc, beginTerminalShape.getBounds2D(), endTerminalShape.getBounds2D(), node.getAngle());\r
+ path.append(arc, false);\r
eh.setPath(e, path);\r
\r
}\r
import java.awt.Color;\r
import java.awt.Graphics2D;\r
import java.awt.RenderingHints;\r
-import java.awt.Shape;\r
import java.awt.Stroke;\r
import java.awt.event.MouseEvent;\r
import java.awt.event.MouseListener;\r
import java.awt.event.MouseMotionListener;\r
-import java.awt.geom.Point2D;\r
+import java.awt.geom.Arc2D;\r
+import java.awt.geom.Path2D;\r
import java.awt.geom.Rectangle2D;\r
import java.beans.PropertyChangeEvent;\r
import java.beans.PropertyChangeListener;\r
private Rectangle2D beginBounds;\r
private Rectangle2D endBounds;\r
private double angle = 0.1;\r
+ private transient Pair<Arc2D, Path2D> shapes = new Pair<Arc2D, Path2D>(new Arc2D.Double(), new Path2D.Double());\r
\r
transient public boolean hover = false;\r
\r
\r
// NICENESS\r
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);\r
+ \r
+ Dependencies.createArrowShape(shapes, beginBounds, endBounds, angle);\r
\r
- // FIXME: optimize memory allocations\r
- Pair<Shape, Shape> shapes = Dependencies.createArrowShape(beginBounds, endBounds, angle);\r
-\r
boolean selected = NodeUtil.isSelected(this, 2);\r
if(selected) {\r
g.setColor(Color.PINK);\r