1/***************************************************************************
2  Title:      GraphBrowser/GraphView.java
3  Author:     Stefan Berghofer, TU Muenchen
4  Options:    :tabSize=4:
5
6  This class defines the window in which the graph is displayed. It
7  contains methods for handling events such as collapsing / uncollapsing
8  nodes of the graph.
9***************************************************************************/
10
11package GraphBrowser;
12
13import java.awt.*;
14import java.awt.event.*;
15import java.io.*;
16import java.util.*;
17
18public class GraphView extends Canvas implements MouseListener, MouseMotionListener {
19	Graph gra, gra2;
20	GraphBrowser browser;
21	Vertex v = null;
22	Vector collapsed = new Vector(10,10);
23	Vector collapsedDirs = new Vector(10,10);
24	TreeBrowser tb;
25	long timestamp;
26	Vertex highlighted = null;
27	Dimension size;
28	boolean parent_needs_layout;
29	Font font;
30
31	public void setTreeBrowser(TreeBrowser br) {
32		tb=br;
33	}
34
35	public GraphBrowser getBrowser() { return browser; }
36
37	public Graph getGraph() { return gra; }
38
39	public Graph getOriginalGraph() { return gra2; }
40
41	public GraphView(Graph gr, GraphBrowser br, Font f) {
42		gra2=gr;
43		browser=br;
44		gra=(Graph)(gra2.clone());
45		parent_needs_layout = true;
46		size = new Dimension(0, 0);
47		font = f;
48		addMouseListener(this);
49		addMouseMotionListener(this);
50	}
51
52	public void PS(String fname,boolean printable) throws IOException {
53	    Graph gra3 = (Graph)gra.clone();
54	    gra3.layout(null);
55	    gra3.PS(fname,printable);
56	}
57
58	public void paint(Graphics g) {
59		g.setFont(font);
60		gra.draw(g);
61		if (highlighted!=null) highlighted.drawBox(g,Color.white);
62		size = new Dimension(gra.max_x-gra.min_x, gra.max_y-gra.min_y);
63		if (parent_needs_layout) {
64			parent_needs_layout = false;
65			getParent().doLayout();
66		}
67	}
68
69	public Dimension getPreferredSize() {
70		return size;
71	}
72
73	public void mouseMoved(MouseEvent evt) {
74		int x = evt.getX() + gra.min_x;
75		int y = evt.getY() + gra.min_y;
76
77		Vertex v2=gra.vertexAt(x,y);
78		Graphics g=getGraphics();
79		g.setFont(font);
80		g.translate(-gra.min_x,-gra.min_y);
81		if (highlighted!=null) {
82			highlighted.drawBox(g,Color.lightGray);
83			highlighted=null;
84		}
85		if (v2!=v) {
86			if (v!=null) v.removeButtons(g);
87			if (v2!=null) v2.drawButtons(g);
88			v=v2;
89		}
90	}
91
92	public void mouseDragged(MouseEvent evt) {}
93
94	/*****************************************************************/
95	/* This method is called if successor / predecessor nodes (whose */
96	/* numbers are stored in Vector c) of a certain node should be   */
97        /* displayed again                                               */
98	/*****************************************************************/
99
100	void uncollapse(Vector c) {
101		collapsed.removeElement(c);
102		collapseNodes();
103	}
104
105	/*****************************************************************/
106	/* This method is called by class TreeBrowser when directories   */
107	/* are collapsed / uncollapsed by the user                       */
108	/*****************************************************************/
109
110	public void collapseDir(Vector v) {
111		collapsedDirs=v;
112
113		collapseNodes();
114	}
115
116	/*****************************************************************/
117	/*                      Inflate node again                       */
118	/*****************************************************************/
119
120	public void inflateNode(Vector c) {
121		Enumeration e1;
122
123		e1=collapsedDirs.elements();
124		while (e1.hasMoreElements()) {
125			Directory d=(Directory)(e1.nextElement());
126			if (d.collapsed==c) {
127				tb.selectNode(d.getNode());
128				return;
129			}
130		}
131
132		collapsed.removeElement(c);
133		e1=gra2.getVertices();
134		while (e1.hasMoreElements()) {
135			Vertex vx=(Vertex)(e1.nextElement());
136			if (vx.getUp()==c) vx.setUp(null);
137			if (vx.getDown()==c) vx.setDown(null);
138		}
139
140		collapseNodes();
141		relayout();
142	}
143
144	public void relayout() {
145		Graphics g = getGraphics();
146		g.setFont(font);
147		browser.showWaitMessage();
148		highlighted=null;
149		gra.layout(g);
150		v=null;
151		parent_needs_layout = true;
152		update(g);
153		browser.showReadyMessage();
154	}
155
156	public void focusToVertex(int n) {
157		Vertex vx=gra.getVertexByNum(n);
158		if (vx!=null) {
159			ScrollPane scrollp = (ScrollPane)(getParent());
160			Dimension vpsize = scrollp.getViewportSize();
161
162                        int x = vx.getX()-gra.min_x;
163                        int y = vx.getY()-gra.min_y;
164			int offset_x = Math.min(scrollp.getHAdjustable().getMaximum(),
165				Math.max(0,x-vpsize.width/2));
166			int offset_y = Math.min(scrollp.getVAdjustable().getMaximum(),
167				Math.max(0,y-vpsize.height/2));
168
169			Graphics g=getGraphics();
170			g.setFont(font);
171			g.translate(-gra.min_x,-gra.min_y);
172			if (highlighted!=null) highlighted.drawBox(g,Color.lightGray);
173			vx.drawBox(g,Color.white);
174			highlighted=vx;
175			scrollp.setScrollPosition(offset_x, offset_y);
176		}
177	}
178
179	/*****************************************************************/
180	/*             Create new graph with collapsed nodes             */
181	/*****************************************************************/
182
183	public void collapseNodes() {
184		Enumeration e1=collapsed.elements();
185		gra=(Graph)(gra2.clone());
186
187		while (e1.hasMoreElements()) {
188			Vector v1=(Vector)(e1.nextElement());
189			Vector v2=gra.decode(v1);
190			if (!v2.isEmpty()) gra.collapse(v2,"[. . . .]",v1);
191		}
192
193		e1=collapsedDirs.elements();
194
195		while (e1.hasMoreElements()) {
196			Directory d=(Directory)(e1.nextElement());
197			Vector v=gra.decode(d.getCollapsed());
198			if (!v.isEmpty())
199				gra.collapse(v,"["+d.getName()+"]",d.getCollapsed());
200		}
201	}
202
203	public void mouseClicked(MouseEvent evt) {
204		Vector code = null;
205		Vertex v2;
206		int x = evt.getX() + gra.min_x;
207		int y = evt.getY() + gra.min_y;
208
209		if (v!=null) {
210			int num=v.getNumber();
211			v2=gra2.getVertexByNum(num);
212			if (v.leftButton(x,y)) {
213				if (v.getUp()!=null) {
214					code=v.getUp();
215					v2.setUp(null);
216					v=null;
217					uncollapse(code);
218					relayout();
219					focusToVertex(num);
220				} else {
221					Vector vs=v2.getPreds();
222					code=gra2.encode(vs);
223					v.setUp(code);v2.setUp(code);
224					v=null;
225					collapsed.insertElementAt(code,0);
226					collapseNodes();
227					relayout();
228					focusToVertex(num);
229				}
230			} else if (v.rightButton(x,y)) {
231				if (v.getDown()!=null) {
232					code=v.getDown();
233					v2.setDown(null);
234					v=null;
235					uncollapse(code);
236					relayout();
237					focusToVertex(num);
238				} else {
239					Vector vs=v2.getSuccs();
240					code=gra2.encode(vs);
241					v.setDown(code);v2.setDown(code);
242					v=null;
243					collapsed.insertElementAt(code,0);
244					collapseNodes();
245					relayout();
246					focusToVertex(num);
247				}
248			} else if (v.getInflate()!=null) {
249				inflateNode(v.getInflate());
250				v=null;
251			} else {
252				if (evt.getWhen()-timestamp < 400 && !(v.getPath().equals("")))
253					browser.viewFile(v.getPath());
254				timestamp=evt.getWhen();
255			}
256		}
257	}
258
259	public void mouseExited(MouseEvent evt) {
260		Graphics g=getGraphics();
261		g.setFont(font);
262		g.translate(-gra.min_x,-gra.min_y);
263		if (highlighted!=null) {
264			highlighted.drawBox(g,Color.lightGray);
265			highlighted=null;
266		}
267		if (v!=null) v.removeButtons(g);
268		v=null;
269	}
270
271	public void mouseEntered(MouseEvent evt) {}
272
273	public void mousePressed(MouseEvent evt) {}
274
275	public void mouseReleased(MouseEvent evt) {}
276}
277