KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > wings > SScrollPane


1 /*
2  * $Id: SScrollPane.java,v 1.5 2005/01/11 12:23:35 hengels Exp $
3  * Copyright 2000,2005 wingS development team.
4  *
5  * This file is part of wingS (http://www.j-wings.org).
6  *
7  * wingS is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU Lesser General Public License
9  * as published by the Free Software Foundation; either version 2.1
10  * of the License, or (at your option) any later version.
11  *
12  * Please see COPYING for the complete licence.
13  */

14 package org.wings;
15
16 import org.wings.plaf.ScrollPaneCG;
17
18 import java.awt.*;
19 import java.awt.event.AdjustmentEvent JavaDoc;
20 import java.awt.event.AdjustmentListener JavaDoc;
21
22 /**
23  * @author <a HREF="mailto:haaf@mercatis.de">Armin Haaf</a>
24  * @version $Revision: 1.5 $
25  */

26 public class SScrollPane
27         extends SContainer
28         implements javax.swing.ScrollPaneConstants JavaDoc {
29
30     /**
31      * The element which should be scrolled.
32      */

33     protected Scrollable scrollable;
34     protected Adjustable verticalScrollBar = null;
35     protected Adjustable horizontalScrollBar = null;
36
37     /**
38      * store the scrollables viewport. Scrollable is reset to this value, if it
39      * is removed from the this scrollpane
40      */

41     protected Rectangle backupViewport;
42
43     protected int horizontalScrollBarPolicy = HORIZONTAL_SCROLLBAR_AS_NEEDED;
44
45     protected int verticalScrollBarPolicy = VERTICAL_SCROLLBAR_AS_NEEDED;
46
47     protected AdjustmentListener JavaDoc adjustmentListener;
48
49     protected int horizontalExtent = 10;
50
51     protected int verticalExtent = 10;
52
53     public SScrollPane() {
54         super(new SScrollPaneLayout());
55
56         setHorizontalScrollBar(new SScrollBar(SConstants.HORIZONTAL));
57         setVerticalScrollBar(new SScrollBar(SConstants.VERTICAL));
58     }
59
60     public SScrollPane(SComponent c) {
61         this();
62         setViewportView(c);
63     }
64
65     public AdjustmentListener JavaDoc getAdjustmentListener() {
66         if (adjustmentListener == null) {
67             adjustmentListener = new AdjustmentListener JavaDoc() {
68                 public void adjustmentValueChanged(AdjustmentEvent JavaDoc e) {
69                     if (scrollable != null) {
70                         synchronizeViewport();
71                     }
72                 }
73             };
74         }
75         return adjustmentListener;
76     }
77
78     /**
79      * synchronize viewport of scrollable with settings of adjustables
80      */

81     public void synchronizeAdjustables() {
82         if (scrollable == null) return;
83
84         Rectangle viewport = scrollable.getViewportSize();
85         Rectangle maxViewport = scrollable.getScrollableViewportSize();
86
87         if (viewport == null) viewport = maxViewport;
88
89         if (getHorizontalScrollBar() != null &&
90                 getHorizontalScrollBarPolicy() != HORIZONTAL_SCROLLBAR_NEVER) {
91             adjustAdjustable(getHorizontalScrollBar(), viewport,
92                     maxViewport);
93         }
94
95         if (getVerticalScrollBar() != null &&
96                 getVerticalScrollBarPolicy() != VERTICAL_SCROLLBAR_NEVER) {
97             adjustAdjustable(getVerticalScrollBar(), viewport,
98                     maxViewport);
99         }
100
101     }
102
103     protected void adjustAdjustable(Adjustable adjustable, Rectangle viewport,
104                                     Rectangle maxViewport) {
105         if (adjustable.getOrientation() == Adjustable.HORIZONTAL) {
106             adjustable.setValue(viewport.x);
107             adjustable.setMaximum(maxViewport.x + maxViewport.width);
108             adjustable.setMinimum(maxViewport.x);
109             adjustable.setVisibleAmount(getHorizontalExtent());
110         } else if (adjustable.getOrientation() == Adjustable.VERTICAL) {
111             adjustable.setValue(viewport.y);
112             adjustable.setMaximum(maxViewport.y + maxViewport.height);
113             adjustable.setMinimum(maxViewport.y);
114             adjustable.setVisibleAmount(getVerticalExtent());
115         }
116     }
117
118     /**
119      * synchronize viewport of scrollable with settings of adjustables
120      */

121     public void synchronizeViewport() {
122         Rectangle viewport = scrollable.getScrollableViewportSize();
123         
124         // should never happen. If it happens we got a serious problem, because
125
// we cannot determine what to scroll...
126
if (viewport == null) viewport = new Rectangle();
127
128         if (getHorizontalScrollBar() != null &&
129                 getHorizontalScrollBarPolicy() != HORIZONTAL_SCROLLBAR_NEVER) {
130             adjustViewport(viewport, getHorizontalScrollBar());
131         }
132
133         if (getVerticalScrollBar() != null &&
134                 getVerticalScrollBarPolicy() != VERTICAL_SCROLLBAR_NEVER) {
135             adjustViewport(viewport, getVerticalScrollBar());
136         }
137
138         scrollable.setViewportSize(viewport);
139     }
140
141     protected void adjustViewport(Rectangle viewport, Adjustable adjustable) {
142         if (adjustable.getOrientation() == Adjustable.HORIZONTAL) {
143             int extent = getHorizontalExtent();
144
145             viewport.x = Math.min(adjustable.getMaximum(),
146                     adjustable.getValue());
147             viewport.x = Math.max(adjustable.getMinimum(),
148                     viewport.x);
149             viewport.width = Math.min(adjustable.getMaximum() - viewport.x,
150                     extent);
151             viewport.width = Math.max(0, viewport.width);
152         } else {
153             int extent = getVerticalExtent();
154
155             viewport.y = Math.min(adjustable.getMaximum(),
156                     adjustable.getValue());
157             viewport.y = Math.max(adjustable.getMinimum(),
158                     viewport.y);
159             viewport.height = Math.min(adjustable.getMaximum() - viewport.y,
160                     extent);
161             viewport.height = Math.max(0, viewport.height);
162         }
163
164     }
165
166     protected void setScrollable(SComponent c) {
167         if (scrollable != null) {
168             // reset to original value
169
scrollable.setViewportSize(backupViewport);
170         }
171
172         if (c instanceof Scrollable && c != null) {
173             scrollable = (Scrollable) c;
174
175             // keep original value
176
backupViewport = scrollable.getViewportSize();
177
178             synchronizeViewport();
179         } else {
180             scrollable = null;
181         }
182
183         reload();
184     }
185
186     public final Scrollable getScrollable() {
187         return scrollable;
188     }
189
190     /**
191      * Sets the scrollable.
192      * If there is already one, it will be removed first.
193      *
194      * @param view the component to add to the viewport
195      */

196     public void setViewportView(SComponent view) {
197         add(view);
198     }
199
200     /**
201      * only {@link Scrollable scrollables} are allowed here!
202      */

203     public SComponent addComponent(SComponent c, Object JavaDoc constraint, int index) {
204         if (c instanceof Scrollable) {
205             super.addComponent(c, SScrollPaneLayout.VIEWPORT, index);
206             setScrollable(c);
207             return c;
208         } else {
209             throw new IllegalArgumentException JavaDoc("Only Scrollables are allowed");
210         }
211     }
212
213     public void setCG(ScrollPaneCG cg) {
214         super.setCG(cg);
215     }
216
217     /**
218      * Returns the horizontal scroll bar.
219      *
220      * @return the scrollbar that controls the viewports horizontal view position
221      */

222     public Adjustable getHorizontalScrollBar() {
223         return horizontalScrollBar;
224     }
225
226     /**
227      * Set the horizontal scroll bar.
228      *
229      * @param sb the scrollbar that controls the viewports horizontal view position
230      */

231     public void setHorizontalScrollBar(Adjustable sb) {
232         setHorizontalScrollBar(sb, SScrollPaneLayout.SOUTH);
233     }
234
235     /**
236      * Set the horizontal scroll bar.
237      *
238      * @param constraint the constraint for the {@link LayoutManager} of this
239      * {@link SContainer}. The {@link LayoutManager} is per default
240      * {@link SScrollPaneLayout}.
241      */

242     public void setHorizontalScrollBar(Adjustable sb, String JavaDoc constraint) {
243         if (horizontalScrollBar != null) {
244             horizontalScrollBar.removeAdjustmentListener(getAdjustmentListener());
245             if (horizontalScrollBar instanceof SComponent)
246                 super.remove((SComponent) horizontalScrollBar);
247         }
248
249         horizontalScrollBar = sb;
250
251         if (horizontalScrollBar != null) {
252             if (horizontalScrollBar instanceof SComponent)
253                 super.addComponent((SComponent) horizontalScrollBar, constraint, getComponentCount());
254
255             synchronizeAdjustables();
256             horizontalScrollBar.addAdjustmentListener(getAdjustmentListener());
257         }
258
259         reload();
260     }
261
262     /**
263      * Returns the horizontal scroll bar policy value.
264      *
265      * @return the horizontal scrollbar policy.
266      * @see #setHorizontalScrollBarPolicy(int)
267      */

268     public final int getHorizontalScrollBarPolicy() {
269         return horizontalScrollBarPolicy;
270     }
271
272     /**
273      * Returns the vertical scroll bar.
274      *
275      * @return the scrollbar that controls the viewports vertical view position
276      */

277     public final Adjustable getVerticalScrollBar() {
278         return verticalScrollBar;
279     }
280
281     /**
282      * Set the vertical scroll bar.
283      *
284      * @param sb the scrollbar that controls the viewports vertical view position
285      */

286     public void setVerticalScrollBar(Adjustable sb) {
287         setVerticalScrollBar(sb, SScrollPaneLayout.EAST);
288     }
289
290     /**
291      * Set the vertical scroll bar.
292      *
293      * @param sb the scrollbar that controls the viewports vertical view position
294      * @param constraint the constraint for the {@link LayoutManager} of this
295      * {@link SContainer}. The {@link LayoutManager} is per default
296      * {@link SScrollPaneLayout}.
297      */

298     public void setVerticalScrollBar(Adjustable sb, String JavaDoc constraint) {
299         if (verticalScrollBar != null) {
300             verticalScrollBar.removeAdjustmentListener(getAdjustmentListener());
301             if (verticalScrollBar instanceof SComponent)
302                 super.remove((SComponent) verticalScrollBar);
303         }
304
305         verticalScrollBar = sb;
306
307         if (verticalScrollBar != null) {
308             if (verticalScrollBar instanceof SComponent)
309                 super.addComponent((SComponent) verticalScrollBar, constraint, getComponentCount());
310
311             synchronizeAdjustables();
312             verticalScrollBar.addAdjustmentListener(getAdjustmentListener());
313         }
314
315         reload();
316     }
317
318     /**
319      * Returns the vertical scroll bar policy value.
320      *
321      * @return the vertical scrollbar policy.
322      * @see #setVerticalScrollBarPolicy(int)
323      */

324     public final int getVerticalScrollBarPolicy() {
325         return verticalScrollBarPolicy;
326     }
327
328     /**
329      * Determines when the horizontal scrollbar appears in the scrollpane.
330      * The options are:
331      * <li><code>SScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED</code></li>
332      * <li><code>SScrollPane.HORIZONTAL_SCROLLBAR_NEVER</code></li>
333      * <li><code>SScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS</code></li>
334      */

335     public void setHorizontalScrollBarPolicy(int policy) {
336         if (policy != horizontalScrollBarPolicy) {
337             horizontalScrollBarPolicy = policy;
338             reload();
339         }
340     }
341
342     /**
343      * Determines when the vertical scrollbar appears in the scrollpane.
344      * The options are:
345      * <li><code>SScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED</code></li>
346      * <li><code>SScrollPane.VERTICAL_SCROLLBAR_NEVER</code></li>
347      * <li><code>SScrollPane.VERTICAL_SCROLLBAR_ALWAYS</code></li>
348      */

349     public void setVerticalScrollBarPolicy(int policy) {
350         if (policy != verticalScrollBarPolicy) {
351             verticalScrollBarPolicy = policy;
352             reload();
353         }
354     }
355
356     /**
357      * Set the preferred size for this scrollpane and
358      * the scrollbars aswell.
359      */

360     public void setPreferredSize(SDimension dim) {
361         super.setPreferredSize(dim);
362         if (horizontalScrollBar instanceof SComponent) {
363             ((SComponent) horizontalScrollBar).setPreferredSize(dim);
364         }
365         if (verticalScrollBar instanceof SComponent) {
366             ((SComponent) verticalScrollBar).setPreferredSize(dim);
367         }
368     }
369
370
371     public void setHorizontalExtent(int horizontalExtent) {
372         this.horizontalExtent = horizontalExtent;
373     }
374
375
376     public final int getHorizontalExtent() {
377         if (scrollable != null) {
378             Dimension preferredExtent = scrollable.getPreferredExtent();
379             if (preferredExtent != null && preferredExtent.width > 0 &&
380                     preferredExtent.width < horizontalExtent) {
381                 return preferredExtent.width;
382             }
383         }
384         return horizontalExtent;
385     }
386
387
388     public void setVerticalExtent(int verticalExtent) {
389         this.verticalExtent = verticalExtent;
390     }
391
392
393     public final int getVerticalExtent() {
394         if (scrollable != null) {
395             Dimension preferredExtent = scrollable.getPreferredExtent();
396             if (preferredExtent != null && preferredExtent.height > 0 &&
397                     preferredExtent.height < verticalExtent) {
398                 return preferredExtent.height;
399             }
400         }
401
402         return verticalExtent;
403     }
404
405     public void scrollRectToVisible(Rectangle aRect) {
406         Rectangle viewport = scrollable.getScrollableViewportSize();
407         
408         // should never happen. If it happen we got a serious problem, because
409
// we cannot determine what to scroll...
410
if (viewport == null) return;
411
412         Adjustable hbar = getHorizontalScrollBar();
413         if (hbar != null &&
414                 getHorizontalScrollBarPolicy() != HORIZONTAL_SCROLLBAR_NEVER) {
415             int nval = scrollValue(hbar.getValue(), getHorizontalExtent(),
416                     aRect.x, aRect.width,
417                     hbar.getUnitIncrement());
418             if (nval != hbar.getValue()) {
419                 hbar.setValue(nval);
420             }
421         }
422
423         Adjustable vbar = getVerticalScrollBar();
424         if (vbar != null &&
425                 getVerticalScrollBarPolicy() != VERTICAL_SCROLLBAR_NEVER) {
426             int nval = scrollValue(vbar.getValue(), getVerticalExtent(),
427                     aRect.y, aRect.height,
428                     vbar.getUnitIncrement());
429             if (nval != vbar.getValue()) {
430                 vbar.setValue(nval);
431             }
432         }
433     }
434
435     /**
436      * Calculate the best new position to show the given range.
437      *
438      * @param pos the current position
439      * @param size the current visible amount
440      * @param rpos the start-position of the range to expose
441      * @param rsize the size of the range to expose
442      * @param inc the unit-increment to advance pos
443      * @return pos the new position
444      */

445     protected int scrollValue(int pos, int size, int rpos, int rsize, int inc) {
446         if (pos <= rpos &&
447                 (pos + size) >= (rpos + rsize)) {
448             // nothing to do
449
return pos;
450         }
451
452         if (pos > rpos) {
453             // scroll backward - ignore rsize, either it fits or it doesn't,
454
// just make sure the difference between pos and rpos is as
455
// small as possible.
456
while (pos > rpos) {
457                 pos -= inc;
458             }
459         } else {
460             // scroll forward
461
while ((pos + size) < (rpos + rsize) &&
462                     (pos + inc) <= rpos) {
463                 pos += inc;
464             }
465         }
466         return pos;
467     }
468 }
469
Popular Tags