GNU Classpath (0.20) | |
Frames | No Frames |
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
GNU Classpath (0.20) |