Showing the changes to java/pkg/java/awt/ScrollPane.java (1 of 18352 files). Show all
Unified · Split
| @@ -0,0 +1,849 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1996, 2010, 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.LightweightPeer; | ||
| 28 | import java.awt.peer.ScrollPanePeer; | ||
| 29 | import java.awt.event.*; | ||
| 30 | import javax.accessibility.*; | ||
| 31 | import sun.awt.ScrollPaneWheelScroller; | ||
| 32 | import sun.awt.SunToolkit; | ||
| 33 | |||
| 34 | import java.beans.ConstructorProperties; | ||
| 35 | import java.beans.Transient; | ||
| 36 | import java.io.ObjectInputStream; | ||
| 37 | import java.io.ObjectOutputStream; | ||
| 38 | import java.io.IOException; | ||
| 39 | |||
| 40 | /** | ||
| 41 | * A container class which implements automatic horizontal and/or | ||
| 42 | * vertical scrolling for a single child component. The display | ||
| 43 | * policy for the scrollbars can be set to: | ||
| 44 | * <OL> | ||
| 45 | * <LI>as needed: scrollbars created and shown only when needed by scrollpane | ||
| 46 | * <LI>always: scrollbars created and always shown by the scrollpane | ||
| 47 | * <LI>never: scrollbars never created or shown by the scrollpane | ||
| 48 | * </OL> | ||
| 49 | * <P> | ||
| 50 | * The state of the horizontal and vertical scrollbars is represented | ||
| 51 | * by two <code>ScrollPaneAdjustable</code> objects (one for each | ||
| 52 | * dimension) which implement the <code>Adjustable</code> interface. | ||
| 53 | * The API provides methods to access those objects such that the | ||
| 54 | * attributes on the Adjustable object (such as unitIncrement, value, | ||
| 55 | * etc.) can be manipulated. | ||
| 56 | * <P> | ||
| 57 | * Certain adjustable properties (minimum, maximum, blockIncrement, | ||
| 58 | * and visibleAmount) are set internally by the scrollpane in accordance | ||
| 59 | * with the geometry of the scrollpane and its child and these should | ||
| 60 | * not be set by programs using the scrollpane. | ||
| 61 | * <P> | ||
| 62 | * If the scrollbar display policy is defined as "never", then the | ||
| 63 | * scrollpane can still be programmatically scrolled using the | ||
| 64 | * setScrollPosition() method and the scrollpane will move and clip | ||
| 65 | * the child's contents appropriately. This policy is useful if the | ||
| 66 | * program needs to create and manage its own adjustable controls. | ||
| 67 | * <P> | ||
| 68 | * The placement of the scrollbars is controlled by platform-specific | ||
| 69 | * properties set by the user outside of the program. | ||
| 70 | * <P> | ||
| 71 | * The initial size of this container is set to 100x100, but can | ||
| 72 | * be reset using setSize(). | ||
| 73 | * <P> | ||
| 74 | * Scrolling with the wheel on a wheel-equipped mouse is enabled by default. | ||
| 75 | * This can be disabled using <code>setWheelScrollingEnabled</code>. | ||
| 76 | * Wheel scrolling can be customized by setting the block and | ||
| 77 | * unit increment of the horizontal and vertical Adjustables. | ||
| 78 | * For information on how mouse wheel events are dispatched, see | ||
| 79 | * the class description for {@link MouseWheelEvent}. | ||
| 80 | * <P> | ||
| 81 | * Insets are used to define any space used by scrollbars and any | ||
| 82 | * borders created by the scroll pane. getInsets() can be used | ||
| 83 | * to get the current value for the insets. If the value of | ||
| 84 | * scrollbarsAlwaysVisible is false, then the value of the insets | ||
| 85 | * will change dynamically depending on whether the scrollbars are | ||
| 86 | * currently visible or not. | ||
| 87 | * | ||
| 88 | * @author Tom Ball | ||
| 89 | * @author Amy Fowler | ||
| 90 | * @author Tim Prinzing | ||
| 91 | */ | ||
| 92 | public class ScrollPane extends Container implements Accessible { | ||
| 93 | |||
| 94 | |||
| 95 | /** | ||
| 96 | * Initialize JNI field and method IDs | ||
| 97 | */ | ||
| 98 | private static native void initIDs(); | ||
| 99 | |||
| 100 | static { | ||
| 101 | /* ensure that the necessary native libraries are loaded */ | ||
| 102 | Toolkit.loadLibraries(); | ||
| 103 | if (!GraphicsEnvironment.isHeadless()) { | ||
| 104 | initIDs(); | ||
| 105 | } | ||
| 106 | } | ||
| 107 | |||
| 108 | /** | ||
| 109 | * Specifies that horizontal/vertical scrollbar should be shown | ||
| 110 | * only when the size of the child exceeds the size of the scrollpane | ||
| 111 | * in the horizontal/vertical dimension. | ||
| 112 | */ | ||
| 113 | public static final int SCROLLBARS_AS_NEEDED = 0; | ||
| 114 | |||
| 115 | /** | ||
| 116 | * Specifies that horizontal/vertical scrollbars should always be | ||
| 117 | * shown regardless of the respective sizes of the scrollpane and child. | ||
| 118 | */ | ||
| 119 | public static final int SCROLLBARS_ALWAYS = 1; | ||
| 120 | |||
| 121 | /** | ||
| 122 | * Specifies that horizontal/vertical scrollbars should never be shown | ||
| 123 | * regardless of the respective sizes of the scrollpane and child. | ||
| 124 | */ | ||
| 125 | public static final int SCROLLBARS_NEVER = 2; | ||
| 126 | |||
| 127 | /** | ||
| 128 | * There are 3 ways in which a scroll bar can be displayed. | ||
| 129 | * This integer will represent one of these 3 displays - | ||
| 130 | * (SCROLLBARS_ALWAYS, SCROLLBARS_AS_NEEDED, SCROLLBARS_NEVER) | ||
| 131 | * | ||
| 132 | * @serial | ||
| 133 | * @see #getScrollbarDisplayPolicy | ||
| 134 | */ | ||
| 135 | private int scrollbarDisplayPolicy; | ||
| 136 | |||
| 137 | /** | ||
| 138 | * An adjustable vertical scrollbar. | ||
| 139 | * It is important to note that you must <em>NOT</em> call 3 | ||
| 140 | * <code>Adjustable</code> methods, namely: | ||
| 141 | * <code>setMinimum()</code>, <code>setMaximum()</code>, | ||
| 142 | * <code>setVisibleAmount()</code>. | ||
| 143 | * | ||
| 144 | * @serial | ||
| 145 | * @see #getVAdjustable | ||
| 146 | */ | ||
| 147 | private ScrollPaneAdjustable vAdjustable; | ||
| 148 | |||
| 149 | /** | ||
| 150 | * An adjustable horizontal scrollbar. | ||
| 151 | * It is important to note that you must <em>NOT</em> call 3 | ||
| 152 | * <code>Adjustable</code> methods, namely: | ||
| 153 | * <code>setMinimum()</code>, <code>setMaximum()</code>, | ||
| 154 | * <code>setVisibleAmount()</code>. | ||
| 155 | * | ||
| 156 | * @serial | ||
| 157 | * @see #getHAdjustable | ||
| 158 | */ | ||
| 159 | private ScrollPaneAdjustable hAdjustable; | ||
| 160 | |||
| 161 | private static final String base = "scrollpane"; | ||
| 162 | private static int nameCounter = 0; | ||
| 163 | |||
| 164 | private static final boolean defaultWheelScroll = true; | ||
| 165 | |||
| 166 | /** | ||
| 167 | * Indicates whether or not scrolling should take place when a | ||
| 168 | * MouseWheelEvent is received. | ||
| 169 | * | ||
| 170 | * @serial | ||
| 171 | * @since 1.4 | ||
| 172 | */ | ||
| 173 | private boolean wheelScrollingEnabled = defaultWheelScroll; | ||
| 174 | |||
| 175 | /* | ||
| 176 | * JDK 1.1 serialVersionUID | ||
| 177 | */ | ||
| 178 | private static final long serialVersionUID = 7956609840827222915L; | ||
| 179 | |||
| 180 | /** | ||
| 181 | * Create a new scrollpane container with a scrollbar display | ||
| 182 | * policy of "as needed". | ||
| 183 | * @throws HeadlessException if GraphicsEnvironment.isHeadless() | ||
| 184 | * returns true | ||
| 185 | * @see java.awt.GraphicsEnvironment#isHeadless | ||
| 186 | */ | ||
| 187 | public ScrollPane() throws HeadlessException { | ||
| 188 | this(SCROLLBARS_AS_NEEDED); | ||
| 189 | } | ||
| 190 | |||
| 191 | /** | ||
| 192 | * Create a new scrollpane container. | ||
| 193 | * @param scrollbarDisplayPolicy policy for when scrollbars should be shown | ||
| 194 | * @throws IllegalArgumentException if the specified scrollbar | ||
| 195 | * display policy is invalid | ||
| 196 | * @throws HeadlessException if GraphicsEnvironment.isHeadless() | ||
| 197 | * returns true | ||
| 198 | * @see java.awt.GraphicsEnvironment#isHeadless | ||
| 199 | */ | ||
| 200 | @ConstructorProperties({"scrollbarDisplayPolicy"}) | ||
| 201 | public ScrollPane(int scrollbarDisplayPolicy) throws HeadlessException { | ||
| 202 | GraphicsEnvironment.checkHeadless(); | ||
| 203 | this.layoutMgr = null; | ||
| 204 | this.width = 100; | ||
| 205 | this.height = 100; | ||
| 206 | switch (scrollbarDisplayPolicy) { | ||
| 207 | case SCROLLBARS_NEVER: | ||
| 208 | case SCROLLBARS_AS_NEEDED: | ||
| 209 | case SCROLLBARS_ALWAYS: | ||
| 210 | this.scrollbarDisplayPolicy = scrollbarDisplayPolicy; | ||
| 211 | break; | ||
| 212 | default: | ||
| 213 | throw new IllegalArgumentException("illegal scrollbar display policy"); | ||
| 214 | } | ||
| 215 | |||
| 216 | vAdjustable = new ScrollPaneAdjustable(this, new PeerFixer(this), | ||
| 217 | Adjustable.VERTICAL); | ||
| 218 | hAdjustable = new ScrollPaneAdjustable(this, new PeerFixer(this), | ||
| 219 | Adjustable.HORIZONTAL); | ||
| 220 | setWheelScrollingEnabled(defaultWheelScroll); | ||
| 221 | } | ||
| 222 | |||
| 223 | /** | ||
| 224 | * Construct a name for this component. Called by getName() when the | ||
| 225 | * name is null. | ||
| 226 | */ | ||
| 227 | String constructComponentName() { | ||
| 228 | synchronized (ScrollPane.class) { | ||
| 229 | return base + nameCounter++; | ||
| 230 | } | ||
| 231 | } | ||
| 232 | |||
| 233 | // The scrollpane won't work with a windowless child... it assumes | ||
| 234 | // it is moving a child window around so the windowless child is | ||
| 235 | // wrapped with a window. | ||
| 236 | private void addToPanel(Component comp, Object constraints, int index) { | ||
| 237 | Panel child = new Panel(); | ||
| 238 | child.setLayout(new BorderLayout()); | ||
| 239 | child.add(comp); | ||
| 240 | super.addImpl(child, constraints, index); | ||
| 241 | validate(); | ||
| 242 | } | ||
| 243 | |||
| 244 | /** | ||
| 245 | * Adds the specified component to this scroll pane container. | ||
| 246 | * If the scroll pane has an existing child component, that | ||
| 247 | * component is removed and the new one is added. | ||
| 248 | * @param comp the component to be added | ||
| 249 | * @param constraints not applicable | ||
| 250 | * @param index position of child component (must be <= 0) | ||
| 251 | */ | ||
| 252 | protected final void addImpl(Component comp, Object constraints, int index) { | ||
| 253 | synchronized (getTreeLock()) { | ||
| 254 | if (getComponentCount() > 0) { | ||
| 255 | remove(0); | ||
| 256 | } | ||
| 257 | if (index > 0) { | ||
| 258 | throw new IllegalArgumentException("position greater than 0"); | ||
| 259 | } | ||
| 260 | |||
| 261 | if (!SunToolkit.isLightweightOrUnknown(comp)) { | ||
| 262 | super.addImpl(comp, constraints, index); | ||
| 263 | } else { | ||
| 264 | addToPanel(comp, constraints, index); | ||
| 265 | } | ||
| 266 | } | ||
| 267 | } | ||
| 268 | |||
| 269 | /** | ||
| 270 | * Returns the display policy for the scrollbars. | ||
| 271 | * @return the display policy for the scrollbars | ||
| 272 | */ | ||
| 273 | public int getScrollbarDisplayPolicy() { | ||
| 274 | return scrollbarDisplayPolicy; | ||
| 275 | } | ||
| 276 | |||
| 277 | /** | ||
| 278 | * Returns the current size of the scroll pane's view port. | ||
| 279 | * @return the size of the view port in pixels | ||
| 280 | */ | ||
| 281 | public Dimension getViewportSize() { | ||
| 282 | Insets i = getInsets(); | ||
| 283 | return new Dimension(width - i.right - i.left, | ||
| 284 | height - i.top - i.bottom); | ||
| 285 | } | ||
| 286 | |||
| 287 | /** | ||
| 288 | * Returns the height that would be occupied by a horizontal | ||
| 289 | * scrollbar, which is independent of whether it is currently | ||
| 290 | * displayed by the scroll pane or not. | ||
| 291 | * @return the height of a horizontal scrollbar in pixels | ||
| 292 | */ | ||
| 293 | public int getHScrollbarHeight() { | ||
| 294 | int h = 0; | ||
| 295 | if (scrollbarDisplayPolicy != SCROLLBARS_NEVER) { | ||
| 296 | ScrollPanePeer peer = (ScrollPanePeer)this.peer; | ||
| 297 | if (peer != null) { | ||
| 298 | h = peer.getHScrollbarHeight(); | ||
| 299 | } | ||
| 300 | } | ||
| 301 | return h; | ||
| 302 | } | ||
| 303 | |||
| 304 | /** | ||
| 305 | * Returns the width that would be occupied by a vertical | ||
| 306 | * scrollbar, which is independent of whether it is currently | ||
| 307 | * displayed by the scroll pane or not. | ||
| 308 | * @return the width of a vertical scrollbar in pixels | ||
| 309 | */ | ||
| 310 | public int getVScrollbarWidth() { | ||
| 311 | int w = 0; | ||
| 312 | if (scrollbarDisplayPolicy != SCROLLBARS_NEVER) { | ||
| 313 | ScrollPanePeer peer = (ScrollPanePeer)this.peer; | ||
| 314 | if (peer != null) { | ||
| 315 | w = peer.getVScrollbarWidth(); | ||
| 316 | } | ||
| 317 | } | ||
| 318 | return w; | ||
| 319 | } | ||
| 320 | |||
| 321 | /** | ||
| 322 | * Returns the <code>ScrollPaneAdjustable</code> object which | ||
| 323 | * represents the state of the vertical scrollbar. | ||
| 324 | * The declared return type of this method is | ||
| 325 | * <code>Adjustable</code> to maintain backward compatibility. | ||
| 326 | * @see java.awt.ScrollPaneAdjustable | ||
| 327 | */ | ||
| 328 | public Adjustable getVAdjustable() { | ||
| 329 | return vAdjustable; | ||
| 330 | } | ||
| 331 | |||
| 332 | /** | ||
| 333 | * Returns the <code>ScrollPaneAdjustable</code> object which | ||
| 334 | * represents the state of the horizontal scrollbar. | ||
| 335 | * The declared return type of this method is | ||
| 336 | * <code>Adjustable</code> to maintain backward compatibility. | ||
| 337 | * @see java.awt.ScrollPaneAdjustable | ||
| 338 | */ | ||
| 339 | public Adjustable getHAdjustable() { | ||
| 340 | return hAdjustable; | ||
| 341 | } | ||
| 342 | |||
| 343 | /** | ||
| 344 | * Scrolls to the specified position within the child component. | ||
| 345 | * A call to this method is only valid if the scroll pane contains | ||
| 346 | * a child. Specifying a position outside of the legal scrolling bounds | ||
| 347 | * of the child will scroll to the closest legal position. | ||
| 348 | * Legal bounds are defined to be the rectangle: | ||
| 349 | * x = 0, y = 0, width = (child width - view port width), | ||
| 350 | * height = (child height - view port height). | ||
| 351 | * This is a convenience method which interfaces with the Adjustable | ||
| 352 | * objects which represent the state of the scrollbars. | ||
| 353 | * @param x the x position to scroll to | ||
| 354 | * @param y the y position to scroll to | ||
| 355 | * @throws NullPointerException if the scrollpane does not contain | ||
| 356 | * a child | ||
| 357 | */ | ||
| 358 | public void setScrollPosition(int x, int y) { | ||
| 359 | synchronized (getTreeLock()) { | ||
| 360 | if (getComponentCount()==0) { | ||
| 361 | throw new NullPointerException("child is null"); | ||
| 362 | } | ||
| 363 | hAdjustable.setValue(x); | ||
| 364 | vAdjustable.setValue(y); | ||
| 365 | } | ||
| 366 | } | ||
| 367 | |||
| 368 | /** | ||
| 369 | * Scrolls to the specified position within the child component. | ||
| 370 | * A call to this method is only valid if the scroll pane contains | ||
| 371 | * a child and the specified position is within legal scrolling bounds | ||
| 372 | * of the child. Specifying a position outside of the legal scrolling | ||
| 373 | * bounds of the child will scroll to the closest legal position. | ||
| 374 | * Legal bounds are defined to be the rectangle: | ||
| 375 | * x = 0, y = 0, width = (child width - view port width), | ||
| 376 | * height = (child height - view port height). | ||
| 377 | * This is a convenience method which interfaces with the Adjustable | ||
| 378 | * objects which represent the state of the scrollbars. | ||
| 379 | * @param p the Point representing the position to scroll to | ||
| 380 | * @throws NullPointerException if {@code p} is {@code null} | ||
| 381 | */ | ||
| 382 | public void setScrollPosition(Point p) { | ||
| 383 | setScrollPosition(p.x, p.y); | ||
| 384 | } | ||
| 385 | |||
| 386 | /** | ||
| 387 | * Returns the current x,y position within the child which is displayed | ||
| 388 | * at the 0,0 location of the scrolled panel's view port. | ||
| 389 | * This is a convenience method which interfaces with the adjustable | ||
| 390 | * objects which represent the state of the scrollbars. | ||
| 391 | * @return the coordinate position for the current scroll position | ||
| 392 | * @throws NullPointerException if the scrollpane does not contain | ||
| 393 | * a child | ||
| 394 | */ | ||
| 395 | @Transient | ||
| 396 | public Point getScrollPosition() { | ||
| 397 | synchronized (getTreeLock()) { | ||
| 398 | if (getComponentCount()==0) { | ||
| 399 | throw new NullPointerException("child is null"); | ||
| 400 | } | ||
| 401 | return new Point(hAdjustable.getValue(), vAdjustable.getValue()); | ||
| 402 | } | ||
| 403 | } | ||
| 404 | |||
| 405 | /** | ||
| 406 | * Sets the layout manager for this container. This method is | ||
| 407 | * overridden to prevent the layout mgr from being set. | ||
| 408 | * @param mgr the specified layout manager | ||
| 409 | */ | ||
| 410 | public final void setLayout(LayoutManager mgr) { | ||
| 411 | throw new AWTError("ScrollPane controls layout"); | ||
| 412 | } | ||
| 413 | |||
| 414 | /** | ||
| 415 | * Lays out this container by resizing its child to its preferred size. | ||
| 416 | * If the new preferred size of the child causes the current scroll | ||
| 417 | * position to be invalid, the scroll position is set to the closest | ||
| 418 | * valid position. | ||
| 419 | * | ||
| 420 | * @see Component#validate | ||
| 421 | */ | ||
| 422 | public void doLayout() { | ||
| 423 | layout(); | ||
| 424 | } | ||
| 425 | |||
| 426 | /** | ||
| 427 | * Determine the size to allocate the child component. | ||
| 428 | * If the viewport area is bigger than the childs | ||
| 429 | * preferred size then the child is allocated enough | ||
| 430 | * to fill the viewport, otherwise the child is given | ||
| 431 | * it's preferred size. | ||
| 432 | */ | ||
| 433 | Dimension calculateChildSize() { | ||
| 434 | // | ||
| 435 | // calculate the view size, accounting for border but not scrollbars | ||
| 436 | // - don't use right/bottom insets since they vary depending | ||
| 437 | // on whether or not scrollbars were displayed on last resize | ||
| 438 | // | ||
| 439 | Dimension size = getSize(); | ||
| 440 | Insets insets = getInsets(); | ||
| 441 | int viewWidth = size.width - insets.left*2; | ||
| 442 | int viewHeight = size.height - insets.top*2; | ||
| 443 | |||
| 444 | // | ||
| 445 | // determine whether or not horz or vert scrollbars will be displayed | ||
| 446 | // | ||
| 447 | boolean vbarOn; | ||
| 448 | boolean hbarOn; | ||
| 449 | Component child = getComponent(0); | ||
| 450 | Dimension childSize = new Dimension(child.getPreferredSize()); | ||
| 451 | |||
| 452 | if (scrollbarDisplayPolicy == SCROLLBARS_AS_NEEDED) { | ||
| 453 | vbarOn = childSize.height > viewHeight; | ||
| 454 | hbarOn = childSize.width > viewWidth; | ||
| 455 | } else if (scrollbarDisplayPolicy == SCROLLBARS_ALWAYS) { | ||
| 456 | vbarOn = hbarOn = true; | ||
| 457 | } else { // SCROLLBARS_NEVER | ||
| 458 | vbarOn = hbarOn = false; | ||
| 459 | } | ||
| 460 | |||
| 461 | // | ||
| 462 | // adjust predicted view size to account for scrollbars | ||
| 463 | // | ||
| 464 | int vbarWidth = getVScrollbarWidth(); | ||
| 465 | int hbarHeight = getHScrollbarHeight(); | ||
| 466 | if (vbarOn) { | ||
| 467 | viewWidth -= vbarWidth; | ||
| 468 | } | ||
| 469 | if(hbarOn) { | ||
| 470 | viewHeight -= hbarHeight; | ||
| 471 | } | ||
| 472 | |||
| 473 | // | ||
| 474 | // if child is smaller than view, size it up | ||
| 475 | // | ||
| 476 | if (childSize.width < viewWidth) { | ||
| 477 | childSize.width = viewWidth; | ||
| 478 | } | ||
| 479 | if (childSize.height < viewHeight) { | ||
| 480 | childSize.height = viewHeight; | ||
| 481 | } | ||
| 482 | |||
| 483 | return childSize; | ||
| 484 | } | ||
| 485 | |||
| 486 | /** | ||
| 487 | * @deprecated As of JDK version 1.1, | ||
| 488 | * replaced by <code>doLayout()</code>. | ||
| 489 | */ | ||
| 490 | @Deprecated | ||
| 491 | public void layout() { | ||
| 492 | if (getComponentCount()==0) { | ||
| 493 | return; | ||
| 494 | } | ||
| 495 | Component c = getComponent(0); | ||
| 496 | Point p = getScrollPosition(); | ||
| 497 | Dimension cs = calculateChildSize(); | ||
| 498 | Dimension vs = getViewportSize(); | ||
| 499 | Insets i = getInsets(); | ||
| 500 | |||
| 501 | c.reshape(i.left - p.x, i.top - p.y, cs.width, cs.height); | ||
| 502 | ScrollPanePeer peer = (ScrollPanePeer)this.peer; | ||
| 503 | if (peer != null) { | ||
| 504 | peer.childResized(cs.width, cs.height); | ||
| 505 | } | ||
| 506 | |||
| 507 | // update adjustables... the viewport size may have changed | ||
| 508 | // with the scrollbars coming or going so the viewport size | ||
| 509 | // is updated before the adjustables. | ||
| 510 | vs = getViewportSize(); | ||
| 511 | hAdjustable.setSpan(0, cs.width, vs.width); | ||
| 512 | vAdjustable.setSpan(0, cs.height, vs.height); | ||
| 513 | } | ||
| 514 | |||
| 515 | /** | ||
| 516 | * Prints the component in this scroll pane. | ||
| 517 | * @param g the specified Graphics window | ||
| 518 | * @see Component#print | ||
| 519 | * @see Component#printAll | ||
| 520 | */ | ||
| 521 | public void printComponents(Graphics g) { | ||
| 522 | if (getComponentCount()==0) { | ||
| 523 | return; | ||
| 524 | } | ||
| 525 | Component c = getComponent(0); | ||
| 526 | Point p = c.getLocation(); | ||
| 527 | Dimension vs = getViewportSize(); | ||
| 528 | Insets i = getInsets(); | ||
| 529 | |||
| 530 | Graphics cg = g.create(); | ||
| 531 | try { | ||
| 532 | cg.clipRect(i.left, i.top, vs.width, vs.height); | ||
| 533 | cg.translate(p.x, p.y); | ||
| 534 | c.printAll(cg); | ||
| 535 | } finally { | ||
| 536 | cg.dispose(); | ||
| 537 | } | ||
| 538 | } | ||
| 539 | |||
| 540 | /** | ||
| 541 | * Creates the scroll pane's peer. | ||
| 542 | */ | ||
| 543 | public void addNotify() { | ||
| 544 | synchronized (getTreeLock()) { | ||
| 545 | |||
| 546 | int vAdjustableValue = 0; | ||
| 547 | int hAdjustableValue = 0; | ||
| 548 | |||
| 549 | // Bug 4124460. Save the current adjustable values, | ||
| 550 | // so they can be restored after addnotify. Set the | ||
| 551 | // adjustables to 0, to prevent crashes for possible | ||
| 552 | // negative values. | ||
| 553 | if (getComponentCount() > 0) { | ||
| 554 | vAdjustableValue = vAdjustable.getValue(); | ||
| 555 | hAdjustableValue = hAdjustable.getValue(); | ||
| 556 | vAdjustable.setValue(0); | ||
| 557 | hAdjustable.setValue(0); | ||
| 558 | } | ||
| 559 | |||
| 560 | if (peer == null) | ||
| 561 | peer = getToolkit().createScrollPane(this); | ||
| 562 | super.addNotify(); | ||
| 563 | |||
| 564 | // Bug 4124460. Restore the adjustable values. | ||
| 565 | if (getComponentCount() > 0) { | ||
| 566 | vAdjustable.setValue(vAdjustableValue); | ||
| 567 | hAdjustable.setValue(hAdjustableValue); | ||
| 568 | } | ||
| 569 | } | ||
| 570 | } | ||
| 571 | |||
| 572 | /** | ||
| 573 | * Returns a string representing the state of this | ||
| 574 | * <code>ScrollPane</code>. This | ||
| 575 | * method is intended to be used only for debugging purposes, and the | ||
| 576 | * content and format of the returned string may vary between | ||
| 577 | * implementations. The returned string may be empty but may not be | ||
| 578 | * <code>null</code>. | ||
| 579 | * | ||
| 580 | * @return the parameter string of this scroll pane | ||
| 581 | */ | ||
| 582 | public String paramString() { | ||
| 583 | String sdpStr; | ||
| 584 | switch (scrollbarDisplayPolicy) { | ||
| 585 | case SCROLLBARS_AS_NEEDED: | ||
| 586 | sdpStr = "as-needed"; | ||
| 587 | break; | ||
| 588 | case SCROLLBARS_ALWAYS: | ||
| 589 | sdpStr = "always"; | ||
| 590 | break; | ||
| 591 | case SCROLLBARS_NEVER: | ||
| 592 | sdpStr = "never"; | ||
| 593 | break; | ||
| 594 | default: | ||
| 595 | sdpStr = "invalid display policy"; | ||
| 596 | } | ||
| 597 | Point p = (getComponentCount()>0)? getScrollPosition() : new Point(0,0); | ||
| 598 | Insets i = getInsets(); | ||
| 599 | return super.paramString()+",ScrollPosition=("+p.x+","+p.y+")"+ | ||
| 600 | ",Insets=("+i.top+","+i.left+","+i.bottom+","+i.right+")"+ | ||
| 601 | ",ScrollbarDisplayPolicy="+sdpStr+ | ||
| 602 | ",wheelScrollingEnabled="+isWheelScrollingEnabled(); | ||
| 603 | } | ||
| 604 | |||
| 605 | void autoProcessMouseWheel(MouseWheelEvent e) { | ||
| 606 | processMouseWheelEvent(e); | ||
| 607 | } | ||
| 608 | |||
| 609 | /** | ||
| 610 | * Process mouse wheel events that are delivered to this | ||
| 611 | * <code>ScrollPane</code> by scrolling an appropriate amount. | ||
| 612 | * <p>Note that if the event parameter is <code>null</code> | ||
| 613 | * the behavior is unspecified and may result in an | ||
| 614 | * exception. | ||
| 615 | * | ||
| 616 | * @param e the mouse wheel event | ||
| 617 | * @since 1.4 | ||
| 618 | */ | ||
| 619 | protected void processMouseWheelEvent(MouseWheelEvent e) { | ||
| 620 | if (isWheelScrollingEnabled()) { | ||
| 621 | ScrollPaneWheelScroller.handleWheelScrolling(this, e); | ||
| 622 | e.consume(); | ||
| 623 | } | ||
| 624 | super.processMouseWheelEvent(e); | ||
| 625 | } | ||
| 626 | |||
| 627 | /** | ||
| 628 | * If wheel scrolling is enabled, we return true for MouseWheelEvents | ||
| 629 | * @since 1.4 | ||
| 630 | */ | ||
| 631 | protected boolean eventTypeEnabled(int type) { | ||
| 632 | if (type == MouseEvent.MOUSE_WHEEL && isWheelScrollingEnabled()) { | ||
| 633 | return true; | ||
| 634 | } | ||
| 635 | else { | ||
| 636 | return super.eventTypeEnabled(type); | ||
| 637 | } | ||
| 638 | } | ||
| 639 | |||
| 640 | /** | ||
| 641 | * Enables/disables scrolling in response to movement of the mouse wheel. | ||
| 642 | * Wheel scrolling is enabled by default. | ||
| 643 | * | ||
| 644 | * @param handleWheel <code>true</code> if scrolling should be done | ||
| 645 | * automatically for a MouseWheelEvent, | ||
| 646 | * <code>false</code> otherwise. | ||
| 647 | * @see #isWheelScrollingEnabled | ||
| 648 | * @see java.awt.event.MouseWheelEvent | ||
| 649 | * @see java.awt.event.MouseWheelListener | ||
| 650 | * @since 1.4 | ||
| 651 | */ | ||
| 652 | public void setWheelScrollingEnabled(boolean handleWheel) { | ||
| 653 | wheelScrollingEnabled = handleWheel; | ||
| 654 | } | ||
| 655 | |||
| 656 | /** | ||
| 657 | * Indicates whether or not scrolling will take place in response to | ||
| 658 | * the mouse wheel. Wheel scrolling is enabled by default. | ||
| 659 | * | ||
| 660 | * @see #setWheelScrollingEnabled(boolean) | ||
| 661 | * @since 1.4 | ||
| 662 | */ | ||
| 663 | public boolean isWheelScrollingEnabled() { | ||
| 664 | return wheelScrollingEnabled; | ||
| 665 | } | ||
| 666 | |||
| 667 | |||
| 668 | /** | ||
| 669 | * Writes default serializable fields to stream. | ||
| 670 | */ | ||
| 671 | private void writeObject(ObjectOutputStream s) throws IOException { | ||
| 672 | // 4352819: We only need this degenerate writeObject to make | ||
| 673 | // it safe for future versions of this class to write optional | ||
| 674 | // data to the stream. | ||
| 675 | s.defaultWriteObject(); | ||
| 676 | } | ||
| 677 | |||
| 678 | /** | ||
| 679 | * Reads default serializable fields to stream. | ||
| 680 | * @exception HeadlessException if | ||
| 681 | * <code>GraphicsEnvironment.isHeadless()</code> returns | ||
| 682 | * <code>true</code> | ||
| 683 | * @see java.awt.GraphicsEnvironment#isHeadless | ||
| 684 | */ | ||
| 685 | private void readObject(ObjectInputStream s) | ||
| 686 | throws ClassNotFoundException, IOException, HeadlessException | ||
| 687 | { | ||
| 688 | GraphicsEnvironment.checkHeadless(); | ||
| 689 | // 4352819: Gotcha! Cannot use s.defaultReadObject here and | ||
| 690 | // then continue with reading optional data. Use GetField instead. | ||
| 691 | ObjectInputStream.GetField f = s.readFields(); | ||
| 692 | |||
| 693 | // Old fields | ||
| 694 | scrollbarDisplayPolicy = f.get("scrollbarDisplayPolicy", | ||
| 695 | SCROLLBARS_AS_NEEDED); | ||
| 696 | hAdjustable = (ScrollPaneAdjustable)f.get("hAdjustable", null); | ||
| 697 | vAdjustable = (ScrollPaneAdjustable)f.get("vAdjustable", null); | ||
| 698 | |||
| 699 | // Since 1.4 | ||
| 700 | wheelScrollingEnabled = f.get("wheelScrollingEnabled", | ||
| 701 | defaultWheelScroll); | ||
| 702 | |||
| 703 | // // Note to future maintainers | ||
| 704 | // if (f.defaulted("wheelScrollingEnabled")) { | ||
| 705 | // // We are reading pre-1.4 stream that doesn't have | ||
| 706 | // // optional data, not even the TC_ENDBLOCKDATA marker. | ||
| 707 | // // Reading anything after this point is unsafe as we will | ||
| 708 | // // read unrelated objects further down the stream (4352819). | ||
| 709 | // } | ||
| 710 | // else { | ||
| 711 | // // Reading data from 1.4 or later, it's ok to try to read | ||
| 712 | // // optional data as OptionalDataException with eof == true | ||
| 713 | // // will be correctly reported | ||
| 714 | // } | ||
| 715 | } | ||
| 716 | |||
| 717 | class PeerFixer implements AdjustmentListener, java.io.Serializable | ||
| 718 | { | ||
| 719 | private static final long serialVersionUID = 1043664721353696630L; | ||
| 720 | |||
| 721 | PeerFixer(ScrollPane scroller) { | ||
| 722 | this.scroller = scroller; | ||
| 723 | } | ||
| 724 | |||
| 725 | /** | ||
| 726 | * Invoked when the value of the adjustable has changed. | ||
| 727 | */ | ||
| 728 | public void adjustmentValueChanged(AdjustmentEvent e) { | ||
| 729 | Adjustable adj = e.getAdjustable(); | ||
| 730 | int value = e.getValue(); | ||
| 731 | ScrollPanePeer peer = (ScrollPanePeer) scroller.peer; | ||
| 732 | if (peer != null) { | ||
| 733 | peer.setValue(adj, value); | ||
| 734 | } | ||
| 735 | |||
| 736 | Component c = scroller.getComponent(0); | ||
| 737 | switch(adj.getOrientation()) { | ||
| 738 | case Adjustable.VERTICAL: | ||
| 739 | c.move(c.getLocation().x, -(value)); | ||
| 740 | break; | ||
| 741 | case Adjustable.HORIZONTAL: | ||
| 742 | c.move(-(value), c.getLocation().y); | ||
| 743 | break; | ||
| 744 | default: | ||
| 745 | throw new IllegalArgumentException("Illegal adjustable orientation"); | ||
| 746 | } | ||
| 747 | } | ||
| 748 | |||
| 749 | private ScrollPane scroller; | ||
| 750 | } | ||
| 751 | |||
| 752 | |||
| 753 | ///////////////// | ||
| 754 | // Accessibility support | ||
| 755 | //////////////// | ||
| 756 | |||
| 757 | /** | ||
| 758 | * Gets the AccessibleContext associated with this ScrollPane. | ||
| 759 | * For scroll panes, the AccessibleContext takes the form of an | ||
| 760 | * AccessibleAWTScrollPane. | ||
| 761 | * A new AccessibleAWTScrollPane instance is created if necessary. | ||
| 762 | * | ||
| 763 | * @return an AccessibleAWTScrollPane that serves as the | ||
| 764 | * AccessibleContext of this ScrollPane | ||
| 765 | * @since 1.3 | ||
| 766 | */ | ||
| 767 | public AccessibleContext getAccessibleContext() { | ||
| 768 | if (accessibleContext == null) { | ||
| 769 | accessibleContext = new AccessibleAWTScrollPane(); | ||
| 770 | } | ||
| 771 | return accessibleContext; | ||
| 772 | } | ||
| 773 | |||
| 774 | /** | ||
| 775 | * This class implements accessibility support for the | ||
| 776 | * <code>ScrollPane</code> class. It provides an implementation of the | ||
| 777 | * Java Accessibility API appropriate to scroll pane user-interface | ||
| 778 | * elements. | ||
| 779 | * @since 1.3 | ||
| 780 | */ | ||
| 781 | protected class AccessibleAWTScrollPane extends AccessibleAWTContainer | ||
| 782 | { | ||
| 783 | /* | ||
| 784 | * JDK 1.3 serialVersionUID | ||
| 785 | */ | ||
| 786 | private static final long serialVersionUID = 6100703663886637L; | ||
| 787 | |||
| 788 | /** | ||
| 789 | * Get the role of this object. | ||
| 790 | * | ||
| 791 | * @return an instance of AccessibleRole describing the role of the | ||
| 792 | * object | ||
| 793 | * @see AccessibleRole | ||
| 794 | */ | ||
| 795 | public AccessibleRole getAccessibleRole() { | ||
| 796 | return AccessibleRole.SCROLL_PANE; | ||
| 797 | } | ||
| 798 | |||
| 799 | } // class AccessibleAWTScrollPane | ||
| 800 | |||
| 801 | } | ||
| 802 | |||
| 803 | /* | ||
| 804 | * In JDK 1.1.1, the pkg private class java.awt.PeerFixer was moved to | ||
| 805 | * become an inner class of ScrollPane, which broke serialization | ||
| 806 | * for ScrollPane objects using JDK 1.1. | ||
| 807 | * Instead of moving it back out here, which would break all JDK 1.1.x | ||
| 808 | * releases, we keep PeerFixer in both places. Because of the scoping rules, | ||
| 809 | * the PeerFixer that is used in ScrollPane will be the one that is the | ||
| 810 | * inner class. This pkg private PeerFixer class below will only be used | ||
| 811 | * if the Java 2 platform is used to deserialize ScrollPane objects that were serialized | ||
| 812 | * using JDK1.1 | ||
| 813 | */ | ||
| 814 | class PeerFixer implements AdjustmentListener, java.io.Serializable { | ||
| 815 | /* | ||
| 816 | * serialVersionUID | ||
| 817 | */ | ||
| 818 | private static final long serialVersionUID = 7051237413532574756L; | ||
| 819 | |||
| 820 | PeerFixer(ScrollPane scroller) { | ||
| 821 | this.scroller = scroller; | ||
| 822 | } | ||
| 823 | |||
| 824 | /** | ||
| 825 | * Invoked when the value of the adjustable has changed. | ||
| 826 | */ | ||
| 827 | public void adjustmentValueChanged(AdjustmentEvent e) { | ||
| 828 | Adjustable adj = e.getAdjustable(); | ||
| 829 | int value = e.getValue(); | ||
| 830 | ScrollPanePeer peer = (ScrollPanePeer) scroller.peer; | ||
| 831 | if (peer != null) { | ||
| 832 | peer.setValue(adj, value); | ||
| 833 | } | ||
| 834 | |||
| 835 | Component c = scroller.getComponent(0); | ||
| 836 | switch(adj.getOrientation()) { | ||
| 837 | case Adjustable.VERTICAL: | ||
| 838 | c.move(c.getLocation().x, -(value)); | ||
| 839 | break; | ||
| 840 | case Adjustable.HORIZONTAL: | ||
| 841 | c.move(-(value), c.getLocation().y); | ||
| 842 | break; | ||
| 843 | default: | ||
| 844 | throw new IllegalArgumentException("Illegal adjustable orientation"); | ||
| 845 | } | ||
| 846 | } | ||
| 847 | |||
| 848 | private ScrollPane scroller; | ||
| 849 | } | ||