Author: vsalaun Date: 2011-06-17 14:41:53 +0200 (Fri, 17 Jun 2011) New Revision: 3181 Url: http://chorem.org/repositories/revision/lima/3181 Log: add key shortcuts for transactions search (except tab key) Modified: trunk/lima-swing/src/main/java/org/chorem/lima/ui/financialtransactionsearch/FinancialTransactionSearchTable.java trunk/lima-swing/src/main/java/org/chorem/lima/ui/financialtransactionsearch/FinancialTransactionSearchTableModel.java trunk/lima-swing/src/main/java/org/chorem/lima/ui/financialtransactionsearch/FinancialTransactionSearchViewHandler.java Modified: trunk/lima-swing/src/main/java/org/chorem/lima/ui/financialtransactionsearch/FinancialTransactionSearchTable.java =================================================================== --- trunk/lima-swing/src/main/java/org/chorem/lima/ui/financialtransactionsearch/FinancialTransactionSearchTable.java 2011-06-17 08:22:47 UTC (rev 3180) +++ trunk/lima-swing/src/main/java/org/chorem/lima/ui/financialtransactionsearch/FinancialTransactionSearchTable.java 2011-06-17 12:41:53 UTC (rev 3181) @@ -33,14 +33,22 @@ import java.awt.event.MouseListener; import java.math.BigDecimal; import java.util.Date; + +import javax.swing.SwingWorker; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.chorem.lima.entity.Account; +import org.chorem.lima.entity.Entry; import org.chorem.lima.entity.EntryBook; +import org.chorem.lima.entity.FinancialTransaction; import org.chorem.lima.ui.celleditor.AccountTableCellEditor; 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.chorem.lima.ui.celleditor.EntryBookTableCellEditor; +import org.chorem.lima.ui.financialtransaction.FinancialTransactionTable; import org.jdesktop.swingx.JXTable; import org.jdesktop.swingx.decorator.ColorHighlighter; import org.jdesktop.swingx.decorator.ComponentAdapter; @@ -59,12 +67,19 @@ /** serialVersionUID. */ private static final long serialVersionUID = 3133690382049594727L; + + /** log. */ + private static final Log log = LogFactory + .getLog(FinancialTransactionSearchTable.class); protected FinancialTransactionSearchViewHandler handler; private Highlighter colorTransaction; private ColorHighlighter colorBalance; + + private int x_tab; + private int y_tab; /** */ @@ -164,12 +179,150 @@ @Override public void keyPressed(KeyEvent e) { + //TODO combinaison de touches dans la config + + // delete selected row with the key : delete or ctrl + clear + // ou de l'entree + if ((e.getKeyCode() == KeyEvent.VK_DELETE ) + || (e.getKeyCode() == KeyEvent.VK_CLEAR + && e.getModifiers() == KeyEvent.CTRL_MASK)){ + handler.deleteSelectedRow(); + } + + // add entry with the key combination : insert or ctrl + enter + if ((e.getKeyCode() == KeyEvent.VK_INSERT ) + || (e.getKeyCode() == KeyEvent.VK_ENTER + && e.getModifiers() == KeyEvent.CTRL_MASK)) { + handler.addEmptyEntry(); + } + + // add financial transaction with the key combination : ctrl + tab + if (e.getKeyCode() == KeyEvent.VK_C + && e.getModifiers() == KeyEvent.CTRL_MASK) { + handler.copyRow(); + } + + // copy : ctrl + c + + // add financial transaction with the key combination : ctrl + tab + if (e.getKeyCode() == KeyEvent.VK_V + && e.getModifiers() == KeyEvent.CTRL_MASK) { + handler.pasteRow(); + } + + // paste : ctrl + v + + // add financial transaction with the key combination : ctrl + tab + if (e.getKeyCode() == KeyEvent.VK_TAB + && e.getModifiers() == KeyEvent.CTRL_MASK) { + handler.addFinancialTransaction(); + } + // clear row selection with the key: escape if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { - if (!this.isEditing()) { + if (!this.isEditing()) { this.clearSelection(); - } + } } + + + //FIXME 2011.06.11 + //Needs fixing + //Exception in thread "AWT-EventQueue-0" + //java.lang.IndexOutOfBoundsException: + //valid viewIndex: 0 <= index < 42 but was: 42 + /** + * 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é + * sinon rajoute une transaction + */ + + /*if (e.getKeyChar() == KeyEvent.VK_TAB) { + int max_x = this.getColumnCount(); + int max_y = this.getRowCount(); + x_tab = this.getSelectedColumn(); + y_tab = this.getSelectedRow(); + Boolean end = true; + + if (x_tab < max_x - 1){ + x_tab++; + } + //end of row + else { + x_tab=0; + y_tab++; + } + + //skip all cell while not editable or if end of table add entry or transaction or end of table + while (!isCellEditable(y_tab, x_tab) && end ){ + System.out.println("coucou"); + //if end of row + if (x_tab == max_x-1) { + Object object = this.handler.tableModel.getElementAt(y_tab); + + //if transaction, add entry + if (object instanceof FinancialTransaction){ + FinancialTransaction financialTransaction = (FinancialTransaction) object; + if (financialTransaction.getEntry().size() == 0){ + handler.addEmptyEntry(); + this.setColumnSelectionInterval(1, 1); + } + } + //if entry + else { + //FIXME set value is doing after key pressed + // so update not terminated before get balanced + //Swing Worker stop the UI 500ms + // found best solution ? + final JXTable table = this; + final int y_t = y_tab; + final int m_t = max_y; + new SwingWorker<Void,Void>() { + @Override protected Void doInBackground() throws InterruptedException { + Thread.sleep(500); + return null; + } + @Override protected void done() { + Object object = handler.tableModel.getElementAt(y_tab-1); + FinancialTransaction financialTransaction = null; + if (object instanceof Entry){ + financialTransaction = ((Entry) object).getFinancialTransaction(); + } + else if (object instanceof FinancialTransaction){ + financialTransaction = (FinancialTransaction) object; + } + BigDecimal amountC = financialTransaction.getAmountCredit(); + BigDecimal amountD = financialTransaction.getAmountDebit(); + if (amountC == amountD){ + if (y_t == m_t-1){ + handler.addFinancialTransaction(); + table.setColumnSelectionInterval(0, 0); + } + } + else { + handler.addEmptyEntry(); + table.setColumnSelectionInterval(1, 1); + y_tab++; + // positionne la sélection sur la nouvelle ligne créée + table.setRowSelectionInterval(y_tab, y_tab); + x_tab=0; + } + } + }.execute(); + } + end = false; + } + else { + if (x_tab < max_x){ + this.setRowSelectionInterval(y_tab, y_tab); + this.setColumnSelectionInterval(x_tab, x_tab); + x_tab++; + } + } + } + }*/ } Modified: trunk/lima-swing/src/main/java/org/chorem/lima/ui/financialtransactionsearch/FinancialTransactionSearchTableModel.java =================================================================== --- trunk/lima-swing/src/main/java/org/chorem/lima/ui/financialtransactionsearch/FinancialTransactionSearchTableModel.java 2011-06-17 08:22:47 UTC (rev 3180) +++ trunk/lima-swing/src/main/java/org/chorem/lima/ui/financialtransactionsearch/FinancialTransactionSearchTableModel.java 2011-06-17 12:41:53 UTC (rev 3181) @@ -27,20 +27,28 @@ import static org.nuiton.i18n.I18n._; import java.math.BigDecimal; +import java.util.Calendar; import java.util.Date; import java.util.List; import javax.swing.table.AbstractTableModel; + +import org.apache.commons.lang.time.DateUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.chorem.lima.beans.FinancialTransactionSearch; +import org.chorem.lima.business.FinancialPeriodServiceMonitorable; import org.chorem.lima.business.FinancialTransactionServiceMonitorable; +import org.chorem.lima.business.LimaBusinessException; import org.chorem.lima.business.LimaException; import org.chorem.lima.business.ServiceListener; +import org.chorem.lima.business.ejb.FinancialPeriodServiceImpl; import org.chorem.lima.entity.Account; import org.chorem.lima.entity.Entry; import org.chorem.lima.entity.EntryBook; import org.chorem.lima.entity.EntryImpl; +import org.chorem.lima.entity.FinancialPeriod; import org.chorem.lima.entity.FinancialTransaction; +import org.chorem.lima.entity.FinancialTransactionImpl; import org.chorem.lima.entity.FiscalPeriod; import org.chorem.lima.entity.Letter; import org.chorem.lima.service.LimaServiceFactory; @@ -71,6 +79,9 @@ /** Transaction service. */ protected final FinancialTransactionServiceMonitorable financialTransactionService; + /** Financial service */ + protected final FinancialPeriodServiceMonitorable financialPeriodService; + /** selected financial period */ protected FiscalPeriod selectedFiscalPeriod; @@ -90,6 +101,9 @@ LimaServiceFactory.getInstance().getService( FinancialTransactionServiceMonitorable.class); financialTransactionService.addListener(this); + financialPeriodService = + LimaServiceFactory.getInstance().getService( + FinancialPeriodServiceMonitorable.class); } /** @@ -141,32 +155,33 @@ switch (column) { case 0: - result = Date.class; + result = Date.class; //Date break; case 1: - result = EntryBook.class; + result = EntryBook.class; //EntryBook break; case 2: - result = String.class; + result = String.class; //Voucher break; case 3: - result = Account.class; + result = Account.class; //Account break; case 4: - result = String.class; + result = String.class; //Description break; case 5: - result = BigDecimal.class; + result = Letter.class; //Letter break; case 6: - result = BigDecimal.class; + result = BigDecimal.class; //Debit break; case 7: - result = BigDecimal.class; + result = BigDecimal.class; //Credit break; case 8: - result = Letter.class; + result = BigDecimal.class; //Balance break; + } return result; @@ -193,17 +208,18 @@ result = _("lima.table.description"); break; case 5: - result = _("lima.table.debit"); + result = _("lima.table.letter"); break; case 6: - result = _("lima.table.credit"); + result = _("lima.table.debit"); break; case 7: - result = _("lima.table.balance"); + result = _("lima.table.credit"); break; case 8: - result = _("lima.table.letter"); + result = _("lima.table.balance"); break; + } return result; @@ -247,39 +263,40 @@ } break; case 2: - result = null; //entrybook + result = null; //EntryBook break; case 3: - result = null; // account + result = null; //Account break; case 4: - result = null; // description + result = null; //Description break; - case 5 : - result = amountDebit; + case 5: + result = null; //Letter break; - case 6: - result = amountCredit; + case 6 : + result = amountDebit; //Debit break; case 7: - result = amountDebit.subtract(amountCredit); + result = amountCredit; //Credit break; case 8: - result = null; + result = amountDebit.subtract(amountCredit); //Balance break; + } } else if (result instanceof Entry) { Entry currentEntry = (Entry)result; switch (column) { case 0: - result = null; // date + result = null; //Date break; - case 1 : // entry book + case 1 : //EntryBook result = null; break; case 2: - result = currentEntry.getVoucher(); + result = currentEntry.getVoucher(); //Voucher break; case 3: // account if (currentEntry.getAccount() != null){ @@ -290,18 +307,9 @@ } break; case 4: - result = currentEntry.getDescription(); + result = currentEntry.getDescription(); //Description break; - case 5 : - result = currentEntry.getDebit() ? currentEntry.getAmount() : BigDecimal.ZERO; - break; - case 6: - result = currentEntry.getDebit() ? BigDecimal.ZERO : currentEntry.getAmount(); - break; - case 7: - result = null; - break; - case 8: + case 5: if (currentEntry.getLetter() != null){ result = currentEntry.getLetter().getCode(); } @@ -309,6 +317,15 @@ result = null; } break; + case 6: //Debit + result = currentEntry.getDebit() ? currentEntry.getAmount() : BigDecimal.ZERO; + break; + case 7: //Credit + result = currentEntry.getDebit() ? BigDecimal.ZERO : currentEntry.getAmount(); + break; + case 8: + result = null; //Balance + break; } } @@ -344,6 +361,67 @@ /** * @throws LimaException */ + public void addFinancialTransaction() throws LimaException{ + /* Calling transaction service */ + FinancialTransaction financialTransaction = new FinancialTransactionImpl(); + financialTransaction.setAmountDebit(BigDecimal.ZERO); + financialTransaction.setAmountCredit(BigDecimal.ZERO); + //if a period is selected + if (selectedFiscalPeriod != null){ + List<FinancialPeriod> financialPeriodsList = + financialPeriodService.getFinancialPeriods(selectedFiscalPeriod.getBeginDate(), + selectedFiscalPeriod.getEndDate()); + FinancialPeriod financialPeriod = null; + if (financialPeriodsList != null) { + financialPeriod = financialPeriodsList.get(0); + } else { + throw new LimaException("Can't set new transaction"); + } + financialTransaction.setFinancialPeriod(financialPeriod); + //financialTransaction.setFinancialPeriod(selectedFiscalPeriod); + // get today + Calendar actualCalendar = Calendar.getInstance(); + // get the financial period date + Date transactionDate = financialPeriod.getBeginDate(); + + Calendar calEnd = Calendar.getInstance(); + calEnd.setTime(financialPeriod.getEndDate()); + int dayMax = calEnd.get(Calendar.DAY_OF_MONTH); + Calendar calBegin = Calendar.getInstance(); + calBegin.setTime(financialPeriod.getBeginDate()); + int dayMin = calBegin.get(Calendar.DAY_OF_MONTH); + int toDay = actualCalendar.get(Calendar.DAY_OF_MONTH); + + if ((toDay>dayMax) || (toDay<dayMin)){ + // change the day + transactionDate = DateUtils.setDays(transactionDate, dayMax); + } + else{ + // change the day + transactionDate = DateUtils.setDays(transactionDate, toDay); + } + + + // set date to the financial transaction + financialTransaction.setTransactionDate(transactionDate); + // create it + financialTransactionService.createFinancialTransaction(financialTransaction); + + //on recharge la liste + cacheDataList = getDataList(financialTransactionSearch); + int row = getDataList(financialTransactionSearch).indexOf(financialTransaction); + fireTableRowsInserted(row, row); + //fireTableDataChanged(); + } + else { + throw new LimaBusinessException("No financial period selected"); + } + } + + + /** + * @throws LimaException + */ public void addEmptyEntry(Object value, int row) throws LimaException { FinancialTransaction currentTransaction = null; Object currentRow = cacheDataList.get(row); @@ -471,6 +549,66 @@ fireTableDataChanged(); } + + /** + * @throws LimaException + */ + public void addEmptyEntry(Object value, String description, int row) throws LimaException { + FinancialTransaction currentTransaction = null; + Object currentRow = cacheDataList.get(row); + Entry entry = new EntryImpl(); + entry.setAmount(BigDecimal.ZERO); + if (description != null) { + entry.setDescription(description); + } + //check if current row is a transaction or an entry + if (currentRow instanceof FinancialTransaction) { + currentTransaction = (FinancialTransaction)currentRow; + } + else if (currentRow instanceof Entry) { + Entry currentEntry = (Entry)currentRow; + //get back the parent transaction of the entry + currentTransaction = currentEntry.getFinancialTransaction(); + } + //create it + entry.setFinancialTransaction(currentTransaction); + financialTransactionService.createEntry(entry); + + //on recharge la liste + cacheDataList = getDataList(financialTransactionSearch); + fireTableDataChanged(); + } + + public void addEntry(Object value, Entry entry, int row) throws LimaException { + FinancialTransaction currentTransaction = null; + int financialTransactionRow = 0; + Object currentRow = cacheDataList.get(row); + //check if current row is a transaction or an entry + if (currentRow instanceof FinancialTransaction) { + currentTransaction = (FinancialTransaction)currentRow; + //update the financial transaction in entire + financialTransactionRow = + getDataList(financialTransactionSearch).indexOf(((FinancialTransaction) currentRow)); + } + else if (currentRow instanceof Entry) { + Entry currentEntry = (Entry)currentRow; + //get back the parent transaction of the entry + currentTransaction = currentEntry.getFinancialTransaction(); + //update the financial transaction in entire + financialTransactionRow = + getDataList(financialTransactionSearch).indexOf(((Entry) currentRow). + getFinancialTransaction()); + } + //create it + entry.setFinancialTransaction(currentTransaction); + financialTransactionService.createEntry(entry); + fireTableRowsUpdated(financialTransactionRow, getRowCount()-1); + + //on recharge la liste + cacheDataList = getDataList(financialTransactionSearch); + fireTableDataChanged(); + } + @Override public void notifyMethod(String serviceName, String methodeName) { if ((serviceName.contains("FinancialTransaction") || methodeName.contains("importEntries") Modified: trunk/lima-swing/src/main/java/org/chorem/lima/ui/financialtransactionsearch/FinancialTransactionSearchViewHandler.java =================================================================== --- trunk/lima-swing/src/main/java/org/chorem/lima/ui/financialtransactionsearch/FinancialTransactionSearchViewHandler.java 2011-06-17 08:22:47 UTC (rev 3180) +++ trunk/lima-swing/src/main/java/org/chorem/lima/ui/financialtransactionsearch/FinancialTransactionSearchViewHandler.java 2011-06-17 12:41:53 UTC (rev 3181) @@ -25,19 +25,29 @@ package org.chorem.lima.ui.financialtransactionsearch; +import static org.nuiton.i18n.I18n._; + import java.util.Date; + +import javax.swing.JOptionPane; +import javax.swing.ListSelectionModel; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.chorem.lima.FinancialStatementWayEnum; import org.chorem.lima.beans.FinancialTransactionSearch; import org.chorem.lima.beans.FinancialTransactionSearchImpl; import org.chorem.lima.business.FinancialTransactionServiceMonitorable; +import org.chorem.lima.business.LimaException; import org.chorem.lima.business.ejbinterface.FinancialTransactionService; import org.chorem.lima.entity.Account; +import org.chorem.lima.entity.Entry; import org.chorem.lima.entity.EntryBook; +import org.chorem.lima.entity.FinancialTransaction; import org.chorem.lima.entity.Letter; import org.chorem.lima.service.LimaServiceFactory; import org.chorem.lima.ui.combobox.FiscalPeriodComboBoxModel; +import org.chorem.lima.util.DialogHelper; /** * Handler associated with financial transaction view. @@ -67,6 +77,8 @@ /** data cache */ protected FinancialTransactionSearch financialTransactionSearch; + + protected Object clipBoard; protected FinancialTransactionSearchViewHandler(FinancialTransactionSearchView view) { this.view = view; @@ -169,8 +181,160 @@ } financialTransactionSearch.setOperator(result); } + + /** + * Delete selected row in table (could be transaction or entry). + * + * Called by model. + * @throws LimaException + */ + public void deleteSelectedRow(){ + table = view.getFinancialTransactionSearchTable(); + tableModel = view.getFinancialTransactionSearchTableModel(); + int indexSelectedRow = table.getSelectedRow(); + if (indexSelectedRow != -1) { + + Object selectedValue = tableModel.getElementAt(indexSelectedRow); + String message = null; + if (selectedValue instanceof FinancialTransaction) { + message = _("lima.charts.financialtransaction.question.removetransaction"); + } + else { + message = _("lima.charts.financialtransaction.question.removeentry"); + } + + int response = JOptionPane.showConfirmDialog(view, message, + _("lima.common.confirmation"), JOptionPane.YES_NO_OPTION); + + if (response == JOptionPane.YES_OPTION) { + + try { + tableModel.removeObject(selectedValue, indexSelectedRow); + //select the upper line + ListSelectionModel selectionModel = + table.getSelectionModel(); + selectionModel.setSelectionInterval( + indexSelectedRow-1, indexSelectedRow-1); + } catch (LimaException eee) { + if (log.isErrorEnabled()) { + log.error("Can't remove transaction or entry", eee); + } + DialogHelper.showMessageDialog(eee.getMessage()); + } + } + } + else { + if (log.isWarnEnabled()) { + log.warn("Call delete selected row without selection"); + } + } + } + + + //implement new transaction button + //add a new entry to the selected transaction + public void addEmptyEntry(){ + + table = view.getFinancialTransactionSearchTable(); + tableModel = view.getFinancialTransactionSearchTableModel(); + + int indexSelectedRow = table.getSelectedRow(); + if (indexSelectedRow != -1) { + Object selectedValue = tableModel.getElementAt(indexSelectedRow); + try { + //copy + paste the description + String description = (String) tableModel.getValueAt(indexSelectedRow, 4); + tableModel.addEmptyEntry(selectedValue, description, indexSelectedRow); + //select the new line + ListSelectionModel selectionModel = + table.getSelectionModel(); + selectionModel.setSelectionInterval( + indexSelectedRow+1, indexSelectedRow+1); + //focus on second column + table.changeSelection(indexSelectedRow+1, 1, false, false); + table.requestFocusInWindow(); + } catch (LimaException eee){ + if (log.isErrorEnabled()) { + log.error("Can't add emptyentry", eee); + } + DialogHelper.showMessageDialog(eee.getMessage()); + } + } + else { + if (log.isWarnEnabled()) { + log.warn("Call addentry selected transaction without selection"); + } + } + } + + + //copy entry + public void copyRow(){ + table = view.getFinancialTransactionSearchTable(); + int indexSelectedRow = table.getSelectedRow(); + + if (indexSelectedRow != -1) { + clipBoard = tableModel.getElementAt(indexSelectedRow); + } + } + + //paste entry + public void pasteRow(){ + table = view.getFinancialTransactionSearchTable(); + int indexSelectedRow = table.getSelectedRow(); + + if (indexSelectedRow != -1) { + Object selectedValue = tableModel.getElementAt(indexSelectedRow); + if (clipBoard instanceof Entry) { + try { + tableModel.addEntry(selectedValue, (Entry) clipBoard, indexSelectedRow); + //select the new line + ListSelectionModel selectionModel = + table.getSelectionModel(); + selectionModel.setSelectionInterval( + indexSelectedRow+1, indexSelectedRow+1); + //focus on second column + table.changeSelection(indexSelectedRow+1, 1, false, false); + table.requestFocusInWindow(); + } catch (LimaException eee){ + if (log.isErrorEnabled()) { + log.error("Can't past entry", eee); + } + DialogHelper.showMessageDialog(eee.getMessage()); + } + } + + } + + } + + + //add a new transaction + public void addFinancialTransaction() { + table = view.getFinancialTransactionSearchTable(); + tableModel = view.getFinancialTransactionSearchTableModel(); + + try { + tableModel.addFinancialTransaction(); + //select the new line + int numberRow = table.getRowCount(); + ListSelectionModel selectionModel = + table.getSelectionModel(); + selectionModel.setSelectionInterval(numberRow-1, numberRow-1); + //focus on first column + table.changeSelection(numberRow-1, 0, false, false); + table.requestFocusInWindow(); + } catch (LimaException eee) { + if (log.isErrorEnabled()) { + log.error("Can't add financialtransaction", eee); + } + DialogHelper.showMessageDialog(eee.getMessage()); + } + } + + public void refresh(){ tableModel = view.getFinancialTransactionSearchTableModel(); if (tableModel != null){