| /* | 
 |  * Copyright 2000-2006 Sun Microsystems, Inc.  All Rights Reserved. | 
 |  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 
 |  * | 
 |  * This code is free software; you can redistribute it and/or modify it | 
 |  * under the terms of the GNU General Public License version 2 only, as | 
 |  * published by the Free Software Foundation.  Sun designates this | 
 |  * particular file as subject to the "Classpath" exception as provided | 
 |  * by Sun in the LICENSE file that accompanied this code. | 
 |  * | 
 |  * This code is distributed in the hope that it will be useful, but WITHOUT | 
 |  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | 
 |  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License | 
 |  * version 2 for more details (a copy is included in the LICENSE file that | 
 |  * accompanied this code). | 
 |  * | 
 |  * You should have received a copy of the GNU General Public License version | 
 |  * 2 along with this work; if not, write to the Free Software Foundation, | 
 |  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | 
 |  * | 
 |  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | 
 |  * CA 95054 USA or visit www.sun.com if you need additional information or | 
 |  * have any questions. | 
 |  */ | 
 | package java.awt; | 
 |  | 
 | import java.awt.event.AdjustmentEvent; | 
 | import java.awt.event.AdjustmentListener; | 
 | import java.awt.peer.ScrollPanePeer; | 
 | import java.io.Serializable; | 
 |  | 
 |  | 
 | /** | 
 |  * This class represents the state of a horizontal or vertical | 
 |  * scrollbar of a <code>ScrollPane</code>.  Objects of this class are | 
 |  * returned by <code>ScrollPane</code> methods. | 
 |  * | 
 |  * @since       1.4 | 
 |  */ | 
 | public class ScrollPaneAdjustable implements Adjustable, Serializable { | 
 |  | 
 |     /** | 
 |      * The <code>ScrollPane</code> this object is a scrollbar of. | 
 |      * @serial | 
 |      */ | 
 |     private ScrollPane sp; | 
 |  | 
 |     /** | 
 |      * Orientation of this scrollbar. | 
 |      * | 
 |      * @serial | 
 |      * @see #getOrientation | 
 |      * @see java.awt.Adjustable#HORIZONTAL | 
 |      * @see java.awt.Adjustable#VERTICAL | 
 |      */ | 
 |     private int orientation; | 
 |  | 
 |     /** | 
 |      * The value of this scrollbar. | 
 |      * <code>value</code> should be greater than <code>minimum</code> | 
 |      * and less than <code>maximum</code> | 
 |      * | 
 |      * @serial | 
 |      * @see #getValue | 
 |      * @see #setValue | 
 |      */ | 
 |     private int value; | 
 |  | 
 |     /** | 
 |      * The minimum value of this scrollbar. | 
 |      * This value can only be set by the <code>ScrollPane</code>. | 
 |      * <p> | 
 |      * <strong>ATTN:</strong> In current implementation | 
 |      * <code>minimum</code> is always <code>0</code>.  This field can | 
 |      * only be altered via <code>setSpan</code> method and | 
 |      * <code>ScrollPane</code> always calls that method with | 
 |      * <code>0</code> for the minimum.  <code>getMinimum</code> method | 
 |      * always returns <code>0</code> without checking this field. | 
 |      * | 
 |      * @serial | 
 |      * @see #getMinimum | 
 |      * @see #setSpan(int, int, int) | 
 |      */ | 
 |     private int minimum; | 
 |  | 
 |     /** | 
 |      * The maximum value of this scrollbar. | 
 |      * This value can only be set by the <code>ScrollPane</code>. | 
 |      * | 
 |      * @serial | 
 |      * @see #getMaximum | 
 |      * @see #setSpan(int, int, int) | 
 |      */ | 
 |     private int maximum; | 
 |  | 
 |     /** | 
 |      * The size of the visible portion of this scrollbar. | 
 |      * This value can only be set by the <code>ScrollPane</code>. | 
 |      * | 
 |      * @serial | 
 |      * @see #getVisibleAmount | 
 |      * @see #setSpan(int, int, int) | 
 |      */ | 
 |     private int visibleAmount; | 
 |  | 
 |     /** | 
 |      * The adjusting status of the <code>Scrollbar</code>. | 
 |      * True if the value is in the process of changing as a result of | 
 |      * actions being taken by the user. | 
 |      * | 
 |      * @see #getValueIsAdjusting | 
 |      * @see #setValueIsAdjusting | 
 |      * @since 1.4 | 
 |      */ | 
 |     private transient boolean isAdjusting; | 
 |  | 
 |     /** | 
 |      * The amount by which the scrollbar value will change when going | 
 |      * up or down by a line. | 
 |      * This value should be a non negative integer. | 
 |      * | 
 |      * @serial | 
 |      * @see #getUnitIncrement | 
 |      * @see #setUnitIncrement | 
 |      */ | 
 |     private int unitIncrement  = 1; | 
 |  | 
 |     /** | 
 |      * The amount by which the scrollbar value will change when going | 
 |      * up or down by a page. | 
 |      * This value should be a non negative integer. | 
 |      * | 
 |      * @serial | 
 |      * @see #getBlockIncrement | 
 |      * @see #setBlockIncrement | 
 |      */ | 
 |     private int blockIncrement = 1; | 
 |  | 
 |     private AdjustmentListener adjustmentListener; | 
 |  | 
 |     /** | 
 |      * Error message for <code>AWTError</code> reported when one of | 
 |      * the public but unsupported methods is called. | 
 |      */ | 
 |     private static final String SCROLLPANE_ONLY = | 
 |         "Can be set by scrollpane only"; | 
 |  | 
 |  | 
 |     /** | 
 |      * Initialize JNI field and method ids. | 
 |      */ | 
 |     private static native void initIDs(); | 
 |  | 
 |     static { | 
 |         Toolkit.loadLibraries(); | 
 |         if (!GraphicsEnvironment.isHeadless()) { | 
 |             initIDs(); | 
 |         } | 
 |     } | 
 |  | 
 |     /** | 
 |      * JDK 1.1 serialVersionUID. | 
 |      */ | 
 |     private static final long serialVersionUID = -3359745691033257079L; | 
 |  | 
 |  | 
 |     /** | 
 |      * Constructs a new object to represent specified scrollabar | 
 |      * of the specified <code>ScrollPane</code>. | 
 |      * Only ScrollPane creates instances of this class. | 
 |      * @param sp           <code>ScrollPane</code> | 
 |      * @param l            <code>AdjustmentListener</code> to add upon creation. | 
 |      * @param orientation  specifies which scrollbar this object represents, | 
 |      *                     can be either  <code>Adjustable.HORIZONTAL</code> | 
 |      *                     or <code>Adjustable.VERTICAL</code>. | 
 |      */ | 
 |     ScrollPaneAdjustable(ScrollPane sp, AdjustmentListener l, int orientation) { | 
 |         this.sp = sp; | 
 |         this.orientation = orientation; | 
 |         addAdjustmentListener(l); | 
 |     } | 
 |  | 
 |     /** | 
 |      * This is called by the scrollpane itself to update the | 
 |      * <code>minimum</code>, <code>maximum</code> and | 
 |      * <code>visible</code> values.  The scrollpane is the only one | 
 |      * that should be changing these since it is the source of these | 
 |      * values. | 
 |      */ | 
 |     void setSpan(int min, int max, int visible) { | 
 |         // adjust the values to be reasonable | 
 |         minimum = min; | 
 |         maximum = Math.max(max, minimum + 1); | 
 |         visibleAmount = Math.min(visible, maximum - minimum); | 
 |         visibleAmount = Math.max(visibleAmount, 1); | 
 |         blockIncrement = Math.max((int)(visible * .90), 1); | 
 |         setValue(value); | 
 |     } | 
 |  | 
 |     /** | 
 |      * Returns the orientation of this scrollbar. | 
 |      * @return    the orientation of this scrollbar, either | 
 |      *            <code>Adjustable.HORIZONTAL</code> or | 
 |      *            <code>Adjustable.VERTICAL</code> | 
 |      */ | 
 |     public int getOrientation() { | 
 |         return orientation; | 
 |     } | 
 |  | 
 |     /** | 
 |      * This method should <strong>NOT</strong> be called by user code. | 
 |      * This method is public for this class to properly implement | 
 |      * <code>Adjustable</code> interface. | 
 |      * | 
 |      * @throws <code>AWTError</code>  Always throws an error when called. | 
 |      */ | 
 |     public void setMinimum(int min) { | 
 |         throw new AWTError(SCROLLPANE_ONLY); | 
 |     } | 
 |  | 
 |     public int getMinimum() { | 
 |         // XXX: This relies on setSpan always being called with 0 for | 
 |         // the minimum (which is currently true). | 
 |         return 0; | 
 |     } | 
 |  | 
 |     /** | 
 |      * This method should <strong>NOT</strong> be called by user code. | 
 |      * This method is public for this class to properly implement | 
 |      * <code>Adjustable</code> interface. | 
 |      * | 
 |      * @throws <code>AWTError</code>  Always throws an error when called. | 
 |      */ | 
 |     public void setMaximum(int max) { | 
 |         throw new AWTError(SCROLLPANE_ONLY); | 
 |     } | 
 |  | 
 |     public int getMaximum() { | 
 |         return maximum; | 
 |     } | 
 |  | 
 |     public synchronized void setUnitIncrement(int u) { | 
 |         if (u != unitIncrement) { | 
 |             unitIncrement = u; | 
 |             if (sp.peer != null) { | 
 |                 ScrollPanePeer peer = (ScrollPanePeer) sp.peer; | 
 |                 peer.setUnitIncrement(this, u); | 
 |             } | 
 |         } | 
 |     } | 
 |  | 
 |     public int getUnitIncrement() { | 
 |         return unitIncrement; | 
 |     } | 
 |  | 
 |     public synchronized void setBlockIncrement(int b) { | 
 |         blockIncrement = b; | 
 |     } | 
 |  | 
 |     public int getBlockIncrement() { | 
 |         return blockIncrement; | 
 |     } | 
 |  | 
 |     /** | 
 |      * This method should <strong>NOT</strong> be called by user code. | 
 |      * This method is public for this class to properly implement | 
 |      * <code>Adjustable</code> interface. | 
 |      * | 
 |      * @throws <code>AWTError</code>  Always throws an error when called. | 
 |      */ | 
 |     public void setVisibleAmount(int v) { | 
 |         throw new AWTError(SCROLLPANE_ONLY); | 
 |     } | 
 |  | 
 |     public int getVisibleAmount() { | 
 |         return visibleAmount; | 
 |     } | 
 |  | 
 |  | 
 |     /** | 
 |      * Sets the <code>valueIsAdjusting</code> property. | 
 |      * | 
 |      * @param b new adjustment-in-progress status | 
 |      * @see #getValueIsAdjusting | 
 |      * @since 1.4 | 
 |      */ | 
 |     public void setValueIsAdjusting(boolean b) { | 
 |         if (isAdjusting != b) { | 
 |             isAdjusting = b; | 
 |             AdjustmentEvent e = | 
 |                 new AdjustmentEvent(this, | 
 |                         AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED, | 
 |                         AdjustmentEvent.TRACK, value, b); | 
 |             adjustmentListener.adjustmentValueChanged(e); | 
 |         } | 
 |     } | 
 |  | 
 |     /** | 
 |      * Returns true if the value is in the process of changing as a | 
 |      * result of actions being taken by the user. | 
 |      * | 
 |      * @return the value of the <code>valueIsAdjusting</code> property | 
 |      * @see #setValueIsAdjusting | 
 |      */ | 
 |     public boolean getValueIsAdjusting() { | 
 |         return isAdjusting; | 
 |     } | 
 |  | 
 |     /** | 
 |      * Sets the value of this scrollbar to the specified value. | 
 |      * <p> | 
 |      * If the value supplied is less than the current minimum or | 
 |      * greater than the current maximum, then one of those values is | 
 |      * substituted, as appropriate. | 
 |      * | 
 |      * @param v the new value of the scrollbar | 
 |      */ | 
 |     public void setValue(int v) { | 
 |         setTypedValue(v, AdjustmentEvent.TRACK); | 
 |     } | 
 |  | 
 |     /** | 
 |      * Sets the value of this scrollbar to the specified value. | 
 |      * <p> | 
 |      * If the value supplied is less than the current minimum or | 
 |      * greater than the current maximum, then one of those values is | 
 |      * substituted, as appropriate. Also, creates and dispatches | 
 |      * the AdjustementEvent with specified type and value. | 
 |      * | 
 |      * @param v the new value of the scrollbar | 
 |      * @param type the type of the scrolling operation occured | 
 |      */ | 
 |     private void setTypedValue(int v, int type) { | 
 |         v = Math.max(v, minimum); | 
 |         v = Math.min(v, maximum - visibleAmount); | 
 |  | 
 |         if (v != value) { | 
 |             value = v; | 
 |             // Synchronously notify the listeners so that they are | 
 |             // guaranteed to be up-to-date with the Adjustable before | 
 |             // it is mutated again. | 
 |             AdjustmentEvent e = | 
 |                 new AdjustmentEvent(this, | 
 |                         AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED, | 
 |                         type, value, isAdjusting); | 
 |             adjustmentListener.adjustmentValueChanged(e); | 
 |         } | 
 |     } | 
 |  | 
 |     public int getValue() { | 
 |         return value; | 
 |     } | 
 |  | 
 |     /** | 
 |      * Adds the specified adjustment listener to receive adjustment | 
 |      * events from this <code>ScrollPaneAdjustable</code>. | 
 |      * If <code>l</code> is <code>null</code>, no exception is thrown | 
 |      * and no action is performed. | 
 |      * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads" | 
 |      * >AWT Threading Issues</a> for details on AWT's threading model. | 
 |      * | 
 |      * @param    l   the adjustment listener. | 
 |      * @see      #removeAdjustmentListener | 
 |      * @see      #getAdjustmentListeners | 
 |      * @see      java.awt.event.AdjustmentListener | 
 |      * @see      java.awt.event.AdjustmentEvent | 
 |      */ | 
 |     public synchronized void addAdjustmentListener(AdjustmentListener l) { | 
 |         if (l == null) { | 
 |             return; | 
 |         } | 
 |         adjustmentListener = AWTEventMulticaster.add(adjustmentListener, l); | 
 |     } | 
 |  | 
 |     /** | 
 |      * Removes the specified adjustment listener so that it no longer | 
 |      * receives adjustment events from this <code>ScrollPaneAdjustable</code>. | 
 |      * If <code>l</code> is <code>null</code>, no exception is thrown | 
 |      * and no action is performed. | 
 |      * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads" | 
 |      * >AWT Threading Issues</a> for details on AWT's threading model. | 
 |      * | 
 |      * @param         l     the adjustment listener. | 
 |      * @see           #addAdjustmentListener | 
 |      * @see           #getAdjustmentListeners | 
 |      * @see           java.awt.event.AdjustmentListener | 
 |      * @see           java.awt.event.AdjustmentEvent | 
 |      * @since         JDK1.1 | 
 |      */ | 
 |     public synchronized void removeAdjustmentListener(AdjustmentListener l){ | 
 |         if (l == null) { | 
 |             return; | 
 |         } | 
 |         adjustmentListener = AWTEventMulticaster.remove(adjustmentListener, l); | 
 |     } | 
 |  | 
 |     /** | 
 |      * Returns an array of all the adjustment listeners | 
 |      * registered on this <code>ScrollPaneAdjustable</code>. | 
 |      * | 
 |      * @return all of this <code>ScrollPaneAdjustable</code>'s | 
 |      *         <code>AdjustmentListener</code>s | 
 |      *         or an empty array if no adjustment | 
 |      *         listeners are currently registered | 
 |      * | 
 |      * @see           #addAdjustmentListener | 
 |      * @see           #removeAdjustmentListener | 
 |      * @see           java.awt.event.AdjustmentListener | 
 |      * @see           java.awt.event.AdjustmentEvent | 
 |      * @since 1.4 | 
 |      */ | 
 |     public synchronized AdjustmentListener[] getAdjustmentListeners() { | 
 |         return (AdjustmentListener[])(AWTEventMulticaster.getListeners( | 
 |                                       adjustmentListener, | 
 |                                       AdjustmentListener.class)); | 
 |     } | 
 |  | 
 |     /** | 
 |      * Returns a string representation of this scrollbar and its values. | 
 |      * @return    a string representation of this scrollbar. | 
 |      */ | 
 |     public String toString() { | 
 |         return getClass().getName() + "[" + paramString() + "]"; | 
 |     } | 
 |  | 
 |     /** | 
 |      * Returns a string representing the state of this scrollbar. | 
 |      * This method is intended to be used only for debugging purposes, | 
 |      * and the content and format of the returned string may vary | 
 |      * between implementations.  The returned string may be empty but | 
 |      * may not be <code>null</code>. | 
 |      * | 
 |      * @return      the parameter string of this scrollbar. | 
 |      */ | 
 |     public String paramString() { | 
 |         return ((orientation == Adjustable.VERTICAL ? "vertical," | 
 |                                                     :"horizontal,") | 
 |                 + "[0.."+maximum+"]" | 
 |                 + ",val=" + value | 
 |                 + ",vis=" + visibleAmount | 
 |                 + ",unit=" + unitIncrement | 
 |                 + ",block=" + blockIncrement | 
 |                 + ",isAdjusting=" + isAdjusting); | 
 |     } | 
 | } |