//mortgage.java import java.awt.*; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import java.awt.font.*; import java.awt.Font; import java.awt.geom.*; import java.awt.Insets; import java.awt.LayoutManager; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.Reader; import java.text.MessageFormat; import java.text.NumberFormat; import java.io.FileReader; import javax.swing.*; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.JTextField; import javax.swing.table.DefaultTableModel; public class Mortgage extends JFrame implements ActionListener { JLabel Llabel; //amount label JTextField Ltextfield; //amount textfield JLabel Olabel; //option label JComboBox options; //option combobox JLabel Tlabel; //term label JTextField Ttextfield; //term textfield JLabel Rlabel; //rate label JTextField Rtextfield; //rate textfield JLabel Plabel; //payment label JLabel $label; //field for monthly payment amount JButton calculate; //calculate button JButton reset; //reset button JButton exit; //exit button JTable table; //create table JMenuItem mnuExit = new JMenuItem("Exit"); DefaultTableModel model;//table model int[] trmArray; double[] intrstArray; JButton graph; private float[] yearlyPrinciple; private float[] yearlyInterest; // int[] trmArray= {7,15,30}; //Double[] intrsArray={5.35,5.50,5.75}; public Mortgage () { super("Mortgage Calculator"); setDefaultLookAndFeelDecorated(true); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); load(); init(); pack(); setVisible(true); } //reading from sequential file public void load() { Reader fis; try { fis = new FileReader("data.txt"); // fine to read mortgage loans BufferedReader b = new BufferedReader(fis); String[] line = b.readLine( ).split(","); trmArray = new int[line.length]; for ( int i = 0; i < line.length; i++ ) { trmArray[ i ] = Integer.parseInt(line[i].trim()); } line = b.readLine( ).split(","); intrstArray = new double[line.length]; for ( int i = 0; i < line.length; i++ ) { intrstArray[ i ] = Double.parseDouble(line[i].trim()); } b.close(); fis.close(); } catch ( Exception e1 ) { e1.printStackTrace(); } } //creates labels, buttons and textfields public void init() { Mortgage5Layout customLayout = new Mortgage5Layout(); Container con = getContentPane(); con.setLayout(customLayout); con.setFont(new Font("Arial", Font.PLAIN, 12)); con.setLayout(customLayout); Llabel = new JLabel("Mortgage Loan Amount $ (no comma)");//amount label con.add(Llabel); Ltextfield = new JTextField("");//amount textfield con.add(Ltextfield); Olabel = new JLabel("Preset Term & Interest Rate %");//option label con.add(Olabel); options = new JComboBox();//option combobox con.add(options); MessageFormat mf = new MessageFormat("{0} years at {1,number,#.##}%"); options.addItem(" (choose rate)"); // for (int i = 0; i < trmArray.length; i++) // { // options.addItem(mf.format(new Object[] { new Integer(trmArray[i]), // new Double(intrstArray[i])})); options.addItem("7 years at 5.35%"); options.addItem("15 years at 5.50%"); options.addItem("30 years at 5.75%"); // } Tlabel = new JLabel("Term (years)");//term label con.add(Tlabel); Ttextfield = new JTextField("");//term textfield con.add(Ttextfield); Rlabel = new JLabel("Interest Rate");//rate label con.add(Rlabel); Rtextfield = new JTextField("");//rate textfield con.add(Rtextfield); Plabel = new JLabel("Monthly Payment Amount");//payment label con.add(Plabel); $label = new JLabel("");//payment textfield con.add($label); calculate = new JButton("Calculate");//calculate button con.add(calculate); reset = new JButton("Clear");//reset button con.add(reset); exit = new JButton ("Close");//exit button con.add(exit); //table header names String[] columnNames = {"Payment #","Payment Amount", "Interest", "Principle Reduction", "Remaining Balance"}; //create table and table model model = new DefaultTableModel(columnNames, 0); table = new JTable(model); JScrollPane scroll = new JScrollPane(table); table.setPreferredScrollableViewportSize(new Dimension (10, 600)); con.add (scroll); graph = new JButton ("Display Graph");//Display Graph button con.add(graph); //action listeners Ltextfield.addActionListener(this); //loanfield options.addActionListener(this); //interestfield calculate.addActionListener(this); //calButtion reset.addActionListener(this); //resetButton exit.addActionListener(this); //exitButton graph.addActionListener(this); //graphButton } //action event from listeners public void actionPerformed(ActionEvent event) { Object source = event.getSource(); if (source == calculate) { startCalculations(); } if (source == reset) { reset(); } if (source==options) { setRate(); } if (source == exit) { exit(); } if (source == mnuExit) { exitGraph(); } if (source == graph) { mFrame = new JFrame("Mortgage Graph"); mFrame.getContentPane().add(new GraphPanel(yearlyPrinciple, yearlyInterest)); mFrame.setSize(800,600); mFrame.setLocation(200,100); mFrame.setVisible(true); //exit listener mnuExit.addActionListener(this); //exitButton } } public JFrame mFrame = new JFrame(); void exitGraph() { mFrame.dispose(); mFrame = null; } void setRate() { int index = options.getSelectedIndex(); //term and interest error check if (index > 0) { try { Ttextfield.setText(Integer.toString(trmArray[index-1])); } catch (NumberFormatException e) { JOptionPane.showMessageDialog(null, "Invalid or missing Loan Term. Please try again!", "Message Dialog", JOptionPane.PLAIN_MESSAGE); Ttextfield.setText(null); } try { Rtextfield.setText(Double.toString(intrstArray[index-1])); } catch (NumberFormatException e) { JOptionPane.showMessageDialog(null, "Invalid or missing Interest Rate. Please try again!", "Message Dialog", JOptionPane.PLAIN_MESSAGE); Rtextfield.setText(null); } } } //calculation section void startCalculations() { Thread thisThread = Thread.currentThread(); NumberFormat currency = NumberFormat.getCurrencyInstance(); double amt = 0; double trm = 0; double intrst = 0; double moIn = 0; double moTrm = 0; double prin = 0; double paymt = 0; //amount error check try { amt = Double.parseDouble(Ltextfield.getText()); } catch (NumberFormatException e) { JOptionPane.showMessageDialog(null, "Missing Amount or Use of Commas", "Message Dialog", JOptionPane.PLAIN_MESSAGE); Ltextfield.setText(null); Ttextfield.setText(null); Rtextfield.setText(null); options.setSelectedIndex(0); } //term and interest error check try { trm = Double.parseDouble(Ttextfield.getText()); } catch (NumberFormatException e) { JOptionPane.showMessageDialog(null, "Invalid or missing Loan Term. Please try again!", "Message Dialog", JOptionPane.PLAIN_MESSAGE); Ttextfield.setText(null); } try { intrst = Double.parseDouble(Rtextfield.getText()); } catch (NumberFormatException e) { JOptionPane.showMessageDialog(null, "Invalid or missing Interest Rate. Please try again!", "Message Dialog", JOptionPane.PLAIN_MESSAGE); Rtextfield.setText(null); } if (amt > 0) { amt = Double.parseDouble(Ltextfield.getText()); moIn = (intrst / 1200);//monthly interest rate moTrm = trm * 12;//number of payments paymt = (amt * moIn) / (1-Math.pow((1+moIn), -moTrm));//amount forumla yearlyPrinciple = new float[(int)trm]; // initialize the arrays to store yearly principle and interest yearlyInterest = new float[(int)trm]; $label.setText("" + currency.format(paymt)); double newPrin = amt; for (int i = 0; i < trm; i++) { yearlyInterest[i] = 0.0f; //start at 0.0 yearlyPrinciple[i] = 0.0f; //start at 0.0 for(int j = 1; j <=12; j++) { double newIn = moIn * newPrin;//monthly interest amount double reduct = paymt - newIn;//monthly principle yearlyInterest[i] += newIn; // accumalate the interest yearlyPrinciple[i] += reduct; //accumalate the principle newPrin = newPrin - reduct;//balance //stops showing negative balance if (newPrin < 0) newPrin = 0; else newPrin = newPrin; //inserts different amounts into the table model.addRow(new Object[] { Integer.toString((i*12) + j), currency.format(paymt), currency.format(newIn), currency.format(reduct), currency.format(newPrin) }); } //for testing purposes only // model.addRow(new Object[] { Integer.toString(i), currency.format(0.0), // currency.format(yearlyInterest[i]), currency.format(yearlyPrinciple[i]), currency.format(0.0) }); } } //less than 0 error check if (amt < 0) { JOptionPane.showMessageDialog(null, "Please Enter Positie Numbers Only.", "Message Dialog", JOptionPane.PLAIN_MESSAGE); Ltextfield.setText(null); } } //resets all fields void reset() { Ltextfield.setText(null); Ttextfield.setText(null); Rtextfield.setText(null); options.setSelectedIndex(0); $label.setText(null); model.setRowCount(0); } //exit the program void exit() { System.exit(0); } public static void main(String args[]) { java.awt.EventQueue.invokeLater(new Runnable() { public void run() { new Mortgage().setVisible(true); } }); } } class GraphPanel extends JPanel { final int HPAD = 60, VPAD = 40; int[] data; Font font; float[] principleData; float[] interestData; public GraphPanel(float[] p, float[] i) { principleData = 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);//11f; //distance between each plot 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); } // 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); } // 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) - (principleData[j] - dataVals[0]) * yScale; 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; 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)principleData[j]; min = (int)interestData[j]; int span = max - min; return new int[] { min, max, span }; } } //creates class for container layout and placement class Mortgage5Layout implements LayoutManager{ public Mortgage5Layout() {} public void addLayoutComponent(String name, Component comp) {} public void removeLayoutComponent(Component comp) {} public Dimension preferredLayoutSize(Container parent) { Dimension dim = new Dimension(0, 0); Insets insets = parent.getInsets(); dim.width = 600 + insets.left + insets.right; dim.height = 425 + insets.top + insets.bottom; return dim; } public Dimension minimumLayoutSize(Container parent) { Dimension dim = new Dimension(0, 0); return dim; } public void layoutContainer(Container parent) { Insets insets = parent.getInsets(); Component c; c = parent.getComponent(0); if (c.isVisible()) {c.setBounds(insets.left+8,insets.top+8,250,24);} c = parent.getComponent(1); if (c.isVisible()) {c.setBounds(insets.left+300,insets.top+8,175,24);} c = parent.getComponent(2); if (c.isVisible()) {c.setBounds(insets.left+8,insets.top+40,250,24);} c = parent.getComponent(3); if (c.isVisible()) {c.setBounds(insets.left+300,insets.top+40,150,24);} c = parent.getComponent(4); if (c.isVisible()) {c.setBounds(insets.left+8,insets.top+72,250,24);} c = parent.getComponent(5); if (c.isVisible()) {c.setBounds(insets.left+300,insets.top+72,96,24);} c = parent.getComponent(6); if (c.isVisible()) {c.setBounds(insets.left+8,insets.top+104,250,24);} c = parent.getComponent(7); if (c.isVisible()) {c.setBounds(insets.left+300,insets.top+104,112,24);} c = parent.getComponent(8); if (c.isVisible()) {c.setBounds(insets.left+8,insets.top+136,250,24);} c = parent.getComponent(9); if (c.isVisible()) {c.setBounds(insets.left+300,insets.top+136,112,24);} c = parent.getComponent(10); if (c.isVisible()) {c.setBounds(insets.left+50,insets.top+168,96,24);} c = parent.getComponent(11); if (c.isVisible()) {c.setBounds(insets.left+225,insets.top+168,112,24);} c = parent.getComponent(12); if (c.isVisible()) {c.setBounds(insets.left+400,insets.top+168,96,24);} c = parent.getComponent(13); if (c.isVisible()) {c.setBounds(insets.left+8,insets.top+200,575,160);} c = parent.getComponent(14); if (c.isVisible()) {c.setBounds(insets.left+225,insets.top+375,112,24);} } }