ScrollPane.java revision 12194:4a9eff2768ce
1246853Sdes/* 2246853Sdes * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. 3246853Sdes * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4246853Sdes * 5246853Sdes * This code is free software; you can redistribute it and/or modify it 6246853Sdes * under the terms of the GNU General Public License version 2 only, as 7246853Sdes * published by the Free Software Foundation. Oracle designates this 8246853Sdes * particular file as subject to the "Classpath" exception as provided 9246853Sdes * by Oracle in the LICENSE file that accompanied this code. 10246853Sdes * 11246853Sdes * This code is distributed in the hope that it will be useful, but WITHOUT 12246853Sdes * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13246853Sdes * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14246853Sdes * version 2 for more details (a copy is included in the LICENSE file that 15246853Sdes * accompanied this code). 16246853Sdes * 17246853Sdes * You should have received a copy of the GNU General Public License version 18246853Sdes * 2 along with this work; if not, write to the Free Software Foundation, 19246853Sdes * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20246853Sdes * 21246853Sdes * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22246853Sdes * or visit www.oracle.com if you need additional information or have any 23246853Sdes * questions. 24246853Sdes */ 25246853Sdespackage java.awt; 26246853Sdes 27246853Sdesimport java.awt.peer.ScrollPanePeer; 28246853Sdesimport java.awt.event.*; 29246853Sdesimport javax.accessibility.*; 30246854Sdesimport sun.awt.ScrollPaneWheelScroller; 31246854Sdesimport sun.awt.SunToolkit; 32246853Sdes 33246853Sdesimport java.beans.ConstructorProperties; 34246853Sdesimport java.beans.Transient; 35246853Sdesimport java.io.ObjectInputStream; 36246853Sdesimport java.io.ObjectOutputStream; 37246853Sdesimport java.io.IOException; 38246853Sdes 39246853Sdes/** 40246853Sdes * A container class which implements automatic horizontal and/or 41246853Sdes * vertical scrolling for a single child component. The display 42246853Sdes * policy for the scrollbars can be set to: 43246853Sdes * <OL> 44246853Sdes * <LI>as needed: scrollbars created and shown only when needed by scrollpane 45246853Sdes * <LI>always: scrollbars created and always shown by the scrollpane 46246853Sdes * <LI>never: scrollbars never created or shown by the scrollpane 47246853Sdes * </OL> 48246853Sdes * <P> 49246853Sdes * The state of the horizontal and vertical scrollbars is represented 50246853Sdes * by two <code>ScrollPaneAdjustable</code> objects (one for each 51246853Sdes * dimension) which implement the <code>Adjustable</code> interface. 52246853Sdes * The API provides methods to access those objects such that the 53246853Sdes * attributes on the Adjustable object (such as unitIncrement, value, 54246853Sdes * etc.) can be manipulated. 55246853Sdes * <P> 56246853Sdes * Certain adjustable properties (minimum, maximum, blockIncrement, 57246853Sdes * and visibleAmount) are set internally by the scrollpane in accordance 58246853Sdes * with the geometry of the scrollpane and its child and these should 59246853Sdes * not be set by programs using the scrollpane. 60246853Sdes * <P> 61246853Sdes * If the scrollbar display policy is defined as "never", then the 62246853Sdes * scrollpane can still be programmatically scrolled using the 63246853Sdes * setScrollPosition() method and the scrollpane will move and clip 64246853Sdes * the child's contents appropriately. This policy is useful if the 65246853Sdes * program needs to create and manage its own adjustable controls. 66246853Sdes * <P> 67246853Sdes * The placement of the scrollbars is controlled by platform-specific 68246853Sdes * properties set by the user outside of the program. 69246853Sdes * <P> 70246853Sdes * The initial size of this container is set to 100x100, but can 71246853Sdes * be reset using setSize(). 72246853Sdes * <P> 73246853Sdes * Scrolling with the wheel on a wheel-equipped mouse is enabled by default. 74246853Sdes * This can be disabled using <code>setWheelScrollingEnabled</code>. 75246853Sdes * Wheel scrolling can be customized by setting the block and 76246853Sdes * unit increment of the horizontal and vertical Adjustables. 77246853Sdes * For information on how mouse wheel events are dispatched, see 78246853Sdes * the class description for {@link MouseWheelEvent}. 79246853Sdes * <P> 80246853Sdes * Insets are used to define any space used by scrollbars and any 81246853Sdes * borders created by the scroll pane. getInsets() can be used 82246853Sdes * to get the current value for the insets. If the value of 83246853Sdes * scrollbarsAlwaysVisible is false, then the value of the insets 84246853Sdes * will change dynamically depending on whether the scrollbars are 85246853Sdes * currently visible or not. 86246853Sdes * 87246853Sdes * @author Tom Ball 88246853Sdes * @author Amy Fowler 89246853Sdes * @author Tim Prinzing 90246853Sdes */ 91246853Sdespublic class ScrollPane extends Container implements Accessible { 92246853Sdes 93246853Sdes 94246853Sdes /** 95246853Sdes * Initialize JNI field and method IDs 96246853Sdes */ 97246853Sdes private static native void initIDs(); 98246853Sdes 99246853Sdes static { 100246853Sdes /* ensure that the necessary native libraries are loaded */ 101246853Sdes Toolkit.loadLibraries(); 102246853Sdes if (!GraphicsEnvironment.isHeadless()) { 103246853Sdes initIDs(); 104246853Sdes } 105246853Sdes } 106246853Sdes 107246853Sdes /** 108246853Sdes * Specifies that horizontal/vertical scrollbar should be shown 109246853Sdes * only when the size of the child exceeds the size of the scrollpane 110246853Sdes * in the horizontal/vertical dimension. 111246853Sdes */ 112246853Sdes public static final int SCROLLBARS_AS_NEEDED = 0; 113246853Sdes 114246853Sdes /** 115246853Sdes * Specifies that horizontal/vertical scrollbars should always be 116246853Sdes * shown regardless of the respective sizes of the scrollpane and child. 117246853Sdes */ 118246853Sdes public static final int SCROLLBARS_ALWAYS = 1; 119246853Sdes 120246853Sdes /** 121246853Sdes * Specifies that horizontal/vertical scrollbars should never be shown 122246853Sdes * regardless of the respective sizes of the scrollpane and child. 123246853Sdes */ 124246853Sdes public static final int SCROLLBARS_NEVER = 2; 125246853Sdes 126246853Sdes /** 127246853Sdes * There are 3 ways in which a scroll bar can be displayed. 128246853Sdes * This integer will represent one of these 3 displays - 129246853Sdes * (SCROLLBARS_ALWAYS, SCROLLBARS_AS_NEEDED, SCROLLBARS_NEVER) 130246853Sdes * 131246853Sdes * @serial 132246853Sdes * @see #getScrollbarDisplayPolicy 133246853Sdes */ 134246853Sdes private int scrollbarDisplayPolicy; 135246853Sdes 136246853Sdes /** 137246853Sdes * An adjustable vertical scrollbar. 138246853Sdes * It is important to note that you must <em>NOT</em> call 3 139246853Sdes * <code>Adjustable</code> methods, namely: 140246853Sdes * <code>setMinimum()</code>, <code>setMaximum()</code>, 141246853Sdes * <code>setVisibleAmount()</code>. 142246853Sdes * 143246853Sdes * @serial 144246853Sdes * @see #getVAdjustable 145246853Sdes */ 146246853Sdes private ScrollPaneAdjustable vAdjustable; 147246853Sdes 148246853Sdes /** 149246853Sdes * An adjustable horizontal scrollbar. 150246853Sdes * It is important to note that you must <em>NOT</em> call 3 151246853Sdes * <code>Adjustable</code> methods, namely: 152246853Sdes * <code>setMinimum()</code>, <code>setMaximum()</code>, 153246853Sdes * <code>setVisibleAmount()</code>. 154246853Sdes * 155246853Sdes * @serial 156246853Sdes * @see #getHAdjustable 157246853Sdes */ 158246853Sdes private ScrollPaneAdjustable hAdjustable; 159246853Sdes 160246853Sdes private static final String base = "scrollpane"; 161246853Sdes private static int nameCounter = 0; 162246853Sdes 163246853Sdes private static final boolean defaultWheelScroll = true; 164246853Sdes 165246853Sdes /** 166246853Sdes * Indicates whether or not scrolling should take place when a 167246853Sdes * MouseWheelEvent is received. 168246853Sdes * 169246853Sdes * @serial 170246853Sdes * @since 1.4 171246853Sdes */ 172246853Sdes private boolean wheelScrollingEnabled = defaultWheelScroll; 173246853Sdes 174246853Sdes /* 175246853Sdes * JDK 1.1 serialVersionUID 176246853Sdes */ 177246853Sdes private static final long serialVersionUID = 7956609840827222915L; 178246853Sdes 179246853Sdes /** 180246853Sdes * Create a new scrollpane container with a scrollbar display 181246853Sdes * policy of "as needed". 182246853Sdes * @throws HeadlessException if GraphicsEnvironment.isHeadless() 183246853Sdes * returns true 184246853Sdes * @see java.awt.GraphicsEnvironment#isHeadless 185246853Sdes */ 186246853Sdes public ScrollPane() throws HeadlessException { 187246853Sdes this(SCROLLBARS_AS_NEEDED); 188246853Sdes } 189246853Sdes 190246853Sdes /** 191246853Sdes * Create a new scrollpane container. 192246853Sdes * @param scrollbarDisplayPolicy policy for when scrollbars should be shown 193246853Sdes * @throws IllegalArgumentException if the specified scrollbar 194246853Sdes * display policy is invalid 195246853Sdes * @throws HeadlessException if GraphicsEnvironment.isHeadless() 196246853Sdes * returns true 197246853Sdes * @see java.awt.GraphicsEnvironment#isHeadless 198246853Sdes */ 199246853Sdes @ConstructorProperties({"scrollbarDisplayPolicy"}) 200246853Sdes public ScrollPane(int scrollbarDisplayPolicy) throws HeadlessException { 201246853Sdes GraphicsEnvironment.checkHeadless(); 202246853Sdes this.layoutMgr = null; 203246853Sdes this.width = 100; 204246853Sdes this.height = 100; 205246853Sdes switch (scrollbarDisplayPolicy) { 206246853Sdes case SCROLLBARS_NEVER: 207246853Sdes case SCROLLBARS_AS_NEEDED: 208246853Sdes case SCROLLBARS_ALWAYS: 209246853Sdes this.scrollbarDisplayPolicy = scrollbarDisplayPolicy; 210246853Sdes break; 211246853Sdes default: 212246853Sdes throw new IllegalArgumentException("illegal scrollbar display policy"); 213246853Sdes } 214246853Sdes 215246853Sdes vAdjustable = new ScrollPaneAdjustable(this, new PeerFixer(this), 216246853Sdes Adjustable.VERTICAL); 217246853Sdes hAdjustable = new ScrollPaneAdjustable(this, new PeerFixer(this), 218246853Sdes Adjustable.HORIZONTAL); 219246853Sdes setWheelScrollingEnabled(defaultWheelScroll); 220246853Sdes } 221246853Sdes 222246853Sdes /** 223246853Sdes * Construct a name for this component. Called by getName() when the 224246853Sdes * name is null. 225246853Sdes */ 226246853Sdes String constructComponentName() { 227246853Sdes synchronized (ScrollPane.class) { 228246853Sdes return base + nameCounter++; 229246853Sdes } 230246853Sdes } 231246853Sdes 232246853Sdes // The scrollpane won't work with a windowless child... it assumes 233246853Sdes // it is moving a child window around so the windowless child is 234246853Sdes // wrapped with a window. 235246853Sdes private void addToPanel(Component comp, Object constraints, int index) { 236246853Sdes Panel child = new Panel(); 237246853Sdes child.setLayout(new BorderLayout()); 238246853Sdes child.add(comp); 239246853Sdes super.addImpl(child, constraints, index); 240246853Sdes validate(); 241246853Sdes } 242246853Sdes 243246853Sdes /** 244246853Sdes * Adds the specified component to this scroll pane container. 245246853Sdes * If the scroll pane has an existing child component, that 246246853Sdes * component is removed and the new one is added. 247246853Sdes * @param comp the component to be added 248246853Sdes * @param constraints not applicable 249246853Sdes * @param index position of child component (must be <= 0) 250246853Sdes */ 251246853Sdes protected final void addImpl(Component comp, Object constraints, int index) { 252246853Sdes synchronized (getTreeLock()) { 253246853Sdes if (getComponentCount() > 0) { 254246853Sdes remove(0); 255246853Sdes } 256246853Sdes if (index > 0) { 257246853Sdes throw new IllegalArgumentException("position greater than 0"); 258246853Sdes } 259246853Sdes 260246853Sdes if (!SunToolkit.isLightweightOrUnknown(comp)) { 261246853Sdes super.addImpl(comp, constraints, index); 262246853Sdes } else { 263246853Sdes addToPanel(comp, constraints, index); 264246853Sdes } 265246853Sdes } 266246853Sdes } 267246853Sdes 268246853Sdes /** 269246853Sdes * Returns the display policy for the scrollbars. 270246853Sdes * @return the display policy for the scrollbars 271246854Sdes */ 272246854Sdes public int getScrollbarDisplayPolicy() { 273246853Sdes return scrollbarDisplayPolicy; 274246853Sdes } 275246853Sdes 276246853Sdes /** 277246853Sdes * Returns the current size of the scroll pane's view port. 278246853Sdes * @return the size of the view port in pixels 279246853Sdes */ 280246853Sdes public Dimension getViewportSize() { 281246853Sdes Insets i = getInsets(); 282246853Sdes return new Dimension(width - i.right - i.left, 283246853Sdes height - i.top - i.bottom); 284246853Sdes } 285246853Sdes 286246853Sdes /** 287246853Sdes * Returns the height that would be occupied by a horizontal 288246853Sdes * scrollbar, which is independent of whether it is currently 289246853Sdes * displayed by the scroll pane or not. 290246853Sdes * @return the height of a horizontal scrollbar in pixels 291246853Sdes */ 292246853Sdes public int getHScrollbarHeight() { 293246853Sdes int h = 0; 294246853Sdes if (scrollbarDisplayPolicy != SCROLLBARS_NEVER) { 295246853Sdes ScrollPanePeer peer = (ScrollPanePeer)this.peer; 296246853Sdes if (peer != null) { 297246853Sdes h = peer.getHScrollbarHeight(); 298246853Sdes } 299246853Sdes } 300246853Sdes return h; 301246853Sdes } 302246853Sdes 303246853Sdes /** 304246853Sdes * Returns the width that would be occupied by a vertical 305246853Sdes * scrollbar, which is independent of whether it is currently 306246853Sdes * displayed by the scroll pane or not. 307246853Sdes * @return the width of a vertical scrollbar in pixels 308246853Sdes */ 309246853Sdes public int getVScrollbarWidth() { 310246853Sdes int w = 0; 311246853Sdes if (scrollbarDisplayPolicy != SCROLLBARS_NEVER) { 312246853Sdes ScrollPanePeer peer = (ScrollPanePeer)this.peer; 313246853Sdes if (peer != null) { 314246853Sdes w = peer.getVScrollbarWidth(); 315246853Sdes } 316246853Sdes } 317246853Sdes return w; 318246853Sdes } 319246853Sdes 320246853Sdes /** 321246853Sdes * Returns the <code>ScrollPaneAdjustable</code> object which 322246853Sdes * represents the state of the vertical scrollbar. 323246853Sdes * The declared return type of this method is 324246853Sdes * <code>Adjustable</code> to maintain backward compatibility. 325246853Sdes * 326246853Sdes * @see java.awt.ScrollPaneAdjustable 327246853Sdes * @return the vertical scrollbar state 328249453Sdes */ 329246853Sdes public Adjustable getVAdjustable() { 330246853Sdes return vAdjustable; 331246853Sdes } 332246853Sdes 333246853Sdes /** 334246853Sdes * Returns the <code>ScrollPaneAdjustable</code> object which 335246853Sdes * represents the state of the horizontal scrollbar. 336246853Sdes * The declared return type of this method is 337246853Sdes * <code>Adjustable</code> to maintain backward compatibility. 338246853Sdes * 339246853Sdes * @see java.awt.ScrollPaneAdjustable 340246853Sdes * @return the horizontal scrollbar state 341246853Sdes */ 342246853Sdes public Adjustable getHAdjustable() { 343246853Sdes return hAdjustable; 344246853Sdes } 345246853Sdes 346249453Sdes /** 347249453Sdes * Scrolls to the specified position within the child component. 348246853Sdes * A call to this method is only valid if the scroll pane contains 349246853Sdes * a child. Specifying a position outside of the legal scrolling bounds 350246853Sdes * of the child will scroll to the closest legal position. 351246853Sdes * Legal bounds are defined to be the rectangle: 352246853Sdes * x = 0, y = 0, width = (child width - view port width), 353246853Sdes * height = (child height - view port height). 354246853Sdes * This is a convenience method which interfaces with the Adjustable 355246853Sdes * objects which represent the state of the scrollbars. 356246853Sdes * @param x the x position to scroll to 357246853Sdes * @param y the y position to scroll to 358246853Sdes * @throws NullPointerException if the scrollpane does not contain 359246853Sdes * a child 360246853Sdes */ 361249453Sdes public void setScrollPosition(int x, int y) { 362249453Sdes synchronized (getTreeLock()) { 363249453Sdes if (getComponentCount()==0) { 364249453Sdes throw new NullPointerException("child is null"); 365249453Sdes } 366249453Sdes hAdjustable.setValue(x); 367249453Sdes vAdjustable.setValue(y); 368249453Sdes } 369249453Sdes } 370249453Sdes 371249453Sdes /** 372249453Sdes * Scrolls to the specified position within the child component. 373249453Sdes * A call to this method is only valid if the scroll pane contains 374249453Sdes * a child and the specified position is within legal scrolling bounds 375249453Sdes * of the child. Specifying a position outside of the legal scrolling 376249453Sdes * bounds of the child will scroll to the closest legal position. 377249453Sdes * Legal bounds are defined to be the rectangle: 378249453Sdes * x = 0, y = 0, width = (child width - view port width), 379249453Sdes * height = (child height - view port height). 380249453Sdes * This is a convenience method which interfaces with the Adjustable 381249453Sdes * objects which represent the state of the scrollbars. 382249453Sdes * @param p the Point representing the position to scroll to 383249453Sdes * @throws NullPointerException if {@code p} is {@code null} 384249453Sdes */ 385246853Sdes public void setScrollPosition(Point p) { 386246853Sdes setScrollPosition(p.x, p.y); 387246853Sdes } 388246853Sdes 389246853Sdes /** 390246853Sdes * Returns the current x,y position within the child which is displayed 391246853Sdes * at the 0,0 location of the scrolled panel's view port. 392246853Sdes * This is a convenience method which interfaces with the adjustable 393 * objects which represent the state of the scrollbars. 394 * @return the coordinate position for the current scroll position 395 * @throws NullPointerException if the scrollpane does not contain 396 * a child 397 */ 398 @Transient 399 public Point getScrollPosition() { 400 synchronized (getTreeLock()) { 401 if (getComponentCount()==0) { 402 throw new NullPointerException("child is null"); 403 } 404 return new Point(hAdjustable.getValue(), vAdjustable.getValue()); 405 } 406 } 407 408 /** 409 * Sets the layout manager for this container. This method is 410 * overridden to prevent the layout mgr from being set. 411 * @param mgr the specified layout manager 412 */ 413 public final void setLayout(LayoutManager mgr) { 414 throw new AWTError("ScrollPane controls layout"); 415 } 416 417 /** 418 * Lays out this container by resizing its child to its preferred size. 419 * If the new preferred size of the child causes the current scroll 420 * position to be invalid, the scroll position is set to the closest 421 * valid position. 422 * 423 * @see Component#validate 424 */ 425 public void doLayout() { 426 layout(); 427 } 428 429 /** 430 * Determine the size to allocate the child component. 431 * If the viewport area is bigger than the preferred size 432 * of the child then the child is allocated enough 433 * to fill the viewport, otherwise the child is given 434 * it's preferred size. 435 */ 436 Dimension calculateChildSize() { 437 // 438 // calculate the view size, accounting for border but not scrollbars 439 // - don't use right/bottom insets since they vary depending 440 // on whether or not scrollbars were displayed on last resize 441 // 442 Dimension size = getSize(); 443 Insets insets = getInsets(); 444 int viewWidth = size.width - insets.left*2; 445 int viewHeight = size.height - insets.top*2; 446 447 // 448 // determine whether or not horz or vert scrollbars will be displayed 449 // 450 boolean vbarOn; 451 boolean hbarOn; 452 Component child = getComponent(0); 453 Dimension childSize = new Dimension(child.getPreferredSize()); 454 455 if (scrollbarDisplayPolicy == SCROLLBARS_AS_NEEDED) { 456 vbarOn = childSize.height > viewHeight; 457 hbarOn = childSize.width > viewWidth; 458 } else if (scrollbarDisplayPolicy == SCROLLBARS_ALWAYS) { 459 vbarOn = hbarOn = true; 460 } else { // SCROLLBARS_NEVER 461 vbarOn = hbarOn = false; 462 } 463 464 // 465 // adjust predicted view size to account for scrollbars 466 // 467 int vbarWidth = getVScrollbarWidth(); 468 int hbarHeight = getHScrollbarHeight(); 469 if (vbarOn) { 470 viewWidth -= vbarWidth; 471 } 472 if(hbarOn) { 473 viewHeight -= hbarHeight; 474 } 475 476 // 477 // if child is smaller than view, size it up 478 // 479 if (childSize.width < viewWidth) { 480 childSize.width = viewWidth; 481 } 482 if (childSize.height < viewHeight) { 483 childSize.height = viewHeight; 484 } 485 486 return childSize; 487 } 488 489 /** 490 * @deprecated As of JDK version 1.1, 491 * replaced by <code>doLayout()</code>. 492 */ 493 @Deprecated 494 public void layout() { 495 if (getComponentCount()==0) { 496 return; 497 } 498 Component c = getComponent(0); 499 Point p = getScrollPosition(); 500 Dimension cs = calculateChildSize(); 501 Dimension vs = getViewportSize(); 502 503 c.reshape(- p.x, - p.y, cs.width, cs.height); 504 ScrollPanePeer peer = (ScrollPanePeer)this.peer; 505 if (peer != null) { 506 peer.childResized(cs.width, cs.height); 507 } 508 509 // update adjustables... the viewport size may have changed 510 // with the scrollbars coming or going so the viewport size 511 // is updated before the adjustables. 512 vs = getViewportSize(); 513 hAdjustable.setSpan(0, cs.width, vs.width); 514 vAdjustable.setSpan(0, cs.height, vs.height); 515 } 516 517 /** 518 * Prints the component in this scroll pane. 519 * @param g the specified Graphics window 520 * @see Component#print 521 * @see Component#printAll 522 */ 523 public void printComponents(Graphics g) { 524 if (getComponentCount()==0) { 525 return; 526 } 527 Component c = getComponent(0); 528 Point p = c.getLocation(); 529 Dimension vs = getViewportSize(); 530 Insets i = getInsets(); 531 532 Graphics cg = g.create(); 533 try { 534 cg.clipRect(i.left, i.top, vs.width, vs.height); 535 cg.translate(p.x, p.y); 536 c.printAll(cg); 537 } finally { 538 cg.dispose(); 539 } 540 } 541 542 /** 543 * Creates the scroll pane's peer. 544 */ 545 public void addNotify() { 546 synchronized (getTreeLock()) { 547 548 int vAdjustableValue = 0; 549 int hAdjustableValue = 0; 550 551 // Bug 4124460. Save the current adjustable values, 552 // so they can be restored after addnotify. Set the 553 // adjustables to 0, to prevent crashes for possible 554 // negative values. 555 if (getComponentCount() > 0) { 556 vAdjustableValue = vAdjustable.getValue(); 557 hAdjustableValue = hAdjustable.getValue(); 558 vAdjustable.setValue(0); 559 hAdjustable.setValue(0); 560 } 561 562 if (peer == null) 563 peer = getComponentFactory().createScrollPane(this); 564 super.addNotify(); 565 566 // Bug 4124460. Restore the adjustable values. 567 if (getComponentCount() > 0) { 568 vAdjustable.setValue(vAdjustableValue); 569 hAdjustable.setValue(hAdjustableValue); 570 } 571 } 572 } 573 574 /** 575 * Returns a string representing the state of this 576 * <code>ScrollPane</code>. This 577 * method is intended to be used only for debugging purposes, and the 578 * content and format of the returned string may vary between 579 * implementations. The returned string may be empty but may not be 580 * <code>null</code>. 581 * 582 * @return the parameter string of this scroll pane 583 */ 584 public String paramString() { 585 String sdpStr; 586 switch (scrollbarDisplayPolicy) { 587 case SCROLLBARS_AS_NEEDED: 588 sdpStr = "as-needed"; 589 break; 590 case SCROLLBARS_ALWAYS: 591 sdpStr = "always"; 592 break; 593 case SCROLLBARS_NEVER: 594 sdpStr = "never"; 595 break; 596 default: 597 sdpStr = "invalid display policy"; 598 } 599 Point p = (getComponentCount()>0)? getScrollPosition() : new Point(0,0); 600 Insets i = getInsets(); 601 return super.paramString()+",ScrollPosition=("+p.x+","+p.y+")"+ 602 ",Insets=("+i.top+","+i.left+","+i.bottom+","+i.right+")"+ 603 ",ScrollbarDisplayPolicy="+sdpStr+ 604 ",wheelScrollingEnabled="+isWheelScrollingEnabled(); 605 } 606 607 void autoProcessMouseWheel(MouseWheelEvent e) { 608 processMouseWheelEvent(e); 609 } 610 611 /** 612 * Process mouse wheel events that are delivered to this 613 * <code>ScrollPane</code> by scrolling an appropriate amount. 614 * <p>Note that if the event parameter is <code>null</code> 615 * the behavior is unspecified and may result in an 616 * exception. 617 * 618 * @param e the mouse wheel event 619 * @since 1.4 620 */ 621 protected void processMouseWheelEvent(MouseWheelEvent e) { 622 if (isWheelScrollingEnabled()) { 623 ScrollPaneWheelScroller.handleWheelScrolling(this, e); 624 e.consume(); 625 } 626 super.processMouseWheelEvent(e); 627 } 628 629 /** 630 * If wheel scrolling is enabled, we return true for MouseWheelEvents 631 * @since 1.4 632 */ 633 protected boolean eventTypeEnabled(int type) { 634 if (type == MouseEvent.MOUSE_WHEEL && isWheelScrollingEnabled()) { 635 return true; 636 } 637 else { 638 return super.eventTypeEnabled(type); 639 } 640 } 641 642 /** 643 * Enables/disables scrolling in response to movement of the mouse wheel. 644 * Wheel scrolling is enabled by default. 645 * 646 * @param handleWheel <code>true</code> if scrolling should be done 647 * automatically for a MouseWheelEvent, 648 * <code>false</code> otherwise. 649 * @see #isWheelScrollingEnabled 650 * @see java.awt.event.MouseWheelEvent 651 * @see java.awt.event.MouseWheelListener 652 * @since 1.4 653 */ 654 public void setWheelScrollingEnabled(boolean handleWheel) { 655 wheelScrollingEnabled = handleWheel; 656 } 657 658 /** 659 * Indicates whether or not scrolling will take place in response to 660 * the mouse wheel. Wheel scrolling is enabled by default. 661 * 662 * @return {@code true} if the wheel scrolling enabled; 663 * otherwise {@code false} 664 * 665 * @see #setWheelScrollingEnabled(boolean) 666 * @since 1.4 667 */ 668 public boolean isWheelScrollingEnabled() { 669 return wheelScrollingEnabled; 670 } 671 672 673 /** 674 * Writes default serializable fields to stream. 675 */ 676 private void writeObject(ObjectOutputStream s) throws IOException { 677 // 4352819: We only need this degenerate writeObject to make 678 // it safe for future versions of this class to write optional 679 // data to the stream. 680 s.defaultWriteObject(); 681 } 682 683 /** 684 * Reads default serializable fields to stream. 685 * @exception HeadlessException if 686 * <code>GraphicsEnvironment.isHeadless()</code> returns 687 * <code>true</code> 688 * @see java.awt.GraphicsEnvironment#isHeadless 689 */ 690 private void readObject(ObjectInputStream s) 691 throws ClassNotFoundException, IOException, HeadlessException 692 { 693 GraphicsEnvironment.checkHeadless(); 694 // 4352819: Gotcha! Cannot use s.defaultReadObject here and 695 // then continue with reading optional data. Use GetField instead. 696 ObjectInputStream.GetField f = s.readFields(); 697 698 // Old fields 699 scrollbarDisplayPolicy = f.get("scrollbarDisplayPolicy", 700 SCROLLBARS_AS_NEEDED); 701 hAdjustable = (ScrollPaneAdjustable)f.get("hAdjustable", null); 702 vAdjustable = (ScrollPaneAdjustable)f.get("vAdjustable", null); 703 704 // Since 1.4 705 wheelScrollingEnabled = f.get("wheelScrollingEnabled", 706 defaultWheelScroll); 707 708// // Note to future maintainers 709// if (f.defaulted("wheelScrollingEnabled")) { 710// // We are reading pre-1.4 stream that doesn't have 711// // optional data, not even the TC_ENDBLOCKDATA marker. 712// // Reading anything after this point is unsafe as we will 713// // read unrelated objects further down the stream (4352819). 714// } 715// else { 716// // Reading data from 1.4 or later, it's ok to try to read 717// // optional data as OptionalDataException with eof == true 718// // will be correctly reported 719// } 720 } 721 722 class PeerFixer implements AdjustmentListener, java.io.Serializable 723 { 724 private static final long serialVersionUID = 1043664721353696630L; 725 726 PeerFixer(ScrollPane scroller) { 727 this.scroller = scroller; 728 } 729 730 /** 731 * Invoked when the value of the adjustable has changed. 732 */ 733 @SuppressWarnings("deprecation") 734 public void adjustmentValueChanged(AdjustmentEvent e) { 735 Adjustable adj = e.getAdjustable(); 736 int value = e.getValue(); 737 ScrollPanePeer peer = (ScrollPanePeer) scroller.peer; 738 if (peer != null) { 739 peer.setValue(adj, value); 740 } 741 742 Component c = scroller.getComponent(0); 743 switch(adj.getOrientation()) { 744 case Adjustable.VERTICAL: 745 c.move(c.getLocation().x, -(value)); 746 break; 747 case Adjustable.HORIZONTAL: 748 c.move(-(value), c.getLocation().y); 749 break; 750 default: 751 throw new IllegalArgumentException("Illegal adjustable orientation"); 752 } 753 } 754 755 private ScrollPane scroller; 756 } 757 758 759///////////////// 760// Accessibility support 761//////////////// 762 763 /** 764 * Gets the AccessibleContext associated with this ScrollPane. 765 * For scroll panes, the AccessibleContext takes the form of an 766 * AccessibleAWTScrollPane. 767 * A new AccessibleAWTScrollPane instance is created if necessary. 768 * 769 * @return an AccessibleAWTScrollPane that serves as the 770 * AccessibleContext of this ScrollPane 771 * @since 1.3 772 */ 773 public AccessibleContext getAccessibleContext() { 774 if (accessibleContext == null) { 775 accessibleContext = new AccessibleAWTScrollPane(); 776 } 777 return accessibleContext; 778 } 779 780 /** 781 * This class implements accessibility support for the 782 * <code>ScrollPane</code> class. It provides an implementation of the 783 * Java Accessibility API appropriate to scroll pane user-interface 784 * elements. 785 * @since 1.3 786 */ 787 protected class AccessibleAWTScrollPane extends AccessibleAWTContainer 788 { 789 /* 790 * JDK 1.3 serialVersionUID 791 */ 792 private static final long serialVersionUID = 6100703663886637L; 793 794 /** 795 * Get the role of this object. 796 * 797 * @return an instance of AccessibleRole describing the role of the 798 * object 799 * @see AccessibleRole 800 */ 801 public AccessibleRole getAccessibleRole() { 802 return AccessibleRole.SCROLL_PANE; 803 } 804 805 } // class AccessibleAWTScrollPane 806 807} 808 809/* 810 * In JDK 1.1.1, the pkg private class java.awt.PeerFixer was moved to 811 * become an inner class of ScrollPane, which broke serialization 812 * for ScrollPane objects using JDK 1.1. 813 * Instead of moving it back out here, which would break all JDK 1.1.x 814 * releases, we keep PeerFixer in both places. Because of the scoping rules, 815 * the PeerFixer that is used in ScrollPane will be the one that is the 816 * inner class. This pkg private PeerFixer class below will only be used 817 * if the Java 2 platform is used to deserialize ScrollPane objects that were serialized 818 * using JDK1.1 819 */ 820class PeerFixer implements AdjustmentListener, java.io.Serializable { 821 /* 822 * serialVersionUID 823 */ 824 private static final long serialVersionUID = 7051237413532574756L; 825 826 PeerFixer(ScrollPane scroller) { 827 this.scroller = scroller; 828 } 829 830 /** 831 * Invoked when the value of the adjustable has changed. 832 */ 833 @SuppressWarnings("deprecation") 834 public void adjustmentValueChanged(AdjustmentEvent e) { 835 Adjustable adj = e.getAdjustable(); 836 int value = e.getValue(); 837 ScrollPanePeer peer = (ScrollPanePeer) scroller.peer; 838 if (peer != null) { 839 peer.setValue(adj, value); 840 } 841 842 Component c = scroller.getComponent(0); 843 switch(adj.getOrientation()) { 844 case Adjustable.VERTICAL: 845 c.move(c.getLocation().x, -(value)); 846 break; 847 case Adjustable.HORIZONTAL: 848 c.move(-(value), c.getLocation().y); 849 break; 850 default: 851 throw new IllegalArgumentException("Illegal adjustable orientation"); 852 } 853 } 854 855 private ScrollPane scroller; 856} 857