The calculator is composed of a display and a board with many buttons. The display is simply a text field which is already available as a base class. Therefore, we only need to get the Board class ready to build a calculator.
The following shows the class for building the board:
Class Board { dj Button b[9]; // Buttons "0",...,"9" dj Button bc {text == "C"}; ... // Buttons "+","-","*","/",".","=" for (i in 0..9) b[i].text == String(i); grid({{bc,bdiv,bmul,bsub}, {b[7],b[8], b[9], badd}, {b[4],b[5], b[6], badd}, {b[1],b[2], b[3], beq }, {b[0],b[0], bpoint,beq}}); }The for statement constrains the values for the text attributes of the digit buttons. The expression String(i) translates an integer i into a string. The grid constraint constrains the positions for the buttons. Notice that a component may spread over several grids.
To have a working caculator, we need to associate actions with the buttons. The following class Calculator class has a board and a text field that serves as the display of the calculator.
class Calculator { double acc = 0; char op = ' '; boolean firstDigit = true; dj TextField tf{text=="0";columns==20}; dj Board bd; // constraints above(tf,bd); sameCenterX(tf,bd); // actions for (i in 0..9) command(bd.b[i],inputDigit(char(i))); command(bd.bc,clear()); command(bd.badd,inputOp('+')); command(bd.bsub,inputOp('-')); command(bd.bmul,inputOp('*')); command(bd.bdiv,inputOp('/')); command(bd.beq,inputOp('=')); command(bd.bpoint,inputPoint()); void inputZero(){ if ((tf.getText()).compareTo("0")!=0) inputDigit('0'); } void inputDigit(char d){ if (firstDigit){ tf.setText(String.valueOf(d)); if (d!='0') firstDigit = false; } else { tf.setText(tf.getText()+d); } } void clear(){ tf.setText("0"); firstDigit=true; acc = 0.0; op = ' '; } void inputOp(char operator){ compute(op); op = operator; } void inputPoint(){ if (!hasPoint(tf.getText())){ tf.setText(tf.getText()+"."); } } void compute(char operator){ double newValue; newValue = (Double.valueOf(tf.getText())).doubleValue(); switch (operator){ case '+' : acc += newValue;break; case '-' : acc -= newValue;break; case '*' : acc *= newValue;break; case '/' : acc /= newValue;break; default : acc = newValue; } tf.setText(Double.toString(acc)); firstDigit = true; } boolean hasPoint(String s){ for (int i=0;i<s.length();i++){ if ((s.charAt(i))=='.') return true; } return false; } }