![JAR search and dependency download from the Maven repository](/logo.png)
ca.odell.glazedlists.swing.TreeTableUtilities Maven / Gradle / Ivy
/* Glazed Lists (c) 2003-2006 */
/* http://publicobject.com/glazedlists/ publicobject.com,*/
/* O'Dell Engineering Ltd.*/
package ca.odell.glazedlists.swing;
import ca.odell.glazedlists.TreeList;
import java.awt.Component;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
/**
* A collection of static utility methods to ease the burdens of implementing
* correct TreeTable behaviour in Swing.
*
* @author James Lemieux
*/
public class TreeTableUtilities {
/**
* Assuming the mouseEvent
occurred over a {@link JTable},
* retrieve the row over which the event occurred.
*
* @param mouseEvent a MouseEvent whose source is a {@link JTable}
* @return the index of the table row over which the event occurred
*/
static int rowAtPoint(MouseEvent mouseEvent) {
final JTable table = (JTable) mouseEvent.getSource();
final Point clickPoint = mouseEvent.getPoint();
return table.rowAtPoint(clickPoint);
}
/**
* Given a mouseEvent
which occurred over a {@link JTable},
* and further assuming that the column is a hierarchical column that
*
* @param mouseEvent a MouseEvent whose source is a {@link JTable}
* @return the TreeTableCellPanel returned by the renderer, or
* null
if the click was outside the table or the
* renderer does not return a TreeTableCellPanel
*/
public static TreeTableCellPanel prepareRenderer(MouseEvent mouseEvent) {
// extract information about the location of the click
final JTable table = (JTable) mouseEvent.getSource();
final Point clickPoint = mouseEvent.getPoint();
final int row = table.rowAtPoint(clickPoint);
final int column = table.columnAtPoint(clickPoint);
// if the coordinates are not within the table, bail early
if (row == -1 || column == -1)
return null;
// translate the click to be relative to the cellRect (and thus its rendered component)
final Rectangle cellRect = table.getCellRect(row, column, true);
// get the component rendered for the cell
final Component renderedComponent = table.prepareRenderer(table.getCellRenderer(row, column), row, column);
// if the component is not a TreeTableCellPanel, bail early
if (!(renderedComponent instanceof TreeTableCellPanel))
return null;
// layout the panel within its bounds
final TreeTableCellPanel renderedPanel = (TreeTableCellPanel) renderedComponent;
renderedPanel.setBounds(cellRect);
renderedPanel.doLayout();
return renderedPanel;
}
/**
* This method toggles the expanded/collapsed state of the given
* row
in the given treeList
without altering the
* row selections within the given table
, if possible. In
* practice, this can only be achieved if the table
uses an
* {@link AdvancedListSelectionModel} as its selection model.
*
* This method also turns off JTable's JTable.autoStartsEdit
* client property during the toggling to stop any attempts at beginning a
* cell edit. This behaviour is only relevant when the toggling action is
* triggered by the keyboard. We do this to avoid invoking two behaviours
* with only a single keystroke: toggling the expand/collapse state AND
* starting a cell edit.
*
* A Runnable is returned which, when executed, restores the settings in
* the EventSelectionModel and the JTable's client property. It is up to
* the caller to decide when the appropriate time to re-enable those
* settings may be and execute the Runnable.
*/
static Runnable toggleExpansion(JTable table, TreeList treeList, int row) {
final RestoreStateRunnable restoreStateRunnable = new RestoreStateRunnable(table);
final AdvancedListSelectionModel selectionModel = restoreStateRunnable.getEventSelectionModel();
// disable the EventSelectionModel so it does not respect our attempted change to row selection (due to treeList.toggleExpanded(row);)
if (selectionModel != null)
selectionModel.setEnabled(false);
// disable attempts to start an edit because of a keystroke
table.putClientProperty("JTable.autoStartsEdit", Boolean.FALSE);
treeList.toggleExpanded(row);
// return a Runnable that restores the state of the table and selection model
return restoreStateRunnable;
}
/**
* Instances of this Runnable restore a captured state of a JTable and its
* EventSelectionModel at some point in the future (when it is executed)
*/
private static class RestoreStateRunnable implements Runnable {
private final JTable table;
private final Boolean autoStartsEdit;
private final AdvancedListSelectionModel eventSelectionModel;
private final boolean eventSelectionModelEnabled;
public RestoreStateRunnable(JTable table) {
this.table = table;
final ListSelectionModel selectionModel = table.getSelectionModel();
eventSelectionModel = selectionModel instanceof AdvancedListSelectionModel ? (AdvancedListSelectionModel) selectionModel : null;
eventSelectionModelEnabled = eventSelectionModel != null && eventSelectionModel.getEnabled();
autoStartsEdit = (Boolean) table.getClientProperty("JTable.autoStartsEdit");
}
public AdvancedListSelectionModel getEventSelectionModel() {
return eventSelectionModel;
}
@Override
public void run() {
table.putClientProperty("JTable.autoStartsEdit", autoStartsEdit);
if (eventSelectionModel != null)
eventSelectionModel.setEnabled(eventSelectionModelEnabled);
}
}
}