1 /* ScrollPane.java -- Scrolling window
2 Copyright (C) 1999, 2002, 2004 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
41 import java
.awt
.event
.MouseEvent
;
42 import java
.awt
.peer
.ComponentPeer
;
43 import java
.awt
.peer
.ScrollPanePeer
;
45 import javax
.accessibility
.Accessible
;
46 import javax
.accessibility
.AccessibleContext
;
47 import javax
.accessibility
.AccessibleRole
;
51 * This widget provides a scrollable region that allows a single
52 * subcomponent to be viewed through a smaller window.
54 * @author Aaron M. Renn (arenn@urbanophile.com)
56 public class ScrollPane
extends Container
implements Accessible
64 * Constant indicating that scrollbars are created as needed in this
67 public static final int SCROLLBARS_AS_NEEDED
= 0;
70 * Constant indicating that scrollbars are always displayed in this
73 public static final int SCROLLBARS_ALWAYS
= 1;
76 * Constant indicating that scrollbars are never displayed in this window.
78 public static final int SCROLLBARS_NEVER
= 2;
81 * The number used to generate the name returned by getName.
83 private static transient long next_scrollpane_number
;
85 // Serialization constant
86 private static final long serialVersionUID
= 7956609840827222915L;
88 /*************************************************************************/
95 * @serial The horizontal scrollbar for this window. The methods
96 * <code>setMinimum()</code>, <code>setMaximum</code>, and
97 * <code>setVisibleAmount</code> must not be called on this scrollbar.
99 private ScrollPaneAdjustable hAdjustable
;
102 * @serial The vertical scrollbar for this window. The methods
103 * <code>setMinimum()</code>, <code>setMaximum</code>, and
104 * <code>setVisibleAmount</code> must not be called on this scrollbar.
106 private ScrollPaneAdjustable vAdjustable
;
109 * @serial Indicates when scrollbars are displayed in this window, will
110 * be one of the constants from this class.
112 private int scrollbarDisplayPolicy
;
114 // Current scroll position
115 private Point scrollPosition
= new Point(0, 0);
117 private boolean wheelScrollingEnabled
;
119 /*************************************************************************/
126 * Initializes a new instance of <code>ScrollPane</code> with a default
127 * scrollbar policy of <code>SCROLLBARS_AS_NEEDED</code>.
129 * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
134 this(SCROLLBARS_AS_NEEDED
);
137 /*************************************************************************/
140 * Initializes a new instance of <code>ScrollPane</code> with the
141 * specified scrollbar policy.
143 * @param scrollbarDisplayPolicy When to display scrollbars, which must
144 * be one of the constants defined in this class.
146 * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
149 ScrollPane(int scrollbarDisplayPolicy
)
151 if (GraphicsEnvironment
.isHeadless ())
152 throw new HeadlessException ();
154 this.scrollbarDisplayPolicy
= scrollbarDisplayPolicy
;
156 if (scrollbarDisplayPolicy
!= SCROLLBARS_ALWAYS
157 && scrollbarDisplayPolicy
!= SCROLLBARS_AS_NEEDED
158 && scrollbarDisplayPolicy
!= SCROLLBARS_NEVER
)
159 throw new IllegalArgumentException("Bad scrollbarDisplayPolicy: " +
160 scrollbarDisplayPolicy
);
162 if (scrollbarDisplayPolicy
!= SCROLLBARS_NEVER
)
164 hAdjustable
= new ScrollPaneAdjustable (this, Scrollbar
.HORIZONTAL
);
165 vAdjustable
= new ScrollPaneAdjustable (this, Scrollbar
.VERTICAL
);
168 wheelScrollingEnabled
= true;
174 /*************************************************************************/
181 * Returns the current scrollbar display policy.
183 * @return The current scrollbar display policy.
186 getScrollbarDisplayPolicy()
188 return(scrollbarDisplayPolicy
);
191 /*************************************************************************/
194 * Returns the horizontal scrollbar for this object. If the scrollbar
195 * display policy is set to <code>SCROLLBARS_NEVER</code> then this
196 * will be <code>null</code>.
198 * @return The horizontal scrollbar for this window.
206 /*************************************************************************/
209 * Returns the vertical scrollbar for this object. If the scrollbar
210 * display policy is set to <code>SCROLLBARS_NEVER</code> then this
211 * will be <code>null</code>.
213 * @return The horizontal scrollbar for this window.
221 /*************************************************************************/
224 * Returns the current viewport size. The viewport is the region of
225 * this object's window where the child is actually displayed.
227 * @return The viewport size.
229 public Dimension
getViewportSize ()
231 Dimension viewsize
= getSize ();
232 Insets insets
= getInsets ();
234 viewsize
.width
-= (insets
.left
+ insets
.right
);
235 viewsize
.height
-= (insets
.top
+ insets
.bottom
);
237 Component
[] list
= getComponents();
238 if ((list
== null) || (list
.length
<= 0))
241 Dimension dim
= list
[0].getPreferredSize();
243 if (dim
.width
<= 0 && dim
.height
<= 0)
246 int vScrollbarWidth
= getVScrollbarWidth ();
247 int hScrollbarHeight
= getHScrollbarHeight ();
249 if (scrollbarDisplayPolicy
== SCROLLBARS_ALWAYS
)
251 viewsize
.width
-= vScrollbarWidth
;
252 viewsize
.height
-= hScrollbarHeight
;
256 if (scrollbarDisplayPolicy
== SCROLLBARS_NEVER
)
259 // The scroll policy is SCROLLBARS_AS_NEEDED, so we need to see if
260 // either scrollbar is needed.
262 // Assume we don't need either scrollbar.
263 boolean mayNeedVertical
= false;
264 boolean mayNeedHorizontal
= false;
266 boolean needVertical
= false;
267 boolean needHorizontal
= false;
269 // Check if we need vertical scrollbars. If we do, then we need to
270 // subtract the width of the vertical scrollbar from the viewport's
272 if (dim
.height
> viewsize
.height
)
274 else if (dim
.height
> (viewsize
.height
- hScrollbarHeight
))
275 // This is tricky. In this case the child is tall enough that its
276 // bottom edge would be covered by a horizontal scrollbar, if one
277 // were present. This means that if there's a horizontal
278 // scrollbar then we need a vertical scrollbar.
279 mayNeedVertical
= true;
281 if (dim
.width
> viewsize
.width
)
282 needHorizontal
= true;
283 else if (dim
.width
> (viewsize
.width
- vScrollbarWidth
))
284 mayNeedHorizontal
= true;
286 if (needVertical
&& mayNeedHorizontal
)
287 needHorizontal
= true;
289 if (needHorizontal
&& mayNeedVertical
)
293 viewsize
.height
-= hScrollbarHeight
;
296 viewsize
.width
-= vScrollbarWidth
;
301 /*************************************************************************/
304 * Returns the height of a horizontal scrollbar.
306 * @return The height of a horizontal scrollbar.
309 getHScrollbarHeight()
311 ScrollPanePeer spp
= (ScrollPanePeer
)getPeer();
313 return(spp
.getHScrollbarHeight());
315 return(0); // FIXME: What to do here?
318 /*************************************************************************/
321 * Returns the width of a vertical scrollbar.
323 * @return The width of a vertical scrollbar.
328 ScrollPanePeer spp
= (ScrollPanePeer
)getPeer();
330 return(spp
.getVScrollbarWidth());
332 return(0); // FIXME: What to do here?
335 /*************************************************************************/
338 * Returns the current scroll position of the viewport.
340 * @return The current scroll position of the viewport.
342 * @throws NullPointerException if the scrollpane does have a child.
347 if (getComponentCount() == 0)
348 throw new NullPointerException();
353 Adjustable v
= getVAdjustable();
354 Adjustable h
= getHAdjustable();
361 return(new Point(x
, y
));
364 /*************************************************************************/
367 * Sets the scroll position to the specified value.
369 * @param scrollPosition The new scrollPosition.
371 * @exception IllegalArgumentException If the specified value is outside
372 * the legal scrolling range.
375 setScrollPosition(Point scrollPosition
) throws IllegalArgumentException
377 setScrollPosition(scrollPosition
.x
, scrollPosition
.y
);
380 /*************************************************************************/
383 * Sets the scroll position to the specified value.
385 * @param x The new X coordinate of the scroll position.
386 * @param y The new Y coordinate of the scroll position.
388 * @throws NullPointerException if scrollpane does not have a child.
390 * @exception IllegalArgumentException If the specified value is outside
391 * the legal scrolling range.
394 setScrollPosition(int x
, int y
)
396 if (getComponentCount() == 0)
397 throw new NullPointerException("child is null");
399 if (x
> (int) (getComponent(0).getWidth() - getViewportSize().getWidth()))
400 x
= (int) (getComponent(0).getWidth() - getViewportSize().getWidth());
401 if (y
> (int) (getComponent(0).getHeight() - getViewportSize().getHeight()))
402 y
= (int) (getComponent(0).getHeight() - getViewportSize().getHeight());
409 Adjustable h
= getHAdjustable();
410 Adjustable v
= getVAdjustable();
417 ScrollPanePeer spp
= (ScrollPanePeer
)getPeer();
419 spp
.setScrollPosition(x
, y
);
422 /*************************************************************************/
425 * Notifies this object that it should create its native peer.
433 setPeer((ComponentPeer
)getToolkit().createScrollPane(this));
436 Component
[] list
= getComponents();
437 if (list
!= null && list
.length
> 0 && list
[0].isLightweight())
439 Panel panel
= new Panel();
440 panel
.setLayout(new BorderLayout());
441 panel
.add(list
[0], BorderLayout
.CENTER
);
446 /*************************************************************************/
449 * Notifies this object that it should destroy its native peers.
454 super.removeNotify();
457 /*************************************************************************/
460 * Adds the specified child component to this container. A
461 * <code>ScrollPane</code> can have at most one child, so if a second
462 * one is added, then first one is removed.
464 * @param component The component to add to this container.
465 * @param constraints A list of layout constraints for this object.
466 * @param index The index at which to add the child, which is ignored
467 * in this implementation.
469 protected final void addImpl (Component component
, Object constraints
,
472 Component
[] list
= getComponents();
473 if ((list
!= null) && (list
.length
> 0))
476 super.addImpl(component
, constraints
, index
);
479 /*************************************************************************/
482 * Lays out this component. This consists of resizing the sole child
483 * component to its perferred size.
491 /*************************************************************************/
494 * Lays out this component. This consists of resizing the sole child
495 * component to its perferred size.
497 * @deprecated This method is deprecated in favor of
498 * <code>doLayout()</code>.
503 Component
[] list
= getComponents ();
504 if ((list
!= null) && (list
.length
> 0))
506 Dimension dim
= list
[0].getPreferredSize ();
507 Dimension vp
= getViewportSize ();
509 if (dim
.width
< vp
.width
)
510 dim
.width
= vp
.width
;
512 if (dim
.height
< vp
.height
)
513 dim
.height
= vp
.height
;
515 ScrollPanePeer peer
= (ScrollPanePeer
) getPeer ();
517 peer
.childResized (dim
.width
, dim
.height
);
519 list
[0].setSize (dim
);
521 Point p
= getScrollPosition ();
524 if (p
.y
> dim
.height
)
527 setScrollPosition (p
);
529 list
[0].setLocation(new Point());
533 /*************************************************************************/
536 * This method overrides its superclass method to ensure no layout
537 * manager is set for this container. <code>ScrollPane</code>'s do
538 * not have layout managers.
540 * @param layoutManager Ignored
541 * @throws AWTError Always throws this error when called.
544 setLayout(LayoutManager layoutManager
)
546 throw new AWTError("ScrollPane controls layout");
549 /*************************************************************************/
552 * Prints all of the components in this container.
554 * @param graphics The desired graphics context for printing.
557 printComponents(Graphics graphics
)
559 super.printComponents(graphics
);
562 /*************************************************************************/
565 * Returns a debug string for this object.
567 * @return A debug string for this object.
572 Insets insets
= getInsets();
573 return getName() + ","
576 + getWidth() + "x" + getHeight() + ","
577 + getIsValidString() + ","
578 + "ScrollPosition=(" + scrollPosition
.x
+ ","
579 + scrollPosition
.y
+ "),"
580 + "Insets=(" + insets
.top
+ ","
582 + insets
.bottom
+ ","
583 + insets
.right
+ "),"
584 + "ScrollbarDisplayPolicy=" + getScrollbarDisplayPolicyString() + ","
585 + "wheelScrollingEnabled=" + isWheelScrollingEnabled();
589 getScrollbarDisplayPolicyString()
591 if (getScrollbarDisplayPolicy() == 0)
593 else if (getScrollbarDisplayPolicy() == 1)
609 * Tells whether or not an event is enabled.
613 protected boolean eventTypeEnabled (int type
)
615 if (type
== MouseEvent
.MOUSE_WHEEL
)
616 return wheelScrollingEnabled
;
618 return super.eventTypeEnabled (type
);
622 * Tells whether or not wheel scrolling is enabled.
626 public boolean isWheelScrollingEnabled ()
628 return wheelScrollingEnabled
;
632 * Enables/disables wheel scrolling.
636 public void setWheelScrollingEnabled (boolean enable
)
638 wheelScrollingEnabled
= enable
;
641 protected class AccessibleAWTScrollPane
extends AccessibleAWTContainer
643 private static final long serialVersionUID
= 6100703663886637L;
645 public AccessibleRole
getAccessibleRole()
647 return AccessibleRole
.SCROLL_PANE
;
652 * Gets the AccessibleContext associated with this <code>ScrollPane</code>.
653 * The context is created, if necessary.
655 * @return the associated context
657 public AccessibleContext
getAccessibleContext()
659 /* Create the context if this is the first request */
660 if (accessibleContext
== null)
661 accessibleContext
= new AccessibleAWTScrollPane();
662 return accessibleContext
;
666 * Generate a unique name for this <code>ScrollPane</code>.
668 * @return A unique name for this <code>ScrollPane</code>.
670 String
generateName()
672 return "scrollpane" + getUniqueLong();
675 private static synchronized long getUniqueLong()
677 return next_scrollpane_number
++;
680 } // class ScrollPane