421 lines
14 KiB
Java
421 lines
14 KiB
Java
|
|
import java.awt.*;
|
|
import java.awt.event.*;
|
|
import javax.swing.*;
|
|
import java.util.*;
|
|
|
|
/*
|
|
* The main work of the application is done in this JPanel-extending class.
|
|
* This allows the java class to be run as a stand-alone application or
|
|
* as an applet within a web browser.
|
|
*/
|
|
class RetirementCalculatorPanel
|
|
extends JPanel
|
|
implements ActionListener, FocusListener
|
|
{
|
|
private RetirementCalculatorModel myModel;
|
|
|
|
private JComponent makeDivider() { return new JLabel(" "); }
|
|
|
|
private HashMap<String, JComponent> myFields;
|
|
private HashMap<JComponent, String> myToolTips;
|
|
private JButton myCalculateButton;
|
|
private JButton myPrintButton;
|
|
private JButton myResetButton;
|
|
private JLabel myResultBox;
|
|
private JLabel myToolTipBox;
|
|
private JTextField myNameField;
|
|
|
|
class ComboChoice
|
|
{
|
|
private String myDesc;
|
|
private int myVal;
|
|
ComboChoice(int val, String desc)
|
|
{
|
|
myDesc = desc;
|
|
myVal = val;
|
|
}
|
|
public String toString() { return myDesc; }
|
|
public int getVal() { return myVal; }
|
|
}
|
|
|
|
private final ComboChoice[] retirement_age_choices = {
|
|
new ComboChoice(55, "55"),
|
|
new ComboChoice(60, "60"),
|
|
new ComboChoice(65, "65"),
|
|
new ComboChoice(70, "70")
|
|
};
|
|
|
|
private final ComboChoice[] life_expectancy_choices = {
|
|
new ComboChoice(82, "82 (Male; 50th percentile)"),
|
|
new ComboChoice(86, "86 (Female; 50th percentile)"),
|
|
new ComboChoice(89, "89 (Male; 75th percentile)"),
|
|
new ComboChoice(92, "92 (Female; 75th percentile)"),
|
|
new ComboChoice(94, "94 (Male; 90th percentile)"),
|
|
new ComboChoice(97, "97 (Female; 90th percentile)")
|
|
};
|
|
|
|
private static int row = 0;
|
|
private void addRow(JPanel panel, JComponent c1, JComponent c2)
|
|
{
|
|
GridBagConstraints c = new GridBagConstraints();
|
|
c.fill = GridBagConstraints.HORIZONTAL;
|
|
c.insets = new Insets(0, 4, 0, 4);
|
|
c.ipadx = 2;
|
|
c.gridwidth = 1;
|
|
c.gridheight = 1;
|
|
c.gridx = 0;
|
|
c.weightx = 0.0;
|
|
c.gridy = row;
|
|
panel.add(c1, c);
|
|
|
|
c.gridx++;
|
|
c.weightx = 1.0;
|
|
panel.add(c2, c);
|
|
|
|
row++;
|
|
}
|
|
private void addDollarRow(JPanel panel, JComponent c1, JComponent c2)
|
|
{
|
|
JPanel dollar_panel = new JPanel();
|
|
dollar_panel.setLayout(new BoxLayout(dollar_panel, BoxLayout.X_AXIS));
|
|
dollar_panel.add(new JLabel("$"));
|
|
dollar_panel.add(c2);
|
|
addRow(panel, c1, dollar_panel);
|
|
}
|
|
private void addRow(JPanel panel, JComponent c1)
|
|
{
|
|
GridBagConstraints c = new GridBagConstraints();
|
|
c.fill = GridBagConstraints.HORIZONTAL;
|
|
c.insets = new Insets(0, 4, 0, 4);
|
|
c.ipadx = 2;
|
|
c.gridwidth = 2;
|
|
c.gridheight = 1;
|
|
c.gridx = 0;
|
|
c.weightx = 0.0;
|
|
c.gridy = row;
|
|
panel.add(c1, c);
|
|
|
|
row++;
|
|
}
|
|
|
|
public RetirementCalculatorPanel()
|
|
{
|
|
super(new BorderLayout());
|
|
|
|
myModel = new RetirementCalculatorModel();
|
|
myFields = new HashMap<String, JComponent>();
|
|
myToolTips = new HashMap<JComponent, String>();
|
|
JPanel inner = new JPanel(new GridBagLayout());
|
|
myToolTipBox = new JLabel(" ", SwingConstants.CENTER);
|
|
JComponent field;
|
|
|
|
myNameField = new JTextField();
|
|
myNameField.addFocusListener(this);
|
|
myToolTips.put(myNameField, "Enter your name.");
|
|
myToolTipBox.setText("Enter your name.");
|
|
addRow(inner, new JLabel("What is your name?", SwingConstants.RIGHT),
|
|
myNameField);
|
|
|
|
field = new JTextField();
|
|
field.addFocusListener(this);
|
|
myFields.put("age", field);
|
|
myToolTips.put(field, "Enter your current age.");
|
|
addRow(inner, new JLabel("What is your age?", SwingConstants.RIGHT),
|
|
field);
|
|
|
|
addRow(inner, makeDivider());
|
|
|
|
field = new JTextField();
|
|
field.addFocusListener(this);
|
|
myFields.put("income wanted", field);
|
|
myToolTips.put(field, "Enter the amount of income that you would like to receive in a year while you are retired.");
|
|
addDollarRow(inner,
|
|
new JLabel("How much annual income will you want in retirement?",
|
|
SwingConstants.RIGHT),
|
|
field);
|
|
|
|
field = new JTextField();
|
|
field.addFocusListener(this);
|
|
myFields.put("current income", field);
|
|
myToolTips.put(field, "Enter the amount of income that you currently receive in a year.");
|
|
addDollarRow(inner,
|
|
new JLabel("What is your current annual income?",
|
|
SwingConstants.RIGHT),
|
|
field);
|
|
|
|
addRow(inner, makeDivider());
|
|
|
|
addRow(inner,
|
|
new JLabel("What is your expected annual income after retirement..."));
|
|
|
|
field = new JTextField();
|
|
field.addFocusListener(this);
|
|
myFields.put("employer pension", field);
|
|
myToolTips.put(field, "If your employer has a pension plan that will pay you a certain amount<br/>after you retire from them, then enter that amount here.");
|
|
addDollarRow(inner,
|
|
new JLabel("... from an employer pension plan?",
|
|
SwingConstants.RIGHT),
|
|
field);
|
|
|
|
field = new JTextField();
|
|
field.addFocusListener(this);
|
|
myFields.put("part time income", field);
|
|
myToolTips.put(field, "Enter how much income you expect to make working at a part-time job after retirement.");
|
|
addDollarRow(inner,
|
|
new JLabel("... from a part-time job?", SwingConstants.RIGHT),
|
|
field);
|
|
|
|
field = new JTextField();
|
|
field.addFocusListener(this);
|
|
myFields.put("other income", field);
|
|
myToolTips.put(field, "If there is any other annual income you expect to receive after retirement<br/>not already accounted for, enter the amount here.");
|
|
addDollarRow(inner, new JLabel("... other?", SwingConstants.RIGHT), field);
|
|
|
|
addRow(inner, makeDivider());
|
|
|
|
field = new JTextField();
|
|
field.addFocusListener(this);
|
|
myFields.put("savings", field);
|
|
myToolTips.put(field, "Enter the amount of money that you have saved right now.");
|
|
addDollarRow(inner,
|
|
new JLabel("How much savings do you have to date?",
|
|
SwingConstants.RIGHT),
|
|
field);
|
|
|
|
field = new JComboBox(retirement_age_choices);
|
|
field.addFocusListener(this);
|
|
myFields.put("retirement age", field);
|
|
myToolTips.put(field, "Select the age at which you are planning to reture.");
|
|
addRow(inner,
|
|
new JLabel("At what age do you expect to retire?",
|
|
SwingConstants.RIGHT),
|
|
field);
|
|
|
|
field = new JComboBox(life_expectancy_choices);
|
|
field.addFocusListener(this);
|
|
myFields.put("life expectancy", field);
|
|
myToolTips.put(field, "Select what you think your life expectancy is.");
|
|
addRow(inner,
|
|
new JLabel("What is your life expectancy?",
|
|
SwingConstants.RIGHT),
|
|
field);
|
|
|
|
addRow(inner, makeDivider());
|
|
|
|
JPanel buttons = new JPanel();
|
|
buttons.setLayout(new BoxLayout(buttons, BoxLayout.X_AXIS));
|
|
buttons.add(Box.createHorizontalGlue());
|
|
myCalculateButton = new JButton("Calculate");
|
|
myCalculateButton.addActionListener(this);
|
|
buttons.add(myCalculateButton);
|
|
buttons.add(Box.createRigidArea(new Dimension(10, 0)));
|
|
myPrintButton = new JButton("Print");
|
|
myPrintButton.addActionListener(this);
|
|
buttons.add(myPrintButton);
|
|
buttons.add(Box.createRigidArea(new Dimension(10, 0)));
|
|
myResetButton = new JButton("Reset");
|
|
myResetButton.addActionListener(this);
|
|
buttons.add(myResetButton);
|
|
buttons.add(Box.createHorizontalGlue());
|
|
|
|
addRow(inner, myToolTipBox);
|
|
|
|
// addRow(inner, makeDivider());
|
|
|
|
addRow(inner, buttons);
|
|
|
|
// addRow(inner, makeDivider());
|
|
|
|
JScrollPane scrollpane = new JScrollPane(inner,
|
|
ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
|
|
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
|
add(scrollpane);
|
|
|
|
myResultBox = new JLabel("", SwingConstants.CENTER);
|
|
myResultBox.setForeground(new Color(0, 0, 200));
|
|
add(myResultBox, BorderLayout.SOUTH);
|
|
|
|
reset();
|
|
}
|
|
|
|
public void actionPerformed(ActionEvent e)
|
|
{
|
|
if (e.getSource() == myCalculateButton)
|
|
calculate();
|
|
else if (e.getSource() == myResetButton)
|
|
reset();
|
|
else if (e.getSource() == myPrintButton)
|
|
print();
|
|
}
|
|
|
|
public void focusGained(FocusEvent e)
|
|
{
|
|
if (e.getComponent().getClass() == JTextField.class)
|
|
{
|
|
((JTextField) e.getComponent()).selectAll();
|
|
}
|
|
String tooltip = myToolTips.get(e.getComponent());
|
|
if (tooltip != null)
|
|
{
|
|
if (tooltip.indexOf("<br") < 0)
|
|
{
|
|
tooltip = tooltip + "<br/> ";
|
|
}
|
|
myToolTipBox.setText("<html>" + tooltip + "</html>");
|
|
}
|
|
}
|
|
|
|
public void focusLost(FocusEvent e)
|
|
{
|
|
}
|
|
|
|
private void calculate()
|
|
{
|
|
Iterator it = myFields.keySet().iterator();
|
|
while (it.hasNext())
|
|
{
|
|
String key = (String) it.next();
|
|
JComponent comp = myFields.get(key);
|
|
if (comp.getClass() == JTextField.class)
|
|
{
|
|
JTextField tf = (JTextField) comp;
|
|
myModel.setField(key, Double.parseDouble(tf.getText()));
|
|
}
|
|
else if (comp.getClass() == JComboBox.class)
|
|
{
|
|
JComboBox cb = (JComboBox) comp;
|
|
myModel.setField(key,
|
|
((ComboChoice) cb.getSelectedItem()).getVal());
|
|
}
|
|
}
|
|
|
|
myModel.calculate();
|
|
myResultBox.setText("<html>The total amount of savings needed at retirement is $" +
|
|
String.format("%,.02f", myModel.getField("total additional savings needed")) +
|
|
".<br/> The annual amount of savings needed is $" +
|
|
String.format("%,.02f", myModel.getField("annual savings needed")) + "</html>");
|
|
}
|
|
|
|
private void reset()
|
|
{
|
|
myModel.reset();
|
|
Iterator it = myFields.keySet().iterator();
|
|
while (it.hasNext())
|
|
{
|
|
String key = (String) it.next();
|
|
JComponent comp = myFields.get(key);
|
|
if (comp.getClass() == JTextField.class)
|
|
{
|
|
JTextField tf = (JTextField) comp;
|
|
double val = myModel.getField(key);
|
|
tf.setText(String.format(
|
|
key.equals("age") ? "%.0f" : "%.2f", val));
|
|
}
|
|
else if (comp.getClass() == JComboBox.class)
|
|
{
|
|
JComboBox cb = (JComboBox) comp;
|
|
int val = (int) myModel.getField(key);
|
|
ComboChoice[] ccp = null;
|
|
if (key.equals("retirement age"))
|
|
ccp = retirement_age_choices;
|
|
else if (key.equals("life expectancy"))
|
|
ccp = life_expectancy_choices;
|
|
if (ccp != null)
|
|
{
|
|
for (ComboChoice cc : ccp)
|
|
{
|
|
if (cc.getVal() == val)
|
|
{
|
|
cb.setSelectedItem(cc);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
myNameField.setText("");
|
|
myResultBox.setText(" ");
|
|
}
|
|
|
|
private String fmt(String fmt, String field)
|
|
{
|
|
return String.format(fmt, myModel.getField(field));
|
|
}
|
|
|
|
private void print()
|
|
{
|
|
calculate();
|
|
String endl = "<br/>";
|
|
String msg = "<html>";
|
|
msg += "Name: " + myNameField.getText() + endl;
|
|
msg += "Age: " + fmt("%.0f", "age") + endl;
|
|
msg += "Retirement age: " + fmt("%.0f", "retirement age") + endl;
|
|
msg += "Current income: $" + fmt("%,.02f", "current income") + endl;
|
|
msg += "Desired annual income: $" +
|
|
fmt("%,.02f", "income wanted") + endl;
|
|
msg += endl;
|
|
msg += "Social Security benefit: $" +
|
|
fmt("%,.02f", "social security") + endl;
|
|
msg += "Traditional Employer Pension: $" +
|
|
fmt("%,.02f", "employer pension") + endl;
|
|
msg += "Part-time income: $" + fmt("%,.02f", "part time income") + endl;
|
|
msg += "Other income: $" + fmt("%,.02f", "other income") + endl;
|
|
msg += "Amount to make up each retirement year: $" +
|
|
fmt("%,.02f", "amount to make up") + endl;
|
|
msg += endl;
|
|
msg += "Total amount to save: $" +
|
|
fmt("%,.02f", "amount to save") + endl;
|
|
msg += "Early retirement addition: $" +
|
|
fmt("%,.02f", "early retirement penalty") + endl;
|
|
msg += "Estimated savings at retirement: $" +
|
|
fmt("%,.02f", "estimated savings") + endl;
|
|
msg += endl;
|
|
msg += "Total additional savings needed at retirement: $" +
|
|
fmt("%,.02f", "total additional savings needed") + endl;
|
|
msg += "Required annual savings: $" +
|
|
fmt("%,.02f", "annual savings needed") + endl;
|
|
msg += "</html>";
|
|
JOptionPane.showMessageDialog(null, msg,
|
|
"Basic Retirement Calculator", JOptionPane.PLAIN_MESSAGE);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* The "main" class of this file allows the app to be run as an applet
|
|
* but also provides a "main" method to run as an application.
|
|
*/
|
|
public class RetirementCalculator extends JApplet
|
|
{
|
|
final static private String PROG_NAME = "Josh's Retirement Calculator";
|
|
|
|
RetirementCalculatorPanel panel;
|
|
|
|
public void init()
|
|
{
|
|
setLayout(new BorderLayout());
|
|
panel = new RetirementCalculatorPanel();
|
|
add(panel, BorderLayout.CENTER);
|
|
}
|
|
|
|
public static void main(String[] args)
|
|
{
|
|
javax.swing.SwingUtilities.invokeLater(new Runnable() {
|
|
public void run()
|
|
{
|
|
JFrame frame = new JFrame(PROG_NAME);
|
|
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
|
|
|
RetirementCalculatorPanel panel =
|
|
new RetirementCalculatorPanel();
|
|
frame.getContentPane().add(panel);
|
|
|
|
frame.setPreferredSize(new Dimension(600, 450));
|
|
|
|
frame.pack();
|
|
frame.setVisible(true);
|
|
}
|
|
});
|
|
}
|
|
}
|