1
2
3
4
5
6
7
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.awt.geom.Rectangle2D;
23 import java.util.Set;
24
25 import javax.swing.BoundedRangeModel;
26 import javax.swing.JComponent;
27 import javax.swing.JPanel;
28 import javax.swing.JScrollBar;
29 import javax.swing.event.ChangeEvent;
30 import javax.swing.event.ChangeListener;
31
32 import edu.uci.ics.jung.visualization.transform.BidirectionalTransformer;
33 import edu.uci.ics.jung.visualization.transform.shape.Intersector;
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58 @SuppressWarnings("serial")
59 public class GraphZoomScrollPane extends JPanel {
60 protected VisualizationViewer<?, ?> vv;
61 protected JScrollBar horizontalScrollBar;
62 protected JScrollBar verticalScrollBar;
63 protected JComponent corner;
64 protected boolean scrollBarsMayControlAdjusting = true;
65 protected JPanel south;
66
67
68
69
70
71
72 public GraphZoomScrollPane(VisualizationViewer<?, ?> vv) {
73 super(new BorderLayout());
74 this.vv = vv;
75 addComponentListener(new ResizeListener());
76 Dimension d = vv.getGraphLayout().getSize();
77 verticalScrollBar = new JScrollBar(JScrollBar.VERTICAL, 0, d.height, 0, d.height);
78 horizontalScrollBar = new JScrollBar(JScrollBar.HORIZONTAL, 0, d.width, 0, d.width);
79 verticalScrollBar.addAdjustmentListener(new VerticalAdjustmentListenerImpl());
80 horizontalScrollBar.addAdjustmentListener(new HorizontalAdjustmentListenerImpl());
81 verticalScrollBar.setUnitIncrement(20);
82 horizontalScrollBar.setUnitIncrement(20);
83
84
85 vv.addChangeListener(
86 new ChangeListener(){
87 public void stateChanged(ChangeEvent evt) {
88 VisualizationViewer<?, ?> vv =
89 (VisualizationViewer<?, ?>)evt.getSource();
90 setScrollBars(vv);
91 }
92 });
93 add(vv);
94 add(verticalScrollBar, BorderLayout.EAST);
95 south = new JPanel(new BorderLayout());
96 south.add(horizontalScrollBar);
97 setCorner(new JPanel());
98 add(south, BorderLayout.SOUTH);
99 }
100
101
102
103
104
105 class HorizontalAdjustmentListenerImpl implements AdjustmentListener {
106 int previous = 0;
107 public void adjustmentValueChanged(AdjustmentEvent e) {
108 int hval = e.getValue();
109 float dh = previous - hval;
110 previous = hval;
111 if(dh != 0 && scrollBarsMayControlAdjusting) {
112
113 float layoutScale = (float) vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT).getScale();
114 dh *= layoutScale;
115 AffineTransform at = AffineTransform.getTranslateInstance(dh, 0);
116 vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT).preConcatenate(at);
117 }
118 }
119 }
120
121
122
123
124
125 class VerticalAdjustmentListenerImpl implements AdjustmentListener {
126 int previous = 0;
127 public void adjustmentValueChanged(AdjustmentEvent e) {
128 JScrollBar sb = (JScrollBar)e.getSource();
129 BoundedRangeModel m = sb.getModel();
130 int vval = m.getValue();
131 float dv = previous - vval;
132 previous = vval;
133 if(dv != 0 && scrollBarsMayControlAdjusting) {
134
135
136 float layoutScale = (float) vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT).getScale();
137 dv *= layoutScale;
138 AffineTransform at = AffineTransform.getTranslateInstance(0, dv);
139 vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT).preConcatenate(at);
140 }
141 }
142 }
143
144
145
146
147
148
149
150 private void setScrollBars(VisualizationViewer<?, ?> vv) {
151 Dimension d = vv.getGraphLayout().getSize();
152 Rectangle2D vvBounds = vv.getBounds();
153
154
155 Rectangle layoutRectangle =
156 new Rectangle(0,0,d.width,d.height);
157
158
159 BidirectionalTransformer viewTransformer = vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW);
160 BidirectionalTransformer layoutTransformer = vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT);
161
162 Point2D h0 = new Point2D.Double(vvBounds.getMinX(), vvBounds.getCenterY());
163 Point2D h1 = new Point2D.Double(vvBounds.getMaxX(), vvBounds.getCenterY());
164 Point2D v0 = new Point2D.Double(vvBounds.getCenterX(), vvBounds.getMinY());
165 Point2D v1 = new Point2D.Double(vvBounds.getCenterX(), vvBounds.getMaxY());
166
167 h0 = viewTransformer.inverseTransform(h0);
168 h0 = layoutTransformer.inverseTransform(h0);
169 h1 = viewTransformer.inverseTransform(h1);
170 h1 = layoutTransformer.inverseTransform(h1);
171 v0 = viewTransformer.inverseTransform(v0);
172 v0 = layoutTransformer.inverseTransform(v0);
173 v1 = viewTransformer.inverseTransform(v1);
174 v1 = layoutTransformer.inverseTransform(v1);
175
176 scrollBarsMayControlAdjusting = false;
177 setScrollBarValues(layoutRectangle, h0, h1, v0, v1);
178 scrollBarsMayControlAdjusting = true;
179 }
180
181 protected void setScrollBarValues(Rectangle rectangle,
182 Point2D h0, Point2D h1,
183 Point2D v0, Point2D v1) {
184 boolean containsH0 = rectangle.contains(h0);
185 boolean containsH1 = rectangle.contains(h1);
186 boolean containsV0 = rectangle.contains(v0);
187 boolean containsV1 = rectangle.contains(v1);
188
189
190
191 Intersector intersector = new Intersector(rectangle, new Line2D.Double(h0, h1));
192
193 int min = 0;
194 int ext;
195 int val = 0;
196 int max;
197
198 Set<Point2D> points = intersector.getPoints();
199 Point2D first = null;
200 Point2D second = null;
201
202 Point2D[] pointArray = (Point2D[])points.toArray(new Point2D[points.size()]);
203 if(pointArray.length > 1) {
204 first = pointArray[0];
205 second = pointArray[1];
206 } else if(pointArray.length > 0) {
207 first = second = pointArray[0];
208 }
209
210 if(first != null && second != null) {
211
212 if((h0.getX() - h1.getX()) * (first.getX() - second.getX()) < 0) {
213
214 Point2D temp = first;
215 first = second;
216 second = temp;
217 }
218
219 if(containsH0 && containsH1) {
220 max = (int)first.distance(second);
221 val = (int)first.distance(h0);
222 ext = (int)h0.distance(h1);
223
224 } else if(containsH0) {
225 max = (int)first.distance(second);
226 val = (int)first.distance(h0);
227 ext = (int)h0.distance(second);
228
229 } else if(containsH1) {
230 max = (int) first.distance(second);
231 val = 0;
232 ext = (int) first.distance(h1);
233
234 } else {
235 max = ext = rectangle.width;
236 val = min;
237 }
238 horizontalScrollBar.setValues(val, ext+1, min, max);
239 }
240
241
242 min = val = 0;
243
244 intersector.intersectLine(new Line2D.Double(v0, v1));
245 points = intersector.getPoints();
246
247 pointArray = (Point2D[])points.toArray(new Point2D[points.size()]);
248 if(pointArray.length > 1) {
249 first = pointArray[0];
250 second = pointArray[1];
251 } else if(pointArray.length > 0) {
252 first = second = pointArray[0];
253 }
254
255 if(first != null && second != null) {
256
257
258 if((v0.getY() - v1.getY()) * (first.getY() - second.getY()) < 0) {
259
260 Point2D temp = first;
261 first = second;
262 second = temp;
263 }
264
265 if(containsV0 && containsV1) {
266 max = (int)first.distance(second);
267 val = (int)first.distance(v0);
268 ext = (int)v0.distance(v1);
269
270 } else if(containsV0) {
271 max = (int)first.distance(second);
272 val = (int)first.distance(v0);
273 ext = (int)v0.distance(second);
274
275 } else if(containsV1) {
276 max = (int) first.distance(second);
277 val = 0;
278 ext = (int) first.distance(v1);
279
280 } else {
281 max = ext = rectangle.height;
282 val = min;
283 }
284 verticalScrollBar.setValues(val, ext+1, min, max);
285 }
286 }
287
288
289
290
291
292 protected class ResizeListener extends ComponentAdapter {
293
294 public void componentHidden(ComponentEvent e) {
295 }
296
297 public void componentResized(ComponentEvent e) {
298 setScrollBars(vv);
299 }
300 public void componentShown(ComponentEvent e) {
301 }
302 }
303
304
305
306
307 public JComponent getCorner() {
308 return corner;
309 }
310
311
312
313
314 public void setCorner(JComponent corner) {
315 this.corner = corner;
316 corner.setPreferredSize(new Dimension(verticalScrollBar.getPreferredSize().width,
317 horizontalScrollBar.getPreferredSize().height));
318 south.add(this.corner, BorderLayout.EAST);
319 }
320
321 public JScrollBar getHorizontalScrollBar() {
322 return horizontalScrollBar;
323 }
324
325 public JScrollBar getVerticalScrollBar() {
326 return verticalScrollBar;
327 }
328 }