Mortgage Calculator

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

class PaymentCanvas extends Canvas implements MouseMotionListener {
   Image oi;
   Graphics og;
   Mortgage mortgage;

   public PaymentCanvas (Mortgage mortgage) { this.mortgage = mortgage; }

   int principal, xborder, yborder, width, height, months;
   double xincr, mnpy, years;
   double apr;
   
   void setup () {
      oi = createImage (this.getSize().width, this.getSize().height);
      og = oi.getGraphics();
      addMouseMotionListener(this);
      this.mortgage = mortgage;
   }
   
   void setParameters() {
      try { principal = Integer.parseInt(mortgage.la.getText()); }
      catch (Exception e) { principal = 0; }

      try {  years = Double.valueOf(mortgage.ny.getText()).doubleValue(); }
      catch (Exception e) { years = 0; }
      months = (int)(years*12.0);
      
      try { apr = Double.valueOf(mortgage.ap.getText()).doubleValue()/100.0; }
      catch (Exception e) { apr = 0.0; }

      if (principal > 0 && apr >= 0 && apr < 1) {
         double factor = Math.exp(months*Math.log(1+apr/12));
         mnpy = principal*(apr/12)*factor/(factor-1);
         mortgage.mp.setText(String.valueOf((int)(mnpy*100)/100.0));
      } else
         mortgage.mp.setText("");
      draw();

      /*** For checking - all monthly unpaid principal
      for (int i=0 ; i < 10000 ; i++) {
         System.out.println(i+":\t"+unpaidPrincipal(i));
         if (unpaidPrincipal(i) <= 0) break;
      }
      ***/
   }
   
   void setParametersGivenYears() {
      try { principal = Integer.parseInt(mortgage.la.getText()); }
      catch (Exception e) { principal = 0; }

      try {  mnpy = Double.valueOf(mortgage.mp.getText()).doubleValue(); }
      catch (Exception e) { mnpy = 0; }
      
      try { apr = Double.valueOf(mortgage.ap.getText()).doubleValue()/100.0; }
      catch (Exception e) { apr = 0.0; }

      if (principal > 0 && apr >= 0 && apr < 1) {
         int n=0;
         for ( ; n < 120000 ; n++) {
            double tot = principal*Math.pow(1+(apr/12.0),n) -
               mnpy*((Math.pow(1+(apr/12.0),n)-1)/(apr/12.0));
            //System.out.println(n+":\t"+tot);
            if (tot <= 0) break;
         }
         months = n;
         //System.out.println("---------");
         //System.out.println("months="+months);
         mortgage.ny.setText(String.valueOf(((int)((n/12.0)*100))/100.0));
      } else
         mortgage.ny.setText("");
      draw();
   }
   
   double unpaidPrincipal (int i) {
      double f1 = Math.exp(i*Math.log(1+apr/12.0));
      double f2 = Math.exp(months*Math.log(1+apr/12.0));
      return (double)principal*((f2-f1)/(f2-1));
   }
   
   double paidPrincipal (int i) {
      return (double)principal-unpaidPrincipal(i);
   }
   
   double interestPaid (int i) {
      return (double)mnpy*i-paidPrincipal(i);
   }
   
   double totalPaid (int i) {
      return (double)mnpy*i;
   }
   
   int translate (double y, double tot)   {
      return yborder-(int)((y*height)/tot);
   }
   
   void draw () {
      int y, z;
      
      xborder = 50;
      yborder = this.getSize().height - 50;
      width = this.getSize().width-70;
      height = this.getSize().height-70;
      
      xincr = (double)(width)/(months+1.0);

      og.setColor(new Color(255,255,255));
      og.fillRect(0,0,this.getSize().width,this.getSize().height);
      og.setColor(Color.black);
      og.drawLine(xborder,yborder,xborder+width,yborder);
      og.drawLine(xborder,yborder,xborder,yborder-height);
      if (apr > 0 && months > 0 && principal > 0) {
         if (mortgage.lg.getState() == true || 
             mortgage.ig.getState() == true) {
            y = translate(principal, mnpy*months);
            og.setColor(Color.green);
            og.drawLine(xborder,y,xborder+width,y);
            og.setColor(Color.black);
            og.drawString(String.valueOf(principal), 75, y-3);
            y = translate(months*mnpy, mnpy*months);
            og.setColor(Color.green);
            og.drawLine(xborder,y,xborder+width,y);
            og.setColor(Color.black);
            og.drawString(String.valueOf((int)(mnpy*months)), 75, y-3);
            y = translate(months*mnpy-principal, mnpy*months);
            og.setColor(Color.green);
            og.drawLine(xborder,y,xborder+width,y);
            og.setColor(Color.black);
            og.drawString(String.valueOf((int)(mnpy*months-principal)),75,y-3);
         }
         int x = (int)xincr;
         if (x > 1) {
            for (int i=1 ; i <= months ; i++) {
               if (mortgage.pg.getState() == true) {
                  og.setColor(Color.red);
                  y = translate(unpaidPrincipal(i), (double)principal);
                  og.fillRect(xborder+(int)(xincr*i),y,x,1);
               } else if (mortgage.lg.getState() == true) {
                  og.setColor(Color.red);
                  y = translate(paidPrincipal(i), mnpy*months);
                  og.fillRect(xborder+(int)(xincr*i),y,x,1);
                  og.setColor(Color.blue);
                  y = translate(totalPaid(i), mnpy*months);
                  og.fillRect(xborder+(int)(xincr*i),y,x,1);
               } else if (mortgage.ig.getState() == true) {
                  og.setColor(Color.red);
                  y = translate(interestPaid(i), mnpy*months);
                  og.fillRect(xborder+(int)(xincr*i),y,x,1);
                  og.setColor(Color.blue);
                  y = translate(totalPaid(i), mnpy*months);
                  og.fillRect(xborder+(int)(xincr*i),y,x,1);
               }
            }
         } else {
            for (int i=0 ; i < width ; i++) {
               int q = xborder+i;
               int r = xborder+i+1;
          int m1 = (i*months)/width;
          int m2 = ((i+1)*months)/width;
               if (mortgage.pg.getState() == true) {
                  og.setColor(Color.red);
                  y = translate(unpaidPrincipal(m1), (double)principal);
                  z = translate(unpaidPrincipal(m2), (double)principal);
                  og.drawLine(q,y,r,z);
               } else if (mortgage.lg.getState() == true) {
                  og.setColor(Color.red);
                  y = translate(paidPrincipal(m1), mnpy*months);
                  z = translate(paidPrincipal(m2), mnpy*months);
                  og.drawLine(q,y,r,z);
                  og.setColor(Color.blue);
                  y = translate(totalPaid(m1), mnpy*months);
                  z = translate(totalPaid(m2), mnpy*months);
                  og.drawLine(q,y,r,z);
               } else if (mortgage.ig.getState() == true) {
                  og.setColor(Color.red);
                  y = translate(interestPaid(m1), mnpy*months);
                  z = translate(interestPaid(m2), mnpy*months);
                  og.drawLine(q,y,r,z);
                  og.setColor(Color.blue);
                  y = translate(totalPaid(m1), mnpy*months);
                  z = translate(totalPaid(m2), mnpy*months);
                  og.drawLine(q,y,r,z);
               }
            }
         }
      }
      getGraphics().drawImage(oi, 0, 0, this);      
   }
   
   public void paint (Graphics g) { draw(); }
   
   public void mouseDragged (MouseEvent e) { }
   
   public void mouseMoved (MouseEvent e) {
      int nmn = ((e.getX()-xborder)*(months+1))/width;
      if (months > 0 && nmn <= months && nmn >= 0) {
         mortgage.mn.setText(String.valueOf(nmn));
         double up = ((int)(unpaidPrincipal(nmn)*100.0))/100.0;
         mortgage.pp.setText(String.valueOf(up));
         mortgage.pr.setText(String.valueOf(((int)((principal-up)*100))/100.0));
         mortgage.ip.setText(String.valueOf((int)(interestPaid(nmn)*100)/100.0));
      } else {
         mortgage.ip.setText("");
         mortgage.mn.setText("");
         mortgage.pr.setText("");
         mortgage.pp.setText("");
      }
   }
}

public class Mortgage extends Applet implements ItemListener, ActionListener {
   PaymentCanvas pc;
   CheckboxGroup cb = new CheckboxGroup();
   Checkbox pg, ig, lg;
   JTextField pp, pr, ip, la, ap, ny, mn, mp;
   JLabel s0, s1, s2, s3, s4, t0, t1, t2;
   
   public void init () {
      setLayout (new BorderLayout(10,10));

      JPanel p = new JPanel();
      p.setLayout(new GridLayout(2,4,20,0));
      p.setBackground(new Color(217,231,255));
      p.add (pp = new JTextField());
      p.add (pr = new JTextField());
      p.add (ip = new JTextField());
      p.add (mn = new JTextField());
      p.add (new JLabel("Unpaid Principle",JLabel.CENTER));
      p.add (new JLabel("Principle Paid", JLabel.CENTER));
      p.add (new JLabel("Interest Paid", JLabel.CENTER));
      p.add (new JLabel("Month",JLabel.CENTER));
      add ("South", p);

      JPanel r = new JPanel();
      r.setLayout(new BorderLayout());
      r.setBackground(new Color(217,231,255));
      
      p = new JPanel();
      p.setLayout(new GridLayout(5,1));
      p.setBackground(new Color(217,231,255));

      JPanel q = new JPanel();
      q.setLayout(new BorderLayout(6,6));
      q.setBackground(new Color(217,231,255));
      q.add ("North", new JLabel("  "));
      q.add ("Center", new JLabel("  "));
      q.add ("South", t0 = new JLabel("Inputs ...", JLabel.CENTER));
      p.add(q);

      q = new JPanel();
      q.setLayout(new BorderLayout(6,6));
      q.setBackground(new Color(217,231,255));
      q.add ("North", s0 = new JLabel("  "));
      q.add ("Center", la = new JTextField(8));
      q.add ("South", new JLabel("Loan Amount ($)",JLabel.CENTER));
      p.add (q);

      q = new JPanel();
      q.setLayout(new BorderLayout(6,6));
      q.setBackground(new Color(217,231,255));
      q.add ("North", s1 = new JLabel("  "));
      q.add ("Center", ap = new JTextField(8));
      q.add ("South", new JLabel("APR Interest (%)",JLabel.CENTER));
      p.add (q);

      q = new JPanel();
      q.setLayout(new BorderLayout(6,6));
      q.setBackground(new Color(217,231,255));
      q.add ("North", s2 = new JLabel("  "));
      q.add ("Center", ny = new JTextField(8));
      q.add ("South", new JLabel("Number of Years",JLabel.CENTER));
      p.add (q);

      q = new JPanel();
      q.setLayout(new BorderLayout(6,6));
      q.setBackground(new Color(217,231,255));
      q.add ("North", s3 = new JLabel("  "));
      q.add ("Center", mp = new JTextField(8));
      q.add ("South", new JLabel("Monthly Payment ($)",JLabel.CENTER));
      p.add (q);
      r.add ("Center", p);

      q = new JPanel();
      q.setLayout(new GridLayout(8,1));
      q.setBackground(new Color(217,231,255));
      q.add (new JLabel("  "));
      q.add (new JLabel("  "));
      q.add (t1 = new JLabel("Choose Graph", JLabel.CENTER));
      q.add (lg = new Checkbox("Principal Paid",cb,true));
      q.add (ig = new Checkbox("Interest paid",cb, false));
      q.add (pg = new Checkbox("Unpaid Principal",cb,false));
      q.add (new JLabel("  "));
      q.add (new JLabel("  "));

      r.add ("South", q);

      add ("East", r);

      q = new JPanel();
      q.setLayout(new GridLayout(1,1));
      q.setBackground(new Color(217,231,255));
      q.add (t2 = new JLabel("Mortgage Calculator", JLabel.CENTER));
      add ("North", q);

      add ("Center", pc = new PaymentCanvas(this));
      
      setBackground(new Color(217,231,255));

      t0.setFont(new Font("TimesRoman", Font.BOLD, 16));
      t1.setFont(new Font("TimesRoman", Font.BOLD, 16));
      t2.setFont(new Font("TimesRoman", Font.BOLD, 24));
      s0.setFont(new Font("TimesRoman", Font.PLAIN, 6));
      s1.setFont(new Font("TimesRoman", Font.PLAIN, 6));
      s2.setFont(new Font("TimesRoman", Font.PLAIN, 6));
      s3.setFont(new Font("TimesRoman", Font.PLAIN, 6));
   }
   
   public void start () {
      pc.setup();
      pc.repaint();
      mn.setEditable(false);
      pp.setEditable(false);
      pr.setEditable(false);
      ip.setEditable(false);

      mn.setBackground(new Color(255,231,217));      
      pp.setBackground(new Color(255,231,217));
      pr.setBackground(new Color(255,231,217));
      ip.setBackground(new Color(255,231,217));      
      la.setBackground(Color.white);
      ap.setBackground(Color.white);
      ny.setBackground(Color.white);
      mp.setBackground(Color.white);
      pg.addItemListener(this);
      ig.addItemListener(this);
      lg.addItemListener(this);
      la.addActionListener(this);
      ap.addActionListener(this);
      ny.addActionListener(this);
      mp.addActionListener(this);
   }

   public void actionPerformed (ActionEvent e) { 
      if (e.getSource() == ap ||
          e.getSource() == ny ||
          e.getSource() == la)
         pc.setParameters(); 
      else
         pc.setParametersGivenYears();
   }
   
   public void itemStateChanged (ItemEvent e) { pc.draw(); }
}