Author: tchemit Date: 2012-12-31 13:31:24 +0100 (Mon, 31 Dec 2012) New Revision: 133 Url: http://forge.codelutin.com/projects/tutti/repository/revisions/133 Log: - improve navigation action in cells (now not force to create a new row if at end) - improve listener api (can uninstall them too!) Modified: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/AbstractTuttiBatchTableUIHandler.java trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/species/frequency/SpeciesFrequencyUIHandler.java trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/table/AbstractTuttiTableUIHandler.java trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/table/MoveToNextEditableCellAction.java trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/table/MoveToNextEditableRowAction.java Modified: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/AbstractTuttiBatchTableUIHandler.java =================================================================== --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/AbstractTuttiBatchTableUIHandler.java 2012-12-30 19:39:00 UTC (rev 132) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/AbstractTuttiBatchTableUIHandler.java 2012-12-31 12:31:24 UTC (rev 133) @@ -114,7 +114,7 @@ TableColumnModel columnModel, AbstractTuttiTableModel<R> tableModel) { - installTableKeyListener(columnModel, table); + installTableKeyListener(columnModel, table, true); JTableFilter tableFilter = new JTableFilter(table); TableRowFilterSupport.forFilter(tableFilter).searchable(true).useTableRenderers(true).actions(true).apply(); Modified: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/species/frequency/SpeciesFrequencyUIHandler.java =================================================================== --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/species/frequency/SpeciesFrequencyUIHandler.java 2012-12-30 19:39:00 UTC (rev 132) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/species/frequency/SpeciesFrequencyUIHandler.java 2012-12-31 12:31:24 UTC (rev 133) @@ -59,6 +59,11 @@ private static final Log log = LogFactory.getLog(SpeciesFrequencyUIHandler.class); + /** + * UI. + * + * @since 0.2 + */ private final SpeciesFrequencyUI ui; public SpeciesFrequencyUIHandler(TuttiUIContext context, @@ -146,7 +151,6 @@ lengthStepCaracterics, model.getLengthStepCaracteristic()); - //TODO Should it come from PROTOCOL or config ? model.setStep(.5f); @@ -220,7 +224,7 @@ table.setModel(tableModel); table.setColumnModel(columnModel); - installTableKeyListener(columnModel, table); + installTableKeyListener(columnModel, table, true); initTable(table); } Modified: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/table/AbstractTuttiTableUIHandler.java =================================================================== --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/table/AbstractTuttiTableUIHandler.java 2012-12-30 19:39:00 UTC (rev 132) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/table/AbstractTuttiTableUIHandler.java 2012-12-31 12:31:24 UTC (rev 133) @@ -25,6 +25,7 @@ */ import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; import com.google.common.collect.Sets; import fr.ifremer.tutti.service.PersistenceService; import fr.ifremer.tutti.ui.swing.AbstractTuttiBeanUIModel; @@ -62,7 +63,6 @@ import java.awt.Component; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; -import java.awt.event.KeyListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.Enumeration; @@ -295,79 +295,13 @@ // always scroll to selected row SwingUtil.scrollToTableSelection(getTable()); + // always force to uninstall listener + uninstallTableSaveOnRowChangedSelectionListener(); + // save when row chaged and was modified - ListSelectionListener listener = new TableRowModificationListener<R>( - getTableModel(), rowMonitor) { - @Override - protected void saveSelectedRow() { - - saveSelectedRowIfNeeded(); - } - }; - table.getSelectionModel().addListSelectionListener(listener); + installTableSaveOnRowChangedSelectionListener(); } - protected final void saveSelectedRowIfNeeded() { - - R row = rowMonitor.getBean(); - - if (row != null) { - - saveSelectedRowIfRequired(rowMonitor, row); - } - } - - protected KeyListener installTableKeyListener(TableColumnModel columnModel, - JTable table) { - - AbstractTuttiTableModel<R> model = getTableModel(); - final MoveToNextEditableCellAction nextCellAction = - MoveToNextEditableCellAction.newAction(model, table); - final MoveToPreviousEditableCellAction previousCellAction = - MoveToPreviousEditableCellAction.newAction(model, table); - - final MoveToNextEditableRowAction nextRowAction = - MoveToNextEditableRowAction.newAction(model, table); - final MoveToPreviousEditableRowAction previousRowAction = - MoveToPreviousEditableRowAction.newAction(model, table); - - // Key adapter à ajouter sur les éditeurs où l'on souhaite gérer les - // touches "entrer", "gauche", "droite" de facon personnalisée. - KeyAdapter keyAdapter = new KeyAdapter() { - - @Override - public void keyPressed(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_ENTER || - e.getKeyCode() == KeyEvent.VK_RIGHT || - e.getKeyCode() == KeyEvent.VK_TAB) { - e.consume(); - nextCellAction.actionPerformed(null); - } else if (e.getKeyCode() == KeyEvent.VK_LEFT) { - e.consume(); - previousCellAction.actionPerformed(null); - } else if (e.getKeyCode() == KeyEvent.VK_UP) { - e.consume(); - previousRowAction.actionPerformed(null); - } else if (e.getKeyCode() == KeyEvent.VK_DOWN) { - e.consume(); - nextRowAction.actionPerformed(null); - } - } - }; - table.addKeyListener(keyAdapter); - - Enumeration<TableColumn> columns = columnModel.getColumns(); - while (columns.hasMoreElements()) { - TableColumn tableColumn = columns.nextElement(); - TableCellEditor cellEditor = tableColumn.getCellEditor(); - if (cellEditor instanceof NumberCellEditor) { - NumberCellEditor editor = (NumberCellEditor) cellEditor; - editor.getNumberEditor().getTextField().addKeyListener(keyAdapter); - } - } - return keyAdapter; - } - protected void addColumnToModel(TableColumnModel model, TableCellEditor editor, TableCellRenderer renderer, @@ -433,11 +367,13 @@ JComboBox comboBox = new JComboBox(); comboBox.setRenderer(newListCellRender(decorator)); + List<B> dataToList = Lists.newArrayList(data); + // add a null value at first position - if (!data.isEmpty() && data.get(0) != null) { - data.add(0, null); + if (!dataToList.isEmpty() && dataToList.get(0) != null) { + dataToList.add(0, null); } - SwingUtil.fillComboBox(comboBox, data, null); + SwingUtil.fillComboBox(comboBox, dataToList, null); ObjectToStringConverter converter = BeanUIUtil.newDecoratedObjectToStringConverter(decorator); BeanUIUtil.decorate(comboBox, converter); @@ -470,4 +406,147 @@ return result; } + //------------------------------------------------------------------------// + //-- Internal methods (listener methods) --// + //------------------------------------------------------------------------// + + private ListSelectionListener tableSelectionListener; + + private KeyAdapter keyAdapter; + + protected void installTableSaveOnRowChangedSelectionListener() { + + Preconditions.checkState( + tableSelectionListener == null, + "There is already a tableSelectionListener registred, " + + "remove it before invoking this method."); + + // create new listener + // save when row chaged and was modified + + tableSelectionListener = new TableRowModificationListener<R>( + getTableModel(), rowMonitor) { + @Override + protected void saveSelectedRow() { + + saveSelectedRowIfNeeded(); + } + }; + + if (log.isInfoEnabled()) { + log.info("Intall " + tableSelectionListener + " on tableModel " + getTableModel()); + } + + getTable().getSelectionModel().addListSelectionListener(tableSelectionListener); + } + + protected void uninstallTableSaveOnRowChangedSelectionListener() { + + if (tableSelectionListener != null) { + + if (log.isInfoEnabled()) { + log.info("Desintall " + tableSelectionListener); + } + + // there was a previous selection listener, remove it + getTable().getSelectionModel().removeListSelectionListener(tableSelectionListener); + tableSelectionListener = null; + } + } + + protected void installTableKeyListener(TableColumnModel columnModel, + JTable table, boolean canCreateRow) { + + Preconditions.checkState( + keyAdapter == null, + "There is already a tableSelectionListener registred, " + + "remove it before invoking this method."); + + AbstractTuttiTableModel<R> model = getTableModel(); + final MoveToNextEditableCellAction nextCellAction = + MoveToNextEditableCellAction.newAction(model, table, canCreateRow); + final MoveToPreviousEditableCellAction previousCellAction = + MoveToPreviousEditableCellAction.newAction(model, table); + + final MoveToNextEditableRowAction nextRowAction = + MoveToNextEditableRowAction.newAction(model, table, canCreateRow); + final MoveToPreviousEditableRowAction previousRowAction = + MoveToPreviousEditableRowAction.newAction(model, table); + + // Key adapter à ajouter sur les éditeurs où l'on souhaite gérer les + // touches "entrer", "gauche", "droite" de facon personnalisée. + keyAdapter = new KeyAdapter() { + + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ENTER || + e.getKeyCode() == KeyEvent.VK_RIGHT || + e.getKeyCode() == KeyEvent.VK_TAB) { + e.consume(); + nextCellAction.actionPerformed(null); + } else if (e.getKeyCode() == KeyEvent.VK_LEFT) { + e.consume(); + previousCellAction.actionPerformed(null); + } else if (e.getKeyCode() == KeyEvent.VK_UP) { + e.consume(); + previousRowAction.actionPerformed(null); + } else if (e.getKeyCode() == KeyEvent.VK_DOWN) { + e.consume(); + nextRowAction.actionPerformed(null); + } + } + }; + + if (log.isInfoEnabled()) { + log.info("Intall " + keyAdapter); + } + + table.addKeyListener(keyAdapter); + + Enumeration<TableColumn> columns = columnModel.getColumns(); + while (columns.hasMoreElements()) { + TableColumn tableColumn = columns.nextElement(); + TableCellEditor cellEditor = tableColumn.getCellEditor(); + if (cellEditor instanceof NumberCellEditor) { + NumberCellEditor editor = (NumberCellEditor) cellEditor; + editor.getNumberEditor().getTextField().addKeyListener(keyAdapter); + } + } + } + + protected void uninstallTableKeyListener() { + + + if (keyAdapter != null) { + + if (log.isInfoEnabled()) { + log.info("Desintall " + keyAdapter); + } + + getTable().removeKeyListener(keyAdapter); + + TableColumnModel columnModel = getTable().getColumnModel(); + Enumeration<TableColumn> columns = columnModel.getColumns(); + while (columns.hasMoreElements()) { + TableColumn tableColumn = columns.nextElement(); + TableCellEditor cellEditor = tableColumn.getCellEditor(); + if (cellEditor instanceof NumberCellEditor) { + NumberCellEditor editor = (NumberCellEditor) cellEditor; + editor.getNumberEditor().getTextField().removeKeyListener(keyAdapter); + } + } + keyAdapter = null; + } + } + + protected final void saveSelectedRowIfNeeded() { + + R row = rowMonitor.getBean(); + + if (row != null) { + + saveSelectedRowIfRequired(rowMonitor, row); + } + } + } Modified: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/table/MoveToNextEditableCellAction.java =================================================================== --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/table/MoveToNextEditableCellAction.java 2012-12-30 19:39:00 UTC (rev 132) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/table/MoveToNextEditableCellAction.java 2012-12-31 12:31:24 UTC (rev 133) @@ -44,12 +44,20 @@ private static final Log log = LogFactory.getLog(MoveToNextEditableCellAction.class); - public static <M extends AbstractTuttiTableModel> MoveToNextEditableCellAction<M> newAction(M model, JTable table) { - return new MoveToNextEditableCellAction<M>(model, table); + public static <M extends AbstractTuttiTableModel> MoveToNextEditableCellAction<M> newAction(M model, JTable table, boolean canCreateRow) { + return new MoveToNextEditableCellAction<M>(model, table, canCreateRow); } - protected MoveToNextEditableCellAction(M model, JTable table) { + /** + * Can create new row if reach the end of editable cells ? + * + * @since 0.3 + */ + private final boolean canCreateRow; + + protected MoveToNextEditableCellAction(M model, JTable table, boolean canCreateRow) { super(model, table); + this.canCreateRow = canCreateRow; } @Override @@ -81,8 +89,14 @@ if (currentRow == rowCount) { - // create a new row in model - addNewRow(); + if (canCreateRow) { + // create a new row in model + addNewRow(); + } else { + + // can not create new row, so do nothing + break; + } } } Modified: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/table/MoveToNextEditableRowAction.java =================================================================== --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/table/MoveToNextEditableRowAction.java 2012-12-30 19:39:00 UTC (rev 132) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/table/MoveToNextEditableRowAction.java 2012-12-31 12:31:24 UTC (rev 133) @@ -44,12 +44,20 @@ private static final Log log = LogFactory.getLog(MoveToNextEditableRowAction.class); - public static <M extends AbstractTuttiTableModel> MoveToNextEditableRowAction<M> newAction(M model, JTable table) { - return new MoveToNextEditableRowAction<M>(model, table); + public static <M extends AbstractTuttiTableModel> MoveToNextEditableRowAction<M> newAction(M model, JTable table, boolean canCreateRow) { + return new MoveToNextEditableRowAction<M>(model, table, canCreateRow); } - protected MoveToNextEditableRowAction(M model, JTable table) { + /** + * Can create new row if reach the end of editable cells ? + * + * @since 0.3 + */ + private final boolean canCreateRow; + + protected MoveToNextEditableRowAction(M model, JTable table, boolean canCreateRow) { super(model, table); + this.canCreateRow = canCreateRow; } @Override @@ -64,17 +72,23 @@ } currentRow++; + boolean canSelect = true; if (currentRow >= getRowCount()) { if (log.isDebugEnabled()) { log.debug("No next row"); } + if (canCreateRow) { + // create a new row in model + addNewRow(); + } else { + canSelect = false; + } + } - // create a new row in model - addNewRow(); + if (canSelect) { + doSelectCell(currentRow, currentColumn); } - doSelectCell(currentRow, currentColumn); - } else { if (log.isDebugEnabled()) { log.debug("Cell not editable at " +