All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jgoodies.binding.list.IndirectListModel Maven / Gradle / Ivy

Go to download

The JGoodies Binding library connects object properties to Swing user interface components. And it helps you represent the state and behavior of a presentation independently of the GUI components used in the interface.

The newest version!
/*
 * Copyright (c) 2002-2015 JGoodies Software GmbH. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  o Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 *  o Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 *  o Neither the name of JGoodies Software GmbH nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.jgoodies.binding.list;

import static com.jgoodies.common.base.Preconditions.checkArgument;
import static com.jgoodies.common.base.Preconditions.checkNotNull;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import javax.swing.ListModel;
import javax.swing.event.EventListenerList;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;

import com.jgoodies.binding.PresentationModel;
import com.jgoodies.binding.beans.BeanAdapter;
import com.jgoodies.binding.beans.Model;
import com.jgoodies.binding.value.ValueHolder;
import com.jgoodies.binding.value.ValueModel;


/**
 * A ListModel implementation that holds a List or ListModel in a ValueModel.
 * If you hold a List, this class can only report that the List has been
 * replaced; this is done by firing a PropertyChangeEvent for the list
 * property. Also, a {@code ListDataEvent} is fired that reports
 * a complete change. In contrast, if you use a ListModel it will report
 * the same PropertyChangeEvent. But fine grained changes in the ListModel
 * will be fired by this class to notify observes about changes in the content,
 * added and removed elements.

* * If the list content doesn't change at all, or if it always changes * completely, you can work well with both List content and ListModel content. * But if the list structure or content changes, the ListModel reports more * fine grained events to registered ListDataListeners, which in turn allows * list views to chooser better user interface gestures: for example, a table * with scroll pane may retain the current selection and scroll offset.

* * If you want to combine List operations and the ListModel change reports, * you may consider using an implementation that combines these two interfaces, * for example {@link com.jgoodies.common.collect.ArrayListModel} * or {@link com.jgoodies.common.collect.LinkedListModel}.

* * Important Note: If you change the ListModel instance, * either by calling {@code #setListModel(ListModel)} or by setting * a new value to the underlying list holder, you must ensure that * the list holder throws a PropertyChangeEvent whenever the instance changes. * This event is used to remove a ListDataListener from the old ListModel * instance and is later used to add it to the new ListModel instance. * It is easy to violate this constraint, just because Java's standard * PropertyChangeSupport helper class that is used by many beans, checks * a changed property value via {@code #equals}, not {@code ==}. * For example, if you change the IndirectListModel's list model from an empty * list {@code L1} to another empty list instance {@code L2}, * the PropertyChangeSupport won't generate a PropertyChangeEvent, * and so, the IndirectListModel won't know about the change, which * may lead to unexpected behavior.

* * This binding library provides some help for firing PropertyChangeEvents * if the old ListModel and new ListModel are equal but not the same. * Class {@link com.jgoodies.binding.beans.ExtendedPropertyChangeSupport} * allows to permanently or individually check the identity (using * {@code ==}) instead of checking the equity (using {@code #equals}). * Class {@link com.jgoodies.binding.beans.Model} uses this extended * property change support. And class {@link ValueHolder} uses it too * and can be configured to always test the identity.

* * This class provides public convenience methods for firing ListDataEvents, * see the methods {@code #fireContentsChanged}, * {@code #fireIntervalAdded}, and {@code #fireIntervalRemoved}. * These are automatically invoked if the list holder holds a ListModel * that fires these events. If on the other hand the underlying List or * ListModel does not fire a required ListDataEvent, you can use these * methods to notify presentations about a change. It is recommended * to avoid sending duplicate ListDataEvents; hence check if the underlying * ListModel fires the necessary events or not.

* * Constraints: The list holder holds instances of {@link List} * or {@link ListModel}. If the ListModel changes, the underlying ValueModel * must fire a PropertyChangeEvent. * * @author Karsten Lentzsch * @version $Revision: 1.13 $ * * @see List * @see ListModel * @see SelectionInList * @see ValueModel * @see com.jgoodies.binding.adapter.ComboBoxAdapter * @see com.jgoodies.binding.adapter.AbstractTableAdapter * @see com.jgoodies.binding.beans.ExtendedPropertyChangeSupport * @see com.jgoodies.binding.beans.Model * @see com.jgoodies.binding.value.ValueHolder * * @param the type of the list elements * * @since 2.0 */ public class IndirectListModel extends Model implements ListModel { // Property Names ********************************************************* /** * The name of the bound write-only list property. */ public static final String PROPERTY_LIST = "list"; /** * The name of the bound read-write listHolder property. */ public static final String PROPERTY_LIST_HOLDER = "listHolder"; // ************************************************************************ /** * An empty {@code ListModel} that is used if the list holder's * content is null. * * @see #getListModel() */ private static final ListModel EMPTY_LIST_MODEL = new EmptyListModel(); // Instance Fields ******************************************************** /** * Holds a {@code List} or {@code ListModel} that in turn * holds the elements. */ private ValueModel listHolder; /** * Holds a copy of the listHolder's value. Used as the old list * when the listHolder's value changes. Required because a ValueModel * may use {@code null} as old value, but the IndirectListModel * must know about the old and the new list. */ private Object list; /** * The size of the current list. Used during changes from an old * to a new list to check for shorter or longer lists, which in turn * leads to different ListDataEvents. * Required only if the old and new list are the same instance. */ private int listSize; /** * Handles changes of the list. */ private final PropertyChangeListener listChangeHandler; /** * Handles structural and content changes of the list model. */ private final ListDataListener listDataChangeHandler; /** * Refers to the list of list data listeners that is used * to notify registered listeners if the ListModel changes. */ private final EventListenerList listenerList = new EventListenerList(); // Instance creation **************************************************** /** * Constructs an IndirectListModel with an empty initial * {@code ArrayListModel}. */ public IndirectListModel() { this((ListModel) new com.jgoodies.common.collect.ArrayListModel()); } /** * Constructs an IndirectListModel on the given item array. * The specified array will be converted to a List.

* * Changes to the list "write through" to the array, and changes * to the array contents will be reflected in the list. * * @param listItems the array of initial items * * @throws NullPointerException if {@code listItems} is {@code null} */ public IndirectListModel(E[] listItems) { this(Arrays.asList(listItems)); } /** * Constructs an IndirectListModel on the given list.

* * Note: Favor {@code ListModel} over * {@code List} when working with an IndirectListModel. * Why? The IndirectListModel can work with both types. What's the * difference? ListModel provides all list access features * required by the IndirectListModel's. In addition it reports more * fine grained change events, instances of {@code ListDataEvents}. * In contrast developer often create Lists and operate on them * and the ListModel may be inconvenient for these operations.

* * A convenient solution for this situation is to use the * {@code ArrayListModel} and {@code LinkedListModel} classes. * These implement both List and ListModel, offer the standard List * operations and report the fine grained ListDataEvents. * * @param list the initial list */ public IndirectListModel(List list) { this(new ValueHolder(list, true)); } /** * Constructs an IndirectListModel on the given list model * using a default list holder. * * @param listModel the initial list model */ public IndirectListModel(ListModel listModel) { this(new ValueHolder(listModel, true)); } /** * Constructs an IndirectListModel on the given list holder.

* * Constraints: * 1) The listHolder must hold instances of List or ListModel and * 2) must report a value change whenever the value's identity changes. * Note that many bean properties don't fire a PropertyChangeEvent * if the old and new value are equal - and so would break this constraint. * If you provide a ValueHolder, enable its identityCheck feature * during construction. If you provide an adapted bean property from * a bean that extends the JGoodies {@code Model} class, * you can enable the identity check feature in the methods * {@code #firePropertyChange} by setting the trailing boolean * parameter to {@code true}. * * @param listHolder holds the list or list model * * @throws NullPointerException * if {@code listHolder} is {@code null} */ public IndirectListModel(ValueModel listHolder) { checkNotNull(listHolder, "The list holder must not be null."); checkListHolderIdentityCheck(listHolder); listChangeHandler = new ListChangeHandler(); listDataChangeHandler = createListDataChangeHandler(); this.listHolder = listHolder; this.listHolder.addValueChangeListener(listChangeHandler); // If the ValueModel holds a ListModel observe list data changes too. list = listHolder.getValue(); listSize = getSize(list); if (list != null) { if (list instanceof ListModel) { ((ListModel) list).addListDataListener(listDataChangeHandler); } else if (!(list instanceof List)) { throw new ClassCastException("The listHolder's value must be a List or ListModel."); } } } // Accessing the List/ListModel ******************************************* /** * Returns the list holder's List or an empty List, if it * holds {@code null}. Throws an exception if the list holder holds * any other type, including ListModels. * * @return the List content or an empty List if the content is {@code null} * * @throws ClassCastException if the list holder is neither * {@code null} nor a List * * @see #setList(List) * @see #getListModel() * @see #setListModel(ListModel) * * @since 2.0 */ public final List getList() { Object aList = getListHolder().getValue(); if (aList == null) { return Collections.emptyList(); } if (aList instanceof List) { return (List) aList; } throw new ClassCastException( "#getList assumes that the list holder holds a List"); } /** * Sets the given list as value of the list holder.

* * Note: Favor {@code ListModel} over * {@code List} when working with an IndirectListModel. * Why? The IndirectListModel can work with both types. What's the * difference? ListModel provides all list access features * required by the IndirectListModel's. In addition it reports more * fine grained change events, instances of {@code ListDataEvents}. * In contrast developer often create Lists and operate on them * and the ListModel may be inconvenient for these operations.

* * A convenient solution for this situation is to use the * {@code ArrayListModel} and {@code LinkedListModel} classes. * These implement both List and ListModel, offer the standard List * operations and report the fine grained ListDataEvents. * * @param newList the list to be set as new list content * * @see #getList() * @see #getListModel() * @see #setListModel(ListModel) */ public final void setList(List newList) { getListHolder().setValue(newList); } /** * Returns the list holder's ListModel or an empty ListModel, if it * holds {@code null}. Throws an exception if the list holder holds * any other type, including Lists. * * @return the ListModel content or an empty ListModel * if the content is {@code null} * * @throws ClassCastException if the list holder is neither * {@code null} nor a ListModel * * @see #setListModel(ListModel) * @see #setList(List) */ public final ListModel getListModel() { Object aListModel = getListHolder().getValue(); if (aListModel == null) { return EMPTY_LIST_MODEL; } if (aListModel instanceof ListModel) { return (ListModel) aListModel; } throw new ClassCastException( "#getListModel assumes that the list holder holds a ListModel"); } /** * Sets the given list model as value of the list holder. * * @param newListModel the list model to be set as new list content * * @see #getListModel() * @see #setList(List) */ public final void setListModel(ListModel newListModel) { getListHolder().setValue(newListModel); } // Accessing the List/ListModel Holder ************************************ /** * Returns the model that holds the List/ListModel. * * @return the model that holds the List/ListModel */ public final ValueModel getListHolder() { return listHolder; } /** * Sets a new list holder. Does nothing if old and new holder are equal. * Removes the list change handler from the old holder and adds * it to the new one. In case the list holder contents is a ListModel, * the list data change handler is updated too by invoking * {@code #updateListDataRegistration} in the same way as done in the * list change handler.

* * TODO: Check and verify whether the list data registration update * can be performed in one step after the listHolder has been * changed - instead of remove the list data change handler, then * changing the listHolder, and finally adding the list data change handler. * * @param newListHolder the list holder to be set * * @throws NullPointerException if the new list holder is {@code null} * @throws IllegalArgumentException if the listHolder is a ValueHolder * that doesn't check the identity when changing its value */ public final void setListHolder(ValueModel newListHolder) { checkNotNull(newListHolder, "The new list holder must not be null."); checkListHolderIdentityCheck(newListHolder); ValueModel oldListHolder = getListHolder(); if (oldListHolder == newListHolder) { return; } Object oldList = list; int oldSize = listSize; Object newList = newListHolder.getValue(); oldListHolder.removeValueChangeListener(listChangeHandler); listHolder = newListHolder; newListHolder.addValueChangeListener(listChangeHandler); updateList(oldList, oldSize, newList); firePropertyChange(PROPERTY_LIST_HOLDER, oldListHolder, newListHolder); } // ListModel Implementation *********************************************** /** * Checks and answers if the list is empty or {@code null}. * * @return true if the list is empty or {@code null}, false otherwise */ public final boolean isEmpty() { return getSize() == 0; } /** * Returns the length of the list, {@code 0} if the list model * is {@code null}. * * @return the size of the list, {@code 0} if the list model is * {@code null} */ @Override public final int getSize() { return getSize(getListHolder().getValue()); } /** * Returns the value at the specified index, {@code null} * if the list model is {@code null}. * * @param index the requested index * @return the value at {@code index}, {@code null} * if the list model is {@code null} * * @throws NullPointerException if the list holder's content is null */ @Override public final E getElementAt(int index) { return getElementAt(getListHolder().getValue(), index); } /** * Adds a listener to the list that's notified each time a change * to the data model occurs. * * @param l the {@code ListDataListener} to be added */ @Override public final void addListDataListener(ListDataListener l) { listenerList.add(ListDataListener.class, l); } /** * Removes a listener from the list that's notified each time a * change to the data model occurs. * * @param l the {@code ListDataListener} to be removed */ @Override public final void removeListDataListener(ListDataListener l) { listenerList.remove(ListDataListener.class, l); } /** * Returns an array of all the list data listeners * registered on this {@code IndirectListModel}. * * @return all of this model's {@code ListDataListener}s, * or an empty array if no list data listeners * are currently registered * * @see #addListDataListener(ListDataListener) * @see #removeListDataListener(ListDataListener) */ public final ListDataListener[] getListDataListeners() { return listenerList.getListeners(ListDataListener.class); } // ListModel Helper Code ************************************************** /** * Notifies all registered ListDataListeners that the contents * of one or more list elements has changed. * The changed elements are specified by the closed interval index0, index1 * -- the end points are included. Note that index0 need not be less than * or equal to index1.

* * If the list holder holds a ListModel, this IndirectListModel listens * to ListDataEvents fired by that ListModel, and forwards these events * by invoking the associated {@code #fireXXX} method, which in turn * notifies all registered ListDataListeners. Therefore if you fire * ListDataEvents in an underlying ListModel, you don't need this method * and should not use it to avoid sending duplicate ListDataEvents. * * @param index0 one end of the new interval * @param index1 the other end of the new interval * * @see ListModel * @see ListDataListener * @see ListDataEvent * * @since 1.0.2 */ public final void fireContentsChanged(int index0, int index1) { Object[] listeners = listenerList.getListenerList(); ListDataEvent e = null; for (int i = listeners.length - 2; i >= 0; i -= 2) { if (listeners[i] == ListDataListener.class) { if (e == null) { e = new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED, index0, index1); } ((ListDataListener) listeners[i + 1]).contentsChanged(e); } } } /** * Notifies all registered ListDataListeners that one or more elements * have been added to this IndirectListModel's List/ListModel. * The new elements are specified by a closed interval index0, index1 * -- the end points are included. Note that index0 need not be less than * or equal to index1.

* * If the list holder holds a ListModel, this IndirectListModel listens * to ListDataEvents fired by that ListModel, and forwards these events * by invoking the associated {@code #fireXXX} method, which in turn * notifies all registered ListDataListeners. Therefore if you fire * ListDataEvents in an underlying ListModel, you don't need this method * and should not use it to avoid sending duplicate ListDataEvents. * * @param index0 one end of the new interval * @param index1 the other end of the new interval * * @see ListModel * @see ListDataListener * @see ListDataEvent * * @since 1.0.2 */ public final void fireIntervalAdded(int index0, int index1) { Object[] listeners = listenerList.getListenerList(); ListDataEvent e = null; listSize = getSize(); for (int i = listeners.length - 2; i >= 0; i -= 2) { if (listeners[i] == ListDataListener.class) { if (e == null) { e = new ListDataEvent(this, ListDataEvent.INTERVAL_ADDED, index0, index1); } ((ListDataListener) listeners[i + 1]).intervalAdded(e); } } } /** * Notifies all registered ListDataListeners that one or more elements * have been removed from this IndirectListModel's List/ListModel. * {@code index0} and {@code index1} are the end points * of the interval that's been removed. Note that {@code index0} * need not be less than or equal to {@code index1}.

* * If the list holder holds a ListModel, this IndirectListModel listens * to ListDataEvents fired by that ListModel, and forwards these events * by invoking the associated {@code #fireXXX} method, which in turn * notifies all registered ListDataListeners. Therefore if you fire * ListDataEvents in an underlying ListModel, you don't need this method * and should not use it to avoid sending duplicate ListDataEvents. * * @param index0 one end of the removed interval, * including {@code index0} * @param index1 the other end of the removed interval, * including {@code index1} * * @see ListModel * @see ListDataListener * @see ListDataEvent * * @since 1.0.2 */ public final void fireIntervalRemoved(int index0, int index1) { Object[] listeners = listenerList.getListenerList(); ListDataEvent e = null; listSize = getSize(); for (int i = listeners.length - 2; i >= 0; i -= 2) { if (listeners[i] == ListDataListener.class) { if (e == null) { e = new ListDataEvent(this, ListDataEvent.INTERVAL_REMOVED, index0, index1); } ((ListDataListener) listeners[i + 1]).intervalRemoved(e); } } } // Misc ****************************************************************** /** * Removes the internal listeners from the list holder. If the current list * is a ListModel, the internal ListDataListener is removed from it. * This IndirectListModel must not be used after calling * {@code #release}.

* * To avoid memory leaks it is recommended to invoke this method, * if the list holder, selection holder, or selection index holder * live much longer than this IndirectListModel. * Instead of releasing the IndirectListModel, you typically make the * list holder obsolete by releasing the PresentationModel or BeanAdapter * that has created them before.

* * As an alternative you may use ValueModels that in turn use * event listener lists implemented using {@code WeakReference}.

* * Basically this release method performs the reverse operation * performed during the IndirectListModel construction. * * @see PresentationModel#release() * @see BeanAdapter#release() * @see java.lang.ref.WeakReference * * @since 1.2 */ public void release() { listHolder.removeValueChangeListener(listChangeHandler); if (list != null && list instanceof ListModel) { ((ListModel) list).removeListDataListener(listDataChangeHandler); } listHolder = null; list = null; } // Default Behavior ******************************************************* /** * Creates and returns the ListDataListener used to observe * changes in the underlying ListModel. It is re-registered * in {@code #updateListModel}. * * @return the ListDataListener that handles changes * in the underlying ListModel */ protected ListDataListener createListDataChangeHandler() { return new ListDataChangeHandler(); } /** * Removes the list data change handler from the old list in case * it is a {@code ListModel} and adds it to new one in case * it is a {@code ListModel}. * It then fires a property change for the list and a contents change event * for the list content. * * @param oldList the old list content * @param oldSize the size of the old List content * @param newList the new list content * * @see javax.swing.JTable#tableChanged(javax.swing.event.TableModelEvent) */ protected void updateList(Object oldList, int oldSize, Object newList) { if (oldList != null && oldList instanceof ListModel) { ((ListModel) oldList).removeListDataListener(listDataChangeHandler); } if (newList != null && newList instanceof ListModel) { ((ListModel) newList).addListDataListener(listDataChangeHandler); } int newSize = getSize(newList); list = newList; listSize = getSize(newList); firePropertyChange(PROPERTY_LIST, oldList, newList); fireListChanged(oldSize - 1, newSize - 1); } /** * Notifies all registered ListDataListeners that this ListModel * has changed from an old list to a new list content. * If the old and new list size differ, a remove or add event for * the removed or added interval is fired. A content change * is reported for the interval common to the old and new list.

* * This method is invoked by #updateList during the transition * from an old List(Model) to a new List(Model).

* * Note: * The order of the events fired ensures that after each event * the size described by the ListDataEvents equals the ListModel size. * * @param oldLastIndex the last index of the old list * @param newLastIndex the last index of the new list */ protected final void fireListChanged(int oldLastIndex, int newLastIndex) { if (newLastIndex < oldLastIndex) { fireIntervalRemoved(newLastIndex + 1, oldLastIndex); } else if (oldLastIndex < newLastIndex) { fireIntervalAdded(oldLastIndex + 1, newLastIndex); } int lastCommonIndex = Math.min(oldLastIndex, newLastIndex); if (lastCommonIndex >= 0) { fireContentsChanged(0, lastCommonIndex); } } // Helper Code ************************************************************ /** * Returns the length of the given list, {@code 0} if the list model * is {@code null}. * * @param aListListModelOrNull a List, ListModel or null * @return the size of the given list, {@code 0} if the list model is * {@code null} */ protected static final int getSize(Object aListListModelOrNull) { if (aListListModelOrNull == null) { return 0; } else if (aListListModelOrNull instanceof ListModel) { return ((ListModel) aListListModelOrNull).getSize(); } else { return ((List) aListListModelOrNull).size(); } } private E getElementAt(Object aList, int index) { checkNotNull(aList, "The list contents is null."); if (aList instanceof ListModel) { return (E) ((ListModel) aList).getElementAt(index); } return ((List) aList).get(index); } /** * Throws an IllegalArgumentException if the given ValueModel * is a ValueHolder that has the identityCheck feature disabled. */ private static void checkListHolderIdentityCheck(ValueModel aListHolder) { if (!(aListHolder instanceof ValueHolder)) { return; } ValueHolder valueHolder = (ValueHolder) aListHolder; checkArgument(valueHolder.isIdentityCheckEnabled(), "The list holder must have the identity check enabled."); } // Helper Classes ********************************************************* /** * A ListModel that has no elements, a size of 0, and never fires an event. */ private static final class EmptyListModel implements ListModel, Serializable { /** * Returns zero to indicate an empty list. */ @Override public int getSize() { return 0; } /** * Returns {@code null} because this model has no elements. */ @Override public Object getElementAt(int index) { return null; } /** * Does nothing, because the empty list will never fire an event. * * @param l the {@code ListDataListener} to be ignored */ @Override public void addListDataListener(ListDataListener l) { // Do nothing. } /** * Does nothing, because the empty list will never fire an event. * * @param l the {@code ListDataListener} to be ignored */ @Override public void removeListDataListener(ListDataListener l) { // Do nothing. } } // Event Handlers ********************************************************* /** * Handles changes of the List or ListModel. */ private final class ListChangeHandler implements PropertyChangeListener { /** * The list has been changed. * Notifies all registered listeners about the change. * * @param evt the property change event to be handled */ @Override public void propertyChange(PropertyChangeEvent evt) { Object oldList = list; int oldSize = listSize; Object newList = evt.getNewValue(); updateList(oldList, oldSize, newList); } } /** * Handles ListDataEvents in the list model. */ private final class ListDataChangeHandler implements ListDataListener { /** * Sent after the indices in the index0, index1 * interval have been inserted in the data model. * The new interval includes both index0 and index1. * * @param evt a {@code ListDataEvent} encapsulating the * event information */ @Override public void intervalAdded(ListDataEvent evt) { int index0 = evt.getIndex0(); int index1 = evt.getIndex1(); fireIntervalAdded(index0, index1); } /** * Sent after the indices in the index0, index1 interval * have been removed from the data model. The interval * includes both index0 and index1. * * @param evt a {@code ListDataEvent} encapsulating the * event information */ @Override public void intervalRemoved(ListDataEvent evt) { int index0 = evt.getIndex0(); int index1 = evt.getIndex1(); fireIntervalRemoved(index0, index1); } /** * Sent when the contents of the list has changed in a way * that's too complex to characterize with the previous * methods. For example, this is sent when an item has been * replaced. Index0 and index1 bracket the change. * * @param evt a {@code ListDataEvent} encapsulating the * event information */ @Override public void contentsChanged(ListDataEvent evt) { fireContentsChanged(evt.getIndex0(), evt.getIndex1()); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy