Class ThreadedTableModel<ROW_OBJECT,DATA_SOURCE>
- java.lang.Object
-
- javax.swing.table.AbstractTableModel
-
- docking.widgets.table.AbstractGTableModel<T>
-
- docking.widgets.table.AbstractSortedTableModel<ROW_TYPE>
-
- docking.widgets.table.GDynamicColumnTableModel<ROW_OBJECT,DATA_SOURCE>
-
- docking.widgets.table.threaded.ThreadedTableModel<ROW_OBJECT,DATA_SOURCE>
-
- Type Parameters:
ROW_OBJECT
- the row object class for this table model.DATA_SOURCE
- the type of data that will be returned fromGDynamicColumnTableModel.getDataSource()
. This object will be given to theDynamicTableColumn
objects used by this table model whenDynamicTableColumn.getValue(Object, ghidra.docking.settings.Settings, Object, ServiceProvider)
is called.
- All Implemented Interfaces:
ConfigurableColumnTableModel
,DynamicColumnTableModel<ROW_OBJECT>
,RowObjectFilterModel<ROW_OBJECT>
,RowObjectTableModel<ROW_OBJECT>
,SelectionStorage<ROW_OBJECT>
,SortedTableModel
,VariableColumnTableModel
,java.io.Serializable
,java.util.EventListener
,javax.swing.event.ChangeListener
,javax.swing.table.TableModel
- Direct Known Subclasses:
GhidraProgramTableModel
,ProjectDataTableModel
,ThreadedTableModelStub
public abstract class ThreadedTableModel<ROW_OBJECT,DATA_SOURCE> extends GDynamicColumnTableModel<ROW_OBJECT,DATA_SOURCE> implements RowObjectFilterModel<ROW_OBJECT>
The base implementation of the threaded table model.You can optionally set this model to load data incrementally by passing the correct constructor argument. Note, if you make this model incremental, then you need to set an incremental task monitor in order to get feedback about loading (see
setIncrementalTaskMonitor(TaskMonitor)
. Alternatively, you can use aGThreadedTablePanel
, which will install the proper monitor for you.- See Also:
- Serialized Form
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description protected class
ThreadedTableModel.IncrementalLoadJobListener
A special internal listener for the model to know when incremental jobs begin and end.
-
Field Summary
Fields Modifier and Type Field Description protected TableData<ROW_OBJECT>
allData
protected TableData<ROW_OBJECT>
filteredData
-
Fields inherited from class docking.widgets.table.GDynamicColumnTableModel
columnSettings, serviceProvider, tableColumns
-
Fields inherited from class docking.widgets.table.AbstractSortedTableModel
hasEverSorted
-
Fields inherited from class docking.widgets.table.AbstractGTableModel
WIDTH_UNDEFINED
-
Fields inherited from interface docking.widgets.table.RowObjectFilterModel
SUB_FILTERING_DISABLED_PROPERTY
-
Fields inherited from interface docking.widgets.table.SortedTableModel
ASCENDING_ORDER, DESCENDING_ORDER
-
-
Constructor Summary
Constructors Modifier Constructor Description protected
ThreadedTableModel(java.lang.String modelName, ServiceProvider serviceProvider)
protected
ThreadedTableModel(java.lang.String modelName, ServiceProvider serviceProvider, TaskMonitor monitor)
protected
ThreadedTableModel(java.lang.String modelName, ServiceProvider serviceProvider, TaskMonitor monitor, boolean loadIncrementally)
The constructor through which all others pass.
-
Method Summary
All Methods Instance Methods Abstract Methods Concrete Methods Modifier and Type Method Description void
addInitialLoadListener(ThreadedTableModelListener listener)
Adds a listener that will be notified of the first table load of this model.void
addObject(ROW_OBJECT obj)
Adds the specified object to this model and schedules an update.void
addThreadedTableModelListener(ThreadedTableModelListener listener)
This is a way to know about updates from the table.void
cancelAllUpdates()
Cancels all current and pending updates to the model.protected void
clearData()
This method will clear all data and trigger fire a table data changed.protected IncrementalLoadJob<ROW_OBJECT>
createIncrementalLoadJob()
protected java.util.Comparator<ROW_OBJECT>
createSortComparator(int columnIndex)
An extension point for subclasses to insert their own comparator objects for their data.void
dispose()
Disposes this model.protected java.util.List<ROW_OBJECT>
doFilter(java.util.List<ROW_OBJECT> data, TableSortingContext<ROW_OBJECT> lastSortingContext, TaskMonitor monitor)
Override this to change how filtering is performed.protected abstract void
doLoad(Accumulator<ROW_OBJECT> accumulator, TaskMonitor monitor)
The basic method that all children must implement.void
fireTableChanged(javax.swing.event.TableModelEvent e)
protected TableAddRemoveStrategy<ROW_OBJECT>
getAddRemoveStrategy()
Returns the strategy to use for performing adds and removes to this table.protected java.util.List<ROW_OBJECT>
getAllData()
java.util.List<ROW_OBJECT>
getModelData()
Implementors should return the current data of the model.int
getModelIndex(ROW_OBJECT t)
Returns the model index of the given item.int
getModelRow(int viewRow)
Given a row index for the view (filtered) model, return the corresponding index in the raw (unfiltered) model.java.lang.String
getName()
Returns the name of this model.int
getRowCount()
java.util.List<ROW_OBJECT>
getRowObjects(int[] rows)
Returns the corresponding row objects for the specified rows.TableFilter<ROW_OBJECT>
getTableFilter()
Returns the filter for this model.java.util.List<ROW_OBJECT>
getUnfilteredData()
protected int
getUnfilteredIndexForRowObject(ROW_OBJECT rowObject)
Performs a quick search for the given item in the unfiltered data of this model.int
getUnfilteredRowCount()
protected ROW_OBJECT
getUnfilteredRowObjectForIndex(int row)
Returns the row object at the given index in the unfiltered data of this model; null if the index is negative or larger than the list.java.lang.Object
getValueAt(int rowIndex, int columnIndex)
The default implementation ofTableModel.getValueAt(int, int)
that calls the abstractRowObjectTableModel.getColumnValueForRow(Object, int)
.int
getViewIndex(ROW_OBJECT t)
Returns the view index of the given item.int
getViewRow(int modelRow)
Given a row index for the raw (unfiltered) model, return the corresponding index in the view (filtered) model.boolean
hasFilter()
Returns true if there is a table filter set that is not theNullTableFilter
.protected void
initializeSorting()
This method is an attempt to help models that forget to call fireTableDataChanged().boolean
isBusy()
Returns true if the model is busy.boolean
isFiltered()
boolean
isLoadIncrementally()
void
reFilter()
Triggers this class to filter the contents of the data.void
reload()
Schedules the model to completely reload its underlying data.void
removeObject(ROW_OBJECT obj)
Removes the specified object from this model and schedules an update.void
removeThreadedTableModelListener(ThreadedTableModelListener listener)
void
reSort()
Resort the table using the current sort criteria.void
setIncrementalTaskMonitor(TaskMonitor monitor)
protected void
setModelState(TableData<ROW_OBJECT> allData, TableData<ROW_OBJECT> filteredData)
void
setTableFilter(TableFilter<ROW_OBJECT> tableFilter)
Sets the givenTableFilter
on this model.protected void
sort(java.util.List<ROW_OBJECT> data, TableSortingContext<ROW_OBJECT> tableSortingContext)
A default sort method that uses theCollections.sort(List, Comparator)
method for sorting.protected void
updateNow()
void
updateObject(ROW_OBJECT obj)
Schedules an update for the specified object.-
Methods inherited from class docking.widgets.table.GDynamicColumnTableModel
addTableColumn, addTableColumn, addTableColumns, createSortComparatorForColumn, createTableColumnDescriptor, disposeDynamicColumnData, getColumn, getColumnClass, getColumnCount, getColumnDescription, getColumnDisplayName, getColumnIndex, getColumnIndex, getColumnName, getColumnSettings, getColumnSettingsDefinitions, getColumnValueForRow, getDataSource, getDefaultColumnCount, getMaxLines, getPreferredColumnWidth, getRenderer, getUniqueIdentifier, isDefaultColumn, isSortable, isVisibleByDefault, loadDiscoveredTableColumns, reloadColumns, removeTableColumn, removeTableColumns, setAllColumnSettings, stateChanged
-
Methods inherited from class docking.widgets.table.AbstractSortedTableModel
addSortListener, cleanupTableSortState, createSortingContext, getIndexForRowObject, getIndexForRowObject, getPendingSortState, getPrimarySortColumnIndex, getRowIndex, getRowObject, getTableSortState, isSorted, isSortPending, notifyModelSorted, setDefaultTableSortState, setTableSortState, sortCompleted
-
Methods inherited from class docking.widgets.table.AbstractGTableModel
getLastSelectedObjects, refresh, setLastSelectedObjects
-
Methods inherited from class javax.swing.table.AbstractTableModel
addTableModelListener, findColumn, fireTableCellUpdated, fireTableDataChanged, fireTableRowsDeleted, fireTableRowsInserted, fireTableRowsUpdated, fireTableStructureChanged, getListeners, getTableModelListeners, isCellEditable, removeTableModelListener, setValueAt
-
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
-
Methods inherited from interface docking.widgets.table.RowObjectTableModel
fireTableDataChanged, getColumnValueForRow, getRowIndex, getRowObject
-
-
-
-
Field Detail
-
allData
protected TableData<ROW_OBJECT> allData
-
filteredData
protected TableData<ROW_OBJECT> filteredData
-
-
Constructor Detail
-
ThreadedTableModel
protected ThreadedTableModel(java.lang.String modelName, ServiceProvider serviceProvider)
-
ThreadedTableModel
protected ThreadedTableModel(java.lang.String modelName, ServiceProvider serviceProvider, TaskMonitor monitor)
-
ThreadedTableModel
protected ThreadedTableModel(java.lang.String modelName, ServiceProvider serviceProvider, TaskMonitor monitor, boolean loadIncrementally)
The constructor through which all others pass.This class must be created on the Swing Thread (see
SwingUtilities.isEventDispatchThread()
).- Parameters:
modelName
- The name of the table model. This value will appear as the name of the thread that manipulates the table data.serviceProvider
- The service provider of the environment. This will be used to allow column objects to have access to services. This man not be null.monitor
- The task monitor to use when manipulating table data (i.e., loading, sorting, filtering).loadIncrementally
- When true, the table's results will be displayed as they are loaded; when false, the table's results will be displayed after all items have been loaded. Passing true is helpful for models that take a long time to run and periodically find data. Alternatively, for quick loading tables, the overhead of loading incrementally is wasteful.
-
-
Method Detail
-
isLoadIncrementally
public boolean isLoadIncrementally()
-
initializeSorting
protected void initializeSorting()
Description copied from class:AbstractSortedTableModel
This method is an attempt to help models that forget to call fireTableDataChanged(). It is expected that tables will fire the notification when they are ready to display data, even if they have that data at construction time. We put this call here so that the forgetful subclasses will have their data sorted for them the first time that this table tries to render itself.- Overrides:
initializeSorting
in classAbstractSortedTableModel<ROW_OBJECT>
-
createIncrementalLoadJob
protected IncrementalLoadJob<ROW_OBJECT> createIncrementalLoadJob()
-
doLoad
protected abstract void doLoad(Accumulator<ROW_OBJECT> accumulator, TaskMonitor monitor) throws CancelledException
The basic method that all children must implement. This is where children load their data.- Parameters:
accumulator
- the datastructure into which you should incrementally place you table row datamonitor
- the task monitor to check for cancellations and to update progress- Throws:
CancelledException
- if the task monitor has been cancelled and a call is made tomonitor.checkCancelled();
.
-
getModelData
public java.util.List<ROW_OBJECT> getModelData()
Description copied from interface:RowObjectTableModel
Implementors should return the current data of the model. For models that support filtering, this will be the filtered version of the data. Furthermore, the data should be the underlying data and not a copy, as this method will potentially sort the given data.For those subclasses using an array, you may use the
Arrays
class to create a list backed by the array (Arrays.asList(Object...)
).- Specified by:
getModelData
in interfaceRowObjectTableModel<ROW_OBJECT>
- Returns:
- the model data.
-
getUnfilteredData
public java.util.List<ROW_OBJECT> getUnfilteredData()
- Specified by:
getUnfilteredData
in interfaceRowObjectFilterModel<ROW_OBJECT>
-
getUnfilteredIndexForRowObject
protected int getUnfilteredIndexForRowObject(ROW_OBJECT rowObject)
Performs a quick search for the given item in the unfiltered data of this model. To search only for object that are visible in the GUI, useAbstractSortedTableModel.getIndexForRowObject(Object)
.- Parameters:
rowObject
- The object for which to search- Returns:
- The index for the given object; a negative value if the object is not in the list
- See Also:
AbstractSortedTableModel.getIndexForRowObject(Object)
-
getUnfilteredRowObjectForIndex
protected ROW_OBJECT getUnfilteredRowObjectForIndex(int row)
Returns the row object at the given index in the unfiltered data of this model; null if the index is negative or larger than the list. To search only for object that are visible in the GUI, useAbstractSortedTableModel.getRowObject(int)
.- Parameters:
row
- The row index for which to get a row object- Returns:
- Returns the row object at the given index in the unfiltered data of this model; null if the index is negative or larger than the list.
- See Also:
AbstractSortedTableModel.getRowObject(int)
-
createSortComparator
protected java.util.Comparator<ROW_OBJECT> createSortComparator(int columnIndex)
Description copied from class:AbstractSortedTableModel
An extension point for subclasses to insert their own comparator objects for their data. Subclasses can create comparators for a single or multiple columns, as desired.- Overrides:
createSortComparator
in classGDynamicColumnTableModel<ROW_OBJECT,DATA_SOURCE>
- Parameters:
columnIndex
- the column index- Returns:
- the comparator
-
getValueAt
public java.lang.Object getValueAt(int rowIndex, int columnIndex)
Description copied from class:AbstractSortedTableModel
The default implementation ofTableModel.getValueAt(int, int)
that calls the abstractRowObjectTableModel.getColumnValueForRow(Object, int)
.- Specified by:
getValueAt
in interfacejavax.swing.table.TableModel
- Overrides:
getValueAt
in classAbstractSortedTableModel<ROW_OBJECT>
-
sort
protected void sort(java.util.List<ROW_OBJECT> data, TableSortingContext<ROW_OBJECT> tableSortingContext)
Description copied from class:AbstractSortedTableModel
A default sort method that uses theCollections.sort(List, Comparator)
method for sorting. Implementors with reasonably sized data sets can rely on this method. For data sets that can become large, theThreadedTableModel
is the recommended base class, as it handles loading/sorting/filtering in a threaded way.- Overrides:
sort
in classAbstractSortedTableModel<ROW_OBJECT>
- Parameters:
data
- The data to be sortedtableSortingContext
- The context required to sort (it contains the sorting columns, a comparator for sorting, etc...).
-
getTableFilter
public TableFilter<ROW_OBJECT> getTableFilter()
Returns the filter for this model. The value returned from this method will not be null, but will instead be an instanceofNullTableFilter
when no filter is applied. The value returned from this method may not actually yet be applied, depending upon when the background thread finishes loading.- Specified by:
getTableFilter
in interfaceRowObjectFilterModel<ROW_OBJECT>
- Returns:
- the filter
-
hasFilter
public boolean hasFilter()
Returns true if there is a table filter set that is not theNullTableFilter
.- Returns:
- true if there is a table filter set.
-
doFilter
protected java.util.List<ROW_OBJECT> doFilter(java.util.List<ROW_OBJECT> data, TableSortingContext<ROW_OBJECT> lastSortingContext, TaskMonitor monitor) throws CancelledException
Override this to change how filtering is performed. This implementation will do nothing if aTableFilter
has not been set via a call tosetTableFilter(TableFilter)
.- Parameters:
data
- The list of data to be filtered.monitor
- the progress monitor to check for cancellation.lastSortingContext
- the comparator used to sort data. This can be used by overridden filter methods that need to query data about how the table is sorted.- Returns:
- The new filtered list of data. If no filtering takes place, then the original list should be returned.
- Throws:
CancelledException
- If the filter operation is cancelled.
-
getUnfilteredRowCount
public int getUnfilteredRowCount()
- Specified by:
getUnfilteredRowCount
in interfaceRowObjectFilterModel<ROW_OBJECT>
-
isFiltered
public boolean isFiltered()
- Specified by:
isFiltered
in interfaceRowObjectFilterModel<ROW_OBJECT>
-
setTableFilter
public void setTableFilter(TableFilter<ROW_OBJECT> tableFilter)
Sets the givenTableFilter
on this model. This table filter will then be used by this model in the defaultdoFilter(List, TableSortingContext, TaskMonitor)
method.- Specified by:
setTableFilter
in interfaceRowObjectFilterModel<ROW_OBJECT>
- Parameters:
tableFilter
- The filter to use for table filtering.
-
updateObject
public void updateObject(ROW_OBJECT obj)
Schedules an update for the specified object.- Parameters:
obj
- the object for which to schedule the update
-
addObject
public void addObject(ROW_OBJECT obj)
Adds the specified object to this model and schedules an update.- Parameters:
obj
- the object to add
-
removeObject
public void removeObject(ROW_OBJECT obj)
Removes the specified object from this model and schedules an update.Note: for this method to function correctly, the given object must compare as
Object.equals(Object)
and have the sameObject.hashCode()
as the object to be removed from the table data. This allows clients to create proxy objects to pass into this method, as long as they honor those requirements.If this model's data is sorted, then a binary search will be used to locate the item to be removed. However, for this to work, all field used to sort the data must still be available from the original object and must be the same values. If this is not true, then the binary search will not work and a brute force search will be used.
- Parameters:
obj
- the object to remove
-
updateNow
protected void updateNow()
-
setModelState
protected void setModelState(TableData<ROW_OBJECT> allData, TableData<ROW_OBJECT> filteredData)
-
getAllData
protected java.util.List<ROW_OBJECT> getAllData()
-
isBusy
public boolean isBusy()
Returns true if the model is busy. "Busy" means the model is either loading or updating.- Returns:
- true if the model is busy
-
reSort
public void reSort()
Resort the table using the current sort criteria. This is useful if the data in the table has changed and is no longer sorted properly. If the setSort method is used, nothing will happen because the table will think it is already sorted on that criteria.- Overrides:
reSort
in classAbstractSortedTableModel<ROW_OBJECT>
-
reFilter
public void reFilter()
Triggers this class to filter the contents of the data.
-
reload
public void reload()
Schedules the model to completely reload its underlying data.
-
fireTableChanged
public void fireTableChanged(javax.swing.event.TableModelEvent e)
- Overrides:
fireTableChanged
in classAbstractSortedTableModel<ROW_OBJECT>
- See Also:
AbstractTableModel.fireTableChanged(javax.swing.event.TableModelEvent)
-
dispose
public void dispose()
Disposes this model. Once a model has been disposed, it cannot be reused.- Overrides:
dispose
in classGDynamicColumnTableModel<ROW_OBJECT,DATA_SOURCE>
-
clearData
protected void clearData()
This method will clear all data and trigger fire a table data changed. Use this method to immediately clear all data. This is useful when you want to reload your table data and not have any old data hanging around being painted, which can produce odd results.
-
cancelAllUpdates
public void cancelAllUpdates()
Cancels all current and pending updates to the model. Waits until all updates have been cancelled.
-
getRowCount
public int getRowCount()
- Specified by:
getRowCount
in interfacejavax.swing.table.TableModel
- Overrides:
getRowCount
in classAbstractGTableModel<ROW_OBJECT>
- See Also:
TableModel.getRowCount()
-
getViewRow
public int getViewRow(int modelRow)
Given a row index for the raw (unfiltered) model, return the corresponding index in the view (filtered) model.- Specified by:
getViewRow
in interfaceRowObjectFilterModel<ROW_OBJECT>
- Parameters:
modelRow
- The row index that corresponds to unfiltered data- Returns:
- the index of that row in the filtered data
- See Also:
getModelRow(int)
-
getModelRow
public int getModelRow(int viewRow)
Given a row index for the view (filtered) model, return the corresponding index in the raw (unfiltered) model.- Specified by:
getModelRow
in interfaceRowObjectFilterModel<ROW_OBJECT>
- Parameters:
viewRow
- The row index that corresponds to filtered data- Returns:
- the index of that row in the unfiltered data
- See Also:
getViewRow(int)
-
getViewIndex
public int getViewIndex(ROW_OBJECT t)
Description copied from interface:RowObjectFilterModel
Returns the view index of the given item. When filtered, this is the index is the smaller, visible set of data; when unfiltered, this index is the same as that returned byRowObjectFilterModel.getModelIndex(Object)
.This operation will be O(n) unless the implementation is sorted, in which case the operation is O(log n), as it uses a binary search.
- Specified by:
getViewIndex
in interfaceRowObjectFilterModel<ROW_OBJECT>
- Parameters:
t
- the item- Returns:
- the view index
-
getModelIndex
public int getModelIndex(ROW_OBJECT t)
Description copied from interface:RowObjectFilterModel
Returns the model index of the given item. When filtered, this is the index is the larger, set of data; when unfiltered, this index is the same as that returned byRowObjectFilterModel.getModelIndex(Object)
.This operation will be O(n) unless the implementation is sorted, in which case the operation is O(log n), as it uses a binary search.
- Specified by:
getModelIndex
in interfaceRowObjectFilterModel<ROW_OBJECT>
- Parameters:
t
- the item- Returns:
- the model index
-
getName
public java.lang.String getName()
Returns the name of this model.- Specified by:
getName
in interfaceRowObjectTableModel<ROW_OBJECT>
- Returns:
- the name of this model
-
getRowObjects
public java.util.List<ROW_OBJECT> getRowObjects(int[] rows)
Returns the corresponding row objects for the specified rows.- Parameters:
rows
- the table rows- Returns:
- the corresponding database keys
-
getAddRemoveStrategy
protected TableAddRemoveStrategy<ROW_OBJECT> getAddRemoveStrategy()
Returns the strategy to use for performing adds and removes to this table. Subclasses can override this method to customize this process for their particular type of data. See the implementations ofTableAddRemoveStrategy
for details.Note: The default add/remove strategy assumes that objects to be removed will be the same instance that is in the list of this model. This allows the
Object.equals(Object)
andObject.hashCode()
to be used when removing the object from the list. If you model does not pass the same instance intoremoveObject(Object)
, then you will need to update your add/remove strategy accordingly.- Returns:
- the strategy
-
setIncrementalTaskMonitor
public void setIncrementalTaskMonitor(TaskMonitor monitor)
-
addInitialLoadListener
public void addInitialLoadListener(ThreadedTableModelListener listener)
Adds a listener that will be notified of the first table load of this model. After the initial load, the listener is removed.- Parameters:
listener
- the listener
-
addThreadedTableModelListener
public void addThreadedTableModelListener(ThreadedTableModelListener listener)
This is a way to know about updates from the table.- Parameters:
listener
- the listener to add- See Also:
addInitialLoadListener(ThreadedTableModelListener)
,removeThreadedTableModelListener(ThreadedTableModelListener)
-
removeThreadedTableModelListener
public void removeThreadedTableModelListener(ThreadedTableModelListener listener)
-
-