jdk/src/share/classes/javax/swing/DefaultListSelectionModel.java
author ant
Thu, 17 May 2012 21:48:57 +0400
changeset 12661 6cf8b7116579
parent 12173 80420757767c
child 20458 f2423fb3fd19
permissions -rw-r--r--
7125044: [macosx] Test failure because Component.transferFocus() works differently in applet and application. Summary: forward port from 7u4 Reviewed-by: art
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 1301
diff changeset
     2
 * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 1301
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 1301
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 1301
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 1301
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 1301
diff changeset
    23
 * questions.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
package javax.swing;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
import java.util.EventListener;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
import java.util.BitSet;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
import java.io.Serializable;
466
6acd5ec503a8 4935607: RFE: LTP: Should be possible to set the TRANSIENT attribute of propertiies to FALSE
malenkov
parents: 2
diff changeset
    31
import java.beans.Transient;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
import javax.swing.event.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
/**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
 * Default data model for list selections.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
 * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
 * <strong>Warning:</strong>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
 * Serialized objects of this class will not be compatible with
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
 * future Swing releases. The current serialization support is
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
 * appropriate for short term storage or RMI between applications running
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
 * the same version of Swing.  As of 1.4, support for long term storage
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
 * of all JavaBeans<sup><font size="-2">TM</font></sup>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
 * has been added to the <code>java.beans</code> package.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
 * Please see {@link java.beans.XMLEncoder}.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
 * @author Philip Milne
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
 * @author Hans Muller
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
 * @see ListSelectionModel
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
public class DefaultListSelectionModel implements ListSelectionModel, Cloneable, Serializable
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
    private static final int MIN = -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
    private static final int MAX = Integer.MAX_VALUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
    private int selectionMode = MULTIPLE_INTERVAL_SELECTION;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
    private int minIndex = MAX;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
    private int maxIndex = MIN;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
    private int anchorIndex = -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
    private int leadIndex = -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
    private int firstAdjustedIndex = MAX;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
    private int lastAdjustedIndex = MIN;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
    private boolean isAdjusting = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
    private int firstChangedIndex = MAX;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
    private int lastChangedIndex = MIN;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
    private BitSet value = new BitSet(32);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
    protected EventListenerList listenerList = new EventListenerList();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
    protected boolean leadAnchorNotificationEnabled = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
    /** {@inheritDoc} */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
    public int getMinSelectionIndex() { return isSelectionEmpty() ? -1 : minIndex; }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
    /** {@inheritDoc} */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
    public int getMaxSelectionIndex() { return maxIndex; }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
    /** {@inheritDoc} */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
    public boolean getValueIsAdjusting() { return isAdjusting; }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
    /** {@inheritDoc} */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
    public int getSelectionMode() { return selectionMode; }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
     * {@inheritDoc}
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
     * @throws IllegalArgumentException {@inheritDoc}
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
    public void setSelectionMode(int selectionMode) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
        switch (selectionMode) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
        case SINGLE_SELECTION:
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
        case SINGLE_INTERVAL_SELECTION:
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
        case MULTIPLE_INTERVAL_SELECTION:
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
            this.selectionMode = selectionMode;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
        default:
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
            throw new IllegalArgumentException("invalid selectionMode");
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
    /** {@inheritDoc} */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
    public boolean isSelectedIndex(int index) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
        return ((index < minIndex) || (index > maxIndex)) ? false : value.get(index);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
    /** {@inheritDoc} */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
    public boolean isSelectionEmpty() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
        return (minIndex > maxIndex);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
    /** {@inheritDoc} */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
    public void addListSelectionListener(ListSelectionListener l) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
        listenerList.add(ListSelectionListener.class, l);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
    /** {@inheritDoc} */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
    public void removeListSelectionListener(ListSelectionListener l) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
        listenerList.remove(ListSelectionListener.class, l);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
     * Returns an array of all the list selection listeners
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
     * registered on this <code>DefaultListSelectionModel</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
     * @return all of this model's <code>ListSelectionListener</code>s
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
     *         or an empty
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
     *         array if no list selection listeners are currently registered
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
     * @see #addListSelectionListener
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
     * @see #removeListSelectionListener
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
     * @since 1.4
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
    public ListSelectionListener[] getListSelectionListeners() {
1301
15e81207e1f2 6727662: Code improvement and warnings removing from swing packages
rupashka
parents: 466
diff changeset
   136
        return listenerList.getListeners(ListSelectionListener.class);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
     * Notifies listeners that we have ended a series of adjustments.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
    protected void fireValueChanged(boolean isAdjusting) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
        if (lastChangedIndex == MIN) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
        /* Change the values before sending the event to the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
         * listeners in case the event causes a listener to make
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
         * another change to the selection.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
        int oldFirstChangedIndex = firstChangedIndex;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
        int oldLastChangedIndex = lastChangedIndex;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
        firstChangedIndex = MAX;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
        lastChangedIndex = MIN;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
        fireValueChanged(oldFirstChangedIndex, oldLastChangedIndex, isAdjusting);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
     * Notifies <code>ListSelectionListeners</code> that the value
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
     * of the selection, in the closed interval <code>firstIndex</code>,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
     * <code>lastIndex</code>, has changed.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
    protected void fireValueChanged(int firstIndex, int lastIndex) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
        fireValueChanged(firstIndex, lastIndex, getValueIsAdjusting());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
     * @param firstIndex the first index in the interval
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
     * @param lastIndex the last index in the interval
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
     * @param isAdjusting true if this is the final change in a series of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
     *          adjustments
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
     * @see EventListenerList
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
    protected void fireValueChanged(int firstIndex, int lastIndex, boolean isAdjusting)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
        Object[] listeners = listenerList.getListenerList();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
        ListSelectionEvent e = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
        for (int i = listeners.length - 2; i >= 0; i -= 2) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
            if (listeners[i] == ListSelectionListener.class) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
                if (e == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
                    e = new ListSelectionEvent(this, firstIndex, lastIndex, isAdjusting);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
                ((ListSelectionListener)listeners[i+1]).valueChanged(e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
    private void fireValueChanged() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
        if (lastAdjustedIndex == MIN) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
        /* If getValueAdjusting() is true, (eg. during a drag opereration)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
         * record the bounds of the changes so that, when the drag finishes (and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
         * setValueAdjusting(false) is called) we can post a single event
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
         * with bounds covering all of these individual adjustments.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
        if (getValueIsAdjusting()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
            firstChangedIndex = Math.min(firstChangedIndex, firstAdjustedIndex);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
            lastChangedIndex = Math.max(lastChangedIndex, lastAdjustedIndex);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
        /* Change the values before sending the event to the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
         * listeners in case the event causes a listener to make
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
         * another change to the selection.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
        int oldFirstAdjustedIndex = firstAdjustedIndex;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
        int oldLastAdjustedIndex = lastAdjustedIndex;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
        firstAdjustedIndex = MAX;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
        lastAdjustedIndex = MIN;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
        fireValueChanged(oldFirstAdjustedIndex, oldLastAdjustedIndex);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
     * Returns an array of all the objects currently registered as
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
     * <code><em>Foo</em>Listener</code>s
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
     * upon this model.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
     * <code><em>Foo</em>Listener</code>s
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
     * are registered using the <code>add<em>Foo</em>Listener</code> method.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
     * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
     * You can specify the <code>listenerType</code> argument
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
     * with a class literal, such as <code><em>Foo</em>Listener.class</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
     * For example, you can query a <code>DefaultListSelectionModel</code>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
     * instance <code>m</code>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
     * for its list selection listeners
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
     * with the following code:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
     * <pre>ListSelectionListener[] lsls = (ListSelectionListener[])(m.getListeners(ListSelectionListener.class));</pre>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
     * If no such listeners exist,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
     * this method returns an empty array.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
     * @param listenerType  the type of listeners requested;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
     *          this parameter should specify an interface
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
     *          that descends from <code>java.util.EventListener</code>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
     * @return an array of all objects registered as
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
     *          <code><em>Foo</em>Listener</code>s
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
     *          on this model,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
     *          or an empty array if no such
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
     *          listeners have been added
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
     * @exception ClassCastException if <code>listenerType</code> doesn't
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
     *          specify a class or interface that implements
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
     *          <code>java.util.EventListener</code>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
     * @see #getListSelectionListeners
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
     * @since 1.3
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
    public <T extends EventListener> T[] getListeners(Class<T> listenerType) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
        return listenerList.getListeners(listenerType);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
    // Updates first and last change indices
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
    private void markAsDirty(int r) {
12173
80420757767c 7027139: getFirstIndex() does not return the first index that has changed
rupashka
parents: 5506
diff changeset
   255
        if (r == -1) {
80420757767c 7027139: getFirstIndex() does not return the first index that has changed
rupashka
parents: 5506
diff changeset
   256
            return;
80420757767c 7027139: getFirstIndex() does not return the first index that has changed
rupashka
parents: 5506
diff changeset
   257
        }
80420757767c 7027139: getFirstIndex() does not return the first index that has changed
rupashka
parents: 5506
diff changeset
   258
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
        firstAdjustedIndex = Math.min(firstAdjustedIndex, r);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
        lastAdjustedIndex =  Math.max(lastAdjustedIndex, r);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
    // Sets the state at this index and update all relevant state.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
    private void set(int r) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
        if (value.get(r)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
        value.set(r);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
        markAsDirty(r);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
        // Update minimum and maximum indices
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
        minIndex = Math.min(minIndex, r);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
        maxIndex = Math.max(maxIndex, r);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
    // Clears the state at this index and update all relevant state.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
    private void clear(int r) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
        if (!value.get(r)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
        value.clear(r);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
        markAsDirty(r);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
        // Update minimum and maximum indices
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
           If (r > minIndex) the minimum has not changed.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
           The case (r < minIndex) is not possible because r'th value was set.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
           We only need to check for the case when lowest entry has been cleared,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
           and in this case we need to search for the first value set above it.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
        */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
        if (r == minIndex) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
            for(minIndex = minIndex + 1; minIndex <= maxIndex; minIndex++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
                if (value.get(minIndex)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
           If (r < maxIndex) the maximum has not changed.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
           The case (r > maxIndex) is not possible because r'th value was set.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
           We only need to check for the case when highest entry has been cleared,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
           and in this case we need to search for the first value set below it.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
        */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
        if (r == maxIndex) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
            for(maxIndex = maxIndex - 1; minIndex <= maxIndex; maxIndex--) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
                if (value.get(maxIndex)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
        /* Performance note: This method is called from inside a loop in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
           changeSelection() but we will only iterate in the loops
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
           above on the basis of one iteration per deselected cell - in total.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
           Ie. the next time this method is called the work of the previous
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
           deselection will not be repeated.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
           We also don't need to worry about the case when the min and max
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
           values are in their unassigned states. This cannot happen because
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
           this method's initial check ensures that the selection was not empty
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
           and therefore that the minIndex and maxIndex had 'real' values.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
           If we have cleared the whole selection, set the minIndex and maxIndex
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
           to their cannonical values so that the next set command always works
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
           just by using Math.min and Math.max.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
        */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
        if (isSelectionEmpty()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
            minIndex = MAX;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
            maxIndex = MIN;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
     * Sets the value of the leadAnchorNotificationEnabled flag.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   334
     * @see             #isLeadAnchorNotificationEnabled()
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
    public void setLeadAnchorNotificationEnabled(boolean flag) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
        leadAnchorNotificationEnabled = flag;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
     * Returns the value of the <code>leadAnchorNotificationEnabled</code> flag.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   342
     * When <code>leadAnchorNotificationEnabled</code> is true the model
90ce3da70b43 Initial load
duke
parents:
diff changeset
   343
     * generates notification events with bounds that cover all the changes to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
     * the selection plus the changes to the lead and anchor indices.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   345
     * Setting the flag to false causes a narrowing of the event's bounds to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   346
     * include only the elements that have been selected or deselected since
90ce3da70b43 Initial load
duke
parents:
diff changeset
   347
     * the last change. Either way, the model continues to maintain the lead
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
     * and anchor variables internally. The default is true.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   349
     * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
     * Note: It is possible for the lead or anchor to be changed without a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   351
     * change to the selection. Notification of these changes is often
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
     * important, such as when the new lead or anchor needs to be updated in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   353
     * the view. Therefore, caution is urged when changing the default value.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   354
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
     * @return  the value of the <code>leadAnchorNotificationEnabled</code> flag
90ce3da70b43 Initial load
duke
parents:
diff changeset
   356
     * @see             #setLeadAnchorNotificationEnabled(boolean)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   358
    public boolean isLeadAnchorNotificationEnabled() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
        return leadAnchorNotificationEnabled;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   360
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
    private void updateLeadAnchorIndices(int anchorIndex, int leadIndex) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
        if (leadAnchorNotificationEnabled) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
            if (this.anchorIndex != anchorIndex) {
12173
80420757767c 7027139: getFirstIndex() does not return the first index that has changed
rupashka
parents: 5506
diff changeset
   365
                markAsDirty(this.anchorIndex);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
                markAsDirty(anchorIndex);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
            if (this.leadIndex != leadIndex) {
12173
80420757767c 7027139: getFirstIndex() does not return the first index that has changed
rupashka
parents: 5506
diff changeset
   370
                markAsDirty(this.leadIndex);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
                markAsDirty(leadIndex);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   373
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   374
        this.anchorIndex = anchorIndex;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   375
        this.leadIndex = leadIndex;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
    private boolean contains(int a, int b, int i) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
        return (i >= a) && (i <= b);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   380
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   381
90ce3da70b43 Initial load
duke
parents:
diff changeset
   382
    private void changeSelection(int clearMin, int clearMax,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   383
                                 int setMin, int setMax, boolean clearFirst) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   384
        for(int i = Math.min(setMin, clearMin); i <= Math.max(setMax, clearMax); i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
90ce3da70b43 Initial load
duke
parents:
diff changeset
   386
            boolean shouldClear = contains(clearMin, clearMax, i);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   387
            boolean shouldSet = contains(setMin, setMax, i);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   388
90ce3da70b43 Initial load
duke
parents:
diff changeset
   389
            if (shouldSet && shouldClear) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   390
                if (clearFirst) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   391
                    shouldClear = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
                else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   394
                    shouldSet = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   395
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   396
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   397
90ce3da70b43 Initial load
duke
parents:
diff changeset
   398
            if (shouldSet) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   399
                set(i);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   400
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   401
            if (shouldClear) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   402
                clear(i);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   403
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   404
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   405
        fireValueChanged();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   406
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   407
90ce3da70b43 Initial load
duke
parents:
diff changeset
   408
   /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   409
    * Change the selection with the effect of first clearing the values
90ce3da70b43 Initial load
duke
parents:
diff changeset
   410
    * in the inclusive range [clearMin, clearMax] then setting the values
90ce3da70b43 Initial load
duke
parents:
diff changeset
   411
    * in the inclusive range [setMin, setMax]. Do this in one pass so
90ce3da70b43 Initial load
duke
parents:
diff changeset
   412
    * that no values are cleared if they would later be set.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   413
    */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   414
    private void changeSelection(int clearMin, int clearMax, int setMin, int setMax) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   415
        changeSelection(clearMin, clearMax, setMin, setMax, true);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   416
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   417
90ce3da70b43 Initial load
duke
parents:
diff changeset
   418
    /** {@inheritDoc} */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   419
    public void clearSelection() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   420
        removeSelectionIntervalImpl(minIndex, maxIndex, false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   421
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   422
90ce3da70b43 Initial load
duke
parents:
diff changeset
   423
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   424
     * Changes the selection to be between {@code index0} and {@code index1}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   425
     * inclusive. {@code index0} doesn't have to be less than or equal to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   426
     * {@code index1}.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   427
     * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   428
     * In {@code SINGLE_SELECTION} selection mode, only the second index
90ce3da70b43 Initial load
duke
parents:
diff changeset
   429
     * is used.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   430
     * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   431
     * If this represents a change to the current selection, then each
90ce3da70b43 Initial load
duke
parents:
diff changeset
   432
     * {@code ListSelectionListener} is notified of the change.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   433
     * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   434
     * If either index is {@code -1}, this method does nothing and returns
90ce3da70b43 Initial load
duke
parents:
diff changeset
   435
     * without exception. Otherwise, if either index is less than {@code -1},
90ce3da70b43 Initial load
duke
parents:
diff changeset
   436
     * an {@code IndexOutOfBoundsException} is thrown.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   437
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   438
     * @param index0 one end of the interval.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
     * @param index1 other end of the interval
90ce3da70b43 Initial load
duke
parents:
diff changeset
   440
     * @throws IndexOutOfBoundsException if either index is less than {@code -1}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   441
     *         (and neither index is {@code -1})
90ce3da70b43 Initial load
duke
parents:
diff changeset
   442
     * @see #addListSelectionListener
90ce3da70b43 Initial load
duke
parents:
diff changeset
   443
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   444
    public void setSelectionInterval(int index0, int index1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   445
        if (index0 == -1 || index1 == -1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   446
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   447
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   448
90ce3da70b43 Initial load
duke
parents:
diff changeset
   449
        if (getSelectionMode() == SINGLE_SELECTION) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   450
            index0 = index1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   451
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   452
90ce3da70b43 Initial load
duke
parents:
diff changeset
   453
        updateLeadAnchorIndices(index0, index1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   454
90ce3da70b43 Initial load
duke
parents:
diff changeset
   455
        int clearMin = minIndex;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   456
        int clearMax = maxIndex;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   457
        int setMin = Math.min(index0, index1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   458
        int setMax = Math.max(index0, index1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   459
        changeSelection(clearMin, clearMax, setMin, setMax);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   460
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   461
90ce3da70b43 Initial load
duke
parents:
diff changeset
   462
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   463
     * Changes the selection to be the set union of the current selection
90ce3da70b43 Initial load
duke
parents:
diff changeset
   464
     * and the indices between {@code index0} and {@code index1} inclusive.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   465
     * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   466
     * In {@code SINGLE_SELECTION} selection mode, this is equivalent
90ce3da70b43 Initial load
duke
parents:
diff changeset
   467
     * to calling {@code setSelectionInterval}, and only the second index
90ce3da70b43 Initial load
duke
parents:
diff changeset
   468
     * is used. In {@code SINGLE_INTERVAL_SELECTION} selection mode, this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   469
     * method behaves like {@code setSelectionInterval}, unless the given
90ce3da70b43 Initial load
duke
parents:
diff changeset
   470
     * interval is immediately adjacent to or overlaps the existing selection,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   471
     * and can therefore be used to grow it.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   472
     * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   473
     * If this represents a change to the current selection, then each
90ce3da70b43 Initial load
duke
parents:
diff changeset
   474
     * {@code ListSelectionListener} is notified of the change. Note that
90ce3da70b43 Initial load
duke
parents:
diff changeset
   475
     * {@code index0} doesn't have to be less than or equal to {@code index1}.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   476
     * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   477
     * If either index is {@code -1}, this method does nothing and returns
90ce3da70b43 Initial load
duke
parents:
diff changeset
   478
     * without exception. Otherwise, if either index is less than {@code -1},
90ce3da70b43 Initial load
duke
parents:
diff changeset
   479
     * an {@code IndexOutOfBoundsException} is thrown.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   480
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   481
     * @param index0 one end of the interval.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   482
     * @param index1 other end of the interval
90ce3da70b43 Initial load
duke
parents:
diff changeset
   483
     * @throws IndexOutOfBoundsException if either index is less than {@code -1}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   484
     *         (and neither index is {@code -1})
90ce3da70b43 Initial load
duke
parents:
diff changeset
   485
     * @see #addListSelectionListener
90ce3da70b43 Initial load
duke
parents:
diff changeset
   486
     * @see #setSelectionInterval
90ce3da70b43 Initial load
duke
parents:
diff changeset
   487
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   488
    public void addSelectionInterval(int index0, int index1)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   489
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   490
        if (index0 == -1 || index1 == -1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   491
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   492
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   493
90ce3da70b43 Initial load
duke
parents:
diff changeset
   494
        // If we only allow a single selection, channel through
90ce3da70b43 Initial load
duke
parents:
diff changeset
   495
        // setSelectionInterval() to enforce the rule.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   496
        if (getSelectionMode() == SINGLE_SELECTION) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   497
            setSelectionInterval(index0, index1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   498
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   499
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   500
90ce3da70b43 Initial load
duke
parents:
diff changeset
   501
        updateLeadAnchorIndices(index0, index1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   502
90ce3da70b43 Initial load
duke
parents:
diff changeset
   503
        int clearMin = MAX;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   504
        int clearMax = MIN;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   505
        int setMin = Math.min(index0, index1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   506
        int setMax = Math.max(index0, index1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   507
90ce3da70b43 Initial load
duke
parents:
diff changeset
   508
        // If we only allow a single interval and this would result
90ce3da70b43 Initial load
duke
parents:
diff changeset
   509
        // in multiple intervals, then set the selection to be just
90ce3da70b43 Initial load
duke
parents:
diff changeset
   510
        // the new range.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   511
        if (getSelectionMode() == SINGLE_INTERVAL_SELECTION &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   512
                (setMax < minIndex - 1 || setMin > maxIndex + 1)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   513
90ce3da70b43 Initial load
duke
parents:
diff changeset
   514
            setSelectionInterval(index0, index1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   515
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   516
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   517
90ce3da70b43 Initial load
duke
parents:
diff changeset
   518
        changeSelection(clearMin, clearMax, setMin, setMax);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   519
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   520
90ce3da70b43 Initial load
duke
parents:
diff changeset
   521
90ce3da70b43 Initial load
duke
parents:
diff changeset
   522
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   523
     * Changes the selection to be the set difference of the current selection
90ce3da70b43 Initial load
duke
parents:
diff changeset
   524
     * and the indices between {@code index0} and {@code index1} inclusive.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   525
     * {@code index0} doesn't have to be less than or equal to {@code index1}.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   526
     * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   527
     * In {@code SINGLE_INTERVAL_SELECTION} selection mode, if the removal
90ce3da70b43 Initial load
duke
parents:
diff changeset
   528
     * would produce two disjoint selections, the removal is extended through
90ce3da70b43 Initial load
duke
parents:
diff changeset
   529
     * the greater end of the selection. For example, if the selection is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   530
     * {@code 0-10} and you supply indices {@code 5,6} (in any order) the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   531
     * resulting selection is {@code 0-4}.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   532
     * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   533
     * If this represents a change to the current selection, then each
90ce3da70b43 Initial load
duke
parents:
diff changeset
   534
     * {@code ListSelectionListener} is notified of the change.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   535
     * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   536
     * If either index is {@code -1}, this method does nothing and returns
90ce3da70b43 Initial load
duke
parents:
diff changeset
   537
     * without exception. Otherwise, if either index is less than {@code -1},
90ce3da70b43 Initial load
duke
parents:
diff changeset
   538
     * an {@code IndexOutOfBoundsException} is thrown.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   539
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   540
     * @param index0 one end of the interval
90ce3da70b43 Initial load
duke
parents:
diff changeset
   541
     * @param index1 other end of the interval
90ce3da70b43 Initial load
duke
parents:
diff changeset
   542
     * @throws IndexOutOfBoundsException if either index is less than {@code -1}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   543
     *         (and neither index is {@code -1})
90ce3da70b43 Initial load
duke
parents:
diff changeset
   544
     * @see #addListSelectionListener
90ce3da70b43 Initial load
duke
parents:
diff changeset
   545
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   546
    public void removeSelectionInterval(int index0, int index1)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   547
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   548
        removeSelectionIntervalImpl(index0, index1, true);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   549
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   550
90ce3da70b43 Initial load
duke
parents:
diff changeset
   551
    // private implementation allowing the selection interval
90ce3da70b43 Initial load
duke
parents:
diff changeset
   552
    // to be removed without affecting the lead and anchor
90ce3da70b43 Initial load
duke
parents:
diff changeset
   553
    private void removeSelectionIntervalImpl(int index0, int index1,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   554
                                             boolean changeLeadAnchor) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   555
90ce3da70b43 Initial load
duke
parents:
diff changeset
   556
        if (index0 == -1 || index1 == -1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   557
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   558
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   559
90ce3da70b43 Initial load
duke
parents:
diff changeset
   560
        if (changeLeadAnchor) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   561
            updateLeadAnchorIndices(index0, index1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   562
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   563
90ce3da70b43 Initial load
duke
parents:
diff changeset
   564
        int clearMin = Math.min(index0, index1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   565
        int clearMax = Math.max(index0, index1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   566
        int setMin = MAX;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   567
        int setMax = MIN;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   568
90ce3da70b43 Initial load
duke
parents:
diff changeset
   569
        // If the removal would produce to two disjoint selections in a mode
90ce3da70b43 Initial load
duke
parents:
diff changeset
   570
        // that only allows one, extend the removal to the end of the selection.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   571
        if (getSelectionMode() != MULTIPLE_INTERVAL_SELECTION &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   572
               clearMin > minIndex && clearMax < maxIndex) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   573
            clearMax = maxIndex;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   574
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   575
90ce3da70b43 Initial load
duke
parents:
diff changeset
   576
        changeSelection(clearMin, clearMax, setMin, setMax);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   577
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   578
90ce3da70b43 Initial load
duke
parents:
diff changeset
   579
    private void setState(int index, boolean state) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   580
        if (state) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   581
            set(index);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   582
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   583
        else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   584
            clear(index);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   585
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   586
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   587
90ce3da70b43 Initial load
duke
parents:
diff changeset
   588
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   589
     * Insert length indices beginning before/after index. If the value
90ce3da70b43 Initial load
duke
parents:
diff changeset
   590
     * at index is itself selected and the selection mode is not
90ce3da70b43 Initial load
duke
parents:
diff changeset
   591
     * SINGLE_SELECTION, set all of the newly inserted items as selected.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   592
     * Otherwise leave them unselected. This method is typically
90ce3da70b43 Initial load
duke
parents:
diff changeset
   593
     * called to sync the selection model with a corresponding change
90ce3da70b43 Initial load
duke
parents:
diff changeset
   594
     * in the data model.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   595
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   596
    public void insertIndexInterval(int index, int length, boolean before)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   597
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   598
        /* The first new index will appear at insMinIndex and the last
90ce3da70b43 Initial load
duke
parents:
diff changeset
   599
         * one will appear at insMaxIndex
90ce3da70b43 Initial load
duke
parents:
diff changeset
   600
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   601
        int insMinIndex = (before) ? index : index + 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   602
        int insMaxIndex = (insMinIndex + length) - 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   603
90ce3da70b43 Initial load
duke
parents:
diff changeset
   604
        /* Right shift the entire bitset by length, beginning with
90ce3da70b43 Initial load
duke
parents:
diff changeset
   605
         * index-1 if before is true, index+1 if it's false (i.e. with
90ce3da70b43 Initial load
duke
parents:
diff changeset
   606
         * insMinIndex).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   607
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   608
        for(int i = maxIndex; i >= insMinIndex; i--) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   609
            setState(i + length, value.get(i));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   610
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   611
90ce3da70b43 Initial load
duke
parents:
diff changeset
   612
        /* Initialize the newly inserted indices.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   613
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   614
        boolean setInsertedValues = ((getSelectionMode() == SINGLE_SELECTION) ?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   615
                                        false : value.get(index));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   616
        for(int i = insMinIndex; i <= insMaxIndex; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   617
            setState(i, setInsertedValues);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   618
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   619
90ce3da70b43 Initial load
duke
parents:
diff changeset
   620
        int leadIndex = this.leadIndex;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   621
        if (leadIndex > index || (before && leadIndex == index)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   622
            leadIndex = this.leadIndex + length;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   623
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   624
        int anchorIndex = this.anchorIndex;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   625
        if (anchorIndex > index || (before && anchorIndex == index)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   626
            anchorIndex = this.anchorIndex + length;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   627
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   628
        if (leadIndex != this.leadIndex || anchorIndex != this.anchorIndex) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   629
            updateLeadAnchorIndices(anchorIndex, leadIndex);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   630
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   631
90ce3da70b43 Initial load
duke
parents:
diff changeset
   632
        fireValueChanged();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   633
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   634
90ce3da70b43 Initial load
duke
parents:
diff changeset
   635
90ce3da70b43 Initial load
duke
parents:
diff changeset
   636
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   637
     * Remove the indices in the interval index0,index1 (inclusive) from
90ce3da70b43 Initial load
duke
parents:
diff changeset
   638
     * the selection model.  This is typically called to sync the selection
90ce3da70b43 Initial load
duke
parents:
diff changeset
   639
     * model width a corresponding change in the data model.  Note
90ce3da70b43 Initial load
duke
parents:
diff changeset
   640
     * that (as always) index0 need not be <= index1.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   641
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   642
    public void removeIndexInterval(int index0, int index1)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   643
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   644
        int rmMinIndex = Math.min(index0, index1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   645
        int rmMaxIndex = Math.max(index0, index1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   646
        int gapLength = (rmMaxIndex - rmMinIndex) + 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   647
90ce3da70b43 Initial load
duke
parents:
diff changeset
   648
        /* Shift the entire bitset to the left to close the index0, index1
90ce3da70b43 Initial load
duke
parents:
diff changeset
   649
         * gap.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   650
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   651
        for(int i = rmMinIndex; i <= maxIndex; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   652
            setState(i, value.get(i + gapLength));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   653
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   654
90ce3da70b43 Initial load
duke
parents:
diff changeset
   655
        int leadIndex = this.leadIndex;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   656
        if (leadIndex == 0 && rmMinIndex == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   657
            // do nothing
90ce3da70b43 Initial load
duke
parents:
diff changeset
   658
        } else if (leadIndex > rmMaxIndex) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   659
            leadIndex = this.leadIndex - gapLength;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   660
        } else if (leadIndex >= rmMinIndex) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   661
            leadIndex = rmMinIndex - 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   662
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   663
90ce3da70b43 Initial load
duke
parents:
diff changeset
   664
        int anchorIndex = this.anchorIndex;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   665
        if (anchorIndex == 0 && rmMinIndex == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   666
            // do nothing
90ce3da70b43 Initial load
duke
parents:
diff changeset
   667
        } else if (anchorIndex > rmMaxIndex) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   668
            anchorIndex = this.anchorIndex - gapLength;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   669
        } else if (anchorIndex >= rmMinIndex) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   670
            anchorIndex = rmMinIndex - 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   671
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   672
90ce3da70b43 Initial load
duke
parents:
diff changeset
   673
        if (leadIndex != this.leadIndex || anchorIndex != this.anchorIndex) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   674
            updateLeadAnchorIndices(anchorIndex, leadIndex);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   675
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   676
90ce3da70b43 Initial load
duke
parents:
diff changeset
   677
        fireValueChanged();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   678
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   679
90ce3da70b43 Initial load
duke
parents:
diff changeset
   680
90ce3da70b43 Initial load
duke
parents:
diff changeset
   681
    /** {@inheritDoc} */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   682
    public void setValueIsAdjusting(boolean isAdjusting) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   683
        if (isAdjusting != this.isAdjusting) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   684
            this.isAdjusting = isAdjusting;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   685
            this.fireValueChanged(isAdjusting);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   686
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   687
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   688
90ce3da70b43 Initial load
duke
parents:
diff changeset
   689
90ce3da70b43 Initial load
duke
parents:
diff changeset
   690
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   691
     * Returns a string that displays and identifies this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   692
     * object's properties.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   693
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   694
     * @return a <code>String</code> representation of this object
90ce3da70b43 Initial load
duke
parents:
diff changeset
   695
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   696
    public String toString() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   697
        String s =  ((getValueIsAdjusting()) ? "~" : "=") + value.toString();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   698
        return getClass().getName() + " " + Integer.toString(hashCode()) + " " + s;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   699
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   700
90ce3da70b43 Initial load
duke
parents:
diff changeset
   701
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   702
     * Returns a clone of this selection model with the same selection.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   703
     * <code>listenerLists</code> are not duplicated.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   704
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   705
     * @exception CloneNotSupportedException if the selection model does not
90ce3da70b43 Initial load
duke
parents:
diff changeset
   706
     *    both (a) implement the Cloneable interface and (b) define a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   707
     *    <code>clone</code> method.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   708
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   709
    public Object clone() throws CloneNotSupportedException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   710
        DefaultListSelectionModel clone = (DefaultListSelectionModel)super.clone();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   711
        clone.value = (BitSet)value.clone();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   712
        clone.listenerList = new EventListenerList();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   713
        return clone;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   714
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   715
90ce3da70b43 Initial load
duke
parents:
diff changeset
   716
    /** {@inheritDoc} */
466
6acd5ec503a8 4935607: RFE: LTP: Should be possible to set the TRANSIENT attribute of propertiies to FALSE
malenkov
parents: 2
diff changeset
   717
    @Transient
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   718
    public int getAnchorSelectionIndex() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   719
        return anchorIndex;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   720
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   721
90ce3da70b43 Initial load
duke
parents:
diff changeset
   722
    /** {@inheritDoc} */
466
6acd5ec503a8 4935607: RFE: LTP: Should be possible to set the TRANSIENT attribute of propertiies to FALSE
malenkov
parents: 2
diff changeset
   723
    @Transient
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   724
    public int getLeadSelectionIndex() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   725
        return leadIndex;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   726
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   727
90ce3da70b43 Initial load
duke
parents:
diff changeset
   728
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   729
     * Set the anchor selection index, leaving all selection values unchanged.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   730
     * If leadAnchorNotificationEnabled is true, send a notification covering
90ce3da70b43 Initial load
duke
parents:
diff changeset
   731
     * the old and new anchor cells.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   732
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   733
     * @see #getAnchorSelectionIndex
90ce3da70b43 Initial load
duke
parents:
diff changeset
   734
     * @see #setLeadSelectionIndex
90ce3da70b43 Initial load
duke
parents:
diff changeset
   735
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   736
    public void setAnchorSelectionIndex(int anchorIndex) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   737
        updateLeadAnchorIndices(anchorIndex, this.leadIndex);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   738
        fireValueChanged();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   739
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   740
90ce3da70b43 Initial load
duke
parents:
diff changeset
   741
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   742
     * Set the lead selection index, leaving all selection values unchanged.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   743
     * If leadAnchorNotificationEnabled is true, send a notification covering
90ce3da70b43 Initial load
duke
parents:
diff changeset
   744
     * the old and new lead cells.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   745
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   746
     * @param leadIndex the new lead selection index
90ce3da70b43 Initial load
duke
parents:
diff changeset
   747
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   748
     * @see #setAnchorSelectionIndex
90ce3da70b43 Initial load
duke
parents:
diff changeset
   749
     * @see #setLeadSelectionIndex
90ce3da70b43 Initial load
duke
parents:
diff changeset
   750
     * @see #getLeadSelectionIndex
90ce3da70b43 Initial load
duke
parents:
diff changeset
   751
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   752
     * @since 1.5
90ce3da70b43 Initial load
duke
parents:
diff changeset
   753
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   754
    public void moveLeadSelectionIndex(int leadIndex) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   755
        // disallow a -1 lead unless the anchor is already -1
90ce3da70b43 Initial load
duke
parents:
diff changeset
   756
        if (leadIndex == -1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   757
            if (this.anchorIndex != -1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   758
                return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   759
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   760
90ce3da70b43 Initial load
duke
parents:
diff changeset
   761
/* PENDING(shannonh) - The following check is nice, to be consistent with
90ce3da70b43 Initial load
duke
parents:
diff changeset
   762
                       setLeadSelectionIndex. However, it is not absolutely
90ce3da70b43 Initial load
duke
parents:
diff changeset
   763
                       necessary: One could work around it by setting the anchor
90ce3da70b43 Initial load
duke
parents:
diff changeset
   764
                       to something valid, modifying the lead, and then moving
90ce3da70b43 Initial load
duke
parents:
diff changeset
   765
                       the anchor back to -1. For this reason, there's no sense
90ce3da70b43 Initial load
duke
parents:
diff changeset
   766
                       in adding it at this time, as that would require
90ce3da70b43 Initial load
duke
parents:
diff changeset
   767
                       updating the spec and officially committing to it.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   768
90ce3da70b43 Initial load
duke
parents:
diff changeset
   769
        // otherwise, don't do anything if the anchor is -1
90ce3da70b43 Initial load
duke
parents:
diff changeset
   770
        } else if (this.anchorIndex == -1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   771
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   772
*/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   773
90ce3da70b43 Initial load
duke
parents:
diff changeset
   774
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   775
90ce3da70b43 Initial load
duke
parents:
diff changeset
   776
        updateLeadAnchorIndices(this.anchorIndex, leadIndex);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   777
        fireValueChanged();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   778
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   779
90ce3da70b43 Initial load
duke
parents:
diff changeset
   780
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   781
     * Sets the lead selection index, ensuring that values between the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   782
     * anchor and the new lead are either all selected or all deselected.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   783
     * If the value at the anchor index is selected, first clear all the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   784
     * values in the range [anchor, oldLeadIndex], then select all the values
90ce3da70b43 Initial load
duke
parents:
diff changeset
   785
     * values in the range [anchor, newLeadIndex], where oldLeadIndex is the old
90ce3da70b43 Initial load
duke
parents:
diff changeset
   786
     * leadIndex and newLeadIndex is the new one.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   787
     * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   788
     * If the value at the anchor index is not selected, do the same thing in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   789
     * reverse selecting values in the old range and deslecting values in the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   790
     * new one.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   791
     * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   792
     * Generate a single event for this change and notify all listeners.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   793
     * For the purposes of generating minimal bounds in this event, do the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   794
     * operation in a single pass; that way the first and last index inside the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   795
     * ListSelectionEvent that is broadcast will refer to cells that actually
90ce3da70b43 Initial load
duke
parents:
diff changeset
   796
     * changed value because of this method. If, instead, this operation were
90ce3da70b43 Initial load
duke
parents:
diff changeset
   797
     * done in two steps the effect on the selection state would be the same
90ce3da70b43 Initial load
duke
parents:
diff changeset
   798
     * but two events would be generated and the bounds around the changed
90ce3da70b43 Initial load
duke
parents:
diff changeset
   799
     * values would be wider, including cells that had been first cleared only
90ce3da70b43 Initial load
duke
parents:
diff changeset
   800
     * to later be set.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   801
     * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   802
     * This method can be used in the <code>mouseDragged</code> method
90ce3da70b43 Initial load
duke
parents:
diff changeset
   803
     * of a UI class to extend a selection.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   804
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   805
     * @see #getLeadSelectionIndex
90ce3da70b43 Initial load
duke
parents:
diff changeset
   806
     * @see #setAnchorSelectionIndex
90ce3da70b43 Initial load
duke
parents:
diff changeset
   807
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   808
    public void setLeadSelectionIndex(int leadIndex) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   809
        int anchorIndex = this.anchorIndex;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   810
90ce3da70b43 Initial load
duke
parents:
diff changeset
   811
        // only allow a -1 lead if the anchor is already -1
90ce3da70b43 Initial load
duke
parents:
diff changeset
   812
        if (leadIndex == -1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   813
            if (anchorIndex == -1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   814
                updateLeadAnchorIndices(anchorIndex, leadIndex);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   815
                fireValueChanged();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   816
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   817
90ce3da70b43 Initial load
duke
parents:
diff changeset
   818
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   819
        // otherwise, don't do anything if the anchor is -1
90ce3da70b43 Initial load
duke
parents:
diff changeset
   820
        } else if (anchorIndex == -1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   821
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   822
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   823
90ce3da70b43 Initial load
duke
parents:
diff changeset
   824
        if (this.leadIndex == -1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   825
            this.leadIndex = leadIndex;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   826
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   827
90ce3da70b43 Initial load
duke
parents:
diff changeset
   828
        boolean shouldSelect = value.get(this.anchorIndex);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   829
90ce3da70b43 Initial load
duke
parents:
diff changeset
   830
        if (getSelectionMode() == SINGLE_SELECTION) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   831
            anchorIndex = leadIndex;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   832
            shouldSelect = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   833
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   834
90ce3da70b43 Initial load
duke
parents:
diff changeset
   835
        int oldMin = Math.min(this.anchorIndex, this.leadIndex);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   836
        int oldMax = Math.max(this.anchorIndex, this.leadIndex);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   837
        int newMin = Math.min(anchorIndex, leadIndex);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   838
        int newMax = Math.max(anchorIndex, leadIndex);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   839
90ce3da70b43 Initial load
duke
parents:
diff changeset
   840
        updateLeadAnchorIndices(anchorIndex, leadIndex);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   841
90ce3da70b43 Initial load
duke
parents:
diff changeset
   842
        if (shouldSelect) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   843
            changeSelection(oldMin, oldMax, newMin, newMax);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   844
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   845
        else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   846
            changeSelection(newMin, newMax, oldMin, oldMax, false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   847
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   848
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   849
}