       1 /*
       2  * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
       3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       4  *
       5  * This code is free software; you can redistribute it and/or modify it
       6  * under the terms of the GNU General Public License version 2 only, as
       7  * published by the Free Software Foundation.  Oracle designates this
       8  * particular file as subject to the "Classpath" exception as provided
       9  * by Oracle in the LICENSE file that accompanied this code.
      10  *
      11  * This code is distributed in the hope that it will be useful, but WITHOUT
      12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      14  * version 2 for more details (a copy is included in the LICENSE file that
      15  * accompanied this code).
      16  *
      17  * You should have received a copy of the GNU General Public License version
      18  * 2 along with this work; if not, write to the Free Software Foundation,
      19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
      20  *
      21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
      22  * or visit www.oracle.com if you need additional information or have any
      23  * questions.
      24  */
      25
      26 package javax.swing;
      27
      28 import javax.swing.event.*;
      29
      30 /**
      31  * This interface represents the current state of the
      32  * selection for any of the components that display a
      33  * list of values with stable indices.  The selection is
      34  * modeled as a set of intervals, each interval represents
      35  * a contiguous range of selected list elements.
      36  * The methods for modifying the set of selected intervals
      37  * all take a pair of indices, index0 and index1, that represent
      38  * a closed interval, i.e. the interval includes both index0 and
      39  * index1.
      40  *
      41  * @author Hans Muller
      42  * @author Philip Milne
      43  * @see DefaultListSelectionModel
      44  * @since 1.2
      45  */
      46
      47 public interface ListSelectionModel
      48 {
      49     /**
      50      * A value for the selectionMode property: select one list index
      51      * at a time.
      52      *
      53      * @see #setSelectionMode
      54      */
      55     int SINGLE_SELECTION = 0;
      56
      57     /**
      58      * A value for the selectionMode property: select one contiguous
      59      * range of indices at a time.
      60      *
      61      * @see #setSelectionMode
      62      */
      63     int SINGLE_INTERVAL_SELECTION = 1;
      64
      65     /**
      66      * A value for the selectionMode property: select one or more
      67      * contiguous ranges of indices at a time.
      68      *
      69      * @see #setSelectionMode
      70      */
      71     int MULTIPLE_INTERVAL_SELECTION = 2;
      72
      73
      74     /**
      75      * Changes the selection to be between {@code index0} and {@code index1}
      76      * inclusive. {@code index0} doesn't have to be less than or equal to
      77      * {@code index1}.
      78      * <p>
      79      * In {@code SINGLE_SELECTION} selection mode, only the second index
      80      * is used.
      81      * <p>
      82      * If this represents a change to the current selection, then each
      83      * {@code ListSelectionListener} is notified of the change.
      84      *
      85      * @param index0 one end of the interval.
      86      * @param index1 other end of the interval
      87      * @see #addListSelectionListener
      88      */
      89     void setSelectionInterval(int index0, int index1);
      90
      91
      92     /**
      93      * Changes the selection to be the set union of the current selection
      94      * and the indices between {@code index0} and {@code index1} inclusive.
      95      * {@code index0} doesn't have to be less than or equal to {@code index1}.
      96      * <p>
      97      * In {@code SINGLE_SELECTION} selection mode, this is equivalent
      98      * to calling {@code setSelectionInterval}, and only the second index
      99      * is used. In {@code SINGLE_INTERVAL_SELECTION} selection mode, this
     100      * method behaves like {@code setSelectionInterval}, unless the given
     101      * interval is immediately adjacent to or overlaps the existing selection,
     102      * and can therefore be used to grow the selection.
     103      * <p>
     104      * If this represents a change to the current selection, then each
     105      * {@code ListSelectionListener} is notified of the change.
     106      *
     107      * @param index0 one end of the interval.
     108      * @param index1 other end of the interval
     109      * @see #addListSelectionListener
     110      * @see #setSelectionInterval
     111      */
     112     void addSelectionInterval(int index0, int index1);
     113
     114
     115     /**
     116      * Changes the selection to be the set difference of the current selection
     117      * and the indices between {@code index0} and {@code index1} inclusive.
     118      * {@code index0} doesn't have to be less than or equal to {@code index1}.
     119      * <p>
     120      * In {@code SINGLE_INTERVAL_SELECTION} selection mode, if the removal
     121      * would produce two disjoint selections, the removal is extended through
     122      * the greater end of the selection. For example, if the selection is
     123      * {@code 0-10} and you supply indices {@code 5,6} (in any order) the
     124      * resulting selection is {@code 0-4}.
     125      * <p>
     126      * If this represents a change to the current selection, then each
     127      * {@code ListSelectionListener} is notified of the change.
     128      *
     129      * @param index0 one end of the interval.
     130      * @param index1 other end of the interval
     131      * @see #addListSelectionListener
     132      */
     133     void removeSelectionInterval(int index0, int index1);
     134
     135
     136     /**
     137      * Returns the first selected index or -1 if the selection is empty.
     138      *
     139      * @return the first selected index or -1 if the selection is empty.
     140      */
     141     int getMinSelectionIndex();
     142
     143
     144     /**
     145      * Returns the last selected index or -1 if the selection is empty.
     146      *
     147      * @return the last selected index or -1 if the selection is empty.
     148      */
     149     int getMaxSelectionIndex();
     150
     151
     152     /**
     153      * Returns true if the specified index is selected.
     154      *
     155      * @param index an index
     156      * @return {@code true} if the specified index is selected
     157      */
     158     boolean isSelectedIndex(int index);
     159
     160
     161     /**
     162      * Return the first index argument from the most recent call to
     163      * setSelectionInterval(), addSelectionInterval() or removeSelectionInterval().
     164      * The most recent index0 is considered the "anchor" and the most recent
     165      * index1 is considered the "lead".  Some interfaces display these
     166      * indices specially, e.g. Windows95 displays the lead index with a
     167      * dotted yellow outline.
     168      *
     169      * @return the anchor selection index
     170      * @see #getLeadSelectionIndex
     171      * @see #setSelectionInterval
     172      * @see #addSelectionInterval
     173      */
     174     int getAnchorSelectionIndex();
     175
     176
     177     /**
     178      * Set the anchor selection index.
     179      *
     180      * @param index the anchor selection index
     181      * @see #getAnchorSelectionIndex
     182      */
     183     void setAnchorSelectionIndex(int index);
     184
     185
     186     /**
     187      * Return the second index argument from the most recent call to
     188      * setSelectionInterval(), addSelectionInterval() or removeSelectionInterval().
     189      *
     190      * @return the lead selection index.
     191      * @see #getAnchorSelectionIndex
     192      * @see #setSelectionInterval
     193      * @see #addSelectionInterval
     194      */
     195     int getLeadSelectionIndex();
     196
     197     /**
     198      * Set the lead selection index.
     199      *
     200      * @param index the lead selection index
     201      * @see #getLeadSelectionIndex
     202      */
     203     void setLeadSelectionIndex(int index);
     204
     205     /**
     206      * Change the selection to the empty set.  If this represents
     207      * a change to the current selection then notify each ListSelectionListener.
     208      *
     209      * @see #addListSelectionListener
     210      */
     211     void clearSelection();
     212
     213     /**
     214      * Returns true if no indices are selected.
     215      *
     216      * @return {@code true} if no indices are selected.
     217      */
     218     boolean isSelectionEmpty();
     219
     220     /**
     221      * Insert {@code length} indices beginning before/after {@code index}. This is typically
     222      * called to sync the selection model with a corresponding change
     223      * in the data model.
     224      *
     225      * @param index the beginning of the interval
     226      * @param length the length of the interval
     227      * @param before if {@code true}, interval inserts before the {@code index},
     228      *               otherwise, interval inserts after the {@code index}
     229      */
     230     void insertIndexInterval(int index, int length, boolean before);
     231
     232     /**
     233      * Remove the indices in the interval {@code index0,index1} (inclusive) from
     234      * the selection model.  This is typically called to sync the selection
     235      * model width a corresponding change in the data model.
     236      *
     237      * @param index0 the beginning of the interval
     238      * @param index1 the end of the interval
     239      */
     240     void removeIndexInterval(int index0, int index1);
     241
     242     /**
     243      * Sets the {@code valueIsAdjusting} property, which indicates whether
     244      * or not upcoming selection changes should be considered part of a single
     245      * change. The value of this property is used to initialize the
     246      * {@code valueIsAdjusting} property of the {@code ListSelectionEvent}s that
     247      * are generated.
     248      * <p>
     249      * For example, if the selection is being updated in response to a user
     250      * drag, this property can be set to {@code true} when the drag is initiated
     251      * and set to {@code false} when the drag is finished. During the drag,
     252      * listeners receive events with a {@code valueIsAdjusting} property
     253      * set to {@code true}. At the end of the drag, when the change is
     254      * finalized, listeners receive an event with the value set to {@code false}.
     255      * Listeners can use this pattern if they wish to update only when a change
     256      * has been finalized.
     257      * <p>
     258      * Setting this property to {@code true} begins a series of changes that
     259      * is to be considered part of a single change. When the property is changed
     260      * back to {@code false}, an event is sent out characterizing the entire
     261      * selection change (if there was one), with the event's
     262      * {@code valueIsAdjusting} property set to {@code false}.
     263      *
     264      * @param valueIsAdjusting the new value of the property
     265      * @see #getValueIsAdjusting
     266      * @see javax.swing.event.ListSelectionEvent#getValueIsAdjusting
     267      */
     268     void setValueIsAdjusting(boolean valueIsAdjusting);
     269
     270     /**
     271      * Returns {@code true} if the selection is undergoing a series of changes.
     272      *
     273      * @return true if the selection is undergoing a series of changes
     274      * @see #setValueIsAdjusting
     275      */
     276     boolean getValueIsAdjusting();
     277
     278     /**
     279      * Sets the selection mode. The following list describes the accepted
     280      * selection modes:
     281      * <ul>
     282      * <li>{@code ListSelectionModel.SINGLE_SELECTION} -
     283      *   Only one list index can be selected at a time. In this mode,
     284      *   {@code setSelectionInterval} and {@code addSelectionInterval} are
     285      *   equivalent, both replacing the current selection with the index
     286      *   represented by the second argument (the "lead").
     287      * <li>{@code ListSelectionModel.SINGLE_INTERVAL_SELECTION} -
     288      *   Only one contiguous interval can be selected at a time.
     289      *   In this mode, {@code addSelectionInterval} behaves like
     290      *   {@code setSelectionInterval} (replacing the current selection),
     291      *   unless the given interval is immediately adjacent to or overlaps
     292      *   the existing selection, and can therefore be used to grow it.
     293      * <li>{@code ListSelectionModel.MULTIPLE_INTERVAL_SELECTION} -
     294      *   In this mode, there's no restriction on what can be selected.
     295      * </ul>
     296      *
     297      * @param selectionMode the selection mode
     298      * @see #getSelectionMode
     299      * @throws IllegalArgumentException if the selection mode isn't
     300      *         one of those allowed
     301      */
     302     void setSelectionMode(int selectionMode);
     303
     304     /**
     305      * Returns the current selection mode.
     306      *
     307      * @return the current selection mode
     308      * @see #setSelectionMode
     309      */
     310     int getSelectionMode();
     311
     312     /**
     313      * Add a listener to the list that's notified each time a change
     314      * to the selection occurs.
     315      *
     316      * @param x the ListSelectionListener
     317      * @see #removeListSelectionListener
     318      * @see #setSelectionInterval
     319      * @see #addSelectionInterval
     320      * @see #removeSelectionInterval
     321      * @see #clearSelection
     322      * @see #insertIndexInterval
     323      * @see #removeIndexInterval
     324      */
     325     void addListSelectionListener(ListSelectionListener x);
     326
     327     /**
     328      * Remove a listener from the list that's notified each time a
     329      * change to the selection occurs.
     330      *
     331      * @param x the ListSelectionListener
     332      * @see #addListSelectionListener
     333      */
     334     void removeListSelectionListener(ListSelectionListener x);
     335
     336     /**
     337      * Returns an array of all of the selected indices in the selection model,
     338      * in increasing order.
     339      *
     340      * @return all of the selected indices, in increasing order,
     341      *         or an empty array if nothing is selected
     342      * @see #removeSelectionInterval
     343      * @see #addListSelectionListener
     344      * @since 11
     345      * @implSpec The default implementation iterates from minimum selected
     346      * index {@link #getMinSelectionIndex()} to maximum selected index {@link
     347      * #getMaxSelectionIndex()} and returns the selected indices {@link
     348      * #isSelectedIndex(int)} in a newly allocated int array.
     349      */
     350     default int[] getSelectedIndices() {
     351         int iMin = getMinSelectionIndex();
     352         int iMax = getMaxSelectionIndex();
     353
     354         if ((iMin < 0) || (iMax < 0)) {
     355             return new int[0];
     356         }
     357
     358         int[] rvTmp = new int[1+ (iMax - iMin)];
     359         int n = 0;
     360         for(int i = iMin; i <= iMax; i++) {
     361             if (isSelectedIndex(i)) {
     362                 rvTmp[n++] = i;
     363             }
     364         }
     365         int[] rv = new int[n];
     366         System.arraycopy(rvTmp, 0, rv, 0, n);
     367         return rv;
     368     }
     369
     370     /**
     371      * Returns the number of selected items.
     372      *
     373      * @return the number of selected items, 0 if no items are selected
     374      * @since 11
     375      * @implSpec The default implementation iterates from minimum selected
     376      * index {@link #getMinSelectionIndex()} to maximum selected index {@link
     377      * #getMaxSelectionIndex()} and returns the number of selected indices
     378      * {@link #isSelectedIndex(int)}
     379      */
     380     default int getSelectedItemsCount() {
     381         int iMin = getMinSelectionIndex();
     382         int iMax = getMaxSelectionIndex();
     383         int count = 0;
     384
     385         for(int i = iMin; i <= iMax; i++) {
     386             if (isSelectedIndex(i)) {
     387                 count++;
     388             }
     389         }
     390         return count;
     391     }
     392 }