1 /*******************************************************************************
2 * Copyright (c) 2011 Association for Decentralized Information Management in
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.diagram.connection.rendering;
14 import gnu.trove.set.hash.THashSet;
16 import java.awt.BasicStroke;
17 import java.awt.Color;
18 import java.awt.Graphics2D;
19 import java.awt.geom.Path2D;
20 import java.io.Serializable;
21 import java.util.List;
23 import org.simantics.diagram.connection.RouteGraph;
24 import org.simantics.diagram.connection.RouteLine;
25 import org.simantics.diagram.connection.RoutePoint;
26 import org.simantics.diagram.connection.RouteTerminal;
27 import org.simantics.diagram.connection.rendering.arrows.ILineEndStyle;
30 public class StyledRouteGraphRenderer implements IRouteGraphRenderer, Serializable {
32 private static final BasicStroke GUIDE_LINE_STROKE = new BasicStroke(0.1f);
33 private static final Color GUIDE_LINE_COLOR = new Color(255,255,255);
35 private static final long serialVersionUID = 1564960933064029020L;
37 protected final ConnectionStyle style;
39 private static class Cache {
40 Path2D path = new Path2D.Double();
41 THashSet<RoutePoint> branchPoints = new THashSet<>();
44 // Caches to avoid creating new objects all the time during rendering
45 protected static ThreadLocal<Cache> caches = ThreadLocal.withInitial(() -> new Cache());
47 public StyledRouteGraphRenderer(ConnectionStyle style) {
49 throw new NullPointerException("null style");
53 public ConnectionStyle getStyle() {
58 public void render(Graphics2D g, RouteGraph rg) {
59 Cache cache = caches.get();
60 Path2D path = cache.path;
61 THashSet<RoutePoint> branchPoints = cache.branchPoints;
65 PathModifier pm = (PathModifier) g.getRenderingHint(ConnectionRenderingHints.KEY_PATH_MODIFIER);
67 path = pm.modify(path);
69 style.drawPath(g, path, false);
72 for(RouteLine line : rg.getLines()) {
73 renderLine(g, line, false);
74 collectBranchPoints(line, branchPoints);
76 for(RouteLine line : rg.getTransientLines()) {
77 renderLine(g, line, true);
78 collectBranchPoints(line, branchPoints);
81 /*for(RouteTerminal terminal : rg.getTerminals())
83 for(RoutePoint point : branchPoints) {
84 style.drawBranchPoint(g, point.getX(), point.getY());
88 private static void collectBranchPoints(RouteLine line, THashSet<RoutePoint> branchPoints) {
89 List<RoutePoint> points = line.getPoints();
90 for(int i=1;i<points.size()-1;++i) {
91 RoutePoint point = points.get(i);
92 branchPoints.add(point);
96 private void renderLine(Graphics2D g, RouteLine line, boolean isTransient) {
97 if(line.getPoints().size() == 0) {
98 System.err.println("Route line does not contain any points (data = " + line.getData() + ").");
101 RoutePoint p1 = line.getBegin();
102 RoutePoint p2 = line.getEnd();
103 double x1 = p1.getX();
104 double y1 = p1.getY();
105 double x2 = p2.getX();
106 double y2 = p2.getY();
107 boolean isHorizontal = line.isHorizontal();
108 // double length = isHorizontal ? x2-x1 : y2-y1; // original length before removing the endpoints
110 if(p1 instanceof RouteTerminal) {
111 RouteTerminal terminal = (RouteTerminal)p1;
112 ILineEndStyle style = terminal.getRenderStyle();
113 style.render(g, x1, y1, 2);
114 x1 += style.getLineEndLength(0);
116 if(p2 instanceof RouteTerminal) {
117 RouteTerminal terminal = (RouteTerminal)p2;
118 ILineEndStyle style = terminal.getRenderStyle();
119 style.render(g, x2, y2, 0);
120 x2 -= style.getLineEndLength(2);
124 if(p1 instanceof RouteTerminal) {
125 RouteTerminal terminal = (RouteTerminal)p1;
126 ILineEndStyle style = terminal.getRenderStyle();
127 style.render(g, x1, y1, 3);
128 y1 += style.getLineEndLength(1);
130 if(p2 instanceof RouteTerminal) {
131 RouteTerminal terminal = (RouteTerminal)p2;
132 ILineEndStyle style = terminal.getRenderStyle();
133 style.render(g, x2, y2, 1);
134 y2 -= style.getLineEndLength(3);
137 // if(length <= style.getDegeneratedLineLength())
138 // style.drawDegeneratedLine(g, 0.5*(x1+x2), 0.5*(y1+y2), isHorizontal, isTransient);
140 // style.drawLine(g, x1, y1, x2, y2, isTransient);
144 public void renderGuides(Graphics2D g, RouteGraph rg) {
145 Path2D path = new Path2D.Double();
146 for(RouteLine line : rg.getLines()) {
147 RoutePoint p1 = line.getBegin();
148 RoutePoint p2 = line.getEnd();
149 double dx = p2.getX() - p1.getX();
150 double dy = p2.getY() - p1.getY();
151 double adx = Math.abs(dx);
152 double ady = Math.abs(dy);
155 dx = 0.5*dx - Math.signum(dx);
158 path.moveTo(p1.getX()+dx, p1.getY());
159 path.lineTo(p2.getX()-dx, p2.getY());
163 dy = 0.5*dy - Math.signum(dy);
166 path.moveTo(p1.getX(), p1.getY()+dy);
167 path.lineTo(p2.getX(), p2.getY()-dy);
170 g.setStroke(GUIDE_LINE_STROKE);
171 g.setColor(GUIDE_LINE_COLOR);
176 public int hashCode() {
177 return style.hashCode();
181 public boolean equals(Object obj) {
186 if (getClass() != obj.getClass())
188 StyledRouteGraphRenderer other = (StyledRouteGraphRenderer) obj;
189 return style.equals(other.style);