package org.simantics.district.network.ui.nodes; import java.awt.Color; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.geom.AffineTransform; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import org.simantics.district.network.ui.styles.DistrictNetworkStaticInfoStyle; import org.simantics.scenegraph.ParentNode; import org.simantics.scenegraph.g2d.G2DNode; import org.simantics.scenegraph.g2d.nodes.spatial.RTreeNode; import org.simantics.scenegraph.utils.DPIUtil; import org.simantics.scenegraph.utils.NodeUtil; public class DistrictNetworkStaticInfoNode extends G2DNode implements DeferredNode { private static final long serialVersionUID = -1723122278582600873L; private static final Font FONT = new Font(Font.SANS_SERIF, Font.PLAIN, DPIUtil.upscale(10)); public static final String NODE_KEY = "DISTRICT_NETWORK_STATIC_INFO"; String info = null; Point2D origin = new Point2D.Double(); Point2D direction = new Point2D.Double(); private DistrictNetworkEdgeNode edgeNode = null; private int prevZoomLevel = -1; @Override public void render(Graphics2D g) { ParentNode root = (ParentNode) NodeUtil.getNearestParentOfType(this, RTreeNode.class); DeferredRenderingNode deferred = root != null ? (DeferredRenderingNode) root.getNode(DistrictNetworkStaticInfoStyle.STATIC_INFO_DEFERRED) : null; if (deferred != null) deferred.deferNode(g.getTransform(), this); else renderDeferred(g); } @Override public void renderDeferred(Graphics2D g) { if (info == null || "".equals(info)) return; int zoomLevel = (Integer) g.getRenderingHint(DistrictRenderingHints.KEY_VIEW_ZOOM_LEVEL); if (zoomLevel < 17) return; AffineTransform oldTransform = g.getTransform(); Font oldFont = g.getFont(); Color oldColor = g.getColor(); Object oldAA = g.getRenderingHint(RenderingHints.KEY_ANTIALIASING); g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); if (edgeNode != null && zoomLevel != prevZoomLevel) { origin.setLocation(edgeNode.getCenterPoint(zoomLevel)); Point2D dir = edgeNode.getDirection(zoomLevel); double s = dir.getX() >= 0.0 ? 1.0 : -1.0; direction.setLocation(s * dir.getX(), s * dir.getY()); } prevZoomLevel = zoomLevel; doRender(g); g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, oldAA); g.setTransform(oldTransform); g.setColor(oldColor); g.setFont(oldFont); } private void doRender(Graphics2D g) { g.translate(origin.getX(), origin.getY()); double scale = 1.0 / g.getTransform().getScaleX(); g.scale(scale, scale); g.setFont(FONT); FontMetrics fm = g.getFontMetrics(); int width = fm.stringWidth(info); int ascent = fm.getMaxAscent(); g.transform(AffineTransform.getRotateInstance(direction.getX(), direction.getY())); g.translate(0, ascent+2); // int height = fm.getHeight(); // g.setColor(Color.WHITE); // g.fillRect(-width/2 - 5, -ascent-1, width+10, height+2); g.setColor(Color.BLACK); // g.drawRect(-width/2 - 5, -ascent-1, width+10, height+2); g.drawString(info, -width/2, 0); } @Override public Rectangle2D getBoundsInLocal() { return null; } public void setLocation(Point2D origin, Point2D direction) { this.origin.setLocation(origin); this.direction.setLocation(direction); } public void setInfo(String info) { this.info = info; } public void setEdgeNode(DistrictNetworkEdgeNode n) { this.edgeNode = n; // Ensure that origin/location are recalculated prevZoomLevel = -1; } }