.
This example illustrates how to use the grid constraint.
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;
}
}