![JAR search and dependency download from the Maven repository](/logo.png)
net.sf.cuf.model.IndexedAdapter Maven / Gradle / Ivy
The newest version!
package net.sf.cuf.model;
import javax.swing.event.ChangeListener;
import javax.swing.event.ChangeEvent;
import java.util.List;
/**
* A IndexedAdapter is a ValueModel that takes an entry of
* a List as its value.
* A IndexedAdapter is simular to an AspectAdapter, it provides
* one item of a list as its own value.
* To detect changes in the list, the list must be the value
* of a ValueModel.
* If the the ValueModel holding the list is a SelectionInList,
* the index of the IndexedAdapter follows the selection in the
* list.
* If the list is not wrapped in a ValueModel, a change of
* the list can't be detected.
* When the wrapped list changes, the index in that list
* is set to NO_SELECTION if there is no IndexProvider.
* We also support the notion of an external update.
* @param the type inside the list
*/
public class IndexedAdapter extends AbstractValueModel
implements ValueModel, ExternalUpdate, ChangeListener
{
/** null or the value model containing our list */
private ValueModel> mTrigger;
/** null or the provider of an index inside the list */
private IndexProvider mIndexProvider;
/** null or mTrigger if the trigger is a SelectionInList */
private SelectionInList mSelectionInList;
/** our source, may be null */
private List mSource;
/** NO_SELECTION or the index in our list */
private int mIndex;
/** checks if mIndex points to a value inside source, never null */
private IndexValidHolder mIndexInList;
/**
* Creates a new IndexedAdapter that does not select an entry in the list.
* @param pTrigger the list we are indexing into is the trigger's value
* @throws IllegalArgumentException if pTrigger or pTrigger.getValue() is null or not
* a List
*/
public IndexedAdapter(final ValueModel> pTrigger)
{
this(pTrigger, IndexProvider.NO_SELECTION);
}
/**
* Creates a new IndexedAdapter.
* @param pTrigger the list we are indexing into is the trigger's value
* @param pIndex NO_SELECTION or the initial index in the list
* @throws IllegalArgumentException if pTrigger or pTrigger.getValue() is null or not
* a List or pIndex is out of range
*/
public IndexedAdapter(final ValueModel> pTrigger, final int pIndex)
{
super();
if (pTrigger==null)
throw new IllegalArgumentException("trigger must not be null");
Object value= pTrigger.getValue();
if ((value!=null) && !(value instanceof List))
throw new IllegalArgumentException("trigger value must be null or a List," +
" not a "+value.getClass().getName());
init(pTrigger.getValue(), pTrigger, pIndex);
}
/**
* Creates a new IndexedAdapter that does not select an entry in the list.
* @param pSource the list we are indexing into
* @throws IllegalArgumentException if pSource is null
*/
public IndexedAdapter(final List pSource)
{
this(pSource, IndexProvider.NO_SELECTION);
}
/**
* Creates a new IndexedAdapter.
* @param pSource the list we are indexing into
* @param pIndex NO_SELECTION or the initial index in the list
* @throws IllegalArgumentException if pSource is null or pIndex is out of range
*/
public IndexedAdapter(final List pSource, final int pIndex)
{
super();
if (pSource==null)
throw new IllegalArgumentException("source must not be null");
init(pSource, null, pIndex);
}
/**
* Handle common constructor stuff.
* @param pSource list we are indexing into, must not be null
* @param pTrigger trigger for our aspect, may be null
* @param pIndex NO_SELECTION or the index in pSource
* @throws IllegalArgumentException if pIndex is out of range
*/
private void init(final List pSource, final ValueModel> pTrigger, final int pIndex)
{
mSource = pSource;
mTrigger = pTrigger;
mIndex = pIndex;
setInSetValue(false, false);
if (mTrigger instanceof IndexProvider)
{
mIndexProvider= (IndexProvider) mTrigger;
mIndex= mIndexProvider.getIndex();
}
else
{
mIndexProvider= null;
}
checkIndex(mIndex, mSource);
mIndexInList= new IndexValidHolder(mIndex);
if (mTrigger!=null)
{
mTrigger.addChangeListener(this);
if (mTrigger instanceof SelectionInList)
{
mSelectionInList= (SelectionInList)mTrigger;
ValueModel indexProvider= mSelectionInList.selectionHolder();
indexProvider.onChangeSend(this, "indexChanged");
}
}
}
/**
* Return the Trigger or null if there is no trigger.
* @return null or the trigger
*/
public ValueModel> getTrigger()
{
return mTrigger;
}
/**
* Returns always true
* @return true
*/
public boolean isEditable()
{
return true;
}
/**
* Cleanup all resources: disconnect from any input sources (like
* other ValueModel's ...), and remove all listeners.
*/
public void dispose()
{
super.dispose();
if (mTrigger!=null && !mTrigger.isDisposed())
{
mTrigger.removeChangeListener(this);
}
if (mSelectionInList!=null && !mSelectionInList.isDisposed())
{
mSelectionInList.selectionHolder().retractInterestsFor(this);
}
mIndexInList.dispose();
}
/**
* Small helper to check the index.
* @param pIndex index to check
* @param pSource List for the index
*/
private static void checkIndex(final int pIndex, final List> pSource)
{
int maxSize= IndexProvider.NO_SELECTION;
if (pSource!=null)
{
maxSize = pSource.size();
}
if ((pIndex!=IndexProvider.NO_SELECTION) &&
((pIndex=maxSize)))
{
throw new IllegalArgumentException("index out of range, got "+
pIndex+", but list size is "+
maxSize);
}
}
/**
* Return the list that is our source. If our trigger is a
* SelectionInList, we get the list directly from the SIL and update
* our source object.
* @return null or the source list
*/
private List getSource()
{
if (mSelectionInList!=null)
{
mSource= mSelectionInList.getValue();
}
return mSource;
}
/**
* Set a new value, this will fire a ChangeEvent if the new value
* is different from the old value.
* If no list is available or no value is selected, nothing happens
* @param pValue the new value (null is o.k.)
* @param pIsSetForced true if a forced setValue should be done
*/
public void setValue(final T pValue, final boolean pIsSetForced)
{
checkDisposed();
if ((getSource()==null) || (mIndex==IndexProvider.NO_SELECTION))
{
return;
}
setInSetValue(true, pIsSetForced);
try
{
mSource.set(mIndex, pValue);
fireStateChanged();
}
finally
{
setInSetValue(false, false);
}
}
/**
* Get the current value, during a callback this is the new value.
* If no list is available or no item is selected, null is returned.
* @return null or the value object
*/
public T getValue()
{
checkDisposed();
if ((getSource()==null) || (mIndex==IndexProvider.NO_SELECTION))
{
return null;
}
return mSource.get(mIndex);
}
/**
* Set the index, if the index is different from the old index
* wie fire a state change.
* @param pIndex the new index
*/
public void setIndex(final int pIndex)
{
checkDisposed();
checkIndex(pIndex, getSource());
mIndex= pIndex;
mIndexInList.setIndex(mIndex);
fireStateChanged();
}
/**
* Get the current index.
* @return NO_SELECTION or the current index
*/
public int getIndex()
{
checkDisposed();
return mIndex;
}
/**
* Callback from our SelectionInList value model if it's index changed.
* @param pEvent not used
*/
@SuppressWarnings({"UnusedDeclaration"})
public void indexChanged(final ChangeEvent pEvent)
{
Integer index= mSelectionInList.selectionHolder().getValue();
setIndex(index);
}
/**
* The provided ValueModel can be used to monitor if this IndexedAdapter
* holds a "valid" value (index is not NO_SELECTION).
* The ValueModel is read-only, and contains either Boolean.TRUE or Boolean.FALSE.
* @return a ValueModel with a Boolean value
*/
public ValueModel isIndexInList()
{
checkDisposed();
return mIndexInList;
}
/**
* Signal this object that portions of its data changed.
* If we have a trigger, we notify it, and assume that it will notify us,
* otherwise we notify our children directly.
*/
public void signalExternalUpdate()
{
if (mTrigger instanceof ExternalUpdate)
{
((ExternalUpdate)mTrigger).signalExternalUpdate();
}
else
{
super.signalExternalUpdate();
}
}
/**
* Invoked when the target of the listener has changed its state.
*
* @param pEvent a ChangeEvent object
*/
public void stateChanged(final ChangeEvent pEvent)
{
checkDisposed();
// ignore callbacks when we are the reason that our model changes
if (isInSetValue())
{
return;
}
// should never happen, because we didn't register somewhere
if (mTrigger==null)
{
throw new IllegalStateException("got a callback with no trigger");
}
List newList= mTrigger.getValue();
int newIndex= IndexProvider.NO_SELECTION;
if (mIndexProvider!=null)
{
newIndex= mIndexProvider.getIndex();
}
else
{
// otherwise try to keep the old index
if (mIndex!=IndexProvider.NO_SELECTION)
{
if ((newList!=null) && (mIndex>=0) && (mIndex
© 2015 - 2025 Weber Informatics LLC | Privacy Policy