// Angular.java
//
// Copyright 2001-2008 by Rick Wagner, all rights reserved.
//
// A very simple applet to convert babylonian angle measurement (degrees, minutes,
// seconds) to engineering units (radians) and to add and subtract two angles.
//
// This file first created March 26, 2001, by Rick Wagner.
// Version 1.07, last updated August 1, 2008, by Rick Wagner.
//
// The object prefix naming convention used here is a modified Hungarian notation.
// "s" is string, "sf" is single precision floating point, "i" is integer, "d" is
// Dimension, "tf" is TextField, and "lbl" is Label.
//
// Version 1.04 adds decimal degrees equivalent angle (July 14, 2008).
// Version 1.05 adds sum and difference calculation (July 28, 2008).

import java.applet.*;
import java.awt.*;

public class Angular extends Applet
{
  private String sVersionNumber = "1.07";                     // String constructor.
  private String sCompiledDate = "August 1, 2008";
  private Dimension dApplet = null;                           // Size of the applet (set in HTML code).

  // Labels and TextFields for the GUI:
  private Label lblTitle = null;                              // Main title label
  private Label lblDegrees0 = null;                           // Labels and TextFields for first operand:
  private TextField tfDegrees0 = null;
  private Label lblMinutes0 = null;
  private TextField tfMinutes0 = null;
  private Label lblSeconds0 = null;
  private TextField tfSeconds0 = null;
  private Label lblEqualsA0 = null;
  private Label lblEqualsB0 = null;
  private Label lblRadians0 = null;
  private TextField tfRadians0 = null;
  private Label lblDecDeg0 = null;
  private TextField tfDecDeg0 = null;

  private TextField tfDegrees1 = null;                        // Labels and TextFields for second operand:
  private TextField tfMinutes1 = null;
  private TextField tfSeconds1 = null;
  private Label lblEqualsA1 = null;
  private Label lblEqualsB1 = null;
  private TextField tfRadians1 = null;
  private TextField tfDecDeg1 = null;

  private Button btnAdd = null;                               // Buttons for operations
  private Button btnSubtract = null;

  private Label lblDegrees2 = null;                           // Labels and TextFields for first operand:
  private Label lblMinutes2 = null;
  private Label lblSeconds2 = null;
  private Label lblRadians2 = null;
  private Label lblDecDeg2 = null;

  private Label lblResult = null;                             // Labels and TextFields for result:
  private TextField tfDegrees2 = null;
  private TextField tfMinutes2 = null;
  private TextField tfSeconds2 = null;
  private Label lblEqualsA2 = null;
  private Label lblEqualsB2 = null;
  private TextField tfRadians2 = null;
  private TextField tfDecDeg2 = null;

  private Font fTitle = null;

  // To allow browsers to get information about the applet (not yet implemented in Netscape nor in MSIE):
  public String getAppletInfo()
  {
    return "\nAngle conversion applet, version " + sVersionNumber +
           ", by Rick Wagner, copyright 2001-2008,\nall rights reserved.\n\n" +
           "Compiled " + sCompiledDate + ". Source code use authorized for\n" +
           "educational purposes only. No use without attribution.";
  }

  // Applet initialization:
  public void init()
  {
    GridBagLayout gbl = new GridBagLayout();                   // Construct the gridbag layout and
    GridBagConstraints gbc = new GridBagConstraints();         // constraints.

    setLayout(gbl);                                            // Convention: use "this" only where
    setBackground(Color.lightGray);                            // it's explicitly necessary.
    dApplet = size();

    lblTitle = new Label("Angle Calculator Applet version "    // Construct the labels and textfields.
                         + sVersionNumber + " compiled "
                         + sCompiledDate, Label.CENTER);
    Font fTitle  = new Font("Default", Font.BOLD, 14);         // Larger font for the title.
    lblTitle.setFont(fTitle);

    lblDegrees0 = new Label("Degrees", Label.CENTER);
    tfDegrees0 = new TextField("0", 8);
    lblMinutes0 = new Label("Minutes", Label.CENTER);
    tfMinutes0 = new TextField("0", 8);
    lblSeconds0 = new Label("Seconds", Label.CENTER);
    tfSeconds0 = new TextField("0", 8);
    lblEqualsA0 = new Label(" = ", Label.CENTER);
    lblEqualsB0 = new Label(" = ", Label.CENTER);
    lblRadians0 = new Label("Radians", Label.CENTER);
    tfRadians0 = new TextField("0", 16);
    lblDecDeg0 = new Label("Decimal Degrees", Label.CENTER);
    tfDecDeg0 = new TextField("0", 16);

    tfDegrees1 = new TextField("0", 8);
    tfMinutes1 = new TextField("0", 8);
    tfSeconds1 = new TextField("0", 8);
    lblEqualsA1 = new Label(" = ", Label.CENTER);
    lblEqualsB1 = new Label(" = ", Label.CENTER);
    tfRadians1 = new TextField("0", 16);
    tfDecDeg1 = new TextField("0", 16);

    lblDegrees2 = new Label("Degrees", Label.CENTER);
    lblMinutes2 = new Label("Minutes", Label.CENTER);
    lblSeconds2 = new Label("Seconds", Label.CENTER);
    lblRadians2 = new Label("Radians", Label.CENTER);
    lblDecDeg2 = new Label("Decimal Degrees", Label.CENTER);

    lblResult = new Label("", Label.CENTER);

    tfDegrees2 = new TextField("", 8);
    tfDegrees2.setEditable(false);
    tfMinutes2 = new TextField("", 8);
    tfMinutes2.setEditable(false);
    tfSeconds2 = new TextField("", 8);
    tfSeconds2.setEditable(false);
    lblEqualsA2 = new Label(" = ", Label.CENTER);
    lblEqualsB2 = new Label(" = ", Label.CENTER);
    tfRadians2 = new TextField("", 16);
    tfRadians2.setEditable(false);
    tfDecDeg2 = new TextField("", 16);
    tfDecDeg2.setEditable(false);

    btnAdd = new Button("Add");                               // Buttons for operations
    btnSubtract = new Button("Subtract");

    Insets insNone = new Insets(0, 0, 0, 0);
    Insets insTopBottom = new Insets(10, 0, 10, 0);

    // Begin the cryptic gridbag stuff:
    gbc.insets = insNone;
    gbc.gridwidth = 1;
    gbc.gridheight = 1;

    gbc.fill = gbc.HORIZONTAL;                                // Title label
    gbc.gridwidth = 7;
    gbc.gridx = 0;
    gbc.gridy = 0;
    gbl.setConstraints(lblTitle, gbc);
    add(lblTitle);
    gbc.fill = gbc.NONE;                                     // Set the fill back to none.
    gbc.gridwidth = 1;                                       // Set the grid width back to one.

    // First operand...
    gbc.gridx = 0;                                           // Degrees
    gbc.gridy = 1;
    gbl.setConstraints(lblDegrees0, gbc);
    add(lblDegrees0);

    gbc.gridx = 0;
    gbc.gridy = 2;
    gbl.setConstraints(tfDegrees0, gbc);
    add(tfDegrees0);

    gbc.gridx = 1;                                           // Minutes
    gbc.gridy = 1;
    gbl.setConstraints(lblMinutes0, gbc);
    add(lblMinutes0);

    gbc.gridx = 1;
    gbc.gridy = 2;
    gbl.setConstraints(tfMinutes0, gbc);
    add(tfMinutes0);

    gbc.gridx = 2;                                           // Seconds
    gbc.gridy = 1;
    gbl.setConstraints(lblSeconds0, gbc);
    add(lblSeconds0);

    gbc.gridx = 2;
    gbc.gridy = 2;
    gbl.setConstraints(tfSeconds0, gbc);
    add(tfSeconds0);

    gbc.gridx = 3;
    gbc.gridy = 2;
    gbl.setConstraints(lblEqualsA0, gbc);
    add(lblEqualsA0);

    gbc.gridx = 4;                                           // Radians
    gbc.gridy = 1;
    gbl.setConstraints(lblRadians0, gbc);
    add(lblRadians0);

    gbc.gridx = 4;
    gbc.gridy = 2;
    gbl.setConstraints(tfRadians0, gbc);
    add(tfRadians0);

    gbc.gridx = 5;
    gbc.gridy = 2;
    gbl.setConstraints(lblEqualsB0, gbc);
    add(lblEqualsB0);

    gbc.gridx = 6;                                           // Decimal degrees
    gbc.gridy = 1;
    gbl.setConstraints(lblDecDeg0, gbc);
    add(lblDecDeg0);

    gbc.gridx = 6;
    gbc.gridy = 2;
    gbl.setConstraints(tfDecDeg0, gbc);
    add(tfDecDeg0);

    // Second operand...
    gbc.gridx = 0;                                           // Degrees
    gbc.gridy = 3;
    gbl.setConstraints(tfDegrees1, gbc);
    add(tfDegrees1);

    gbc.gridx = 1;                                           // Minutes
    gbc.gridy = 3;
    gbl.setConstraints(tfMinutes1, gbc);
    add(tfMinutes1);

    gbc.gridx = 2;                                           // Seconds
    gbc.gridy = 3;
    gbl.setConstraints(tfSeconds1, gbc);
    add(tfSeconds1);

    gbc.gridx = 3;
    gbc.gridy = 3;
    gbl.setConstraints(lblEqualsA1, gbc);
    add(lblEqualsA1);

    gbc.gridx = 4;                                           // Radians
    gbc.gridy = 3;
    gbl.setConstraints(tfRadians1, gbc);
    add(tfRadians1);

    gbc.gridx = 5;
    gbc.gridy = 3;
    gbl.setConstraints(lblEqualsB1, gbc);
    add(lblEqualsB1);

    gbc.gridx = 6;                                           // Decimal degrees
    gbc.gridy = 3;
    gbl.setConstraints(tfDecDeg1, gbc);
    add(tfDecDeg1);

    // Buttons...
    gbc.fill = gbc.HORIZONTAL;                               // "Add" button
    gbc.gridwidth = 4;
    gbc.insets = insTopBottom;
    gbc.gridx = 0;
    gbc.gridy = 4;
    gbl.setConstraints(btnAdd, gbc);
    add(btnAdd);

    gbc.gridx = 4;                                           // "Subtract" button
    gbc.gridy = 4;
    gbl.setConstraints(btnSubtract, gbc);
    add(btnSubtract);
    gbc.fill = gbc.NONE;

    // Calculation result...
    gbc.gridwidth = 1;                                       // Labels
    gbc.insets = insNone;
    gbc.gridx = 0;
    gbc.gridy = 5;
    gbl.setConstraints(lblDegrees2, gbc);
    add(lblDegrees2);

    gbc.gridx = 1;
    gbc.gridy = 5;
    gbl.setConstraints(lblMinutes2, gbc);
    add(lblMinutes2);

    gbc.gridx = 2;
    gbc.gridy = 5;
    gbl.setConstraints(lblSeconds2, gbc);
    add(lblSeconds2);

    gbc.gridx = 4;
    gbc.gridy = 5;
    gbl.setConstraints(lblRadians2, gbc);
    add(lblRadians2);

    gbc.gridx = 6;
    gbc.gridy = 5;
    gbl.setConstraints(lblDecDeg2, gbc);
    add(lblDecDeg2);

    gbc.gridx = 0;                                           // Text fields
    gbc.gridy = 6;
    gbl.setConstraints(tfDegrees2, gbc);
    add(tfDegrees2);

    gbc.gridx = 1;
    gbc.gridy = 6;
    gbl.setConstraints(tfMinutes2, gbc);
    add(tfMinutes2);

    gbc.gridx = 2;
    gbc.gridy = 6;
    gbl.setConstraints(tfSeconds2, gbc);
    add(tfSeconds2);

    gbc.gridx = 3;
    gbc.gridy = 6;
    gbl.setConstraints(lblEqualsA2, gbc);
    add(lblEqualsA2);

    gbc.gridx = 4;
    gbc.gridy = 6;
    gbl.setConstraints(tfRadians2, gbc);
    add(tfRadians2);

    gbc.gridx = 5;
    gbc.gridy = 6;
    gbl.setConstraints(lblEqualsB2, gbc);
    add(lblEqualsB2);

    gbc.gridx = 6;
    gbc.gridy = 6;
    gbl.setConstraints(tfDecDeg2, gbc);
    add(tfDecDeg2);

    gbc.fill = gbc.HORIZONTAL;                                // "Result" label
    gbc.gridwidth = 7;
    gbc.insets = insNone;
    gbc.gridx = 0;
    gbc.gridy = 7;
    gbl.setConstraints(lblResult, gbc);
    add(lblResult);
  }

  // Do this every time the browser returns to the page:
  public void start()
  {
    System.out.println(getAppletInfo());
  }

  // Do this on every applet paint event from the OS and on explicit repaint():
  public void paint(Graphics g)
  {
    // Draw a recessed frame around the applet border. Designed for gray-on-gray browser background.
    g.setColor(Color.black);
    g.drawLine(0, 0, dApplet.width - 1, 0);
    g.drawLine(0, 0, 0, dApplet.height - 1);
    g.setColor(Color.white);
    g.drawLine(0, dApplet.height - 1, dApplet.width - 1, dApplet.height - 1);
    g.drawLine(dApplet.width - 1, 1, dApplet.width - 1, dApplet.height - 1);
  }

  // Applet keystroke event:
  public boolean keyDown(Event e, int k)        // Character is inserted in the TextField on keyDown:
  {
    String strRadians = null;                   // For parsing the radians text entry.
    int i = 0;                                  // Index for parsing the radians text entry.
    int iLength;                                // Variable for parsing the radians text entry.

    if (e.target == tfDegrees0)
    {
      if ((k >= 48 && k <= 57) ||               // Key is in the digit range.
          (e.id == Event.KEY_ACTION || k == 127 || k == 22 || k == 3 || k == 1025 || k == 8))
      {                                         // Or it's a function or delete, etc.
      }
      else
      {
        return true;                            // Absorb the event (no character inserted).
      }
    }

    if (e.target == tfMinutes0)
    {
      if ((k >= 48 && k <= 57) ||
          (e.id == Event.KEY_ACTION || k == 127 || k == 22 || k == 3 || k == 1025 || k == 8))
      {
      }
      else
      {
        return true;                            // Absorb the event (no character inserted).
      }
    }

    if (e.target == tfSeconds0)
    {
      if ((k >= 48 && k <= 57) ||
          (e.id == Event.KEY_ACTION || k == 127 || k == 22 || k == 3 || k == 1025 || k == 8))
      {
      }
      else
      {
        return true;                            // Absorb the event (no character inserted).
      }
    }

    if (e.target == tfRadians0)
    {
      if ((k >= 48 && k <= 57) || k == 46 ||
          (e.id == Event.KEY_ACTION || k == 127 || k == 22 || k == 3 || k == 1025 || k == 8))
      {
        // See if a decimal point (k == 46) already exists in the string and if it does, return true
        if (k == 46)
        {
          strRadians = tfRadians0.getText();
          iLength = strRadians.length();
          for (i = 0; i < iLength; i++)
          {
            if (strRadians.charAt(i) == 46)
            {
              return true;                     // Absorb the event (no character inserted).
            }
          }
        }
      }
      else
      {
        return true;                           // Absorb the event (no character inserted).
      }
    }

    if (e.target == tfDecDeg0)
    {
      if ((k >= 48 && k <= 57) || k == 46 ||
          (e.id == Event.KEY_ACTION || k == 127 || k == 22 || k == 3 || k == 1025 || k == 8))
      {
        // See if a decimal point (k == 46) already exists in the string and if it does, return true
        if (k == 46)
        {
          strRadians = tfDecDeg0.getText();
          iLength = strRadians.length();
          for (i = 0; i < iLength; i++)
          {
            if (strRadians.charAt(i) == 46)
            {
              return true;                    // Absorb the event (no character inserted).
            }
          }
        }
      }
      else
      {
        return true;                          // Absorb the event (no character inserted).
      }
    }

    if (e.target == tfDegrees1)
    {
      if ((k >= 48 && k <= 57) ||             // Key is in the digit range.
          (e.id == Event.KEY_ACTION || k == 127 || k == 22 || k == 3 || k == 1025 || k == 8))
      {                                       // Or it's a function or delete, etc.
      }
      else
      {
        return true;                          // Absorb the event (no character inserted).
      }
    }

    if (e.target == tfMinutes1)
    {
      if ((k >= 48 && k <= 57) ||
          (e.id == Event.KEY_ACTION || k == 127 || k == 22 || k == 3 || k == 1025 || k == 8))
      {
      }
      else
      {
        return true;                          // Absorb the event (no character inserted).
      }
    }

    if (e.target == tfSeconds1)
    {
      if ((k >= 48 && k <= 57) ||
          (e.id == Event.KEY_ACTION || k == 127 || k == 22 || k == 3 || k == 1025 || k == 8))
      {
      }
      else
      {
        return true;                          // Absorb the event (no character inserted).
      }
    }

    if (e.target == tfRadians1)
    {
      if ((k >= 48 && k <= 57) || k == 46 ||
          (e.id == Event.KEY_ACTION || k == 127 || k == 22 || k == 3 || k == 1025 || k == 8))
      {
        // See if a decimal point (k == 46) already exists in the string and if it does, return true
        if (k == 46)
        {
          strRadians = tfRadians1.getText();
          iLength = strRadians.length();
          for (i = 0; i < iLength; i++)
          {
            if (strRadians.charAt(i) == 46)
            {
              return true;                    // Absorb the event (no character inserted).
            }
          }
        }
      }
      else
      {
        return true;                          // Absorb the event (no character inserted).
      }
    }

    if (e.target == tfDecDeg1)
    {
      if ((k >= 48 && k <= 57) || k == 46 ||
          (e.id == Event.KEY_ACTION || k == 127 || k == 22 || k == 3 || k == 1025 || k == 8))
      {
        // See if a decimal point (k == 46) already exists in the string and if it does, return true
        if (k == 46)
        {
          strRadians = tfDecDeg1.getText();
          iLength = strRadians.length();
          for (i = 0; i < iLength; i++)
          {
            if (strRadians.charAt(i) == 46)
            {
              return true;                    // Absorb the event (no character inserted).
            }
          }
        }
      }
      else
      {
        return true;                          // Absorb the event (no character inserted).
      }
    }
    return false;
  } // End of keyDown().

  // Applet keystroke event:
  public boolean keyUp(Event e, int k)        // Computation is initiated on keyUp:
  {
    if (e.target == tfDegrees0)
    {
      if ((k >= 48 && k <= 57) ||
          (e.id == Event.KEY_ACTION || k == 127 || k == 22 || k == 3 || k == 1025 || k == 8))
      {
        computeRadian(false);
      }
      else
      {
        return true;                          // Absorb the event.
      }
    }

    if (e.target == tfMinutes0)
    {
      if ((k >= 48 && k <= 57) ||
          (e.id == Event.KEY_ACTION || k == 127 || k == 22 || k == 3 || k == 1025 || k == 8))
      {
        computeRadian(false);
      }
      else
      {
        return true;                          // Absorb the event.
      }
    }

    if (e.target == tfSeconds0)
    {
      if ((k >= 48 && k <= 57) ||
          (e.id == Event.KEY_ACTION || k == 127 || k == 22 || k == 3 || k == 1025 || k == 8))
      {
        computeRadian(false);
      }
      else
      {
        return true;                          // Absorb the event.
      }
    }

    if (e.target == tfRadians0)
    {
      if ((k >= 48 && k <= 57) || k == 46 ||
          (e.id == Event.KEY_ACTION || k == 127 || k == 22 || k == 3 || k == 1025 || k == 8))
      {
        computeBabylonian(true, false);
      }
      else
      {
        return true;                          // Absorb the event.
      }
    }

    if (e.target == tfDecDeg0)
    {
      if ((k >= 48 && k <= 57) || k == 46 ||
          (e.id == Event.KEY_ACTION || k == 127 || k == 22 || k == 3 || k == 1025 || k == 8))
      {
        computeFromDecDeg(false);
      }
      else
      {
        return true;                          // Absorb the event.
      }
    }

    if (e.target == tfDegrees1)
    {
      if ((k >= 48 && k <= 57) ||
          (e.id == Event.KEY_ACTION || k == 127 || k == 22 || k == 3 || k == 1025 || k == 8))
      {
        computeRadian(true);
      }
      else
      {
        return true;                          // Absorb the event.
      }
    }

    if (e.target == tfMinutes1)
    {
      if ((k >= 48 && k <= 57) ||
          (e.id == Event.KEY_ACTION || k == 127 || k == 22 || k == 3 || k == 1025 || k == 8))
      {
        computeRadian(true);
      }
      else
      {
        return true;                          // Absorb the event.
      }
    }

    if (e.target == tfSeconds1)
    {
      if ((k >= 48 && k <= 57) ||
          (e.id == Event.KEY_ACTION || k == 127 || k == 22 || k == 3 || k == 1025 || k == 8))
      {
        computeRadian(true);
      }
      else
      {
        return true;                          // Absorb the event.
      }
    }

    if (e.target == tfRadians1)
    {
      if ((k >= 48 && k <= 57) || k == 46 ||
          (e.id == Event.KEY_ACTION || k == 127 || k == 22 || k == 3 || k == 1025 || k == 8))
      {
        computeBabylonian(true, true);
      }
      else
      {
        return true;                          // Absorb the event.
      }
    }

    if (e.target == tfDecDeg1)
    {
      if ((k >= 48 && k <= 57) || k == 46 ||
          (e.id == Event.KEY_ACTION || k == 127 || k == 22 || k == 3 || k == 1025 || k == 8))
      {
        computeFromDecDeg(true);
      }
      else
      {
        return true;                          // Absorb the event.
      }
    }

    return false;
  }                                           // End of keyUp().

  // Button action events:
  public boolean action(Event e, Object o)
  {
    if (e.target == btnAdd)                                      // "Add" button
    {
      computeSum();
      return true;
    }

    if (e.target == btnSubtract)                                 // "Subtract" button
    {
      computeDifference();
      return true;
    }

    return false;
  }                                                              // End of action()

  // Do the computation of radian units from babylonian input:
  private void computeRadian(boolean bFlag)
  {
    int iDeg = 0;
    int iMin = 0;
    int iSec = 0;
    float sfRadians = 0;
    float sfDecDeg = 0;                                          // Decimal degrees (new feature v. 1.04)
    String strDegrees = null;
    String strMinutes = null;
    String strSeconds = null;

    if (bFlag)
    {
       strDegrees = tfDegrees1.getText();
       strMinutes = tfMinutes1.getText();
       strSeconds = tfSeconds1.getText();
    }
    else
    {
       strDegrees = tfDegrees0.getText();
       strMinutes = tfMinutes0.getText();
       strSeconds = tfSeconds0.getText();
    }

    try
    {
      iDeg = Integer.valueOf(strDegrees).intValue();
    }
    catch (NumberFormatException e)
    {
    }

    if (iDeg < 0)
    {
      iDeg = -iDeg;
      tfDegrees0.setText(Integer.toString(iDeg));
    }

    try
    {
      iMin = Integer.valueOf(strMinutes).intValue();
    }
    catch (NumberFormatException e)
    {
    }

    if (iMin < 0)
    {
      iMin = -iMin;
      tfMinutes0.setText(Integer.toString(iMin));
    }

    try
    {
      iSec = Integer.valueOf(strSeconds).intValue();
    }
    catch (NumberFormatException e)
    {
    }

    if (iSec < 0)
    {
      iSec = -iSec;
      tfSeconds0.setText(Integer.toString(iSec));
    }

    sfRadians = (float) ((iDeg + ((float) iMin) / 60 + ((float) iSec) / 3600) * Math.PI / 180);
    sfDecDeg = (sfRadians * 180) / ((float) Math.PI);

    if (bFlag)
    {
      tfRadians1.setText(Float.toString(sfRadians));
      tfDecDeg1.setText(Float.toString(sfDecDeg));
    }
    else
    {
      tfRadians0.setText(Float.toString(sfRadians));
      tfDecDeg0.setText(Float.toString(sfDecDeg));
    }
    clearResult();
  }                                                             // End of computeRadian()

  // Do the computation of Babylonian units on radian input:
  private void computeBabylonian(boolean bRadians, boolean bFlag)
  {
    float sfRadians = 0;
    float sfDecDeg = 0;                                          // Decimal degrees (new feature v. 1.04)
    String strRadians = null;
    int iDeg = 0;
    int iMin = 0;
    int iSec = 0;

    // Flag bFlag: if false, data from zeroeth row, from the next row otherwise.
    if (bFlag)
    {
      strRadians = tfRadians1.getText();
    }
    else
    {
      strRadians = tfRadians0.getText();
    }

    try
    {
      sfRadians = Float.valueOf(strRadians).floatValue();
    }
    catch (NumberFormatException e)
    {
    }

    if (sfRadians < 0)                                          // Defensive programming. There's no way
    {                                                           // it can be negative because of minus
      sfRadians = -sfRadians;                                   // sign filtering above. (but a clever
      if (bFlag)                                                // hacker can make use of the minus sign
      {                                                         // in exponential format)
        tfRadians1.setText(Float.toString(sfRadians));
      }
      else
      {
        tfRadians0.setText(Float.toString(sfRadians));
      }
    }

    // Round down (truncate):
    iDeg = (int) (sfRadians * 180 / Math.PI);

    // Round down (truncate):
    iMin = (int) (((sfRadians * 180 / Math.PI) - iDeg) * 60);

    // Round off:
    iSec = (int) ((((((sfRadians * 180 / Math.PI) - iDeg) * 60) - iMin) * 60) + 0.5);

    // Fix up the format if necessary:
    if (iSec == 60)
    {
      iMin++;
      iSec = 0;

      if (iMin == 60)
      {
        iDeg++;
        iMin = 0;
      }
    }

    if (bFlag)
    {
      tfDegrees1.setText(Integer.toString(iDeg));
      tfMinutes1.setText(Integer.toString(iMin));
      tfSeconds1.setText(Integer.toString(iSec));
    }
    else
    {
      tfDegrees0.setText(Integer.toString(iDeg));
      tfMinutes0.setText(Integer.toString(iMin));
      tfSeconds0.setText(Integer.toString(iSec));
    }

    if (bRadians)                                                // Flag bRadians indicates that the number
    {                                                            // to compute is coming from the Radians
      sfDecDeg = (sfRadians * 180) / ((float) Math.PI);          // text field (not from DecDeg).
      if (bFlag)
      {
        tfDecDeg1.setText(Float.toString(sfDecDeg));
      }
      else
      {
        tfDecDeg0.setText(Float.toString(sfDecDeg));
      }
    }
    clearResult();
  }                                                             // End of computeBabylonian()

  // Do the computation of Babylonian units on decimal degrees input:
  private void computeFromDecDeg(boolean bFlag)
  {
    // Convert decimal degrees to radians.
    float sfRadians = 0;
    float sfDecDeg = 0;                                          // Decimal degrees (new feature v. 1.04)
    String strDecDeg = null;

    if (bFlag)
    {
      strDecDeg = tfDecDeg1.getText();
    }
    else
    {
      strDecDeg = tfDecDeg0.getText();
    }

    try
    {
      sfDecDeg = Float.valueOf(strDecDeg).floatValue();
    }
    catch (NumberFormatException e)
    {
    }

    if (sfDecDeg < 0)                                           // Defensive programming. There's no way
    {                                                           // it can be negative because of minus
      sfDecDeg = -sfDecDeg;                                     // sign filtering above.
      if (bFlag)
      {
        tfDecDeg1.setText(Float.toString(sfDecDeg));
      }
      else
      {
        tfDecDeg0.setText(Float.toString(sfDecDeg));
      }
    }

    sfRadians = (sfDecDeg * ((float) Math.PI)) / 180;

    if (bFlag)
    {
      tfRadians1.setText(Float.toString(sfRadians));
      computeBabylonian(false, true);                           // Convert from radians to Babylonian.
    }
    else
    {
      tfRadians0.setText(Float.toString(sfRadians));
      computeBabylonian(false, false);                          // Convert from radians to Babylonian.
    }
    clearResult();
  }                                                             // End of computeFromDecDeg()

  private void clearResult()
  {
    tfDegrees2.setText("");
    tfMinutes2.setText("");
    tfSeconds2.setText("");
    tfRadians2.setText("");
    tfDecDeg2.setText("");
    lblResult.setText("");
  }                                                             // End of clearResult()

  private void computeSum()
  {
    float sfRadians0 = 0;                                       // First operand
    float sfRadians1 = 0;                                       // Second operand
    float sfRadiansSum = 0;                                     // Sum
    float sfDecDeg = 0;

    String strRadians0 = null;
    String strRadians1 = null;

    int iDeg = 0;
    int iMin = 0;
    int iSec = 0;

    strRadians0 = tfRadians0.getText();
    strRadians1 = tfRadians1.getText();

    try
    {
      sfRadians0 = Float.valueOf(strRadians0).floatValue();
    }
    catch (NumberFormatException e)
    {
    }
    try
    {
      sfRadians1 = Float.valueOf(strRadians1).floatValue();
    }
    catch (NumberFormatException e)
    {
    }

    sfRadiansSum = sfRadians0 + sfRadians1;

    sfDecDeg = (sfRadiansSum * 180) / ((float) Math.PI);

    // Round down (truncate):
    iDeg = (int) (sfRadiansSum * 180 / Math.PI);

    // Round down (truncate):
    iMin = (int) (((sfRadiansSum * 180 / Math.PI) - iDeg) * 60);

    // Round off:
    iSec = (int) ((((((sfRadiansSum * 180 / Math.PI) - iDeg) * 60) - iMin) * 60) + 0.5);

    // Fix up the format if necessary:
    if (iSec == 60)
    {
      iMin++;
      iSec = 0;

      if (iMin == 60)
      {
        iDeg++;
        iMin = 0;
      }
    }

    tfDegrees2.setText(Integer.toString(iDeg));
    tfMinutes2.setText(Integer.toString(iMin));
    tfSeconds2.setText(Integer.toString(iSec));

    tfRadians2.setText(Float.toString(sfRadiansSum));
    tfDecDeg2.setText(Float.toString(sfDecDeg));
    lblResult.setText("");
  }

  private void computeDifference()
  {
    float sfRadians0 = 0;                                        // First operand
    float sfRadians1 = 0;                                        // Second operand
    float sfRadiansSum = 0;                                      // Sum
    float sfDecDeg = 0;

    String strRadians0 = null;
    String strRadians1 = null;

    int iDeg = 0;
    int iMin = 0;
    int iSec = 0;

    strRadians0 = tfRadians0.getText();
    strRadians1 = tfRadians1.getText();

    try
    {
      sfRadians0 = Float.valueOf(strRadians0).floatValue();
    }
    catch (NumberFormatException e)
    {
    }
    try
    {
      sfRadians1 = Float.valueOf(strRadians1).floatValue();
    }
    catch (NumberFormatException e)
    {
    }

    sfRadiansSum = sfRadians0 - sfRadians1;

    if (sfRadiansSum < 0)
    {
      sfRadiansSum = -sfRadiansSum;
      lblResult.setText("Difference result is an absolute value.");
    }

    sfDecDeg = (sfRadiansSum * 180) / ((float) Math.PI);

    // Round down (truncate):
    iDeg = (int) (sfRadiansSum * 180 / Math.PI);

    // Round down (truncate):
    iMin = (int) (((sfRadiansSum * 180 / Math.PI) - iDeg) * 60);

    // Round off:
    iSec = (int) ((((((sfRadiansSum * 180 / Math.PI) - iDeg) * 60) - iMin) * 60) + 0.5);

    // Fix up the format if necessary:
    if (iSec == 60)
    {
      iMin++;
      iSec = 0;

      if (iMin == 60)
      {
        iDeg++;
        iMin = 0;
      }
    }

    tfDegrees2.setText(Integer.toString(iDeg));
    tfMinutes2.setText(Integer.toString(iMin));
    tfSeconds2.setText(Integer.toString(iSec));

    tfRadians2.setText(Float.toString(sfRadiansSum));
    tfDecDeg2.setText(Float.toString(sfDecDeg));
  }                                                              // End of computeSum()

} // End of Angular applet.