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