1. /*
  2. * @(#)ScrollPaneAdjustable.java 1.7 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.awt;
  8. import java.awt.event.AdjustmentEvent;
  9. import java.awt.event.AdjustmentListener;
  10. import java.awt.peer.ScrollPanePeer;
  11. import java.io.Serializable;
  12. /**
  13. * This class represents the state of a horizontal or vertical
  14. * scrollbar of a <code>ScrollPane</code>. Objects of this class are
  15. * returned by <code>ScrollPane</code> methods.
  16. *
  17. * @version 1.7 01/23/03
  18. * @since 1.4
  19. */
  20. public class ScrollPaneAdjustable implements Adjustable, Serializable {
  21. /**
  22. * The <code>ScrollPane</code> this object is a scrollbar of.
  23. * @serial
  24. */
  25. private ScrollPane sp;
  26. /**
  27. * Orientation of this scrollbar.
  28. *
  29. * @serial
  30. * @see #getOrientation
  31. * @see java.awt.Adjustable#HORIZONTAL
  32. * @see java.awt.Adjustable#VERTICAL
  33. */
  34. private int orientation;
  35. /**
  36. * The value of this scrollbar.
  37. * <code>value</code> should be greater than <code>minimum</code>
  38. * and less than <code>maximum</code>
  39. *
  40. * @serial
  41. * @see #getValue
  42. * @see #setValue
  43. */
  44. private int value;
  45. /**
  46. * The minimum value of this scrollbar.
  47. * This value can only be set by the <code>ScrollPane</code>.
  48. * <p>
  49. * <strong>ATTN:</strong> In current implementation
  50. * <code>minimum</code> is always <code>0</code>. This field can
  51. * only be altered via <code>setSpan</code> method and
  52. * <code>ScrollPane</code> always calls that method with
  53. * <code>0</code> for the minimum. <code>getMinimum</code> method
  54. * always returns <code>0</code> without checking this field.
  55. *
  56. * @serial
  57. * @see #getMinimum
  58. * @see #setSpan(int, int, int)
  59. */
  60. private int minimum;
  61. /**
  62. * The maximum value of this scrollbar.
  63. * This value can only be set by the <code>ScrollPane</code>.
  64. *
  65. * @serial
  66. * @see #getMaximum
  67. * @see #setSpan(int, int, int)
  68. */
  69. private int maximum;
  70. /**
  71. * The size of the visible portion of this scrollbar.
  72. * This value can only be set by the <code>ScrollPane</code>.
  73. *
  74. * @serial
  75. * @see #getVisibleAmount
  76. * @see #setSpan(int, int, int)
  77. */
  78. private int visibleAmount;
  79. /**
  80. * The adjusting status of the <code>Scrollbar</code>.
  81. * True if the value is in the process of changing as a result of
  82. * actions being taken by the user.
  83. *
  84. * @see #getValueIsAdjusting
  85. * @see #setValueIsAdjusting
  86. * @since 1.4
  87. */
  88. private transient boolean isAdjusting;
  89. /**
  90. * The amount by which the scrollbar value will change when going
  91. * up or down by a line.
  92. * This value should be a non negative integer.
  93. *
  94. * @serial
  95. * @see #getUnitIncrement
  96. * @see #setUnitIncrement
  97. */
  98. private int unitIncrement = 1;
  99. /**
  100. * The amount by which the scrollbar value will change when going
  101. * up or down by a page.
  102. * This value should be a non negative integer.
  103. *
  104. * @serial
  105. * @see #getBlockIncrement
  106. * @see #setBlockIncrement
  107. */
  108. private int blockIncrement = 1;
  109. private AdjustmentListener adjustmentListener;
  110. /**
  111. * Error message for <code>AWTError</code> reported when one of
  112. * the public but unsupported methods is called.
  113. */
  114. private static final String SCROLLPANE_ONLY =
  115. "Can be set by scrollpane only";
  116. /**
  117. * Initialize JNI field and method ids.
  118. */
  119. private static native void initIDs();
  120. static {
  121. Toolkit.loadLibraries();
  122. if (!GraphicsEnvironment.isHeadless()) {
  123. initIDs();
  124. }
  125. }
  126. /**
  127. * JDK 1.1 serialVersionUID.
  128. */
  129. private static final long serialVersionUID = -3359745691033257079L;
  130. /**
  131. * Constructs a new object to represent specified scrollabar
  132. * of the specified <code>ScrollPane</code>.
  133. * Only ScrollPane creates instances of this class.
  134. * @param sp <code>ScrollPane</code>
  135. * @param l <code>AdjustmentListener</code> to add upon creation.
  136. * @param orientation specifies which scrollbar this object represents,
  137. * can be either <code>Adjustable.HORIZONTAL</code>
  138. * or <code>Adjustable.VERTICAL</code>.
  139. */
  140. ScrollPaneAdjustable(ScrollPane sp, AdjustmentListener l, int orientation) {
  141. this.sp = sp;
  142. this.orientation = orientation;
  143. addAdjustmentListener(l);
  144. }
  145. /**
  146. * This is called by the scrollpane itself to update the
  147. * <code>minimum</code>, <code>maximum</code> and
  148. * <code>visible</code> values. The scrollpane is the only one
  149. * that should be changing these since it is the source of these
  150. * values.
  151. */
  152. void setSpan(int min, int max, int visible) {
  153. // adjust the values to be reasonable
  154. minimum = min;
  155. maximum = Math.max(max, minimum + 1);
  156. visibleAmount = Math.min(visible, maximum - minimum);
  157. visibleAmount = Math.max(visibleAmount, 1);
  158. blockIncrement = Math.max((int)(visible * .90), 1);
  159. setValue(value);
  160. }
  161. /**
  162. * Returns the orientation of this scrollbar.
  163. * @return the orientation of this scrollbar, either
  164. * <code>Adjustable.HORIZONTAL</code> or
  165. * <code>Adjustable.VERTICAL</code>
  166. */
  167. public int getOrientation() {
  168. return orientation;
  169. }
  170. /**
  171. * This method should <strong>NOT</strong> be called by user code.
  172. * This method is public for this class to properly implement
  173. * <code>Adjustable</code> interface.
  174. *
  175. * @throws <code>AWTError</code> Always throws an error when called.
  176. */
  177. public void setMinimum(int min) {
  178. throw new AWTError(SCROLLPANE_ONLY);
  179. }
  180. public int getMinimum() {
  181. // XXX: This relies on setSpan always being called with 0 for
  182. // the minimum (which is currently true).
  183. return 0;
  184. }
  185. /**
  186. * This method should <strong>NOT</strong> be called by user code.
  187. * This method is public for this class to properly implement
  188. * <code>Adjustable</code> interface.
  189. *
  190. * @throws <code>AWTError</code> Always throws an error when called.
  191. */
  192. public void setMaximum(int max) {
  193. throw new AWTError(SCROLLPANE_ONLY);
  194. }
  195. public int getMaximum() {
  196. return maximum;
  197. }
  198. public synchronized void setUnitIncrement(int u) {
  199. if (u != unitIncrement) {
  200. unitIncrement = u;
  201. if (sp.peer != null) {
  202. ScrollPanePeer peer = (ScrollPanePeer) sp.peer;
  203. peer.setUnitIncrement(this, u);
  204. }
  205. }
  206. }
  207. public int getUnitIncrement() {
  208. return unitIncrement;
  209. }
  210. public synchronized void setBlockIncrement(int b) {
  211. blockIncrement = b;
  212. }
  213. public int getBlockIncrement() {
  214. return blockIncrement;
  215. }
  216. /**
  217. * This method should <strong>NOT</strong> be called by user code.
  218. * This method is public for this class to properly implement
  219. * <code>Adjustable</code> interface.
  220. *
  221. * @throws <code>AWTError</code> Always throws an error when called.
  222. */
  223. public void setVisibleAmount(int v) {
  224. throw new AWTError(SCROLLPANE_ONLY);
  225. }
  226. public int getVisibleAmount() {
  227. return visibleAmount;
  228. }
  229. /**
  230. * Sets the <code>valueIsAdjusting</code> property.
  231. *
  232. * @param b new adjustment-in-progress status
  233. * @see #getValueIsAdjusting
  234. * @since 1.4
  235. */
  236. public void setValueIsAdjusting(boolean b) {
  237. if (isAdjusting != b) {
  238. isAdjusting = b;
  239. AdjustmentEvent e =
  240. new AdjustmentEvent(this,
  241. AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED,
  242. AdjustmentEvent.TRACK, value, b);
  243. adjustmentListener.adjustmentValueChanged(e);
  244. }
  245. }
  246. /**
  247. * Returns true if the value is in the process of changing as a
  248. * result of actions being taken by the user.
  249. *
  250. * @return the value of the <code>valueIsAdjusting</code> property
  251. * @see #setValueIsAdjusting
  252. */
  253. public boolean getValueIsAdjusting() {
  254. return isAdjusting;
  255. }
  256. /**
  257. * Sets the value of this scrollbar to the specified value.
  258. * <p>
  259. * If the value supplied is less than the current minimum or
  260. * greater than the current maximum, then one of those values is
  261. * substituted, as appropriate.
  262. *
  263. * @param v the new value of the scrollbar
  264. */
  265. public void setValue(int v) {
  266. // bounds check
  267. v = Math.max(v, minimum);
  268. v = Math.min(v, maximum - visibleAmount);
  269. if (v != value) {
  270. value = v;
  271. // Synchronously notify the listeners so that they are
  272. // guaranteed to be up-to-date with the Adjustable before
  273. // it is mutated again.
  274. AdjustmentEvent e =
  275. new AdjustmentEvent(this,
  276. AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED,
  277. AdjustmentEvent.TRACK, value, isAdjusting);
  278. adjustmentListener.adjustmentValueChanged(e);
  279. }
  280. }
  281. public int getValue() {
  282. return value;
  283. }
  284. /**
  285. * Adds the specified adjustment listener to receive adjustment
  286. * events from this <code>ScrollPaneAdjustable</code>.
  287. * If <code>l</code> is <code>null</code>, no exception is thrown
  288. * and no action is performed.
  289. *
  290. * @param l the adjustment listener.
  291. * @see #removeAdjustmentListener
  292. * @see #getAdjustmentListeners
  293. * @see java.awt.event.AdjustmentListener
  294. * @see java.awt.event.AdjustmentEvent
  295. */
  296. public synchronized void addAdjustmentListener(AdjustmentListener l) {
  297. if (l == null) {
  298. return;
  299. }
  300. adjustmentListener = AWTEventMulticaster.add(adjustmentListener, l);
  301. }
  302. /**
  303. * Removes the specified adjustment listener so that it no longer
  304. * receives adjustment events from this <code>ScrollPaneAdjustable</code>.
  305. * If <code>l</code> is <code>null</code>, no exception is thrown
  306. * and no action is performed.
  307. *
  308. * @param l the adjustment listener.
  309. * @see #addAdjustmentListener
  310. * @see #getAdjustmentListeners
  311. * @see java.awt.event.AdjustmentListener
  312. * @see java.awt.event.AdjustmentEvent
  313. * @since JDK1.1
  314. */
  315. public synchronized void removeAdjustmentListener(AdjustmentListener l){
  316. if (l == null) {
  317. return;
  318. }
  319. adjustmentListener = AWTEventMulticaster.remove(adjustmentListener, l);
  320. }
  321. /**
  322. * Returns an array of all the adjustment listeners
  323. * registered on this <code>ScrollPaneAdjustable</code>.
  324. *
  325. * @return all of this <code>ScrollPaneAdjustable</code>'s
  326. * <code>AdjustmentListener</code>s
  327. * or an empty array if no adjustment
  328. * listeners are currently registered
  329. *
  330. * @see #addAdjustmentListener
  331. * @see #removeAdjustmentListener
  332. * @see java.awt.event.AdjustmentListener
  333. * @see java.awt.event.AdjustmentEvent
  334. * @since 1.4
  335. */
  336. public synchronized AdjustmentListener[] getAdjustmentListeners() {
  337. return (AdjustmentListener[])(AWTEventMulticaster.getListeners(
  338. adjustmentListener,
  339. AdjustmentListener.class));
  340. }
  341. /**
  342. * Returns a string representation of this scrollbar and its values.
  343. * @return a string representation of this scrollbar.
  344. */
  345. public String toString() {
  346. return getClass().getName() + "[" + paramString() + "]";
  347. }
  348. /**
  349. * Returns a string representing the state of this scrollbar.
  350. * This method is intended to be used only for debugging purposes,
  351. * and the content and format of the returned string may vary
  352. * between implementations. The returned string may be empty but
  353. * may not be <code>null</code>.
  354. *
  355. * @return the parameter string of this scrollbar.
  356. */
  357. public String paramString() {
  358. return ((orientation == Adjustable.VERTICAL ? "vertical,"
  359. :"horizontal,")
  360. + "[0.."+maximum+"]"
  361. + ",val=" + value
  362. + ",vis=" + visibleAmount
  363. + ",unit=" + unitIncrement
  364. + ",block=" + blockIncrement
  365. + ",isAdjusting=" + isAdjusting);
  366. }
  367. }