ExpenseReport.java Source code

Java tutorial

Introduction

Here is the source code for ExpenseReport.java

Source

/*
Swing, Second Edition
by Matthew Robinson, Pavel Vorobiev
    
*/

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
import java.text.SimpleDateFormat;

import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;
import javax.swing.table.*;

public class ExpenseReport extends JFrame {
    protected JTable m_table;
    protected ExpenseReportData m_data;
    protected JLabel m_title;

    public ExpenseReport() {
        super("Expense Report");
        setSize(570, 200);

        m_data = new ExpenseReportData(this);

        m_table = new JTable();
        m_table.setAutoCreateColumnsFromModel(false);
        m_table.setModel(m_data);
        m_table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

        for (int k = 0; k < ExpenseReportData.m_columns.length; k++) {
            TableCellRenderer renderer;
            if (k == ExpenseReportData.COL_APPROVED)
                renderer = new CheckCellRenderer();
            else {
                DefaultTableCellRenderer textRenderer = new DefaultTableCellRenderer();
                textRenderer.setHorizontalAlignment(ExpenseReportData.m_columns[k].m_alignment);
                renderer = textRenderer;
            }

            TableCellEditor editor;

            if (k == ExpenseReportData.COL_CATEGORY)
                editor = new DefaultCellEditor(new JComboBox(ExpenseReportData.CATEGORIES));
            else if (k == ExpenseReportData.COL_APPROVED)
                editor = new DefaultCellEditor(new JCheckBox());
            else
                editor = new DefaultCellEditor(new JTextField());

            TableColumn column = new TableColumn(k, ExpenseReportData.m_columns[k].m_width, renderer, editor);
            m_table.addColumn(column);
        }

        JTableHeader header = m_table.getTableHeader();
        header.setUpdateTableInRealTime(false);

        JScrollPane ps = new JScrollPane();
        ps.setSize(550, 150);
        ps.getViewport().add(m_table);
        getContentPane().add(ps, BorderLayout.CENTER);

        JPanel p = new JPanel();
        p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));

        ImageIcon penny = new ImageIcon("penny.gif");
        m_title = new JLabel("Total: $", penny, JButton.LEFT);
        m_title.setForeground(Color.black);
        m_title.setAlignmentY(0.5f);
        p.add(m_title);
        p.add(Box.createHorizontalGlue());

        JButton bt = new JButton("Insert before");
        bt.setMnemonic('b');
        bt.setAlignmentY(0.5f);
        ActionListener lst = new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                int row = m_table.getSelectedRow();
                m_data.insert(row);
                m_table.tableChanged(
                        new TableModelEvent(m_data, row, row, TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));
                m_table.repaint();
            }
        };
        bt.addActionListener(lst);
        p.add(bt);

        bt = new JButton("Insert after");
        bt.setMnemonic('a');
        bt.setAlignmentY(0.5f);
        lst = new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                int row = m_table.getSelectedRow();
                m_data.insert(row + 1);
                m_table.tableChanged(new TableModelEvent(m_data, row + 1, row + 1, TableModelEvent.ALL_COLUMNS,
                        TableModelEvent.INSERT));
                m_table.repaint();
            }
        };
        bt.addActionListener(lst);
        p.add(bt);

        bt = new JButton("Delete row");
        bt.setMnemonic('d');
        bt.setAlignmentY(0.5f);
        lst = new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                int row = m_table.getSelectedRow();
                if (m_data.delete(row)) {
                    m_table.tableChanged(new TableModelEvent(m_data, row, row, TableModelEvent.ALL_COLUMNS,
                            TableModelEvent.INSERT));
                    m_table.repaint();
                    calcTotal();
                }
            }
        };
        bt.addActionListener(lst);
        p.add(bt);

        getContentPane().add(p, BorderLayout.SOUTH);

        calcTotal();

        WindowListener wndCloser = new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        };
        addWindowListener(wndCloser);

        setVisible(true);
    }

    public void calcTotal() {
        double total = 0;
        for (int k = 0; k < m_data.getRowCount(); k++) {
            Double amount = (Double) m_data.getValueAt(k, ExpenseReportData.COL_AMOUNT);
            total += amount.doubleValue();
        }
        m_title.setText("Total: $" + total);
    }

    public static void main(String argv[]) {
        new ExpenseReport();
    }
}

class CheckCellRenderer extends JCheckBox implements TableCellRenderer {
    protected static Border m_noFocusBorder;

    public CheckCellRenderer() {
        super();
        m_noFocusBorder = new EmptyBorder(1, 2, 1, 2);
        setOpaque(true);
        setBorder(m_noFocusBorder);
    }

    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
            int row, int column) {
        if (value instanceof Boolean) {
            Boolean b = (Boolean) value;
            setSelected(b.booleanValue());
        }

        setBackground(isSelected && !hasFocus ? table.getSelectionBackground() : table.getBackground());
        setForeground(isSelected && !hasFocus ? table.getSelectionForeground() : table.getForeground());

        setFont(table.getFont());
        setBorder(hasFocus ? UIManager.getBorder("Table.focusCellHighlightBorder") : m_noFocusBorder);

        return this;
    }
}

class ExpenseData {
    public Date m_date;
    public Double m_amount;
    public Integer m_category;
    public Boolean m_approved;
    public String m_description;

    public ExpenseData() {
        m_date = new Date();
        m_amount = new Double(0);
        m_category = new Integer(1);
        m_approved = new Boolean(false);
        m_description = "";
    }

    public ExpenseData(Date date, double amount, int category, boolean approved, String description) {
        m_date = date;
        m_amount = new Double(amount);
        m_category = new Integer(category);
        m_approved = new Boolean(approved);
        m_description = description;
    }
}

class ColumnData {
    public String m_title;
    int m_width;
    int m_alignment;

    public ColumnData(String title, int width, int alignment) {
        m_title = title;
        m_width = width;
        m_alignment = alignment;
    }
}

class ExpenseReportData extends AbstractTableModel {
    public static final ColumnData m_columns[] = { new ColumnData("Date", 80, JLabel.LEFT),
            new ColumnData("Amount", 80, JLabel.RIGHT), new ColumnData("Category", 130, JLabel.LEFT),
            new ColumnData("Approved", 80, JLabel.LEFT), new ColumnData("Description", 180, JLabel.LEFT) };

    public static final int COL_DATE = 0;
    public static final int COL_AMOUNT = 1;
    public static final int COL_CATEGORY = 2;
    public static final int COL_APPROVED = 3;
    public static final int COL_DESCR = 4;

    public static final String[] CATEGORIES = { "Fares", "Logging", "Business meals", "Others" };

    protected ExpenseReport m_parent;
    protected SimpleDateFormat m_frm;
    protected Vector m_vector;

    public ExpenseReportData(ExpenseReport parent) {
        m_parent = parent;
        m_frm = new SimpleDateFormat("MM/dd/yy");
        m_vector = new Vector();
        setDefaultData();
    }

    public void setDefaultData() {
        m_vector.removeAllElements();
        try {
            m_vector.addElement(new ExpenseData(m_frm.parse("04/06/99"), 200, 0, true, "Airline tickets"));
            m_vector.addElement(new ExpenseData(m_frm.parse("04/06/99"), 50, 2, false, "Lunch with client"));
            m_vector.addElement(new ExpenseData(m_frm.parse("04/06/99"), 120, 1, true, "Hotel"));
        } catch (java.text.ParseException ex) {
        }
    }

    public int getRowCount() {
        return m_vector == null ? 0 : m_vector.size();
    }

    public int getColumnCount() {
        return m_columns.length;
    }

    public String getColumnName(int column) {
        return m_columns[column].m_title;
    }

    public boolean isCellEditable(int nRow, int nCol) {
        return true;
    }

    public Object getValueAt(int nRow, int nCol) {
        if (nRow < 0 || nRow >= getRowCount())
            return "";
        ExpenseData row = (ExpenseData) m_vector.elementAt(nRow);
        switch (nCol) {
        case COL_DATE:
            return m_frm.format(row.m_date);
        case COL_AMOUNT:
            return row.m_amount;
        case COL_CATEGORY:
            return CATEGORIES[row.m_category.intValue()];
        case COL_APPROVED:
            return row.m_approved;
        case COL_DESCR:
            return row.m_description;
        }
        return "";
    }

    public void setValueAt(Object value, int nRow, int nCol) {
        if (nRow < 0 || nRow >= getRowCount())
            return;
        ExpenseData row = (ExpenseData) m_vector.elementAt(nRow);
        String svalue = value.toString();

        switch (nCol) {
        case COL_DATE:
            Date date = null;
            try {
                date = m_frm.parse(svalue);
            } catch (java.text.ParseException ex) {
                date = null;
            }
            if (date == null) {
                JOptionPane.showMessageDialog(null, svalue + " is not a valid date", "Warning",
                        JOptionPane.WARNING_MESSAGE);
                return;
            }
            row.m_date = date;
            break;
        case COL_AMOUNT:
            try {
                row.m_amount = new Double(svalue);
            } catch (NumberFormatException e) {
                break;
            }
            m_parent.calcTotal();
            break;
        case COL_CATEGORY:
            for (int k = 0; k < CATEGORIES.length; k++)
                if (svalue.equals(CATEGORIES[k])) {
                    row.m_category = new Integer(k);
                    break;
                }
            break;
        case COL_APPROVED:
            row.m_approved = (Boolean) value;
            break;
        case COL_DESCR:
            row.m_description = svalue;
            break;
        }
    }

    public void insert(int row) {
        if (row < 0)
            row = 0;
        if (row > m_vector.size())
            row = m_vector.size();
        m_vector.insertElementAt(new ExpenseData(), row);
    }

    public boolean delete(int row) {
        if (row < 0 || row >= m_vector.size())
            return false;
        m_vector.remove(row);
        return true;
    }
}