scala/ScalaBook/chapter-06/calc.scala

import swing._
import swing.event._

object calc extends SimpleGUIApplication {
  def top = new MainFrame {
    val max_cols = 20
    var isDecimal = false
    var tmp: String = _
    var leftOperand: Double = _
    var curr_value:Double = 0.0
    var isFirstOperation = true
    var previous_oper = ""
    var opPressed = false
    def do_oper(oper:String, l:Double, r:Double): Double = 
      oper match {
       case "+" => l+r
       case "-" => l-r
       case "*" => l*r
       case "/" =>  if (r == 0.0) 
                      Math.NaN_DOUBLE
                    else l/r
      }
    title = "Rudimentary Calculator"
    //preferredSize = (350,250)
    font = new java.awt.Font("Verdana", java.awt.Font.PLAIN, 20)
    val cb0 = new Button { text = "0" }
    val cb1 = new Button { text = "1" }
    val cb2 = new Button { text = "2" }
    val cb3 = new Button { text = "3" }
    val cb4 = new Button { text = "4" }
    val cb5 = new Button { text = "5" }
    val cb6 = new Button { text = "6" }
    val cb7 = new Button { text = "7" }
    val cb8 = new Button { text = "8" }
    val cb9 = new Button { text = "9" }
    val cbp = new Button { text = "." }
    val cbe = new Button { text = "=" }
    val cbplus = new Button { text = "+" }
    val cbminus = new Button { text = "-" }
    val cbtimes = new Button { text = "*" }
    val cbdivide = new Button { text = "/" }
    val cbpm = new Button { text = "±" }
    val cbclr = new Button { text = "Clr" }
    val cbsqrt = new Button { text = "√" }
    val cbreci = new Button { text = "1/x" }
    var buttons = new GridPanel(0,5){
      hGap = 15
      vGap = 15
      contents += cb7
      contents += cb8
      contents += cb9
      contents += cbplus
      contents += cbclr
      contents += cb4
      contents += cb5
      contents += cb6
      contents += cbminus
      contents += cbsqrt
      contents += cb1
      contents += cb2
      contents += cb3
      contents += cbtimes
      contents += cbreci
      contents += cb0
      contents += cbp
      contents += cbe
      contents += cbdivide
      contents += cbpm
    }
    val num_display = new Label {
      text = "0"
      border = Swing.LineBorder(java.awt.Color.blue, 3)
      font = new java.awt.Font("Verdana", java.awt.Font.BOLD, 16)
      horizontalAlignment = Alignment.Right
    }
    contents = new GridBagPanel {
       var c = new Constraints
       c.fill = GridBagPanel.Fill.Horizontal
       c.gridwidth = java.awt.GridBagConstraints.REMAINDER
       add(num_display, c)
       add(Swing.VStrut(20), c)
       c.fill = GridBagPanel.Fill.None
       add(buttons, c)
       border = Swing.EmptyBorder(30, 30, 30, 30)
    }
    listenTo(cb7)
    reactions += {
      case ButtonClicked(b) => 
        if ( b.eq(cb7) && ( num_display.text.length < max_cols) ) {
          tmp = num_display.text
          if (tmp == "0" || tmp == "Error" || opPressed)
            tmp = ""
          num_display.text = tmp.concat("7")
          opPressed = false
        }
    }
    listenTo(cb8)
    reactions += {
      case ButtonClicked(b) => 
        if ( b.eq(cb8) && ( num_display.text.length < max_cols) ) {
          tmp = num_display.text
          if (tmp == "0" || tmp == "Error" || opPressed)
            tmp = ""
          num_display.text = tmp.concat("8")
          opPressed = false
        }
    }
    listenTo(cb9)
    reactions += {
      case ButtonClicked(b) => 
        if ( b.eq(cb9) && ( num_display.text.length < max_cols) ) {
          tmp = num_display.text
          if (tmp == "0" || tmp == "Error" || opPressed)
            tmp = ""
          num_display.text = tmp.concat("9")
          opPressed = false
        }
    }
    listenTo(cb4)
    reactions += {
      case ButtonClicked(b) => 
        if ( b.eq(cb4) && ( num_display.text.length < max_cols) ) {
          tmp = num_display.text
          if (tmp == "0" || tmp == "Error" || opPressed)
            tmp = ""
          num_display.text = tmp.concat("4")
          opPressed = false
        }
    }
    listenTo(cb5)
    reactions += {
      case ButtonClicked(b) => 
        if ( b.eq(cb5) && ( num_display.text.length < max_cols) ) {
          tmp = num_display.text
          if (tmp == "0" || tmp == "Error" || opPressed)
            tmp = ""
          num_display.text = tmp.concat("5")
          opPressed = false
        }
    }
    listenTo(cb6)
    reactions += {
      case ButtonClicked(b) => 
        if ( b.eq(cb6) && ( num_display.text.length < max_cols) ) {
          tmp = num_display.text
          if (tmp == "0" || tmp == "Error" || opPressed)
            tmp = ""
          num_display.text = tmp.concat("6")
          opPressed = false
        }
    }
    listenTo(cb1)
    reactions += {
      case ButtonClicked(b) => 
        if ( b.eq(cb1) && ( num_display.text.length < max_cols) ) {
          tmp = num_display.text
          if (tmp == "0" || tmp == "Error" || opPressed)
            tmp = ""
          num_display.text = tmp.concat("1")
          opPressed = false
        }
    }
    listenTo(cb2)
    reactions += {
      case ButtonClicked(b) => 
        if ( b.eq(cb2) && ( num_display.text.length < max_cols) ) {
          tmp = num_display.text
          if (tmp == "0" || tmp == "Error" || opPressed)
            tmp = ""
          num_display.text = tmp.concat("2")
          opPressed = false
        }
    } 
    listenTo(cb3)
    reactions += {
      case ButtonClicked(b) => 
        if ( b.eq(cb3) && ( num_display.text.length < max_cols) ) {
          tmp = num_display.text
          if (tmp == "0" || tmp == "Error" || opPressed)
            tmp = ""
          num_display.text = tmp.concat("3")
          opPressed = false
        }
    }
    listenTo(cb0)
    reactions += {
      case ButtonClicked(b) => 
        if ( b.eq(cb0) && ( num_display.text.length < max_cols) ) {
          tmp = num_display.text
          if (tmp == "0" || tmp == "Error" || opPressed)
            tmp = ""
          num_display.text = tmp.concat("0")
          opPressed = false
        }
    }
    listenTo(cbp)
    reactions += {
      case ButtonClicked(b) => 
        if ( b.eq(cbp) && ( num_display.text.length < max_cols) ) {
          tmp = num_display.text
          if ( ! isDecimal && tmp != "Error" && ! tmp.contains(".") ) {
            num_display.text = tmp.concat(".")
            isDecimal = true
          }
          opPressed = false
        }
    }
    listenTo(cbplus)
    reactions += {
      case ButtonClicked(b) => 
        if ( b.eq(cbplus) ) {
          tmp = num_display.text
          if ( tmp != "Error") {
            curr_value = java.lang.Double.parseDouble(tmp)
            if ( ! isFirstOperation ) {
              if (!leftOperand.isNaN)
                leftOperand = do_oper(previous_oper, leftOperand, curr_value)
              if (leftOperand.isNaN) 
                num_display.text = "Error"
              else 
                num_display.text = leftOperand.toString
            } 
            else {
              leftOperand = curr_value
              isFirstOperation = false
            }
            previous_oper = "+"
            opPressed = true
            isDecimal = false
          }
        }
    } 
    listenTo(cbminus)
    reactions += {
      case ButtonClicked(b) => 
        if ( b.eq(cbminus) ) {
          tmp = num_display.text
          if ( tmp != "Error") {
            curr_value = java.lang.Double.parseDouble(tmp)
            if ( ! isFirstOperation ) {
              if (!leftOperand.isNaN)
                leftOperand = do_oper(previous_oper, leftOperand, curr_value)
              if (leftOperand.isNaN)
                num_display.text = "Error"
              else 
                num_display.text = leftOperand.toString
            } 
            else {
              leftOperand = curr_value
              isFirstOperation = false
            }
            previous_oper = "-"
            opPressed = true
            isDecimal = false
          }  
        }
    } 
    listenTo(cbtimes)
    reactions += {
      case ButtonClicked(b) => 
        if ( b.eq(cbtimes) ) {
          tmp = num_display.text
          if ( tmp != "Error") {
            curr_value = java.lang.Double.parseDouble(tmp)
            if ( ! isFirstOperation ) {
              if (!leftOperand.isNaN)
                leftOperand = do_oper(previous_oper, leftOperand, curr_value)
              if (leftOperand.isNaN)
                num_display.text = "Error"
              else 
                num_display.text = leftOperand.toString
            } 
            else {
              leftOperand = curr_value
              isFirstOperation = false
            }
            previous_oper = "*"
            opPressed = true
            isDecimal = false
          }
        }
    } 
    listenTo(cbdivide)
    reactions += {
      case ButtonClicked(b) => 
        if ( b.eq(cbdivide) ) {
          tmp = num_display.text
          if ( tmp != "Error") {
            curr_value = java.lang.Double.parseDouble(tmp)
            if ( ! isFirstOperation ) {
              if (!leftOperand.isNaN)
                leftOperand = do_oper(previous_oper, leftOperand, curr_value)
              if (leftOperand.isNaN)
                num_display.text = "Error"
              else 
                num_display.text = leftOperand.toString
            } 
            else {
              leftOperand = curr_value
              isFirstOperation = false
            }
            previous_oper = "/"
            opPressed = true
            isDecimal = false
          }
        }
    }
    listenTo(cbpm)
    reactions += {
      case ButtonClicked(b) => 
        if ( b.eq(cbpm) ) {
          tmp = num_display.text
          if (tmp != "0" && tmp != "Error" && !opPressed) {
            curr_value = -(java.lang.Double.parseDouble(tmp))
            num_display.text = curr_value.toString
            opPressed = false
          }
        }
    }  
    listenTo(cbclr)
    reactions += {
      case ButtonClicked(b) => 
        if ( b.eq(cbclr) ) {
          num_display.text = "0"
          opPressed = false
          isFirstOperation = true
          isDecimal = false
        }
    } 
    listenTo(cbe)
    reactions += {
      case ButtonClicked(b) => 
        if ( b.eq(cbe) ) {
          tmp = num_display.text
          if ( tmp != "Error") {
            curr_value = java.lang.Double.parseDouble(tmp)
            if ( ! isFirstOperation ) {
              leftOperand = do_oper(previous_oper, leftOperand, curr_value)
              if (leftOperand.isNaN)
                num_display.text = "Error"
              else 
                num_display.text = leftOperand.toString
            } 
            else {
              leftOperand = curr_value
            }
            isFirstOperation = true
            previous_oper = ""
            opPressed = false
          }
        }
    } 
    listenTo(cbsqrt)
    reactions += {
      case ButtonClicked(b) => 
        if ( b.eq(cbsqrt) ) {
          tmp = num_display.text
          if ( tmp != "Error") {
            curr_value = java.lang.Double.parseDouble(tmp)
            if ( curr_value < 0.0) {
              curr_value = Math.NaN_DOUBLE
              num_display.text = "Error"            
            }
            else 
              num_display.text = (Math.sqrt(curr_value)).toString
          }
          opPressed = true
        }
    }
    listenTo(cbreci)
    reactions += {
      case ButtonClicked(b) => 
        if ( b.eq(cbreci) ) {
          tmp = num_display.text
          if ( tmp != "Error") {
            curr_value = java.lang.Double.parseDouble(tmp)
            if ( curr_value == 0.0) {
              curr_value = Math.NaN_DOUBLE
              num_display.text = "Error"            
            }
            else 
              num_display.text = (1/curr_value).toString
          }
          opPressed = true
        }
    }
  }
}