OSDN Git Service

2006-08-14 Mark Wielaard <mark@klomp.org>
[pf3gnuchains/gcc-fork.git] / libjava / classpath / javax / swing / DefaultBoundedRangeModel.java
1 /* DefaultBoundedRangeModel.java -- Default implementation
2    of BoundedRangeModel.
3    Copyright (C) 2002, 2004, 2005, 2006,  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., 51 Franklin Street, Fifth Floor, Boston, MA
20 02110-1301 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.IOException;
43 import java.io.ObjectInputStream;
44 import java.io.ObjectOutputStream;
45 import java.io.Serializable;
46 import java.util.EventListener;
47
48 import javax.swing.event.ChangeEvent;
49 import javax.swing.event.ChangeListener;
50 import javax.swing.event.EventListenerList;
51
52 /**
53  * The default implementation of <code>BoundedRangeModel</code>.
54  *
55  * @author Andrew Selkirk (aselkirk@sympatico.ca)
56  * @author Sascha Brawer (brawer@dandelis.ch)
57  */
58 public class DefaultBoundedRangeModel
59   implements BoundedRangeModel, Serializable
60 {
61   /**
62    * The identifier of this class in object serialization. Verified
63    * using the serialver tool of Sun J2SE 1.4.1_01.
64    */
65   private static final long serialVersionUID = 5034068491295259790L;
66
67   /**
68    * An event that is sent to all registered {@link ChangeListener}s
69    * when the state of this range model has changed.
70    *
71    * <p>The event object is created on demand, the first time it
72    * is actually needed.</p>
73    *
74    * @see #fireStateChanged()
75    */
76   protected transient ChangeEvent changeEvent;
77
78   /**
79    * The list of the currently registered EventListeners.
80    */
81   protected EventListenerList listenerList = new EventListenerList();
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    * The current extent of the range model, which is a number greater
93    * than or equal to zero. In a scroll bar visualization of a {@link
94    * BoundedRangeModel}, the <code>extent</code> is displayed as the
95    * size of the thumb.
96    */
97   private int extent;
98
99   /**
100    * The current minimum value of the range model, which is always
101    * less than or equal to {@link #maximum}.
102    */
103   private int minimum;
104
105   /**
106    * The current maximum value of the range model, which is always
107    * greater than or equal to {@link #minimum}.
108    */
109   private int maximum;
110
111   /**
112    * A property that indicates whether the value of this {@link
113    * BoundedRangeModel} is going to change in the immediate future.
114    */
115   private boolean isAdjusting;
116
117   /**
118    * Constructs a <code>DefaultBoundedRangeModel</code> with default
119    * values for the properties. The properties <code>value</code>,
120    * <code>extent</code> and <code>minimum</code> will be initialized
121    * to zero; <code>maximum</code> will be set to 100; the property
122    * <code>valueIsAdjusting</code> will be <code>false</code>.
123    */
124   public DefaultBoundedRangeModel()
125   {
126     // The fields value, extent, minimum have the default value 0, and
127     // isAdjusting is already false. These fields no not need to be
128     // set explicitly.
129     maximum = 100;
130   }
131
132   /**
133    * Constructs a <code>DefaultBoundedRangeModel</code> with the
134    * specified values for some properties.
135    *
136    * @param value the initial value of the range model, which must be
137    *     a number between <code>minimum</code> and <code>(maximum -
138    *     extent)</code>. In a scroll bar visualization of a {@link
139    *     BoundedRangeModel}, the <code>value</code> is displayed as the
140    *     position of the thumb.
141    * @param extent the initial extent of the range model, which is a
142    *     number greater than or equal to zero. In a scroll bar
143    *     visualization of a {@link BoundedRangeModel}, the
144    *     <code>extent</code> is displayed as the size of the thumb.
145    * @param minimum the initial minimal value of the range model.
146    * @param maximum the initial maximal value of the range model.
147    *
148    * @throws IllegalArgumentException if the following condition is
149    *     not satisfied: <code>minimum &lt;= value &lt;= value + extent &lt;=
150    *     maximum</code>.
151    */
152   public DefaultBoundedRangeModel(int value, int extent, int minimum,
153                                   int maximum)
154   {
155     if (!(minimum <= value && extent >= 0 && (value + extent) <= maximum))
156       throw new IllegalArgumentException();
157
158     this.value = value;
159     this.extent = extent;
160     this.minimum = minimum;
161     this.maximum = maximum;
162
163     // The isAdjusting field already has a false value by default.
164   }
165
166   /**
167    * Returns a string with all relevant properties of this range
168    * model.
169    *
170    * @return a string representing the object
171    */
172   public String toString()
173   {
174     return getClass().getName()
175       + "[value=" + value
176       + ", extent=" + extent
177       + ", min=" + minimum
178       + ", max=" + maximum
179       + ", adj=" + isAdjusting
180       + ']';
181   }
182
183   /**
184    * Returns the current value of this bounded range model.  In a
185    * scroll bar visualization of a {@link BoundedRangeModel}, the
186    * <code>value</code> is displayed as the position of the thumb.
187    *
188    * @return the value
189    */
190   public int getValue()
191   {
192     return value;
193   }
194
195   /**
196    * Changes the current value of this bounded range model. In a
197    * scroll bar visualization of a {@link BoundedRangeModel}, the
198    * <code>value</code> is displayed as the position of the thumb;
199    * changing the <code>value</code> of a scroll bar's model
200    * thus moves the thumb to a different position.
201    *
202    * @param value the value
203    */
204   public void setValue(int value)
205   {
206     value = Math.max(minimum, value);
207     if (value + extent > maximum)
208       value = maximum - extent;
209
210     if (value != this.value)
211       {
212         this.value = value;
213         fireStateChanged();
214       }
215   }
216
217   /**
218    * Returns the current extent of this bounded range model, which is
219    * a number greater than or equal to zero. In a scroll bar
220    * visualization of a {@link BoundedRangeModel}, the
221    * <code>extent</code> is displayed as the size of the thumb.
222    *
223    * @return the extent
224    */
225   public int getExtent()
226   {
227     return extent;
228   }
229
230   /**
231    * Changes the current extent of this bounded range model. In a
232    * scroll bar visualization of a {@link BoundedRangeModel}, the
233    * <code>extent</code> is displayed as the size of the thumb.
234    *
235    * @param extent the new extent of the range model, which is a
236    *     number greater than or equal to zero.
237    */
238   public void setExtent(int extent)
239   {
240     extent = Math.max(extent, 0);
241     if (value + extent > maximum)
242       extent = maximum - value;
243
244     if (extent != this.extent)
245       {
246         this.extent = extent;
247         fireStateChanged();
248       }
249   }
250
251   /**
252    * Returns the current minimal value of this bounded range model.
253    */
254   public int getMinimum()
255   {
256     return minimum;
257   }
258
259   /**
260    * Changes the current minimal value of this bounded range model.
261    *
262    * @param minimum the new minimal value.
263    */
264   public void setMinimum(int minimum)
265   {
266     int value, maximum;
267
268     maximum = Math.max(minimum, this.maximum);
269     value = Math.max(minimum, this.value);
270
271     setRangeProperties(value, extent, minimum, maximum, isAdjusting);
272   }
273
274   /**
275    * Returns the current maximal value of this bounded range model.
276    *
277    * @return the maximum
278    */
279   public int getMaximum()
280   {
281     return maximum;
282   }
283
284   /**
285    * Changes the current maximal value of this bounded range model.
286    *
287    * @param maximum the new maximal value.
288    */
289   public void setMaximum(int maximum)
290   {
291     int value, extent, minimum;
292
293     minimum = Math.min(this.minimum, maximum);
294     extent = Math.min(this.extent, maximum - minimum);
295     value = Math.min(this.value, maximum - extent);
296
297     setRangeProperties(value, extent, minimum, maximum, isAdjusting);
298   }
299
300   /**
301    * Returns whether or not the value of this bounded range model is
302    * going to change in the immediate future. Scroll bars set this
303    * property to <code>true</code> while the thumb is being dragged
304    * around; when the mouse is relased, they set the property to
305    * <code>false</code> and post a final {@link ChangeEvent}.
306    *
307    * @return <code>true</code> if the value will change soon again;
308    *     <code>false</code> if the value will probably not change soon.
309    */
310   public boolean getValueIsAdjusting()
311   {
312     return isAdjusting;
313   }
314
315   /**
316    * Specifies whether or not the value of this bounded range model is
317    * going to change in the immediate future. Scroll bars set this
318    * property to <code>true</code> while the thumb is being dragged
319    * around; when the mouse is relased, they set the property to
320    * <code>false</code>.
321    *
322    * @param isAdjusting <code>true</code> if the value will change
323    *     soon again; <code>false</code> if the value will probably not
324    *     change soon.
325    */
326   public void setValueIsAdjusting(boolean isAdjusting)
327   {
328     if (isAdjusting == this.isAdjusting)
329       return;
330
331     this.isAdjusting = isAdjusting;
332     fireStateChanged();
333   }
334
335   /**
336    * Sets all properties.
337    *
338    * @param value the new value of the range model.  In a scroll bar
339    *     visualization of a {@link BoundedRangeModel}, the
340    *     <code>value</code> is displayed as the position of the thumb.
341    * @param extent the new extent of the range model, which is a
342    *     number greater than or equal to zero. In a scroll bar
343    *     visualization of a {@link BoundedRangeModel}, the
344    *     <code>extent</code> is displayed as the size of the thumb.
345    * @param minimum the new minimal value of the range model.
346    * @param maximum the new maximal value of the range model.
347    * @param isAdjusting whether or not the value of this bounded range
348    *     model is going to change in the immediate future. Scroll bars set
349    *     this property to <code>true</code> while the thumb is being
350    *     dragged around; when the mouse is relased, they set the property
351    *     to <code>false</code>.
352    */
353   public void setRangeProperties(int value, int extent, int minimum,
354                                  int maximum, boolean isAdjusting)
355   {
356     minimum = Math.min(Math.min(minimum, maximum), value);
357     maximum = Math.max(value, maximum);
358     if (extent + value > maximum)
359       extent = maximum - value;
360     extent = Math.max(0, extent);
361
362     if ((value == this.value)
363         && (extent == this.extent)
364         && (minimum == this.minimum)
365         && (maximum == this.maximum)
366         && (isAdjusting == this.isAdjusting))
367       return;
368
369     this.value = value;
370     this.extent = extent;
371     this.minimum = minimum;
372     this.maximum = maximum;
373     this.isAdjusting = isAdjusting;
374                 
375     fireStateChanged();
376   }
377
378   /**
379    * Subscribes a ChangeListener to state changes.
380    *
381    * @param listener the listener to be subscribed.
382    */
383   public void addChangeListener(ChangeListener listener)
384   {
385     listenerList.add(ChangeListener.class, listener);
386   }
387
388   /**
389    * Cancels the subscription of a ChangeListener.
390    *
391    * @param listener the listener to be unsubscribed.
392    */
393   public void removeChangeListener(ChangeListener listener)
394   {
395     listenerList.remove(ChangeListener.class, listener);
396   }
397
398   /**
399    * Sends a {@link ChangeEvent} to any registered {@link
400    * ChangeListener}s.
401    *
402    * @see #addChangeListener(ChangeListener)
403    * @see #removeChangeListener(ChangeListener)
404    */
405   protected void fireStateChanged()
406   {
407     ChangeListener[] listeners = getChangeListeners();
408     
409     if (changeEvent == null)
410       changeEvent = new ChangeEvent(this);
411
412     for (int i = listeners.length - 1; i >= 0; --i)
413       listeners[i].stateChanged(changeEvent);
414   }
415
416   /**
417    * Retrieves the current listeners of the specified class.
418    *
419    * @param listenerType the class of listeners; usually {@link
420    *     ChangeListener}<code>.class</code>.
421    *
422    * @return an array with the currently subscribed listeners, or
423    *     an empty array if there are currently no listeners.
424    *
425    * @since 1.3
426    */
427   public EventListener[] getListeners(Class listenerType)
428   {
429     return listenerList.getListeners(listenerType);
430   }
431
432   /**
433    * Returns all <code>ChangeListeners</code> that are currently
434    * subscribed for changes to this
435    * <code>DefaultBoundedRangeModel</code>.
436    *
437    * @return an array with the currently subscribed listeners, or
438    *     an empty array if there are currently no listeners.
439    *
440    * @since 1.4
441    */
442   public ChangeListener[] getChangeListeners()
443   {
444     return (ChangeListener[]) getListeners(ChangeListener.class);
445   }
446   
447   /**
448    * Provides serialization support.
449    *
450    * @param stream  the output stream (<code>null</code> not permitted).
451    *
452    * @throws IOException  if there is an I/O error.
453    */
454   private void writeObject(ObjectOutputStream stream) 
455     throws IOException 
456   {
457     stream.defaultWriteObject();
458   }
459
460   /**
461    * Provides serialization support.
462    *
463    * @param stream  the input stream (<code>null</code> not permitted).
464    *
465    * @throws IOException  if there is an I/O error.
466    * @throws ClassNotFoundException  if there is a classpath problem.
467    */
468   private void readObject(ObjectInputStream stream)
469     throws ClassNotFoundException, IOException
470   {
471     stream.defaultReadObject();
472     listenerList = new EventListenerList();
473   }
474
475 }