Engine for Calculator by Michael Schmidt : Calculator « SWT JFace Eclipse « Java

Java
1. 2D Graphics GUI
2. 3D
3. Advanced Graphics
4. Ant
5. Apache Common
6. Chart
7. Class
8. Collections Data Structure
9. Data Type
10. Database SQL JDBC
11. Design Pattern
12. Development Class
13. EJB3
14. Email
15. Event
16. File Input Output
17. Game
18. Generics
19. GWT
20. Hibernate
21. I18N
22. J2EE
23. J2ME
24. JDK 6
25. JNDI LDAP
26. JPA
27. JSP
28. JSTL
29. Language Basics
30. Network Protocol
31. PDF RTF
32. Reflection
33. Regular Expressions
34. Scripting
35. Security
36. Servlets
37. Spring
38. Swing Components
39. Swing JFC
40. SWT JFace Eclipse
41. Threads
42. Tiny Application
43. Velocity
44. Web Services SOA
45. XML
Java Tutorial
Java Source Code / Java Documentation
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java » SWT JFace Eclipse » CalculatorScreenshots 
Engine for Calculator by Michael Schmidt

/**
  The following code is from Michael Schmidt(MichaelMSchmidt (at) msn.com).
  
  The code is published under BSD license.
  
  Thanks for the input from Michael Schmidt.
*/


package us.mschmidt.komo;

/**
 * This is a generic calculator engine that includes a memory register, some
 * numeric conversions (square root, inverse), and the ability to chain 
 * calculations.  To use it, create a GUI shell with a display and some means 
 * of entering keystrokes (Buttons work well).  Invoke this engine from the GUI
 * shell using the constructor method, which requires that the display size 
 * (String length) be set.  Obtain the initial display, if desired, with the 
 * getDisplayString() method.  Subsequently, the display string is returned by 
 * the setInput() method when an operation (character) is passed to the engine.
 * <p>
 * The constructor requires a display size to be set.  The minimum is three
 * characters, with at least 22 characters recommended and recommended  size 
 * being 30 characters.  
 *  
 @author   Michael Schmidt
 @version  1.1
 */
class CalcEngine {
  
  // Instantiatee constants
  private final String calcChars;
  private final String convChars;
  private final String dispChars;
  private final String memChars;
  private final String errChars;
  
  // Instantiate variables
  // The error messages
  private String nanErr = new String();
  private String tooLongErr = new String();
  private String infinityErr = new String();
  private int displaySize;
  
  // The calculator 'registers'
  private String displayString = new String();
  private String memoryString = new String();
  private String operatorString = new String();
  
  // A boolean to indicate if display will be cleared on the next key entry
  private boolean clearDisplay;
  
  // A character to store the pending calculation
  private char calcChar;

  /**
   * Constructor to create the calculator engine object.
   
   @param displaySizeVal  The GUI display size, minimum of 3 and
   *                         recommended size of 30
   */
  CalcEngine(final int displaySizeVal) {
    final int minSize = 3;
    // Initialize operation characters
    calcChars = "+-/*=";
    convChars = "IQ";
    dispChars = "BCERS.0123456789";
    memChars = "DLMP";
    errChars = "EINO*";
    
    // Set initial display and internal variables
    displayString = "0.";
    clearDisplay = true;
    calcChar = ' ';
    
    // Set the display size
    displaySize = minSize;
    if (displaySizeVal > minSize) {
      displaySize = displaySizeVal;
    
    // Customize the error strings based on the display size
    setErrorStrings();
  }
  
  /**
   * Customizes the error messages based on the display size.
   */
  private void setErrorStrings() {
    
    // Initialize constants for display size thresholds
    final int infLength = 8;
    final int nanLength = 12;
    final int tooLongLength = 15;
    final int fullLength = 22;
    
    // Set default strings for optimal display size
    nanErr = "Not a Number";
    tooLongErr = "Number too long";
    infinityErr = "Infinity";
    
    if (displaySize < infLength) {
      nanErr = "NaN";
      tooLongErr = "***";
      infinityErr = "Inf";
    else if (displaySize < nanLength) {
      nanErr = "NaN";
      tooLongErr = "Overflow";
    else if (displaySize < tooLongLength) {
      tooLongErr = "Overflow";
    else if (displaySize >= fullLength) {
      nanErr = "ERROR: " + nanErr;
      tooLongErr = "ERROR: " + tooLongErr; 
      infinityErr = "ERROR: " + infinityErr; 
    }
  }
  
  /**
   * Provides the display string to the calling class.  Used after the  
   * engine is instantiated.  Subsequently, the display string is returned by
   * the setInput() method.
   
   @return  the display String
   */
  public String getDisplayString() {
    return displayString;
  }
  
  /**
   * Allows entry of keystrokes from the calling class.
   
   @param keyVal  A designation of the key pressed by the user using the
   *                 code.  
   *                 Display codes: B backspace, C clear, E clear entry,
   *                 R recall memory to display, S change sign, . decimal, 
   *                 0-9 numeric entries.
   *                 Memory codes: D clear memory, M subtract from memory, 
   *                 L store in memory, P add to memory. 
   *                 Calculate codes: I inverse, Q square root, S subtract.
   @return        boolean true if the display has changed, false if not
   */
  public String setInput(final char keyVal) {
    final char keyChar = keyVal;
    if (dispChars.indexOf(keyChar!= -1) {
      doDisplayOp(keyChar);
    else if (convChars.indexOf(keyChar!= -1) {
      doConvertOp(keyChar);
    else if (memChars.indexOf(keyChar!= -1) {
      doMemoryOp(keyChar);
    else if (calcChars.indexOf(keyChar!= -1) {
      doCalcOp(keyChar);
    }
    return displayString;
  }
  
  /**
   * Clears the display when 1) the clearDisplay flag had previously been set
   * to 'true' and 2) a new character or calculation operation is entered.
   */
  private void doDisplayClear() {
    if (clearDisplay) {
      displayString = "";
      clearDisplay = false;
    }
  }

  /**
   * Performs number conversion operations: inverse (1/X) and square root.
   
   @param keyVal  a designation of the key pressed by the user
   */
  private void doConvertOp(final char keyVal) {
    final char opChar = keyVal;
    String tempString = doConvert(displayString, opChar);
    clearDisplay = true;
    if (tempString.length() 0) {
      displayString = tempString;
    }
  }

  /**
   * Performs display operations.  Simple assignment operations are performed 
   * in this method while more complex operations are performed in sub-methods. 
   
   @param keyVal  a designation of which key was pressed by the user
   */
  private void doDisplayOp(final char keyVal) {
    final char opChar = keyVal;

    switch (opChar) {
      case 'B':  // Backspace
        doBackspace();
        break;

      case 'C':  // Clear.  Note use of dropthrough
        operatorString = "";
        calcChar = ' ';

      case 'E':  // Clear Entry
        displayString = "0.";
        clearDisplay = true;
        break;


      case 'R':  // Recall Memory to Display
        displayString = memoryString;
        break;

      case 'S':  // Change Sign
        doChangeSign();
        break;

      case '.':  // Can't have two decimal points.
        doDecimal(opChar);
        break;

      case '0':  // Don't want 00 to be entered.
        doZero(opChar);
        break;

      default:  // Default case is for the digits 1 through 9.
        doAddChar(opChar);
        break;
    }
  }
  
  /**
   * Performs backspace operation.
   */
  private void doBackspace() {
    if (isError(displayString)) {
      return;
    }
    if (displayString.length() 0) {
      displayString = displayString.substring(
          0, displayString.length() 1);
    }
  }

  /**
   * Performs operation to add a character to the display.
   
   @param c  the character to add
   */
  private void doAddChar(final char c) {
    if (isError(displayString)) {
      return;
    }
    if (displayString.length() < displaySize) {
      doDisplayClear();
      displayString += c;
    }
  }
  
  /**
   * Performs sign change operation.
   */
  private void doChangeSign() {
    if (isError(displayString)) {
      return;
    }
    if ('-' == displayString.charAt(0)) {
      displayString = displayString.substring(
          1, displayString.length());
    else if (displayString.length() < displaySize) {
      displayString = '-' + displayString;
    }
  }
  
  /**
   * Performs operation when decimal is pressed.
   
   @param c  the decimal character
   */
  private void doDecimal(final char c) {
    if (isError(displayString)) {
      return;
    }
    if (displayString.indexOf('.'== -
        && displayString.length() < displaySize) {
      doDisplayClear();
      displayString += c;
    }
  }
  
  /**
   * Performs operation when '0' is pressed.
   
   @param c  the zero operation character
   */
  private void doZero(final char c) {
    if (isError(displayString)) {
      return;
    }
    if (!displayString.equals("0"&& displayString.length() <  displaySize) {
      doDisplayClear();
      displayString += c;
    }
  }

  /**
   * Updates the value stored in the memory register.  Simple assignment 
   * operations are performed here while more complex operations are performed 
   * in sub-methods.
   
   @param keyVal  a designation of which key was pressed by the user
   */
  private void doMemoryOp(final char keyVal) {
    final char opChar = keyVal;

    switch (opChar) {
      case 'D':  // Clear Memory
        memoryString = "";
        break;
        
      case 'L':  // Save to Memory
        assignMemoryString(trimString(displayString));
        break;

      case 'M':  // Subtract from Memory
        subtractFromMemory();
        break;

      case 'P':  // Add to Memory
        addToMemory();
        break;

      default:  // Do nothing - this should never happen.
        break;
    }

    clearDisplay = true;
  }
  
  /**
   * Performs the operation to add a display entry to the number in the
   * memory register.
   */
  private void addToMemory() {
    String tempString = new String();
    if (== memoryString.length()) {
      tempString = trimString(displayString);
    else {
      tempString = doComputation(memoryString, displayString, '+');
    }
    assignMemoryString(tempString);
  }
  
  /**
   * Performs the operation to subtract a display entry from the number in the
   * memory register.
   */
  private void subtractFromMemory() {
    String tempString = new String();
    if (== memoryString.length()) {
      tempString = doComputation("0", displayString, '-');
    else {
      tempString = doComputation(memoryString, displayString, '-');
    }
    assignMemoryString(tempString);
  }
  
  /**
   * Checks if String is valid and, if so, assigns it to the memory register.
   
   @param s  the String to assign
   */
  private void assignMemoryString(final String s) {
    if (isError(s)) {
      displayString = s;
    else {
      memoryString = s;
    }
  }

  /**
   * Guides 2-number calculations.  Updates the operator string, display 
   * string, and the pending calculation flag.  Performs calculation if 
   * possible.
   
   @param keyVal  a designation of which key was pressed byt he user
   */
  private void doCalcOp(final char keyVal) {
    final char opChar = keyVal;

    // If there is no display value, the keystroke is deemed invalid and 
    // nothing is done.
    if (== displayString.length()) {
      return;
    }

    // If there is no operator value, '=' key presses are considered 
    // invalid.  If a calculation key is pressed, check that the display 
    // value is valid and if so, copy the display value to the operator.  
    // No calculation is done.
    if (== operatorString.length()) {
      if ('=' != opChar) {
        if (isError(displayString)) {
          calcChar = ' ';
        else {
          operatorString = displayString;
          calcChar = opChar;
        }
        clearDisplay = true;
      }
      return;
    }
    
    // There are operator and display values, so do the pending calculation.
    displayString = doComputation(operatorString, displayString, calcChar);

    // If '=' was pressed or result was invalid, reset pending calculation
    // flag and operator value.  Otherwise, set new calculation flag so 
    // calculations can be chained.
    if (('=' == opChar|| isError(displayString)) {
      calcChar = ' ';
      operatorString = "";
    else {
      calcChar = opChar;
      operatorString = displayString;
    }

    // Set the clear display flag
    clearDisplay = true;
  }
  
  /**
   * Performs the computations.
   
   @param numStringA  the displayed value
   @param numStringB  the stored value
   @param opVal        the operation to be performed
   @return            the solution as a string variable
   */
  private String doComputation(final String numStringA, 
      final String numStringB, final char opVal) {
    String valStringA = numStringA;
    String valStringB = numStringB;
    char opChar = opVal;
    Double valA = 0.0
    Double valB = 0.0;
    Double valAnswer = 0.0;

    // Make sure register strings are numbers
    if (valStringA.length() && valStringB.length() 0) {
      try {
        valA = Double.parseDouble(numStringA);
        valB = Double.parseDouble(numStringB);
      catch (final NumberFormatException e) {
        return nanErr;
      }
    else {
      return "";
    }

    switch (opChar) {
      case '+':  // Addition
        valAnswer = valA + valB;
        break;

      case '-':  // Subtraction
        valAnswer = valA - valB;
        break;

      case '/':  // Division
        valAnswer = valA / valB;
        break;

      case '*':  // Multiplication
        valAnswer = valA * valB;
        break;

      default:  // Do nothing - this should never happen
        break;
    }

    // Convert answer to properly formatted string.
    return trimString(valAnswer.toString());
  }
  
  /**
   * Performs number conversion computations.
   
   @param numString  the number to be converted
   @param opVal    designation of the operation to be performed
   @return      the converted value
   */
  private String doConvert(final String numString, final char opVal) {
    char opChar = opVal;
    String valString = numString;
    Double valA = 0.0
    Double valAnswer = 0.0;

    // Make sure String is a number.  If it is zero-length, assume the
    // keystroke was inadvertent and return "".
    if (valString.length() 0) {
      try {
        valA = Double.parseDouble(valString);
      catch (final NumberFormatException e) {
        return nanErr;
      }
    else {
      return "";
    }

    switch (opChar) {
      case 'Q':  // Square Root
        valAnswer = Math.sqrt(valA);
        break;

      case 'I':  // Inverse
        valAnswer = 1.0 / valA;
        break;

      default:  // Do nothing - this should never happen
        break;
    }

    // Return properly formatted result String.
    return trimString(valAnswer.toString());
  }

  /**
   * Formats String to be displayed.
   
   @param stringVal  a new string to be displayed
   @return          the properly formatted and trimmed string
   */
  private String trimString(final String stringVal) {
    String returnString = stringVal;

    // Check if value is Not a Number
    if (returnString.equals("NaN")) {
      return nanErr;
    }
    
    // Check if value is infinity
    if (returnString.endsWith("Infinity")) {
      return infinityErr;
    }
    
    // Check if value is -0
    if (returnString.equals("-0.0")) {
      return "0";
    }
    
    // Trim unnecessary trailing .0
    if (returnString.endsWith(".0")) {
      returnString = returnString.substring(0, returnString.length() 2);
    }
    
    // Check if string is too long to display
    if (returnString.length() > displaySize) {
      return tooLongErr;
    }

    return returnString;
  }
  
  /**
   * Tests if the String is an error message.
   
   @param s  the String to be tested
   @return  boolean true if this is an error message, false if not
   */
  private boolean isError(final String s) {
    String testString = s;
    if (== testString.length()) {
      return false;
    }
    char c = testString.charAt(0);
    return ((errChars.indexOf(c== -1)) false true;
  }

  /**
   * Override to provide useful information when the class toString method is
   * called.
   
   @return  the information String
   @see     java.lang.Object#toString()
   */
  @Override
  public final String toString() {
    return "komo.CalcEngine is the engine portion of the calculator utility";
  }
}


           
       
Related examples in the same category
1. Calculator by Michael SchmidtCalculator by Michael Schmidt
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.