ca.odell.glazedlists.swing.JXTableSupport Maven / Gradle / Ivy
/* Glazed Lists (c) 2003-2010 */
/* http://publicobject.com/glazedlists/ publicobject.com,*/
/* O'Dell Engineering Ltd.*/
package ca.odell.glazedlists.swing;
import ca.odell.glazedlists.EventList;
import ca.odell.glazedlists.SortedList;
import ca.odell.glazedlists.gui.TableFormat;
import ca.odell.glazedlists.impl.Preconditions;
import ca.odell.glazedlists.impl.beans.BeanProperty;
import ca.odell.glazedlists.impl.gui.SortingStrategy;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;
import org.jdesktop.swingx.JXTable;
/**
* Developer Preview:
* JXTableSupport
prototype
*
* Integrates a {@link JXTable} with Glazed Lists by
*
* - installing a {@link DefaultEventTableModel} as table model
* - installing a {@link DefaultEventSelectionModel} as table selection model
* - installing a {@link TableComparatorChooser} as sorting integration approach
*
*
* Warning: This class must be
* mutated from the Swing Event Dispatch Thread. Failure to do so will result in
* an {@link IllegalStateException} thrown from any one of:
*
*
* - {@link #install(JXTable, EventList, TableFormat, SortedList, Object)}
*
- {@link #uninstall()}
*
*
* @author Holger Brands
*/
public class JXTableSupport {
/** The JXTable to integrate with. */
private JXTable table;
/** The state of JXTable before install; needed for uninstall to restore state. */
private JXTableMemento tableMemento;
/** the installed event table model. */
private AdvancedTableModel tableModel;
/** the installed event selection model. */
private AdvancedListSelectionModel selectionModel;
/** the installed TableFormat. */
private TableFormat tableFormat;
/** the installed TableComparatorChooser. */
private TableComparatorChooser tableComparatorChooser;
/**
* Installs the Glazed Lists integration on the given table
.
* First, the current state of the table is determined to be able to restore this state
* when the integration is uninstalled again.
*
* Then this method installs
*
* - a {@link DefaultEventTableModel} as table model
* - a {@link DefaultEventSelectionModel} as table selection model
* - a {@link TableComparatorChooser} as sorting integration approach
*
* The effect of this is, that Glazed Lists takes full control of sorting (and filtering)
* functionality and disables JXTable's sorting support.
*
*
* @param element type of {@link EventList}
* @param table the JXTable to integrate with
* @param eventList the {@link EventList} with data for the table model
* @param tableFormat the {@link TableFormat} to use
* @param sortedList the {@link SortedList} to use with the {@link TableComparatorChooser}
* @param sortingStrategy the {@link SortingStrategy} to use with the
* {@link TableComparatorChooser}
* @return the JXTableSupport instance to use for uninstallation of GLazed Lists integration
*
* @throws IllegalStateException if this method is called from any Thread
* other than the Swing Event Dispatch Thread
*/
public static JXTableSupport install(JXTable table, EventList eventList,
TableFormat tableFormat, SortedList sortedList, Object sortingStrategy) {
Preconditions.checkNotNull(table, "JXTable must be defined.");
Preconditions.checkNotNull(eventList, "EventList must be defined.");
Preconditions.checkNotNull(tableFormat, "TableFormat must be defined.");
Preconditions.checkNotNull(sortedList, "SortedList must be defined.");
Preconditions.checkNotNull(sortingStrategy, "SortingStrategy must be defined.");
checkAccessThread();
return new JXTableSupport(table, eventList, tableFormat, sortedList, sortingStrategy);
}
/**
* @return the {@link JXTable} or null
if JXTableSupport has already been uninstalled
*/
public JXTable getTable() {
return table;
}
/**
* @return the installed {@link AdvancedListSelectionModel} or null
if already uninstalled
*/
public AdvancedListSelectionModel getTableSelectionModel() {
return selectionModel;
}
/**
* @return the installed {@link AdvancedTableModel} or null
if already uninstalled
*/
public AdvancedTableModel getTableModel() {
return tableModel;
}
/**
* @return the installed {@link TableFormat} or null
if already uninstalled
*/
public TableFormat getTableFormat() {
return tableFormat;
}
/**
* @return the installed {@link TableComparatorChooser} or null
if already uninstalled
*/
public TableComparatorChooser getTableComparatorChooser() {
return tableComparatorChooser;
}
/**
* Uninstalls the GlazedLists integration and restores the state of JXTable as it was before
* the installation.
*
* @throws IllegalStateException if this method is called from any Thread
* other than the Swing Event Dispatch Thread
*/
public void uninstall() {
checkAccessThread();
tableComparatorChooser.dispose();
tableMemento.restoreStateTo(table);
tableModel.dispose();
selectionModel.dispose();
tableComparatorChooser = null;
tableModel = null;
selectionModel = null;
tableFormat = null;
table = null;
tableMemento = null;
}
/**
* @return true if this {@link JXTableSupport} instance is currently
* installed and altering the behaviour of the JXTable; false if
* it has been {@link #uninstall}ed.
*/
public boolean isInstalled() {
return table != null;
}
/** Installs the GlazedLists integration on the given JXTable. */
private JXTableSupport(JXTable table, EventList eventList,
TableFormat tableFormat, SortedList sortedList, Object sortingStrategy) {
this.table = table;
this.tableFormat = tableFormat;
// remember table state for restore on uninstall
tableMemento = JXTableMemento.create(table);
tableMemento.storeStateFrom(table);
// set state needed to integrate with Glazed Lists
tableMemento.configureStateForGlazedLists(table);
// prepare and set TableModel und SelectionModel
tableModel = GlazedListsSwing.eventTableModelWithThreadProxyList(eventList, tableFormat);
table.setModel(tableModel);
selectionModel = GlazedListsSwing.eventSelectionModelWithThreadProxyList(eventList);
table.setSelectionModel(selectionModel);
// finally install TableComparatorChooser
tableComparatorChooser = TableComparatorChooser.install(table, sortedList,
sortingStrategy, tableFormat);
}
/**
* A convenience method to ensure {@link JXTableSupportTest} is being accessed from the Event
* Dispatch Thread.
*/
private static void checkAccessThread() {
if (!SwingUtilities.isEventDispatchThread())
throw new IllegalStateException(
"JXTableSupport must be accessed from the Swing Event Dispatch Thread, but was called on Thread \""
+ Thread.currentThread().getName() + "\"");
}
/**
* JXTableMemento
holds common state for {@link JXTable}.
* Version specific state for SwingX 1.0 or SwingX 1.6 is managed by subclasses.
*
* @author Holger Brands
*/
private static abstract class JXTableMemento {
private TableModel oldTableModel;
private ListSelectionModel oldSelectionModel;
private boolean oldSortable;
private TableCellRenderer oldDefaultRenderer;
/**
* Gets the current state from the given JXTable and stores it for later restore.
*/
public void storeStateFrom(JXTable table) {
oldTableModel = table.getModel();
oldSelectionModel = table.getSelectionModel();
oldSortable = table.isSortable();
oldDefaultRenderer = table.getTableHeader().getDefaultRenderer();
}
/**
* Restores the previously stored state to the given JXTable.
*/
public void restoreStateTo(JXTable table) {
table.setModel(oldTableModel);
table.setSelectionModel(oldSelectionModel);
table.setSortable(oldSortable);
table.getTableHeader().setDefaultRenderer(oldDefaultRenderer);
}
/**
* Configures the given JXTable for use with GlazedLists
*/
public void configureStateForGlazedLists(JXTable table) {
table.setSortable(false);
table.getTableHeader().setDefaultRenderer(new JTableHeader().getDefaultRenderer());
}
/**
* Creates a memento instance suitable for the given JXTable.
*/
public static JXTableMemento create(JXTable table) {
if (isSwingX16(table)) {
return new JXTable16Memento();
} else {
return new JXTable10Memento();
}
}
/**
* Determines if the table is from SwingX 1.0.x or SwingX 1.6.x.
* The former has a public method getSelectionMapper
, the latter not.
*
* @param table the JXTable to check
* @return true
, is it's SwingX 1.6.x
*/
private static boolean isSwingX16(JXTable table) {
boolean result = false;
try {
table.getClass().getMethod("getSelectionMapper", new Class[0]);
} catch (NoSuchMethodException e) {
result = true;
}
return result;
}
}
/**
* JXTable10Memento
for SwingX 1.0-specific state like the selection mapper.
*
* @author Holger Brands
*/
private static class JXTable10Memento extends JXTableMemento {
private Boolean oldSelectionMapperEnabled;
private final BeanProperty selectionMapperEnabledProperty = new BeanProperty(JXTable.class, "selectionMapper.enabled", true, true);
@Override
public void storeStateFrom(JXTable table) {
super.storeStateFrom(table);
oldSelectionMapperEnabled = (Boolean) selectionMapperEnabledProperty.get(table);
}
@Override
public void restoreStateTo(JXTable table) {
super.restoreStateTo(table);
selectionMapperEnabledProperty.set(table, oldSelectionMapperEnabled);
}
@Override
public void configureStateForGlazedLists(JXTable table) {
super.configureStateForGlazedLists(table);
selectionMapperEnabledProperty.set(table, Boolean.FALSE);
}
}
/**
* JXTable16Memento
for SwingX 1.6-specific state like the row sorter.
*
* @author Holger Brands
*/
private static class JXTable16Memento extends JXTableMemento {
private Boolean oldAutoCreateRowSorter;
private final BeanProperty autoCreateRowSorterProperty = new BeanProperty(JXTable.class, "autoCreateRowSorter", true, true);
private Object oldRowSorter;
private final BeanProperty rowSorterProperty = new BeanProperty(JXTable.class, "rowSorter", true, true);
@Override
public void storeStateFrom(JXTable table) {
super.storeStateFrom(table);
oldAutoCreateRowSorter = (Boolean) autoCreateRowSorterProperty.get(table);
oldRowSorter = rowSorterProperty.get(table);
}
@Override
public void restoreStateTo(JXTable table) {
super.restoreStateTo(table);
autoCreateRowSorterProperty.set(table, oldAutoCreateRowSorter);
rowSorterProperty.set(table, oldRowSorter);
}
@Override
public void configureStateForGlazedLists(JXTable table) {
super.configureStateForGlazedLists(table);
autoCreateRowSorterProperty.set(table, Boolean.FALSE);
rowSorterProperty.set(table, null);
}
}
}