diff options
author | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
---|---|---|
committer | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
commit | 554fd8c5195424bdbcabf5de30fdc183aba391bd (patch) | |
tree | 976dc5ab7fddf506dadce60ae936f43f58787092 /libjava/classpath/javax/swing/DefaultListSelectionModel.java | |
download | cbb-gcc-4.6.4-upstream.tar.bz2 cbb-gcc-4.6.4-upstream.tar.xz |
obtained gcc-4.6.4.tar.bz2 from upstream website;upstream
verified gcc-4.6.4.tar.bz2.sig;
imported gcc-4.6.4 source tree from verified upstream tarball.
downloading a git-generated archive based on the 'upstream' tag
should provide you with a source tree that is binary identical
to the one extracted from the above tarball.
if you have obtained the source via the command 'git clone',
however, do note that line-endings of files in your working
directory might differ from line-endings of the respective
files in the upstream repository.
Diffstat (limited to 'libjava/classpath/javax/swing/DefaultListSelectionModel.java')
-rw-r--r-- | libjava/classpath/javax/swing/DefaultListSelectionModel.java | 855 |
1 files changed, 855 insertions, 0 deletions
diff --git a/libjava/classpath/javax/swing/DefaultListSelectionModel.java b/libjava/classpath/javax/swing/DefaultListSelectionModel.java new file mode 100644 index 000000000..273ca0d15 --- /dev/null +++ b/libjava/classpath/javax/swing/DefaultListSelectionModel.java @@ -0,0 +1,855 @@ +/* DefaultListSelectionModel.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing; + +import java.io.Serializable; +import java.util.BitSet; +import java.util.EventListener; + +import javax.swing.event.EventListenerList; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; + +/** + * The default implementation of {@link ListSelectionModel}, + * which is used by {@link javax.swing.JList} and + * similar classes to manage the selection status of a number of data + * elements. + * + * <p>The class is organized <em>abstractly</em> as a set of intervals of + * integers. Each interval indicates an inclusive range of indices in a + * list -- held by some other object and unknown to this class -- which is + * considered "selected". There are various accessors for querying and + * modifying the set of intervals, with simplified forms accepting a single + * index, representing an interval with only one element. </p> + */ +public class DefaultListSelectionModel implements Cloneable, + ListSelectionModel, + Serializable +{ + private static final long serialVersionUID = -5718799865110415860L; + + /** The list of ListSelectionListeners subscribed to this selection model. */ + protected EventListenerList listenerList = new EventListenerList(); + + + /** + * The current list selection mode. Must be one of the numeric constants + * <code>SINGLE_SELECTION</code>, <code>SINGLE_INTERVAL_SELECTION</code> + * or <code>MULTIPLE_INTERVAL_SELECTION</code> from {@link + * ListSelectionModel}. The default value is + * <code>MULTIPLE_INTERVAL_SELECTION</code>. + */ + int selectionMode = MULTIPLE_INTERVAL_SELECTION; + + /** + * The index of the "lead" of the most recent selection. The lead is the + * second argument in any call to {@link #setSelectionInterval}, {@link + * #addSelectionInterval} or {@link #removeSelectionInterval}. Generally + * the lead refers to the most recent position a user dragged their mouse + * over. + */ + int leadSelectionIndex = -1; + + /** + * The index of the "anchor" of the most recent selection. The anchor is + * the first argument in any call to {@link #setSelectionInterval}, + * {@link #addSelectionInterval} or {@link + * #removeSelectionInterval}. Generally the anchor refers to the first + * recent position a user clicks when they begin to drag their mouse over + * a list. + * + * @see #getAnchorSelectionIndex + * @see #setAnchorSelectionIndex + */ + int anchorSelectionIndex = -1; + + /** + * controls the range of indices provided in any {@link + * ListSelectionEvent} fired by the selectionModel. Let + * <code>[A,L]</code> be the range of indices between {@link + * #anchorSelectionIndex} and {@link #leadSelectionIndex} inclusive, and + * let <code>[i0,i1]</code> be the range of indices changed in a given + * call which generates a {@link ListSelectionEvent}. Then when this + * property is <code>true</code>, the {@link ListSelectionEvent} contains + * the range <code>[A,L] union [i0,i1]</code>; when <code>false</code> it + * will contain only <code>[i0,i1]</code>. The default is + * <code>true</code>. + * + * @see #isLeadAnchorNotificationEnabled + * @see #setLeadAnchorNotificationEnabled + */ + protected boolean leadAnchorNotificationEnabled = true; + + /** + * Whether the selection is currently "adjusting". Any {@link + * ListSelectionEvent} events constructed in response to changes in this + * list selection model will have their {@link + * ListSelectionEvent#isAdjusting} field set to this value. + * + * @see #getValueIsAdjusting + * @see #setValueIsAdjusting + */ + boolean valueIsAdjusting = false; + + + /** + * The current set of "intervals", represented simply by a {@link + * java.util.BitSet}. A set bit indicates a selected index, whereas a + * cleared bit indicates a non-selected index. + */ + BitSet sel = new BitSet(); + + /** + * A variable to store the previous value of sel. + * Used to make sure we only fireValueChanged when the BitSet + * actually does change. + */ + Object oldSel; + + /** + * Whether this call of setLeadSelectionInterval was called locally + * from addSelectionInterval + */ + boolean setLeadCalledFromAdd = false; + + /** + * Returns the selection mode, which is one of {@link #SINGLE_SELECTION}, + * {@link #SINGLE_INTERVAL_SELECTION} and + * {@link #MULTIPLE_INTERVAL_SELECTION}. The default value is + * {@link #MULTIPLE_INTERVAL_SELECTION}. + * + * @return The selection mode. + * + * @see #setSelectionMode(int) + */ + public int getSelectionMode() + { + return selectionMode; + } + + /** + * Sets the value of the {@link #selectionMode} property. + * + * @param mode The new value of the property + */ + public void setSelectionMode(int mode) + { + if (mode < ListSelectionModel.SINGLE_SELECTION + || mode > ListSelectionModel.MULTIPLE_INTERVAL_SELECTION) + throw new IllegalArgumentException("Unrecognised mode: " + mode); + selectionMode = mode; + } + + /** + * Gets the value of the {@link #anchorSelectionIndex} property. + * + * @return The current property value + * + * @see #setAnchorSelectionIndex + */ + public int getAnchorSelectionIndex() + { + return anchorSelectionIndex; + } + + /** + * Sets the value of the {@link #anchorSelectionIndex} property. + * + * @param index The new property value + * + * @see #getAnchorSelectionIndex + */ + public void setAnchorSelectionIndex(int index) + { + if (anchorSelectionIndex != index) + { + int old = anchorSelectionIndex; + anchorSelectionIndex = index; + if (leadAnchorNotificationEnabled) + fireValueChanged(index, old); + } + } + + /** + * Gets the value of the {@link #leadSelectionIndex} property. + * + * @return The current property value + * + * @see #setLeadSelectionIndex + */ + public int getLeadSelectionIndex() + { + return leadSelectionIndex; + } + + /** + * <p>Sets the value of the {@link #anchorSelectionIndex} property. As a + * side effect, alters the selection status of two ranges of indices. Let + * <code>OL</code> be the old lead selection index, <code>NL</code> be + * the new lead selection index, and <code>A</code> be the anchor + * selection index. Then if <code>A</code> is a valid selection index, + * one of two things happens depending on the seleciton status of + * <code>A</code>:</p> + * + * <ul> + * + * <li><code>isSelectedIndex(A) == true</code>: set <code>[A,OL]</code> + * to <em>deselected</em>, then set <code>[A,NL]</code> to + * <em>selected</em>.</li> + * + * <li><code>isSelectedIndex(A) == false</code>: set <code>[A,OL]</code> + * to <em>selected</em>, then set <code>[A,NL]</code> to + * <em>deselected</em>.</li> + * + * </ul> + * + * <p>This method generates at most a single {@link ListSelectionEvent} + * despite changing multiple ranges. The range of values provided to the + * {@link ListSelectionEvent} includes only the minimum range of values + * which changed selection status between the beginning and end of the + * method.</p> + * + * @param leadIndex The new property value + * + * @see #getAnchorSelectionIndex + */ + public void setLeadSelectionIndex(int leadIndex) + { + // Only set the lead selection index to < 0 if anchorSelectionIndex < 0. + if (leadIndex < 0) + { + if (anchorSelectionIndex < 0) + leadSelectionIndex = -1; + else + return; + } + + // Only touch the lead selection index if the anchor is >= 0. + if (anchorSelectionIndex < 0) + return; + + if (selectionMode == SINGLE_SELECTION) + setSelectionInterval (leadIndex, leadIndex); + + int oldLeadIndex = leadSelectionIndex; + if (oldLeadIndex == -1) + oldLeadIndex = leadIndex; + if (setLeadCalledFromAdd == false) + oldSel = sel.clone(); + leadSelectionIndex = leadIndex; + + if (anchorSelectionIndex == -1) + return; + + int R1 = Math.min(anchorSelectionIndex, oldLeadIndex); + int R2 = Math.max(anchorSelectionIndex, oldLeadIndex); + int S1 = Math.min(anchorSelectionIndex, leadIndex); + int S2 = Math.max(anchorSelectionIndex, leadIndex); + + int lo = Math.min(R1, S1); + int hi = Math.max(R2, S2); + + if (isSelectedIndex(anchorSelectionIndex)) + { + sel.clear(R1, R2+1); + sel.set(S1, S2+1); + } + else + { + sel.set(R1, R2+1); + sel.clear(S1, S2+1); + } + + int beg = sel.nextSetBit(0), end = -1; + for(int i=beg; i >= 0; i=sel.nextSetBit(i+1)) + end = i; + + BitSet old = (BitSet) oldSel; + + // The new and previous lead location requires repainting. + old.set(oldLeadIndex, !sel.get(oldLeadIndex)); + old.set(leadSelectionIndex, !sel.get(leadSelectionIndex)); + + fireDifference(sel, old); + } + + /** + * Moves the lead selection index to <code>leadIndex</code> without + * changing the selection values. + * + * If leadAnchorNotificationEnabled is true, send a notification covering the + * old and new lead cells. + * + * @param leadIndex the new lead selection index + * @since 1.5 + */ + public void moveLeadSelectionIndex (int leadIndex) + { + if (leadSelectionIndex == leadIndex) + return; + + leadSelectionIndex = leadIndex; + if (isLeadAnchorNotificationEnabled()) + fireValueChanged(Math.min(leadSelectionIndex, leadIndex), + Math.max(leadSelectionIndex, leadIndex)); + } + + /** + * Gets the value of the {@link #leadAnchorNotificationEnabled} property. + * + * @return The current property value + * + * @see #setLeadAnchorNotificationEnabled + */ + public boolean isLeadAnchorNotificationEnabled() + { + return leadAnchorNotificationEnabled; + } + + /** + * Sets the value of the {@link #leadAnchorNotificationEnabled} property. + * + * @param l The new property value + * + * @see #isLeadAnchorNotificationEnabled + */ + public void setLeadAnchorNotificationEnabled(boolean l) + { + leadAnchorNotificationEnabled = l; + } + + /** + * Gets the value of the {@link #valueIsAdjusting} property. + * + * @return The current property value + * + * @see #setValueIsAdjusting + */ + public boolean getValueIsAdjusting() + { + return valueIsAdjusting; + } + + /** + * Sets the value of the {@link #valueIsAdjusting} property. + * + * @param v The new property value + * + * @see #getValueIsAdjusting + */ + public void setValueIsAdjusting(boolean v) + { + valueIsAdjusting = v; + } + + /** + * Determines whether the selection is empty. + * + * @return <code>true</code> if the selection is empty, otherwise + * <code>false</code> + */ + public boolean isSelectionEmpty() + { + return sel.isEmpty(); + } + + /** + * Gets the smallest index which is currently a member of a selection + * interval. + * + * @return The least integer <code>i</code> such that <code>i >= + * 0</code> and <code>i</code> is a member of a selected interval, or + * <code>-1</code> if there are no selected intervals + * + * @see #getMaxSelectionIndex + */ + public int getMinSelectionIndex() + { + if (isSelectionEmpty()) + return -1; + + return sel.nextSetBit(0); + } + + /** + * Gets the largest index which is currently a member of a selection + * interval. + * + * @return The greatest integer <code>i</code> such that <code>i >= + * 0</code> and <code>i</code> is a member of a selected interval, or + * <code>-1</code> if there are no selected intervals + * + * @see #getMinSelectionIndex + */ + public int getMaxSelectionIndex() + { + if (isSelectionEmpty()) + return -1; + + int mx = -1; + for(int i=sel.nextSetBit(0); i >= 0; i=sel.nextSetBit(i+1)) + { + mx = i; + } + return mx; + } + + /** + * Determines whether a particular index is a member of a selection + * interval. + * + * @param a The index to search for + * + * @return <code>true</code> if the index is a member of a selection interval, + * otherwise <code>false</code> + */ + public boolean isSelectedIndex(int a) + { + // TODO: Probably throw an exception here? + if (a >= sel.length() || a < 0) + return false; + return sel.get(a); + } + + /** + * If the {@link #selectionMode} property is equal to + * <code>SINGLE_SELECTION</code> equivalent to calling + * <code>setSelectionInterval(index1, index2)</code>; + * If the {@link #selectionMode} property is equal to + * <code>SINGLE_INTERVAL_SELECTION</code> and the interval being + * added is not adjacent to an already selected interval, + * equivalent to <code>setSelectionInterval(index1, index2)</code>. + * Otherwise adds the range <code>[index0, index1]</code> + * to the selection interval set. + * + * @param index0 The beginning of the range of indices to select + * @param index1 The end of the range of indices to select + * + * @see #setSelectionInterval + * @see #removeSelectionInterval + */ + public void addSelectionInterval(int index0, int index1) + { + if (index0 == -1 || index1 == -1) + return; + + if (selectionMode == SINGLE_SELECTION) + setSelectionInterval(index0, index1); + else + { + int lo = Math.min(index0, index1); + int hi = Math.max(index0, index1); + oldSel = sel.clone(); + + + // COMPAT: Like Sun (but not like IBM), we allow calls to + // addSelectionInterval when selectionMode is + // SINGLE_SELECTION_INTERVAL iff the interval being added + // is adjacent to an already selected interval + if (selectionMode == SINGLE_INTERVAL_SELECTION) + if (!(isSelectedIndex(index0) || + isSelectedIndex(index1) || + isSelectedIndex(Math.max(lo-1,0)) || + isSelectedIndex(Math.min(hi+1,sel.size())))) + sel.clear(); + + // We have to update the anchorSelectionIndex and leadSelectionIndex + // variables + + // The next if statements breaks down to "if this selection is adjacent + // to the previous selection and going in the same direction" + if ((isSelectedIndex(leadSelectionIndex)) + && ((index0 - 1 == leadSelectionIndex + && (index1 >= index0) + && (leadSelectionIndex >= anchorSelectionIndex)) + || (index0 + 1 == leadSelectionIndex && (index1 <= index0) + && (leadSelectionIndex <= anchorSelectionIndex))) + && (anchorSelectionIndex != -1 || leadSelectionIndex != -1)) + { + // setting setLeadCalledFromAdd to true tells setLeadSelectionIndex + // not to update oldSel + setLeadCalledFromAdd = true; + setLeadSelectionIndex(index1); + setLeadCalledFromAdd = false; + } + else + { + leadSelectionIndex = index1; + anchorSelectionIndex = index0; + sel.set(lo, hi+1); + fireDifference(sel, (BitSet) oldSel); + } + } + } + + + /** + * Deselects all indices in the inclusive range + * <code>[index0,index1]</code>. + * + * @param index0 The beginning of the range of indices to deselect + * @param index1 The end of the range of indices to deselect + * + * @see #addSelectionInterval + * @see #setSelectionInterval + */ + public void removeSelectionInterval(int index0, + int index1) + { + if (index0 == -1 || index1 == -1) + return; + + oldSel = sel.clone(); + int lo = Math.min(index0, index1); + int hi = Math.max(index0, index1); + + // if selectionMode is SINGLE_INTERVAL_SELECTION and removing the interval + // (index0,index1) would leave two disjoint selection intervals, remove all + // selected indices from lo to the last selected index + if (getMinSelectionIndex() > 0 && getMinSelectionIndex() < lo && + selectionMode == SINGLE_INTERVAL_SELECTION) + hi = sel.size() - 1; + + sel.clear(lo, hi+1); + //update anchorSelectionIndex and leadSelectionIndex variables + //TODO: will probably need MouseDragged to test properly and know if this works + setAnchorSelectionIndex(index0); + leadSelectionIndex = index1; + + fireDifference(sel, (BitSet) oldSel); + } + + /** + * Removes all intervals in the selection set. + */ + public void clearSelection() + { + // Find the selected interval. + int from = sel.nextSetBit(0); + if (from < 0) + return; // Empty selection - nothing to do. + int to = from; + + int i; + + for (i = from; i>=0; i=sel.nextSetBit(i+1)) + to = i; + + sel.clear(); + fireValueChanged(from, to, valueIsAdjusting); + } + + /** + * Fire the change event, covering the difference between the two sets. + * + * @param current the current set + * @param x the previous set, the object will be reused. + */ + private void fireDifference(BitSet current, BitSet x) + { + x.xor(current); + int from = x.nextSetBit(0); + if (from < 0) + return; // No difference. + int to = from; + int i; + + for (i = from; i >= 0; i = x.nextSetBit(i+1)) + to = i; + + fireValueChanged(from, to, valueIsAdjusting); + } + + /** + * Clears the current selection and marks a given interval as "selected". If + * the current selection mode is <code>SINGLE_SELECTION</code> only the + * index <code>index2</code> is selected. + * + * @param anchor the anchor selection index. + * @param lead the lead selection index. + */ + public void setSelectionInterval(int anchor, int lead) + { + if (anchor == -1 || lead == -1) + return; + if (selectionMode == SINGLE_SELECTION) + { + int lo = lead; + int hi = lead; + int selected = sel.nextSetBit(0); + if (selected == lead) + return; // the selection is not changing + if (selected >= 0) + { + lo = Math.min(lo, selected); + hi = Math.max(hi, selected); + } + if (anchorSelectionIndex >= 0) + { + lo = Math.min(lo, anchorSelectionIndex); + hi = Math.max(hi, anchorSelectionIndex); + } + sel.clear(); + sel.set(lead); + leadSelectionIndex = lead; + anchorSelectionIndex = lead; + fireValueChanged(lo, hi); + } + else if (selectionMode == SINGLE_INTERVAL_SELECTION) + { + // determine the current interval + int first = sel.nextSetBit(0); + int last = first; + if (first >= 0) + last += (sel.cardinality() - 1); + + // update the selection + int lo = Math.min(anchor, lead); + int hi = Math.max(anchor, lead); + if (lo == first && hi == last) + return; // selected interval is not being changed + sel.clear(); + sel.set(lo, hi + 1); + + // include the old selection in the event range + if (first >= 0) + lo = Math.min(lo, first); + if (last >= 0) + hi = Math.max(hi, last); + if (anchorSelectionIndex >= 0) + { + lo = Math.min(lo, anchorSelectionIndex); + hi = Math.max(hi, anchorSelectionIndex); + } + anchorSelectionIndex = anchor; + leadSelectionIndex = lead; + fireValueChanged(lo, hi); + } + else + { + BitSet oldSel = (BitSet) sel.clone(); + sel.clear(); + if (selectionMode == SINGLE_SELECTION) + anchor = lead; + + int lo = Math.min(anchor, lead); + int hi = Math.max(anchor, lead); + sel.set(lo, hi+1); + // update the anchorSelectionIndex and leadSelectionIndex variables + setAnchorSelectionIndex(anchor); + leadSelectionIndex = lead; + + fireDifference(sel, oldSel); + } + } + + /** + * Inserts a number of indices either before or after a particular + * position in the set of indices. Renumbers all indices after the + * inserted range. The new indices in the inserted range are not + * selected. This method is typically called to synchronize the selection + * model with an inserted range of elements in a {@link ListModel}. + * + * @param index The position to insert indices at + * @param length The number of indices to insert + * @param before Indicates whether to insert the indices before the index + * or after it + */ + public void insertIndexInterval(int index, + int length, + boolean before) + { + if (!before) + { + index++; + length--; + } + BitSet tmp = sel.get(index, sel.size()); + sel.clear(index, sel.size()); + int n = tmp.size(); + for (int i = 0; i < n; ++i) + sel.set(index + length + i, tmp.get(i)); + } + + /** + * Removes a range from the set of indices. Renumbers all indices after + * the removed range. This method is typically called to synchronize the + * selection model with a deleted range of elements in a {@link + * ListModel}. + * + * @param index0 The first index to remove (inclusive) + * @param index1 The last index to remove (inclusive) + */ + public void removeIndexInterval(int index0, + int index1) + { + int lo = Math.min(index0, index1); + int hi = Math.max(index0, index1); + + BitSet tmp = sel.get(hi, sel.size()); + sel.clear(lo, sel.size()); + int n = tmp.size(); + for (int i = 0; i < n; ++i) + sel.set(lo + i, tmp.get(i)); + } + + /** + * Fires a {@link ListSelectionEvent} to all the listeners of type {@link + * ListSelectionListener} registered with this selection model to + * indicate that a series of adjustment has just ended. + * + * The values of {@link #getMinSelectionIndex} and + * {@link #getMaxSelectionIndex} are used in the {@link ListSelectionEvent} + * that gets fired. + * + * @param isAdjusting <code>true</code> if this is the final change + * in a series of adjustments, <code>false/code> otherwise + */ + protected void fireValueChanged(boolean isAdjusting) + { + fireValueChanged(getMinSelectionIndex(), getMaxSelectionIndex(), + isAdjusting); + } + + /** + * Fires a {@link ListSelectionEvent} to all the listeners of type {@link + * ListSelectionListener} registered with this selection model. + * + * @param firstIndex The low index of the changed range + * @param lastIndex The high index of the changed range + */ + protected void fireValueChanged(int firstIndex, int lastIndex) + { + fireValueChanged(firstIndex, lastIndex, getValueIsAdjusting()); + } + + /** + * Fires a {@link ListSelectionEvent} to all the listeners of type {@link + * ListSelectionListener} registered with this selection model. + * + * @param firstIndex The low index of the changed range + * @param lastIndex The high index of the changed range + * @param isAdjusting Whether this change is part of a seqence of adjustments + * made to the selection, such as during interactive scrolling + */ + protected void fireValueChanged(int firstIndex, int lastIndex, + boolean isAdjusting) + { + ListSelectionEvent evt = new ListSelectionEvent(this, firstIndex, + lastIndex, isAdjusting); + ListSelectionListener[] listeners = getListSelectionListeners(); + for (int i = 0; i < listeners.length; ++i) + listeners[i].valueChanged(evt); + } + + /** + * Adds a listener. + * + * @param listener The listener to add + * + * @see #removeListSelectionListener + * @see #getListSelectionListeners + */ + public void addListSelectionListener(ListSelectionListener listener) + { + listenerList.add(ListSelectionListener.class, listener); + } + + /** + * Removes a registered listener. + * + * @param listener The listener to remove + * + * @see #addListSelectionListener + * @see #getListSelectionListeners + */ + public void removeListSelectionListener(ListSelectionListener listener) + { + listenerList.remove(ListSelectionListener.class, listener); + } + + /** + * Returns an array of all registerers listeners. + * + * @param listenerType The type of listener to retrieve + * + * @return The array + * + * @see #getListSelectionListeners + * @since 1.3 + */ + public <T extends EventListener> T[] getListeners(Class<T> listenerType) + { + return listenerList.getListeners(listenerType); + } + + /** + * Returns an array of all registerd list selection listeners. + * + * @return the array + * + * @see #addListSelectionListener + * @see #removeListSelectionListener + * @see #getListeners + * @since 1.4 + */ + public ListSelectionListener[] getListSelectionListeners() + { + return (ListSelectionListener[]) getListeners(ListSelectionListener.class); + } + + /** + * Returns a clone of this object. + * <code>listenerList</code> don't gets duplicated. + * + * @return the cloned object + * + * @throws CloneNotSupportedException if an error occurs + */ + public Object clone() + throws CloneNotSupportedException + { + DefaultListSelectionModel model = + (DefaultListSelectionModel) super.clone(); + model.sel = (BitSet) sel.clone(); + model.listenerList = new EventListenerList(); + return model; + } +} |