1 /* 2 * Copyright (c) 2000, 2006, 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</code>. Objects of this class are 38 * returned by <code>ScrollPane</code> methods. 39 * 40 * @since 1.4 41 */ 42 public class ScrollPaneAdjustable implements Adjustable, Serializable { 43 44 /** 45 * The <code>ScrollPane</code> 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</code> should be greater than <code>minimum</code> 63 * and less than <code>maximum</code> 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</code>. 74 * <p> 75 * <strong>ATTN:</strong> In current implementation 76 * <code>minimum</code> is always <code>0</code>. This field can 77 * only be altered via <code>setSpan</code> method and 78 * <code>ScrollPane</code> always calls that method with 79 * <code>0</code> for the minimum. <code>getMinimum</code> method 80 * always returns <code>0</code> 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</code>. 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</code>. 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</code>. 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 private AdjustmentListener adjustmentListener; 142 143 /** 144 * Error message for <code>AWTError</code> reported when one of 145 * the public but unsupported methods is called. 146 */ 147 private static final String SCROLLPANE_ONLY = 148 "Can be set by scrollpane only"; 149 150 151 /** 152 * Initialize JNI field and method ids. 153 */ 154 private static native void initIDs(); 155 156 static { 157 Toolkit.loadLibraries(); 158 if (!GraphicsEnvironment.isHeadless()) { 159 initIDs(); 160 } 161 AWTAccessor.setScrollPaneAdjustableAccessor(new AWTAccessor.ScrollPaneAdjustableAccessor() { 162 public void setTypedValue(final ScrollPaneAdjustable adj, 163 final int v, final int type) { 164 adj.setTypedValue(v, type); 165 } 166 }); 167 } 168 169 /** 170 * JDK 1.1 serialVersionUID. 171 */ 172 private static final long serialVersionUID = -3359745691033257079L; 173 174 175 /** 176 * Constructs a new object to represent specified scrollabar 177 * of the specified <code>ScrollPane</code>. 178 * Only ScrollPane creates instances of this class. 179 * @param sp <code>ScrollPane</code> 180 * @param l <code>AdjustmentListener</code> to add upon creation. 181 * @param orientation specifies which scrollbar this object represents, 182 * can be either <code>Adjustable.HORIZONTAL</code> 183 * or <code>Adjustable.VERTICAL</code>. 184 */ 185 ScrollPaneAdjustable(ScrollPane sp, AdjustmentListener l, int orientation) { 186 this.sp = sp; 187 this.orientation = orientation; 188 addAdjustmentListener(l); 189 } 190 191 /** 192 * This is called by the scrollpane itself to update the 193 * <code>minimum</code>, <code>maximum</code> and 194 * <code>visible</code> values. The scrollpane is the only one 195 * that should be changing these since it is the source of these 196 * values. 197 */ 198 void setSpan(int min, int max, int visible) { 199 // adjust the values to be reasonable 200 minimum = min; 201 maximum = Math.max(max, minimum + 1); 202 visibleAmount = Math.min(visible, maximum - minimum); 203 visibleAmount = Math.max(visibleAmount, 1); 204 blockIncrement = Math.max((int)(visible * .90), 1); 205 setValue(value); 206 } 207 208 /** 209 * Returns the orientation of this scrollbar. 210 * @return the orientation of this scrollbar, either 211 * <code>Adjustable.HORIZONTAL</code> or 212 * <code>Adjustable.VERTICAL</code> 213 */ 214 public int getOrientation() { 215 return orientation; 216 } 217 218 /** 219 * This method should <strong>NOT</strong> be called by user code. 220 * This method is public for this class to properly implement 221 * <code>Adjustable</code> interface. 222 * 223 * @throws AWTError Always throws an error when called. 224 */ 225 public void setMinimum(int min) { 226 throw new AWTError(SCROLLPANE_ONLY); 227 } 228 229 public int getMinimum() { 230 // XXX: This relies on setSpan always being called with 0 for 231 // the minimum (which is currently true). 232 return 0; 233 } 234 235 /** 236 * This method should <strong>NOT</strong> be called by user code. 237 * This method is public for this class to properly implement 238 * <code>Adjustable</code> interface. 239 * 240 * @throws AWTError Always throws an error when called. 241 */ 242 public void setMaximum(int max) { 243 throw new AWTError(SCROLLPANE_ONLY); 244 } 245 246 public int getMaximum() { 247 return maximum; 248 } 249 250 public synchronized void setUnitIncrement(int u) { 251 if (u != unitIncrement) { 252 unitIncrement = u; 253 if (sp.peer != null) { 254 ScrollPanePeer peer = (ScrollPanePeer) sp.peer; 255 peer.setUnitIncrement(this, u); 256 } 257 } 258 } 259 260 public int getUnitIncrement() { 261 return unitIncrement; 262 } 263 264 public synchronized void setBlockIncrement(int b) { 265 blockIncrement = b; 266 } 267 268 public int getBlockIncrement() { 269 return blockIncrement; 270 } 271 272 /** 273 * This method should <strong>NOT</strong> be called by user code. 274 * This method is public for this class to properly implement 275 * <code>Adjustable</code> interface. 276 * 277 * @throws AWTError Always throws an error when called. 278 */ 279 public void setVisibleAmount(int v) { 280 throw new AWTError(SCROLLPANE_ONLY); 281 } 282 283 public int getVisibleAmount() { 284 return visibleAmount; 285 } 286 287 288 /** 289 * Sets the <code>valueIsAdjusting</code> property. 290 * 291 * @param b new adjustment-in-progress status 292 * @see #getValueIsAdjusting 293 * @since 1.4 294 */ 295 public void setValueIsAdjusting(boolean b) { 296 if (isAdjusting != b) { 297 isAdjusting = b; 298 AdjustmentEvent e = 299 new AdjustmentEvent(this, 300 AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED, 301 AdjustmentEvent.TRACK, value, b); 302 adjustmentListener.adjustmentValueChanged(e); 303 } 304 } 305 306 /** 307 * Returns true if the value is in the process of changing as a 308 * result of actions being taken by the user. 309 * 310 * @return the value of the <code>valueIsAdjusting</code> property 311 * @see #setValueIsAdjusting 312 */ 313 public boolean getValueIsAdjusting() { 314 return isAdjusting; 315 } 316 317 /** 318 * Sets the value of this scrollbar to the specified value. 319 * <p> 320 * If the value supplied is less than the current minimum or 321 * greater than the current maximum, then one of those values is 322 * substituted, as appropriate. 323 * 324 * @param v the new value of the scrollbar 325 */ 326 public void setValue(int v) { 327 setTypedValue(v, AdjustmentEvent.TRACK); 328 } 329 330 /** 331 * Sets the value of this scrollbar to the specified value. 332 * <p> 333 * If the value supplied is less than the current minimum or 334 * greater than the current maximum, then one of those values is 335 * substituted, as appropriate. Also, creates and dispatches 336 * the AdjustementEvent with specified type and value. 337 * 338 * @param v the new value of the scrollbar 339 * @param type the type of the scrolling operation occurred 340 */ 341 private void setTypedValue(int v, int type) { 342 v = Math.max(v, minimum); 343 v = Math.min(v, maximum - visibleAmount); 344 345 if (v != value) { 346 value = v; 347 // Synchronously notify the listeners so that they are 348 // guaranteed to be up-to-date with the Adjustable before 349 // it is mutated again. 350 AdjustmentEvent e = 351 new AdjustmentEvent(this, 352 AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED, 353 type, value, isAdjusting); 354 adjustmentListener.adjustmentValueChanged(e); 355 } 356 } 357 358 public int getValue() { 359 return value; 360 } 361 362 /** 363 * Adds the specified adjustment listener to receive adjustment 364 * events from this <code>ScrollPaneAdjustable</code>. 365 * If <code>l</code> is <code>null</code>, no exception is thrown 366 * and no action is performed. 367 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads" 368 * >AWT Threading Issues</a> for details on AWT's threading model. 369 * 370 * @param l the adjustment listener. 371 * @see #removeAdjustmentListener 372 * @see #getAdjustmentListeners 373 * @see java.awt.event.AdjustmentListener 374 * @see java.awt.event.AdjustmentEvent 375 */ 376 public synchronized void addAdjustmentListener(AdjustmentListener l) { 377 if (l == null) { 378 return; 379 } 380 adjustmentListener = AWTEventMulticaster.add(adjustmentListener, l); 381 } 382 383 /** 384 * Removes the specified adjustment listener so that it no longer 385 * receives adjustment events from this <code>ScrollPaneAdjustable</code>. 386 * If <code>l</code> is <code>null</code>, no exception is thrown 387 * and no action is performed. 388 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads" 389 * >AWT Threading Issues</a> for details on AWT's threading model. 390 * 391 * @param l the adjustment listener. 392 * @see #addAdjustmentListener 393 * @see #getAdjustmentListeners 394 * @see java.awt.event.AdjustmentListener 395 * @see java.awt.event.AdjustmentEvent 396 * @since JDK1.1 397 */ 398 public synchronized void removeAdjustmentListener(AdjustmentListener l){ 399 if (l == null) { 400 return; 401 } 402 adjustmentListener = AWTEventMulticaster.remove(adjustmentListener, l); 403 } 404 405 /** 406 * Returns an array of all the adjustment listeners 407 * registered on this <code>ScrollPaneAdjustable</code>. 408 * 409 * @return all of this <code>ScrollPaneAdjustable</code>'s 410 * <code>AdjustmentListener</code>s 411 * or an empty array if no adjustment 412 * listeners are currently registered 413 * 414 * @see #addAdjustmentListener 415 * @see #removeAdjustmentListener 416 * @see java.awt.event.AdjustmentListener 417 * @see java.awt.event.AdjustmentEvent 418 * @since 1.4 419 */ 420 public synchronized AdjustmentListener[] getAdjustmentListeners() { 421 return (AdjustmentListener[])(AWTEventMulticaster.getListeners( 422 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</code>. 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 }