Source for javax.swing.DefaultListSelectionModel

   1: /* DefaultListSelectionModel.java --
   2:    Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package javax.swing;
  40: 
  41: import java.io.Serializable;
  42: import java.util.BitSet;
  43: import java.util.EventListener;
  44: 
  45: import javax.swing.event.EventListenerList;
  46: import javax.swing.event.ListSelectionEvent;
  47: import javax.swing.event.ListSelectionListener;
  48: 
  49: /**
  50:  * The default implementation of {@link ListSelectionModel},
  51:  * which is used by {@link javax.swing.JList} and
  52:  * similar classes to manage the selection status of a number of data
  53:  * elements.
  54:  *
  55:  * <p>The class is organized <em>abstractly</em> as a set of intervals of
  56:  * integers. Each interval indicates an inclusive range of indices in a
  57:  * list -- held by some other object and unknown to this class -- which is
  58:  * considered "selected". There are various accessors for querying and
  59:  * modifying the set of intervals, with simplified forms accepting a single
  60:  * index, representing an interval with only one element. </p>
  61:  */
  62: public class DefaultListSelectionModel implements Cloneable,
  63:                                                   ListSelectionModel,
  64:                                                   Serializable
  65: {
  66:   private static final long serialVersionUID = -5718799865110415860L;
  67: 
  68:   /** The list of ListSelectionListeners subscribed to this selection model. */
  69:   protected EventListenerList listenerList = new EventListenerList();
  70: 
  71: 
  72:   /**
  73:    * The current list selection mode. Must be one of the numeric constants
  74:    * <code>SINGLE_SELECTION</code>, <code>SINGLE_INTERVAL_SELECTION</code>
  75:    * or <code>MULTIPLE_INTERVAL_SELECTION</code> from {@link
  76:    * ListSelectionModel}. The default value is
  77:    * <code>MULTIPLE_INTERVAL_SELECTION</code>.
  78:    */
  79:   int selectionMode = MULTIPLE_INTERVAL_SELECTION;
  80: 
  81:   /**
  82:    * The index of the "lead" of the most recent selection. The lead is the
  83:    * second argument in any call to {@link #setSelectionInterval}, {@link
  84:    * #addSelectionInterval} or {@link #removeSelectionInterval}. Generally
  85:    * the lead refers to the most recent position a user dragged their mouse
  86:    * over.
  87:    */
  88:   int leadSelectionIndex = -1;
  89: 
  90:   /**
  91:    * The index of the "anchor" of the most recent selection. The anchor is
  92:    * the first argument in any call to {@link #setSelectionInterval},
  93:    * {@link #addSelectionInterval} or {@link
  94:    * #removeSelectionInterval}. Generally the anchor refers to the first
  95:    * recent position a user clicks when they begin to drag their mouse over
  96:    * a list.
  97:    *
  98:    * @see #getAnchorSelectionIndex
  99:    * @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: }