Line | Hits | Source |
---|---|---|
1 | /* | |
2 | * Copyright (c) 2003, the JUNG Project and the Regents of the University of | |
3 | * California All rights reserved. | |
4 | * | |
5 | * This software is open-source under the BSD license; see either "license.txt" | |
6 | * or http://jung.sourceforge.net/license.txt for a description. | |
7 | * Created on Feb 2, 2005 | |
8 | * | |
9 | */ | |
10 | package edu.uci.ics.jung.visualization; | |
11 | ||
12 | import java.awt.BorderLayout; | |
13 | import java.awt.Dimension; | |
14 | import java.awt.Rectangle; | |
15 | import java.awt.event.AdjustmentEvent; | |
16 | import java.awt.event.AdjustmentListener; | |
17 | import java.awt.event.ComponentAdapter; | |
18 | import java.awt.event.ComponentEvent; | |
19 | import java.awt.geom.AffineTransform; | |
20 | import java.awt.geom.Line2D; | |
21 | import java.awt.geom.Point2D; | |
22 | import java.util.Set; | |
23 | ||
24 | import javax.swing.BoundedRangeModel; | |
25 | import javax.swing.JComponent; | |
26 | import javax.swing.JPanel; | |
27 | import javax.swing.JScrollBar; | |
28 | import javax.swing.event.ChangeEvent; | |
29 | import javax.swing.event.ChangeListener; | |
30 | ||
31 | import edu.uci.ics.jung.visualization.transform.Transformer; | |
32 | import edu.uci.ics.jung.visualization.transform.shape.Intersector; | |
33 | ||
34 | ||
35 | ||
36 | /** | |
37 | * GraphZoomScrollPane is a Container for the Graph's VisualizationViewer | |
38 | * and includes custom horizontal and vertical scrollbars. | |
39 | * GraphZoomScrollPane listens for changes in the scale and | |
40 | * translation of the VisualizationViewer, and will update the | |
41 | * scrollbar positions and sizes accordingly. Changes in the | |
42 | * scrollbar positions will cause the corresponding change in | |
43 | * the translation component (offset) of the VisualizationViewer. | |
44 | * The scrollbars are modified so that they will allow panning | |
45 | * of the graph when the scale has been changed (e.g. zoomed-in | |
46 | * or zoomed-out). | |
47 | * | |
48 | * The lower-right corner of this component is available to | |
49 | * use as a small button or menu. | |
50 | * | |
51 | * samples.graph.GraphZoomScrollPaneDemo shows the use of this component. | |
52 | * | |
53 | * @author Tom Nelson - RABA Technologies | |
54 | * | |
55 | * | |
56 | */ | |
57 | 0 | public class GraphZoomScrollPane extends JPanel { |
58 | protected VisualizationViewer vv; | |
59 | protected JScrollBar horizontalScrollBar; | |
60 | protected JScrollBar verticalScrollBar; | |
61 | protected JComponent corner; | |
62 | 0 | protected boolean scrollBarsMayControlAdjusting = true; |
63 | protected JPanel south; | |
64 | ||
65 | /** | |
66 | * Create an instance of the GraphZoomScrollPane to contain the | |
67 | * VisualizationViewer | |
68 | * @param vv | |
69 | */ | |
70 | public GraphZoomScrollPane(VisualizationViewer vv) { | |
71 | 0 | super(new BorderLayout()); |
72 | 0 | this.vv = vv; |
73 | 0 | addComponentListener(new ResizeListener()); |
74 | 0 | Dimension d = vv.getGraphLayout().getCurrentSize(); |
75 | 0 | verticalScrollBar = new JScrollBar(JScrollBar.VERTICAL, 0, d.height, 0, d.height); |
76 | 0 | horizontalScrollBar = new JScrollBar(JScrollBar.HORIZONTAL, 0, d.width, 0, d.width); |
77 | 0 | verticalScrollBar.addAdjustmentListener(new VerticalAdjustmentListenerImpl()); |
78 | 0 | horizontalScrollBar.addAdjustmentListener(new HorizontalAdjustmentListenerImpl()); |
79 | 0 | verticalScrollBar.setUnitIncrement(20); |
80 | 0 | horizontalScrollBar.setUnitIncrement(20); |
81 | // respond to changes in the VisualizationViewer's transform | |
82 | // and set the scroll bar parameters appropriately | |
83 | 0 | vv.addChangeListener( |
84 | new ChangeListener(){ | |
85 | public void stateChanged(ChangeEvent evt) { | |
86 | VisualizationViewer vv = | |
87 | (VisualizationViewer)evt.getSource(); | |
88 | setScrollBars(vv); | |
89 | } | |
90 | }); | |
91 | 0 | add(vv); |
92 | 0 | add(verticalScrollBar, BorderLayout.EAST); |
93 | 0 | south = new JPanel(new BorderLayout()); |
94 | 0 | south.add(horizontalScrollBar); |
95 | 0 | setCorner(new JPanel()); |
96 | 0 | add(south, BorderLayout.SOUTH); |
97 | 0 | } |
98 | ||
99 | /** | |
100 | * listener for adjustment of the horizontal scroll bar. | |
101 | * Sets the translation of the VisualizationViewer | |
102 | */ | |
103 | class HorizontalAdjustmentListenerImpl implements AdjustmentListener { | |
104 | int previous = 0; | |
105 | public void adjustmentValueChanged(AdjustmentEvent e) { | |
106 | int hval = e.getValue(); | |
107 | float dh = previous - hval; | |
108 | previous = hval; | |
109 | if(dh != 0 && scrollBarsMayControlAdjusting) { | |
110 | // get the uniform scale of all transforms | |
111 | float layoutScale = (float) vv.getLayoutTransformer().getScale(); | |
112 | dh *= layoutScale; | |
113 | AffineTransform at = AffineTransform.getTranslateInstance(dh, 0); | |
114 | vv.getLayoutTransformer().preConcatenate(at); | |
115 | } | |
116 | } | |
117 | } | |
118 | ||
119 | /** | |
120 | * Listener for adjustment of the vertical scroll bar. | |
121 | * Sets the translation of the VisualizationViewer | |
122 | */ | |
123 | class VerticalAdjustmentListenerImpl implements AdjustmentListener { | |
124 | int previous = 0; | |
125 | public void adjustmentValueChanged(AdjustmentEvent e) { | |
126 | JScrollBar sb = (JScrollBar)e.getSource(); | |
127 | BoundedRangeModel m = sb.getModel(); | |
128 | int vval = m.getValue(); | |
129 | float dv = previous - vval; | |
130 | previous = vval; | |
131 | if(dv != 0 && scrollBarsMayControlAdjusting) { | |
132 | // get the uniform scale of all transforms | |
133 | float layoutScale = (float) vv.getLayoutTransformer().getScale(); | |
134 | dv *= layoutScale; | |
135 | AffineTransform at = AffineTransform.getTranslateInstance(0, dv); | |
136 | vv.getLayoutTransformer().preConcatenate(at); | |
137 | } | |
138 | } | |
139 | } | |
140 | ||
141 | /** | |
142 | * use the supplied vv characteristics to set the position and | |
143 | * dimensions of the scroll bars. Called in response to | |
144 | * a ChangeEvent from the VisualizationViewer | |
145 | * @param xform the transform of the VisualizationViewer | |
146 | */ | |
147 | private void setScrollBars(VisualizationViewer vv) { | |
148 | 0 | Dimension d = vv.getGraphLayout().getCurrentSize(); |
149 | 0 | Rectangle vvBounds = vv.getBounds(); |
150 | ||
151 | // a rectangle representing the layout | |
152 | 0 | Rectangle layoutRectangle = |
153 | new Rectangle(0,0,d.width,d.height); | |
154 | //-d.width/2, -d.height/2, 2*d.width, 2*d.height); | |
155 | ||
156 | 0 | Transformer viewTransformer = vv.getViewTransformer(); |
157 | 0 | Transformer layoutTransformer = vv.getLayoutTransformer(); |
158 | ||
159 | 0 | Point2D h0 = new Point2D.Double(vvBounds.getMinX(), vvBounds.getCenterY()); |
160 | 0 | Point2D h1 = new Point2D.Double(vvBounds.getMaxX(), vvBounds.getCenterY()); |
161 | 0 | Point2D v0 = new Point2D.Double(vvBounds.getCenterX(), vvBounds.getMinY()); |
162 | 0 | Point2D v1 = new Point2D.Double(vvBounds.getCenterX(), vvBounds.getMaxY()); |
163 | ||
164 | 0 | h0 = viewTransformer.inverseTransform(h0); |
165 | 0 | h0 = layoutTransformer.inverseTransform(h0); |
166 | 0 | h1 = viewTransformer.inverseTransform(h1); |
167 | 0 | h1 = layoutTransformer.inverseTransform(h1); |
168 | 0 | v0 = viewTransformer.inverseTransform(v0); |
169 | 0 | v0 = layoutTransformer.inverseTransform(v0); |
170 | 0 | v1 = viewTransformer.inverseTransform(v1); |
171 | 0 | v1 = layoutTransformer.inverseTransform(v1); |
172 | ||
173 | 0 | scrollBarsMayControlAdjusting = false; |
174 | 0 | setScrollBarValues(layoutRectangle, h0, h1, v0, v1); |
175 | 0 | scrollBarsMayControlAdjusting = true; |
176 | 0 | } |
177 | ||
178 | protected void setScrollBarValues(Rectangle rectangle, | |
179 | Point2D h0, Point2D h1, | |
180 | Point2D v0, Point2D v1) { | |
181 | 0 | boolean containsH0 = rectangle.contains(h0); |
182 | 0 | boolean containsH1 = rectangle.contains(h1); |
183 | 0 | boolean containsV0 = rectangle.contains(v0); |
184 | 0 | boolean containsV1 = rectangle.contains(v1); |
185 | ||
186 | // horizontal scrollbar: | |
187 | ||
188 | 0 | Intersector intersector = new Intersector(rectangle, new Line2D.Double(h0, h1)); |
189 | ||
190 | 0 | int min = 0; |
191 | int ext; | |
192 | 0 | int val = 0; |
193 | int max; | |
194 | ||
195 | 0 | Set points = intersector.getPoints(); |
196 | 0 | Point2D first = null; |
197 | 0 | Point2D second = null; |
198 | ||
199 | 0 | Point2D[] pointArray = (Point2D[])points.toArray(new Point2D[points.size()]); |
200 | 0 | if(pointArray.length > 1) { |
201 | 0 | first = pointArray[0]; |
202 | 0 | second = pointArray[1]; |
203 | 0 | } else if(pointArray.length > 0) { |
204 | 0 | first = second = pointArray[0]; |
205 | } | |
206 | ||
207 | 0 | if(first != null && second != null) { |
208 | // correct direction of intersect points | |
209 | 0 | if((h0.getX() - h1.getX()) * (first.getX() - second.getX()) < 0) { |
210 | // swap them | |
211 | 0 | Point2D temp = first; |
212 | 0 | first = second; |
213 | 0 | second = temp; |
214 | } | |
215 | ||
216 | 0 | if(containsH0 && containsH1) { |
217 | 0 | max = (int)first.distance(second); |
218 | 0 | val = (int)first.distance(h0); |
219 | 0 | ext = (int)h0.distance(h1); |
220 | ||
221 | 0 | } else if(containsH0) { |
222 | 0 | max = (int)first.distance(second); |
223 | 0 | val = (int)first.distance(h0); |
224 | 0 | ext = (int)h0.distance(second); |
225 | ||
226 | 0 | } else if(containsH1) { |
227 | 0 | max = (int) first.distance(second); |
228 | 0 | val = 0; |
229 | 0 | ext = (int) first.distance(h1); |
230 | ||
231 | } else { | |
232 | 0 | max = ext = rectangle.width; |
233 | 0 | val = min; |
234 | } | |
235 | 0 | horizontalScrollBar.setValues(val, ext+1, min, max); |
236 | } | |
237 | ||
238 | // vertical scroll bar | |
239 | 0 | min = val = 0; |
240 | ||
241 | 0 | intersector.intersectLine(new Line2D.Double(v0, v1)); |
242 | 0 | points = intersector.getPoints(); |
243 | ||
244 | 0 | pointArray = (Point2D[])points.toArray(new Point2D[points.size()]); |
245 | 0 | if(pointArray.length > 1) { |
246 | 0 | first = pointArray[0]; |
247 | 0 | second = pointArray[1]; |
248 | 0 | } else if(pointArray.length > 0) { |
249 | 0 | first = second = pointArray[0]; |
250 | } | |
251 | ||
252 | 0 | if(first != null && second != null) { |
253 | ||
254 | // arrange for direction | |
255 | 0 | if((v0.getY() - v1.getY()) * (first.getY() - second.getY()) < 0) { |
256 | // swap them | |
257 | 0 | Point2D temp = first; |
258 | 0 | first = second; |
259 | 0 | second = temp; |
260 | } | |
261 | ||
262 | 0 | if(containsV0 && containsV1) { |
263 | 0 | max = (int)first.distance(second); |
264 | 0 | val = (int)first.distance(v0); |
265 | 0 | ext = (int)v0.distance(v1); |
266 | ||
267 | 0 | } else if(containsV0) { |
268 | 0 | max = (int)first.distance(second); |
269 | 0 | val = (int)first.distance(v0); |
270 | 0 | ext = (int)v0.distance(second); |
271 | ||
272 | 0 | } else if(containsV1) { |
273 | 0 | max = (int) first.distance(second); |
274 | 0 | val = 0; |
275 | 0 | ext = (int) first.distance(v1); |
276 | ||
277 | } else { | |
278 | 0 | max = ext = rectangle.height; |
279 | 0 | val = min; |
280 | } | |
281 | 0 | verticalScrollBar.setValues(val, ext+1, min, max); |
282 | } | |
283 | 0 | } |
284 | ||
285 | /** | |
286 | * Listener to adjust the scroll bar parameters when the window | |
287 | * is resized | |
288 | */ | |
289 | protected class ResizeListener extends ComponentAdapter { | |
290 | ||
291 | public void componentHidden(ComponentEvent e) { | |
292 | } | |
293 | ||
294 | public void componentResized(ComponentEvent e) { | |
295 | setScrollBars(vv); | |
296 | } | |
297 | public void componentShown(ComponentEvent e) { | |
298 | } | |
299 | } | |
300 | ||
301 | /** | |
302 | * @return Returns the corner component. | |
303 | */ | |
304 | public JComponent getCorner() { | |
305 | 0 | return corner; |
306 | } | |
307 | ||
308 | /** | |
309 | * @param corner The cornerButton to set. | |
310 | */ | |
311 | public void setCorner(JComponent corner) { | |
312 | 0 | this.corner = corner; |
313 | 0 | corner.setPreferredSize(new Dimension(verticalScrollBar.getPreferredSize().width, |
314 | horizontalScrollBar.getPreferredSize().height)); | |
315 | 0 | south.add(this.corner, BorderLayout.EAST); |
316 | 0 | } |
317 | ||
318 | public JScrollBar getHorizontalScrollBar() { | |
319 | 0 | return horizontalScrollBar; |
320 | } | |
321 | ||
322 | public JScrollBar getVerticalScrollBar() { | |
323 | 0 | return verticalScrollBar; |
324 | } | |
325 | } |
this report was generated by version 1.0.5 of jcoverage. |
copyright © 2003, jcoverage ltd. all rights reserved. |