com.jgoodies.binding.extras
Class SelectionInListModel

java.lang.Object
  extended by com.jgoodies.binding.beans.Model
      extended by com.jgoodies.binding.list.ListModelHolder
          extended by com.jgoodies.binding.extras.SelectionInListModel
All Implemented Interfaces:
Observable, Serializable, ListModel

public final class SelectionInListModel
extends ListModelHolder

Represents a selection in a ListModel. Provides bound bean properties for the ListModel, the selection, the selection index, and the selection empty state. Selection changes fire an event only if the old and new value are not equal. If you need to compare the identity you can use and observe the selection index instead of the selection or value.

Note: This class is not yet part of the binary Binding library; it comes with the Binding distributions as an extra. The API is work in progress and may change without notice; this class may even be completely removed from future distributions. If you want to use this class, you may consider copying it into your codebase.

The SelectionInListModel uses three ValueModels to hold the ListModel, the selection and selection index and provides bound bean properties for these models. You can access, observe and replace these ValueModels. This is useful to connect a SelectionInListModel with other ValueModels; for example you can use the SelectionInListModel's selection holder as bean channel for a PresentationModel. See the Binding tutorial classes for examples on how to connect a SelectionInListModel with a PresentationModel.

This class also implements the ListModel interface that allows API users to observe fine grained changes in the structure and contents of the list. Hence instances of this class can be used directly as model of a JList. If you want to use a SelectionInList with a JComboBox or JTable, you can convert the SelectionInList to the associated component model interfaces using the adapter classes ComboBoxAdapter and AbstractTableAdapter respectively. These classes are part of the Binding library too.

Unlike the older SelectionInList, the SelectionInListModel supports only ListModels as content of its ListModel holder. The SelectionInList2 supports Lists as content of its List holder. The SelectionInList2 and SelectionInListModel differ in how precise they can fire events about changes to the content and structure of the underlying List or ListModel content. The SelectionInList2 can only report that the List changes completely; this is done by emitting a PropertyChangeEvent for the list property. Also, a ListDataEvent is fired that reports a complete change. The SelectionInListModel reports the same PropertyChangeEvent. But fine grained changes in the ListModel will be forwarded as fine grained changes in the content, added and removed elements.

If the List or ListModel content doesn't change at all, or if it always changes completely, there's no differences between the SelectionInListModel and the SelectionInList2. 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.

An example for the benefit of fine grained ListDataEvents is the asynchronous transport of list elements from a server to a client. Let's say you transport the list elements in portions of 10 elements to improve the application's responsiveness. The user can then work with the SelectionInListModel as soon as the ListModel gets populated. If at a later time more elements are added to the ListModel, the SelectionInListModel can retain the selection index (and selection) and will just report a ListDataEvent about the interval added. JList, JTable and JComboBox will then just add the new elements at the end of the list presentation.

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 ArrayListModel or LinkedListModel.

Imporant Note: If you change the ListModel instance, either by calling #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 #equals, not ==. For example, if you change the SelectionInList's list model from an empty list L1 to another empty list instance L2, the PropertyChangeSupport won't generate a PropertyChangeEvent, and so, the SelectionInList 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 ExtendedPropertyChangeSupport allows to permanently or individually check the identity (using ==) instead of checking the equity (using #equals). Class Model uses this extended property change support. And class 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 #fireContentsChanged, #fireIntervalAdded, and #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. Typically an underlying ListModel will fire the add and remove events; but often it'll lack an event if the (seletcted) contents has changed. A convenient way to indicate that change is #fireSelectedContentsChanged. See the tutorial's AlbumManagerModel for an example how to use this feature.

Constraints: The ListModel holder holds instances of ListModel, the selection holder values of type Object and the selection index holder of type Integer. The selection index holder must hold non-null index values; however, when firing an index value change event, both the old and new value may be null. If the ListModel changes, the underyling ValueModel must fire a PropertyChangeEvent.

Since:
1.1
Version:
$Revision: 1.4 $
Author:
Karsten Lentzsch
See Also:
SelectionInList2, ValueModel, List, ListModel, ComboBoxAdapter, AbstractTableAdapter, ExtendedPropertyChangeSupport, Model, ValueHolder, Serialized Form

Field Summary
static String PROPERTYNAME_SELECTION
          The name of the bound read-write selection property.
static String PROPERTYNAME_SELECTION_EMPTY
          The name of the bound read-only selectionEmpty property.
static String PROPERTYNAME_SELECTION_HOLDER
          The name of the bound read-write selection holder property.
static String PROPERTYNAME_SELECTION_INDEX
          The name of the bound read-write selectionIndex property.
static String PROPERTYNAME_SELECTION_INDEX_HOLDER
          The name of the bound read-write selection index holder property.
 
Fields inherited from class com.jgoodies.binding.list.ListModelHolder
listDataChangeHandler, listModel, PROPERTYNAME_LIST_MODEL, PROPERTYNAME_LIST_MODEL_HOLDER
 
Constructor Summary
SelectionInListModel()
          Constructs a SelectionInList with an empty initial ArrayListModel using defaults for the selection holder and selection index holder.
SelectionInListModel(ListModel listModel)
          Constructs a SelectionInList on the given ListModel using defaults for the selection holder and selection index holder.
SelectionInListModel(ListModel listModel, ValueModel selectionHolder)
          Constructs a SelectionInList on the given ListModel and selection holder using a default selection index holder.
SelectionInListModel(ListModel listModel, ValueModel selectionHolder, ValueModel selectionIndexHolder)
          Constructs a SelectionInList on the given ListModel, selection holder, and selection index holder.
SelectionInListModel(ValueModel listModelHolder)
          Constructs a SelectionInList on the given ListModel holder using defaults for the selection holder and selection index holder.
SelectionInListModel(ValueModel listModelHolder, ValueModel selectionHolder)
          Constructs a SelectionInList on the given ListModel holder, selection holder and selection index holder.
SelectionInListModel(ValueModel listModelHolder, ValueModel selectionHolder, ValueModel selectionIndexHolder)
          Constructs a SelectionInList on the given ListModel holder, selection holder and selection index holder.
 
Method Summary
 void clearSelection()
          Clears the selection of this SelectionInList - if any.
protected  ListDataListener createListDataChangeHandler()
          Creates and returns the ListDataListener used to observe changes in the underlying ListModel.
 void fireSelectedContentsChanged()
          Notifies all registered ListDataListeners that the contents of the selected list item - if any - has changed.
 Object getSelection()
          Looks up and returns the current selection using the current selection index.
 ValueModel getSelectionHolder()
          Returns the selection holder.
 int getSelectionIndex()
          Returns the selection index.
 ValueModel getSelectionIndexHolder()
          Returns the selection index holder.
 boolean hasSelection()
          Checks and answers if an element is selected.
 boolean isSelectionEmpty()
          Checks and answers whether the selection is empty or not.
 void setSelection(Object newSelection)
          Sets the first list element that equals the given new selection as new selection.
 void setSelectionHolder(ValueModel newSelectionHolder)
          Sets a new selection holder.
 void setSelectionIndex(int newSelectionIndex)
          Sets a new selection index.
 void setSelectionIndexHolder(ValueModel newSelectionIndexHolder)
          Sets a new selection index holder.
protected  void updateListModel(ListModel oldListModel, ListModel newListModel)
          Removes the list data change handler from the old list in case it is a ListModel and adds it to new one in case it is a ListModel.
 
Methods inherited from class com.jgoodies.binding.list.ListModelHolder
addListDataListener, fireContentsChanged, fireIntervalAdded, fireIntervalRemoved, fireListChanged, getElementAt, getListDataListeners, getListModel, getListModelHolder, getSize, getSize, isEmpty, removeListDataListener, setListModel, setListModelHolder
 
Methods inherited from class com.jgoodies.binding.beans.Model
addPropertyChangeListener, addPropertyChangeListener, addVetoableChangeListener, addVetoableChangeListener, equals, fireMulticastPropertyChange, fireMultiplePropertiesChanged, firePropertyChange, firePropertyChange, firePropertyChange, firePropertyChange, firePropertyChange, firePropertyChange, firePropertyChange, fireVetoableChange, fireVetoableChange, fireVetoableChange, fireVetoableChange, fireVetoableChange, fireVetoableChange, getPropertyChangeListeners, getPropertyChangeListeners, getVetoableChangeListeners, getVetoableChangeListeners, removePropertyChangeListener, removePropertyChangeListener, removeVetoableChangeListener, removeVetoableChangeListener
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

PROPERTYNAME_SELECTION

public static final String PROPERTYNAME_SELECTION
The name of the bound read-write selection property.

See Also:
Constant Field Values

PROPERTYNAME_SELECTION_EMPTY

public static final String PROPERTYNAME_SELECTION_EMPTY
The name of the bound read-only selectionEmpty property.

See Also:
Constant Field Values

PROPERTYNAME_SELECTION_HOLDER

public static final String PROPERTYNAME_SELECTION_HOLDER
The name of the bound read-write selection holder property.

See Also:
Constant Field Values

PROPERTYNAME_SELECTION_INDEX

public static final String PROPERTYNAME_SELECTION_INDEX
The name of the bound read-write selectionIndex property.

See Also:
Constant Field Values

PROPERTYNAME_SELECTION_INDEX_HOLDER

public static final String PROPERTYNAME_SELECTION_INDEX_HOLDER
The name of the bound read-write selection index holder property.

See Also:
Constant Field Values
Constructor Detail

SelectionInListModel

public SelectionInListModel()
Constructs a SelectionInList with an empty initial ArrayListModel using defaults for the selection holder and selection index holder.


SelectionInListModel

public SelectionInListModel(ListModel listModel)
Constructs a SelectionInList on the given ListModel using defaults for the selection holder and selection index holder.

Parameters:
listModel - the initial ListModel

SelectionInListModel

public SelectionInListModel(ListModel listModel,
                            ValueModel selectionHolder)
Constructs a SelectionInList on the given ListModel and selection holder using a default selection index holder.

Parameters:
listModel - the initial ListModel
selectionHolder - holds the selection
Throws:
NullPointerException - if selectionHolder is null

SelectionInListModel

public SelectionInListModel(ListModel listModel,
                            ValueModel selectionHolder,
                            ValueModel selectionIndexHolder)
Constructs a SelectionInList on the given ListModel, selection holder, and selection index holder.

Parameters:
listModel - the initial ListModel
selectionHolder - holds the selection
selectionIndexHolder - holds the selection index
Throws:
NullPointerException - if selectionHolder, or selectionIndexHolder is null

SelectionInListModel

public SelectionInListModel(ValueModel listModelHolder)
Constructs a SelectionInList on the given ListModel holder using defaults for the selection holder and selection index holder.

Constraints: 1) The listModelHolder must hold instances of 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 Model class, you can enable the identity check feature in the methods #firePropertyChange by setting the trailing boolean parameter to true.

Parameters:
listModelHolder - holds the ListModel
Throws:
NullPointerException - if the listModelHolder, selectionHolder, or selectionIndexHolder is null
IllegalArgumentException - if the listModelHolder is a ValueHolder that doesn't check the identity when changing its value
ClassCastException - if the listModelHolder contents is not a ListModel

SelectionInListModel

public SelectionInListModel(ValueModel listModelHolder,
                            ValueModel selectionHolder)
Constructs a SelectionInList on the given ListModel holder, selection holder and selection index holder.

Constraints: 1) The listModelHolder must hold instances of 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 Model class, you can enable the identity check feature in the methods #firePropertyChange by setting the trailing boolean parameter to true.

Parameters:
listModelHolder - holds the ListModel
selectionHolder - holds the selection
Throws:
NullPointerException - if the listModelHolder, selectionHolder, or selectionIndexHolder is null
IllegalArgumentException - if the listModelHolder is a ValueHolder that doesn't check the identity when changing its value
ClassCastException - if the listModelHolder contents is not a ListModel

SelectionInListModel

public SelectionInListModel(ValueModel listModelHolder,
                            ValueModel selectionHolder,
                            ValueModel selectionIndexHolder)
Constructs a SelectionInList on the given ListModel holder, selection holder and selection index holder.

Constraints: 1) The listModelHolder must hold instances of 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 Model class, you can enable the identity check feature in the methods #firePropertyChange by setting the trailing boolean parameter to true.

Parameters:
listModelHolder - holds the ListModel
selectionHolder - holds the selection
selectionIndexHolder - holds the selection index
Throws:
NullPointerException - if the listModelHolder, selectionHolder, or selectionIndexHolder is null
IllegalArgumentException - if the listModelHolder is a ValueHolder that doesn't check the identity when changing its value
ClassCastException - if the listModelHolder contents is not a ListModel
Method Detail

getSelection

public Object getSelection()
Looks up and returns the current selection using the current selection index. Returns null if no object is selected or if the list has no elements.

Returns:
the current selection, null if none is selected

setSelection

public void setSelection(Object newSelection)
Sets the first list element that equals the given new selection as new selection. Does nothing if the list is empty.

Parameters:
newSelection - the object to be set as new selection

getSelectionHolder

public ValueModel getSelectionHolder()
Returns the selection holder.

Returns:
the selection holder

setSelectionHolder

public void setSelectionHolder(ValueModel newSelectionHolder)
Sets a new selection holder. Does nothing if the new is the same as before. The selection remains unchanged and is still driven by the selection index holder. It's just that future index changes will update the new selection holder and that future selection holder changes affect the selection index.

Parameters:
newSelectionHolder - the selection holder to set
Throws:
NullPointerException - if the new selection holder is null

getSelectionIndex

public int getSelectionIndex()
Returns the selection index.

Returns:
the selection index
Throws:
NullPointerException - if the selection index holder has a null Object set

setSelectionIndex

public void setSelectionIndex(int newSelectionIndex)
Sets a new selection index. Does nothing if it is the same as before.

Parameters:
newSelectionIndex - the selection index to be set
Throws:
IndexOutOfBoundsException - if the new selection index is outside the bounds of the list

getSelectionIndexHolder

public ValueModel getSelectionIndexHolder()
Returns the selection index holder.

Returns:
the selection index holder

setSelectionIndexHolder

public void setSelectionIndexHolder(ValueModel newSelectionIndexHolder)
Sets a new selection index holder. Does nothing if the new is the same as before.

Parameters:
newSelectionIndexHolder - the selection index holder to set
Throws:
NullPointerException - if the new selection index holder is null
IllegalArgumentException - if the value of the new selection index holder is null

hasSelection

public boolean hasSelection()
Checks and answers if an element is selected.

Returns:
true if an element is selected, false otherwise

isSelectionEmpty

public boolean isSelectionEmpty()
Checks and answers whether the selection is empty or not. Unlike #hasSelection, the underlying property #selectionEmpty for this method is bound. I.e. you can observe this property using a PropertyChangeListener to update UI state.

Returns:
true if nothing is selected, false if there's a selection
See Also:
clearSelection(), hasSelection()

clearSelection

public void clearSelection()
Clears the selection of this SelectionInList - if any.


fireSelectedContentsChanged

public void fireSelectedContentsChanged()
Notifies all registered ListDataListeners that the contents of the selected list item - if any - has changed. Useful to update a presentation after editing the selection. See the tutorial's AlbumManagerModel for an example how to use this feature.

If the list holder holds a ListModel, this SelectionInList listens to ListDataEvents fired by that ListModel, and forwards these events by invoking the associated #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.

See Also:
ListModel, ListDataListener, ListDataEvent

createListDataChangeHandler

protected ListDataListener createListDataChangeHandler()
Creates and returns the ListDataListener used to observe changes in the underlying ListModel. It is re-registered in #updateListModel.

Overrides:
createListDataChangeHandler in class ListModelHolder
Returns:
the ListDataListener that handles changes in the underlying ListModel

updateListModel

protected void updateListModel(ListModel oldListModel,
                               ListModel newListModel)
Removes the list data change handler from the old list in case it is a ListModel and adds it to new one in case it is a ListModel. Also updates the selection index, fires a property change for the list and a contents change event.

Overrides:
updateListModel in class ListModelHolder
Parameters:
oldListModel - the old list content
newListModel - the new list content


Copyright © 2002-2006 JGoodies Karsten Lentzsch. All Rights Reserved.