package beast.app.tools; import java.awt.Component; import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import javax.swing.JTable; import javax.swing.table.TableCellEditor; // TODO: check whetehr this is still relevant. Last complaint was at 16-JUN-2011! /** * This class is a workaround for a bug in Java (4503845) * see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4503845 * Although the state appears as fixed, it does not yet work on 1.5 * (see the comments at the end on the previous page) * <p/> * The bug refers to tables with editing cells. When the user interacts * with other UI element -or other cell in the table-, the editor component * should receive a stopCellEditing call. * This does not happen if the user selects a UI element outside the table. * <p/> * For example: * - A dialog contains a table and a Cancel button that, before closing, * verifies whether there are changes to save. * -The user is modifying one cell and then presses the Cancel button * -Then the cell editor does not receive an stopCellEditing call, so * there seems to be no changes to save! * <p/> * A basic solution for this last example would be to call to * table.getCellEditor().stopCellEditing() when reacting to events on the * Cancel button, but this call should be made on every event handler for * each UI element! * <p/> * This class works by listening to focus events when a cell editor is selected. * If the focus is transfered to any place outside the table, it calls to * stopCellEditing() * Why is it not enough to check the focus on just the editor component? * => Because the TableCellEditor could be composed of multiple Components */ public class TableEditorStopper extends FocusAdapter implements PropertyChangeListener { public static void ensureEditingStopWhenTableLosesFocus(JTable table) { new TableEditorStopper(table); } private TableEditorStopper(JTable table) { this.table = table; table.addPropertyChangeListener("tableCellEditor", this); } @Override public void propertyChange(PropertyChangeEvent evt) { if (focused != null) { focused.removeFocusListener(this); } focused = table.getEditorComponent(); if (focused != null) { focused.addFocusListener(this); } } @Override public void focusLost(FocusEvent e) { if (focused != null) { focused.removeFocusListener(this); focused = e.getOppositeComponent(); if (table == focused || table.isAncestorOf(focused)) { focused.addFocusListener(this); } else { focused = null; TableCellEditor editor = table.getCellEditor(); if (editor != null) { editor.stopCellEditing(); } } } } private Component focused; private JTable table; }