All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ca.odell.glazedlists.swt.DefaultEventKTableModel Maven / Gradle / Ivy

/* Glazed Lists                                                 (c) 2003-2012 */
/* http://publicobject.com/glazedlists/                      publicobject.com,*/
/*                                                     O'Dell Engineering Ltd.*/
package ca.odell.glazedlists.swt;

import ca.odell.glazedlists.EventList;
import ca.odell.glazedlists.event.ListEvent;
import ca.odell.glazedlists.event.ListEventListener;
import ca.odell.glazedlists.gui.TableFormat;
import ca.odell.glazedlists.gui.WritableTableFormat;

import org.eclipse.swt.graphics.Point;

import de.kupzog.ktable.KTable;
import de.kupzog.ktable.KTableCellEditor;
import de.kupzog.ktable.KTableCellRenderer;
import de.kupzog.ktable.KTableModel;

/**
 * A {@link KTableModel} that displays an {@link EventList}. Each element of the
 * {@link EventList} corresponds to a row in the {@link KTableModel}. The columns
 * of the table must be specified using a {@link TableFormat}.
 *
 * 

* * * * * * *
Extension: KTable
This Glazed Lists extension requires the third party library KTable.
Tested Version:2.1.2
Home page:http://ktable.sourceforge.net/
License:Eclipse Public License
* *

The DefaultEventKTableModel class is not thread-safe. Unless otherwise * noted, all methods are only safe to be called from the SWT event dispatch thread. * To do this programmatically, use {@link org.eclipse.swt.widgets.Display#asyncExec(Runnable)}. * * @author Jesse Wilson * @author Holger Brands */ public class DefaultEventKTableModel implements KTableModel, ListEventListener { /** the table we're providing the model for */ private KTable table; /** indicator to dispose source list */ private boolean disposeSource; /** the proxy moves events to the SWT thread */ protected EventList source; /** maps row objects to cell values */ private KTableFormat kTableFormat; /** * Create a new {@link DefaultEventKTableModel} that uses elements from the * specified {@link EventList} as rows, and the specified {@link TableFormat} * to divide row objects across columns. * * @param table the KTable the model is created for * @param source the {@link EventList} * @param tableFormat provides logic to divide row objects across columns. * If the value implements the {@link KTableFormat} interface, those * methods will be used to provide further details such as cell renderers, * cell editors and row heights. */ public DefaultEventKTableModel(KTable table, EventList source, TableFormat tableFormat) { this(table, source, tableFormat, false); } /** * Create a new {@link DefaultEventKTableModel} that uses elements from the * specified {@link EventList} as rows, and the specified {@link TableFormat} * to divide row objects across columns. * * @param table the KTable the model is created for * @param source the {@link EventList} * @param tableFormat provides logic to divide row objects across columns. * If the value implements the {@link KTableFormat} interface, those * methods will be used to provide further details such as cell renderers, * cell editors and row heights. * @param disposeSource true if the source list should be disposed when disposing * this model, false otherwise * */ protected DefaultEventKTableModel(KTable table, EventList source, TableFormat tableFormat, boolean disposeSource) { this.disposeSource = disposeSource; this.table = table; this.source = source; // this TableFormat supports KTable directly if(tableFormat instanceof KTableFormat) { this.kTableFormat = (KTableFormat)tableFormat; // adapt a regular TableFormat for use with KTable } else { this.kTableFormat = new TableFormatKTableFormat(tableFormat); } // listen for events on the SWT display thread this.source.addListEventListener(this); } /** {@inheritDoc} */ @Override public void listChanged(ListEvent listChanges) { // KTable has no fine-grained event notification, // so each time the data changes we'll probably break // selection. Hopefully we can resolve this problem // in the future by saving selection and adjusting it // as the model changes table.redraw(); } /** {@inheritDoc} */ @Override public Object getContentAt(int column, int row) { // get header content if(row < getFixedHeaderRowCount()) { return kTableFormat.getColumnHeaderValue(row, column); // get regular cell content } else { source.getReadWriteLock().readLock().lock(); try { return kTableFormat.getColumnValue(source.get(row - getFixedHeaderRowCount()), column); } finally { source.getReadWriteLock().readLock().unlock(); } } } /** {@inheritDoc} */ @Override public String getTooltipAt(int column, int row) { // headers have no tooltips if(row < getFixedHeaderRowCount()) { return null; // get regular row tooltips } else { source.getReadWriteLock().readLock().lock(); try { return kTableFormat.getColumnTooltip(source.get(row - getFixedHeaderRowCount()), column); } finally { source.getReadWriteLock().readLock().unlock(); } } } /** {@inheritDoc} */ @Override public KTableCellEditor getCellEditor(int column, int row) { // header rows aren't editable if(row < getFixedHeaderRowCount()) { return null; // regular rows are editable if the tableformat is writable } else if(kTableFormat instanceof WritableTableFormat) { source.getReadWriteLock().readLock().lock(); try { Object baseObject = source.get(row); return kTableFormat.getColumnEditor(baseObject, column); } finally { source.getReadWriteLock().readLock().unlock(); } // this table isn't editable } else { return null; } } /** {@inheritDoc} */ @Override public void setContentAt(int column, int row, Object value) { // header rows aren't editable if(row < getFixedHeaderRowCount()) { throw new UnsupportedOperationException("Unexpected set() on column header"); // regular rows are editable if the tableformat is writable } else if(kTableFormat instanceof WritableTableFormat) { source.getReadWriteLock().readLock().lock(); try { WritableTableFormat writableTableFormat = (WritableTableFormat)kTableFormat; Object baseObject = source.get(row - getFixedHeaderRowCount()); Object updatedObject = writableTableFormat.setColumnValue(baseObject, value, column); if(updatedObject != null) { source.set(row - getFixedHeaderRowCount(), updatedObject); } } finally { source.getReadWriteLock().readLock().unlock(); } // this table isn't editable } else { throw new UnsupportedOperationException("Unexpected set() on read-only table"); } } /** {@inheritDoc} */ @Override public KTableCellRenderer getCellRenderer(int column, int row) { // headers get the default renderer if(row < getFixedHeaderRowCount()) { return KTableCellRenderer.defaultRenderer; // regular rows may have a custom renderer } else { source.getReadWriteLock().readLock().lock(); try { return kTableFormat.getColumnRenderer(source.get(row - getFixedHeaderRowCount()), column); } finally { source.getReadWriteLock().readLock().unlock(); } } } /** {@inheritDoc} */ @Override public Point belongsToCell(int column, int row) { // no spanning by default return new Point(column, row); } /** {@inheritDoc} */ @Override public int getRowCount() { // a row for every list element, plus the headers source.getReadWriteLock().readLock().lock(); try { return source.size() + getFixedHeaderRowCount(); } finally { source.getReadWriteLock().readLock().unlock(); } } /** {@inheritDoc} */ @Override public int getFixedHeaderRowCount() { return kTableFormat.getFixedHeaderRowCount(); } /** {@inheritDoc} */ @Override public int getFixedSelectableRowCount() { return kTableFormat.getFixedSelectableColumnCount(); } /** {@inheritDoc} */ @Override public int getColumnCount() { return kTableFormat.getColumnCount(); } /** {@inheritDoc} */ @Override public int getFixedHeaderColumnCount() { return kTableFormat.getFixedHeaderColumnCount(); } /** {@inheritDoc} */ @Override public int getFixedSelectableColumnCount() { return kTableFormat.getFixedSelectableColumnCount(); } /** {@inheritDoc} */ @Override public int getColumnWidth(int col) { return kTableFormat.getColumnWidth(col); } /** {@inheritDoc} */ @Override public boolean isColumnResizable(int col) { return kTableFormat.isColumnResizable(col); } /** {@inheritDoc} */ @Override public void setColumnWidth(int col, int width) { kTableFormat.setColumnWidth(col, width); } /** {@inheritDoc} */ @Override public int getRowHeight(int row) { // header row height if(row < getFixedHeaderRowCount()) { return 20; // regular row height } else if(row < getRowCount()) { source.getReadWriteLock().readLock().lock(); try { return kTableFormat.getRowHeight(source.get(row - getFixedHeaderRowCount())); } finally { source.getReadWriteLock().readLock().unlock(); } // KTable queries for heights beyond the table's rows } else { return 20; } } /** {@inheritDoc} */ @Override public boolean isRowResizable(int row) { // header rows are not resizable if(row < getFixedHeaderRowCount()) { return false; // regular rows may be resizable } else { source.getReadWriteLock().readLock().lock(); try { return kTableFormat.isRowResizable(source.get(row - getFixedHeaderRowCount())); } finally { source.getReadWriteLock().readLock().unlock(); } } } /** {@inheritDoc} */ @Override public int getRowHeightMinimum() { return kTableFormat.getRowHeightMinimum(); } /** {@inheritDoc} */ @Override public void setRowHeight(int row, int value) { // header rows are not resizable if(row < getFixedHeaderRowCount()) { return; // regular rows may be resizable } else { source.getReadWriteLock().readLock().lock(); try { kTableFormat.setRowHeight(source.get(row - getFixedHeaderRowCount()), value); } finally { source.getReadWriteLock().readLock().unlock(); } } } /** * Releases the resources consumed by this {@link DefaultEventKTableModel} so that it * may eventually be garbage collected. * *

A {@link DefaultEventKTableModel} will be garbage collected without a call to * {@link #dispose()}, but not before its source {@link EventList} is garbage * collected. By calling {@link #dispose()}, you allow the {@link DefaultEventKTableModel} * to be garbage collected before its source {@link EventList}. This is * necessary for situations where a {@link DefaultEventKTableModel} is short-lived but * its source {@link EventList} is long-lived. * *

Warning: It is an error * to call any method on a {@link DefaultEventKTableModel} after it has been disposed. */ public void dispose() { source.removeListEventListener(this); if (disposeSource) { source.dispose(); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy