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