![JAR search and dependency download from the Maven repository](/logo.png)
net.sf.cuf.model.ui.ListTableMapperBase Maven / Gradle / Ivy
The newest version!
package net.sf.cuf.model.ui;
import net.sf.cuf.model.RowColumnChangeEvent;
import net.sf.cuf.model.SelectionInList;
import javax.swing.table.TableModel;
import javax.swing.ListSelectionModel;
import javax.swing.JTable;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.EventListenerList;
import javax.swing.event.ListSelectionEvent;
import java.util.List;
import static net.sf.cuf.model.ui.CufTableRowSorter.convertRowIndexToModel;
import static net.sf.cuf.model.ui.CufTableRowSorter.convertRowIndexToView;
/**
* ListTableMapperBase contains the common code of TableSelectionModel and ListTableMapper.
* The main difference between those is that the TableSelectionModel supports editing
* but requires a row data object that contains all displayed column values,
* and the ListTableMapper is read only but supports navigation through multiple getters and conversions.
* @param The Type we have for a table row entry
*/
public abstract class ListTableMapperBase implements TableModel, ListSelectionListener
{
/** our JTable, never null */
private JTable mTable;
/** value model holding the list, never null */
protected SelectionInList mSelectionInList;
/** helper for the TableModel callback handling */
private EventListenerList mListenerList;
/** marker if we are inside a selection change, we then ignore selection
* changes from the "other" model */
private boolean mInSelectionChange;
/**
* Common construction stuff, it creates a new adaption between
* a JTable and a SelectionInList value model.
* This object is also set as the JTable's TableModel and ListSelectionModel.
* @param pTable the table for which we provide TableModel and ListSelectionModel behaviour
* @param pValueModel the value model that drives the table (data, selection)
* and gets updated by the table (selection only)
* @throws IllegalArgumentException if a parameter is bogus
*/
protected void init(final JTable pTable, final SelectionInList pValueModel)
{
if (pTable==null)
{
throw new IllegalArgumentException("the table must not be null");
}
if (pValueModel==null)
{
throw new IllegalArgumentException("the value model must not be null");
}
mTable = pTable;
mSelectionInList = pValueModel;
mListenerList = new EventListenerList();
mInSelectionChange = false;
// we support only single-selection
pTable.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
// this must stay at the end so that everything is setup first
mSelectionInList.onChangeSend (this, "vmDataChanged");
mSelectionInList.selectionHolder().onChangeSend(this, "vmSelectionChanged");
pTable.setModel (this);
pTable.getSelectionModel().addListSelectionListener(this);
}
/**
* Called whenever the data of the SelectionInList changes.
* @param pEvent not used
*/
@SuppressWarnings({"UnusedDeclaration"})
public void vmDataChanged(final ChangeEvent pEvent)
{
// ignore the changes we triggered
if (mInSelectionChange)
{
return;
}
// notify the table to re-read the data, this will clear the selection,
// so we re-set the selection afterwards
int modelIndex= mSelectionInList.selectionHolder().intValue();
mInSelectionChange= true;
try
{
TableModelEvent e = createTableModelEvent(pEvent);
fireTableChanged(e);
setTableSelection(modelIndex);
}
finally
{
mInSelectionChange= false;
}
}
/**
* Create a event for updating the table, takes extra info from a RowColumnChangeEvent
* (like row and column) into account.
* @param pEvent the change event that triggered us
* @return a matching TableModelEvent
*/
private TableModelEvent createTableModelEvent(ChangeEvent pEvent)
{
TableModelEvent e;
if (pEvent instanceof RowColumnChangeEvent)
{
RowColumnChangeEvent event= (RowColumnChangeEvent) pEvent;
if (event.hasRowInfo())
{
int viewRowIndex = convertRowIndexToView(mTable, event.getRow());
if (event.hasColumnInfo())
{
e= new TableModelEvent(this, viewRowIndex);
}
else
{
e= new TableModelEvent(this, viewRowIndex, viewRowIndex, event.getColumn());
}
}
else
{
e= new TableModelEvent(this);
}
}
else
{
e= new TableModelEvent(this);
}
return e;
}
/**
* Called whenever the selection of the SelectionInList changes.
* @param pEvent not used
*/
@SuppressWarnings({"UnusedDeclaration"})
public void vmSelectionChanged(final ChangeEvent pEvent)
{
// ignore the changes we triggered
if (mInSelectionChange)
{
return;
}
mInSelectionChange= true;
try
{
// re-adjust the table selection in our JTable
int modelIndex= mSelectionInList.selectionHolder().intValue();
setTableSelection(modelIndex);
}
finally
{
mInSelectionChange= false;
}
}
/**
* Helper method to set (or un-set) the table selection
* @param pModelIndex the model index, may be -1
*/
private void setTableSelection(final int pModelIndex)
{
int viewIndex = convertRowIndexToView(mTable, pModelIndex);
if (viewIndex==-1)
{
mTable.getSelectionModel().clearSelection();
}
else
{
mTable.getSelectionModel().setSelectionInterval(viewIndex, viewIndex);
}
}
/**
* Called whenever the selection of the JTable changes, we update
* our SelectionInList index.
* @param pEvent event describing the new selection
*/
public void valueChanged(final ListSelectionEvent pEvent)
{
// ignore the changes we triggered
if (mInSelectionChange)
{
return;
}
// ignore intermediate changes
if (pEvent.getValueIsAdjusting())
{
return;
}
mInSelectionChange= true;
try
{
int viewIndex= mTable.getSelectedRow();
// due to Bug 4905083, up to JDK 1.5, we must ignore changes that
// happen with invalid rows
if (mTable.getRowCount()<=viewIndex)
{
return;
}
int modelIndex;
if (viewIndex < 0)
{
modelIndex= SelectionInList.NO_SELECTION;
}
else
{
modelIndex = convertRowIndexToModel(mTable, viewIndex);
}
mSelectionInList.selectionHolder().setValueForced(modelIndex);
}
finally
{
mInSelectionChange= false;
}
}
/*
* Swing TableModel methods
*/
public int getRowCount()
{
List list= mSelectionInList.getValue();
return list==null ? 0 : list.size();
}
public boolean isCellEditable(final int pRowIndex, final int pColumnIndex)
{
return false;
}
public void setValueAt(final Object pValue, final int pRowIndex, final int pColumnIndex)
{
throw new UnsupportedOperationException("this is a read-only table model");
}
public void addTableModelListener(final TableModelListener pTableModelListener)
{
mListenerList.add(TableModelListener.class, pTableModelListener);
}
public void removeTableModelListener(final TableModelListener pTableModelListener)
{
mListenerList.remove(TableModelListener.class, pTableModelListener);
}
/**
* Helper to fire a table event to all our table model listeners.
* @param pEvent the table event
*/
protected void fireTableChanged(final TableModelEvent pEvent)
{
Object[] listeners = mListenerList.getListenerList();
for (int i= listeners.length-2; i>=0; i-=2)
{
if (listeners[i]==TableModelListener.class)
{
((TableModelListener)listeners[i+1]).tableChanged(pEvent);
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy