1. /*
  2. * @(#)ScrollPaneAdjustable.java 1.9 03/12/19
  3. *
  4. * Copyright 2004 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.9 12/19/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. setTypedValue(v, AdjustmentEvent.TRACK);
  267. }
  268. /**
  269. * Sets the value of this scrollbar to the specified value.
  270. * <p>
  271. * If the value supplied is less than the current minimum or
  272. * greater than the current maximum, then one of those values is
  273. * substituted, as appropriate. Also, creates and dispatches
  274. * the AdjustementEvent with specified type and value.
  275. *
  276. * @param v the new value of the scrollbar
  277. * @param type the type of the scrolling operation occured
  278. */
  279. private void setTypedValue(int v, int type) {
  280. v = Math.max(v, minimum);
  281. v = Math.min(v, maximum - visibleAmount);
  282. if (v != value) {
  283. value = v;
  284. // Synchronously notify the listeners so that they are
  285. // guaranteed to be up-to-date with the Adjustable before
  286. // it is mutated again.
  287. AdjustmentEvent e =
  288. new AdjustmentEvent(this,
  289. AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED,
  290. type, value, isAdjusting);
  291. adjustmentListener.adjustmentValueChanged(e);
  292. }
  293. }
  294. public int getValue() {
  295. return value;
  296. }
  297. /**
  298. * Adds the specified adjustment listener to receive adjustment
  299. * events from this <code>ScrollPaneAdjustable</code>.
  300. * If <code>l</code> is <code>null</code>, no exception is thrown
  301. * and no action is performed.
  302. *
  303. * @param l the adjustment listener.
  304. * @see #removeAdjustmentListener
  305. * @see #getAdjustmentListeners
  306. * @see java.awt.event.AdjustmentListener
  307. * @see java.awt.event.AdjustmentEvent
  308. */
  309. public synchronized void addAdjustmentListener(AdjustmentListener l) {
  310. if (l == null) {
  311. return;
  312. }
  313. adjustmentListener = AWTEventMulticaster.add(adjustmentListener, l);
  314. }
  315. /**
  316. * Removes the specified adjustment listener so that it no longer
  317. * receives adjustment events from this <code>ScrollPaneAdjustable</code>.
  318. * If <code>l</code> is <code>null</code>, no exception is thrown
  319. * and no action is performed.
  320. *
  321. * @param l the adjustment listener.
  322. * @see #addAdjustmentListener
  323. * @see #getAdjustmentListeners
  324. * @see java.awt.event.AdjustmentListener
  325. * @see java.awt.event.AdjustmentEvent
  326. * @since JDK1.1
  327. */
  328. public synchronized void removeAdjustmentListener(AdjustmentListener l){
  329. if (l == null) {
  330. return;
  331. }
  332. adjustmentListener = AWTEventMulticaster.remove(adjustmentListener, l);
  333. }
  334. /**
  335. * Returns an array of all the adjustment listeners
  336. * registered on this <code>ScrollPaneAdjustable</code>.
  337. *
  338. * @return all of this <code>ScrollPaneAdjustable</code>'s
  339. * <code>AdjustmentListener</code>s
  340. * or an empty array if no adjustment
  341. * listeners are currently registered
  342. *
  343. * @see #addAdjustmentListener
  344. * @see #removeAdjustmentListener
  345. * @see java.awt.event.AdjustmentListener
  346. * @see java.awt.event.AdjustmentEvent
  347. * @since 1.4
  348. */
  349. public synchronized AdjustmentListener[] getAdjustmentListeners() {
  350. return (AdjustmentListener[])(AWTEventMulticaster.getListeners(
  351. adjustmentListener,
  352. AdjustmentListener.class));
  353. }
  354. /**
  355. * Returns a string representation of this scrollbar and its values.
  356. * @return a string representation of this scrollbar.
  357. */
  358. public String toString() {
  359. return getClass().getName() + "[" + paramString() + "]";
  360. }
  361. /**
  362. * Returns a string representing the state of this scrollbar.
  363. * This method is intended to be used only for debugging purposes,
  364. * and the content and format of the returned string may vary
  365. * between implementations. The returned string may be empty but
  366. * may not be <code>null</code>.
  367. *
  368. * @return the parameter string of this scrollbar.
  369. */
  370. public String paramString() {
  371. return ((orientation == Adjustable.VERTICAL ? "vertical,"
  372. :"horizontal,")
  373. + "[0.."+maximum+"]"
  374. + ",val=" + value
  375. + ",vis=" + visibleAmount
  376. + ",unit=" + unitIncrement
  377. + ",block=" + blockIncrement
  378. + ",isAdjusting=" + isAdjusting);
  379. }
  380. }