import java.awt.*;
import java.awt.event.*;
import java.awt.font.*;
import java.awt.geom.*;
import java.io.*;
import java.text.*;
import java.util.Locale;
import javax.swing.*;
import javax.swing.border.*;
public class MC extends JFrame implements ActionListener {
JTextField principalTxt, termTxt, rateTxt, monthlyPaymentTxt;
JTextArea displayArea;
JButton calculateButton, graphButton, amortizeButton, clearButton, exitButton;
JComboBox options;
// Can these 6 be removed and declared as local variables?
int term = 0;
double principal = 0;
double rate = 0;
double monthlyPayment = 0;
double interest = 0;
int notePeriod = 0;
int[] termArray;
double[] rateArray;
private float[] monthlyPrincipal;
private float[] interestPaid;
public MC() {
super ("Mortgage Payment Calculator by S Kemen");
load();
// Initialize components.
JPanel row1 = new JPanel();
JLabel mortgageLabel = new JLabel("MORTGAGE PAYMENT CALCULATOR", JLabel.CENTER);
JPanel row2 = new JPanel(new GridLayout(1, 2));
JLabel principalLabel = new JLabel("Mortgage Principal $",JLabel.LEFT);
principalTxt = new JTextField(10);
JPanel row3 = new JPanel(new GridLayout(1, 2));
JLabel termLabel = new JLabel("Mortgage Term (Yrs)",JLabel.LEFT);
termTxt = new JTextField(10);
JPanel row4 = new JPanel(new GridLayout(1, 2));
JLabel rateLabel = new JLabel("Interest Rate (%)", JLabel.LEFT);
rateTxt = new JTextField(10);
JPanel row5 = new JPanel(new GridLayout(1, 2));
JLabel presetLabel = new JLabel("Preset Term and Interest Rate:", JLabel.LEFT);
// JPanel row6 = new JPanel();
// JComboBox choices = new JComboBox();
options = new JComboBox();
MessageFormat mf = new MessageFormat("{0} years at {1,number,#.##}%");
JLabel choiceLabel = new JLabel(" (choose rate)");
for (int i = 0; i < termArray.length; i++) {
options.addItem(mf.format(new Object[] { new Integer(termArray [i]),
new Double(rateArray[i])}));
}
JPanel row6 = new JPanel(new GridLayout(1, 2));
JLabel monthlyPaymentLabel = new JLabel("Monthly Payment $", JLabel.LEFT);
monthlyPaymentTxt = new JTextField(10);
//create buttons
JPanel button = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 10));
graphButton = new JButton("Display Graph");
amortizeButton = new JButton("Amortize Payments");
clearButton = new JButton("Clear");
exitButton = new JButton("Exit");
calculateButton = new JButton("Calculate");
//create textarea to display Amortize output
displayArea = new JTextArea(10, 45);
JScrollPane scroll = new JScrollPane(displayArea);
Container pane = getContentPane();
// Set layout before adding components.
pane.setLayout(new BoxLayout( pane, BoxLayout.Y_AXIS));
Border rowborder = new EmptyBorder( 3, 10, 3, 10 );
pane.add(row1);
row1.add(mortgageLabel);
row1.setMaximumSize( new Dimension( 10000, row1.getMinimumSize().height));
row1.setBorder( rowborder);
pane.add(row2);
row2.add(principalLabel);
row2.add(principalTxt);
row2.setMaximumSize( new Dimension( 10000, row2.getMinimumSize().height));
row2.setBorder( rowborder);
pane.add(row3);
row3.add(termLabel);
row3.add(termTxt);
row3.setMaximumSize( new Dimension( 10000, row3.getMinimumSize().height));
row3.setBorder( rowborder);
pane.add(row4);
row4.add(rateLabel);
row4.add(rateTxt);
row4.setMaximumSize( new Dimension( 10000, row4.getMinimumSize().height));
row4.setBorder( rowborder);
pane.add(row5);
row5.add(presetLabel);
row5.setMaximumSize( new Dimension( 10000, row4.getMinimumSize().height));
row5.setBorder( rowborder);
pane.add(row6);
row6.add(choiceLabel);
row6.setMaximumSize( new Dimension( 10000, row4.getMinimumSize().height));
row6.setBorder( rowborder);
// Left this out
JPanel radioPanel = new JPanel();
radioPanel.setLayout(new FlowLayout(FlowLayout.RIGHT, 4, 4 ));
// radioPanel.add(choices);
radioPanel.add(options);
pane.add(radioPanel);
radioPanel.setMaximumSize( new Dimension( 10000,
radioPanel.getMinimumSize().height));
radioPanel.setBorder( rowborder);
// Left this out
JPanel row7 = new JPanel();
pane.add(row7);
row7.add(monthlyPaymentLabel);
row7.add(monthlyPaymentTxt);
monthlyPaymentTxt.setEnabled(false); //set payment amount uneditable
row7.setMaximumSize( new Dimension( 10000, row5.getMinimumSize().height));
row7.setBorder( rowborder);
//Add buttons
button.add(calculateButton);
button.add(clearButton);
button.add(exitButton);
button.add(amortizeButton);
button.add(graphButton);
pane.add(button);
button.setMaximumSize( new Dimension( 10000, button.getMinimumSize().height));
//scroll text pane for Amortize output
scroll.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
pane.add(scroll);
setContentPane(pane);
//add listeners for buttons and combo box
// choice.addActionListener(this);
options.addActionListener(this);
clearButton.addActionListener(this);
exitButton.addActionListener(this);
calculateButton.addActionListener(this);
amortizeButton.addActionListener(this);
graphButton.addActionListener(this);
// Keep JFrame method together.
setSize(550, 500);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
public void actionPerformed(ActionEvent event) {
Object command = event.getSource();
if(command == calculateButton) { //function for Calculate button
try {
principal = Double.parseDouble(principalTxt.getText());
} catch(NumberFormatException e) {
//catch null pointer exception if Principal is null
JOptionPane.showMessageDialog(null, "Invaild Entry! Please Try Again",
"ERROR", JOptionPane.ERROR_MESSAGE);
}
try {
//Get input from Term text box, checked first before combo box
term = Integer.parseInt(termTxt.getText());
rate = Double.parseDouble(rateTxt.getText()); //Input from Rate text box
} catch(NumberFormatException e) {
//If Term and Rate are null, buttons are checked for input values
//Set rate and term based on which item in the combobox is selected
//Still have to fill in this area for the combo box arrays
/*
if
else {
//If no option is selected and combo box null,
// this is an actual error.
JOptionPane.showMessageDialog(null, "Invaild Entry! " +
"Please Try Again",
"ERROR", JOptionPane.ERROR_MESSAGE);
}
*/
}
interest = rate / 100 / 12; //Monthly interst rate
notePeriod= term * 12; //Number of months over which loan is amortized
//calculation formula
monthlyPayment = (principal * interest) /
(1 - Math.pow(1 + interest, -notePeriod));
//formatting variables
DecimalFormat df = new DecimalFormat("\u00A4#,##0.00"); //currency
DecimalFormat pf = new DecimalFormat("#,##0.00%"); //percentages
DecimalFormat mi = new DecimalFormat("#,##0.000%"); //percentages
monthlyPaymentTxt.setText("" + df.format(monthlyPayment));
}
if(command == clearButton) { //Function for Clear button
principalTxt.setText(null);
monthlyPaymentTxt.setText(null);
rateTxt.setText(null);
termTxt.setText(null);
displayArea.setText(null);
}
if(command == exitButton) { //Function for Exit button
System.exit(0);
}
if (command == amortizeButton) { //Function for Amortize button
//Amoritization variables
double loanBalance = notePeriod * monthlyPayment;
// You need to use the member variables with these two names
// so you can send them to your GraphPanel. Instantiate them
// here and fill the elements in this loop. The member
// variables remain null and choke up GraphPanel.
double interestPaid = 0; //Interest paid on the loan
double monthlyPrincipal = 0; //Principal in each monthly payment
//running total of principal after payment
double principalBalance = principal;
//String for output
String titles = "Month\t Principal\t\tInterest\t\tBalance\n";
displayArea.setText(titles);
displayArea.append(""); //Inserts a blank line
//This loop is used to calculate and display the payment schedule information
for(int counter = 0; counter < term * 12 - 0; counter++) { //start outer loop
//start inner loop
interestPaid = principalBalance * interest;
monthlyPrincipal = monthlyPayment - interestPaid;
loanBalance = loanBalance - monthlyPayment;
principalBalance = principalBalance - monthlyPrincipal;
//formatting variables
DecimalFormat df = new DecimalFormat("\u00A4#,##0.00"); //currency
DecimalFormat pf = new DecimalFormat("#,##0.00%"); //percentages
DecimalFormat mi = new DecimalFormat("#,##0.000%"); //percentages
//formatting for output
displayArea.setCaretPosition(0);
displayArea.append((counter +1) + ")\t" +
df.format(monthlyPrincipal)+"\t\t" +
df.format(interestPaid)+"\t\t" +
df.format(principalBalance)+"\n");
}
}
if (command == graphButton) { //Function for Graph button
JDialog d = new JDialog(this, false);
d.getContentPane().add(new GraphPanel(monthlyPrincipal, interestPaid));
d.setSize(800,600);
d.setLocation(200,100);
d.setVisible(true);
/*
mFrame = new JFrame("Mortgage Payment Graph");
mFrame.getContentPane().add(new GraphPanel(monthlyPrincipal, interestPaid));
mFrame.setSize(800,600);
mFrame.setLocation(200,100);
*/
}
}
//reading from sequential file
private void load() {
Reader fis;
try {
fis = new InputStreamReader(getClass().getResourceAsStream("data.txt"));
BufferedReader br = new BufferedReader( fis );
termArray = new int[4];
rateArray = new double[4];
String line;
int i = 0;
while((line = br.readLine()) != null) {
String[] s = line.split(",");
termArray[ i ] = Integer.parseInt(s[0].trim());
rateArray[ i ] = Double.parseDouble(s[1].trim());
i++;
}
br.close();
} catch ( Exception e1 ) {
e1.printStackTrace( );
}
}
public static void main(String[] args) {
MC smc = new MC();
}
}
class GraphPanel extends JPanel {
final int
HPAD = 60,
VPAD = 40;
int[] data;
float[] principalData;
float[] interestData;
Font font;
public GraphPanel(float[] p, float[] i) {
principalData = p;
interestData = i;
font = new Font("lucida sans regular", Font.PLAIN, 16);
setBackground(Color.white);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setFont(font);
FontRenderContext frc = g2.getFontRenderContext();
int w = getWidth();
int h = getHeight();
// scales
float xInc = (w - HPAD - VPAD) / (interestData.length - 1);
float yInc = (h - 2*VPAD) / 10f;
int[] dataVals = getDataVals(); //min and max values for y-axis
float yScale = dataVals[2] / 10f;
// ordinate (y - axis)
g2.draw(new Line2D.Double(HPAD, VPAD, HPAD, h - VPAD));
// plot tic marks
float x1 = HPAD, y1 = VPAD, x2 = HPAD - 3, y2;
for(int j = 0; j < 10; j++) {
g2.draw(new Line2D.Double(x1, y1, x2, y1));
y1 += yInc;
}
// labels
String text; LineMetrics lm;
float xs, ys, textWidth, height;
for(int j = 0; j <= 10; j++) {
text = String.valueOf(dataVals[1] - (int)(j * yScale));
textWidth = (float)font.getStringBounds(text, frc).getWidth();
lm = font.getLineMetrics(text, frc);
height = lm.getAscent();
xs = HPAD - textWidth - 7;
ys = VPAD + (j * yInc) + height/2;
g2.drawString(text, xs, ys);
if(j == 0) g2.drawString("Principal", xs, ys - 15);
}
// abcissa (x - axis)
g2.draw(new Line2D.Double(HPAD, h - VPAD, w - VPAD, h - VPAD));
// tic marks
x1 = HPAD; y1 = h - VPAD; y2 = y1 + 3;
for(int j = 0; j < interestData.length; j++) {
g2.draw(new Line2D.Double(x1, y1, x1, y2));
x1 += xInc;
}
// labels
ys = h - VPAD;
for(int j = 0; j < interestData.length; j++) {
text = String.valueOf(j + 1);
textWidth = (float)font.getStringBounds(text, frc).getWidth();
lm = font.getLineMetrics(text, frc);
height = lm.getHeight();
xs = HPAD + j * xInc - textWidth/2;
g2.drawString(text, xs, ys + height);
if( j == (interestData.length - 1))
g2.drawString("Year", (int)w /2 , ys + height + 15);
}
// plot data
float yy2 = 0, yy1 = 0, xx2 = 0, xx1;
x1 = HPAD;
xx1 = HPAD;
yScale = (float)(h - 2*VPAD) / dataVals[2];
for(int j = 0; j < interestData.length; j++) {
g.setColor(Color.blue);
y1 = VPAD + (h - 2*VPAD) - (principalData[j] - dataVals[0]) * yScale;
g2.fillOval((int)x1, (int)y1 - 2, 5, 5);
if(j > 0)
g2.draw(new Line2D.Double(x1, y1, x2, y2));
x2 = x1;
y2 = y1;
x1 += xInc;
g.setColor(Color.red);
yy1 = VPAD + (h - 2*VPAD) - (interestData[j] - dataVals[0]) * yScale;
g2.fillOval((int)xx1, (int)yy1 - 1, 5, 5);
if(j > 0)
g2.draw(new Line2D.Double(xx1, yy1, xx2, yy2));
xx2 = xx1;
yy2 = yy1;
xx1 += xInc;
}
}
private int[] getDataVals() {
int max = Integer.MIN_VALUE;
int min = Integer.MAX_VALUE;
int j = interestData.length -1;
max = (int)principalData[j];
min = (int)interestData[j];
int span = max - min;
return new int[] { min, max, span };
}
}