Source for java.awt.ScrollPane

   1: /* ScrollPane.java -- Scrolling window
   2:    Copyright (C) 1999, 2002, 2004  Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   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.
  10: 
  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.
  15: 
  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.
  20: 
  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.
  25: 
  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. */
  37: 
  38: 
  39: package java.awt;
  40: 
  41: import java.awt.event.MouseEvent;
  42: import java.awt.peer.ComponentPeer;
  43: import java.awt.peer.ScrollPanePeer;
  44: 
  45: import javax.accessibility.Accessible;
  46: import javax.accessibility.AccessibleContext;
  47: import javax.accessibility.AccessibleRole;
  48: 
  49: /**
  50:   * This widget provides a scrollable region that allows a single 
  51:   * subcomponent to be viewed through a smaller window.
  52:   *
  53:   * @author Aaron M. Renn (arenn@urbanophile.com)
  54:   */
  55: public class ScrollPane extends Container implements Accessible
  56: {
  57: 
  58: /*
  59:  * Static Variables
  60:  */
  61: 
  62: /**
  63:   * Constant indicating that scrollbars are created as needed in this
  64:   * windows.
  65:   */
  66: public static final int SCROLLBARS_AS_NEEDED = 0;
  67: 
  68: /**
  69:   * Constant indicating that scrollbars are always displayed in this
  70:   * window.
  71:   */
  72: public static final int SCROLLBARS_ALWAYS = 1;
  73: 
  74: /**
  75:   * Constant indicating that scrollbars are never displayed in this window.
  76:   */
  77: public static final int SCROLLBARS_NEVER = 2;
  78: 
  79: // Serialization constant
  80: private static final long serialVersionUID = 7956609840827222915L;
  81: 
  82: /*************************************************************************/
  83: 
  84: /*
  85:  * Instance Variables
  86:  */
  87: 
  88: /**
  89:   * @serial The horizontal scrollbar for this window.  The methods
  90:   * <code>setMinimum()</code>, <code>setMaximum</code>, and
  91:   * <code>setVisibleAmount</code> must not be called on this scrollbar.
  92:   */
  93: private ScrollPaneAdjustable hAdjustable;
  94: 
  95: /**
  96:   * @serial The vertical scrollbar for this window.  The methods
  97:   * <code>setMinimum()</code>, <code>setMaximum</code>, and
  98:   * <code>setVisibleAmount</code> must not be called on this scrollbar.
  99:   */
 100: private ScrollPaneAdjustable vAdjustable;
 101: 
 102: /**
 103:   * @serial Indicates when scrollbars are displayed in this window, will
 104:   * be one of the constants from this class.
 105:   */
 106: private int scrollbarDisplayPolicy;
 107: 
 108: // Current scroll position
 109: private Point scrollPosition = new Point(0, 0);
 110: 
 111: private boolean wheelScrollingEnabled;
 112: 
 113: /*************************************************************************/
 114: 
 115: /*
 116:  * Constructors
 117:  */
 118: 
 119: /**
 120:   * Initializes a new instance of <code>ScrollPane</code> with a default
 121:   * scrollbar policy of <code>SCROLLBARS_AS_NEEDED</code>.
 122:   *
 123:   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
 124:   */
 125: public
 126: ScrollPane()
 127: {
 128:   this(SCROLLBARS_AS_NEEDED);
 129: }
 130: 
 131: /*************************************************************************/
 132: 
 133: /**
 134:   * Initializes a new instance of <code>ScrollPane</code> with the
 135:   * specified scrollbar policy.
 136:   *
 137:   * @param scrollbarDisplayPolicy When to display scrollbars, which must
 138:   * be one of the constants defined in this class.
 139:   *
 140:   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
 141:   */
 142: public
 143: ScrollPane(int scrollbarDisplayPolicy)
 144: {
 145:   if (GraphicsEnvironment.isHeadless ())
 146:     throw new HeadlessException ();
 147: 
 148:   this.scrollbarDisplayPolicy = scrollbarDisplayPolicy;
 149: 
 150:   if (scrollbarDisplayPolicy != SCROLLBARS_ALWAYS
 151:       && scrollbarDisplayPolicy != SCROLLBARS_AS_NEEDED
 152:       && scrollbarDisplayPolicy != SCROLLBARS_NEVER)
 153:     throw new IllegalArgumentException("Bad scrollbarDisplayPolicy: " +
 154:                                        scrollbarDisplayPolicy);
 155: 
 156:   if (scrollbarDisplayPolicy != SCROLLBARS_NEVER)
 157:     {
 158:       hAdjustable = new ScrollPaneAdjustable (this, Scrollbar.HORIZONTAL);
 159:       vAdjustable = new ScrollPaneAdjustable (this, Scrollbar.VERTICAL);
 160:     }
 161: 
 162:   wheelScrollingEnabled = true;
 163: 
 164:   // Default size.
 165:   setSize(100,100);
 166: }
 167: 
 168: /*************************************************************************/
 169: 
 170: /*
 171:  * Instance Variables
 172:  */
 173: 
 174: /**
 175:   * Returns the current scrollbar display policy.
 176:   *
 177:   * @return The current scrollbar display policy.
 178:   */
 179: public int
 180: getScrollbarDisplayPolicy()
 181: {
 182:   return(scrollbarDisplayPolicy);
 183: }
 184: 
 185: /*************************************************************************/
 186: 
 187: /**
 188:   * Returns the horizontal scrollbar for this object.  If the scrollbar
 189:   * display policy is set to <code>SCROLLBARS_NEVER</code> then this
 190:   * will be <code>null</code>.
 191:   *
 192:   * @return The horizontal scrollbar for this window.
 193:   */
 194: public Adjustable
 195: getHAdjustable()
 196: {
 197:   return(hAdjustable);
 198: }
 199: 
 200: /*************************************************************************/
 201: 
 202: /**
 203:   * Returns the vertical scrollbar for this object.  If the scrollbar
 204:   * display policy is set to <code>SCROLLBARS_NEVER</code> then this
 205:   * will be <code>null</code>.
 206:   *
 207:   * @return The horizontal scrollbar for this window.
 208:   */
 209: public Adjustable
 210: getVAdjustable()
 211: {
 212:   return(vAdjustable);
 213: }
 214: 
 215: /*************************************************************************/
 216: 
 217: /**
 218:   * Returns the current viewport size.  The viewport is the region of
 219:   * this object's window where the child is actually displayed.
 220:   *
 221:   * @return The viewport size.
 222:   */
 223: public Dimension getViewportSize ()
 224: {
 225:   Dimension viewsize = getSize ();
 226:   Insets insets = getInsets ();
 227: 
 228:   viewsize.width -= (insets.left + insets.right);
 229:   viewsize.height -= (insets.top + insets.bottom);
 230: 
 231:   Component[] list = getComponents();
 232:   if ((list == null) || (list.length <= 0))
 233:     return viewsize;
 234: 
 235:   Dimension dim = list[0].getPreferredSize();
 236: 
 237:   if (dim.width <= 0 && dim.height <= 0)
 238:     return viewsize;
 239: 
 240:   int vScrollbarWidth = getVScrollbarWidth ();
 241:   int hScrollbarHeight = getHScrollbarHeight ();
 242: 
 243:   if (scrollbarDisplayPolicy == SCROLLBARS_ALWAYS)
 244:     {
 245:       viewsize.width -= vScrollbarWidth;
 246:       viewsize.height -= hScrollbarHeight;
 247:       return viewsize;
 248:     }
 249: 
 250:   if (scrollbarDisplayPolicy == SCROLLBARS_NEVER)
 251:     return viewsize;
 252: 
 253:   // The scroll policy is SCROLLBARS_AS_NEEDED, so we need to see if
 254:   // either scrollbar is needed.
 255: 
 256:   // Assume we don't need either scrollbar.
 257:   boolean mayNeedVertical = false;
 258:   boolean mayNeedHorizontal = false;
 259: 
 260:   boolean needVertical = false;
 261:   boolean needHorizontal = false;
 262: 
 263:   // Check if we need vertical scrollbars.  If we do, then we need to
 264:   // subtract the width of the vertical scrollbar from the viewport's
 265:   // width.
 266:   if (dim.height > viewsize.height)
 267:     needVertical = true;
 268:   else if (dim.height > (viewsize.height - hScrollbarHeight))
 269:     // This is tricky.  In this case the child is tall enough that its
 270:     // bottom edge would be covered by a horizontal scrollbar, if one
 271:     // were present.  This means that if there's a horizontal
 272:     // scrollbar then we need a vertical scrollbar.
 273:     mayNeedVertical = true;
 274: 
 275:   if (dim.width > viewsize.width)
 276:     needHorizontal = true;
 277:   else if (dim.width > (viewsize.width - vScrollbarWidth))
 278:     mayNeedHorizontal = true;
 279: 
 280:   if (needVertical && mayNeedHorizontal)
 281:     needHorizontal = true;
 282: 
 283:   if (needHorizontal && mayNeedVertical)
 284:     needVertical = true;
 285: 
 286:   if (needHorizontal)
 287:     viewsize.height -= hScrollbarHeight;
 288: 
 289:   if (needVertical)
 290:     viewsize.width -= vScrollbarWidth;
 291: 
 292:   return viewsize;
 293: }
 294: 
 295: /*************************************************************************/
 296: 
 297: /**
 298:   * Returns the height of a horizontal scrollbar.
 299:   *
 300:   * @return The height of a horizontal scrollbar.
 301:   */
 302: public int
 303: getHScrollbarHeight()
 304: {
 305:   ScrollPanePeer spp = (ScrollPanePeer)getPeer();
 306:   if (spp != null)
 307:     return(spp.getHScrollbarHeight());
 308:   else
 309:     return(0); // FIXME: What to do here?
 310: }
 311: 
 312: /*************************************************************************/
 313: 
 314: /**
 315:   * Returns the width of a vertical scrollbar.
 316:   *
 317:   * @return The width of a vertical scrollbar.
 318:   */
 319: public int
 320: getVScrollbarWidth()
 321: {
 322:   ScrollPanePeer spp = (ScrollPanePeer)getPeer();
 323:   if (spp != null)
 324:     return(spp.getVScrollbarWidth());
 325:   else
 326:     return(0); // FIXME: What to do here?
 327: }
 328: 
 329: /*************************************************************************/
 330: 
 331: /**
 332:   * Returns the current scroll position of the viewport.
 333:   *
 334:   * @return The current scroll position of the viewport.
 335:   */
 336: public Point
 337: getScrollPosition()
 338: {
 339:   int x = 0;
 340:   int y = 0;
 341: 
 342:   Adjustable v = getVAdjustable();
 343:   Adjustable h = getHAdjustable();
 344: 
 345:   if (v != null)
 346:     y = v.getValue();
 347:   if (h != null)
 348:     x = h.getValue();
 349: 
 350:   return(new Point(x, y));
 351: }
 352: 
 353: /*************************************************************************/
 354: 
 355: /**
 356:   * Sets the scroll position to the specified value.
 357:   *
 358:   * @param scrollPosition The new scrollPosition.
 359:   *
 360:   * @exception IllegalArgumentException If the specified value is outside
 361:   * the legal scrolling range.
 362:   */
 363: public void
 364: setScrollPosition(Point scrollPosition) throws IllegalArgumentException
 365: {
 366:   setScrollPosition(scrollPosition.x, scrollPosition.y);
 367: }
 368: 
 369: /*************************************************************************/
 370: 
 371: /**
 372:   * Sets the scroll position to the specified value.
 373:   *
 374:   * @param x The new X coordinate of the scroll position.
 375:   * @param y The new Y coordinate of the scroll position.
 376:   *
 377:   * @exception IllegalArgumentException If the specified value is outside
 378:   * the legal scrolling range.
 379:   */
 380: public void
 381: setScrollPosition(int x, int y)
 382: {
 383:   Adjustable h = getHAdjustable();
 384:   Adjustable v = getVAdjustable();
 385: 
 386:   if (h != null)
 387:     h.setValue(x);
 388:   if (v != null)
 389:     v.setValue(y);
 390: 
 391:   ScrollPanePeer spp = (ScrollPanePeer)getPeer();
 392:   if (spp != null)
 393:     spp.setScrollPosition(x, y);
 394: }
 395: 
 396: /*************************************************************************/
 397: 
 398: /**
 399:   * Notifies this object that it should create its native peer.
 400:   */
 401: public void
 402: addNotify()
 403: {
 404:   if (peer != null)
 405:     return;
 406: 
 407:   setPeer((ComponentPeer)getToolkit().createScrollPane(this));
 408:   super.addNotify();
 409: 
 410:   Component[] list = getComponents();
 411:   if (list != null && list.length > 0 && ! (list[0] instanceof Panel))
 412:   {
 413:     Panel panel = new Panel();
 414:     panel.setLayout(new BorderLayout());
 415:     panel.add(list[0], BorderLayout.CENTER);
 416:     add(panel);
 417:   }
 418: }
 419: 
 420: /*************************************************************************/
 421: 
 422: /**
 423:   * Notifies this object that it should destroy its native peers.
 424:   */
 425: public void
 426: removeNotify()
 427: {
 428:   super.removeNotify();
 429: }
 430: 
 431: /*************************************************************************/
 432: 
 433: /**
 434:   * Adds the specified child component to this container.  A 
 435:   * <code>ScrollPane</code> can have at most one child, so if a second
 436:   * one is added, then first one is removed.
 437:   *
 438:   * @param component The component to add to this container.
 439:   * @param constraints A list of layout constraints for this object.
 440:   * @param index The index at which to add the child, which is ignored
 441:   * in this implementation.
 442:   */
 443:   protected final void addImpl (Component component, Object constraints,
 444:                 int index)
 445: {
 446:   Component[] list = getComponents();
 447:   if ((list != null) && (list.length > 0))
 448:     remove(list[0]);
 449: 
 450:   super.addImpl(component, constraints, -1);
 451: 
 452:   doLayout();
 453: }
 454: 
 455: /*************************************************************************/
 456: 
 457: /**
 458:   * Lays out this component.  This consists of resizing the sole child
 459:   * component to its perferred size.
 460:   */
 461: public void
 462: doLayout()
 463: {
 464:   layout ();
 465: }
 466: 
 467: /*************************************************************************/
 468: 
 469: /**
 470:   * Lays out this component.  This consists of resizing the sole child
 471:   * component to its perferred size.
 472:   *
 473:   * @deprecated This method is deprecated in favor of
 474:   * <code>doLayout()</code>.
 475:   */
 476: public void
 477: layout()
 478: {
 479:   Component[] list = getComponents ();
 480:   if ((list != null) && (list.length > 0))
 481:     {
 482:       Dimension dim = list[0].getPreferredSize ();
 483:       Dimension vp = getViewportSize ();
 484: 
 485:       if (dim.width < vp.width)
 486:     dim.width = vp.width;
 487: 
 488:       if (dim.height < vp.height)
 489:     dim.height = vp.height;
 490: 
 491:       ScrollPanePeer peer = (ScrollPanePeer) getPeer ();
 492:       if (peer != null)
 493:     peer.childResized (dim.width, dim.height);
 494: 
 495:       list[0].setSize (dim);
 496: 
 497:       Point p = getScrollPosition ();
 498:       if (p.x > dim.width)
 499:         p.x = dim.width;
 500:       if (p.y > dim.height)
 501:         p.y = dim.height;
 502: 
 503:       setScrollPosition (p);
 504:     }
 505: }
 506: 
 507: /*************************************************************************/
 508: 
 509: /**
 510:   * This method overrides its superclass method to ensure no layout
 511:   * manager is set for this container.  <code>ScrollPane</code>'s do
 512:   * not have layout managers.
 513:   *
 514:   * @param layoutManager Ignored
 515:   */
 516: public final void
 517: setLayout(LayoutManager layoutManager)
 518: {
 519:   return;
 520: }
 521: 
 522: /*************************************************************************/
 523: 
 524: /**
 525:   * Prints all of the components in this container.
 526:   *
 527:   * @param graphics The desired graphics context for printing.
 528:   */
 529: public void
 530: printComponents(Graphics graphics)
 531: {
 532:   super.printComponents(graphics);
 533: }
 534: 
 535: /*************************************************************************/
 536: 
 537: /**
 538:   * Returns a debug string for this object.
 539:   *
 540:   * @return A debug string for this object.
 541:   */
 542: public String
 543: paramString()
 544: {
 545:   Insets insets = getInsets();
 546:   return getName() + ","
 547:          + getX() + ","
 548:          + getY() + ","
 549:          + getWidth() + "x" + getHeight() + ","
 550:          + "ScrollPosition=(" + scrollPosition.getX() + "," 
 551:                               + scrollPosition.getY() + "),"
 552:          + "Insets=(" + insets.top + ","
 553:                       + insets.left + ","
 554:                       + insets.bottom + ","
 555:                       + insets.right + "),"
 556:          + "ScrollbarDisplayPolicy=" + getScrollbarDisplayPolicy() + ","
 557:          + "wheelScrollingEnabled=" + isWheelScrollingEnabled();
 558: }
 559: 
 560:   /**
 561:    * Tells whether or not an event is enabled.
 562:    *
 563:    * @since 1.4
 564:    */
 565:   protected boolean eventTypeEnabled (int type)
 566:   {
 567:     if (type == MouseEvent.MOUSE_WHEEL)
 568:       return wheelScrollingEnabled;
 569: 
 570:     return super.eventTypeEnabled (type);
 571:   }
 572: 
 573:   /**
 574:    * Tells whether or not wheel scrolling is enabled.
 575:    *
 576:    * @since 1.4
 577:    */
 578:   public boolean isWheelScrollingEnabled ()
 579:   {
 580:     return wheelScrollingEnabled;
 581:   }
 582: 
 583:   /**
 584:    * Enables/disables wheel scrolling.
 585:    *
 586:    * @since 1.4
 587:    */
 588:   public void setWheelScrollingEnabled (boolean enable)
 589:   {
 590:     wheelScrollingEnabled = enable;
 591:   }
 592:   
 593:   protected class AccessibleAWTScrollPane extends AccessibleAWTContainer
 594:   {
 595:     private static final long serialVersionUID = 6100703663886637L;
 596: 
 597:     public AccessibleRole getAccessibleRole()
 598:     {
 599:       return AccessibleRole.SCROLL_PANE;
 600:     }
 601:   }
 602: 
 603:   /**
 604:    * Gets the AccessibleContext associated with this <code>ScrollPane</code>.
 605:    * The context is created, if necessary.
 606:    *
 607:    * @return the associated context
 608:    */
 609:   public AccessibleContext getAccessibleContext()
 610:   {
 611:     /* Create the context if this is the first request */
 612:     if (accessibleContext == null)
 613:       accessibleContext = new AccessibleAWTScrollPane();
 614:     return accessibleContext;
 615:   }
 616: } // class ScrollPane