A ListModel implementation that delegates to a ListModel
held by a ValueModel.
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 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 (selected) contents has changed.
The current class name "ListModelHolder" and accessor #getListModelHolder
may confuse users: what's the difference between the class (a ListModel)
and its list model holder (a ValueModel)?
TODO: Find a better name and provide a transition to the new class name.
I consider using "IndirectListModel" as the new name.
addListDataListener
public final void addListDataListener(ListDataListener l)
Adds a listener to the list that's notified each time a change
to the data model occurs.
l
- the ListDataListener
to be added
createListDataChangeHandler
protected ListDataListener createListDataChangeHandler()
Creates and returns the ListDataListener used to observe
changes in the underlying ListModel. It is re-registered
in #updateListModel
.
- the ListDataListener that handles changes
in the underlying ListModel
fireContentsChanged
public final void fireContentsChanged(int index0,
int index1)
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.
index0
- one end of the new intervalindex1
- the other end of the new interval
ListModel
, ListDataListener
, ListDataEvent
fireIntervalAdded
public final void fireIntervalAdded(int index0,
int index1)
Notifies all registered ListDataListeners that one or more elements
have been added to this SelectionInList'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.
index0
- one end of the new intervalindex1
- the other end of the new interval
ListModel
, ListDataListener
, ListDataEvent
fireIntervalRemoved
public final void fireIntervalRemoved(int index0,
int index1)
Notifies all registered ListDataListeners that one or more elements
have been removed from this SelectionInList's List/ListModel.
index0
and index1
are the end points
of the interval that's been removed. Note that index0
need not be less than or equal to index1
.
index0
- one end of the removed interval,
including index0
index1
- the other end of the removed interval,
including index1
ListModel
, ListDataListener
, ListDataEvent
fireListChanged
protected final void fireListChanged(int oldLastIndex,
int newLastIndex)
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).
The order of the events fired ensures that after each event
the size described by the ListDataEvents equals the ListModel size.
oldLastIndex
- the last index of the old listnewLastIndex
- the last index of the new list
getElementAt
public final Object getElementAt(int index)
Returns the value at the specified index.
index
- the requested index
getListDataListeners
public final ListDataListener[] getListDataListeners()
Returns an array of all the list data listeners
registered on this SelectionInList
.
- all of this model's
ListDataListener
s,
or an empty array if no list data listeners
are currently registered
getListModel
public final ListModel getListModel()
Returns the contents of the list model holder.
- the contents of the list model holder.
getListModelHolder
public final ValueModel getListModelHolder()
Returns the ValueModel that holds the ListModel we delegate to.
- the ValueModel that holds the ListModel we delegate to.
getSize
public final int getSize()
Returns the length of the list, 0
if the list model
is null
.
- the size of the list,
0
if the list model is
null
getSize
protected final int getSize(ListModel aListOrNull)
Returns the lists size or 0 if the list is null.
aListOrNull
- a List or null
- the list's size or 0 if the list is null
isEmpty
public final boolean isEmpty()
Checks and answers if the ListModel is empty or null
.
- true if the ListModel is empty or
null
, false otherwise
release
public void release()
Removes the internal listener from the list model holder.
If the current list model is not null, the internal ListDataListener
is removed from the list model. This ListModelHolder
must not be used after calling
#release
.
To avoid memory leaks it is recommended to invoke this method,
if the list model holder lives much longer than this ListModelHolder.
Instead of releasing the ListModelHolder, you typically make
the list holder obsolete by releasing the PresentationModel
or BeanAdapter that has created the model before.
As an alternative you may use ValueModels that in turn use
event listener lists implemented using
WeakReference
.
Basically this release method performs the reverse operation
performed during the ListModelHolder construction.
removeListDataListener
public final void removeListDataListener(ListDataListener l)
Removes a listener from the list that's notified each time a
change to the data model occurs.
l
- the ListDataListener
to be removed
setListModel
public final void setListModel(ListModel newListModel)
Sets the given list model as value of the list holder.
newListModel
- the list model to be set as new list content
setListModelHolder
public final void setListModelHolder(ValueModel newListModelHolder)
Sets a new ListModel 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. The list data change handler is re-registered
by invoking
#updateListModel
.
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.
newListModelHolder
- the ListModel holder to be set
updateListModel
protected void updateListModel(ListModel oldListModel,
ListModel newListModel)
Removes the list data change handler from the old list in case
it is not null
and adds it to new one in case
it is a not null
.
Also fires a property change for listModel and
a ListModel update event.
oldListModel
- the old ListModelnewListModel
- the new ListModel