1. /*
  2. * @(#)DefaultBoundedRangeModel.java 1.33 01/11/29
  3. *
  4. * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.swing;
  8. import javax.swing.event.*;
  9. import java.io.Serializable;
  10. /**
  11. * A generic implementation of BoundedRangeModel.
  12. * <p>
  13. * <strong>Warning:</strong>
  14. * Serialized objects of this class will not be compatible with
  15. * future Swing releases. The current serialization support is appropriate
  16. * for short term storage or RMI between applications running the same
  17. * version of Swing. A future release of Swing will provide support for
  18. * long term persistence.
  19. *
  20. * @version 1.33 11/29/01
  21. * @author David Kloba
  22. * @author Hans Muller
  23. * @see BoundedRangeModel
  24. */
  25. public class DefaultBoundedRangeModel implements BoundedRangeModel, Serializable
  26. {
  27. /**
  28. * Only one ChangeEvent is needed per model instance since the
  29. * event's only (read-only) state is the source property. The source
  30. * of events generated here is always "this".
  31. */
  32. protected transient ChangeEvent changeEvent = null;
  33. /** The listeners waiting for model changes. */
  34. protected EventListenerList listenerList = new EventListenerList();
  35. private int value = 0;
  36. private int extent = 0;
  37. private int min = 0;
  38. private int max = 100;
  39. private boolean isAdjusting = false;
  40. /**
  41. * Initializes all of the properties with default values.
  42. * Those values are:
  43. * <ul>
  44. * <li><code>value</code> = 0
  45. * <li><code>extent</code> = 0
  46. * <li><code>minimum</code> = 0
  47. * <li><code>maximum</code> = 100
  48. * <li><code>adjusting</code> = false
  49. * </ul>
  50. */
  51. public DefaultBoundedRangeModel() {
  52. }
  53. /**
  54. * Initializes value, extent, minimum and maximum. Adjusting is false.
  55. * Throws an IllegalArgumentException if the following constraints
  56. * aren't satisfied:
  57. * <pre>
  58. * min <= value <= value+extent <= max
  59. * </pre>
  60. */
  61. public DefaultBoundedRangeModel(int value, int extent, int min, int max)
  62. {
  63. if ((max >= min) &&
  64. (value >= min) &&
  65. ((value + extent) >= value) &&
  66. ((value + extent) <= max)) {
  67. this.value = value;
  68. this.extent = extent;
  69. this.min = min;
  70. this.max = max;
  71. }
  72. else {
  73. throw new IllegalArgumentException("invalid range properties");
  74. }
  75. }
  76. /**
  77. * Return the model's current value.
  78. * @return the model's current value
  79. * @see #setValue
  80. * @see BoundedRangeModel#getValue
  81. */
  82. public int getValue() {
  83. return value;
  84. }
  85. /**
  86. * Return the model's extent.
  87. * @return the model's extent
  88. * @see #setExtent
  89. * @see BoundedRangeModel#getExtent
  90. */
  91. public int getExtent() {
  92. return extent;
  93. }
  94. /**
  95. * Return the model's minimum.
  96. * @return the model's minimum
  97. * @see #setMinimum
  98. * @see BoundedRangeModel#getMinimum
  99. */
  100. public int getMinimum() {
  101. return min;
  102. }
  103. /**
  104. * Return the model's maximum.
  105. * @return the model's maximum
  106. * @see #setMaximum
  107. * @see BoundedRangeModel#getMaximum
  108. */
  109. public int getMaximum() {
  110. return max;
  111. }
  112. /**
  113. * Sets the current value of the model. For a slider, that
  114. * determines where the knob appears. Ensures that the new
  115. * value, <I>n</I> falls within the model's constraints:
  116. * <pre>
  117. * minimum <= value <= value+extent <= maximum
  118. * </pre>
  119. *
  120. * @see BoundedRangeModel#setValue
  121. */
  122. public void setValue(int n) {
  123. int newValue = Math.max(n, min);
  124. if(newValue + extent > max) {
  125. newValue = max - extent;
  126. }
  127. setRangeProperties(newValue, extent, min, max, isAdjusting);
  128. }
  129. /**
  130. * Sets the extent to <I>n</I> after ensuring that <I>n</I>
  131. * is greater than or equal to zero and falls within the model's
  132. * constraints:
  133. * <pre>
  134. * minimum <= value <= value+extent <= maximum
  135. * </pre>
  136. * @see BoundedRangeModel#setExtent
  137. */
  138. public void setExtent(int n) {
  139. int newExtent = Math.max(0, n);
  140. if(value + newExtent > max) {
  141. newExtent = max - value;
  142. }
  143. setRangeProperties(value, newExtent, min, max, isAdjusting);
  144. }
  145. /**
  146. * Sets the minimum to <I>n</I> after ensuring that <I>n</I>
  147. * that the other three properties obey the model's constraints:
  148. * <pre>
  149. * minimum <= value <= value+extent <= maximum
  150. * </pre>
  151. * @see #getMinimum
  152. * @see BoundedRangeModel#setMinimum
  153. */
  154. public void setMinimum(int n) {
  155. int newMax = Math.max(n, max);
  156. int newValue = Math.max(n, value);
  157. int newExtent = Math.min(newMax - newValue, extent);
  158. setRangeProperties(newValue, newExtent, n, newMax, isAdjusting);
  159. }
  160. /**
  161. * Sets the maximum to <I>n</I> after ensuring that <I>n</I>
  162. * that the other three properties obey the model's constraints:
  163. * <pre>
  164. * minimum <= value <= value+extent <= maximum
  165. * </pre>
  166. * @see BoundedRangeModel#setMaximum
  167. */
  168. public void setMaximum(int n) {
  169. int newMin = Math.min(n, min);
  170. int newValue = Math.min(n, value);
  171. int newExtent = Math.min(n - newValue, extent);
  172. setRangeProperties(newValue, newExtent, newMin, n, isAdjusting);
  173. }
  174. /**
  175. * Sets the valueIsAdjusting property.
  176. *
  177. * @see #getValueIsAdjusting
  178. * @see #setValue
  179. * @see BoundedRangeModel#setValueIsAdjusting
  180. */
  181. public void setValueIsAdjusting(boolean b) {
  182. setRangeProperties(value, extent, min, max, b);
  183. }
  184. /**
  185. * Returns true if the value is in the process of changing
  186. * as a result of actions being taken by the user.
  187. *
  188. * @return the value of the valueIsAdjusting property
  189. * @see #setValue
  190. * @see BoundedRangeModel#getValueIsAdjusting
  191. */
  192. public boolean getValueIsAdjusting() {
  193. return isAdjusting;
  194. }
  195. /**
  196. * Sets all of the BoundedRangeModel properties after forcing
  197. * the arguments to obey the usual constraints:
  198. * <pre>
  199. * minimum <= value <= value+extent <= maximum
  200. * </pre>
  201. * <p>
  202. * At most, one ChangeEvent is generated.
  203. *
  204. * @see BoundedRangeModel#setRangeProperties
  205. * @see #setValue
  206. * @see #setExtent
  207. * @see #setMinimum
  208. * @see #setMaximum
  209. * @see #setValueIsAdjusting
  210. */
  211. public void setRangeProperties(int newValue, int newExtent, int newMin, int newMax, boolean adjusting)
  212. {
  213. if (newMin > newMax) {
  214. newMin = newMax;
  215. }
  216. if (newValue > newMax) {
  217. newMax = newValue;
  218. }
  219. if (newValue < newMin) {
  220. newMin = newValue;
  221. }
  222. /* Convert the addends to long so that extent can be
  223. * Integer.MAX_VALUE without rolling over the sum.
  224. * A JCK test covers this, see bug 4097718.
  225. */
  226. if (((long)newExtent + (long)newValue) > newMax) {
  227. newExtent = newMax - newValue;
  228. }
  229. if (newExtent < 0) {
  230. newExtent = 0;
  231. }
  232. boolean isChange =
  233. (newValue != value) ||
  234. (newExtent != extent) ||
  235. (newMin != min) ||
  236. (newMax != max) ||
  237. (adjusting != isAdjusting);
  238. if (isChange) {
  239. value = newValue;
  240. extent = newExtent;
  241. min = newMin;
  242. max = newMax;
  243. isAdjusting = adjusting;
  244. fireStateChanged();
  245. }
  246. }
  247. /**
  248. * Adds a ChangeListener. The change listeners are run each
  249. * time any one of the Bounded Range model properties changes.
  250. *
  251. * @param l the ChangeListener to add
  252. * @see #removeChangeListener
  253. * @see BoundedRangeModel#addChangeListener
  254. */
  255. public void addChangeListener(ChangeListener l) {
  256. listenerList.add(ChangeListener.class, l);
  257. }
  258. /**
  259. * Removes a ChangeListener.
  260. *
  261. * @param l the ChangeListener to remove
  262. * @see #addChangeListener
  263. * @see BoundedRangeModel#removeChangeListener
  264. */
  265. public void removeChangeListener(ChangeListener l) {
  266. listenerList.remove(ChangeListener.class, l);
  267. }
  268. /**
  269. * Run each ChangeListeners stateChanged() method.
  270. *
  271. * @see #setRangeProperties
  272. * @see EventListenerList
  273. */
  274. protected void fireStateChanged()
  275. {
  276. Object[] listeners = listenerList.getListenerList();
  277. for (int i = listeners.length - 2; i >= 0; i -=2 ) {
  278. if (listeners[i] == ChangeListener.class) {
  279. if (changeEvent == null) {
  280. changeEvent = new ChangeEvent(this);
  281. }
  282. ((ChangeListener)listeners[i+1]).stateChanged(changeEvent);
  283. }
  284. }
  285. }
  286. /**
  287. * Returns a string that displays all of the BoundedRangeModel properties.
  288. */
  289. public String toString() {
  290. String modelString =
  291. "value=" + getValue() + ", " +
  292. "extent=" + getExtent() + ", " +
  293. "min=" + getMinimum() + ", " +
  294. "max=" + getMaximum() + ", " +
  295. "adj=" + getValueIsAdjusting();
  296. return getClass().getName() + "[" + modelString + "]";
  297. }
  298. }