/******************************************************************************* * Copyright (c) 2011 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.diagram.connection.rendering; import gnu.trove.set.hash.THashSet; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Graphics2D; import java.awt.geom.Path2D; import java.io.Serializable; import java.util.List; import org.simantics.diagram.connection.RouteGraph; import org.simantics.diagram.connection.RouteLine; import org.simantics.diagram.connection.RoutePoint; import org.simantics.diagram.connection.RouteTerminal; import org.simantics.diagram.connection.rendering.arrows.ILineEndStyle; public class StyledRouteGraphRenderer implements IRouteGraphRenderer, Serializable { private static final BasicStroke GUIDE_LINE_STROKE = new BasicStroke(0.1f); private static final Color GUIDE_LINE_COLOR = new Color(255,255,255); private static final long serialVersionUID = 1564960933064029020L; protected final ConnectionStyle style; private static class Cache { Path2D path = new Path2D.Double(); THashSet branchPoints = new THashSet<>(); } // Caches to avoid creating new objects all the time during rendering protected static ThreadLocal caches = ThreadLocal.withInitial(() -> new Cache()); public StyledRouteGraphRenderer(ConnectionStyle style) { if (style == null) throw new NullPointerException("null style"); this.style = style; } public ConnectionStyle getStyle() { return style; } @Override public void render(Graphics2D g, RouteGraph rg) { Cache cache = caches.get(); Path2D path = cache.path; THashSet branchPoints = cache.branchPoints; path.reset(); rg.getPath2D(path); PathModifier pm = (PathModifier) g.getRenderingHint(ConnectionRenderingHints.KEY_PATH_MODIFIER); if (pm != null) { path = pm.modify(path); } style.drawPath(g, path, false); branchPoints.clear(); for(RouteLine line : rg.getLines()) { renderLine(g, line, false); collectBranchPoints(line, branchPoints); } for(RouteLine line : rg.getTransientLines()) { renderLine(g, line, true); collectBranchPoints(line, branchPoints); } /*for(RouteTerminal terminal : rg.getTerminals()) terminal.render(g);*/ for(RoutePoint point : branchPoints) { style.drawBranchPoint(g, point.getX(), point.getY()); } } private static void collectBranchPoints(RouteLine line, THashSet branchPoints) { List points = line.getPoints(); for(int i=1;i ady) { if(adx > 4) dx = 0.5*dx - Math.signum(dx); else dx *= 0.25; path.moveTo(p1.getX()+dx, p1.getY()); path.lineTo(p2.getX()-dx, p2.getY()); } else { if(ady > 4) dy = 0.5*dy - Math.signum(dy); else dy *= 0.25; path.moveTo(p1.getX(), p1.getY()+dy); path.lineTo(p2.getX(), p2.getY()-dy); } } g.setStroke(GUIDE_LINE_STROKE); g.setColor(GUIDE_LINE_COLOR); g.draw(path); } @Override public int hashCode() { return style.hashCode(); } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; StyledRouteGraphRenderer other = (StyledRouteGraphRenderer) obj; return style.equals(other.style); } }