KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > swt > custom > ScrolledComposite


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.swt.custom;
12
13 import org.eclipse.swt.*;
14 import org.eclipse.swt.graphics.*;
15 import org.eclipse.swt.widgets.*;
16
17 /**
18  * A ScrolledComposite provides scrollbars and will scroll its content when the user
19  * uses the scrollbars.
20  *
21  *
22  * <p>There are two ways to use the ScrolledComposite:
23  *
24  * <p>
25  * 1) Set the size of the control that is being scrolled and the ScrolledComposite
26  * will show scrollbars when the contained control can not be fully seen.
27  *
28  * 2) The second way imitates the way a browser would work. Set the minimum size of
29  * the control and the ScrolledComposite will show scroll bars if the visible area is
30  * less than the minimum size of the control and it will expand the size of the control
31  * if the visible area is greater than the minimum size. This requires invoking
32  * both setMinWidth(), setMinHeight() and setExpandHorizontal(), setExpandVertical().
33  *
34  * <code><pre>
35  * public static void main (String [] args) {
36  * Display display = new Display ();
37  * Color red = display.getSystemColor(SWT.COLOR_RED);
38  * Color blue = display.getSystemColor(SWT.COLOR_BLUE);
39  * Shell shell = new Shell (display);
40  * shell.setLayout(new FillLayout());
41  *
42  * // set the size of the scrolled content - method 1
43  * final ScrolledComposite sc1 = new ScrolledComposite(shell, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
44  * final Composite c1 = new Composite(sc1, SWT.NONE);
45  * sc1.setContent(c1);
46  * c1.setBackground(red);
47  * GridLayout layout = new GridLayout();
48  * layout.numColumns = 4;
49  * c1.setLayout(layout);
50  * Button b1 = new Button (c1, SWT.PUSH);
51  * b1.setText("first button");
52  * c1.setSize(c1.computeSize(SWT.DEFAULT, SWT.DEFAULT));
53  *
54  * // set the minimum width and height of the scrolled content - method 2
55  * final ScrolledComposite sc2 = new ScrolledComposite(shell, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
56  * sc2.setExpandHorizontal(true);
57  * sc2.setExpandVertical(true);
58  * final Composite c2 = new Composite(sc2, SWT.NONE);
59  * sc2.setContent(c2);
60  * c2.setBackground(blue);
61  * layout = new GridLayout();
62  * layout.numColumns = 4;
63  * c2.setLayout(layout);
64  * Button b2 = new Button (c2, SWT.PUSH);
65  * b2.setText("first button");
66  * sc2.setMinSize(c2.computeSize(SWT.DEFAULT, SWT.DEFAULT));
67  *
68  * Button add = new Button (shell, SWT.PUSH);
69  * add.setText("add children");
70  * final int[] index = new int[]{0};
71  * add.addListener(SWT.Selection, new Listener() {
72  * public void handleEvent(Event e) {
73  * index[0]++;
74  * Button button = new Button(c1, SWT.PUSH);
75  * button.setText("button "+index[0]);
76  * // reset size of content so children can be seen - method 1
77  * c1.setSize(c1.computeSize(SWT.DEFAULT, SWT.DEFAULT));
78  * c1.layout();
79  *
80  * button = new Button(c2, SWT.PUSH);
81  * button.setText("button "+index[0]);
82  * // reset the minimum width and height so children can be seen - method 2
83  * sc2.setMinSize(c2.computeSize(SWT.DEFAULT, SWT.DEFAULT));
84  * c2.layout();
85  * }
86  * });
87  *
88  * shell.open ();
89  * while (!shell.isDisposed ()) {
90  * if (!display.readAndDispatch ()) display.sleep ();
91  * }
92  * display.dispose ();
93  * }
94  * </pre></code>
95  *
96  * <dl>
97  * <dt><b>Styles:</b><dd>H_SCROLL, V_SCROLL
98  * </dl>
99  */

100 public class ScrolledComposite extends Composite {
101
102     Control content;
103     Listener contentListener;
104     
105     int minHeight = 0;
106     int minWidth = 0;
107     boolean expandHorizontal = false;
108     boolean expandVertical = false;
109     boolean alwaysShowScroll = false;
110
111 /**
112  * Constructs a new instance of this class given its parent
113  * and a style value describing its behavior and appearance.
114  * <p>
115  * The style value is either one of the style constants defined in
116  * class <code>SWT</code> which is applicable to instances of this
117  * class, or must be built by <em>bitwise OR</em>'ing together
118  * (that is, using the <code>int</code> "|" operator) two or more
119  * of those <code>SWT</code> style constants. The class description
120  * lists the style constants that are applicable to the class.
121  * Style bits are also inherited from superclasses.
122  * </p>
123  *
124  * @param parent a widget which will be the parent of the new instance (cannot be null)
125  * @param style the style of widget to construct
126  *
127  * @exception IllegalArgumentException <ul>
128  * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
129  * </ul>
130  * @exception SWTException <ul>
131  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
132  * </ul>
133  *
134  * @see SWT#H_SCROLL
135  * @see SWT#V_SCROLL
136  * @see #getStyle()
137  */

138 public ScrolledComposite(Composite parent, int style) {
139     super(parent, checkStyle(style));
140     super.setLayout(new ScrolledCompositeLayout());
141     ScrollBar hBar = getHorizontalBar ();
142     if (hBar != null) {
143         hBar.setVisible(false);
144         hBar.addListener (SWT.Selection, new Listener () {
145             public void handleEvent (Event e) {
146                 hScroll();
147             }
148         });
149     }
150     
151     ScrollBar vBar = getVerticalBar ();
152     if (vBar != null) {
153         vBar.setVisible(false);
154         vBar.addListener (SWT.Selection, new Listener () {
155             public void handleEvent (Event e) {
156                 vScroll();
157             }
158         });
159     }
160     
161     contentListener = new Listener() {
162         public void handleEvent(Event e) {
163             if (e.type != SWT.Resize) return;
164             layout(false);
165         }
166     };
167 }
168
169 static int checkStyle (int style) {
170     int mask = SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER | SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
171     return style & mask;
172 }
173
174 /**
175  * Returns the Always Show Scrollbars flag. True if the scrollbars are
176  * always shown even if they are not required. False if the scrollbars are only
177  * visible when some part of the composite needs to be scrolled to be seen.
178  * The H_SCROLL and V_SCROLL style bits are also required to enable scrollbars in the
179  * horizontal and vertical directions.
180  *
181  * @return the Always Show Scrollbars flag value
182  */

183 public boolean getAlwaysShowScrollBars() {
184     //checkWidget();
185
return alwaysShowScroll;
186 }
187
188 /**
189  * Returns <code>true</code> if the content control
190  * will be expanded to fill available horizontal space.
191  *
192  * @return the receiver's horizontal expansion state
193  *
194  * @exception SWTException <ul>
195  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
196  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
197  * </ul>
198  *
199  * @since 3.2
200  */

201 public boolean getExpandHorizontal() {
202     checkWidget();
203     return expandHorizontal;
204 }
205
206 /**
207  * Returns <code>true</code> if the content control
208  * will be expanded to fill available vertical space.
209  *
210  * @return the receiver's vertical expansion state
211  *
212  * @exception SWTException <ul>
213  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
214  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
215  * </ul>
216  *
217  * @since 3.2
218  */

219 public boolean getExpandVertical() {
220     checkWidget();
221     return expandVertical;
222 }
223
224 /**
225  * Returns the minimum width of the content control.
226  *
227  * @return the minimum width
228  *
229  * @exception SWTException <ul>
230  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
231  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
232  * </ul>
233  *
234  * @since 3.2
235  */

236 public int getMinWidth() {
237     checkWidget();
238     return minWidth;
239 }
240
241 /**
242  * Returns the minimum height of the content control.
243  *
244  * @return the minimum height
245  *
246  * @exception SWTException <ul>
247  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
248  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
249  * </ul>
250  *
251  * @since 3.2
252  */

253 public int getMinHeight() {
254     checkWidget();
255     return minHeight;
256 }
257
258 /**
259  * Get the content that is being scrolled.
260  *
261  * @return the control displayed in the content area
262  */

263 public Control getContent() {
264     //checkWidget();
265
return content;
266 }
267
268 void hScroll() {
269     if (content == null) return;
270     Point location = content.getLocation ();
271     ScrollBar hBar = getHorizontalBar ();
272     int hSelection = hBar.getSelection ();
273     content.setLocation (-hSelection, location.y);
274 }
275 boolean needHScroll(Rectangle contentRect, boolean vVisible) {
276     ScrollBar hBar = getHorizontalBar();
277     if (hBar == null) return false;
278     
279     Rectangle hostRect = getBounds();
280     int border = getBorderWidth();
281     hostRect.width -= 2*border;
282     ScrollBar vBar = getVerticalBar();
283     if (vVisible && vBar != null) hostRect.width -= vBar.getSize().x;
284     
285     if (!expandHorizontal && contentRect.width > hostRect.width) return true;
286     if (expandHorizontal && minWidth > hostRect.width) return true;
287     return false;
288 }
289
290 boolean needVScroll(Rectangle contentRect, boolean hVisible) {
291     ScrollBar vBar = getVerticalBar();
292     if (vBar == null) return false;
293     
294     Rectangle hostRect = getBounds();
295     int border = getBorderWidth();
296     hostRect.height -= 2*border;
297     ScrollBar hBar = getHorizontalBar();
298     if (hVisible && hBar != null) hostRect.height -= hBar.getSize().y;
299     
300     if (!expandVertical && contentRect.height > hostRect.height) return true;
301     if (expandVertical && minHeight > hostRect.height) return true;
302     return false;
303 }
304
305 /**
306  * Return the point in the content that currently appears in the top left
307  * corner of the scrolled composite.
308  *
309  * @return the point in the content that currently appears in the top left
310  * corner of the scrolled composite. If no content has been set, this returns
311  * (0, 0).
312  *
313  * @exception SWTException <ul>
314  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
315  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
316  * </ul>
317  *
318  * @since 2.0
319  */

320 public Point getOrigin() {
321     checkWidget();
322     if (content == null) return new Point(0, 0);
323     Point location = content.getLocation();
324     return new Point(-location.x, -location.y);
325 }
326 /**
327  * Scrolls the content so that the specified point in the content is in the top
328  * left corner. If no content has been set, nothing will occur.
329  *
330  * Negative values will be ignored. Values greater than the maximum scroll
331  * distance will result in scrolling to the end of the scrollbar.
332  *
333  * @param origin the point on the content to appear in the top left corner
334  *
335  * @exception SWTException <ul>
336  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
337  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
338  * <li>ERROR_INVALID_ARGUMENT - value of origin is outside of content
339  * </ul>
340  * @since 2.0
341  */

342 public void setOrigin(Point origin) {
343     setOrigin(origin.x, origin.y);
344 }
345 /**
346  * Scrolls the content so that the specified point in the content is in the top
347  * left corner. If no content has been set, nothing will occur.
348  *
349  * Negative values will be ignored. Values greater than the maximum scroll
350  * distance will result in scrolling to the end of the scrollbar.
351  *
352  * @param x the x coordinate of the content to appear in the top left corner
353  *
354  * @param y the y coordinate of the content to appear in the top left corner
355  *
356  * @exception SWTException <ul>
357  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
358  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
359  * </ul>
360  *
361  * @since 2.0
362  */

363 public void setOrigin(int x, int y) {
364     checkWidget();
365     if (content == null) return;
366     ScrollBar hBar = getHorizontalBar ();
367     if (hBar != null) {
368         hBar.setSelection(x);
369         x = -hBar.getSelection ();
370     } else {
371         x = 0;
372     }
373     ScrollBar vBar = getVerticalBar ();
374     if (vBar != null) {
375         vBar.setSelection(y);
376         y = -vBar.getSelection ();
377     } else {
378         y = 0;
379     }
380     content.setLocation(x, y);
381 }
382 /**
383  * Set the Always Show Scrollbars flag. True if the scrollbars are
384  * always shown even if they are not required. False if the scrollbars are only
385  * visible when some part of the composite needs to be scrolled to be seen.
386  * The H_SCROLL and V_SCROLL style bits are also required to enable scrollbars in the
387  * horizontal and vertical directions.
388  *
389  * @param show true to show the scrollbars even when not required, false to show scrollbars only when required
390  *
391  * @exception SWTException <ul>
392  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
393  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
394  * </ul>
395  */

396 public void setAlwaysShowScrollBars(boolean show) {
397     checkWidget();
398     if (show == alwaysShowScroll) return;
399     alwaysShowScroll = show;
400     ScrollBar hBar = getHorizontalBar ();
401     if (hBar != null && alwaysShowScroll) hBar.setVisible(true);
402     ScrollBar vBar = getVerticalBar ();
403     if (vBar != null && alwaysShowScroll) vBar.setVisible(true);
404     layout(false);
405 }
406
407 /**
408  * Set the content that will be scrolled.
409  *
410  * @param content the control to be displayed in the content area
411  *
412  * @exception SWTException <ul>
413  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
414  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
415  * </ul>
416  */

417 public void setContent(Control content) {
418     checkWidget();
419     if (this.content != null && !this.content.isDisposed()) {
420         this.content.removeListener(SWT.Resize, contentListener);
421         this.content.setBounds(new Rectangle(-200, -200, 0, 0));
422     }
423     
424     this.content = content;
425     ScrollBar vBar = getVerticalBar ();
426     ScrollBar hBar = getHorizontalBar ();
427     if (this.content != null) {
428         if (vBar != null) {
429             vBar.setMaximum (0);
430             vBar.setThumb (0);
431             vBar.setSelection(0);
432         }
433         if (hBar != null) {
434             hBar.setMaximum (0);
435             hBar.setThumb (0);
436             hBar.setSelection(0);
437         }
438         content.setLocation(0, 0);
439         layout(false);
440         this.content.addListener(SWT.Resize, contentListener);
441     } else {
442         if (hBar != null) hBar.setVisible(alwaysShowScroll);
443         if (vBar != null) vBar.setVisible(alwaysShowScroll);
444     }
445 }
446 /**
447  * Configure the ScrolledComposite to resize the content object to be as wide as the
448  * ScrolledComposite when the width of the ScrolledComposite is greater than the
449  * minimum width specified in setMinWidth. If the ScrolledComposite is less than the
450  * minimum width, the content will not be resized and instead the horizontal scroll bar will be
451  * used to view the entire width.
452  * If expand is false, this behaviour is turned off. By default, this behaviour is turned off.
453  *
454  * @param expand true to expand the content control to fill available horizontal space
455  *
456  * @exception SWTException <ul>
457  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
458  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
459  * </ul>
460  */

461 public void setExpandHorizontal(boolean expand) {
462     checkWidget();
463     if (expand == expandHorizontal) return;
464     expandHorizontal = expand;
465     layout(false);
466 }
467 /**
468  * Configure the ScrolledComposite to resize the content object to be as tall as the
469  * ScrolledComposite when the height of the ScrolledComposite is greater than the
470  * minimum height specified in setMinHeight. If the ScrolledComposite is less than the
471  * minimum height, the content will not be resized and instead the vertical scroll bar will be
472  * used to view the entire height.
473  * If expand is false, this behaviour is turned off. By default, this behaviour is turned off.
474  *
475  * @param expand true to expand the content control to fill available vertical space
476  *
477  * @exception SWTException <ul>
478  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
479  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
480  * </ul>
481  */

482 public void setExpandVertical(boolean expand) {
483     checkWidget();
484     if (expand == expandVertical) return;
485     expandVertical = expand;
486     layout(false);
487 }
488 /**
489  * Sets the layout which is associated with the receiver to be
490  * the argument which may be null.
491  * <p>
492  * Note: No Layout can be set on this Control because it already
493  * manages the size and position of its children.
494  * </p>
495  *
496  * @param layout the receiver's new layout or null
497  *
498  * @exception SWTException <ul>
499  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
500  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
501  * </ul>
502  */

503 public void setLayout (Layout layout) {
504     checkWidget();
505     return;
506 }
507 /**
508  * Specify the minimum height at which the ScrolledComposite will begin scrolling the
509  * content with the vertical scroll bar. This value is only relevant if
510  * setExpandVertical(true) has been set.
511  *
512  * @param height the minimum height or 0 for default height
513  *
514  * @exception SWTException <ul>
515  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
516  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
517  * </ul>
518  */

519 public void setMinHeight(int height) {
520     setMinSize(minWidth, height);
521 }
522 /**
523  * Specify the minimum width and height at which the ScrolledComposite will begin scrolling the
524  * content with the horizontal scroll bar. This value is only relevant if
525  * setExpandHorizontal(true) and setExpandVertical(true) have been set.
526  *
527  * @param size the minimum size or null for the default size
528  *
529  * @exception SWTException <ul>
530  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
531  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
532  * </ul>
533  */

534 public void setMinSize(Point size) {
535     if (size == null) {
536         setMinSize(0, 0);
537     } else {
538         setMinSize(size.x, size.y);
539     }
540 }
541 /**
542  * Specify the minimum width and height at which the ScrolledComposite will begin scrolling the
543  * content with the horizontal scroll bar. This value is only relevant if
544  * setExpandHorizontal(true) and setExpandVertical(true) have been set.
545  *
546  * @param width the minimum width or 0 for default width
547  * @param height the minimum height or 0 for default height
548  *
549  * @exception SWTException <ul>
550  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
551  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
552  * </ul>
553  */

554 public void setMinSize(int width, int height) {
555     checkWidget();
556     if (width == minWidth && height == minHeight) return;
557     minWidth = Math.max(0, width);
558     minHeight = Math.max(0, height);
559     layout(false);
560 }
561 /**
562  * Specify the minimum width at which the ScrolledComposite will begin scrolling the
563  * content with the horizontal scroll bar. This value is only relevant if
564  * setExpandHorizontal(true) has been set.
565  *
566  * @param width the minimum width or 0 for default width
567  *
568  * @exception SWTException <ul>
569  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
570  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
571  * </ul>
572  */

573 public void setMinWidth(int width) {
574     setMinSize(width, minHeight);
575 }
576
577 void vScroll() {
578     if (content == null) return;
579     Point location = content.getLocation ();
580     ScrollBar vBar = getVerticalBar ();
581     int vSelection = vBar.getSelection ();
582     content.setLocation (location.x, -vSelection);
583 }
584 }
585
Popular Tags