/*
   COPYRIGHT (C) 2010 - 2013 by Alexander Wait. All Rights Reserved.

   This class displays the GUI for the calculator.

   @site http://www.javaika.com
   @author Alexander Wait
   @version 2010-07-18
*/



import java.awt.Color;
import java.awt.Container; 
import java.awt.Dimension; 
import java.awt.FlowLayout;
import java.awt.Font;  
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.datatransfer.StringSelection;
import java.awt.event.*;

import javax.swing.*;



public class ScientificCalculatorGui extends JApplet implements ComponentListener, KeyListener
{
   private static final String copyright = "Copyright (c) 2012 by Alexander Wait - All Rights Reserved";
   
   private static final long serialVersionUID = 1L;
   
   
   static boolean isApplication = false;
   
   static boolean runRestricted = false;
   
   static boolean isVisible = false;
   
   
   private static final int FRAME_SIZE_X = 615; 
   
   private static final int FRAME_SIZE_Y = 555;
   
   private static final int MENU_ARRAY_SIZE = 8;
   
   private static final int ENTER_ARRAY_SIZE = 3; 
   
   private static final int OPERATOR_ARRAY_SIZE = 24;
   
   private static final int DECIMAL_PLACE_MINIMUM = 1;
   
   private static final int DECIMAL_PLACE_MAXIMUM = 15;
   
   private static final int INITIAL_DECIMAL_PLACES = 3; 
   
   private static final int VARIANCE_DEVIATION_INDEX = 0; 
   
   private static final int INITIAL_COMPUTATION_COUNTER = 1; 
   
   private static final int MINIMUM_MAXIMUM_INDEX = 3; 
   
   private static final int MAX_FIBONACCI_NUMBER = 93;
   
   private static final int MEDIAN_MODE_INDEX = 1;
   
   private static final int COUNT_RANGE_INDEX = 2;   
   
   private static final int SUM_SQUARES_INDEX = 4; 
   
   private static final int MEAN_SQUARES_INDEX = 5; 
   
   private static final int DATA_PRINT_INDEX = 6; 
   
   private static final int DECIMAL_INDEX = 7; 
   
   private static final int ENTER_INDEX = 0; 
   
   private static final int COPY_INDEX = 1; 
   
   private static final int EQUALS_INDEX = 2;
   
   
   //************************************** START INITIALISATION CODE **************************************//
   
   
   /**
    * Browser constructor.
    */
   public void init()
   {  
      String copyrightParam = getParameter("copyright");
       
      if ((copyrightParam == null) || !copyrightParam.equals(copyright)) 
      {
         Message.showMessage("Invalid Copyright", "WARNING", "warning"); 
      }       
       
      else if (!getDocumentBase().getHost().equals(Domain.getDomain()))
      {
         Message.showMessage("Unauthorised Applet Use", "ERROR", "error");
      }
  
      else
      {
         try {getToolkit().getSystemClipboard();}
      
         catch (java.security.AccessControlException e) {runRestricted = true;}  
 
         
         initialiser(); includeResizeEvent(); setJMenuBar(menuBar); 
         
         setSize(FRAME_SIZE_X,FRAME_SIZE_Y); defaultOnStartup();
         

         if(runRestricted) {enterButton[COPY_INDEX].setEnabled(false);}
      }
   }

   
   
   /**
    * Application constructor.
    */
   public ScientificCalculatorGui() 
   {
      if (isApplication)
      {
         initialiser();
         
      
         frame = new JFrame(); 
         
         frame.setMinimumSize(new Dimension(FRAME_SIZE_X, FRAME_SIZE_Y));
         
         frame.setSize(FRAME_SIZE_X,FRAME_SIZE_Y);
         
         frame.setLocationRelativeTo(null); 
         
         frame.setTitle("Calculator Program");
         
         frame.setJMenuBar(menuBar); 
         
         frame.add(contentPane); 
         
         
         setVisibility(); defaultOnStartup();
      }
      
   }
   
   
   
   /**
    * GUI initializer.
    * ESCA-JAVA0076:
    */
   private void initialiser()
   {
      calc = new ScientificCalculator(); valid = new Validation(); 
      
      
      
      // Initialize content pane and layout.
      
      contentPane = getContentPane(); contentPane.setLayout(new GridBagLayout()); 
      
  
      
      // Initialize text field GUI components.  
  
      input = new JTextField(); input.addKeyListener(this);
      
      input.setPreferredSize(new Dimension(579, 26));
       
      input.setFont(new Font(input.getFont().getName(), 

      input.getFont().getStyle(), 16)); 
      
      
      
      // Initialize text area GUI components.   
      
      display = new JTextArea (14,45); display.setEditable(false); 
      
      
      
      // Initialize key pad GUI components.
      
      pad = new KeyPad(input); pad.display.setEditable(false); 
      
      pad.display.setPreferredSize(new Dimension(20,53)); 
      
      
      
      // Initialize scroll pane GUI components. 
      
      scrollPane = new JScrollPane(display, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
      
      JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); 
     
      
      
      // Initialize menu bar GUI components. 
      
      menuBar = new JMenuBar(); 
      
      menuBar.add(createModeMenu()); menuBar.add(createDisplayMenu()); 
      
      menuBar.add(createSequenceMenu()); menuBar.add(createSettingsMenu());
      
      
      
      // Initialize check box GUI components.  
      
      workingBox = new JCheckBox("W");
      
      workingBox.setFocusPainted(false); workingBox.setSelected(false); 
      
      workingBox.addItemListener(new HandlerClass("work")); 
      
      
      
      // Initialize radio button GUI components.   
      
      degrees = new JRadioButton("D", true); degrees.setFocusPainted(false);
      
      degrees.addItemListener(new HandlerClass("deg")); 
      
      
      radians = new JRadioButton("R", true); radians.setFocusPainted(false);  

      radians.addItemListener(new HandlerClass("rad")); 
      
      
      
      // Initialize button group GUI components. 
      
      group = new ButtonGroup(); group.add(degrees); group.add(radians); 
      
      
      
      // Initialize default settings for GUI components. 
      
      calc.setMode(true); calc.setDecimalPlaces(3); 
      
      
      places = INITIAL_DECIMAL_PLACES; 
      
      runType = "Calculator"; working = false;
      
      computationCounter = INITIAL_COMPUTATION_COUNTER; 
      
     
      
      // Initialize JPanel GUI components.
      
      settingsPanel = new JPanel(); settingsPanel.setLayout(new GridLayout(1, 2)); 
      
      enterPanel = new JPanel(); enterPanel.setLayout(new GridLayout(3, 1));
      
      containerPanel = new JPanel(); containerPanel.setLayout(new GridLayout(2,1));
      
      operatorPanel = new JPanel(); operatorPanel.setLayout(new GridLayout(6, 4));
      
      topPanel = new JPanel(); topPanel.setLayout(new FlowLayout());
      
      
      
      // Add GUI components to JPanels. 
      
      settingsPanel.add(workingBox); settingsPanel.add(degrees); settingsPanel.add(radians); 

      topPanel.add(containerPanel); topPanel.add(pad); topPanel.add(operatorPanel);
      
      containerPanel.add(settingsPanel); containerPanel.add(enterPanel); 
      
      
      
      // Method calls for GUI initialization.
      
      addMouseMotionListener(new HandlerClass("mouse")); 

      gridBagConstraints(); constructOperatorButtons(); setColors(); setGraphicIcons();
   }
   
   
   
   /**
    * Constructs the operator buttons.
    * ESCA-JAVA0076:
    */
   private void constructOperatorButtons()
   {
      for (int i = 0; i < enterButton.length; i ++)
      {
         enterButton[i] = new JButton(enterButtonText[i]); 
         
         enterButton[i].setPreferredSize(new Dimension(135, 29));
         
         enterButton[i].setFocusPainted(false); enterPanel.add(enterButton[i]);
         
         enterButton[i].addMouseMotionListener(new HandlerClass("mouse")); 
      }
 
      enterButton[ENTER_INDEX].addActionListener(new EnterButtonListener());
      
      enterButton[COPY_INDEX].addActionListener(new CopyButtonListener()); 
      
      enterButton[EQUALS_INDEX].addActionListener(new EqualsButtonListener());

      
      for (int i = 0; i < operatorButton.length; i ++)
      {
         operatorButton[i] = new JButton(operatorButtonText[i]); 

         operatorButton[i].setPreferredSize(new Dimension(83, 29)); 
         
         operatorButton[i].setFocusPainted(false); operatorPanel.add(operatorButton[i]); 
         
         operatorButton[i].addMouseMotionListener(new HandlerClass("mouse")); 
         
         operatorButton[i].addActionListener(new OperatorButtonListener(i));
      }  
      
      
      disableEnablePanels("enter", ENTER_INDEX, ENTER_INDEX, false); 
      
      disableEnablePanels("menu", VARIANCE_DEVIATION_INDEX, DATA_PRINT_INDEX, false);
   }
   
   
   
   /**
    * Sets the background color.
    */
   private void setColors()
   {
      contentPane.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      topPanel.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      display.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );

      pad.display.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );

      input.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
     
      degrees.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      radians.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      workingBox.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
 
   }
   
   
   
   /**
    * Sets icons for graphical elements.
    */
   private void setGraphicIcons()
   {
      degrees.setIcon(new ImageIcon
      (this.getClass().getResource("files/images/RadioButtonNormalUnselected.png")));
             
      degrees.setSelectedIcon(new ImageIcon
      (this.getClass().getResource("files/images/RadioButtonNormalSelected.png")));

      degrees.setDisabledIcon(new ImageIcon
      (this.getClass().getResource("files/images/RadioButtonDisabledUnselected.png")));

      degrees.setDisabledSelectedIcon(new ImageIcon
      (this.getClass().getResource("files/images/RadioButtonDisabledSelected.png")));
      
      
      radians.setIcon(new ImageIcon
      (this.getClass().getResource("files/images/RadioButtonNormalUnselected.png")));
                 
      radians.setSelectedIcon(new ImageIcon
      (this.getClass().getResource("files/images/RadioButtonNormalSelected.png")));

      radians.setDisabledIcon(new ImageIcon
      (this.getClass().getResource("files/images/RadioButtonDisabledUnselected.png")));

      radians.setDisabledSelectedIcon(new ImageIcon
      (this.getClass().getResource("files/images/RadioButtonDisabledSelected.png")));
      
      
      workingBox.setIcon(new ImageIcon
      (this.getClass().getResource("files/images/CheckBoxNormalUnselected.png")));
                     
      workingBox.setSelectedIcon(new ImageIcon
      (this.getClass().getResource("files/images/CheckBoxNormalSelected.png")));

      workingBox.setDisabledIcon(new ImageIcon
      (this.getClass().getResource("files/images/CheckBoxDisabledUnselected.png")));

      workingBox.setDisabledSelectedIcon(new ImageIcon
      (this.getClass().getResource("files/images/CheckBoxDisabledSelected.png")));
         
   }
   
   
   
   /**
    * Sets the grid bag layout.
    * ESCA-JAVA0076:
    */
   private void gridBagConstraints()
   {
      // Initialize grid bag layout of GUI.
      
      constraints = new GridBagConstraints();
      
      constraints.fill = GridBagConstraints.HORIZONTAL;
      
      
      
      // Grid bag constraints 1.
      
      constraints.insets = new Insets(10,0,0,0);
      
      
      constraints.ipadx = 0; 
      
      constraints.ipady = 0;

      constraints.gridwidth = 3;
      
      constraints.weightx = 0; 
      
      constraints.weighty = 0; 
      
      constraints.gridx = 0; 
      
      constraints.gridy = 0;
      
      
      contentPane.add(topPanel, constraints);
      
      
      
      // Grid bag constraints 2.
      
      constraints.insets = new Insets(10,0,0,0);
      
      
      constraints.ipadx = 0; 
      
      constraints.ipady = 0;

      constraints.gridwidth = 3;
      
      constraints.weightx = 0; 
      
      constraints.weighty = 0; 
      
      constraints.gridx = 0; 
      
      constraints.gridy = 1;
      
      
      contentPane.add(input, constraints);
      
      
      
      // Grid bag constraints 3.
      
      constraints.insets = new Insets(10,0,0,0);
      
      
      constraints.ipadx = 0; 
      
      constraints.ipady = 0;

      constraints.gridwidth = 3;
    
      constraints.weightx = 0; 
      
      constraints.weighty = 0; 
      
      constraints.gridx = 0; 
      
      constraints.gridy = 2;
      
      
      contentPane.add(scrollPane, constraints);
   }
   
   
   //*************************************** END INITIALISATION CODE ***************************************//
   
   
   //************************************* START INTERFACE EVENT CODE **************************************//
   
   
   private class EnterButtonListener
   implements ActionListener
   {
   
      /**
       * Listener that responds appropriately to enter button click.
       */
      public void actionPerformed(ActionEvent event)
      {
         enterActionHelper();
      }
   }
   
   
   
   private class EqualsButtonListener
   implements ActionListener
   {

      /**
       * Listener that responds appropriately to equal button click. 
       * ESCA-JAVA0166:
       */
      public void actionPerformed(ActionEvent event)
      {
         equalsActionHelper();
       
      }
   }
   
   
   
   /**
    * ESCA-JAVA0043:
    */
   private class CopyButtonListener
   implements ActionListener
   {

     
      /**
       * Listener that responds appropriately to copy button click.
       * ESCA-JAVA0166:
       */
      public void actionPerformed(ActionEvent event)
      {
         StringSelection ss = new StringSelection(display.getText());
         Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss, null);
      }
   }
   
   
   
   private class OperatorButtonListener
   implements ActionListener
   {
      
      /**
       * Listener that responds appropriately to operator 
       * button click using a switch.
       * @param args
       */
      private OperatorButtonListener(int args)
      {
         button = args;
      }

      public void actionPerformed(ActionEvent event)
      {
         operatorActionHelper(button);
      }

      int button;
   }
   
   
   
   /**
    * Show working check box listener. 
    */
   private class HandlerClass implements ItemListener, MouseMotionListener
   {
      String type;

      private HandlerClass(String handlerType)
      {
         type = handlerType;
      }

      public void itemStateChanged(ItemEvent event)
      {
         if (type.equals("work"))
         {
            if (workingBox.isSelected())
            {
               working = true;
            }

            else
            {
               working = false;
            }
         }

         else if (type.equals("deg")) 
         {
            calc.setMode(true);
         }

         else if (type.equals("rad")) 
         {
            calc.setMode(false);
         }
      }

      public void mouseDragged(MouseEvent event){}

      public void mouseMoved(MouseEvent event){}
   }
   


   /**
    * Overrides KeyListener.
    */
   public void keyTyped(KeyEvent e) {}
   
   public void keyReleased(KeyEvent e) {}
   
   public void keyPressed(KeyEvent e) 
   {
      int key = e.getKeyCode();
       
      if (key == KeyEvent.VK_ENTER) 
      {    
         if (runType.equals("Calculator"))
         {
            equalsActionHelper();
         }
         
         else
         {
            enterActionHelper();
         }
      }
   }
   
   
   
   /**
    * Overrides ComponentListener.
    */
   public void componentMoved(ComponentEvent e) {}
   
   
   public void componentResized(ComponentEvent e) {}
   
   
   public void componentShown(ComponentEvent e) {setContentDisplay(true);}
   
   
   public void componentHidden(ComponentEvent e) {setContentDisplay(false);}
   
    
   //************************************** END INTERFACE EVENT CODE ***************************************//
   
   
   //**************************************** START PUBLIC METHODS *****************************************//
   
   
   /**
    * Sets the visibility of the frame.
    */
   public void setVisibility()
   {
      if (isVisible) 
      {
         frame.setVisible(true);
      }
      
      else 
      {
         frame.setVisible(false);
      } 
   }
   
   
   
   /**
    * Displays or Hides contents of GUI.
    * @param shown
    */
   public void setContentDisplay(boolean shown)
   {
      menuBar.setVisible(shown);
         
      contentPane.setVisible(shown);
   }
   
   
   //***************************************** END PUBLIC METHODS ******************************************//
   
   
   //**************************************** START PRIVATE METHODS ****************************************//
   
   
   /**
    * Helper for enter action.
    * ESCA-JAVA0049:
      ESCA-JAVA0166:
    */
   private void enterActionHelper()
   {
      try
       {
          pad.display.setText(""); 
          
          final int MAX_RANDOM_VALUE = 99;
          
          
          if (!input.getText().equals(""))
          {
             if (runType.equals("dataSet"))
             {
                if (dataStep.equals("number"))
                {
                   if (valid.integerValidation(input.getText())) 
                   {
                      if (Integer.parseInt(input.getText()) > 1)
                      {
                         int size = Integer.parseInt(input.getText());

                         dataSetArray = new double[size]; 

                         
                         display.setText(Tools.returnNewline(3) + "  Enter number " + 
                         
                         (index) + ":" + Tools.returnNewline(2)); input.setText(""); 
                         
                         
                         dataStep = "values";
                      }
                   }
                   
                   else {enterException();}
                }

                else if (dataStep.equals("values") && index < dataSetArray.length)
                {
                   if (valid.numberValidation(input.getText()))
                   {
                      double val = Double.parseDouble(input.getText());

                      dataSetArray[index - 1] = val;
                      
                      
                      display.setText(Tools.returnNewline(3) + "  Enter number " + 
                      
                      (index + 1) + ":" + Tools.returnNewline(2)); pad.clear(); 
                      
                      
                      index ++;
                   }
                   
                   else {enterException();}
                }

                else if (dataStep.equals("values") && index == dataSetArray.length)
                {
                   dataSetArray[index - 1] = Double.parseDouble(input.getText()); 

                   
                   display.setText(Tools.returnNewline(1) +
                   
                   "  The DataSet has been successfully added." + Tools.returnNewline(1) + 
                   
                   "  Results are shown under 'Display'" + Tools.returnNewline(1));

                   
                   disableEnablePanels("menu", VARIANCE_DEVIATION_INDEX, DATA_PRINT_INDEX, true); 
                   
                   
                   pad.clear(); dataStep = "results";
                }
             }

             if (runType.equals("settings"))
             {
                if (valid.integerValidation(input.getText()))
                {
                   places = Integer.parseInt(input.getText()); calc.setDecimalPlaces(places);

                   if ((DECIMAL_PLACE_MINIMUM <= places) && (DECIMAL_PLACE_MAXIMUM >= places))
                   {
                      disableEnablePanels("enter", ENTER_INDEX, ENTER_INDEX, false); 
                    
                      disableEnablePanels("enter", EQUALS_INDEX, EQUALS_INDEX, true); 

                      disableEnablePanels("operator", 0, operatorButton.length - 1, true);
                      
                      
                      runType = "Calculator"; pad.clear();
                   }

                   else {enterException();}
                }
                
                else {enterException();}
             }

             if (runType.equals("randomSequence"))
             {
                if (valid.integerValidation(input.getText()))
                {
                   if ((dataStep.equals("number")) && (Integer.parseInt(input.getText()) > 0) 
                   && (Integer.parseInt(input.getText()) <= MAX_FIBONACCI_NUMBER))
                   {
                      number = Integer.parseInt(input.getText()); pad.clear();
                      
                      
                      display.setText(Tools.returnNewline(1) + "  Set the minimum random value." + 
                      
                      Tools.returnNewline(1)); dataStep = "minimum";

                      
                      display.append("  Enter number between " + "[0" + "-" + 
                      
                      MAX_RANDOM_VALUE + "]" + Tools.returnNewline(2));
                   }

                   else if ((dataStep.equals("minimum")) && (Integer.parseInt(input.getText()) >= 0) 
                   && (Integer.parseInt(input.getText()) <= MAX_RANDOM_VALUE))
                   {
                      minimum = Integer.parseInt(input.getText()); pad.clear();
                      
                      
                      display.setText(Tools.returnNewline(1) + 

                      "  Set the maximum random value." + Tools.returnNewline(1)); 
                      
                      
                      dataStep = "maximum"; display.append("  Enter number between " + 
                      
                      "[" + minimum + "-" + MAX_RANDOM_VALUE + "]" + Tools.returnNewline(2));
                   }

                   else if ((dataStep.equals("maximum")) 
                   && (Integer.parseInt(input.getText()) >= minimum) 
                   && (Integer.parseInt(input.getText()) <= MAX_RANDOM_VALUE))
                   {
                      maximum = Integer.parseInt(input.getText()); pad.clear();
                      
                      
                      display.setText(Tools.returnNewline(1) + 
                     
                      "  Press enter to display results."); dataStep = "results";
                   }

                   if (dataStep.equals("results"))
                   {
                      display.setText(Tools.returnNewline(1) + 
                      
                      "  Random Sequence: " + Tools.returnNewline(2));
                     
                      
                      for (int i = 0; i < number; i ++)
                      {
                         display.append("  " + "Number " + (i + 1) + ")   " + 
                      
                         DataFunctions.random(minimum,maximum) + Tools.returnNewline(2));
                      }
                   }
                }
                
                else {enterException();}
             }

             if (runType.equals("fibonacciSequence"))
             {
                if (valid.integerValidation(input.getText()))
                {
                   if ((dataStep.equals("number")) && (Integer.parseInt(input.getText()) > 0) 
                   && (Integer.parseInt(input.getText()) <= MAX_FIBONACCI_NUMBER))
                   {
                      number = Integer.parseInt(input.getText()); pad.clear();
         
                      display.setText(Tools.returnNewline(1) + "  Press enter to display results.");
                      

                      dataStep = "results";
                   }

                   if (dataStep.equals("results"))
                   {
                      display.setText(Tools.returnNewline(1) + 
                      
                      "  Fibonacci Sequence: " + Tools.returnNewline(2));

                      
                      for (int i = 0; i < number; i ++)
                      {
                         display.append("  " + "Number " + (i + 1) + ")   " + 
                      
                         DataFunctions.fibonacci(i) + Tools.returnNewline(2));
                      }
                   }
                }
                
                else {enterException();}
             }
          }
       }

       catch (Exception e) {enterException();} 
   }

   
   
   /**
    * Handler for equals action.
    */
   private void equalsActionHelper()
   {
      pad.display.setText("");  
       
      if (!input.getText().equals(""))
      {
         String formula = calc.formatFormula(input.getText());
    
         
         display.append
         (
            Tools.returnNewline(1) + "  [A:" + computationCounter + "]    " + formula + "   "
         ); 
         
         calc.setOuterFormula(formula); runCalculation(working); pad.clear();
          
         display.setCaretPosition(display.getDocument().getLength());
      }
  
   }
   
   
   
   /**
    * Helper for operator action.
    * ESCA-JAVA0076:
    * @param button
    */
   private void operatorActionHelper(int button)
   {
      switch (button)
      {
         case 0:  input.setText(input.getText() + "Log("); break; 
         
         case 1:  input.setText(input.getText() + "Mod("); break;
         
         case 2:  input.setText(input.getText() + "Pwr("); break; 
         
         case 3:  input.setText(input.getText() + "Cwr("); break;
         
         case 4:  input.setText(input.getText() + "Sin("); break; 
         
         case 5:  input.setText(input.getText() + "Cos("); break;
         
         case 6:  input.setText(input.getText() + "Tan("); break; 
         
         case 7:  input.setText(input.getText() + "Fac("); break; 
         
         case 8:  input.setText(input.getText() + "Inv("); break; 
         
         case 9:  input.setText(input.getText() + "Abs("); break; 
         
         case 10: input.setText(input.getText() + " x 10 ^ "); break; 
         
         case 11: input.setText(input.getText() + ","); break; 
         
         case 12: input.setText(input.getText() + " x "); break; 
         
         case 13: input.setText(input.getText() + " / "); break; 
         
         case 14: input.setText(input.getText() + " + "); break; 
         
         case 15: input.setText(input.getText() + " - "); break; 
         
         case 16: input.setText(input.getText() + " ^ "); break; 
         
         case 17: input.setText(input.getText() + " v "); break; 
         
         case 18: input.setText(input.getText() + "("); break; 
         
         case 19: input.setText(input.getText() + ")"); break;
         
         case 20: input.setText(input.getText() + "-"); break;
         
         case 21: input.setText(input.getText() + "PI"); break;
         
         case 22: input.setText(input.getText() + "e"); break;
         
         case 23: input.setText(input.getText() + "+"); break;
         
         default: System.exit(0); break;
      }
   }
   
   
   
   /**
    * Displays the calculation and simplification of formula. 
    * ESCA-JAVA0166:
    * ESCA-JAVA0076:
    * @param showWorking
    */
   private void runCalculation(boolean showWorking)
   {
      calc.simplificationList.clear(); calc.run(); 

      if (showWorking)
      {
         for (int i = 1; i < calc.simplificationList.size(); i ++) 
         {
            display.append("\n\n" + Tools.returnSpace(17) 
            + "= " + calc.simplificationList.get(i));
         }
      }
      
      else
      {
         display.append("\n\n" + Tools.returnSpace(17) + "= " + 
         calc.simplificationList.get(calc.simplificationList.size() - 1));
      }

      display.append("\n\n");
 
      
      computationCounter ++;
  
   }


   
   /**
    * Default mode on startup.
    */
   private void defaultOnStartup()
   {

      disableEnablePanels("enter", ENTER_INDEX, ENTER_INDEX, false); 
      
      disableEnablePanels("enter", EQUALS_INDEX, EQUALS_INDEX, true); 
      
      disableEnablePanels("operator", 0, operatorButton.length - 1, true); 
      
      disableEnablePanels("menu", VARIANCE_DEVIATION_INDEX, DATA_PRINT_INDEX, false);
      
      disableEnablePanels("menu", DECIMAL_INDEX, DECIMAL_INDEX, true); 
      
      runType = "Calculator"; computationCounter = INITIAL_COMPUTATION_COUNTER;
      
      display.setText("  \n CALCULATOR MODE \n\n");
      
      display.addMouseMotionListener(new HandlerClass("mouse")); 
   }
   
   

   /**
    * Disables or enables the interface contents for data set mode.
    */
   private void datasetInterfaceInitialisation()
   {
      disableEnablePanels("menu", VARIANCE_DEVIATION_INDEX, DECIMAL_INDEX, false); 
      
      disableEnablePanels("operator", 0, operatorButton.length - 1, false); 
      
      disableEnablePanels("enter", ENTER_INDEX, ENTER_INDEX, true);
      
      disableEnablePanels("enter", EQUALS_INDEX, EQUALS_INDEX, false);    
   }



   /**
    * Disables or enables the interface contents for series mode.
    */
   private void seriesInterfaceInitialisation()
   {
      disableEnablePanels("operator", 0, operatorButton.length - 1, false);
      
      disableEnablePanels("enter", EQUALS_INDEX, EQUALS_INDEX, false);
      
      disableEnablePanels("enter", ENTER_INDEX, ENTER_INDEX, true);
   }



   /**
    * Disables or enables the panels.
    * @param type
    * @param startIndex 
    * @param endIndex
    * @param enabled
    */
   private void disableEnablePanels(String type, 
   int startIndex, int endIndex, Boolean enabled)
   {
      for (int i = startIndex; i <= endIndex; i ++)
      {
         if (type.equals("menu"))
         {
            item[i].setEnabled(enabled);
         }

         if (type.equals("enter"))
         {
            enterButton[i].setEnabled(enabled);
         }

         if (type.equals("operator"))
         {
            operatorButton[i].setEnabled(enabled);
         }
      }
   }
 
   

   /**
    * Adds variance and deviation menu item and listener that responds appropriately.
    * @return 
    */
   private JMenuItem varianceDeviation() 
   {

      item[VARIANCE_DEVIATION_INDEX] = new JMenuItem("Variance and Deviation");

      class MenuItemListener implements ActionListener
      {
         public void actionPerformed(ActionEvent event)  
         {
            display.setText(Tools.returnNewline(1) + "  The variance is: " + 
            calc.decimalRounding(DataFunctions.returnDeviationVariance
            (dataSetArray,true), places) + Tools.returnNewline(1));

            display.append(Tools.returnNewline(1) + "  The standard deviation is: " + 
            calc.decimalRounding(DataFunctions.returnDeviationVariance
            (dataSetArray,false), places));
         }
      }

      ActionListener listener = new MenuItemListener(); 
      
      item[VARIANCE_DEVIATION_INDEX].addActionListener(listener);

      return item[VARIANCE_DEVIATION_INDEX];
   }



   /**
    * Adds median and mode menu item and listener that responds appropriately.
    * @return 
    */
   private JMenuItem medianMode() 
   {

      item[MEDIAN_MODE_INDEX] = new JMenuItem("Median and Mode");

      class MenuItemListener implements ActionListener
      {
         public void actionPerformed(ActionEvent event)  
         {
            display.setText(Tools.returnNewline(1) + "  The median value is: " + 
            calc.decimalRounding(DataFunctions.returnMedian
            (dataSetArray), places) + Tools.returnNewline(1));
   
            display.append(Tools.returnNewline(1) + "  The modes are: " + 
            DataFunctions.returnModes(dataSetArray) + "  ");
         }
      }

      ActionListener listener = new MenuItemListener(); 
      
      item[MEDIAN_MODE_INDEX].addActionListener(listener);

      return item[MEDIAN_MODE_INDEX];
   }



   /**
    * Adds count and range menu item and listener that responds appropriately.
    * @return 
    */
   private JMenuItem countRange() 
   {

      item[COUNT_RANGE_INDEX] = new JMenuItem("Count and Range");

      class MenuItemListener implements ActionListener
      {
         public void actionPerformed(ActionEvent event)  
         {
            display.setText(Tools.returnNewline(1) + "  The count is: " + 
            DataFunctions.returnCount(dataSetArray) + Tools.returnNewline(1));

            display.append(Tools.returnNewline(1) + "  The range is: " + 
            calc.decimalRounding(DataFunctions.returnRange(dataSetArray), places));
         }
      }

      ActionListener listener = new MenuItemListener(); 
      
      item[COUNT_RANGE_INDEX].addActionListener(listener);

      return item[COUNT_RANGE_INDEX];
   }



   /**
    * Adds minimum and maximum menu item and listener that responds appropriately.
    * @return 
    */
   private JMenuItem minimumMaximum() 
   {

      item[MINIMUM_MAXIMUM_INDEX] = new JMenuItem("Minimum and Maximum");

      class MenuItemListener implements ActionListener
      {
         public void actionPerformed(ActionEvent event)  
         {
            display.setText(Tools.returnNewline(1) + "  The minimum value is: " + 
            calc.decimalRounding(DataFunctions.returnMinimum
            (dataSetArray), places) + Tools.returnNewline(1));

            display.append(Tools.returnNewline(1) + "  The maximum value is: " + 
            calc.decimalRounding(DataFunctions.returnMaximum
            (dataSetArray), places));
         }
      }

      ActionListener listener = new MenuItemListener(); 
      
      item[MINIMUM_MAXIMUM_INDEX].addActionListener(listener);

      return item[MINIMUM_MAXIMUM_INDEX];
   }



   /**
    * Adds sum and squares menu item and listener that responds appropriately. 
    * @return
    */
   private JMenuItem sumSquares() 
   {

      item[SUM_SQUARES_INDEX] = new JMenuItem("Sum and Squares");

      class MenuItemListener implements ActionListener
      {
         public void actionPerformed(ActionEvent event)  
         {
            display.setText(Tools.returnNewline(1) + "  The sum is: " + 
            calc.decimalRounding(DataFunctions.returnSum
            (dataSetArray,false), places) + Tools.returnNewline(1));

            display.append(Tools.returnNewline(1) + "  The sum of squares is: " + 
            calc.decimalRounding(DataFunctions.returnSum
            (dataSetArray,true), places));
         }
      }

      ActionListener listener = new MenuItemListener(); 
      
      item[SUM_SQUARES_INDEX].addActionListener(listener);

      return item[SUM_SQUARES_INDEX];
   }



   /**
    * Adds mean and squares menu item and listener that responds appropriately.
    * @return 
    */
   private JMenuItem meanSquares() 
   {

      item[MEAN_SQUARES_INDEX] = new JMenuItem("Mean and Squares");

      class MenuItemListener implements ActionListener
      {
         public void actionPerformed(ActionEvent event)  
         {
            display.setText(Tools.returnNewline(1) + "  The mean is: " + 
            calc.decimalRounding(DataFunctions.returnMean
            (dataSetArray,false), places) + Tools.returnNewline(1));
            
            display.append(Tools.returnNewline(1) + "  The mean of squares is: " + 
            calc.decimalRounding(DataFunctions.returnMean
            (dataSetArray,true), places));
         }
      }
      
      ActionListener listener = new MenuItemListener(); 
      
      item[MEAN_SQUARES_INDEX].addActionListener(listener);

      return item[MEAN_SQUARES_INDEX];
   }



   /**
    * Adds print menu item and listener that responds appropriately. 
    * @return 
    */
   private JMenuItem dataPrint() 
   {

      item[DATA_PRINT_INDEX] = new JMenuItem("Display The Full Data Set");

      class MenuItemListener implements ActionListener
      {
         public void actionPerformed(ActionEvent event)  
         {
            display.setText(Tools.returnNewline(1) + "  The dataset values are: " + 
            DataFunctions.printData(dataSetArray) + "  " + Tools.returnNewline(1));
         }
      }

      ActionListener listener = new MenuItemListener(); 
      
      item[DATA_PRINT_INDEX].addActionListener(listener);

      return item[DATA_PRINT_INDEX];
   }



   /**
    * Adds random menu item and listener that responds appropriately. 
    * @return
    */
   private JMenuItem random() 
   {

      JMenuItem menuItem = new JMenuItem("Random");

      class MenuItemListener implements ActionListener
      {
         public void actionPerformed(ActionEvent event)  
         {
            seriesInterfaceInitialisation();

            display.setText(Tools.returnNewline(1) + 
            "  How many random numbers ? " + Tools.returnNewline(1));
            
            display.append("  Enter number between " + "[1" + "-" + 
            MAX_FIBONACCI_NUMBER + "]" + Tools.returnNewline(2));
            
            runType = "randomSequence"; dataStep = "number";
         }
      }

      ActionListener listener = new MenuItemListener(); 
      
      menuItem.addActionListener(listener);

      return menuItem;
   }



   /**
    * Adds random menu item and listener that responds appropriately. 
    * @return
    */
   private JMenuItem fibonacci() 
   {

      JMenuItem menuItem = new JMenuItem("Fibonacci");

      class MenuItemListener implements ActionListener
      {
         public void actionPerformed(ActionEvent event)  
         {
            seriesInterfaceInitialisation();  

            display.setText(Tools.returnNewline(1) + 
            "  How many fibonacci numbers ? " + Tools.returnNewline(1));
            
            display.append("  Enter number between " + "[1" + "-" + 
            MAX_FIBONACCI_NUMBER + "]" + Tools.returnNewline(2));

            runType = "fibonacciSequence"; dataStep = "number";
         }
      }

      ActionListener listener = new MenuItemListener(); 
      
      menuItem.addActionListener(listener);

      return menuItem;
   }



   /**
    * Adds decimal places menu item and listener that responds appropriately. 
    * @return
    */
   private JMenuItem decimalPlaces() 
   {

      item[DECIMAL_INDEX] = new JMenuItem("Rounding");

      class MenuItemListener implements ActionListener
      {
         public void actionPerformed(ActionEvent event)  
         {
            seriesInterfaceInitialisation();
            
            display.append(Tools.returnNewline(1) + "  Enter number between " + 
            "[" + DECIMAL_PLACE_MINIMUM + "-" + DECIMAL_PLACE_MAXIMUM + "]" + 
            Tools.returnNewline(2)); runType = "settings";
         }
      }

      ActionListener listener = new MenuItemListener(); 
      
      item[DECIMAL_INDEX].addActionListener(listener);

      return item[DECIMAL_INDEX];
   }



   /**
    * Adds data set mode menu item and listener that responds appropriately.
    * @return menuItem 
    */
   private JMenuItem dataSetMode() 
   {
  
      JMenuItem menuItem = new JMenuItem("Statistics");

      class MenuItemListener implements ActionListener
      {
         public void actionPerformed(ActionEvent event)  
         {
            datasetInterfaceInitialisation();
         
            display.setText("  \n STATISTICS MODE \n\n");
            
            display.append("  How many numbers ?" + Tools.returnNewline(2)); 
            
            dataStep = "number"; runType = "dataSet"; index = 1;
         }
      }

      ActionListener listener = new MenuItemListener(); 
     
      menuItem.addActionListener(listener);
      
      return menuItem;
   }



   /**
    * Adds calculator mode menu item and listener that responds appropriately.
    * @return menuItem 
    */
   private JMenuItem calculatorMode() 
   {

      JMenuItem menuItem = new JMenuItem("Calculator");
   
      class MenuItemListener implements ActionListener
      {
         public void actionPerformed(ActionEvent event)  
         {
        
            defaultOnStartup();
         }
      }

      ActionListener listener = new MenuItemListener(); 
      
      menuItem.addActionListener(listener);

      return menuItem;
   }
   


   /**
    * Adds a file menu. 
    * @return menu
    */
   private JMenu createModeMenu()
   {

      JMenu menu = new JMenu("Mode "); 
      
      menu.add(calculatorMode()); menu.add(dataSetMode()); 
      
      menu.addMouseMotionListener(new HandlerClass("mouse")); 

      return menu;
   }



   /**
    * Adds a display menu. 
    * @return menu
    */
   private JMenu createDisplayMenu()
   {

      JMenu menu = new JMenu("Display "); 
      
      menu.add(dataPrint()); menu.add(minimumMaximum()); 
      
      menu.add(varianceDeviation()); menu.add(meanSquares()); 
      
      menu.add(sumSquares()); menu.add(medianMode()); menu.add(countRange());  
      
      menu.addMouseMotionListener(new HandlerClass("mouse")); 

      return menu;
   }



   /**
    * Adds a sequence menu. 
    * @return menu
    */
   private JMenu createSequenceMenu()
   {

      JMenu menu = new JMenu("Sequence "); 
      
      menu.add(fibonacci()); menu.add(random()); 
      
      menu.addMouseMotionListener(new HandlerClass("mouse")); 

      return menu;
   }



   /**
    * Adds a settings menu. 
    * @return menu
    */
   private JMenu createSettingsMenu()
   {

      JMenu menu = new JMenu("Settings "); menu.add(decimalPlaces()); 
      
      menu.addMouseMotionListener(new HandlerClass("mouse")); 

      return menu;
   }
   
   
   
   /**
    * Displays the integer exception text in the display.
    */
   private void enterException()
   {
      pad.display.setText(" Invalid entry ");
   }
   
   
   
   /**
    * Window resize event.
    */
   private void includeResizeEvent()
   {
      this.addComponentListener 
      (
         new ComponentAdapter() 
         {
            public void componentResized(ComponentEvent e) 
            {
               appletDisplayHandler();
            }
          
         }
      ); 
   }
   
   
   
   /**
    * Controls the JApplet component visibility. 
    * ESCA-JAVA0266:
    */
   private void appletDisplayHandler()
   {
      final String ZOOM_WARNING = 
   
      "It appears that web pages in your browser are zoomed out. \n\n" +
      "In order to display the applet, your browser needs to be set \n" +
      "at its default zoom level of 100% or greater. \n\n" +
      "Sorry about that.";
   
   
      if ((getWidth() < FRAME_SIZE_X) || (getHeight() < FRAME_SIZE_Y))
      {
         contentPane.setVisible(false); menuBar.setVisible(false);
      
         
         if (!zoomWarningShown) 
         {
            Message.showMessage(ZOOM_WARNING, "Browser zoom setting", "warning");
            
            zoomWarningShown = true;
         } 
      }
       
      else 
      {
         contentPane.setVisible(true); menuBar.setVisible(true);
      } 
   }


   //***************************************** END PRIVATE METHODS *****************************************//
   
   
   //********************************************** START MAIN *********************************************//
   
   
   /**
    * Main
    * @param args
    */
   public static void main(String[] args)
   {
      isApplication = true;
      
      isVisible = true;
     
      new ScientificCalculatorGui(); 

   }
   
   
   //*********************************************** END MAIN **********************************************//
   
    
   private KeyPad pad;
   
   /**
    * ESCA-JAVA0007:
    */
   public JFrame frame;
   
   private boolean working;
   private JTextField input; 
   private Validation valid;
   private JMenuBar menuBar; 
   private JTextArea display;
   private ButtonGroup group;
   private JCheckBox workingBox;
   private Container contentPane;
   private double[] dataSetArray;
   private JScrollPane scrollPane;
   private boolean zoomWarningShown;
   private String runType, dataStep;
   private ScientificCalculator calc;
   private int number, minimum, maximum;
   
   private JRadioButton degrees, radians;
   
   private GridBagConstraints constraints;
   private int computationCounter, places, index;
   
   private final String[] enterButtonText = {"ENTER", "COPY", "="};
   
   private final JMenuItem[] item = new JMenuItem[MENU_ARRAY_SIZE];
   
   private final JButton[] enterButton = new JButton[ENTER_ARRAY_SIZE];
   private final JButton[] operatorButton = new JButton[OPERATOR_ARRAY_SIZE];
   
   private JPanel settingsPanel, enterPanel, operatorPanel, containerPanel, topPanel;

   private final String[] operatorButtonText =
   
   {"Log(n,b)","Mod(n,d)", "Per(n,r)", "Com(n,r)", "Sin(n)", "Cos(n)","Tan(n)",
    "Fac(n)", "Inv(n)", "Abs(n)", "x10^", ",","x","/","+","-","^","v","(",")","n","PI","e","p"};

   
   //********************************************** END CLASS **********************************************//

}


/*
   COPYRIGHT (C) 2010 - 2013 by Alexander Wait. All Rights Reserved.

   This class simplifies and computes equations.

   @site http://www.javaika.com
   @author Alexander Wait
   @version 2012-07-01
*/



import java.text.*;
import java.util.ArrayList;



public class ScientificCalculator 
{

   private enum Bracket {OPEN, CLOSE};
   
   private static final int LOOP_TIMEOUT = 3000;

   private static final int COMPLEX_OPERATOR_LENGTH = 3;
   
   private static final int COMMA_ARRAY_SHIFT = 1;
   
   private static final int ADD_SUBTRACT_ARRAY_SHIFT = 2;
   
   private static final int INFINITY_ARRAY_SHIFT = 6;

 
   /**
    * Constructor.
    */
   public ScientificCalculator()
   {
      arith = new Arithmetic();
      
   }

   
   //**************************************** START PUBLIC METHODS *****************************************//
   
   
   /**
    * Rounds a value to a specified number of decimal places. 
    * @param val
    * @param place 
    * @return 
    * @return
    */
   public double decimalRounding(double val, int place) 
   {
        
      String maskBuilder = "#."; 

      for (int i = 0; i < place; i ++)
      {
         maskBuilder += "#";
      }

      DecimalFormat places = new DecimalFormat(maskBuilder);

      if (DataFunctions.areDoublesEqual(val, Double.POSITIVE_INFINITY) 
      || DataFunctions.areDoublesEqual(val, Double.NEGATIVE_INFINITY))
      {
         return val;
      }

      else
      {
         return Double.valueOf(places.format(val));
      }
   }
   
  
   
   /**
    * Runs the calculation.
    * ESCA-JAVA0266
    * ESCA-JAVA0166
    * ESCA-JAVA0285:
    */
   public void run()
   {
      try
      {
         simplificationList.add(getOuterFormula()); setDone(false); 
         
         String formula = null; String answer = null; int cycles = 0;
    
   
         while (!getDone())
         {
            simplifySimpleOperators(); simplifySingleOperators(); simplifyDoubleOperators();
            
            formula = simplificationList.get(simplificationList.size() -1); cycles ++;
            
            if (isNumeric(formula) || (cycles > LOOP_TIMEOUT)) {setDone(true);}
         }
       
         
         if ((!formula.equals("Infinity")) && (!formula.equals("-Infinity")))
         {
            answer = Double.toString(decimalRounding(Double.parseDouble(formula), getDecimalPlaces()));     
         
            simplificationList.set(simplificationList.size() -1, answer + " [" + getDecimalPlaces() + "dp]");
         }
      }
      
      catch (Exception e)  
      {   
         populateSimplificationList("Underfined");
      }
      
   }
   
   
   
   /**
    * Adds spaces around addition and subtraction 
    * operators if no space exists.
    * @param formula
    * @return
    */
   public String formatFormula(String formula)
   {
      String formatted = "";
   
      
      for (int i = 0; i < formula.length(); i ++)
      {
         if ((i > 0) && isSimpleOperator(formula, i))     
         {
            if (!isNumberAdjacentRight(formula, i) 
            || isNumberAdjacentLeft(formula, i) || formula.charAt(i-1) == ')')
            {
               if ((i < (formula.length() -1)) && (formula.charAt(i -1) != 'E'))
               {
                  if (formula.charAt(i -1) != ' ') {formatted += " ";}
            
                  formatted += formula.charAt(i);
               
                  if (formula.charAt(i +1) != ' ') {formatted += " ";}
               
                  continue;
               }
            }
         }
         
         formatted += formula.charAt(i);
      }
      
     
      return formatted;
   
   }
   
   
   
   /**
    * Matches a number with optional '-' and decimal.
    * @param str
    * @return
    */
   public static boolean isNumeric(String str) 
   {
      if (str.matches("-?\\d+(\\.\\d+)?"))
      {  
         return true;
      }
      
      else if (str.equals("Infinity"))
      {
         return true;
      }
      
      else if (str.equals("-Infinity"))
      {
         return true;
      }

      else {return false;}
   }
   
   
   /**
    * Sets the mode switch.
    * @param set
    */
   public void setMode(boolean set) {mode = set;}
   
   
   /**
    * Sets the mode switch.
    * @param places
    */
   public void setDecimalPlaces(int places) {decimalPlaces = places;}
   
   
   /**
    * Sets the done switch.
    * @param set
    */
   public void setDone(boolean set) {done = set;}
   
   
   /**
    * Sets the external formula.
    * @param set
    */
   public void setOuterFormula(String set) {expression = set;}
   
   
   /**
    * Return the mode switch.
    * @return
    */
   public boolean getMode() {return mode;}
   
   
   /**
    * Return the done switch.
    * @return
    */
   public boolean getDone() {return done;}
   
    
   //***************************************** END PUBLIC METHODS ******************************************//
   
   
   //**************************************** START PRIVATE METHODS ****************************************//
   
   
   /**
    * Simplifies double operators (Log, Per, etc)
    */
   private void simplifyDoubleOperators()
   {
      String doubleOperator = ""; setSingleExecutedState(false); 

      setOpenBracketIndex(getIndexMostNestedBracket(getOuterFormula(), Bracket.OPEN));   
      setCloseBracketIndex(getIndexMostNestedBracket(getOuterFormula(), Bracket.CLOSE));
     
      if (isDoubleOpenOperatorBracket(getOuterFormula(), getOpenBracketIndex()) 
      && !containsPriorityOperators(getElement(getOuterFormula(), 
      getOpenBracketIndex() +1, getCloseBracketIndex() -1))) 
      {
         doubleOperator = getBracketOperator
         (getOuterFormula(), getOpenBracketIndex() -1, COMPLEX_OPERATOR_LENGTH);
          
         double valueBefore = Double.parseDouble 
         (getNumberBeforeOperator(getOuterFormula(), getCommaIndex(getOuterFormula())));
         
         double valueAfter = Double.parseDouble 
         (getNumberAfterOperator(getOuterFormula(), getCommaIndex(getOuterFormula())));
          
       
         if (doubleOperator.equals("Log") || doubleOperator.equals("log")) 
         {doubleResult = arith.logarithm(valueBefore, valueAfter); setDoubleExecutedState(true);}
            
         if (doubleOperator.equals("Mod") || doubleOperator.equals("mod")) 
         {doubleResult = arith.modulus(valueBefore, valueAfter); setDoubleExecutedState(true);}
            
         if (doubleOperator.equals("Pwr") || doubleOperator.equals("pwr"))      
         {doubleResult = arith.pWithRep((long)valueBefore, (long)valueAfter); setDoubleExecutedState(true);}
         
         if (doubleOperator.equals("Pnr") || doubleOperator.equals("pnr"))          
         {doubleResult = arith.pWithoutRep((long)valueBefore, (long)valueAfter); setDoubleExecutedState(true);}
         
         if (doubleOperator.equals("Cwr") || doubleOperator.equals("cwr"))          
         {doubleResult = arith.cWithRep((long)valueBefore, (long)valueAfter); setDoubleExecutedState(true);}
            
         if (doubleOperator.equals("Cnr") || doubleOperator.equals("cnr"))        
         {doubleResult = arith.cWithoutRep((long)valueBefore, (long)valueAfter); setDoubleExecutedState(true);}
            
         if (Double.toString(doubleResult).equals("NaN"))
         {throw new NumberFormatException();}
         
         if (getDoubleExecutedState()) 
         {
            setOuterFormula(getInserted(getOuterFormula(), Double.toString(doubleResult), 
            getOpenBracketIndex() - COMPLEX_OPERATOR_LENGTH, getCloseBracketIndex()));
         
            populateSimplificationList(getOuterFormula()); 
         
            simplifySimpleOperators();
         }         
          
      }
      
   }
 
   
   
   /**
    * Simplifies single operators (Sin , Cosine , Tan , etc)
    * ESCA-JAVA0266
    * ESCA-JAVA0029:
    * ESCA-JAVA0171:
    */
   private void simplifySingleOperators()
   {
      String singleOperator = "";
      
      double value = 0; setSingleExecutedState(false); 

      setOpenBracketIndex(getIndexMostNestedBracket(getOuterFormula(), Bracket.OPEN));   
      setCloseBracketIndex(getIndexMostNestedBracket(getOuterFormula(), Bracket.CLOSE));
     
      if (isSingleOpenOperatorBracket(getOuterFormula(), getOpenBracketIndex()) 
      && !containsPriorityOperators(getElement(getOuterFormula(), 
      getOpenBracketIndex() +1, getCloseBracketIndex() -1))) 
      {
         singleOperator = getBracketOperator(getOuterFormula(), 
         getOpenBracketIndex() -1, COMPLEX_OPERATOR_LENGTH);
          
         value = Double.parseDouble(getElement(getOuterFormula(), 
         getOpenBracketIndex() +1, getCloseBracketIndex() -1));
          
         
         if (singleOperator.equals("Fac") || singleOperator.equals("fac")) 
         {doubleResult = arith.factorial((long)value, (long)0); setSingleExecutedState(true);}
            
         if (singleOperator.equals("Sin") || singleOperator.equals("sin")) 
         {doubleResult = arith.sin(value, getMode()); setSingleExecutedState(true);}
            
         if (singleOperator.equals("Cos") || singleOperator.equals("cos")) 
         {doubleResult = arith.cos(value, getMode()); setSingleExecutedState(true);}
            
         if (singleOperator.equals("Tan") || singleOperator.equals("tan")) 
         {doubleResult = arith.tan(value, getMode()); setSingleExecutedState(true);} 
            
         if (singleOperator.equals("Abs") || singleOperator.equals("abs")) 
         {doubleResult = arith.absolute(value); setSingleExecutedState(true);}
            
         if (singleOperator.equals("Inv") || singleOperator.equals("inv")) 
         {doubleResult = arith.invert(value); setSingleExecutedState(true);}
            
         if (Double.toString(doubleResult).equals("NaN")) 
         {throw new NumberFormatException();}
         
         
         if (getSingleExecutedState()) 
         {
            setOuterFormula(getInserted(getOuterFormula(), Double.toString(doubleResult), 
            getOpenBracketIndex() - COMPLEX_OPERATOR_LENGTH, getCloseBracketIndex()));
         
            populateSimplificationList(getOuterFormula()); 
         
            simplifySimpleOperators();
         }         
      }
     
   }
   
   
   
   /**
    * Simplifies simple operators (^ , V , x , / , etc)
    * ESCA-JAVA0119
    */
   private void simplifySimpleOperators()
   {
      bracketInitialiser();
      
      for (int i = getIndexStartPosition(); i < getIndexEndPosition(); i ++)
      {
         for (int j = getOpenBracketIndex() +1; j < getCloseBracketIndex(); j ++)
         {
            if (getOuterFormula().charAt(j) == Validation.simpleOperator[i] 
            && (!isNumberAdjacentRight(getOuterFormula(), j)))
            {
               double valueBefore = Double.parseDouble(getNumberBeforeOperator(getOuterFormula(), j));
  
               double valueAfter = Double.parseDouble(getNumberAfterOperator(getOuterFormula(), j));
               
               
               if ((getOuterFormula().charAt(j) == 'x') || (getOuterFormula().charAt(j) == '*'))  
               {doubleResult = arith.multiplication(valueBefore, valueAfter);}
               
               if ((getOuterFormula().charAt(j) == '/')) 
               {doubleResult = arith.division(valueBefore, valueAfter);}
               
               if ((getOuterFormula().charAt(j) == '^')) 
               {doubleResult = arith.square(valueBefore, valueAfter);}
         
               if ((getOuterFormula().charAt(j) == 'v')) 
               {doubleResult = arith.root(valueBefore, valueAfter);}
               
               if ((getOuterFormula().charAt(j) == '+')) 
               {doubleResult = arith.addition(valueBefore, valueAfter);}
                       
               if ((getOuterFormula().charAt(j) == '-')) 
               {doubleResult = arith.subtraction(valueBefore, valueAfter);}
                         
               
               if (Double.toString(doubleResult).equals("NaN")) 
               {throw new NumberFormatException();}
               
               
               if (openBracketFound && closeBracketFound)
               { 
                  setOuterFormula(getInserted
                  (
                     getOuterFormula(), Double.toString(doubleResult), 
                        
                     getInsertStartIndex(), getInsertEndIndex())
                  );
                  
                  simplificationList.add(getOuterFormula());   
               }
          
               i = Validation.simpleOperator.length -1; 
               j = getCloseBracketIndex(); 
               
               simpleOperatorFound = true;               
            }           
         }         
      }

      bracketControl();
   
   }
   
   
   
   /**
    * Bracket initializer.
    */
   private void bracketInitialiser()
   {
      openBracketFound = false; closeBracketFound = false; simpleOperatorFound = false; 
      
      substituteNumbers(getOuterFormula()); 
      
      if (numberSubFound) {simplificationList.add(getOuterFormula());} indexInitialiser();

      
      if(!containsPriorityOperators(getElement(getOuterFormula(), 
      getOpenBracketIndex() +1, getCloseBracketIndex() -1))) 
      {
         uniteSignOperators(getElement(getOuterFormula(), 
         getOpenBracketIndex() +1, getCloseBracketIndex() -1));    
         
         setOuterFormula(getInserted(getOuterFormula(), getUnitedFormula(), 
         getOpenBracketIndex() +1, getCloseBracketIndex() -1)); indexInitialiser();

         setIndexStartPosition(0); setIndexEndPosition(ADD_SUBTRACT_ARRAY_SHIFT);
      }
      
      else
      { 
         setIndexStartPosition(ADD_SUBTRACT_ARRAY_SHIFT); 
         
         setIndexEndPosition(Validation.simpleOperator.length);
      }

   }
   
   
   
   /**
    * Bracket controller.
    */
   private void bracketControl()
   {
      if (simpleOperatorFound && !openBracketFound && !closeBracketFound)
      {
         setOuterFormula(getInserted(getOuterFormula(), Double.toString(doubleResult),
         getInsertStartIndex(), getInsertEndIndex()));
         
         simplificationList.add(getOuterFormula());
         
         simplifySimpleOperators();
      }
   
      if (!simpleOperatorFound && openBracketFound && closeBracketFound
      && !isSingleOpenOperatorBracket(getOuterFormula(), getOpenBracketIndex())
      && !isDoubleOpenOperatorBracket(getOuterFormula(), getOpenBracketIndex()))
      {
         doubleResult = Double.parseDouble(getElement(getOuterFormula(), 
         getOpenBracketIndex() +1, getCloseBracketIndex() -1));
      
         setOuterFormula(getInserted(getOuterFormula(), Double.toString(doubleResult),
         getOpenBracketIndex(), getCloseBracketIndex()));
         
         simplificationList.add(getOuterFormula());
         
        
         simplifySimpleOperators();
      }
      
      if (simpleOperatorFound && openBracketFound && closeBracketFound) 
      {simplifySimpleOperators();} 
      
   }
   
   
   
   /**
    * Index initializer.
    */
   private void indexInitialiser()
   {
      setOpenBracketIndex(getIndexMostNestedBracket(getOuterFormula(), Bracket.OPEN));   
      setCloseBracketIndex(getIndexMostNestedBracket(getOuterFormula(), Bracket.CLOSE));
     
      if (!openBracketFound && !closeBracketFound) 
      
      {setOpenBracketIndex(-1); setCloseBracketIndex(getOuterFormula().length());}
      
   }
   
   
   
   /**
    * Inserts numbers for special characters into the expression.
    * @param formula
    */
   private void substituteNumbers(String formula)
   {
      numberSubFound = false; 
   
      for (int i = 0; i < formula.length(); i ++)
      {
         if ((i < formula.length() -1) && (formula.charAt(i) == 'P') && (formula.charAt(i +1) == 'I'))
         {
            setOuterFormula(getInserted(formula, Double.toString(arith.piValueReturn()), i, i +1)); 
            
            substituteNumbers(getOuterFormula()); numberSubFound = true;
    
         }
         
         if (formula.charAt(i) == 'e')
         {
            setOuterFormula(getInserted(formula, Double.toString(arith.eValueReturn()), i, i)); 
            
            substituteNumbers(getOuterFormula()); numberSubFound = true;
    
         }
      
      }
  
   }
   
   
   
   /**
    * Returns true if formula contains operators with 
    * the exception of sign operators (+, -)
    * ESCA-JAVA0175
    * @param formula
    * @return
    */
   private static boolean containsPriorityOperators(String formula)
   {
      boolean priorityOperators = false;
      
      for (int i = 0; i < formula.length(); i ++)
      {
         for (int j = ADD_SUBTRACT_ARRAY_SHIFT; 
         j < (Validation.simpleOperator.length - COMMA_ARRAY_SHIFT); j ++)
         {
            if ((formula.charAt(i) == Validation.simpleOperator[j]))
            {
               if ((formula.charAt(i)) == '+' || (formula.charAt(i) == '-'))
               {        
                  if (!isNumberAdjacentRight(formula, i))
                  {

                     priorityOperators = true;
                  }

               }
           
               priorityOperators = true;
            }
         } 
      }
  
      return priorityOperators;
   
   }
   
   
   
   /**
    * Tests if an index of a string is adjacent to a number on the right.
    * @param formula
    * @param index
    * @return
    */
   private static boolean isNumberAdjacentRight(String formula, int index)
   {
      boolean numberSign = false;
      
      if ((index < formula.length() -1) && ((formula.charAt(index) == '+') || (formula.charAt(index) == '-')))
      {
         for (int i = ADD_SUBTRACT_ARRAY_SHIFT; i < (Validation.number.length - INFINITY_ARRAY_SHIFT); i ++) 
         {
            if (formula.charAt(index +1) == Validation.number[i] || formula.charAt(index +1) == 'I')
            {
               numberSign = true;
            }
         }
      }
        
      return numberSign;
   }
   
   
   
   /**
    * Tests if an index of a string is adjacent to a number on the left.
    * @param formula
    * @param index
    * @return
    */
   private static boolean isNumberAdjacentLeft(String formula, int index)
   {
      boolean numberSign = false;
      
      if ((index > 0) && ((formula.charAt(index) == '+') || (formula.charAt(index) == '-')))
      {
         for (int i = ADD_SUBTRACT_ARRAY_SHIFT; i < Validation.number.length; i ++) 
         {
            if (formula.charAt(index -1) == Validation.number[i])
            {
               numberSign = true; 

            }
  
         }
      }
        
      return numberSign;
   }
   
   
   
   /**
    * Converts a row of +, - operators into one type.
    * ESCA-JAVA0119
    * @param formula
    */
   private void uniteSignOperators(String formula)
   {
      int combinedCount = 0; int minusCount = 0; String sign = "";
      
      unitedFormula = formula; boolean held = false;
  
 
      for (int i = 0; i < (formula.length()); i ++)
      {
         if (!isNumberAdjacentRight(formula, i) 
         && ((formula.charAt(i) == '+') || (formula.charAt(i) == '-')))
         {
            if (formula.charAt(i) == '-') {minusCount ++;}

            if (!held) {setInsertStartIndex(i);}
        
            setInsertEndIndex(i); combinedCount ++;
            
            held = true; continue;  
         } 
     
         for (int j = ADD_SUBTRACT_ARRAY_SHIFT; j < Validation.number.length; j ++)
         {
            if (formula.charAt(i) == Validation.number[j])
            {
               if (combinedCount > 1)
               {
                  if (returnNegative(minusCount)) {sign = "-";}
       
                  if (!returnNegative(minusCount)) {sign = "+";}
        
                  setUnitedFormula(getInserted(formula, sign, 
                  getInsertStartIndex(), getInsertEndIndex()));
                 
                  uniteSignOperators(getUnitedFormula()); 
                  
                  i = formula.length();
               }
       
               else {minusCount = 0; combinedCount = 0; held = false;} break;
            } 
         }
      }
   
   }
   
  
   
   /**
    * Returns the formula after calculation has been inserted.
    * @param formula
    * @param insert
    * @param indexStart
    * @param indexEnd
    * @return
    */
   private static String getInserted(String formula, String insert, int indexStart, int indexEnd)
   {
      String result = "";
      
      for (int i = 0; i < indexStart; i ++)
      {
         result += formula.charAt(i);
   
      }
    
      for (int i = 0; i < insert.length(); i ++)
      {
         result += insert.charAt(i);
         
      }
      
      for (int i = (indexEnd+1); i < formula.length(); i ++)
      {
         result += formula.charAt(i);
     
      }
         
      return result;
   }
   
   

   /**
    * Tests if the character at a specific index of a supplied
    * formula is a valid simple operator.
    * @param formula
    * @param index
    * @return
    */
   private static boolean isSimpleOperator(String formula, int index)
   {
      boolean simpleOperator = false;

      
      for (int i = 0; i < Validation.simpleOperator.length; i++)
      {
         if (Validation.simpleOperator[i] == formula.charAt(index))
         {
            simpleOperator = true;
         }
      }
      
      if ((index > 0) && (index < (formula.length() -1))
      && (formula.charAt(index -1) == '(') && (formula.charAt(index +1) == 'I'))
      {
         simpleOperator = false;
      }
      
      if ((index > 0) && (formula.charAt(index -1) == 'n'))
      {
         simpleOperator = false;
      }


      return simpleOperator;
      
   }
   
   
   
   /**
    * Returns the number forming part of a single operation (Sin , Cosine , Tan , etc).
    * ESCA-JAVA0130
    * @param formula
    * @param indexStart
    * @param indexEnd
    * @return
    */
   private String getElement(String formula, int indexStart, int indexEnd)
   { 

      if (formula == null) {return null;}  
      
      else if ((indexStart <= indexEnd) && (indexStart >= 0) 
      && (indexEnd < formula.length()))
      {
         String element = ""; 
     
         for (int i = indexStart; i <= indexEnd; i ++)
         {
            element += formula.charAt(i);
         }
     
         return element;  
      }
      
      else {return null;}

   }
   
   
   
   /**
    * Returns the number forming part of a simple operation (+ , - , x , / , etc).
    * @param formula
    * @param operatorIndex
    * @return
    */
   private String getNumberBeforeOperator(String formula, int operatorIndex)
   {  
      String number = "";  boolean found = false; boolean started = false;
 
      if (formula == null) {return null;}
      
      else if ((operatorIndex > 0) && (operatorIndex < (formula.length() -1)))
      {
         for (int i = (operatorIndex -1); i >= 0; i --)
         {
            for (int j = 0; j < Validation.number.length; j ++)
            {
               found = false;
                
               if (formula.charAt(i) == Validation.number[j])
               {
                  number = formula.charAt(i) + number; 
                      
                  found = true; started = true; break;
               }    
            }
                
            if (started)
            {
               setInsertStartIndex(i); 
                
               if ((formula.charAt(i) == '+') || (formula.charAt(i) == '-'))
               {
                  if ((i > 0) && (formula.charAt(i -1) == 'E')) {continue;}
               
                  else {setInsertStartIndex(i); break;}
               }
                
               if ((formula.charAt(i) == ' ')) {setInsertStartIndex(i +1); break;}
                   
               if (started && !found) {setInsertStartIndex(i +1); break;}        
            }
                
            else {continue;}
         }
         
         return number;
      }
      
      else {return null;}
      
   }
   
   
   
   /**
    * Returns the number forming part of a simple operation (+ , - , x , / , etc).
    * @param formula
    * @param operatorIndex
    * @return
    */
   private String getNumberAfterOperator(String formula, int operatorIndex)
   {
      String number = "";  boolean found = false; boolean started = false;
     
      if (formula == null) {return null;}
      
      else if ((operatorIndex > 0) && (operatorIndex < (formula.length() -1)))
      {
         for (int i = (operatorIndex +1); i < formula.length(); i ++)
         {
            for (int j = 0; j < Validation.number.length; j ++)
            {
               found = false;
                 
               if (formula.charAt(i) == Validation.number[j])
               {
                  number += formula.charAt(i); 
                       
                  found = true; started = true; break;
               }    
            }
                 
            if (started)
            {         
               setInsertEndIndex(i); 
                
               if ((i < formula.length() - 1) 
               && ((formula.charAt(i +1) == '+') || (formula.charAt(i +1) == '-')))
               {
                  setInsertEndIndex(i -1);  
               
                  if ((formula.charAt(i) == 'E')) {continue;}
            
                  else {break;}
               }

               if ((formula.charAt(i) == ' ')) {setInsertEndIndex(i -1); break;}
                    
               if (started && !found) {setInsertEndIndex(i -1); break;}
            }
                 
            else {continue;}
         }

         return number;
      }
      
      else {return null;}
      
   }
   
   
   
   /**
    * Returns the comma index of a double operator.
    * @param formula
    * @return
    */
   private int getCommaIndex(String formula)
   { 
      int commaIndex = 0;
   
      for (int i = getOpenBracketIndex() +1; i < getCloseBracketIndex(); i ++)
      {
         if (formula.charAt(i) == ',')
         {
            commaIndex = i; break;
         }
      
      }
      
      return commaIndex;  
   } 
   
   
   
   /**
    * Returns true if an opening bracket forms 
    * part of a double operator expression.
    * @param formula
    * @param bracketIndex
    * @return
    */
   private static boolean isDoubleOpenOperatorBracket(String formula, int bracketIndex)
   {
                                
      if (formula == null) {return false;}    
      
      boolean singleOpenOperatorBracket = false; 
      
      if ((bracketIndex >= COMPLEX_OPERATOR_LENGTH) && (bracketIndex < formula.length()))
      {
         for (int i = 0; i < Validation.doubleOperator.length; i ++)
         {
            if 
            (
               getBracketOperator(formula, bracketIndex -1, 
               COMPLEX_OPERATOR_LENGTH).equals(Validation.doubleOperator[i]) 
            
               ||
            
               getBracketOperator(formula, bracketIndex -1, 
               COMPLEX_OPERATOR_LENGTH).equals(Validation.doubleOperator[i].toLowerCase())
            )
         
            {
               singleOpenOperatorBracket = true; 

               break;
            }      
         }
      }
     
      return singleOpenOperatorBracket;   
     
   }
   
   
   
   /**
    * Returns true if an opening bracket forms 
    * part of a single operator expression.
    * @param formula
    * @param bracketIndex
    * @return
    */
   private static boolean isSingleOpenOperatorBracket(String formula, int bracketIndex)
   {

      if (formula == null) {return false;}    
      
      boolean singleOpenOperatorBracket = false; 
      
      if ((bracketIndex >= COMPLEX_OPERATOR_LENGTH) && (bracketIndex < formula.length()))
      {
         for (int i = 0; i < Validation.singleOperator.length; i ++)
         {
            if 
            (
               getBracketOperator(formula, bracketIndex -1, 
               COMPLEX_OPERATOR_LENGTH).equals(Validation.singleOperator[i])
           
               ||
            
               getBracketOperator(formula, bracketIndex -1, 
               COMPLEX_OPERATOR_LENGTH).equals(Validation.singleOperator[i].toLowerCase())
            )
           
            {
               singleOpenOperatorBracket = true; 

               break;
            }      
         }
      }
     
      return singleOpenOperatorBracket;
      
   }
   
   
   
   /**
    * Returns the formula index of the most nested bracket.
    * @param formula
    * @param type
    * @return
    */
   private int getIndexMostNestedBracket(String formula, Bracket type)
   {
      int index = 0; int count = 0; int maximumCount = 0;
     
      if (type == Bracket.OPEN)
      {
         for (int i = 0; i < formula.length(); i ++)
         {
            if ((formula.charAt(i) == '(')) {openBracketFound = true; count ++;}
         
            if ((formula.charAt(i) == ')')) {count --;}
         
            if (count > maximumCount) {maximumCount = count; index = i;}
         }
      }

      if (type == Bracket.CLOSE)
      {
         for (int i = (formula.length() -1); i >= 0; i --)
         {
            if ((formula.charAt(i) == ')')) {closeBracketFound = true; count ++;}
            
            if ((formula.charAt(i) == '(')) {count --;}

            if (count > maximumCount) {maximumCount = count;} 
            
            if ((maximumCount == count) && (formula.charAt(i) == ')')) {index = i;}
         }
        
      }
     
      return index;
      
   }
   
   
   
   /**
    * Returns the single operator given the bracket
    * opening index of that operator.
    * @param string
    * @param indexStart
    * @param length
    * @return
    */
   private static String getBracketOperator(String string, int indexStart, int length)
   {
   
      if (string == null) {return null;}
            
      else if ((indexStart < string.length()) 
      && ((indexStart - length +1) >= 0))
      { 
         String result = "";  
     
         for (int i = indexStart; i >= (indexStart - length +1); i --)
         {
            result = string.charAt(i) + result; 
         }
         
         return result;
      }
      
      else {return null;}
     
   }
   
   
   
   /**
    * Returns true if the number of negatives is an odd number.
    * @param negatives
    * @return
    */
   private static boolean returnNegative(int negatives)
   {   
      if ((negatives % 2) != 0)
      {
         return true;
      }
      
      else
      {
         return false;
      }
  
   }
   
   
   
   /**
    * Adds the simplification strings to a collection.
    * @param simplification
    */
   private void populateSimplificationList(String simplification)
   {  
     
   
      simplificationList.add(simplification);
   }
   
   
   
   /**
    * Sets the external formula.
    * @param set
    */
   private void setUnitedFormula(String set) {unitedFormula = set;}
   
   
   /**
    * Sets the open bracket index.
    * @param index
    */
   private void setOpenBracketIndex(int index) {openBracketIndex = index;}
   
   
   /**
    * Sets the close bracket index.
    * @param index
    */
   private void setCloseBracketIndex(int index) {closeBracketIndex = index;}
   
   
   /**
    * Sets the start index.
    * @param index
    */
   private void setInsertStartIndex(int index) {insertStartIndex = index;}
   
   
   /**
    * Sets the end index.
    * @param index
    */
   private void setInsertEndIndex(int index) {insertEndIndex = index;}
   
   
   /**
    * Sets the index start position.
    * @param index
    */
   private void setIndexStartPosition(int index) {indexStartPosition = index;}
   
   
   /**
    * Sets the index end position.
    * @param index
    */
   private void setIndexEndPosition(int index) {indexEndPosition = index;}
   
  
   /**
    * Sets single executed state.
    * @param state
    */
   private void setSingleExecutedState(boolean state) {singleExecuted = state;}
   
   
   /**
    * Sets double executed state.
    * @param state
    */
   private void setDoubleExecutedState(boolean state) {doubleExecuted = state;}
   
  
   /**
    * Returns the open bracket index.
    * @return
    */
   private int getOpenBracketIndex() {return openBracketIndex;}
   
   
   /**
    * Returns the close bracket index.
    * @return
    */
   private int getCloseBracketIndex() {return closeBracketIndex;}
   
   
   /**
    * Returns the close bracket index.
    * @return
    */
   private int getDecimalPlaces() {return decimalPlaces;}
   
   /**
    * Returns the start index.
    * @return
    */
   private int getInsertStartIndex() {return insertStartIndex;}
   
   
   /**
    * Returns the end index.
    * @return
    */
   private int getInsertEndIndex() {return insertEndIndex;}
   
   
   /**
    * Returns the end index.
    * @return
    */
   private int getIndexStartPosition() {return indexStartPosition;}
   
   
   /**
    * Returns the end index.
    * @return
    */
   private int getIndexEndPosition() {return indexEndPosition;}
  
   
   /**
    * Returns the external formula.
    * @return
    */
   private String getOuterFormula() {return expression;}  
   
   
   /**
    * Returns the external formula.
    * @return
    */
   private String getUnitedFormula() {return unitedFormula;}  
  
   
   /**
    * Return single executed state.
    * @return
    */
   private boolean getSingleExecutedState() {return singleExecuted;}
   
   
   /**
    * Return double executed state.
    * @return
    */
   private boolean getDoubleExecutedState() {return doubleExecuted;} 
   
   
   //***************************************** END PRIVATE METHODS *****************************************//
   
   
   private int decimalPlaces;
   private double doubleResult;
   private final Arithmetic arith;
   private String expression, unitedFormula;
   private int insertStartIndex, insertEndIndex;
   private int openBracketIndex, closeBracketIndex; 
   private int indexStartPosition, indexEndPosition; 
   private boolean mode, singleExecuted, doubleExecuted, done;
   ArrayList <String> simplificationList = new ArrayList <String>();  
   private boolean openBracketFound, closeBracketFound, simpleOperatorFound, numberSubFound;
   
   
   //********************************************** END CLASS **********************************************//
  
}


/*
   COPYRIGHT (C) 2010 - 2013 by Alexander Wait. All Rights Reserved.

   This class performs basic arithmetic.

   @site http://www.javaika.com
   @author Alexander Wait
   @version 2010-07-18
*/



public class Arithmetic
{

   
   /**
    * 
    */
   public static final int MAX_DEGREES_OBTUSE = 180; 


   /**
    * 
    */
   public static final int MAX_DEGREES_ACUTE = 90; 
   

   //**************************************** START PUBLIC METHODS *****************************************//
   
   
   /**
    * Finds the addition of two values. 
    * @param valueOne 
    * @param valueTwo 
    * @return
    */
   public double addition(double valueOne, double valueTwo)
   {
      
      return (valueOne + valueTwo);
   }



   /**
    * Finds the subtraction of two values. 
    * @param valueOne
    * @param valueTwo 
    * @return 
    */
   public double subtraction(double valueOne, double valueTwo)
   {

      return (valueOne - valueTwo);
   }




   /**
    * Finds the multiplication of two values. 
    * @param valueOne
    * @param valueTwo
    * @return
    */
   public double multiplication(double valueOne, double valueTwo)
   {

      return (valueOne * valueTwo);
   }



   /**
    * Finds the division of two values. 
    * @param valueOne 
    * @param valueTwo  
    * @return 
    */
   public double division(double valueOne, double valueTwo)
   {

      return (valueOne / valueTwo);
   }

   

   /**
    * Finds the absolute value of a number.
    * @param value  
    * @return 
    */
   public double absolute(double value)
   {

      return (Math.abs(value));
   }



   /**
    * Finds the remainder of two values. 
    * @param value
    * @param divisor
    * @return
    */
   public double modulus(double value, double divisor)
   {

      return (value % divisor);
   }



   /**
    * Finds the inversion of a number.
    * @param value 
    * @return 
    */
   public double invert(double value)
   {

      return (1 / value);
   }



   /** 
    * Finds the power of a number.
    * @param value
    * @param raise 
    * @return 
    */
   public double square(double value, double raise)
   { 

      return (Math.pow(value,raise));
   }



   /**
    * Finds the root of a number. 
    * @param degree
    * @param value 
    * @return 
    */
   public double root(double degree, double value)
   {

      return (Math.pow(value, 1 / degree));
   }



   /**
    * Finds the factorial of a number.
    * ESCA-JAVA0078:
    * @param value
    * @param stop
    * @return answer
    */
   public double factorial(long value, long stop)
   {
      double answer = value;  
      
      if (DataFunctions.areDoublesEqual(value, Double.POSITIVE_INFINITY))
      {answer = Double.POSITIVE_INFINITY;}
      
      else if ((value < 0) || (stop < 0)) {answer = Double.NaN;}
      
      else if (value == 0) {answer = 1;}
      
      else
      {
         for (long i = value -1; i > stop; i --)
         {
            answer *= (i); if (answer == Double.POSITIVE_INFINITY) {break;}
         }
      }

      return answer;
   }



   /**
    * Finds the log to a specified base. 
    * @param value 
    * @param base 
    * @return 
    */
   public double logarithm(double value, double base)
   {

      return (Math.log(value) / Math.log(base));
   }



   /**
    * Finds the sin of a number.
    * @param val 
    * @param degrees
    * @return answer
    */
   public double sin(double val, boolean degrees)
   {

      double answer = 0;

      if (degrees)
      {
         if (DataFunctions.areDoublesEqual(val % MAX_DEGREES_OBTUSE, 0) 
         && (val >= MAX_DEGREES_OBTUSE || val <= - MAX_DEGREES_OBTUSE))
         {
            answer = 0;
         }

         else
         {
            answer = Math.sin(Math.toRadians(val));
         }
      }

      else
      {
         if (DataFunctions.areDoublesEqual(val % Math.PI, 0) 
         && (val >= Math.PI || val <= - Math.PI))
         {
            answer = 0;
         }

         else
         {
            answer = Math.sin(val);
         }
      }

      return answer;
   }



   /**
    * Finds the cosine of a number.
    * @param val 
    * @param degrees  
    * @return answer
    */
   public double cos(double val, boolean degrees)
   {
      double answer = 0;

      if (degrees)
      {
         if (DataFunctions.areDoublesEqual
         ((val + MAX_DEGREES_ACUTE) % MAX_DEGREES_OBTUSE, 0) 
         && (val >= MAX_DEGREES_ACUTE || val <= - MAX_DEGREES_ACUTE))
         {
            answer = 0;
         }

         else
         {
            answer = Math.cos(Math.toRadians(val));
         }
      }

      else
      {
         if (DataFunctions.areDoublesEqual((val+Math.PI / 2) % Math.PI, 0) 
         && (val >= Math.PI / 2 || val <= - Math.PI / 2))
         {
            answer = 0;
         }

         else
         {
            answer = Math.cos(val);
         }
      }

      return answer;
   }



   /**
    * Finds the tan of a number.
    * @param val 
    * @param degrees 
    * @return 
    */
   public double tan(double val, boolean degrees)
   {

      double answer = 0;

      if (degrees)
      {
         if (DataFunctions.areDoublesEqual(val % MAX_DEGREES_OBTUSE, 0) 
         && (val >= MAX_DEGREES_OBTUSE || val <= - MAX_DEGREES_OBTUSE))
         {
            answer = 0;
         }

         else if (DataFunctions.areDoublesEqual
         ((val + MAX_DEGREES_ACUTE) % MAX_DEGREES_OBTUSE, 0))
         {
            answer = Double.POSITIVE_INFINITY;
         }

         else
         {
            answer = Math.tan(Math.toRadians(val));
         }
      }

      else
      {
         if (DataFunctions.areDoublesEqual(val % Math.PI, 0) 
         && (val >= Math.PI || val <= -Math.PI))
         {
            answer = 0;
         }

         else if (DataFunctions.areDoublesEqual((val + Math.PI/2) % Math.PI, 0))
         {
            answer = Double.POSITIVE_INFINITY;
         }

         else
         {
            answer = Math.tan(val);
         }
      }

      return answer;
   }

   
   
   /**
    * Finds the permutations with repetition of n objects by selecting r.
    * ESCA-JAVA0264:
    * @param n
    * @param r
    * @return
    */
   public double pWithRep(long n, long r)
   {
      double answer = square(n, r);   

      return answer;
   }
   
   
   
   /**
    * Finds the permutations without repetition of n objects by selecting r.
    * ESCA-JAVA0264:
    * @param n
    * @param r
    * @return
    */
   public double pWithoutRep(long n, long r)
   { 
      double answer = 0;
      
      if (n < r) {answer = Double.NaN;}
      
      else {answer = factorial(n, n-r);}
      
      return answer;
   }

   
   
   /**
    * Finds the combinations with repetition of n objects by selecting r.
    * ESCA-JAVA0264:
    * @param n
    * @param r
    * @return
    */
   public double cWithRep(long n, long r)
   {     
      double answer = 0; double denominator = 1/factorial(r, 0);
      
      answer = factorial(n+r-1, n-1) * (denominator);

      return answer;
   }
   
   
   
   /**
    * Finds the combinations without repetition of n objects by selecting r.
    * ESCA-JAVA0264:
    * @param n
    * @param r
    * @return
    */
   public double cWithoutRep(long n, long r)
   {     
      double answer = 0; 
      
      if (n < r) {answer = Double.NaN;}
      
      else
      {
         double denominator = 1/factorial(r, 0);
      
         answer = factorial(n, n-r) * (denominator);
      }
   
      return answer;
   }
 
 
   
   /**
    * Returns the value of e.
    * @return
    */
   public double eValueReturn()
   {

      return (Math.E);
   }



   /**
    * Returns the value of PI.
    * @return 
    */
   public double piValueReturn()
   {

      return (Math.PI);
   }
   
   
   //***************************************** END PUBLIC METHODS ******************************************//
   
   
   //********************************************** END CLASS **********************************************//
   
}


/*
   COPYRIGHT (C) 2010 -2013 by Alexander Wait. All Rights Reserved.

   This class defines colors and color methods.

   @site http://www.javaika.com
   @author Alexander Wait
   @version 2012-05-18
*/



public class ColorFunctions
{

   private static final int HEXADECIMAL_BASE = 16;
   
   private static final int COLOR_COMPONENT_RED = 250;
   
   private static final int COLOR_COMPONENT_GREEN = 250;
   
   private static final int COLOR_COMPONENT_BLUE = 250;
   
   
   
   private ColorFunctions() {}
   
   
   //**************************************** START PUBLIC METHODS *****************************************//

   
   /**
    * Returns the color in hexadecimal format.
    * @param sliderValue
    * @return
    */
   public static String returnHexadecimalColor(int sliderValue)
   {
      String compFirst = ""; String compSecond = ""; int counter = -1;
 
      for (int i = 0; i < HEXADECIMAL_BASE; i ++)
      {
         compFirst = returnComponent(i);

          for (int j = 0; j < HEXADECIMAL_BASE; j ++)
          {
             compSecond = returnComponent(j); counter ++; 
  
             if (counter == sliderValue)
             {
                break;
             }
             
          }
  
          if (counter == sliderValue)
          {
             break;
          }
  
       }
   
       return 
       (
          "#" + compFirst + compSecond + compFirst + 
          
          compSecond + compFirst + compSecond
       );
   
   }
   
   
   
   /**
    * Return the set red color component 
    * for setting the programs background color. 
    * @return
    */
   public static int red()
   {
      return COLOR_COMPONENT_RED;
   }
   
   
   
   /**
    * Return the set green color component 
    * for setting the programs background color. 
    * @return
    */
   public static int green()
   {
      return COLOR_COMPONENT_GREEN;
   }
   
   
   
   /**
    * Return the set blue color component 
    * for setting the programs background color. 
    * @return
    */
   public static int blue()
   {
      return COLOR_COMPONENT_BLUE;
   }
   
   
   //***************************************** END PUBLIC METHODS ******************************************//


   //**************************************** START PRIVATE METHODS ****************************************//
   
   
   /**
    * Returns the hexadecimal component.
    * ESCA-JAVA0076:
    * @param index
    * @return
    */
   private static String returnComponent(int index)
   {
      String component = "";
  
      switch (index)
      {
         case 10: component = "A"; break; case 11: component = "B"; break;  
         
         case 12: component = "C"; break; case 13: component = "D"; break; 
         
         case 14: component = "E"; break; case 15: component = "F"; break;
   
         default: component = Integer.toString(index); break;
      }
   
      return component;   
   }
   
 
   //***************************************** END PRIVATE METHODS *****************************************//

   
   //********************************************** END CLASS **********************************************//
   
}


/*
   COPYRIGHT (C) 2010 - 2013 by Alexander Wait. All Rights Reserved.

   This class performs particular functions on a supplied data set.

   @site http://www.javaika.com
   @author Alexander Wait
   @version 2010-07-18
*/



import java.util.*;



public class DataFunctions 
{ 

   private static final double EPSILON = 0;

   
   private DataFunctions() {}
   
   
   //**************************************** START PUBLIC METHODS *****************************************//
   
   
   /**
    * Encodes a text with line breaks using a specified flag
    * character. The same flag character can be used to
    * decode the text back to include line breaks.
    * @param text
    * @param flag
    * @return
    */
   public static String newlineFlagEncoding(String text, String flag)
   {
      if (text != null)
      {
         return text.replaceAll("\n", flag);
      }
      
      else
      {
         return null;
      }
   }
   
   
   
   /**
    * Decodes a text with line break flags to reconstruct the
    * original text with line breaks.
    * @param text
    * @param flag
    * @return
    */
   public static String newlineFlagDecoding(String text, String flag)
   {
      if (text != null)
      {
         return text.replaceAll(flag, "\n");
      }
      
      else
      {
         return null;
      }
   }
   
   
   
   /**
    * Returns a random number in a range. 
    * @param minimum 
    * @param maximum 
    * @return 
    */
   public static int random(int minimum, int maximum)
   {
      Random dice = new Random();

      return (minimum + dice.nextInt(maximum - minimum + 1));
   }



   /**
    * Returns how many values in the data set. 
    * @param array 
    * @return 
    */
   public static int returnCount(double[] array)
   {

      return array.length;
   }



   /**
    * Finds the range. 
    * @param array 
    * @return 
    */
   public static double returnRange(double[] array)
   {

      return (returnMaximum(array) - returnMinimum(array));
   }



   /**
    * Returns the data set.
    * @param array 
    * @return data
    */
   public static String printData(double[] array)
   {
      String data = "{ "; boolean executed = false;

      
      for (double element : array) 
      {
         if (executed) {data += (" , " + element);}

         else {data += element;}
         
         executed = true;
      }

      data += " }";

      return data;
   }



   /**
    * Returns the modes and mode frequency of a data set.
    * @param array  
    *  @return modes
    */
   public static String returnModes(double[] array)
   {
      String modes = "{ "; boolean executed = false; double data = 0;
      
      double[] occurances = new double[array.length]; int count = 0;

      
      for (int i = 0; i < array.length; i ++)
      {
         data = array[i];

         for (int j = i; j < array.length; j ++)
         {
            if (areDoublesEqual(array[j], data)) {count ++;}
         }

         occurances[i] = count; count = 0;
      }

      for (int i = 0; i < occurances.length; i ++)
      {
         if (areDoublesEqual(occurances[i], returnMaximum(occurances)))
         {
            if (executed) {modes += (" , " + array[i]);}
            
            else {modes += array[i];} executed = true;
         }
      }

      modes += (" }" + Tools.returnNewline(2) + "  The mode occurances are: " + 
      
      (int)returnMaximum(occurances));

      return modes;
   }



   /**
    * Finds the sum of all the values within the data set.
    * @param array 
    * @param squares 
    * @return sum
    */
   public static double returnSum(double[] array, boolean squares)
   {

      double sum = 0;

      
      for (double element : array) 
      {
         if (squares)
         {
            sum += Math.pow((element), 2);
         }

         else 
         {
            sum += element;
         }
      }

      return sum;
   }
   


   /**
    * Finds the mean.
    * @param array 
    * @param squares 
    * @return mean
    */
   public static double returnMean(double[] array, boolean squares)
   {
      double mean = 0;

      
      if (squares)
      {
         mean = returnSum(array, true) / array.length;
      }

      else 
      {
         mean = returnSum(array, false) / array.length;
      }

      return mean;
   }



   /**
    * Finds the variance or standard deviation.
    * @param array 
    * @param variance 
    * @return 
    * @return
    */
   public static double returnDeviationVariance(double[] array, boolean variance)
   {
      double deviationCount = 0;

      
      for (double element : array) 
      {
         deviationCount += (Math.pow((element - returnMean(array, false)), 2));
      }

      if (variance) 
      {
         return (deviationCount / array.length);
      }

      else 
      {
         return (Math.sqrt(deviationCount / (array.length - 1)));
      }
   }



   /**
    * Finds the maximum value.
    * @param array
    * @return maximum
    */
   public static double returnMaximum(double[] array)
   {
      double maximum = Double.NEGATIVE_INFINITY; 

      
      for (double element : array) 
      {
         if (element > maximum)
         {
            maximum = element;
         }
      }

      return maximum;
   }



   /**
    * Finds the minimum value.
    * @param array  
    * @return minimum
    */
   public static double returnMinimum(double[] array)
   {
      double minimum = Double.POSITIVE_INFINITY; 

      
      for (double element : array) 
      {
         if (element < minimum)
         {
            minimum = element;
         }
      }

      return minimum;
   }



   /**
    * Finds the median value.
    * @param array 
    * @return median
    */
   public static double returnMedian(double[] array)
   {
      double median = 0; double data = 0; double[] clone = new double[array.length]; 

      
      for (int i = 0; i < array.length; i ++) 
      {clone[i] = array[i];}

      for (int i = 0; i < clone.length; i ++)
      {
         for (int j = i; j < clone.length; j ++)
         {
            data = clone[i];

            if (clone[j] < clone[i])
            {
               clone[i] = clone[j]; 
               clone[j] = data;
            }
         }
      }

      if (clone.length % 2 == 0) 
      {median = (clone[(clone.length / 2) - 1] + clone[(clone.length / 2)]) / 2;}

      else {median = clone[(clone.length - 1) / 2];}

      return median;
   }



   /**
    * Finds the FIBONACCI number at a specified location. 
    * @param location 
    * @return current
    */
   public static long fibonacci(int location)
   {
      long secondPrevious = 0; long firstPrevious = 1; 
      
      long current = secondPrevious + firstPrevious;

      
      if (location == 0) {return secondPrevious;}

      else if (location == 1) {return firstPrevious;}

      else
      {
         for (int i = 1; i < location; i ++)
         {
            current = secondPrevious + firstPrevious;
            secondPrevious = firstPrevious;
            firstPrevious = current; 
         }

         return current;
      }
   }


   
   /**
    * Tests if two double values are equal using a threshold value.
    * @param first
    * @param second
    * @return
    */
   public static boolean areDoublesEqual(double first, double second)
   {
      return (Math.abs(first - second) <= EPSILON);
   }
   
   
   
   /**
    * Tests if one double value is greater than another.
    * @param first
    * @param second
    * @return
    */
   public static boolean isDoubleGreater(double first, double second)
   {
      return (first > second);
   }
   
   
   //***************************************** END PUBLIC METHODS ******************************************//
   

   //********************************************** END CLASS **********************************************//
   
}


/*
   COPYRIGHT (C) 2010 - 2013 by Alexander Wait. All Rights Reserved.

   This class returns the domain attributes.

   @site http://www.javaika.com
   @author Alexander Wait
   @version 2012-07-06
*/



public class Domain 
{
  
   private static final String DOMAIN = "javaika.com";

   private static final boolean RUN_LOCAL = false; 
   
   private static final boolean prefix = true;
   
   private static final String PORT = "80";
   
   
   private Domain() {}
   
   
   //**************************************** START PUBLIC METHODS *****************************************//
   
   
   /**
    * Returns the domain name.
    * @return
    */
   public static final String getDomain()
   {
      if (prefix)
      {
         return ("www." + DOMAIN);
      }
      
      else
      {
         return (DOMAIN);
      }
   }
   
   
   
   /**
    * Returns the port number.
    * @return
    */
   public static final String getPort()
   {
      if (RUN_LOCAL)
      {
         return (":" + PORT);
         
      }
      
      else {return ("");} 
   }
   
   
   //***************************************** END PUBLIC METHODS ******************************************//
   
   
   //********************************************** END CLASS **********************************************//

}


/*
   COPYRIGHT (C) 2010 - 2013 by Alexander Wait. All Rights Reserved.

   This class builds a number key pad.

   @site http://www.javaika.com
   @author Alexander Wait
   @version 2010-07-18
*/



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



public class KeyPad extends JPanel
{

   private static final long serialVersionUID = 1L; 
   
   private static final int NORMAL_INDEX = 0; 
   private static final int PRESSED_INDEX = 2; 
   private static final int ROLLOVER_INDEX = 1;
   private static final int PAD_ARRAY_SIZE = 12;
   private static final int BACK_BUTTON_SIZE_X = 70; 
   private static final int BACK_BUTTON_SIZE_Y = 25;
   private static final int LAYOUT_ROWS = 4; 
   private static final int LAYOUT_COLUMNS = 3; 
   private static final int GRAY_SHADE = 235;


   //************************************** START INITIALISATION CODE **************************************//
   
   
   /**
    * Initializes the keypad interface.
    * @param disp
    */
   public KeyPad(JTextField disp)   
   {
      other = disp; 

      new Validation(); setLayout(new BorderLayout()); 
      
      display = new JTextField(); display.setBackground(new Color
      (GRAY_SHADE,GRAY_SHADE,GRAY_SHADE)); add(display, "North"); 
      
      buttonPanel = new JPanel(); buttonPanel.setLayout(new GridLayout
      (LAYOUT_ROWS, LAYOUT_COLUMNS)); backPanel = new JPanel(); 
      
      backPanel.setLayout(new FlowLayout()); 

      for (int i = 0; i < padButton.length; i ++)
      {
         padButton[i] = new JButton(new ImageIcon(this.getClass().getResource
         (
            "files/images/" + fileName[i][NORMAL_INDEX]))
         );

         padButton[i].setRolloverIcon(new ImageIcon(this.getClass().getResource
         (
            "files/images/" + fileName[i][ROLLOVER_INDEX]))
         );

         padButton[i].setPressedIcon(new ImageIcon(this.getClass().getResource
         (
            "files/images/" + fileName[i][PRESSED_INDEX]))
         );

         padButton[i].setBorder(BorderFactory.createEmptyBorder(0,0,0,0));
         
         padButton[i].addActionListener(new PadButtonListener(i));
         
         buttonPanel.add(padButton[i]);
      }

      add(buttonPanel, "Center"); 

      backButton = new JButton(new ImageIcon(this.getClass().getResource
      (
         "files/images/KeyPadButtonBackNormal.gif"))
      ); 

      backButton.setPressedIcon(new ImageIcon(this.getClass().getResource
      (
         "files/images/KeyPadButtonBackPressed.gif"))
      );

      backButton.setBorder(BorderFactory.createEmptyBorder(0,0,0,0)); 
      
      backButton.setPreferredSize(new Dimension
      (BACK_BUTTON_SIZE_X, BACK_BUTTON_SIZE_Y)); 
      
      backButton.addActionListener(new BackButtonListener()); 
      add(backButton, "South");
   }
   
   
   //*************************************** END INITIALISATION CODE ***************************************//
   
   
   //************************************* START INTERFACE EVENT CODE **************************************//


   private class PadButtonListener
   implements ActionListener
   {

      /**
       * Listens to keypad button press using a switch control.
       * @param args
       */
      private PadButtonListener(int args)
      {
         button = args;
        
      }

      public void actionPerformed(ActionEvent event)
      {
         switch (button)
         {
            case 0: enterText("7"); break; case 1: enterText("8"); break;
            
            case 2: enterText("9"); break; case 3: enterText("4"); break;
            
            case 4: enterText("5"); break; case 5: enterText("6"); break;
            
            case 6: enterText("1"); break; case 7: enterText("2"); break;
            
            case 8: enterText("3"); break; case 9: enterText("0"); break;
            
            case 10: enterText("."); break; case 11: clear(); break;
            
            default: System.exit(0); break;
         }
      }

      int button; 
   }



   private class BackButtonListener
   implements ActionListener
   {

      /**
       * Listens to backspace button press. 
       */
      public void actionPerformed(ActionEvent event)
      {
         backText();
      }
   }
   
   
   //************************************** END INTERFACE EVENT CODE ***************************************//


   //**************************************** START PUBLIC METHODS *****************************************//

   
   /**
    * Enters text into the keypad display.
    * @param label 
    */
   public void enterText(final String label)
   {

      if (other == null)
      {
         display.setText(display.getText() + label);
      }
      
      else
      {
         other.setText(other.getText() + label);
      }
   }



   /**
    * Removes characters and operators from display. 
    */
   public void backText()
   {
      String text = ""; 
      
      if (other == null)
      {   
         for (int i = 0; i < display.getText().length() - 1; i ++)
         {
            text += display.getText().charAt(i);
         
         }
         
         display.setText(text);
      }
      
      else
      {   
         for (int i = 0; i < other.getText().length() - 1; i ++)
         {
            text += other.getText().charAt(i);
         
         }
         
         other.setText(text);
      }    
   }

   

   /** 
    * Clears the keypad display.
    */
   public void clear()
   {
      if (other == null) {display.setText("");}
      
      else {other.setText("");}
   }

   
   //***************************************** END PUBLIC METHODS ******************************************//
   

   private JButton backButton;
   
   /** Other display. */
   public final JTextField other;
   
   /** Main display.  */
   public final JTextField display; 
   
   private JPanel buttonPanel, backPanel;
   
   private JButton[] padButton = new JButton[PAD_ARRAY_SIZE];

   private String[][] fileName =   
   {{"KeyPadButtonSevenNormal.gif","KeyPadButtonSevenRollover.gif","KeyPadButtonSevenPressed.gif"},
   {"KeyPadButtonEightNormal.gif","KeyPadButtonEightRollover.gif","KeyPadButtonEightPressed.gif"},
   {"KeyPadButtonNineNormal.gif","KeyPadButtonNineRollover.gif","KeyPadButtonNinePressed.gif"},
   {"KeyPadButtonFourNormal.gif","KeyPadButtonFourRollover.gif","KeyPadButtonFourPressed.gif"},
   {"KeyPadButtonFiveNormal.gif","KeyPadButtonFiveRollover.gif","KeyPadButtonFivePressed.gif"},
   {"KeyPadButtonSixNormal.gif","KeyPadButtonSixRollover.gif","KeyPadButtonSixPressed.gif"},
   {"KeyPadButtonOneNormal.gif","KeyPadButtonOneRollover.gif","KeyPadButtonOnePressed.gif"},
   {"KeyPadButtonTwoNormal.gif","KeyPadButtonTwoRollover.gif","KeyPadButtonTwoPressed.gif"},
   {"KeyPadButtonThreeNormal.gif","KeyPadButtonThreeRollover.gif","KeyPadButtonThreePressed.gif"},
   {"KeyPadButtonZeroNormal.gif","KeyPadButtonZeroRollover.gif","KeyPadButtonZeroPressed.gif"},
   {"KeyPadButtonPointNormal.gif","KeyPadButtonPointRollover.gif","KeyPadButtonPointPressed.gif"},
   {"KeyPadButtonClearNormal.gif","KeyPadButtonClearRollover.gif","KeyPadButtonClearPressed.gif"}};
   
   
   //********************************************** END CLASS **********************************************//

}


/*
   COPYRIGHT (C) 2010 - 2013 by Alexander Wait. All Rights Reserved.

   This class displays message dialogs.

   @site http://www.javaika.com
   @author Alexander Wait
   @version 2011-07-18
*/



import javax.swing.*;



public class Message
{

   private Message(){}
   
   
   //**************************************** START PUBLIC METHODS *****************************************//


   /**
    * Displays a message dialog.
    * @param text
    * @param heading
    * @param type 
    */
   public static void showMessage(String text, String heading, String type)
   {
      new JOptionPane(); Object[] options = {}; 

      if (type.equals("error"))
      {
         JOptionPane.showOptionDialog(null, text, heading,  
         JOptionPane.YES_OPTION, JOptionPane.ERROR_MESSAGE, null, options, null);
      }

      if (type.equals("information"))
      {
         JOptionPane.showOptionDialog(null, text, heading, 
         JOptionPane.YES_OPTION, JOptionPane.INFORMATION_MESSAGE, null, options, null);
      }

      if (type.equals("warning"))
      {
         JOptionPane.showOptionDialog(null, text, heading, 
         JOptionPane.YES_OPTION, JOptionPane.WARNING_MESSAGE, null, options, null);
      }

      if (type.equals("question"))
      {
         JOptionPane.showOptionDialog(null, text, heading, 
         JOptionPane.YES_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, null);
      }
   }
   
   
   //***************************************** END PUBLIC METHODS ******************************************//
   
   
   //********************************************** END CLASS **********************************************//
   
}


/*
   COPYRIGHT (C) 2010 - 2013 by Alexander Wait. All Rights Reserved.

   This class provides handy tools.

   @site http://www.javaika.com
   @author Alexander Wait
   @version 2012-02-01
*/



public class Tools 
{

   private static final int EXCEPTION_LINE_BEAK = 2;
   
   
   private Tools() {}
   
   
   //**************************************** START PUBLIC METHODS *****************************************//


   /**
    * This method returns the line number and path where it's called.
    * The syntax new Exception().getStackTrace()[0].getLineNumber() 
    * will only give the current line number of the source file.
    * @return
    */
   public static String thisPathAndLine()
   {
   
      String lineAndPath = ""; String stackTrace = "";
 
      stackTrace = new Exception().getStackTrace()[1].toString();
      
      
      for (int i = stackTrace.length()-1; i >= 0; i --)
      {
         if (stackTrace.charAt(i) == ')') {continue;} 
        
         else if (stackTrace.charAt(i) == '(') {break;}
        
         else {lineAndPath = (stackTrace.charAt(i) + lineAndPath);}
      }
         
      return lineAndPath + returnNewline(EXCEPTION_LINE_BEAK);
      
   }
   
   
   
   /**
    * Delays execution.
    * @param length
    */
   public static void delay(long length) 
   {
      for (long i = 0; i < length; i ++) {}
   }
   
  
 
   /**
    * This method returns a space.
    * @param length
    * @return
    */
   public static String returnSpace(int length)
   {
      String space = "";
      
      
      for (int i = 0; i < length; i ++)
      {
         space += " ";
      }
      
      return space;
   }
   
   
   
   /**
    * Assigns newlines to a string.
    * @param lines
    * @return
    */
   public static String returnNewline(int lines)
   {
      String newline = "";
      
      
      for (int i = 0; i < lines; i++)
      {
         newline += "\n";
      }
      
      
      return newline;
   
   }
   
   
   
   /**
    * Returns the users desktop path.
    * @return
    */
   public static String returnDesktopPath()
   {
      return (System.getProperty("user.home") + "/Desktop").replace("\\", "/") + "/"; 
   }
   

   //***************************************** END PUBLIC METHODS ******************************************//

   
   //********************************************** END CLASS **********************************************//
   
}


/*
   COPYRIGHT (C) 2010 - 2013 by Alexander Wait. All Rights Reserved.

   This class is used for sophisticated validation of data.

   @site http://www.javaika.com
   @author Alexander Wait
   @version 2010-07-18
*/



import java.util.regex.Pattern;



public class Validation
{

   //************************************** START INITIALISATION CODE **************************************//


   private static final String IP_ADDRESS_PATTERN = 
   
   "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +

   "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";
   
   
   private static final String NUMBER_PATTERN = "[+-]?[0-9]*[.]?[0-9]*";
   
   private static final String ALPHANUMERIC_PATTERN = "[A-Za-z0-9]*";
   
   private static final String LETTER_PATTERN = "[A-Za-z]*";
   
   private static final String INTEGER_PATTERN = "[0-9]*";



   /**
    *  Validation constructor.
    */
   public Validation()
   {
      count = 0;
   }
   
   
   //*************************************** END INITIALISATION CODE ***************************************//

   
   //**************************************** START PUBLIC METHODS *****************************************//
   
   
   /**
    * Tests a string against a supplied mask string.
    * The key for testing a string is as follows.
    * '^' represents a upper case letter.
    * '#' represents a lower case letter.
    * '?' represents a digit.
    * @param maskString
    * @param testString 
    * @return result()
    */
   public boolean maskValidation(String maskString, String testString)
   {
      count = 0;

      
      if (maskString.length() == testString.length())
      {
         for (int i = 0; i < maskString.length(); i ++)
         {
            if (maskString.charAt(i) == testString.charAt(i))
            {
               count ++;
            }

            if (maskString.charAt(i) == '?')
            {
               for (char element : digit) 
               {
                  if (testString.charAt(i) == element) 
                  {
                     count ++;
                  }
               }
            }

            if (maskString.charAt(i) == '#')
            {
               for (char element : lowerCase) 
               {
                  if (testString.charAt(i) == element)
                  {
                     count ++;
                  }
               }
            }

            if (maskString.charAt(i) == '^')
            {
               for (char element : upperCase) 
               {
                  if (testString.charAt(i) == element)
                  {
                     count ++;
                  }
               }
            }
         }
      }
      
      
      if (count != testString.length()) {return false;}
      
      else {return true;}
   }
   
   
   
   /**
    * Checks the validation of an IP address.
    * @param testString
    * @return
    */
   public boolean ipAddressValidation(String testString)
   {
      pattern = Pattern.compile(IP_ADDRESS_PATTERN);
      
      
      return (pattern.matcher(testString).matches());
   }
   
   
   
   /**
    * Checks the validation of an integer.
    * @param testString
    * @return
    */
   public boolean integerValidation(String testString)
   {
      pattern = Pattern.compile(INTEGER_PATTERN);
      
      
      return (pattern.matcher(testString).matches());
   }
   
   
   
   /**
    * Checks the validation of a letter string.
    * @param testString
    * @return
    */
   public boolean letterValidation(String testString)
   {
      pattern = Pattern.compile(LETTER_PATTERN);
      
      
      return (pattern.matcher(testString).matches());
   }
   
   
   
   /**
    * Checks the validation of an alphanumeric string.
    * @param testString
    * @return
    */
   public boolean alphanumericValidation(String testString)
   {
      pattern = Pattern.compile(ALPHANUMERIC_PATTERN);
      
      
      return (pattern.matcher(testString).matches());
   }
   
   
   
   /**
    * Checks the validation of an alphanumeric string.
    * @param testString
    * @return
    */
   public boolean numberValidation(String testString)
   {
      pattern = Pattern.compile(NUMBER_PATTERN);
      
      
      return (pattern.matcher(testString).matches());
   }


   //***************************************** END PUBLIC METHODS ******************************************//


   private int count;
   
   private Pattern pattern;


   /**
    * ESCA-JAVA0007:
    */
   public static String[] numberOperator = {"PI", "e"};
   
   /**
    * ESCA-JAVA0007:
    */
   public static char[] digit = {'0','1','2','3','4','5','6','7','8','9'};
   
   /**
    * ESCA-JAVA0007:
    */
   public static char[] simpleOperator = {'-', '+', 'v', '^', '/', 'x', '*', ','};
   
   /**
    * ESCA-JAVA0007:
    */
   public static char[] number = 
   {'-','+','.','0','1','2','3','4','5','6','7','8','9','E','I','n','f','i','t','y'};
   
   /**
    * ESCA-JAVA0007:
    */
   public static String[] singleOperator = {"Sin", "Cos", "Tan", "Fac", "Inv", "Abs"};
   
   /**
    * ESCA-JAVA0007:
    */
   public static String[] doubleOperator = {"Log", "Mod", "Pwr", "Pnr", "Cwr", "Cnr"};
  
   /**
    * ESCA-JAVA0007:
    */
   public static char[] lowerCase = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o',
   'p','q','r','s','t','u','v','w','x','y','z'};
   
   /**
    * ESCA-JAVA0007:
    */
   public static char[] upperCase = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O',
   'P','Q','R','S','T','U','V','W','X','Y','Z'};
   
   
   //********************************************** END CLASS **********************************************//

}