1 /*******************************************************************************
\r
2 * Copyright (c) 2011 Association for Decentralized Information Management in
\r
4 * All rights reserved. This program and the accompanying materials
\r
5 * are made available under the terms of the Eclipse Public License v1.0
\r
6 * which accompanies this distribution, and is available at
\r
7 * http://www.eclipse.org/legal/epl-v10.html
\r
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.diagram.connection.rendering;
\r
14 import gnu.trove.set.hash.THashSet;
\r
16 import java.awt.BasicStroke;
\r
17 import java.awt.Color;
\r
18 import java.awt.Graphics2D;
\r
19 import java.awt.geom.Path2D;
\r
20 import java.io.Serializable;
\r
21 import java.util.List;
\r
23 import org.simantics.diagram.connection.RouteGraph;
\r
24 import org.simantics.diagram.connection.RouteLine;
\r
25 import org.simantics.diagram.connection.RoutePoint;
\r
26 import org.simantics.diagram.connection.RouteTerminal;
\r
27 import org.simantics.diagram.connection.rendering.arrows.ILineEndStyle;
\r
30 public class StyledRouteGraphRenderer implements IRouteGraphRenderer, Serializable {
\r
32 private static final BasicStroke GUIDE_LINE_STROKE = new BasicStroke(0.1f);
\r
33 private static final Color GUIDE_LINE_COLOR = new Color(255,255,255);
\r
35 private static final long serialVersionUID = 1564960933064029020L;
\r
37 protected final ConnectionStyle style;
\r
39 // Caches to avoid creating new objects all the time during rendering
\r
40 protected transient Path2D path;
\r
41 protected transient THashSet<RoutePoint> branchPoints;
\r
43 public StyledRouteGraphRenderer(ConnectionStyle style) {
\r
45 throw new NullPointerException("null style");
\r
49 public ConnectionStyle getStyle() {
\r
54 public void render(Graphics2D g, RouteGraph rg) {
\r
56 path = new Path2D.Double();
\r
59 style.drawPath(g, path, false);
\r
61 if (branchPoints == null)
\r
62 branchPoints = new THashSet<RoutePoint>();
\r
63 branchPoints.clear();
\r
64 for(RouteLine line : rg.getLines()) {
\r
65 renderLine(g, line, false);
\r
66 collectBranchPoints(line, branchPoints);
\r
68 for(RouteLine line : rg.getTransientLines()) {
\r
69 renderLine(g, line, true);
\r
70 collectBranchPoints(line, branchPoints);
\r
73 /*for(RouteTerminal terminal : rg.getTerminals())
\r
74 terminal.render(g);*/
\r
75 for(RoutePoint point : branchPoints) {
\r
76 style.drawBranchPoint(g, point.getX(), point.getY());
\r
80 private static void collectBranchPoints(RouteLine line, THashSet<RoutePoint> branchPoints) {
\r
81 List<RoutePoint> points = line.getPoints();
\r
82 for(int i=1;i<points.size()-1;++i) {
\r
83 RoutePoint point = points.get(i);
\r
84 branchPoints.add(point);
\r
88 private void renderLine(Graphics2D g, RouteLine line, boolean isTransient) {
\r
89 if(line.getPoints().size() == 0) {
\r
90 System.err.println("Route line does not contain any points (data = " + line.getData() + ").");
\r
93 RoutePoint p1 = line.getBegin();
\r
94 RoutePoint p2 = line.getEnd();
\r
95 double x1 = p1.getX();
\r
96 double y1 = p1.getY();
\r
97 double x2 = p2.getX();
\r
98 double y2 = p2.getY();
\r
99 boolean isHorizontal = line.isHorizontal();
\r
100 // double length = isHorizontal ? x2-x1 : y2-y1; // original length before removing the endpoints
\r
102 if(p1 instanceof RouteTerminal) {
\r
103 RouteTerminal terminal = (RouteTerminal)p1;
\r
104 ILineEndStyle style = terminal.getRenderStyle();
\r
105 style.render(g, x1, y1, 2);
\r
106 x1 += style.getLineEndLength(0);
\r
108 if(p2 instanceof RouteTerminal) {
\r
109 RouteTerminal terminal = (RouteTerminal)p2;
\r
110 ILineEndStyle style = terminal.getRenderStyle();
\r
111 style.render(g, x2, y2, 0);
\r
112 x2 -= style.getLineEndLength(2);
\r
116 if(p1 instanceof RouteTerminal) {
\r
117 RouteTerminal terminal = (RouteTerminal)p1;
\r
118 ILineEndStyle style = terminal.getRenderStyle();
\r
119 style.render(g, x1, y1, 3);
\r
120 y1 += style.getLineEndLength(1);
\r
122 if(p2 instanceof RouteTerminal) {
\r
123 RouteTerminal terminal = (RouteTerminal)p2;
\r
124 ILineEndStyle style = terminal.getRenderStyle();
\r
125 style.render(g, x2, y2, 1);
\r
126 y2 -= style.getLineEndLength(3);
\r
129 // if(length <= style.getDegeneratedLineLength())
\r
130 // style.drawDegeneratedLine(g, 0.5*(x1+x2), 0.5*(y1+y2), isHorizontal, isTransient);
\r
132 // style.drawLine(g, x1, y1, x2, y2, isTransient);
\r
136 public void renderGuides(Graphics2D g, RouteGraph rg) {
\r
137 Path2D path = new Path2D.Double();
\r
138 for(RouteLine line : rg.getLines()) {
\r
139 RoutePoint p1 = line.getBegin();
\r
140 RoutePoint p2 = line.getEnd();
\r
141 double dx = p2.getX() - p1.getX();
\r
142 double dy = p2.getY() - p1.getY();
\r
143 double adx = Math.abs(dx);
\r
144 double ady = Math.abs(dy);
\r
147 dx = 0.5*dx - Math.signum(dx);
\r
150 path.moveTo(p1.getX()+dx, p1.getY());
\r
151 path.lineTo(p2.getX()-dx, p2.getY());
\r
155 dy = 0.5*dy - Math.signum(dy);
\r
158 path.moveTo(p1.getX(), p1.getY()+dy);
\r
159 path.lineTo(p2.getX(), p2.getY()-dy);
\r
162 g.setStroke(GUIDE_LINE_STROKE);
\r
163 g.setColor(GUIDE_LINE_COLOR);
\r
168 public int hashCode() {
\r
169 return style.hashCode();
\r
173 public boolean equals(Object obj) {
\r
178 if (getClass() != obj.getClass())
\r
180 StyledRouteGraphRenderer other = (StyledRouteGraphRenderer) obj;
\r
181 return style.equals(other.style);
\r