OSDN Git Service

2005-04-19 Roman Kennke <roman@kennke.org>
[pf3gnuchains/gcc-fork.git] / libjava / javax / swing / DefaultBoundedRangeModel.java
1 /* DefaultBoundedRangeModel.java -- Default implementation
2    of BoundedRangeModel.
3    Copyright (C) 2002, 2004, 2005  Free Software Foundation, Inc.
4
5 This file is part of GNU Classpath.
6
7 GNU Classpath is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU Classpath is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU Classpath; see the file COPYING.  If not, write to the
19 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20 02111-1307 USA.
21
22 Linking this library statically or dynamically with other modules is
23 making a combined work based on this library.  Thus, the terms and
24 conditions of the GNU General Public License cover the whole
25 combination.
26
27 As a special exception, the copyright holders of this library give you
28 permission to link this library with independent modules to produce an
29 executable, regardless of the license terms of these independent
30 modules, and to copy and distribute the resulting executable under
31 terms of your choice, provided that you also meet, for each linked
32 independent module, the terms and conditions of the license of that
33 module.  An independent module is a module which is not derived from
34 or based on this library.  If you modify this library, you may extend
35 this exception to your version of the library, but you are not
36 obligated to do so.  If you do not wish to do so, delete this
37 exception statement from your version. */
38
39
40 package javax.swing;
41
42 import java.io.Serializable;
43 import java.util.EventListener;
44
45 import javax.swing.event.ChangeEvent;
46 import javax.swing.event.ChangeListener;
47 import javax.swing.event.EventListenerList;
48
49 /**
50  * A default implementation of <code>BoundedRangeModel</code>.
51  *
52  * @author Andrew Selkirk (aselkirk@sympatico.ca)
53  * @author Sascha Brawer (brawer@dandelis.ch)
54  */
55 public class DefaultBoundedRangeModel
56   implements BoundedRangeModel, Serializable
57 {
58   /**
59    * The identifier of this class in object serialization. Verified
60    * using the serialver tool of Sun J2SE 1.4.1_01.
61    */
62   private static final long serialVersionUID = 5034068491295259790L;
63
64
65   /**
66    * An event that is sent to all registered {@link ChangeListener}s
67    * when the state of this range model has changed.
68    *
69    * <p>The event object is created on demand, the first time it
70    * is actually needed.</p>
71    *
72    * @see #fireStateChanged()
73    */
74   protected transient ChangeEvent changeEvent;
75
76
77   /**
78    * The list of the currently registered EventListeners.
79    */
80   protected EventListenerList listenerList = new EventListenerList();
81
82
83   /**
84    * The current value of the range model, which is always between
85    * {@link #minimum} and ({@link #maximum} - {@link #extent}). In a
86    * scroll bar visualization of a {@link BoundedRangeModel}, the
87    * <code>value</code> is displayed as the position of the thumb.
88    */
89   private int value;
90
91
92   /**
93    * The current extent of the range model, which is a number greater
94    * than or equal to zero. In a scroll bar visualization of a {@link
95    * BoundedRangeModel}, the <code>extent</code> is displayed as the
96    * size of the thumb.
97    */
98   private int extent;
99
100
101   /**
102    * The current minimum value of the range model, which is always
103    * less than or equal to {@link #maximum}.
104    */
105   private int minimum;
106
107
108   /**
109    * The current maximum value of the range model, which is always
110    * greater than or equal to {@link #minimum}.
111    */
112   private int maximum;
113
114
115   /**
116    * A property that indicates whether the value of this {@link
117    * BoundedRangeModel} is going to change in the immediate future.
118    */
119   private boolean isAdjusting;
120
121
122   /**
123    * Constructs a <code>DefaultBoundedRangeModel</code> with default
124    * values for the properties. The properties <code>value</code>,
125    * <code>extent</code> and <code>minimum</code> will be initialized
126    * to zero; <code>maximum</code> will be set to 100; the property
127    * <code>valueIsAdjusting</code> will be <code>false</code>.
128    */
129   public DefaultBoundedRangeModel()
130   {
131     // The fields value, extent, minimum have the default value 0, and
132     // isAdjusting is already false. These fields no not need to be
133     // set explicitly.
134     maximum = 100;
135   }
136
137
138   /**
139    * Constructs a <code>DefaultBoundedRangeModel</code> with the
140    * specified values for some properties.
141    *
142    * @param value the initial value of the range model, which must be
143    * a number between <code>minimum</code> and <code>(maximum -
144    * extent)</code>. In a scroll bar visualization of a {@link
145    * BoundedRangeModel}, the <code>value</code> is displayed as the
146    * position of the thumb.
147    *
148    * @param extent the initial extent of the range model, which is a
149    * number greater than or equal to zero. In a scroll bar
150    * visualization of a {@link BoundedRangeModel}, the
151    * <code>extent</code> is displayed as the size of the thumb.
152    *
153    * @param minimum the initial minimal value of the range model.
154    *
155    * @param maximum the initial maximal value of the range model.
156    *
157    * @throws IllegalArgumentException if the following condition is
158    * not satisfied: <code>minimum &lt;= value &lt;= value + extent &lt;=
159    * maximum</code>.
160    */
161   public DefaultBoundedRangeModel(int value, int extent, int minimum,
162                                   int maximum)
163   {
164     if (!(minimum <= value && extent >= 0 && (value + extent) <= maximum))
165       throw new IllegalArgumentException();
166
167     this.value = value;
168     this.extent = extent;
169     this.minimum = minimum;
170     this.maximum = maximum;
171
172     // The isAdjusting field already has a false value by default.
173   }
174
175
176   /**
177    * Returns a string with all relevant properties of this range
178    * model.
179    *
180    * @return a string representing the object
181    */
182   public String toString()
183   {
184     return getClass().getName()
185       + "[value=" + value
186       + ", extent=" + extent
187       + ", min=" + minimum
188       + ", max=" + maximum
189       + ", adj=" + isAdjusting
190       + ']';
191   }
192
193
194   /**
195    * Returns the current value of this bounded range model.  In a
196    * scroll bar visualization of a {@link BoundedRangeModel}, the
197    * <code>value</code> is displayed as the position of the thumb.
198    *
199    * @return the value
200    */
201   public int getValue()
202   {
203     return value;
204   }
205
206
207   /**
208    * Changes the current value of this bounded range model. In a
209    * scroll bar visualization of a {@link BoundedRangeModel}, the
210    * <code>value</code> is displayed as the position of the thumb;
211    * changing the <code>value</code> of a scroll bar's model
212    * thus moves the thumb to a different position.
213    *
214    * @param value the value
215    */
216   public void setValue(int value)
217   {
218     value = Math.max(minimum, value);
219     if (value + extent > maximum)
220       value = maximum - extent;
221
222     if (value != this.value)
223       {
224         this.value = value;
225         fireStateChanged();
226       }
227   }
228
229
230   /**
231    * Returns the current extent of this bounded range model, which is
232    * a number greater than or equal to zero. In a scroll bar
233    * visualization of a {@link BoundedRangeModel}, the
234    * <code>extent</code> is displayed as the size of the thumb.
235    *
236    * @return the extent
237    */
238   public int getExtent()
239   {
240     return extent;
241   }
242
243
244   /**
245    * Changes the current extent of this bounded range model. In a
246    * scroll bar visualization of a {@link BoundedRangeModel}, the
247    * <code>extent</code> is displayed as the size of the thumb.
248    *
249    * @param extent the new extent of the range model, which is a
250    * number greater than or equal to zero.
251    */
252   public void setExtent(int extent)
253   {
254     extent = Math.max(extent, 0);
255     if (value + extent > maximum)
256       extent = maximum - value;
257
258     if (extent != this.extent)
259       {
260         this.extent = extent;
261         fireStateChanged();
262       }
263   }
264
265
266   /**
267    * Returns the current minimal value of this bounded range model.
268    */
269   public int getMinimum()
270   {
271     return minimum;
272   }
273
274
275   /**
276    * Changes the current minimal value of this bounded range model.
277    *
278    * @param minimum the new minimal value.
279    */
280   public void setMinimum(int minimum)
281   {
282     int value, maximum;
283
284     maximum = Math.max(minimum, this.maximum);
285     value = Math.max(minimum, this.value);
286
287     setRangeProperties(value, extent, minimum, maximum, isAdjusting);
288   }
289
290
291   /**
292    * Returns the current maximal value of this bounded range model.
293    *
294    * @return the maximum
295    */
296   public int getMaximum()
297   {
298     return maximum;
299   }
300
301
302   /**
303    * Changes the current maximal value of this bounded range model.
304    *
305    * @param maximum the new maximal value.
306    */
307   public void setMaximum(int maximum)
308   {
309     int value, extent, minimum;
310
311     minimum = Math.min(this.minimum, maximum);
312     extent = Math.min(this.extent, maximum - minimum);
313     value = Math.min(this.value, maximum - extent);
314
315     setRangeProperties(value, extent, minimum, maximum, isAdjusting);
316   }
317
318
319   /**
320    * Returns whether or not the value of this bounded range model is
321    * going to change in the immediate future. Scroll bars set this
322    * property to <code>true</code> while the thumb is being dragged
323    * around; when the mouse is relased, they set the property to
324    * <code>false</code> and post a final {@link ChangeEvent}.
325    *
326    * @return <code>true</code> if the value will change soon again;
327    * <code>false</code> if the value will probably not change soon.
328    */
329   public boolean getValueIsAdjusting()
330   {
331     return isAdjusting;
332   }
333
334
335   /**
336    * Specifies whether or not the value of this bounded range model is
337    * going to change in the immediate future. Scroll bars set this
338    * property to <code>true</code> while the thumb is being dragged
339    * around; when the mouse is relased, they set the property to
340    * <code>false</code>.
341    *
342    * @param isAdjusting <code>true</code> if the value will change
343    * soon again; <code>false</code> if the value will probably not
344    * change soon.
345    */
346   public void setValueIsAdjusting(boolean isAdjusting)
347   {
348     if (isAdjusting == this.isAdjusting)
349       return;
350
351     this.isAdjusting = isAdjusting;
352     fireStateChanged();
353   }
354
355
356   /**
357    * Sets all properties.
358    *
359    * @param value the new value of the range model.  In a scroll bar
360    * visualization of a {@link BoundedRangeModel}, the
361    * <code>value</code> is displayed as the position of the thumb.
362    *
363    * @param extent the new extent of the range model, which is a
364    * number greater than or equal to zero. In a scroll bar
365    * visualization of a {@link BoundedRangeModel}, the
366    * <code>extent</code> is displayed as the size of the thumb.
367    *
368    * @param minimum the new minimal value of the range model.
369    *
370    * @param maximum the new maximal value of the range model.
371
372    * @param isAdjusting whether or not the value of this bounded range
373    * model is going to change in the immediate future. Scroll bars set
374    * this property to <code>true</code> while the thumb is being
375    * dragged around; when the mouse is relased, they set the property
376    * to <code>false</code>.
377    */
378   public void setRangeProperties(int value, int extent, int minimum,
379                                  int maximum, boolean isAdjusting)
380   {
381     minimum = Math.min(Math.min(minimum, maximum), value);
382     maximum = Math.max(value, maximum);
383     if (extent + value > maximum)
384       extent = maximum - value;
385     extent = Math.max(0, extent);
386
387     if ((value == this.value)
388         && (extent == this.extent)
389         && (minimum == this.minimum)
390         && (maximum == this.maximum)
391         && (isAdjusting == this.isAdjusting))
392       return;
393
394     this.value = value;
395     this.extent = extent;
396     this.minimum = minimum;
397     this.maximum = maximum;
398     this.isAdjusting = isAdjusting;
399                 
400     fireStateChanged();
401   }
402
403
404   /**
405    * Subscribes a ChangeListener to state changes.
406    *
407    * @param listener the listener to be subscribed.
408    */
409   public void addChangeListener(ChangeListener listener)
410   {
411     listenerList.add(ChangeListener.class, listener);
412   }
413
414
415   /**
416    * Cancels the subscription of a ChangeListener.
417    *
418    * @param listener the listener to be unsubscribed.
419    */
420   public void removeChangeListener(ChangeListener listener)
421   {
422     listenerList.remove(ChangeListener.class, listener);
423   }
424
425
426   /**
427    * Sends a {@link ChangeEvent} to any registered {@link
428    * ChangeListener}s.
429    *
430    * @see #addChangeListener(ChangeListener)
431    * @see #removeChangeListener(ChangeListener)
432    */
433   protected void fireStateChanged()
434   {
435     ChangeListener[] listeners = getChangeListeners();
436     
437     if (changeEvent == null)
438       changeEvent = new ChangeEvent(this);
439
440     for (int i = listeners.length - 1; i >= 0; --i)
441       listeners[i].stateChanged(changeEvent);
442   }
443
444
445   /**
446    * Retrieves the current listeners of the specified class.
447    *
448    * @param c the class of listeners; usually {@link
449    * ChangeListener}<code>.class</code>.
450    *
451    * @return an array with the currently subscribed listeners, or
452    * an empty array if there are currently no listeners.
453    *
454    * @since 1.3
455    */
456   public EventListener[] getListeners(Class listenerType)
457   {
458     return listenerList.getListeners(listenerType);
459   }
460
461
462   /**
463    * Returns all <code>ChangeListeners</code> that are currently
464    * subscribed for changes to this
465    * <code>DefaultBoundedRangeModel</code>.
466    *
467    * @return an array with the currently subscribed listeners, or
468    * an empty array if there are currently no listeners.
469    *
470    * @since 1.4
471    */
472   public ChangeListener[] getChangeListeners()
473   {
474     return (ChangeListener[]) getListeners(ChangeListener.class);
475   }
476 }