1 /* 2 * Copyright (c) 2000, 2014, 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 sun.awt.AWTAccessor; 28 29 import java.awt.event.AdjustmentEvent; 30 import java.awt.event.AdjustmentListener; 31 import java.awt.peer.ScrollPanePeer; 32 import java.io.Serializable; 33 34 35 /** 36 * This class represents the state of a horizontal or vertical 37 * scrollbar of a {@code ScrollPane}. Objects of this class are 38 * returned by {@code ScrollPane} methods. 39 * 40 * @since 1.4 41 */ 42 public class ScrollPaneAdjustable implements Adjustable, Serializable { 43 44 /** 45 * The {@code ScrollPane} this object is a scrollbar of. 46 * @serial 47 */ 48 private ScrollPane sp; 49 50 /** 51 * Orientation of this scrollbar. 52 * 53 * @serial 54 * @see #getOrientation 55 * @see java.awt.Adjustable#HORIZONTAL 56 * @see java.awt.Adjustable#VERTICAL 57 */ 58 private int orientation; 59 60 /** 61 * The value of this scrollbar. 62 * {@code value} should be greater than {@code minimum} 63 * and less than {@code maximum} 64 * 65 * @serial 66 * @see #getValue 67 * @see #setValue 68 */ 69 private int value; 70 71 /** 72 * The minimum value of this scrollbar. 73 * This value can only be set by the {@code ScrollPane}. 74 * <p> 75 * <strong>ATTN:</strong> In current implementation 76 * {@code minimum} is always {@code 0}. This field can 77 * only be altered via {@code setSpan} method and 78 * {@code ScrollPane} always calls that method with 79 * {@code 0} for the minimum. {@code getMinimum} method 80 * always returns {@code 0} without checking this field. 81 * 82 * @serial 83 * @see #getMinimum 84 * @see #setSpan(int, int, int) 85 */ 86 private int minimum; 87 88 /** 89 * The maximum value of this scrollbar. 90 * This value can only be set by the {@code ScrollPane}. 91 * 92 * @serial 93 * @see #getMaximum 94 * @see #setSpan(int, int, int) 95 */ 96 private int maximum; 97 98 /** 99 * The size of the visible portion of this scrollbar. 100 * This value can only be set by the {@code ScrollPane}. 101 * 102 * @serial 103 * @see #getVisibleAmount 104 * @see #setSpan(int, int, int) 105 */ 106 private int visibleAmount; 107 108 /** 109 * The adjusting status of the {@code Scrollbar}. 110 * True if the value is in the process of changing as a result of 111 * actions being taken by the user. 112 * 113 * @see #getValueIsAdjusting 114 * @see #setValueIsAdjusting 115 * @since 1.4 116 */ 117 private transient boolean isAdjusting; 118 119 /** 120 * The amount by which the scrollbar value will change when going 121 * up or down by a line. 122 * This value should be a non negative integer. 123 * 124 * @serial 125 * @see #getUnitIncrement 126 * @see #setUnitIncrement 127 */ 128 private int unitIncrement = 1; 129 130 /** 131 * The amount by which the scrollbar value will change when going 132 * up or down by a page. 133 * This value should be a non negative integer. 134 * 135 * @serial 136 * @see #getBlockIncrement 137 * @see #setBlockIncrement 138 */ 139 private int blockIncrement = 1; 140 141 @SuppressWarnings("serial") // Not statically typed as Serializable 142 private AdjustmentListener adjustmentListener; 143 144 /** 145 * Error message for {@code AWTError} reported when one of 146 * the public but unsupported methods is called. 147 */ 148 private static final String SCROLLPANE_ONLY = 149 "Can be set by scrollpane only"; 150 151 152 /** 153 * Initialize JNI field and method ids. 154 */ 155 private static native void initIDs(); 156 157 static { 158 Toolkit.loadLibraries(); 159 if (!GraphicsEnvironment.isHeadless()) { 160 initIDs(); 161 } 162 AWTAccessor.setScrollPaneAdjustableAccessor(new AWTAccessor.ScrollPaneAdjustableAccessor() { 163 public void setTypedValue(final ScrollPaneAdjustable adj, 164 final int v, final int type) { 165 adj.setTypedValue(v, type); 166 } 167 }); 168 } 169 170 /** 171 * JDK 1.1 serialVersionUID. 172 */ 173 private static final long serialVersionUID = -3359745691033257079L; 174 175 176 /** 177 * Constructs a new object to represent specified scrollabar 178 * of the specified {@code ScrollPane}. 179 * Only ScrollPane creates instances of this class. 180 * @param sp {@code ScrollPane} 181 * @param l {@code AdjustmentListener} to add upon creation. 182 * @param orientation specifies which scrollbar this object represents, 183 * can be either {@code Adjustable.HORIZONTAL} 184 * or {@code Adjustable.VERTICAL}. 185 */ 186 ScrollPaneAdjustable(ScrollPane sp, AdjustmentListener l, int orientation) { 187 this.sp = sp; 188 this.orientation = orientation; 189 addAdjustmentListener(l); 190 } 191 192 /** 193 * This is called by the scrollpane itself to update the 194 * {@code minimum}, {@code maximum} and 195 * {@code visible} values. The scrollpane is the only one 196 * that should be changing these since it is the source of these 197 * values. 198 */ 199 void setSpan(int min, int max, int visible) { 200 // adjust the values to be reasonable 201 minimum = min; 202 maximum = Math.max(max, minimum + 1); 203 visibleAmount = Math.min(visible, maximum - minimum); 204 visibleAmount = Math.max(visibleAmount, 1); 205 blockIncrement = Math.max((int)(visible * .90), 1); 206 setValue(value); 207 } 208 209 /** 210 * Returns the orientation of this scrollbar. 211 * @return the orientation of this scrollbar, either 212 * {@code Adjustable.HORIZONTAL} or 213 * {@code Adjustable.VERTICAL} 214 */ 215 public int getOrientation() { 216 return orientation; 217 } 218 219 /** 220 * This method should <strong>NOT</strong> be called by user code. 221 * This method is public for this class to properly implement 222 * {@code Adjustable} interface. 223 * 224 * @throws AWTError Always throws an error when called. 225 */ 226 public void setMinimum(int min) { 227 throw new AWTError(SCROLLPANE_ONLY); 228 } 229 230 public int getMinimum() { 231 // XXX: This relies on setSpan always being called with 0 for 232 // the minimum (which is currently true). 233 return 0; 234 } 235 236 /** 237 * This method should <strong>NOT</strong> be called by user code. 238 * This method is public for this class to properly implement 239 * {@code Adjustable} interface. 240 * 241 * @throws AWTError Always throws an error when called. 242 */ 243 public void setMaximum(int max) { 244 throw new AWTError(SCROLLPANE_ONLY); 245 } 246 247 public int getMaximum() { 248 return maximum; 249 } 250 251 public synchronized void setUnitIncrement(int u) { 252 if (u != unitIncrement) { 253 unitIncrement = u; 254 if (sp.peer != null) { 255 ScrollPanePeer peer = (ScrollPanePeer) sp.peer; 256 peer.setUnitIncrement(this, u); 257 } 258 } 259 } 260 261 public int getUnitIncrement() { 262 return unitIncrement; 263 } 264 265 public synchronized void setBlockIncrement(int b) { 266 blockIncrement = b; 267 } 268 269 public int getBlockIncrement() { 270 return blockIncrement; 271 } 272 273 /** 274 * This method should <strong>NOT</strong> be called by user code. 275 * This method is public for this class to properly implement 276 * {@code Adjustable} interface. 277 * 278 * @throws AWTError Always throws an error when called. 279 */ 280 public void setVisibleAmount(int v) { 281 throw new AWTError(SCROLLPANE_ONLY); 282 } 283 284 public int getVisibleAmount() { 285 return visibleAmount; 286 } 287 288 289 /** 290 * Sets the {@code valueIsAdjusting} property. 291 * 292 * @param b new adjustment-in-progress status 293 * @see #getValueIsAdjusting 294 * @since 1.4 295 */ 296 public void setValueIsAdjusting(boolean b) { 297 if (isAdjusting != b) { 298 isAdjusting = b; 299 AdjustmentEvent e = 300 new AdjustmentEvent(this, 301 AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED, 302 AdjustmentEvent.TRACK, value, b); 303 adjustmentListener.adjustmentValueChanged(e); 304 } 305 } 306 307 /** 308 * Returns true if the value is in the process of changing as a 309 * result of actions being taken by the user. 310 * 311 * @return the value of the {@code valueIsAdjusting} property 312 * @see #setValueIsAdjusting 313 */ 314 public boolean getValueIsAdjusting() { 315 return isAdjusting; 316 } 317 318 /** 319 * Sets the value of this scrollbar to the specified value. 320 * <p> 321 * If the value supplied is less than the current minimum or 322 * greater than the current maximum, then one of those values is 323 * substituted, as appropriate. 324 * 325 * @param v the new value of the scrollbar 326 */ 327 public void setValue(int v) { 328 setTypedValue(v, AdjustmentEvent.TRACK); 329 } 330 331 /** 332 * Sets the value of this scrollbar to the specified value. 333 * <p> 334 * If the value supplied is less than the current minimum or 335 * greater than the current maximum, then one of those values is 336 * substituted, as appropriate. Also, creates and dispatches 337 * the AdjustmentEvent with specified type and value. 338 * 339 * @param v the new value of the scrollbar 340 * @param type the type of the scrolling operation occurred 341 */ 342 private void setTypedValue(int v, int type) { 343 v = Math.max(v, minimum); 344 v = Math.min(v, maximum - visibleAmount); 345 346 if (v != value) { 347 value = v; 348 // Synchronously notify the listeners so that they are 349 // guaranteed to be up-to-date with the Adjustable before 350 // it is mutated again. 351 AdjustmentEvent e = 352 new AdjustmentEvent(this, 353 AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED, 354 type, value, isAdjusting); 355 adjustmentListener.adjustmentValueChanged(e); 356 } 357 } 358 359 public int getValue() { 360 return value; 361 } 362 363 /** 364 * Adds the specified adjustment listener to receive adjustment 365 * events from this {@code ScrollPaneAdjustable}. 366 * If {@code l} is {@code null}, no exception is thrown 367 * and no action is performed. 368 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads" 369 * >AWT Threading Issues</a> for details on AWT's threading model. 370 * 371 * @param l the adjustment listener. 372 * @see #removeAdjustmentListener 373 * @see #getAdjustmentListeners 374 * @see java.awt.event.AdjustmentListener 375 * @see java.awt.event.AdjustmentEvent 376 */ 377 public synchronized void addAdjustmentListener(AdjustmentListener l) { 378 if (l == null) { 379 return; 380 } 381 adjustmentListener = AWTEventMulticaster.add(adjustmentListener, l); 382 } 383 384 /** 385 * Removes the specified adjustment listener so that it no longer 386 * receives adjustment events from this {@code ScrollPaneAdjustable}. 387 * If {@code l} is {@code null}, no exception is thrown 388 * and no action is performed. 389 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads" 390 * >AWT Threading Issues</a> for details on AWT's threading model. 391 * 392 * @param l the adjustment listener. 393 * @see #addAdjustmentListener 394 * @see #getAdjustmentListeners 395 * @see java.awt.event.AdjustmentListener 396 * @see java.awt.event.AdjustmentEvent 397 * @since 1.1 398 */ 399 public synchronized void removeAdjustmentListener(AdjustmentListener l){ 400 if (l == null) { 401 return; 402 } 403 adjustmentListener = AWTEventMulticaster.remove(adjustmentListener, l); 404 } 405 406 /** 407 * Returns an array of all the adjustment listeners 408 * registered on this {@code ScrollPaneAdjustable}. 409 * 410 * @return all of this {@code ScrollPaneAdjustable}'s 411 * {@code AdjustmentListener}s 412 * or an empty array if no adjustment 413 * listeners are currently registered 414 * 415 * @see #addAdjustmentListener 416 * @see #removeAdjustmentListener 417 * @see java.awt.event.AdjustmentListener 418 * @see java.awt.event.AdjustmentEvent 419 * @since 1.4 420 */ 421 public synchronized AdjustmentListener[] getAdjustmentListeners() { 422 return AWTEventMulticaster.getListeners(adjustmentListener, 423 AdjustmentListener.class); 424 } 425 426 /** 427 * Returns a string representation of this scrollbar and its values. 428 * @return a string representation of this scrollbar. 429 */ 430 public String toString() { 431 return getClass().getName() + "[" + paramString() + "]"; 432 } 433 434 /** 435 * Returns a string representing the state of this scrollbar. 436 * This method is intended to be used only for debugging purposes, 437 * and the content and format of the returned string may vary 438 * between implementations. The returned string may be empty but 439 * may not be {@code null}. 440 * 441 * @return the parameter string of this scrollbar. 442 */ 443 public String paramString() { 444 return ((orientation == Adjustable.VERTICAL ? "vertical," 445 :"horizontal,") 446 + "[0.."+maximum+"]" 447 + ",val=" + value 448 + ",vis=" + visibleAmount 449 + ",unit=" + unitIncrement 450 + ",block=" + blockIncrement 451 + ",isAdjusting=" + isAdjusting); 452 } 453 }