View Javadoc

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  	// prepare
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  	// draw the line
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  	// draw the arrow
54  	g.setColor(getPointerColor(grp, e));
55  	ArrowTools.getArrowShape(_sp, _ep, _al, _aw, _arrow);
56  	g.fillPolygon(_arrow);
57  
58  	// draw the label
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  	// get line bounds
82  	super.getEdgeScreenBounds(grp, e, scr);
83  	
84  	// prepare
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  	// add arrow bounds
96  	ArrowTools.getArrowShape(_sp, _ep, _al, _aw, _arrow);
97  	scr.add(_arrow.getBounds());
98  
99  	// add label bounds
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 	// test the top bound
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 	// test the left bound
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 	// test the bottom bound
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 	// test the right bound
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 }