package es.icarto.gvsig.navtableforms.calculation; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.math.BigDecimal; import java.text.NumberFormat; import java.text.ParseException; import java.util.HashMap; import java.util.Map; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JFormattedTextField; import javax.swing.JTextArea; import javax.swing.JTextField; import org.apache.log4j.Logger; import es.icarto.gvsig.navtableforms.IValidatableForm; import es.icarto.gvsig.navtableforms.ormlite.domainvalues.KeyValue; import es.udc.cartolab.gvsig.navtable.format.DoubleFormatNT; public abstract class Calculation { private static final Logger logger = Logger.getLogger(Calculation.class); protected JTextField resultWidget; protected HashMap<String, JComponent> operands; protected OperandComponentListener handler; private final Map<String, JComponent> formWidgets; protected IValidatableForm form; protected final NumberFormat formatter = DoubleFormatNT .getBigDecimalFormat(); private boolean calculateOnlyWhenValid = true; // TODO: Maybe this class should have a fillValues method. It will be used // to re-calculate the value and set it if the operator values have changed // outside the form public Calculation(IValidatableForm form) { this.form = form; formWidgets = form.getWidgets(); resultWidget = (JTextField) formWidgets.get(resultName()); operands = new HashMap<String, JComponent>(); for (String name : operandNames()) { operands.put(name, formWidgets.get(name)); } this.handler = new OperandComponentListener(); } protected void setCalculateOnlyWhenValid(boolean calculateOnlyWhenValid) { this.calculateOnlyWhenValid = calculateOnlyWhenValid; } protected abstract String resultName(); protected abstract String[] operandNames(); protected void setValue(boolean valid) { if (calculateOnlyWhenValid && !valid) { return; } String value = ""; if (!allEmpty()) { value = calculate(); } resultWidget.setText(value); form.getFormController().setValue(resultName(), value); // We must assert that the new value in resultWidgets, passes the // validation (or not) form.validateForm(); } protected abstract String calculate(); public void setListeners() { for (JComponent widget : operands.values()) { if (widget instanceof JFormattedTextField) { ((JFormattedTextField) widget).addKeyListener(handler); } else if (widget instanceof JTextField) { ((JTextField) widget).addKeyListener(handler); } else if (widget instanceof JComboBox) { ((JComboBox) widget).addActionListener(handler); } else if (widget instanceof JCheckBox) { ((JCheckBox) widget).addActionListener(handler); } else if (widget instanceof JTextArea) { ((JTextArea) widget).addKeyListener(handler); } } } public void removeListeners() { for (JComponent widget : operands.values()) { if (widget instanceof JFormattedTextField) { ((JFormattedTextField) widget).removeKeyListener(handler); } else if (widget instanceof JTextField) { ((JTextField) widget).removeKeyListener(handler); } else if (widget instanceof JComboBox) { ((JComboBox) widget).removeActionListener(handler); } else if (widget instanceof JCheckBox) { ((JCheckBox) widget).removeActionListener(handler); } else if (widget instanceof JTextArea) { ((JTextArea) widget).removeKeyListener(handler); } } } public class OperandComponentListener implements KeyListener, ActionListener { @Override public void keyTyped(KeyEvent e) { } @Override public void keyPressed(KeyEvent e) { } @Override public void keyReleased(KeyEvent e) { delegate(); } @Override public void actionPerformed(ActionEvent e) { delegate(); } private void delegate() { if (!form.isFillingValues()) { form.validateForm(); setValue(!form.getValidatorForm().hasValidationErrors()); } } } /** * * @return true when all the operator components are empty */ protected boolean allEmpty() { for (JComponent c : operands.values()) { if (c instanceof JFormattedTextField) { if (!((JFormattedTextField) c).getText().trim().isEmpty()) { return false; } } else if (c instanceof JTextField) { if (!((JTextField) c).getText().trim().isEmpty()) { return false; } } else if (c instanceof JComboBox) { JComboBox jcomboBox = ((JComboBox) c); final Object selectedItem = jcomboBox.getSelectedItem(); if ((selectedItem != null) && !selectedItem.toString().trim().isEmpty()) { return false; } } else if (c instanceof JTextArea) { if (!((JTextArea) c).getText().trim().isEmpty()) { return false; } } } return true; } protected BigDecimal operandValue(String name) { JComponent jComponent = operands.get(name); String importe = ""; if (jComponent instanceof JTextField) { importe = ((JTextField) jComponent).getText().trim(); } else if (jComponent instanceof JComboBox) { Object selectedItem = ((JComboBox) jComponent).getSelectedItem(); if (selectedItem != null) { if (selectedItem instanceof KeyValue) { importe = ((KeyValue) selectedItem).getKey(); } else { importe = selectedItem.toString().trim(); } } } BigDecimal value = new BigDecimal(0); if (!importe.isEmpty()) { try { value = (BigDecimal) formatter.parse(importe); } catch (ParseException e) { logger.error(e.getStackTrace(), e); } } return value; } }