View Javadoc
1   /*
2    * Copyright (c) 2005, the JUNG Project and the Regents of the University of
3    * California All rights reserved.
4    *
5    * This software is open-source under the BSD license; see either "license.txt"
6    * or http://jung.sourceforge.net/license.txt for a description.
7    *
8    * Created on Aug 23, 2005
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          // don't draw edge if either incident vertex is not drawn
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 }