libjava/ChangeLog:
[official-gcc.git] / libjava / classpath / java / awt / ScrollPane.java
blobec9746f9339f5b6f8aa0462214d71c2a98773abc
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)
9 any later version.
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
19 02110-1301 USA.
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
24 combination.
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. */
39 package java.awt;
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;
50 /**
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
60 * Static Variables
63 /**
64 * Constant indicating that scrollbars are created as needed in this
65 * windows.
67 public static final int SCROLLBARS_AS_NEEDED = 0;
69 /**
70 * Constant indicating that scrollbars are always displayed in this
71 * window.
73 public static final int SCROLLBARS_ALWAYS = 1;
75 /**
76 * Constant indicating that scrollbars are never displayed in this window.
78 public static final int SCROLLBARS_NEVER = 2;
80 /**
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 /*************************************************************************/
91 * Instance Variables
94 /**
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 /*************************************************************************/
122 * Constructors
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.
131 public
132 ScrollPane()
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.
148 public
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;
170 // Default size.
171 setSize(100,100);
174 /*************************************************************************/
177 * Instance Variables
181 * Returns the current scrollbar display policy.
183 * @return The current scrollbar display policy.
185 public int
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.
200 public Adjustable
201 getHAdjustable()
203 return(hAdjustable);
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.
215 public Adjustable
216 getVAdjustable()
218 return(vAdjustable);
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))
239 return viewsize;
241 Dimension dim = list[0].getPreferredSize();
243 if (dim.width <= 0 && dim.height <= 0)
244 return viewsize;
246 int vScrollbarWidth = getVScrollbarWidth ();
247 int hScrollbarHeight = getHScrollbarHeight ();
249 if (scrollbarDisplayPolicy == SCROLLBARS_ALWAYS)
251 viewsize.width -= vScrollbarWidth;
252 viewsize.height -= hScrollbarHeight;
253 return viewsize;
256 if (scrollbarDisplayPolicy == SCROLLBARS_NEVER)
257 return viewsize;
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
271 // width.
272 if (dim.height > viewsize.height)
273 needVertical = true;
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)
290 needVertical = true;
292 if (needHorizontal)
293 viewsize.height -= hScrollbarHeight;
295 if (needVertical)
296 viewsize.width -= vScrollbarWidth;
298 return viewsize;
301 /*************************************************************************/
304 * Returns the height of a horizontal scrollbar.
306 * @return The height of a horizontal scrollbar.
308 public int
309 getHScrollbarHeight()
311 ScrollPanePeer spp = (ScrollPanePeer)getPeer();
312 if (spp != null)
313 return(spp.getHScrollbarHeight());
314 else
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.
325 public int
326 getVScrollbarWidth()
328 ScrollPanePeer spp = (ScrollPanePeer)getPeer();
329 if (spp != null)
330 return(spp.getVScrollbarWidth());
331 else
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.
344 public Point
345 getScrollPosition()
347 if (getComponentCount() == 0)
348 throw new NullPointerException();
350 int x = 0;
351 int y = 0;
353 Adjustable v = getVAdjustable();
354 Adjustable h = getHAdjustable();
356 if (v != null)
357 y = v.getValue();
358 if (h != null)
359 x = h.getValue();
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.
374 public void
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.
393 public void
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());
404 if (x < 0)
405 x = 0;
406 if (y < 0)
407 y = 0;
409 Adjustable h = getHAdjustable();
410 Adjustable v = getVAdjustable();
412 if (h != null)
413 h.setValue(x);
414 if (v != null)
415 v.setValue(y);
417 ScrollPanePeer spp = (ScrollPanePeer)getPeer();
418 if (spp != null)
419 spp.setScrollPosition(x, y);
422 /*************************************************************************/
425 * Notifies this object that it should create its native peer.
427 public void
428 addNotify()
430 if (peer != null)
431 return;
433 setPeer((ComponentPeer)getToolkit().createScrollPane(this));
434 super.addNotify();
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);
442 add(panel);
446 /*************************************************************************/
449 * Notifies this object that it should destroy its native peers.
451 public void
452 removeNotify()
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,
470 int index)
472 Component[] list = getComponents();
473 if ((list != null) && (list.length > 0))
474 remove(list[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.
485 public void
486 doLayout()
488 layout ();
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>.
500 public void
501 layout()
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 ();
516 if (peer != null)
517 peer.childResized (dim.width, dim.height);
519 list[0].setSize (dim);
521 Point p = getScrollPosition ();
522 if (p.x > dim.width)
523 p.x = dim.width;
524 if (p.y > dim.height)
525 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.
543 public final void
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.
556 public void
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.
569 public String
570 paramString()
572 Insets insets = getInsets();
573 return getName() + ","
574 + getX() + ","
575 + getY() + ","
576 + getWidth() + "x" + getHeight() + ","
577 + getIsValidString() + ","
578 + "ScrollPosition=(" + scrollPosition.x + ","
579 + scrollPosition.y + "),"
580 + "Insets=(" + insets.top + ","
581 + insets.left + ","
582 + insets.bottom + ","
583 + insets.right + "),"
584 + "ScrollbarDisplayPolicy=" + getScrollbarDisplayPolicyString() + ","
585 + "wheelScrollingEnabled=" + isWheelScrollingEnabled();
588 private String
589 getScrollbarDisplayPolicyString()
591 if (getScrollbarDisplayPolicy() == 0)
592 return "as-needed";
593 else if (getScrollbarDisplayPolicy() == 1)
594 return "always";
595 else
596 return "never";
599 private String
600 getIsValidString()
602 if (isValid())
603 return "valid";
604 else
605 return "invalid";
609 * Tells whether or not an event is enabled.
611 * @since 1.4
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.
624 * @since 1.4
626 public boolean isWheelScrollingEnabled ()
628 return wheelScrollingEnabled;
632 * Enables/disables wheel scrolling.
634 * @since 1.4
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