1
2
3
4
5
6
7
8 package org.glassbox.graphview;
9
10 import de.fzi.wim.guibase.graphview.view.AbstractEdgePainter;
11 import de.fzi.wim.guibase.graphview.view.JGraphPane;
12 import de.fzi.wim.guibase.graphview.graph.Edge;
13 import de.fzi.wim.guibase.graphview.graph.Node;
14
15 import java.awt.*;
16
17 /***
18 An abstract painter for edges with a pointer.
19 This painter draws a little arrow at the intersection of edge and the bounds rectangle of the
20 node the edge is pointing to.
21 */
22 public abstract class AbstractArrowReadEdgePainter extends AbstractEdgePainter implements ZoomableEdgePainter {
23 private Rectangle _bnde;
24 private Point _p1, _p2;
25 private Polygon _arrow;
26 private int _arrowwidth, _arrowlength;
27 private int _aw, _al;
28
29 protected AbstractArrowReadEdgePainter(int arrowlength, int arrowwidth) {
30 _bnde = new Rectangle();
31 _p1 = new Point();
32 _p2 = new Point();
33 _arrow = new Polygon();
34 _arrowwidth = arrowwidth;
35 _arrowlength = arrowlength;
36 setZoomFactor(1d);
37 }
38
39 public void setZoomFactor(double zf) {
40 _al = (int)((double)_arrowlength * zf);
41 _aw = (int)((double)_arrowwidth * zf);
42 }
43
44 private static double calc(double c, double m) {
45 return Math.sqrt(c*c/(1+m*m));
46 }
47
48 public void paintEdge(JGraphPane grp,Graphics2D g, Edge e) {
49
50 Point sp = grp.getScreenPointForNode(e.getFrom());
51 Point ep = grp.getScreenPointForNode(e.getTo());
52
53 getNodeScreenBounds(grp, e.getTo(), _bnde);
54
55 Point _sp = sp;
56 Point _ep = getIntersection(_bnde, sp, ep);
57
58 if (_sp == null || _ep == null || (_sp.x == _ep.x && _sp.y == _ep.y)) return;
59
60
61 g.setColor(getEdgeColor(grp, e));
62 g.setStroke(getEdgeStroke(grp, e));
63 g.drawLine(_sp.x, _sp.y, _ep.x, _ep.y);
64
65
66 ArrowTools.getReadBar(_sp, _ep, _aw, _arrow);
67 g.fillPolygon(_arrow);
68
69
70 g.setColor(getPointerColor(grp, e));
71 ArrowTools.getArrowShape(_sp, _ep, _al, _aw, _arrow);
72 g.fillPolygon(_arrow);
73
74
75 String en = getEdgeLabel(grp, e);
76 if (en != null) {
77 g.setColor(getTextColor(grp, e));
78 g.setFont(getFont(grp, e));
79 int lw = grp.getFontMetrics(g.getFont()).stringWidth(en);
80 if (_sp.x == _ep.x) {
81 g.drawString(en, _sp.x-lw/2, _sp.y+(_ep.y-_sp.y)/2);
82 } else if (Math.abs(_ep.x-_sp.x)>Math.abs(_ep.y-_sp.y)) {
83 double m = (double)(_ep.y-sp.y)/(double)(_ep.x-sp.x);
84 int x = _sp.x+(int)((double)(_ep.x-_sp.x)/2d);
85 int y = _sp.y+(int)(m*(double)(_ep.x-_sp.x)/2d);
86 g.drawString(en, x-lw/2, y);
87 } else {
88 double m = (double)(_ep.x-_sp.x)/(double)(_ep.y-_sp.y);
89 int x = _sp.x+(int)(m*(double)(_ep.y-_sp.y)/2d);
90 int y = _sp.y+(int)((double)(_ep.y-_sp.y)/2d);
91 g.drawString(en, x-lw/2, y);
92 }
93 }
94 }
95
96 public void getEdgeScreenBounds(JGraphPane grp,Edge e,Rectangle scr) {
97
98 super.getEdgeScreenBounds(grp, e, scr);
99
100
101 Point sp = grp.getScreenPointForNode(e.getFrom());
102 Point ep = grp.getScreenPointForNode(e.getTo());
103
104 getNodeScreenBounds(grp, e.getTo(), _bnde);
105
106 Point _sp = sp;
107 Point _ep = getIntersection(_bnde, sp, ep);
108
109 if (_sp == null || _ep == null || (_sp.x == _ep.x && _sp.y == _ep.y)) return;
110
111
112 ArrowTools.getArrowShape(_sp, _ep, _al, _aw, _arrow);
113 scr.add(_arrow.getBounds());
114
115
116 String en = getEdgeLabel(grp, e);
117 if (en!=null && !en.equals("")) {
118 int lw = grp.getFontMetrics(getFont(grp, e)).stringWidth(en);
119 int lh = grp.getFontMetrics(getFont(grp, e)).getHeight();
120 if (lw>scr.width) {
121 scr.x -= (lw-scr.width)/2;
122 scr.width = lw;
123 }
124 if (lh>scr.height) {
125 scr.y -= (lh-scr.height)/2;
126 scr.height = lh;
127 }
128 }
129 }
130
131 protected void getNodeScreenBounds(JGraphPane grp, Node n, Rectangle r) {
132 grp.getPainterForNode(n).getNodeScreenBounds(grp, n, r);
133 }
134
135 /*** Get the Point of Intersection for a Rectangle and a Line. */
136 private Point getIntersection(Rectangle r, Point p1, Point p2) {
137 Point _ = null;
138
139 _p1.setLocation(r.getX(), r.getY());
140 _p2.setLocation(r.getX()+r.getWidth(), r.getY());
141 _ = getLineIntersection(p1, p2, _p1, _p2);
142 if (_!=null && !(_.x>r.getX()+r.getWidth() || _.x<r.getX())) return _;
143
144 _p2.setLocation(r.getX(), r.getY()+r.getHeight());
145 _ = getLineIntersection(p1, p2, _p1, _p2);
146 if (_!=null && !(_.y>r.getY()+r.getHeight() || _.y<r.getY())) return _;
147
148 _p1.setLocation(r.getX()+r.getWidth(), r.getY()+r.getHeight());
149 _ = getLineIntersection(p1, p2, _p1, _p2);
150 if (_!=null && !(_.x>r.getX()+r.getWidth() || _.x<r.getX())) return _;
151
152 _p2.setLocation(r.getX()+r.getWidth(), r.getY());
153 _ = getLineIntersection(p1, p2, _p1, _p2);
154 return _;
155 }
156
157 private Point getLineIntersection(Point p1, Point p2, Point r1, Point r2) {
158 Point p = null;
159 double t =
160 (r1.getX()*(r1.getY()-r2.getY()) + r1.getY()*(r2.getX()-r1.getX()) - p1.getX()*(r1.getY()-r2.getY()) - p1.getY()*(r2.getX()-r1.getX())) /
161 ((p2.getX()-p1.getX())*(r1.getY()-r2.getY()) + (p2.getY()-p1.getY())*(r2.getX()-r1.getX()));
162 if ((0<=t) && (t<=1)) {
163 p = new Point((int)(p1.getX() + t*(p2.getX()-p1.getX())), (int)(p1.getY() + t*(p2.getY()-p1.getY())));
164 }
165 return p;
166 }
167
168 protected abstract Color getEdgeColor(JGraphPane grp, Edge e);
169
170 protected abstract Color getPointerColor(JGraphPane grp, Edge e);
171
172 protected abstract Color getTextColor(JGraphPane grp, Edge e);
173
174 protected abstract Font getFont(JGraphPane grp, Edge e);
175
176 protected abstract Stroke getEdgeStroke(JGraphPane grp, Edge e);
177
178 protected abstract String getEdgeLabel(JGraphPane grp, Edge e);
179 }