001    /* DefaultListSelectionModel.java --
002       Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
003    
004    This file is part of GNU Classpath.
005    
006    GNU Classpath is free software; you can redistribute it and/or modify
007    it under the terms of the GNU General Public License as published by
008    the Free Software Foundation; either version 2, or (at your option)
009    any later version.
010    
011    GNU Classpath is distributed in the hope that it will be useful, but
012    WITHOUT ANY WARRANTY; without even the implied warranty of
013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014    General Public License for more details.
015    
016    You should have received a copy of the GNU General Public License
017    along with GNU Classpath; see the file COPYING.  If not, write to the
018    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019    02110-1301 USA.
020    
021    Linking this library statically or dynamically with other modules is
022    making a combined work based on this library.  Thus, the terms and
023    conditions of the GNU General Public License cover the whole
024    combination.
025    
026    As a special exception, the copyright holders of this library give you
027    permission to link this library with independent modules to produce an
028    executable, regardless of the license terms of these independent
029    modules, and to copy and distribute the resulting executable under
030    terms of your choice, provided that you also meet, for each linked
031    independent module, the terms and conditions of the license of that
032    module.  An independent module is a module which is not derived from
033    or based on this library.  If you modify this library, you may extend
034    this exception to your version of the library, but you are not
035    obligated to do so.  If you do not wish to do so, delete this
036    exception statement from your version. */
037    
038    
039    package javax.swing;
040    
041    import java.io.Serializable;
042    import java.util.BitSet;
043    import java.util.EventListener;
044    
045    import javax.swing.event.EventListenerList;
046    import javax.swing.event.ListSelectionEvent;
047    import javax.swing.event.ListSelectionListener;
048    
049    /**
050     * The default implementation of {@link ListSelectionModel},
051     * which is used by {@link javax.swing.JList} and
052     * similar classes to manage the selection status of a number of data
053     * elements.
054     *
055     * <p>The class is organized <em>abstractly</em> as a set of intervals of
056     * integers. Each interval indicates an inclusive range of indices in a
057     * list -- held by some other object and unknown to this class -- which is
058     * considered "selected". There are various accessors for querying and
059     * modifying the set of intervals, with simplified forms accepting a single
060     * index, representing an interval with only one element. </p>
061     */
062    public class DefaultListSelectionModel implements Cloneable,
063                                                      ListSelectionModel,
064                                                      Serializable
065    {
066      private static final long serialVersionUID = -5718799865110415860L;
067    
068      /** The list of ListSelectionListeners subscribed to this selection model. */
069      protected EventListenerList listenerList = new EventListenerList();
070    
071    
072      /**
073       * The current list selection mode. Must be one of the numeric constants
074       * <code>SINGLE_SELECTION</code>, <code>SINGLE_INTERVAL_SELECTION</code>
075       * or <code>MULTIPLE_INTERVAL_SELECTION</code> from {@link
076       * ListSelectionModel}. The default value is
077       * <code>MULTIPLE_INTERVAL_SELECTION</code>.
078       */
079      int selectionMode = MULTIPLE_INTERVAL_SELECTION;
080    
081      /**
082       * The index of the "lead" of the most recent selection. The lead is the
083       * second argument in any call to {@link #setSelectionInterval}, {@link
084       * #addSelectionInterval} or {@link #removeSelectionInterval}. Generally
085       * the lead refers to the most recent position a user dragged their mouse
086       * over.
087       */
088      int leadSelectionIndex = -1;
089    
090      /**
091       * The index of the "anchor" of the most recent selection. The anchor is
092       * the first argument in any call to {@link #setSelectionInterval},
093       * {@link #addSelectionInterval} or {@link
094       * #removeSelectionInterval}. Generally the anchor refers to the first
095       * recent position a user clicks when they begin to drag their mouse over
096       * a list.
097       *
098       * @see #getAnchorSelectionIndex
099       * @see #setAnchorSelectionIndex
100       */
101      int anchorSelectionIndex = -1;
102    
103      /**
104       * controls the range of indices provided in any {@link
105       * ListSelectionEvent} fired by the selectionModel. Let
106       * <code>[A,L]</code> be the range of indices between {@link
107       * #anchorSelectionIndex} and {@link #leadSelectionIndex} inclusive, and
108       * let <code>[i0,i1]</code> be the range of indices changed in a given
109       * call which generates a {@link ListSelectionEvent}. Then when this
110       * property is <code>true</code>, the {@link ListSelectionEvent} contains
111       * the range <code>[A,L] union [i0,i1]</code>; when <code>false</code> it
112       * will contain only <code>[i0,i1]</code>. The default is
113       * <code>true</code>.
114       *
115       * @see #isLeadAnchorNotificationEnabled
116       * @see #setLeadAnchorNotificationEnabled
117       */
118      protected boolean leadAnchorNotificationEnabled = true;
119    
120      /**
121       * Whether the selection is currently "adjusting". Any {@link
122       * ListSelectionEvent} events constructed in response to changes in this
123       * list selection model will have their {@link
124       * ListSelectionEvent#isAdjusting} field set to this value.
125       *
126       * @see #getValueIsAdjusting
127       * @see #setValueIsAdjusting
128       */
129      boolean valueIsAdjusting = false;
130    
131    
132      /**
133       * The current set of "intervals", represented simply by a {@link
134       * java.util.BitSet}. A set bit indicates a selected index, whereas a
135       * cleared bit indicates a non-selected index.
136       */
137      BitSet sel = new BitSet();
138    
139      /**
140       * A variable to store the previous value of sel.
141       * Used to make sure we only fireValueChanged when the BitSet
142       * actually does change.
143       */
144      Object oldSel;
145    
146      /**
147       * Whether this call of setLeadSelectionInterval was called locally
148       * from addSelectionInterval
149       */
150      boolean setLeadCalledFromAdd = false;
151    
152      /**
153       * Returns the selection mode, which is one of {@link #SINGLE_SELECTION},
154       * {@link #SINGLE_INTERVAL_SELECTION} and
155       * {@link #MULTIPLE_INTERVAL_SELECTION}.  The default value is
156       * {@link #MULTIPLE_INTERVAL_SELECTION}.
157       *
158       * @return The selection mode.
159       *
160       * @see #setSelectionMode(int)
161       */
162      public int getSelectionMode()
163      {
164        return selectionMode;
165      }
166    
167      /**
168       * Sets the value of the {@link #selectionMode} property.
169       *
170       * @param mode The new value of the property
171       */
172      public void setSelectionMode(int mode)
173      {
174        if (mode < ListSelectionModel.SINGLE_SELECTION
175            || mode > ListSelectionModel.MULTIPLE_INTERVAL_SELECTION)
176          throw new IllegalArgumentException("Unrecognised mode: " + mode);
177        selectionMode = mode;
178      }
179    
180      /**
181       * Gets the value of the {@link #anchorSelectionIndex} property.
182       *
183       * @return The current property value
184       *
185       * @see #setAnchorSelectionIndex
186       */
187      public int getAnchorSelectionIndex()
188      {
189        return anchorSelectionIndex;
190      }
191    
192      /**
193       * Sets the value of the {@link #anchorSelectionIndex} property.
194       *
195       * @param index The new property value
196       *
197       * @see #getAnchorSelectionIndex
198       */
199      public void setAnchorSelectionIndex(int index)
200      {
201        if (anchorSelectionIndex != index)
202          {
203            int old = anchorSelectionIndex;
204            anchorSelectionIndex = index;
205            if (leadAnchorNotificationEnabled)
206              fireValueChanged(index, old);
207          }
208      }
209    
210      /**
211       * Gets the value of the {@link #leadSelectionIndex} property.
212       *
213       * @return The current property value
214       *
215       * @see #setLeadSelectionIndex
216       */
217      public int getLeadSelectionIndex()
218      {
219        return leadSelectionIndex;
220      }
221    
222      /**
223       * <p>Sets the value of the {@link #anchorSelectionIndex} property. As a
224       * side effect, alters the selection status of two ranges of indices. Let
225       * <code>OL</code> be the old lead selection index, <code>NL</code> be
226       * the new lead selection index, and <code>A</code> be the anchor
227       * selection index. Then if <code>A</code> is a valid selection index,
228       * one of two things happens depending on the seleciton status of
229       * <code>A</code>:</p>
230       *
231       * <ul>
232       *
233       * <li><code>isSelectedIndex(A) == true</code>: set <code>[A,OL]</code>
234       * to <em>deselected</em>, then set <code>[A,NL]</code> to
235       * <em>selected</em>.</li>
236       *
237       * <li><code>isSelectedIndex(A) == false</code>: set <code>[A,OL]</code>
238       * to <em>selected</em>, then set <code>[A,NL]</code> to
239       * <em>deselected</em>.</li>
240       *
241       * </ul>
242       *
243       * <p>This method generates at most a single {@link ListSelectionEvent}
244       * despite changing multiple ranges. The range of values provided to the
245       * {@link ListSelectionEvent} includes only the minimum range of values
246       * which changed selection status between the beginning and end of the
247       * method.</p>
248       *
249       * @param leadIndex The new property value
250       *
251       * @see #getAnchorSelectionIndex
252       */
253      public void setLeadSelectionIndex(int leadIndex)
254      {
255        // Only set the lead selection index to < 0 if anchorSelectionIndex < 0.
256        if (leadIndex < 0)
257          {
258            if (anchorSelectionIndex < 0)
259              leadSelectionIndex = -1;
260            else
261              return;
262          }
263    
264        // Only touch the lead selection index if the anchor is >= 0.
265        if (anchorSelectionIndex < 0)
266          return;
267    
268        if (selectionMode == SINGLE_SELECTION)
269          setSelectionInterval (leadIndex, leadIndex);
270    
271        int oldLeadIndex = leadSelectionIndex;
272        if (oldLeadIndex == -1)
273          oldLeadIndex = leadIndex;
274        if (setLeadCalledFromAdd == false)
275          oldSel = sel.clone();
276        leadSelectionIndex = leadIndex;
277    
278        if (anchorSelectionIndex == -1)
279          return;
280    
281        int R1 = Math.min(anchorSelectionIndex, oldLeadIndex);
282        int R2 = Math.max(anchorSelectionIndex, oldLeadIndex);
283        int S1 = Math.min(anchorSelectionIndex, leadIndex);
284        int S2 = Math.max(anchorSelectionIndex, leadIndex);
285    
286        int lo = Math.min(R1, S1);
287        int hi = Math.max(R2, S2);
288    
289        if (isSelectedIndex(anchorSelectionIndex))
290          {
291            sel.clear(R1, R2+1);
292            sel.set(S1, S2+1);
293          }
294        else
295          {
296            sel.set(R1, R2+1);
297            sel.clear(S1, S2+1);
298          }
299    
300        int beg = sel.nextSetBit(0), end = -1;
301        for(int i=beg; i >= 0; i=sel.nextSetBit(i+1))
302          end = i;
303    
304        BitSet old = (BitSet) oldSel;
305    
306        // The new and previous lead location requires repainting.
307        old.set(oldLeadIndex, !sel.get(oldLeadIndex));
308        old.set(leadSelectionIndex, !sel.get(leadSelectionIndex));
309    
310        fireDifference(sel, old);
311      }
312    
313      /**
314       * Moves the lead selection index to <code>leadIndex</code> without
315       * changing the selection values.
316       *
317       * If leadAnchorNotificationEnabled is true, send a notification covering the
318       * old and new lead cells.
319       *
320       * @param leadIndex the new lead selection index
321       * @since 1.5
322       */
323      public void moveLeadSelectionIndex (int leadIndex)
324      {
325        if (leadSelectionIndex == leadIndex)
326          return;
327    
328        leadSelectionIndex = leadIndex;
329        if (isLeadAnchorNotificationEnabled())
330          fireValueChanged(Math.min(leadSelectionIndex, leadIndex),
331                           Math.max(leadSelectionIndex, leadIndex));
332      }
333    
334      /**
335       * Gets the value of the {@link #leadAnchorNotificationEnabled} property.
336       *
337       * @return The current property value
338       *
339       * @see #setLeadAnchorNotificationEnabled
340       */
341      public boolean isLeadAnchorNotificationEnabled()
342      {
343        return leadAnchorNotificationEnabled;
344      }
345    
346      /**
347       * Sets the value of the {@link #leadAnchorNotificationEnabled} property.
348       *
349       * @param l The new property value
350       *
351       * @see #isLeadAnchorNotificationEnabled
352       */
353      public void setLeadAnchorNotificationEnabled(boolean l)
354      {
355        leadAnchorNotificationEnabled = l;
356      }
357    
358      /**
359       * Gets the value of the {@link #valueIsAdjusting} property.
360       *
361       * @return The current property value
362       *
363       * @see #setValueIsAdjusting
364       */
365      public boolean getValueIsAdjusting()
366      {
367        return valueIsAdjusting;
368      }
369    
370      /**
371       * Sets the value of the {@link #valueIsAdjusting} property.
372       *
373       * @param v The new property value
374       *
375       * @see #getValueIsAdjusting
376       */
377      public void setValueIsAdjusting(boolean v)
378      {
379        valueIsAdjusting = v;
380      }
381    
382      /**
383       * Determines whether the selection is empty.
384       *
385       * @return <code>true</code> if the selection is empty, otherwise
386       * <code>false</code>
387       */
388      public boolean isSelectionEmpty()
389      {
390        return sel.isEmpty();
391      }
392    
393      /**
394       * Gets the smallest index which is currently a member of a selection
395       * interval.
396       *
397       * @return The least integer <code>i</code> such that <code>i >=
398       *     0</code> and <code>i</code> is a member of a selected interval, or
399       *     <code>-1</code> if there are no selected intervals
400       *
401       * @see #getMaxSelectionIndex
402       */
403      public int getMinSelectionIndex()
404      {
405        if (isSelectionEmpty())
406          return -1;
407    
408        return sel.nextSetBit(0);
409      }
410    
411      /**
412       * Gets the largest index which is currently a member of a selection
413       * interval.
414       *
415       * @return The greatest integer <code>i</code> such that <code>i >=
416       *     0</code> and <code>i</code> is a member of a selected interval, or
417       *     <code>-1</code> if there are no selected intervals
418       *
419       * @see #getMinSelectionIndex
420       */
421      public int getMaxSelectionIndex()
422      {
423        if (isSelectionEmpty())
424          return -1;
425    
426        int mx = -1;
427        for(int i=sel.nextSetBit(0); i >= 0; i=sel.nextSetBit(i+1))
428          {
429            mx = i;
430          }
431        return mx;
432      }
433    
434      /**
435       * Determines whether a particular index is a member of a selection
436       * interval.
437       *
438       * @param a The index to search for
439       *
440       * @return <code>true</code> if the index is a member of a selection interval,
441       *     otherwise <code>false</code>
442       */
443      public boolean isSelectedIndex(int a)
444      {
445        // TODO: Probably throw an exception here?
446        if (a >= sel.length() || a < 0)
447          return false;
448        return sel.get(a);
449      }
450    
451      /**
452       * If the {@link #selectionMode} property is equal to
453       * <code>SINGLE_SELECTION</code> equivalent to calling
454       * <code>setSelectionInterval(index1, index2)</code>;
455       * If the {@link #selectionMode} property is equal to
456       * <code>SINGLE_INTERVAL_SELECTION</code> and the interval being
457       * added is not adjacent to an already selected interval,
458       * equivalent to <code>setSelectionInterval(index1, index2)</code>.
459       * Otherwise adds the range <code>[index0, index1]</code>
460       * to the selection interval set.
461       *
462       * @param index0 The beginning of the range of indices to select
463       * @param index1 The end of the range of indices to select
464       *
465       * @see #setSelectionInterval
466       * @see #removeSelectionInterval
467       */
468      public void addSelectionInterval(int index0, int index1)
469      {
470        if (index0 == -1 || index1 == -1)
471          return;
472    
473        if (selectionMode == SINGLE_SELECTION)
474          setSelectionInterval(index0, index1);
475        else
476        {
477        int lo = Math.min(index0, index1);
478        int hi = Math.max(index0, index1);
479        oldSel = sel.clone();
480    
481    
482        // COMPAT: Like Sun (but not like IBM), we allow calls to
483        // addSelectionInterval when selectionMode is
484        // SINGLE_SELECTION_INTERVAL iff the interval being added
485        // is adjacent to an already selected interval
486        if (selectionMode == SINGLE_INTERVAL_SELECTION)
487          if (!(isSelectedIndex(index0) ||
488                isSelectedIndex(index1) ||
489                isSelectedIndex(Math.max(lo-1,0)) ||
490                isSelectedIndex(Math.min(hi+1,sel.size()))))
491            sel.clear();
492    
493        // We have to update the anchorSelectionIndex and leadSelectionIndex
494        // variables
495    
496        // The next if statements breaks down to "if this selection is adjacent
497        // to the previous selection and going in the same direction"
498        if ((isSelectedIndex(leadSelectionIndex))
499            && ((index0 - 1 == leadSelectionIndex
500                 && (index1 >= index0)
501                 && (leadSelectionIndex >= anchorSelectionIndex))
502                || (index0 + 1 == leadSelectionIndex && (index1 <= index0)
503                    && (leadSelectionIndex <= anchorSelectionIndex)))
504            && (anchorSelectionIndex != -1 || leadSelectionIndex != -1))
505          {
506            // setting setLeadCalledFromAdd to true tells setLeadSelectionIndex
507            //   not to update oldSel
508            setLeadCalledFromAdd = true;
509            setLeadSelectionIndex(index1);
510            setLeadCalledFromAdd = false;
511          }
512        else
513          {
514            leadSelectionIndex = index1;
515            anchorSelectionIndex = index0;
516            sel.set(lo, hi+1);
517            fireDifference(sel, (BitSet) oldSel);
518          }
519        }
520      }
521    
522    
523      /**
524       * Deselects all indices in the inclusive range
525       * <code>[index0,index1]</code>.
526       *
527       * @param index0 The beginning of the range of indices to deselect
528       * @param index1 The end of the range of indices to deselect
529       *
530       * @see #addSelectionInterval
531       * @see #setSelectionInterval
532       */
533      public void removeSelectionInterval(int index0,
534                                          int index1)
535      {
536        if (index0 == -1 || index1 == -1)
537          return;
538    
539        oldSel = sel.clone();
540        int lo = Math.min(index0, index1);
541        int hi = Math.max(index0, index1);
542    
543        // if selectionMode is SINGLE_INTERVAL_SELECTION and removing the interval
544        //   (index0,index1) would leave two disjoint selection intervals, remove all
545        //   selected indices from lo to the last selected index
546        if (getMinSelectionIndex() > 0 && getMinSelectionIndex() < lo &&
547            selectionMode == SINGLE_INTERVAL_SELECTION)
548          hi = sel.size() - 1;
549    
550        sel.clear(lo, hi+1);
551        //update anchorSelectionIndex and leadSelectionIndex variables
552        //TODO: will probably need MouseDragged to test properly and know if this works
553        setAnchorSelectionIndex(index0);
554        leadSelectionIndex = index1;
555    
556        fireDifference(sel, (BitSet) oldSel);
557      }
558    
559      /**
560       * Removes all intervals in the selection set.
561       */
562      public void clearSelection()
563      {
564        // Find the selected interval.
565        int from = sel.nextSetBit(0);
566        if (from < 0)
567          return; // Empty selection - nothing to do.
568        int to = from;
569    
570        int i;
571    
572        for (i = from; i>=0; i=sel.nextSetBit(i+1))
573          to = i;
574    
575        sel.clear();
576        fireValueChanged(from, to, valueIsAdjusting);
577      }
578    
579      /**
580       * Fire the change event, covering the difference between the two sets.
581       *
582       * @param current the current set
583       * @param x the previous set, the object will be reused.
584       */
585      private void fireDifference(BitSet current, BitSet x)
586      {
587        x.xor(current);
588        int from = x.nextSetBit(0);
589        if (from < 0)
590          return; // No difference.
591        int to = from;
592        int i;
593    
594        for (i = from; i >= 0; i = x.nextSetBit(i+1))
595          to = i;
596    
597        fireValueChanged(from, to, valueIsAdjusting);
598      }
599    
600      /**
601       * Clears the current selection and marks a given interval as "selected". If
602       * the current selection mode is <code>SINGLE_SELECTION</code> only the
603       * index <code>index2</code> is selected.
604       *
605       * @param anchor  the anchor selection index.
606       * @param lead  the lead selection index.
607       */
608      public void setSelectionInterval(int anchor, int lead)
609      {
610        if (anchor == -1 || lead == -1)
611          return;
612        if (selectionMode == SINGLE_SELECTION)
613          {
614            int lo = lead;
615            int hi = lead;
616            int selected = sel.nextSetBit(0);
617            if (selected == lead)
618              return;  // the selection is not changing
619            if (selected >= 0)
620              {
621                lo = Math.min(lo, selected);
622                hi = Math.max(hi, selected);
623              }
624            if (anchorSelectionIndex >= 0)
625              {
626                lo = Math.min(lo, anchorSelectionIndex);
627                hi = Math.max(hi, anchorSelectionIndex);
628              }
629            sel.clear();
630            sel.set(lead);
631            leadSelectionIndex = lead;
632            anchorSelectionIndex = lead;
633            fireValueChanged(lo, hi);
634          }
635        else if (selectionMode == SINGLE_INTERVAL_SELECTION)
636          {
637            // determine the current interval
638            int first = sel.nextSetBit(0);
639            int last = first;
640            if (first >= 0)
641              last += (sel.cardinality() - 1);
642    
643            // update the selection
644            int lo = Math.min(anchor, lead);
645            int hi = Math.max(anchor, lead);
646            if (lo == first && hi == last)
647              return;  // selected interval is not being changed
648            sel.clear();
649            sel.set(lo, hi + 1);
650    
651            // include the old selection in the event range
652            if (first >= 0)
653              lo = Math.min(lo, first);
654            if (last >= 0)
655              hi = Math.max(hi, last);
656            if (anchorSelectionIndex >= 0)
657              {
658                lo = Math.min(lo, anchorSelectionIndex);
659                hi = Math.max(hi, anchorSelectionIndex);
660              }
661            anchorSelectionIndex = anchor;
662            leadSelectionIndex = lead;
663            fireValueChanged(lo, hi);
664          }
665        else
666        {
667          BitSet oldSel = (BitSet) sel.clone();
668          sel.clear();
669          if (selectionMode == SINGLE_SELECTION)
670            anchor = lead;
671    
672          int lo = Math.min(anchor, lead);
673          int hi = Math.max(anchor, lead);
674          sel.set(lo, hi+1);
675          // update the anchorSelectionIndex and leadSelectionIndex variables
676          setAnchorSelectionIndex(anchor);
677          leadSelectionIndex = lead;
678    
679          fireDifference(sel, oldSel);
680        }
681      }
682    
683      /**
684       * Inserts a number of indices either before or after a particular
685       * position in the set of indices. Renumbers all indices after the
686       * inserted range. The new indices in the inserted range are not
687       * selected. This method is typically called to synchronize the selection
688       * model with an inserted range of elements in a {@link ListModel}.
689       *
690       * @param index The position to insert indices at
691       * @param length The number of indices to insert
692       * @param before Indicates whether to insert the indices before the index
693       *     or after it
694       */
695      public void insertIndexInterval(int index,
696                                      int length,
697                                      boolean before)
698      {
699        if (!before)
700          {
701            index++;
702            length--;
703          }
704        BitSet tmp = sel.get(index, sel.size());
705        sel.clear(index, sel.size());
706        int n = tmp.size();
707        for (int i = 0; i < n; ++i)
708          sel.set(index + length + i, tmp.get(i));
709      }
710    
711      /**
712       * Removes a range from the set of indices. Renumbers all indices after
713       * the removed range. This method is typically called to synchronize the
714       * selection model with a deleted range of elements in a {@link
715       * ListModel}.
716       *
717       * @param index0 The first index to remove (inclusive)
718       * @param index1 The last index to remove (inclusive)
719       */
720      public void removeIndexInterval(int index0,
721                                      int index1)
722      {
723        int lo = Math.min(index0, index1);
724        int hi = Math.max(index0, index1);
725    
726        BitSet tmp = sel.get(hi, sel.size());
727        sel.clear(lo, sel.size());
728        int n = tmp.size();
729        for (int i = 0; i < n; ++i)
730          sel.set(lo + i, tmp.get(i));
731      }
732    
733      /**
734       * Fires a {@link ListSelectionEvent} to all the listeners of type {@link
735       * ListSelectionListener} registered with this selection model to
736       * indicate that a series of adjustment has just ended.
737       *
738       * The values of {@link #getMinSelectionIndex} and
739       * {@link #getMaxSelectionIndex} are used in the {@link ListSelectionEvent}
740       * that gets fired.
741       *
742       * @param isAdjusting <code>true</code> if this is the final change
743       *     in a series of adjustments, <code>false/code> otherwise
744       */
745      protected void fireValueChanged(boolean isAdjusting)
746      {
747        fireValueChanged(getMinSelectionIndex(), getMaxSelectionIndex(),
748                         isAdjusting);
749      }
750    
751      /**
752       * Fires a {@link ListSelectionEvent} to all the listeners of type {@link
753       * ListSelectionListener} registered with this selection model.
754       *
755       * @param firstIndex The low index of the changed range
756       * @param lastIndex The high index of the changed range
757       */
758      protected void fireValueChanged(int firstIndex, int lastIndex)
759      {
760        fireValueChanged(firstIndex, lastIndex, getValueIsAdjusting());
761      }
762    
763      /**
764       * Fires a {@link ListSelectionEvent} to all the listeners of type {@link
765       * ListSelectionListener} registered with this selection model.
766       *
767       * @param firstIndex The low index of the changed range
768       * @param lastIndex The high index of the changed range
769       * @param isAdjusting Whether this change is part of a seqence of adjustments
770       *     made to the selection, such as during interactive scrolling
771       */
772      protected void fireValueChanged(int firstIndex, int lastIndex,
773                                      boolean isAdjusting)
774      {
775        ListSelectionEvent evt = new ListSelectionEvent(this, firstIndex,
776                                                        lastIndex, isAdjusting);
777        ListSelectionListener[] listeners = getListSelectionListeners();
778        for (int i = 0; i < listeners.length; ++i)
779          listeners[i].valueChanged(evt);
780      }
781    
782      /**
783       * Adds a listener.
784       *
785       * @param listener The listener to add
786       *
787       * @see #removeListSelectionListener
788       * @see #getListSelectionListeners
789       */
790      public void addListSelectionListener(ListSelectionListener listener)
791      {
792        listenerList.add(ListSelectionListener.class, listener);
793      }
794    
795      /**
796       * Removes a registered listener.
797       *
798       * @param listener The listener to remove
799       *
800       * @see #addListSelectionListener
801       * @see #getListSelectionListeners
802       */
803      public void removeListSelectionListener(ListSelectionListener listener)
804      {
805        listenerList.remove(ListSelectionListener.class, listener);
806      }
807    
808      /**
809       * Returns an array of all registerers listeners.
810       *
811       * @param listenerType The type of listener to retrieve
812       *
813       * @return The array
814       *
815       * @see #getListSelectionListeners
816       * @since 1.3
817       */
818      public <T extends EventListener> T[] getListeners(Class<T> listenerType)
819      {
820        return listenerList.getListeners(listenerType);
821      }
822    
823      /**
824       * Returns an array of all registerd list selection listeners.
825       *
826       * @return the array
827       *
828       * @see #addListSelectionListener
829       * @see #removeListSelectionListener
830       * @see #getListeners
831       * @since 1.4
832       */
833      public ListSelectionListener[] getListSelectionListeners()
834      {
835        return (ListSelectionListener[]) getListeners(ListSelectionListener.class);
836      }
837    
838      /**
839       * Returns a clone of this object.
840       * <code>listenerList</code> don't gets duplicated.
841       *
842       * @return the cloned object
843       *
844       * @throws CloneNotSupportedException if an error occurs
845       */
846      public Object clone()
847        throws CloneNotSupportedException
848      {
849        DefaultListSelectionModel model =
850          (DefaultListSelectionModel) super.clone();
851        model.sel = (BitSet) sel.clone();
852        model.listenerList = new EventListenerList();
853        return model;
854      }
855    }