1 /* 2 * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package java.awt; 26 27 import java.awt.peer.ScrollPanePeer; 28 import java.awt.event.*; 29 import javax.accessibility.*; 30 import sun.awt.ScrollPaneWheelScroller; 31 import sun.awt.SunToolkit; 32 33 import java.beans.ConstructorProperties; 34 import java.beans.Transient; 35 import java.io.ObjectInputStream; 36 import java.io.ObjectOutputStream; 37 import java.io.IOException; 38 39 /** 40 * A container class which implements automatic horizontal and/or 41 * vertical scrolling for a single child component. The display 42 * policy for the scrollbars can be set to: 43 * <OL> 44 * <LI>as needed: scrollbars created and shown only when needed by scrollpane 45 * <LI>always: scrollbars created and always shown by the scrollpane 46 * <LI>never: scrollbars never created or shown by the scrollpane 47 * </OL> 48 * <P> 49 * The state of the horizontal and vertical scrollbars is represented 50 * by two {@code ScrollPaneAdjustable} objects (one for each 51 * dimension) which implement the {@code Adjustable} interface. 52 * The API provides methods to access those objects such that the 53 * attributes on the Adjustable object (such as unitIncrement, value, 54 * etc.) can be manipulated. 55 * <P> 56 * Certain adjustable properties (minimum, maximum, blockIncrement, 57 * and visibleAmount) are set internally by the scrollpane in accordance 58 * with the geometry of the scrollpane and its child and these should 59 * not be set by programs using the scrollpane. 60 * <P> 61 * If the scrollbar display policy is defined as "never", then the 62 * scrollpane can still be programmatically scrolled using the 63 * setScrollPosition() method and the scrollpane will move and clip 64 * the child's contents appropriately. This policy is useful if the 65 * program needs to create and manage its own adjustable controls. 66 * <P> 67 * The placement of the scrollbars is controlled by platform-specific 68 * properties set by the user outside of the program. 69 * <P> 70 * The initial size of this container is set to 100x100, but can 71 * be reset using setSize(). 72 * <P> 73 * Scrolling with the wheel on a wheel-equipped mouse is enabled by default. 74 * This can be disabled using {@code setWheelScrollingEnabled}. 75 * Wheel scrolling can be customized by setting the block and 76 * unit increment of the horizontal and vertical Adjustables. 77 * For information on how mouse wheel events are dispatched, see 78 * the class description for {@link MouseWheelEvent}. 79 * <P> 80 * Insets are used to define any space used by scrollbars and any 81 * borders created by the scroll pane. getInsets() can be used 82 * to get the current value for the insets. If the value of 83 * scrollbarsAlwaysVisible is false, then the value of the insets 84 * will change dynamically depending on whether the scrollbars are 85 * currently visible or not. 86 * 87 * @author Tom Ball 88 * @author Amy Fowler 89 * @author Tim Prinzing 90 */ 91 public class ScrollPane extends Container implements Accessible { 92 93 94 /** 95 * Initialize JNI field and method IDs 96 */ initIDs()97 private static native void initIDs(); 98 99 static { 100 /* ensure that the necessary native libraries are loaded */ Toolkit.loadLibraries()101 Toolkit.loadLibraries(); 102 if (!GraphicsEnvironment.isHeadless()) { initIDs()103 initIDs(); 104 } 105 } 106 107 /** 108 * Specifies that horizontal/vertical scrollbar should be shown 109 * only when the size of the child exceeds the size of the scrollpane 110 * in the horizontal/vertical dimension. 111 */ 112 public static final int SCROLLBARS_AS_NEEDED = 0; 113 114 /** 115 * Specifies that horizontal/vertical scrollbars should always be 116 * shown regardless of the respective sizes of the scrollpane and child. 117 */ 118 public static final int SCROLLBARS_ALWAYS = 1; 119 120 /** 121 * Specifies that horizontal/vertical scrollbars should never be shown 122 * regardless of the respective sizes of the scrollpane and child. 123 */ 124 public static final int SCROLLBARS_NEVER = 2; 125 126 /** 127 * There are 3 ways in which a scroll bar can be displayed. 128 * This integer will represent one of these 3 displays - 129 * (SCROLLBARS_ALWAYS, SCROLLBARS_AS_NEEDED, SCROLLBARS_NEVER) 130 * 131 * @serial 132 * @see #getScrollbarDisplayPolicy 133 */ 134 private int scrollbarDisplayPolicy; 135 136 /** 137 * An adjustable vertical scrollbar. 138 * It is important to note that you must <em>NOT</em> call 3 139 * {@code Adjustable} methods, namely: 140 * {@code setMinimum()}, {@code setMaximum()}, 141 * {@code setVisibleAmount()}. 142 * 143 * @serial 144 * @see #getVAdjustable 145 */ 146 private ScrollPaneAdjustable vAdjustable; 147 148 /** 149 * An adjustable horizontal scrollbar. 150 * It is important to note that you must <em>NOT</em> call 3 151 * {@code Adjustable} methods, namely: 152 * {@code setMinimum()}, {@code setMaximum()}, 153 * {@code setVisibleAmount()}. 154 * 155 * @serial 156 * @see #getHAdjustable 157 */ 158 private ScrollPaneAdjustable hAdjustable; 159 160 private static final String base = "scrollpane"; 161 private static int nameCounter = 0; 162 163 private static final boolean defaultWheelScroll = true; 164 165 /** 166 * Indicates whether or not scrolling should take place when a 167 * MouseWheelEvent is received. 168 * 169 * @serial 170 * @since 1.4 171 */ 172 private boolean wheelScrollingEnabled = defaultWheelScroll; 173 174 /* 175 * JDK 1.1 serialVersionUID 176 */ 177 private static final long serialVersionUID = 7956609840827222915L; 178 179 /** 180 * Create a new scrollpane container with a scrollbar display 181 * policy of "as needed". 182 * @throws HeadlessException if GraphicsEnvironment.isHeadless() 183 * returns true 184 * @see java.awt.GraphicsEnvironment#isHeadless 185 */ ScrollPane()186 public ScrollPane() throws HeadlessException { 187 this(SCROLLBARS_AS_NEEDED); 188 } 189 190 /** 191 * Create a new scrollpane container. 192 * @param scrollbarDisplayPolicy policy for when scrollbars should be shown 193 * @throws IllegalArgumentException if the specified scrollbar 194 * display policy is invalid 195 * @throws HeadlessException if GraphicsEnvironment.isHeadless() 196 * returns true 197 * @see java.awt.GraphicsEnvironment#isHeadless 198 */ 199 @ConstructorProperties({"scrollbarDisplayPolicy"}) ScrollPane(int scrollbarDisplayPolicy)200 public ScrollPane(int scrollbarDisplayPolicy) throws HeadlessException { 201 GraphicsEnvironment.checkHeadless(); 202 this.layoutMgr = null; 203 this.width = 100; 204 this.height = 100; 205 switch (scrollbarDisplayPolicy) { 206 case SCROLLBARS_NEVER: 207 case SCROLLBARS_AS_NEEDED: 208 case SCROLLBARS_ALWAYS: 209 this.scrollbarDisplayPolicy = scrollbarDisplayPolicy; 210 break; 211 default: 212 throw new IllegalArgumentException("illegal scrollbar display policy"); 213 } 214 215 vAdjustable = new ScrollPaneAdjustable(this, new PeerFixer(this), 216 Adjustable.VERTICAL); 217 hAdjustable = new ScrollPaneAdjustable(this, new PeerFixer(this), 218 Adjustable.HORIZONTAL); 219 setWheelScrollingEnabled(defaultWheelScroll); 220 } 221 222 /** 223 * Construct a name for this component. Called by getName() when the 224 * name is null. 225 */ constructComponentName()226 String constructComponentName() { 227 synchronized (ScrollPane.class) { 228 return base + nameCounter++; 229 } 230 } 231 232 // The scrollpane won't work with a windowless child... it assumes 233 // it is moving a child window around so the windowless child is 234 // wrapped with a window. addToPanel(Component comp, Object constraints, int index)235 private void addToPanel(Component comp, Object constraints, int index) { 236 Panel child = new Panel(); 237 child.setLayout(new BorderLayout()); 238 child.add(comp); 239 super.addImpl(child, constraints, index); 240 validate(); 241 } 242 243 /** 244 * Adds the specified component to this scroll pane container. 245 * If the scroll pane has an existing child component, that 246 * component is removed and the new one is added. 247 * @param comp the component to be added 248 * @param constraints not applicable 249 * @param index position of child component (must be <= 0) 250 */ addImpl(Component comp, Object constraints, int index)251 protected final void addImpl(Component comp, Object constraints, int index) { 252 synchronized (getTreeLock()) { 253 if (getComponentCount() > 0) { 254 remove(0); 255 } 256 if (index > 0) { 257 throw new IllegalArgumentException("position greater than 0"); 258 } 259 260 if (!SunToolkit.isLightweightOrUnknown(comp)) { 261 super.addImpl(comp, constraints, index); 262 } else { 263 addToPanel(comp, constraints, index); 264 } 265 } 266 } 267 268 /** 269 * Returns the display policy for the scrollbars. 270 * @return the display policy for the scrollbars 271 */ getScrollbarDisplayPolicy()272 public int getScrollbarDisplayPolicy() { 273 return scrollbarDisplayPolicy; 274 } 275 276 /** 277 * Returns the current size of the scroll pane's view port. 278 * @return the size of the view port in pixels 279 */ getViewportSize()280 public Dimension getViewportSize() { 281 Insets i = getInsets(); 282 return new Dimension(width - i.right - i.left, 283 height - i.top - i.bottom); 284 } 285 286 /** 287 * Returns the height that would be occupied by a horizontal 288 * scrollbar, which is independent of whether it is currently 289 * displayed by the scroll pane or not. 290 * @return the height of a horizontal scrollbar in pixels 291 */ getHScrollbarHeight()292 public int getHScrollbarHeight() { 293 int h = 0; 294 if (scrollbarDisplayPolicy != SCROLLBARS_NEVER) { 295 ScrollPanePeer peer = (ScrollPanePeer)this.peer; 296 if (peer != null) { 297 h = peer.getHScrollbarHeight(); 298 } 299 } 300 return h; 301 } 302 303 /** 304 * Returns the width that would be occupied by a vertical 305 * scrollbar, which is independent of whether it is currently 306 * displayed by the scroll pane or not. 307 * @return the width of a vertical scrollbar in pixels 308 */ getVScrollbarWidth()309 public int getVScrollbarWidth() { 310 int w = 0; 311 if (scrollbarDisplayPolicy != SCROLLBARS_NEVER) { 312 ScrollPanePeer peer = (ScrollPanePeer)this.peer; 313 if (peer != null) { 314 w = peer.getVScrollbarWidth(); 315 } 316 } 317 return w; 318 } 319 320 /** 321 * Returns the {@code ScrollPaneAdjustable} object which 322 * represents the state of the vertical scrollbar. 323 * The declared return type of this method is 324 * {@code Adjustable} to maintain backward compatibility. 325 * 326 * @see java.awt.ScrollPaneAdjustable 327 * @return the vertical scrollbar state 328 */ getVAdjustable()329 public Adjustable getVAdjustable() { 330 return vAdjustable; 331 } 332 333 /** 334 * Returns the {@code ScrollPaneAdjustable} object which 335 * represents the state of the horizontal scrollbar. 336 * The declared return type of this method is 337 * {@code Adjustable} to maintain backward compatibility. 338 * 339 * @see java.awt.ScrollPaneAdjustable 340 * @return the horizontal scrollbar state 341 */ getHAdjustable()342 public Adjustable getHAdjustable() { 343 return hAdjustable; 344 } 345 346 /** 347 * Scrolls to the specified position within the child component. 348 * A call to this method is only valid if the scroll pane contains 349 * a child. Specifying a position outside of the legal scrolling bounds 350 * of the child will scroll to the closest legal position. 351 * Legal bounds are defined to be the rectangle: 352 * x = 0, y = 0, width = (child width - view port width), 353 * height = (child height - view port height). 354 * This is a convenience method which interfaces with the Adjustable 355 * objects which represent the state of the scrollbars. 356 * @param x the x position to scroll to 357 * @param y the y position to scroll to 358 * @throws NullPointerException if the scrollpane does not contain 359 * a child 360 */ setScrollPosition(int x, int y)361 public void setScrollPosition(int x, int y) { 362 synchronized (getTreeLock()) { 363 if (getComponentCount()==0) { 364 throw new NullPointerException("child is null"); 365 } 366 hAdjustable.setValue(x); 367 vAdjustable.setValue(y); 368 } 369 } 370 371 /** 372 * Scrolls to the specified position within the child component. 373 * A call to this method is only valid if the scroll pane contains 374 * a child and the specified position is within legal scrolling bounds 375 * of the child. Specifying a position outside of the legal scrolling 376 * bounds of the child will scroll to the closest legal position. 377 * Legal bounds are defined to be the rectangle: 378 * x = 0, y = 0, width = (child width - view port width), 379 * height = (child height - view port height). 380 * This is a convenience method which interfaces with the Adjustable 381 * objects which represent the state of the scrollbars. 382 * @param p the Point representing the position to scroll to 383 * @throws NullPointerException if {@code p} is {@code null} 384 */ setScrollPosition(Point p)385 public void setScrollPosition(Point p) { 386 setScrollPosition(p.x, p.y); 387 } 388 389 /** 390 * Returns the current x,y position within the child which is displayed 391 * at the 0,0 location of the scrolled panel's view port. 392 * 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 getScrollPosition()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 */ setLayout(LayoutManager mgr)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 */ doLayout()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 */ calculateChildSize()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()}. 492 */ 493 @Deprecated layout()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 */ printComponents(Graphics g)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 */ addNotify()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}. 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}. 581 * 582 * @return the parameter string of this scroll pane 583 */ paramString()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 autoProcessMouseWheel(MouseWheelEvent e)607 void autoProcessMouseWheel(MouseWheelEvent e) { 608 processMouseWheelEvent(e); 609 } 610 611 /** 612 * Process mouse wheel events that are delivered to this 613 * {@code ScrollPane} by scrolling an appropriate amount. 614 * <p>Note that if the event parameter is {@code null} 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 */ processMouseWheelEvent(MouseWheelEvent e)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 */ eventTypeEnabled(int type)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} if scrolling should be done 647 * automatically for a MouseWheelEvent, 648 * {@code false} otherwise. 649 * @see #isWheelScrollingEnabled 650 * @see java.awt.event.MouseWheelEvent 651 * @see java.awt.event.MouseWheelListener 652 * @since 1.4 653 */ setWheelScrollingEnabled(boolean handleWheel)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 */ isWheelScrollingEnabled()668 public boolean isWheelScrollingEnabled() { 669 return wheelScrollingEnabled; 670 } 671 672 673 /** 674 * Writes default serializable fields to stream. 675 */ writeObject(ObjectOutputStream s)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()} returns 687 * {@code true} 688 * @see java.awt.GraphicsEnvironment#isHeadless 689 */ readObject(ObjectInputStream s)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 PeerFixer(ScrollPane scroller)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") adjustmentValueChanged(AdjustmentEvent e)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 */ getAccessibleContext()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} 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 */ getAccessibleRole()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 */ 820 class PeerFixer implements AdjustmentListener, java.io.Serializable { 821 /* 822 * serialVersionUID 823 */ 824 private static final long serialVersionUID = 7051237413532574756L; 825 PeerFixer(ScrollPane scroller)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") adjustmentValueChanged(AdjustmentEvent e)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