Author: Bavencoff Date: 2013-06-12 18:03:34 +0200 (Wed, 12 Jun 2013) New Revision: 3680 Url: http://chorem.org/projects/lima/repository/revisions/3680 Log: user experience Added: trunk/lima-swing/src/main/java/org/chorem/lima/ui/celleditor/DateTableCellRenderer.java trunk/lima-swing/src/main/java/org/chorem/lima/ui/celleditor/EntryTableCellRenderer.java trunk/lima-swing/src/main/java/org/chorem/lima/ui/celleditor/StringTableCellEditor.java Modified: trunk/lima-swing/src/main/java/org/chorem/lima/ui/celleditor/AccountTableCellEditor.java trunk/lima-swing/src/main/java/org/chorem/lima/ui/celleditor/AccountTableCellRenderer.java trunk/lima-swing/src/main/java/org/chorem/lima/ui/celleditor/BigDecimalTableCellEditor.java trunk/lima-swing/src/main/java/org/chorem/lima/ui/celleditor/BigDecimalTableCellRenderer.java trunk/lima-swing/src/main/java/org/chorem/lima/ui/celleditor/EmptyCellRenderer.java trunk/lima-swing/src/main/java/org/chorem/lima/ui/financialtransaction/FinancialTransactionTable.java trunk/lima-swing/src/main/java/org/chorem/lima/ui/financialtransaction/FinancialTransactionTableModel.java trunk/lima-swing/src/main/java/org/chorem/lima/ui/financialtransaction/FinancialTransactionView.jaxx trunk/lima-swing/src/main/java/org/chorem/lima/ui/financialtransaction/FinancialTransactionViewHandler.java trunk/lima-swing/src/main/resources/i18n/lima-swing_en_GB.properties trunk/lima-swing/src/main/resources/i18n/lima-swing_fr_FR.properties Modified: trunk/lima-swing/src/main/java/org/chorem/lima/ui/celleditor/AccountTableCellEditor.java =================================================================== --- trunk/lima-swing/src/main/java/org/chorem/lima/ui/celleditor/AccountTableCellEditor.java 2013-06-07 16:09:48 UTC (rev 3679) +++ trunk/lima-swing/src/main/java/org/chorem/lima/ui/celleditor/AccountTableCellEditor.java 2013-06-12 16:03:34 UTC (rev 3680) @@ -117,7 +117,7 @@ } } keyPressed = false; - return !(evt instanceof MouseEvent) || ((MouseEvent) evt).getClickCount() == 2; + return !(evt instanceof MouseEvent) || ((MouseEvent) evt).getClickCount() == 1; } Modified: trunk/lima-swing/src/main/java/org/chorem/lima/ui/celleditor/AccountTableCellRenderer.java =================================================================== --- trunk/lima-swing/src/main/java/org/chorem/lima/ui/celleditor/AccountTableCellRenderer.java 2013-06-07 16:09:48 UTC (rev 3679) +++ trunk/lima-swing/src/main/java/org/chorem/lima/ui/celleditor/AccountTableCellRenderer.java 2013-06-12 16:03:34 UTC (rev 3680) @@ -5,9 +5,8 @@ /** * @author Sylvain Bavencoff <bavencoff@codelutin.com> */ -public class AccountTableCellRenderer extends EmptyCellRenderer { +public class AccountTableCellRenderer extends EntryTableCellRenderer { - @Override public void setValue(Object value) { Object result = value; @@ -18,5 +17,4 @@ super.setValue(result); } - } Modified: trunk/lima-swing/src/main/java/org/chorem/lima/ui/celleditor/BigDecimalTableCellEditor.java =================================================================== --- trunk/lima-swing/src/main/java/org/chorem/lima/ui/celleditor/BigDecimalTableCellEditor.java 2013-06-07 16:09:48 UTC (rev 3679) +++ trunk/lima-swing/src/main/java/org/chorem/lima/ui/celleditor/BigDecimalTableCellEditor.java 2013-06-12 16:03:34 UTC (rev 3680) @@ -29,33 +29,23 @@ import org.chorem.lima.LimaConfig; import org.chorem.lima.LimaContext; -import javax.swing.DefaultCellEditor; -import javax.swing.JTextField; -import javax.swing.SwingConstants; -import javax.swing.event.AncestorEvent; -import javax.swing.event.AncestorListener; -import java.awt.event.FocusEvent; -import java.awt.event.FocusListener; +import javax.swing.*; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; import java.math.BigDecimal; /** * @author sletellier <letellier@codelutin.com> * @author mallon <mallon@codelutin.com> */ -public class BigDecimalTableCellEditor extends DefaultCellEditor { +public class BigDecimalTableCellEditor extends StringTableCellEditor { - protected int row; protected String comma = ""; private static final Log log = LogFactory.getLog(BigDecimalTableCellEditor.class); public BigDecimalTableCellEditor() { - super(new JTextField()); - setClickCountToStart(1); + super(); getComponent().setHorizontalAlignment(SwingConstants.RIGHT); getComponent().addKeyListener(new KeyListener() { @Override @@ -73,62 +63,9 @@ limitComma(e); } }); - getComponent().addFocusListener(new FocusListener() { - - @Override - public void focusGained(FocusEvent event) { - runEdition(); - } - - @Override - public void focusLost(FocusEvent event) { - // nothing to do - } - }); - getComponent().addAncestorListener(new AncestorListener() { - - @Override - public void ancestorAdded(AncestorEvent event) { - runEdition(); - } - - @Override - public void ancestorRemoved(AncestorEvent event) { - // nothing to do - } - - @Override - public void ancestorMoved(AncestorEvent event) { - // nothing to do - } - }); - getComponent().addPropertyChangeListener(new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - runEdition(); - } - }); } - @Override - public JTextField getComponent() { - return (JTextField) super.getComponent(); - } - /** - * Two kinds of edition, with LimaConfig value - * */ - public void runEdition() { - String comportmentEditingCell = LimaConfig.getInstance().getComportmentEditingCell(); - if (comportmentEditingCell.equals("ALL")) { - getComponent().selectAll(); - } else { - int textFieldSize = getComponent().getText().length(); - getComponent().select(textFieldSize, textFieldSize); - } - } - - /** * Split decimal with scale config * @return bigDecimal value * */ Modified: trunk/lima-swing/src/main/java/org/chorem/lima/ui/celleditor/BigDecimalTableCellRenderer.java =================================================================== --- trunk/lima-swing/src/main/java/org/chorem/lima/ui/celleditor/BigDecimalTableCellRenderer.java 2013-06-07 16:09:48 UTC (rev 3679) +++ trunk/lima-swing/src/main/java/org/chorem/lima/ui/celleditor/BigDecimalTableCellRenderer.java 2013-06-12 16:03:34 UTC (rev 3680) @@ -27,15 +27,13 @@ import org.chorem.lima.LimaConfig; import org.chorem.lima.LimaContext; -import javax.swing.JTable; -import javax.swing.SwingConstants; -import javax.swing.table.DefaultTableCellRenderer; -import java.awt.Component; +import javax.swing.*; +import java.awt.*; import java.math.BigDecimal; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; -public class BigDecimalTableCellRenderer extends DefaultTableCellRenderer { +public class BigDecimalTableCellRenderer extends EntryTableCellRenderer { private static final long serialVersionUID = -2499433026151065390L; @@ -46,11 +44,11 @@ public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { - super.getTableCellRendererComponent( + JLabel myCell = (JLabel) super.getTableCellRendererComponent( table, value, isSelected, hasFocus, row, column); - setHorizontalAlignment(SwingConstants.RIGHT); - setValue(value); - return this; + myCell.setHorizontalAlignment(SwingConstants.RIGHT); + + return myCell; } public void setValue(Object aValue) { Added: trunk/lima-swing/src/main/java/org/chorem/lima/ui/celleditor/DateTableCellRenderer.java =================================================================== --- trunk/lima-swing/src/main/java/org/chorem/lima/ui/celleditor/DateTableCellRenderer.java (rev 0) +++ trunk/lima-swing/src/main/java/org/chorem/lima/ui/celleditor/DateTableCellRenderer.java 2013-06-12 16:03:34 UTC (rev 3680) @@ -0,0 +1,19 @@ +package org.chorem.lima.ui.celleditor; + +import java.text.DateFormat; +import java.util.Date; + +/** + * @author Sylvain Bavencoff <bavencoff@codelutin.com> + */ +public class DateTableCellRenderer extends EntryTableCellRenderer { + + protected void setValue(Object value) { + if (value instanceof Date) { + DateFormat format = DateFormat.getDateInstance(DateFormat.MEDIUM); + super.setValue(format.format((Date) value)); + } else { + super.setValue(value); + } + } +} Modified: trunk/lima-swing/src/main/java/org/chorem/lima/ui/celleditor/EmptyCellRenderer.java =================================================================== --- trunk/lima-swing/src/main/java/org/chorem/lima/ui/celleditor/EmptyCellRenderer.java 2013-06-07 16:09:48 UTC (rev 3679) +++ trunk/lima-swing/src/main/java/org/chorem/lima/ui/celleditor/EmptyCellRenderer.java 2013-06-12 16:03:34 UTC (rev 3680) @@ -24,14 +24,9 @@ */ package org.chorem.lima.ui.celleditor; -import javax.swing.JLabel; -import javax.swing.JTable; -import javax.swing.UIManager; -import javax.swing.border.Border; -import javax.swing.border.EmptyBorder; +import javax.swing.*; import javax.swing.table.DefaultTableCellRenderer; -import java.awt.Color; -import java.awt.Component; +import java.awt.*; /** * Renderer qui affiche la valeur de la cellule (toString()) en permettant de @@ -59,30 +54,21 @@ public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { - - //Create a new JLabel to avoid colouring only when row is selected - JLabel mycell = new JLabel(); - mycell.setOpaque(true); - setBorder(new EmptyBorder(1, 1, 1, 1)); - setName("Table.cellRenderer"); - mycell.setBackground(Color.WHITE); - mycell.setForeground(Color.BLACK); - //Setting default foreGround and backGround colours when isSelected - if (isSelected) { - mycell.setForeground(table.getSelectionForeground()); - mycell.setBackground(table.getSelectionBackground()); - } - //Setting default foreGround and backGround colours when hasFocus - if (hasFocus) { - Border border = null; + + Component component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + + if (table.isCellEditable(row, column) + && (value == null + || (value instanceof String) && ((String) value).isEmpty() + ) + ) { + setBackground(new Color(255, 198, 209)); + } else { if (isSelected) { - border = UIManager.getBorder("Table.focusSelectedCellHighlightBorder"); + setForeground(new Color(0, 0, 0)); } - if (border == null) { - border = UIManager.getBorder("Table.focusCellHighlightBorder"); - } - mycell.setBorder(border); } + if (table.isCellEditable(row, column)) { // true for voucher and description // false for Account Class @@ -90,14 +76,15 @@ // else setText if (value instanceof String) { if (String.valueOf(value) == null || String.valueOf(value).isEmpty()) { - mycell.setBackground(new Color(255, 198, 209)); + component.setBackground(new Color(255, 198, 209)); } } else { - mycell.setBackground(new Color(255, 198, 209)); + if (value == null) { + component.setBackground(new Color(255, 198, 209)); + } } } - setValue(value); - return mycell; + return this; } } Added: trunk/lima-swing/src/main/java/org/chorem/lima/ui/celleditor/EntryTableCellRenderer.java =================================================================== --- trunk/lima-swing/src/main/java/org/chorem/lima/ui/celleditor/EntryTableCellRenderer.java (rev 0) +++ trunk/lima-swing/src/main/java/org/chorem/lima/ui/celleditor/EntryTableCellRenderer.java 2013-06-12 16:03:34 UTC (rev 3680) @@ -0,0 +1,104 @@ +package org.chorem.lima.ui.celleditor; + +import com.google.common.base.Preconditions; +import org.chorem.lima.ui.financialtransaction.FinancialTransactionTable; +import org.chorem.lima.ui.financialtransaction.FinancialTransactionTableModel; +import sun.swing.DefaultLookup; + +import javax.swing.*; +import javax.swing.border.Border; +import javax.swing.border.EmptyBorder; +import javax.swing.table.TableCellRenderer; +import java.awt.*; +import java.io.Serializable; + +/** + * @author Sylvain Bavencoff <bavencoff@codelutin.com> + */ +public class EntryTableCellRenderer implements TableCellRenderer, Serializable { + + private String text = null; + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + //Create a new JLabel to avoid colouring only when row is selected + + Preconditions.checkState(table instanceof FinancialTransactionTable); + + JLabel myCell = new JLabel(); + myCell.setOpaque(true); + myCell.setBorder(new EmptyBorder(1, 1, 1, 1)); + myCell.setName("Table.entryCellRenderer"); + + Color background = Color.WHITE; + Color foreground = Color.BLACK; + + FinancialTransactionTableModel model = (FinancialTransactionTableModel) ((FinancialTransactionTable)table).getModel(); + + /*JTable.DropLocation dropLocation = table.getDropLocation(); + if (dropLocation != null + && !dropLocation.isInsertRow() + && !dropLocation.isInsertColumn() + && dropLocation.getRow() == row + && dropLocation.getColumn() == column) { + + background = DefaultLookup.getColor(myCell, myCell.getUI(), "Table.dropCellForeground"); + foreground = DefaultLookup.getColor(myCell, myCell.getUI(), "Table.dropCellBackground"); + + isSelected = true; + } */ + + if (isSelected) { + foreground = table.getSelectionForeground(); + background = table.getSelectionBackground(); + } else { + Color alternateColor = DefaultLookup.getColor(myCell, myCell.getUI(), "Table.alternateRowColor"); + if (alternateColor != null && model.getIndexTransaction(row) % 2 != 0) { + background = alternateColor; + } + } + + if (table.isCellEditable(row, column) + && (value == null + || (value instanceof String) && ((String) value).isEmpty() + ) + ) { + background = new Color(255, 198, 209); + } + + if (model.getBalanceTransactionInRow(row).signum() != 0) { + foreground = new Color(240, 30, 30); + } + + myCell.setBackground(background); + myCell.setForeground(foreground); + + if (hasFocus) { + Border border = null; + if (isSelected) { + border = DefaultLookup.getBorder(myCell, myCell.getUI(), "Table.focusSelectedCellHighlightBorder"); + } + if (border == null) { + border = DefaultLookup.getBorder(myCell, myCell.getUI(), "Table.focusCellHighlightBorder"); + } + myCell.setBorder(border); + + } else { + Border border = DefaultLookup.getBorder(myCell, myCell.getUI(), "Table.cellNoFocusBorder"); + if (border == null) { + border = new EmptyBorder(1, 1, 1, 1); + } + myCell.setBorder(border); + } + + setValue(value); + + myCell.setText(text); + + return myCell; + } + + protected void setValue(Object value) { + this.text = (value == null) ? "" : value.toString(); + } + } Added: trunk/lima-swing/src/main/java/org/chorem/lima/ui/celleditor/StringTableCellEditor.java =================================================================== --- trunk/lima-swing/src/main/java/org/chorem/lima/ui/celleditor/StringTableCellEditor.java (rev 0) +++ trunk/lima-swing/src/main/java/org/chorem/lima/ui/celleditor/StringTableCellEditor.java 2013-06-12 16:03:34 UTC (rev 3680) @@ -0,0 +1,95 @@ +package org.chorem.lima.ui.celleditor; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.chorem.lima.LimaConfig; + +import javax.swing.*; +import javax.swing.border.Border; +import javax.swing.event.AncestorEvent; +import javax.swing.event.AncestorListener; +import java.awt.*; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +/** + * @author Sylvain Bavencoff <bavencoff@codelutin.com> + */ +public class StringTableCellEditor extends DefaultCellEditor { + + private static final Log log = LogFactory.getLog(BigDecimalTableCellEditor.class); + + public StringTableCellEditor() { + super(new JTextField()); + setClickCountToStart(1);Border border = BorderFactory.createLineBorder(new Color(123, 165, 205), 2); + //Border border = BorderFactory.createLoweredBevelBorder(); + + getComponent().setBorder(border); + getComponent().addFocusListener(new FocusListener() { + + @Override + public void focusGained(FocusEvent event) { + runEdition(); + } + + @Override + public void focusLost(FocusEvent event) { + // nothing to do + } + }); + getComponent().addAncestorListener(new AncestorListener() { + + @Override + public void ancestorAdded(AncestorEvent event) { + runEdition(); + } + + @Override + public void ancestorRemoved(AncestorEvent event) { + // nothing to do + } + + @Override + public void ancestorMoved(AncestorEvent event) { + // nothing to do + } + }); + getComponent().addPropertyChangeListener(new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + runEdition(); + } + }); + } + + @Override + public JTextField getComponent() { + return (JTextField) super.getComponent(); + } + + /** + * Two kinds of edition, with LimaConfig value + * */ + public void runEdition() { + String comportmentEditingCell = LimaConfig.getInstance().getComportmentEditingCell(); + if (comportmentEditingCell.equals("ALL")) { + getComponent().selectAll(); + } else { + int textFieldSize = getComponent().getText().length(); + getComponent().select(textFieldSize, textFieldSize); + } + } + + /** + * Split decimal with scale config + * @return bigDecimal value + * */ + @Override + public Object getCellEditorValue() { + String stringValue = super.getCellEditorValue().toString(); + return stringValue; + } + +} Modified: trunk/lima-swing/src/main/java/org/chorem/lima/ui/financialtransaction/FinancialTransactionTable.java =================================================================== --- trunk/lima-swing/src/main/java/org/chorem/lima/ui/financialtransaction/FinancialTransactionTable.java 2013-06-07 16:09:48 UTC (rev 3679) +++ trunk/lima-swing/src/main/java/org/chorem/lima/ui/financialtransaction/FinancialTransactionTable.java 2013-06-12 16:03:34 UTC (rev 3680) @@ -34,15 +34,14 @@ import org.chorem.lima.ui.celleditor.BigDecimalTableCellEditor; import org.chorem.lima.ui.celleditor.BigDecimalTableCellRenderer; import org.chorem.lima.ui.celleditor.DateTableCellEditor; -import org.chorem.lima.ui.celleditor.EmptyCellRenderer; -import org.jdesktop.swingx.JXTable; -import org.jdesktop.swingx.decorator.ColorHighlighter; -import org.jdesktop.swingx.decorator.ComponentAdapter; -import org.jdesktop.swingx.decorator.HighlightPredicate; -import org.jdesktop.swingx.decorator.Highlighter; +import org.chorem.lima.ui.celleditor.DateTableCellRenderer; +import org.chorem.lima.ui.celleditor.EntryTableCellRenderer; +import org.chorem.lima.ui.celleditor.StringTableCellEditor; +import javax.swing.*; +import javax.swing.table.TableCellEditor; import java.awt.*; -import java.awt.event.KeyAdapter; +import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; @@ -60,7 +59,7 @@ * @author jpepin * @author echatellier */ -public class FinancialTransactionTable extends JXTable { +public class FinancialTransactionTable extends JTable { /** serialVersionUID. */ private static final long serialVersionUID = 3133690382049594727L; @@ -72,15 +71,14 @@ public FinancialTransactionTable(final FinancialTransactionViewHandler handler) { this.handler = handler; - addKeyListener(new MyKeyAdapter()); + //Get new date editor + setDefaultEditor(Date.class, new DateTableCellEditor()); - addMouseListener(new MyMouseAdapter()); + //Get new String editor - //addListSelectionListener(); + StringTableCellEditor stringTableCellEditor = new StringTableCellEditor(); + setDefaultEditor(String.class, stringTableCellEditor); - //Get new date editor - setDefaultEditor(Date.class, new DateTableCellEditor()); - //Get new account editor setDefaultEditor(Account.class, new AccountTableCellEditor()); @@ -90,8 +88,11 @@ //Get new BigDecimal renderer setDefaultRenderer(BigDecimal.class, new BigDecimalTableCellRenderer()); + //get new Date renderer for empty cells + setDefaultRenderer(Date.class, new DateTableCellRenderer()); + //get new String renderer for empty cells - setDefaultRenderer(String.class, new EmptyCellRenderer()); + setDefaultRenderer(String.class, new EntryTableCellRenderer()); //get new Account renderer for empty cells setDefaultRenderer(Account.class, new AccountTableCellRenderer()); @@ -100,131 +101,182 @@ setShowVerticalLines(true); setGridColor(new Color(210,210,210)); + InputMap inputMap= getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + ActionMap actionMap = getActionMap(); - // 1 transaction of 2 - HighlightPredicate predicate = new HighlightPredicate() { - @Override - public boolean isHighlighted(Component renderer, - ComponentAdapter adapter) { - int index = handler.view.getFinancialTransactionTableModel().getIndexTransaction(adapter.row); - return index % 2 == 1; - } - }; - Highlighter colorTransaction = - new ColorHighlighter(predicate, new Color(242, 242, 242), null); - addHighlighter(colorTransaction); + // action on Tab + Object binding = inputMap.get(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0)); + actionMap.put(binding, new NextCellAction()); - predicate = new HighlightPredicate() { - @Override - public boolean isHighlighted(Component renderer, - ComponentAdapter adapter) { - int index = handler.view.getFinancialTransactionTableModel().getIndexTransaction(adapter.row); - return index % 2 == 0; - } - }; - colorTransaction = - new ColorHighlighter(predicate, getBackground(), null); - addHighlighter(colorTransaction); + // action on Shift + Tab + binding = inputMap.get(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, KeyEvent.SHIFT_DOWN_MASK)); + actionMap.put(binding, new CellRouteHorizontalFirstAction(false)); - // highlight unbalanced financial transactions - predicate = new HighlightPredicate() { - @Override - public boolean isHighlighted(Component renderer, - ComponentAdapter adapter) { + // action on Enter + binding = inputMap.get(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0)); + actionMap.put(binding, new CellRouteVerticalFirstAction(true)); - BigDecimal balance = handler.view.getFinancialTransactionTableModel().getBalanceTransactionInRow(adapter.row); - return balance.compareTo(BigDecimal.ZERO) != 0; - } - }; - colorTransaction = - new ColorHighlighter(predicate, null, new Color(240, 30, 30)); - addHighlighter(colorTransaction); + // action on Shift + Enter + binding = inputMap.get(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, KeyEvent.SHIFT_DOWN_MASK)); + actionMap.put(binding, new CellRouteVerticalFirstAction(false)); + // remove input Ctrl + Del + inputMap= stringTableCellEditor.getComponent().getInputMap(JComponent.WHEN_FOCUSED); + while (inputMap != null) { + inputMap.remove(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, KeyEvent.CTRL_DOWN_MASK)); + inputMap = inputMap.getParent(); + } } public FinancialTransactionViewHandler getHandler() { return handler; } - private class MyKeyAdapter extends KeyAdapter { + private class NextCellAction extends AbstractAction { FinancialTransactionTable table = FinancialTransactionTable.this; FinancialTransactionTableModel tableModel = table.handler.view.getFinancialTransactionTableModel(); @Override - public void keyPressed(KeyEvent e) { + public void actionPerformed(ActionEvent e) { + if (log.isDebugEnabled()) { + log.debug("Key tab used"); + } + int nbColumn = getColumnCount(); + int nbRows = getRowCount(); + int column = getSelectedColumn(); + int row = getSelectedRow(); - final FinancialTransactionViewHandler handler = getHandler(); + if (column >= 0 && row >= 0) { - /*Allow to block access to the first row when key enter pressed, if selection on - * last row*/ - /* if (e.getKeyCode() == KeyEvent.VK_ENTER){ - int selectedRow = table.getSelectedRow(); - if( selectedRow == table.getRowCount()-1){ - *//*-2, cause we have a row count beginning at one and we want to back to the line before*//* - table.setRowSelectionInterval(table.getRowCount()-2, table.getRowCount()-2); - } else { - table.setRowSelectionInterval(selectedRow, selectedRow); - } - }*/ + boolean end = false; - /* - * Touche tab - * Incrémente le curseur de case tant que la case n'est pas editable - * Ajoute une entrée comptable si tab est sur - * la dernière cellule et si la transaction est non équilibrée - * sinon rajoute une transaction - */ - if (e.getKeyChar() == KeyEvent.VK_TAB) { - if (log.isDebugEnabled()) { - log.debug("Key tab used"); - } - int nbColumn = getColumnCount(); - int nbRows = getRowCount(); - int column = getSelectedColumn(); - int row = getSelectedRow(); - - if (column >= 0 && row >= 0) { - - boolean end = false; - - FinancialTransaction transaction = tableModel.getTransactionAt(row); - do { - if (column >= nbColumn - 1) { - if (row >= nbRows - 1 || transaction != tableModel.getTransactionAt(row + 1)) { - BigDecimal credit = transaction.getAmountCredit(); - BigDecimal debit = transaction.getAmountDebit(); - if (credit.compareTo(debit) != 0) { - table.handler.addEntry(); - column = 1; - row++; - end = true; - } else if (row >= nbRows - 1) { - table.handler.addFinancialTransaction(); - column = 0; - row++; - end = true; - } else { - column = 0; - row++; - } + FinancialTransaction transaction = tableModel.getTransactionAt(row); + do { + if (column >= nbColumn - 1) { + if (row >= nbRows - 1 || transaction != tableModel.getTransactionAt(row + 1)) { + BigDecimal credit = transaction.getAmountCredit(); + BigDecimal debit = transaction.getAmountDebit(); + if (credit.compareTo(debit) != 0) { + table.handler.addEntry(); + column = 2; + row++; + end = true; + } else if (row >= nbRows - 1) { + table.handler.addFinancialTransaction(); + column = 0; + row++; + end = true; } else { column = 0; row++; } } else { - column++; + column = 0; + row++; } - } while (!end && !tableModel.isCellEditable(row,column)); - setRowSelectionInterval(row, row); - setColumnSelectionInterval(column, column); - editCellAt(column, row); + } else { + column++; + } + } while (!end && !tableModel.isCellEditable(row,column)); + if (isEditing()) { + TableCellEditor editor = getCellEditor(); + editor.stopCellEditing(); + } + setRowSelectionInterval(row, row); + setColumnSelectionInterval(column, column); + //editCellAt(row, column); + } + } + } - e.consume(); + private class CellRouteHorizontalFirstAction extends AbstractAction { + + FinancialTransactionTable table = FinancialTransactionTable.this; + FinancialTransactionTableModel tableModel = table.handler.view.getFinancialTransactionTableModel(); + + protected int step; + protected int route1; + protected int route2; + protected int nbCell1; + protected int nbCell2; + + public CellRouteHorizontalFirstAction(boolean nextCell) { + step = nextCell ? +1 : -1; + } + + protected void init() { + route1 = getSelectedColumn(); + route2 = getSelectedRow(); + nbCell1 = getColumnCount(); + nbCell2 = getRowCount(); + } + + protected int getRow() { + return route2; + } + + protected int getColumn() { + return route1; + } + + protected boolean isEditable() { + return tableModel.isCellEditable(getRow(), getColumn()); + } + + @Override + public void actionPerformed(ActionEvent e) { + init(); + if (route1 >= 0 && route2 >= 0) { + do { + route1 = route1 + step; + if (route1 < 0 || route1 >= nbCell1) { + route1 = route1 % nbCell1; + if (route1 < 0) { + route1 = route1 + nbCell1; + } + route2 = route2 + step; + if (route2 < 0 || route2 >= nbCell2) { + route2 = route2 % nbCell2; + if (route2 < 0) { + route2 = route2 + nbCell2; + } + } + } + } while (!isEditable()); + if (isEditing()) { + TableCellEditor editor = getCellEditor(); + editor.stopCellEditing(); } + int row = getRow(); + int column = getColumn(); + setRowSelectionInterval(row, row); + setColumnSelectionInterval(column, column); + //editCellAt(row, column); } + } + } + private class CellRouteVerticalFirstAction extends CellRouteHorizontalFirstAction { + + public CellRouteVerticalFirstAction(boolean nextCell) { + super(nextCell); } + + protected void init() { + route1 = getSelectedRow(); + route2 = getSelectedColumn(); + nbCell1 = getRowCount(); + nbCell2 = getColumnCount(); + } + + protected int getRow() { + return route1; + } + + protected int getColumn() { + return route2; + } } private class MyMouseAdapter extends MouseAdapter { @@ -237,4 +289,10 @@ } } + private class DeleteEntryAction extends AbstractAction { + @Override + public void actionPerformed(ActionEvent e) { + handler.deleteSelectedEntry(); + } + } } Modified: trunk/lima-swing/src/main/java/org/chorem/lima/ui/financialtransaction/FinancialTransactionTableModel.java =================================================================== --- trunk/lima-swing/src/main/java/org/chorem/lima/ui/financialtransaction/FinancialTransactionTableModel.java 2013-06-07 16:09:48 UTC (rev 3679) +++ trunk/lima-swing/src/main/java/org/chorem/lima/ui/financialtransaction/FinancialTransactionTableModel.java 2013-06-12 16:03:34 UTC (rev 3680) @@ -25,16 +25,11 @@ package org.chorem.lima.ui.financialtransaction; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.chorem.lima.LimaContext; import org.chorem.lima.business.api.FinancialTransactionService; import org.chorem.lima.entity.Account; import org.chorem.lima.entity.Entry; import org.chorem.lima.entity.FinancialTransaction; import org.chorem.lima.service.LimaServiceFactory; -import org.nuiton.util.decorator.Decorator; -import org.nuiton.util.decorator.DecoratorProvider; import javax.swing.table.AbstractTableModel; import java.math.BigDecimal; @@ -57,8 +52,6 @@ /** serialVersionUID. */ private static final long serialVersionUID = -7495388454688562991L; - private static final Log log = LogFactory.getLog(FinancialTransactionViewHandler.class); - /** Service (just to update setValueAt(). */ protected FinancialTransactionService financialTransactionService; @@ -66,18 +59,9 @@ protected List<FinancialTransaction> transactions; - /** - * To decorate account objects. - */ - protected final Decorator<Account> accountDecorator; - public FinancialTransactionTableModel() { financialTransactionService = LimaServiceFactory.getService(FinancialTransactionService.class); - - DecoratorProvider decoratorProvider = - LimaContext.get().getDecoratorProvider(); - accountDecorator = decoratorProvider.getDecoratorByType(Account.class); } public void setEntries(List<Entry> entries) { @@ -143,10 +127,10 @@ result = _("lima.ui.financialtransaction.description"); break; case 4: - result = _("lima.ui.financialtransaction.debit"); + result = _("lima.ui.financialtransaction.credit"); break; case 5: - result = _("lima.ui.financialtransaction.credit"); + result = _("lima.ui.financialtransaction.debit"); break; } return result; @@ -184,10 +168,10 @@ result = entry.getDescription(); break; case 4: - result = entry.getDebit() ? entry.getAmount() : BigDecimal.ZERO; + result = entry.getDebit() ? BigDecimal.ZERO : entry.getAmount(); break; case 5: - result = entry.getDebit() ? BigDecimal.ZERO : entry.getAmount(); + result = entry.getDebit() ? entry.getAmount() : BigDecimal.ZERO; break; } return result; @@ -204,50 +188,6 @@ || entries.get(rowIndex).getFinancialTransaction() != entries.get(rowIndex - 1).getFinancialTransaction(); } - /** - * Obtain the first entry book of the current transaction. - * - * @param selectedRow row selected - * @return first entry index - */ - public int getFirstEntry(int selectedRow) { - int result = -1; - int currentRow = selectedRow; - while (currentRow > -1) { - Object o = entries.get(currentRow); - if (o instanceof Entry) { - - // current row is still a entry book - currentRow--; - continue; - } - if (o instanceof FinancialTransaction) { - // got the begin of a transaction - if (currentRow == selectedRow) { - - // the selected row is on the transaction - // - // look out if there is a next line and if then look out if - // this is a entry book - result = -1; - } else { - - // the next row is an entry book row - result = currentRow + 1; - } - break; - } - } - return result; - } - - public Entry getEntryAt(int row) { - if (row == -1) { - return null; - } - return entries.get(row); - } - /** to modifiy financialtransaction or entry */ @Override public void setValueAt(Object value, int row, int column) { @@ -325,13 +265,13 @@ case 4: if (((BigDecimal) value).signum() > 0 ) { entry.setAmount((BigDecimal) value); - entry.setDebit(true); + entry.setDebit(false); } break; case 5: if (((BigDecimal) value).signum() > 0 ) { entry.setAmount((BigDecimal) value); - entry.setDebit(false); + entry.setDebit(true); } break; } @@ -362,6 +302,15 @@ } + public Entry getEntryAt(int row) { + return entries.get(row); + } + + public FinancialTransaction getTransactionAt(int row) { + Entry entry = entries.get(row); + return entry.getFinancialTransaction(); + } + public int indexOf(Entry entry) { return entries.indexOf(entry); } @@ -379,71 +328,65 @@ return index; } - public int indexOfEntryInTransaction(Entry entry) { - FinancialTransaction transaction = entry.getFinancialTransaction(); - int result = -1; - for (Entry entryTmp : entries) { - if (entryTmp.getFinancialTransaction() == transaction) { - result ++; - } - if (entry == entryTmp) { - break; - } - } - return result; + public int getIndexTransaction(int row) { + FinancialTransaction transaction = getTransactionAt(row); + int index = transactions.indexOf(transaction); + return index; } /** - * Delete row. + * Insert new entry. * - * @param row row to delete + * @param entry entry to insert + * @param newRow position */ - public void deleteRow(int row) { - Entry entry = entries.remove(row); + public void addEntry(Entry entry, int newRow) { FinancialTransaction transaction = entry.getFinancialTransaction(); - if (transaction.sizeEntry() == 0) { - transactions.remove(transaction); + if (transactions.contains(transaction)) { + entries.add(newRow, entry); + fireTableRowsInserted(newRow, newRow); } - fireTableRowsDeleted(row, row); } /** - * Insert new row. - * - * @param entry entry to insert - * @param newRow position + * Delete entry. + * + * @param entry entry to delete */ - public void addRow(Entry entry, int newRow) { - entries.add(newRow, entry); - fireTableRowsInserted(newRow, newRow); + public void deleteEntry(Entry entry) { + int row = entries.indexOf(entry); + entries.remove(entry); + fireTableRowsDeleted(row, row); } - /** - * Insert new row. - * - * @param entry entry to insert - */ - public void addRow(Entry entry) { - entries.add(entry); - fireTableRowsInserted(entries.size() - 1, entries.size() - 1); - + public void addTransaction(FinancialTransaction transaction) { + int indexFirstEntry = entries.size(); + if (!transactions.contains(transaction)) { + transactions.add(transaction); + entries.addAll(transaction.getEntry()); + } + int indexLastEntry = entries.size() - 1; + fireTableRowsInserted(indexFirstEntry, indexLastEntry - 1); } - public FinancialTransaction getTransactionAt(int row) { - Entry entry = entries.get(row); - return entry.getFinancialTransaction(); + public void deleteTransaction(FinancialTransaction transaction) { + if (transactions.contains(transaction)) { + int indexFirst = indexOf(transaction); + int indexLast = indexFirst + transaction.sizeEntry() - 1; + entries.removeAll(transaction.getEntry()); + transactions.remove(transaction); + if (indexFirst <= indexLast) { + fireTableRowsDeleted(indexFirst, indexFirst); + } + } } - public int getIndexTransaction(int row) { - FinancialTransaction transaction = getTransactionAt(row); - return transactions.indexOf(transaction); - } - public BigDecimal getBalanceTransactionInRow(int row) { FinancialTransaction transaction = getTransactionAt(row); BigDecimal debit = transaction.getAmountDebit(); BigDecimal credit = transaction.getAmountCredit(); - return debit.subtract(credit); + BigDecimal balance = debit.subtract(credit); + return balance; } public int size() { @@ -454,21 +397,5 @@ return result; } - public void addTransaction(FinancialTransaction transaction) { - int indexFirstEntry = entries.size(); - if (!transactions.contains(transaction)) { - transactions.add(transaction); - } - int indexLastEntry = entries.size(); - Collection<Entry> entriesTransaction = transaction.getEntry(); - for (Entry entry : entriesTransaction) { - if (!entries.contains(entry)) { - entries.add(entry); - indexLastEntry++; - } - } - fireTableRowsInserted(indexFirstEntry, indexLastEntry - 1); - } - } Modified: trunk/lima-swing/src/main/java/org/chorem/lima/ui/financialtransaction/FinancialTransactionView.jaxx =================================================================== --- trunk/lima-swing/src/main/java/org/chorem/lima/ui/financialtransaction/FinancialTransactionView.jaxx 2013-06-07 16:09:48 UTC (rev 3679) +++ trunk/lima-swing/src/main/java/org/chorem/lima/ui/financialtransaction/FinancialTransactionView.jaxx 2013-06-12 16:03:34 UTC (rev 3680) @@ -41,12 +41,13 @@ id='selectionModel' initializer="new DefaultListSelectionModel()" selectionMode='{ListSelectionModel.SINGLE_SELECTION}' - onValueChanged="setSelectedRow(financialTransactionTable.getSelectedRow() != -1)"/> + onValueChanged="handler.selectionChanged()"/> <Boolean id="selectedRow" javaBean="false"/> <Boolean id="transactionInClipBoard" javaBean="false"/> <Boolean id="entryInClipBoard" javaBean="false"/> + <Boolean id="balance" javaBean="true"/> <script> <![CDATA[ @@ -88,11 +89,15 @@ <JMenuItem text="lima.common.copy" enabled="{isSelectedRow()}" onActionPerformed="handler.copyEntry(financialTransactionTable.getSelectedRow())" - accelerator="{KeyStroke.getKeyStroke('C', KeyEvent.CTRL_DOWN_MASK)}" /> + accelerator="{KeyStroke.getKeyStroke('C', KeyEvent.CTRL_DOWN_MASK + KeyEvent.ALT_DOWN_MASK)}" /> <JMenuItem text="lima.common.paste" - enabled="{isEntryInClipBoard()}" + enabled="{isEntryInClipBoard() && isSelectedRow()}" onActionPerformed="handler.pasteEntry(financialTransactionTable.getSelectedRow())" - accelerator="{KeyStroke.getKeyStroke('V', KeyEvent.CTRL_DOWN_MASK)}" /> + accelerator="{KeyStroke.getKeyStroke('V', KeyEvent.CTRL_DOWN_MASK + KeyEvent.ALT_DOWN_MASK)}" /> + <JMenuItem text="lima.common.balance" + enabled="{!isBalance()}" + onActionPerformed="handler.balanceTransaction(financialTransactionTable.getSelectedRow())" + accelerator="{KeyStroke.getKeyStroke('B', KeyEvent.CTRL_DOWN_MASK)}" /> </JMenu> </JMenuBar> </cell> @@ -139,7 +144,7 @@ <JScrollPane> <FinancialTransactionTableModel id="financialTransactionTableModel"/> <FinancialTransactionTable - id="financialTransactionTable" sortable="false" rowHeight="22" + id="financialTransactionTable" rowHeight="22" constructorParams='handler' selectionModel='{selectionModel}' model='{financialTransactionTableModel}'/> Modified: trunk/lima-swing/src/main/java/org/chorem/lima/ui/financialtransaction/FinancialTransactionViewHandler.java =================================================================== --- trunk/lima-swing/src/main/java/org/chorem/lima/ui/financialtransaction/FinancialTransactionViewHandler.java 2013-06-07 16:09:48 UTC (rev 3679) +++ trunk/lima-swing/src/main/java/org/chorem/lima/ui/financialtransaction/FinancialTransactionViewHandler.java 2013-06-12 16:03:34 UTC (rev 3680) @@ -170,7 +170,7 @@ public void updateFinancialTransactions() { FinancialPeriod financialPeriod = (FinancialPeriod)view.getFinancialPeriodComboBox().getSelectedItem(); EntryBook entryBook = (EntryBook)view.getEntryBookComboBox().getSelectedItem(); - + // la selection de la financialPeriod est obligatoire // sinon, tout un exercice, c'est trop lourd // l'entry book par contre, est facultatif @@ -197,10 +197,52 @@ view.getFinancialTransactionTableModel().setEntries(transAndEntries); } + public void selectionChanged() { + FinancialTransactionTable table = view.getFinancialTransactionTable(); + FinancialTransactionTableModel tableModel = view.getFinancialTransactionTableModel(); + int selectedRow = table.getSelectedRow(); + view.setSelectedRow(selectedRow >= 0 && selectedRow < tableModel.size()); + if (selectedRow >= 0 && selectedRow < tableModel.size()) { + FinancialTransaction transaction = tableModel.getTransactionAt(selectedRow); + BigDecimal credit = transaction.getAmountCredit(); + BigDecimal debit = transaction.getAmountDebit(); + view.setBalance(credit.compareTo(debit) == 0); + } else { + view.setBalance(true); + } + } + + public void balanceTransaction(int rowSelected) { + FinancialTransactionTableModel tableModel = view.getFinancialTransactionTableModel(); + FinancialTransactionTable table = view.getFinancialTransactionTable(); + + if (table.isEditing()) { + TableCellEditor editor = table.getCellEditor(); + editor.stopCellEditing(); + } + + Entry entry = tableModel.getEntryAt(rowSelected); + FinancialTransaction transaction = entry.getFinancialTransaction(); + BigDecimal credit = transaction.getAmountCredit(); + BigDecimal debit = transaction.getAmountDebit(); + if (entry.isDebit()) { + debit = debit.subtract(entry.getAmount()); + } else { + credit = credit.subtract(entry.getAmount()); + } + + BigDecimal balance = credit.subtract(debit); + entry.setAmount(balance.abs()); + entry.setDebit(balance.signum() > 0); + financialTransactionService.updateEntry(entry); + tableModel.fireTableRowsUpdated(rowSelected, rowSelected); + view.setBalance(true); + } + /** * Copy selected Transaction * - * @param indexSelectedRow + * @param indexSelectedRow selected row to copy a transaction */ public void copyTransaction(int indexSelectedRow){ clipBoard = view.getFinancialTransactionTableModel().getTransactionAt(indexSelectedRow); @@ -211,7 +253,7 @@ /** * Copy selected Entry * - * @param indexSelectedRow + * @param indexSelectedRow selected row to copy a entry */ public void copyEntry(int indexSelectedRow){ clipBoard = view.getFinancialTransactionTableModel().getEntryAt(indexSelectedRow); @@ -258,6 +300,10 @@ } tableModel.addTransaction(transaction); + if (table.isEditing()) { + TableCellEditor editor = table.getCellEditor(); + editor.stopCellEditing(); + } int index = tableModel.indexOf(transaction); selectionModel.setSelectionInterval(index, index); } @@ -290,8 +336,12 @@ transaction.addEntry(entry); + if (table.isEditing()) { + TableCellEditor editor = table.getCellEditor(); + editor.stopCellEditing(); + } int index = tableModel.indexOf(transaction) + transaction.sizeEntry() - 1; - tableModel.addRow(entry, index); + tableModel.addEntry(entry, index); selectionModel.setSelectionInterval(index, index); //focus on second column @@ -317,8 +367,12 @@ currentTransaction.addEntry(entry); // on met a jour l'ui + if (table.isEditing()) { + TableCellEditor editor = table.getCellEditor(); + editor.stopCellEditing(); + } int newRow = row + 1; - tableModel.addRow(newEntry, newRow); + tableModel.addEntry(newEntry, newRow); table.addRowSelectionInterval(newRow, newRow); return newRow; } @@ -363,16 +417,20 @@ // create it FinancialTransaction fTransaction = financialTransactionService.createFinancialTransaction(financialTransaction); - // create 2 first entry of this transaction + // create first entry of this transaction Entry entry = new EntryImpl(); entry.setFinancialTransaction(fTransaction); entry = financialTransactionService.createEntry(entry); fTransaction.addEntry(entry); // add it in ui - int addIndex = tableModel.size(); - tableModel.addRow(entry, addIndex); + tableModel.addTransaction(fTransaction); + int addIndex = tableModel.size() - 1; //select the new line + if (table.isEditing()) { + TableCellEditor editor = table.getCellEditor(); + editor.stopCellEditing(); + } ListSelectionModel selectionModel = table.getSelectionModel(); selectionModel.setSelectionInterval(addIndex, addIndex); table.changeSelection(addIndex, 1, false, false); @@ -453,7 +511,7 @@ // add it in ui int addIndex = tableModel.indexOf(lastEntry) + 1; - tableModel.addRow(newEntry, addIndex); + tableModel.addEntry(newEntry, addIndex); //select the new line ListSelectionModel selectionModel = table.getSelectionModel(); @@ -485,16 +543,12 @@ _("lima.ui.financialtransaction.titleremovetransaction"), JOptionPane.YES_NO_OPTION); if (response == JOptionPane.YES_OPTION) { - //must delete the entries of the deleted transaction - Collection<Entry> entries = transaction.getEntry(); - if (entries != null){ - for (Entry entry : entries){ - tableModel.deleteRow(tableModel.indexOf(entry)); - } - } financialTransactionService.removeFinancialTransaction(transaction); + //must delete the entries of the deleted transaction + tableModel.deleteTransaction(transaction); + if (tableModel.size() > 0) { if (indexSelectedRow >= tableModel.size()) { indexSelectedRow = tableModel.size() - 1; @@ -526,19 +580,19 @@ _("lima.ui.financialtransaction.titleremoveentry"), JOptionPane.YES_NO_OPTION); if (response == JOptionPane.YES_OPTION) { - tableModel.deleteRow(indexSelectedRow); - financialTransactionService.removeEntry(entry); FinancialTransaction transaction = entry.getFinancialTransaction(); - transaction.removeEntry(entry); - if (transaction.sizeEntry() == 0) { + if (transaction.sizeEntry() > 1) { + financialTransactionService.removeEntry(entry); + transaction.removeEntry(entry); + tableModel.deleteEntry(entry); + } else { financialTransactionService.removeFinancialTransaction(transaction); + tableModel.deleteTransaction(transaction); } if (tableModel.size() > 0) { if (indexSelectedRow >= tableModel.size()) { indexSelectedRow = tableModel.size() - 1; - } else { - indexSelectedRow++; } selectionModel.setSelectionInterval( indexSelectedRow, indexSelectedRow); @@ -548,8 +602,6 @@ } } - - /** * Select previous value in combo box. * Modified: trunk/lima-swing/src/main/resources/i18n/lima-swing_en_GB.properties =================================================================== --- trunk/lima-swing/src/main/resources/i18n/lima-swing_en_GB.properties 2013-06-07 16:09:48 UTC (rev 3679) +++ trunk/lima-swing/src/main/resources/i18n/lima-swing_en_GB.properties 2013-06-12 16:03:34 UTC (rev 3680) @@ -44,6 +44,7 @@ lima.common.amountcredit=Credit amount lima.common.amountdebit=Debit amount lima.common.autocomplete=Autocomplete +lima.common.balance=Balance lima.common.begindate=Begin lima.common.buttonback=← lima.common.buttonnext=→ Modified: trunk/lima-swing/src/main/resources/i18n/lima-swing_fr_FR.properties =================================================================== --- trunk/lima-swing/src/main/resources/i18n/lima-swing_fr_FR.properties 2013-06-07 16:09:48 UTC (rev 3679) +++ trunk/lima-swing/src/main/resources/i18n/lima-swing_fr_FR.properties 2013-06-12 16:03:34 UTC (rev 3680) @@ -44,6 +44,7 @@ lima.common.amountcredit=Total Crédit lima.common.amountdebit=Total Débit lima.common.autocomplete=Autocomplétion +lima.common.balance=Équilibrer lima.common.begindate=Début lima.common.buttonback=← lima.common.buttonnext=→