1 package org.simantics.district.network.ui.nodes;
5 import java.awt.Graphics2D;
6 import java.awt.geom.AffineTransform;
7 import java.awt.geom.Point2D;
8 import java.awt.geom.Rectangle2D;
9 import java.util.Comparator;
10 import java.util.List;
11 import java.util.Optional;
12 import java.util.concurrent.atomic.AtomicReference;
14 import org.simantics.maps.MapScalingTransform;
15 import org.simantics.scenegraph.g2d.G2DNode;
16 import org.simantics.scenegraph.utils.DPIUtil;
17 import org.simantics.scl.runtime.Lists;
18 import org.simantics.scl.runtime.tuple.Tuple3;
20 public class DistrictNetworkHoverInfoNode extends G2DNode implements HoverSensitiveNode {
22 private static final Font FONT = new Font("Tahoma", Font.PLAIN, (int)(DPIUtil.upscale(9) * MapScalingTransform.getScaleY() + 0.5));
24 private static final long serialVersionUID = 1L;
26 public static final String NODE_KEY = "DISTRICT_NETWORK_HOVER_INFO";
28 private static final int W1 = 50;
29 private static final int W2 = 30;
30 private static final int PAD = 5;
32 private List<Tuple3> labels;
34 private Point2D origin;
36 private boolean hover = false;
38 private static AtomicReference<DistrictNetworkHoverInfoNode> activeNode = new AtomicReference<>();
41 public void render(Graphics2D g) {
42 if (!hover || activeNode.get() != this)
45 AffineTransform ot = g.getTransform();
46 Font of = g.getFont();
52 private void doRender(Graphics2D g) {
53 g.translate(origin.getX(), origin.getY());
54 double scale = 1.5 / g.getTransform().getScaleX();
55 g.scale(scale, scale);
58 double rowHeight = g.getFontMetrics().getHeight() * 1.1;
60 // let's calculate the max width
61 Optional<Integer> max = labels.stream().map(t -> g.getFontMetrics().stringWidth((String) t.c2)).max(Comparator.naturalOrder());
62 int width = max.orElse(10);
63 g.setColor(Color.WHITE);
64 int totalHeight = (int)Math.round(rowHeight * labels.size());
65 g.fillRect(-(W1 + PAD + W2 + 5), -(totalHeight + (int)Math.round(rowHeight)), (W1 + PAD + W2 + width + 10), totalHeight + 5);
67 g.setColor(Color.BLACK);
69 for (Tuple3 t : labels) {
70 g.translate(0.f, -rowHeight);
73 g.drawString((String) t.c0, -(W1 + PAD + W2), 0.f);
77 int width1 = g.getFontMetrics().stringWidth((String) t.c1);
78 g.drawString((String) t.c1, - width1, 0.f);
82 g.drawString((String) t.c2, PAD, 0.f);
88 public Rectangle2D getBoundsInLocal() {
92 @SuppressWarnings("unchecked")
93 public void setLabels(List<Tuple3> list) {
94 this.labels = Lists.reverse(list);
97 public void setOrigin(Point2D origin) {
102 public boolean hover(boolean hover, boolean isConnectionTool) {
103 hover = hover && activeNode.updateAndGet(current -> current == null ? this : current) == this;
104 boolean changed = hover != this.hover;
108 if (!hover) activeNode.updateAndGet(current -> current == this ? null : current);
116 public void delete() {
118 activeNode.getAndUpdate(current -> current == this ? null : current);