1
2
3
4
5
6
7
8
9
10 package com.github.davidmoten.xuml;
11
12 import java.awt.Color;
13 import java.awt.Component;
14 import java.awt.Dimension;
15 import java.awt.Shape;
16 import java.awt.geom.AffineTransform;
17 import java.awt.geom.Ellipse2D;
18 import java.awt.geom.Point2D;
19
20 import edu.uci.ics.jung.algorithms.layout.Layout;
21 import edu.uci.ics.jung.graph.Graph;
22 import edu.uci.ics.jung.graph.util.Context;
23 import edu.uci.ics.jung.graph.util.Pair;
24 import edu.uci.ics.jung.visualization.Layer;
25 import edu.uci.ics.jung.visualization.RenderContext;
26 import edu.uci.ics.jung.visualization.renderers.EdgeLabelRenderer;
27 import edu.uci.ics.jung.visualization.renderers.Renderer;
28 import edu.uci.ics.jung.visualization.transform.shape.GraphicsDecorator;
29
30 public class MyEdgeLabelRenderer<V, E> implements Renderer.EdgeLabel<V, E> {
31
32 private final double unaryEdgeDeltaY;
33 private final Color bgColor;
34
35 public MyEdgeLabelRenderer(double unaryEdgeDeltaY, Color bgColor) {
36 this.unaryEdgeDeltaY = unaryEdgeDeltaY;
37 this.bgColor = bgColor;
38 }
39
40 public Component prepareRenderer(RenderContext<V, E> rc, EdgeLabelRenderer graphLabelRenderer,
41 Object value, boolean isSelected, E edge) {
42 return rc.getEdgeLabelRenderer().<E> getEdgeLabelRendererComponent(rc.getScreenDevice(),
43 value, rc.getEdgeFontTransformer().apply(edge), isSelected, edge);
44 }
45
46 @Override
47 public void labelEdge(RenderContext<V, E> rc, Layout<V, E> layout, E e, String label) {
48 if (label == null || label.length() == 0)
49 return;
50
51 Graph<V, E> graph = layout.getGraph();
52
53 Pair<V> endpoints = graph.getEndpoints(e);
54 V v1 = endpoints.getFirst();
55 V v2 = endpoints.getSecond();
56 if (!rc.getEdgeIncludePredicate().apply(Context.<Graph<V, E>, E> getInstance(graph, e)))
57 return;
58
59 if (!rc.getVertexIncludePredicate()
60 .apply(Context.<Graph<V, E>, V> getInstance(graph, v1))
61 || !rc.getVertexIncludePredicate()
62 .apply(Context.<Graph<V, E>, V> getInstance(graph, v2)))
63 return;
64
65 Point2D p1 = layout.apply(v1);
66 Point2D p2 = layout.apply(v2);
67 p1 = rc.getMultiLayerTransformer().transform(Layer.LAYOUT, p1);
68 p2 = rc.getMultiLayerTransformer().transform(Layer.LAYOUT, p2);
69 float x1 = (float) p1.getX();
70 float y1 = (float) p1.getY();
71 float x2 = (float) p2.getX();
72 float y2 = (float) p2.getY();
73
74 GraphicsDecorator g = rc.getGraphicsContext();
75 float distX = x2 - x1;
76 float distY = y2 - y1;
77 double totalLength = Math.sqrt(distX * distX + distY * distY);
78
79 double closeness = rc.getEdgeLabelClosenessTransformer()
80 .apply(Context.<Graph<V, E>, E> getInstance(graph, e)).doubleValue();
81
82 int posX = (int) (x1 + (closeness) * distX);
83 int posY = (int) (y1 + (closeness) * distY);
84
85 int xDisplacement = (int) (rc.getLabelOffset() * (distY / totalLength));
86 int yDisplacement = (int) (rc.getLabelOffset() * (-distX / totalLength));
87
88 Component component = prepareRenderer(rc, rc.getEdgeLabelRenderer(), label,
89 rc.getPickedEdgeState().isPicked(e), e);
90
91 Dimension d = component.getPreferredSize();
92
93 Shape edgeShape = rc.getEdgeShapeTransformer()
94 .apply(Context.<Graph<V, E>, E> getInstance(graph, e).element);
95
96 double parallelOffset = 1;
97
98 parallelOffset += rc.getParallelEdgeIndexFunction().getIndex(graph, e);
99
100 parallelOffset *= d.height;
101 if (edgeShape instanceof Ellipse2D) {
102 parallelOffset += edgeShape.getBounds().getHeight();
103 parallelOffset = -parallelOffset;
104 yDisplacement += unaryEdgeDeltaY;
105 }
106
107 AffineTransform old = g.getTransform();
108 AffineTransform xform = new AffineTransform(old);
109 xform.translate(posX + xDisplacement, posY + yDisplacement);
110 double dx = x2 - x1;
111 double dy = y2 - y1;
112 if (rc.getEdgeLabelRenderer().isRotateEdgeLabels()) {
113 double theta = Math.atan2(dy, dx);
114 if (dx < 0) {
115 theta += Math.PI;
116 }
117 xform.rotate(theta);
118 }
119 if (dx < 0) {
120 parallelOffset = -parallelOffset;
121 }
122
123 xform.translate(-d.width / 2, -(d.height / 2 - parallelOffset));
124 g.setTransform(xform);
125 g.setBackground(bgColor);
126 g.clearRect(0, 0, d.width, d.height);
127 g.draw(component, rc.getRendererPane(), 0, 0, d.width, d.height, true);
128
129 g.setTransform(old);
130 }
131
132 }