View Javadoc

1   /*
2    * $Id: AbstractArrowReadEdgePainter.java 1153 2008-07-03 09:47:47Z kwfgrid.bassheide $
3    *
4    * Copyright (c) 2008, Fraunhofer FIRST
5    * Fraunhofer Institute for Computer Architecture and Software Technology
6    * See http://www.first.fraunhofer.de and http://www.gridworkflow.org/gwes for more details.
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  	// prepare
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  	// draw the line
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      // draw vertical bar that indicates read edge
66      ArrowTools.getReadBar(_sp, _ep, _aw, _arrow);
67      g.fillPolygon(_arrow);
68  
69      // draw the arrow
70  	g.setColor(getPointerColor(grp, e));
71  	ArrowTools.getArrowShape(_sp, _ep, _al, _aw, _arrow);
72  	g.fillPolygon(_arrow);
73  
74  	// draw the label
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  	// get line bounds
98  	super.getEdgeScreenBounds(grp, e, scr);
99  
100 	// prepare
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 	// add arrow bounds
112 	ArrowTools.getArrowShape(_sp, _ep, _al, _aw, _arrow);
113 	scr.add(_arrow.getBounds());
114 
115 	// add label bounds
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 	// test the top bound
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 	// test the left bound
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 	// test the bottom bound
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 	// test the right bound
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 }