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