/*
* Copyright 2008 Jeff Dwyer
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.apress.progwt.client.calculator;
import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DockPanel;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.MultiWordSuggestOracle;
import com.google.gwt.user.client.ui.SuggestBox;
import com.google.gwt.user.client.ui.SuggestionEvent;
import com.google.gwt.user.client.ui.SuggestionHandler;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.TextBox;
public class Calculator extends Composite {
/**
* Format is postive;negative. We want to override the default
* thousands separator ',' to help ease our parser.
*/
private static final NumberFormat nf = NumberFormat
.getDecimalFormat().getFormat("###0.#####;-###0.#####");
private ControlAction lastAction;
private boolean doClearOnNextDigit;
private TextBox inputBox;
private double lastNum = 0;
private TextArea ticker;
public Calculator() {
DockPanel dockPanel = new DockPanel();
Grid controls = new Grid(5, 2);
Grid numbersP = new Grid(4, 3);
// initialize the 1-9 buttons
for (int row = 0; row < 3; row++) {
for (int col = 0; col < 3; col++) {
numbersP.setWidget(row, col, new NumberButton(this, row
* 3 + col + 1));
}
}
numbersP.setWidget(3, 0, new NumberButton(this, 0));
numbersP.setWidget(3, 1, new NumberButton(this, "."));
numbersP.setWidget(3, 2, new ControlButton(this,
new ControlAction(this, "+/-") {
@Override
public boolean isMultiArg() {
return false;
}
@Override
public double performAction(ControlAction lastAction,
double previous, double current) {
return -1 * current;
}
}));
controls.setWidget(0, 0, new ControlButton(this,
new ControlAction(this, "/") {
@Override
public double performAction(ControlAction lastAction,
double previous, double current) {
return previous / current;
}
}));
controls.setWidget(0, 1, new ControlButton(this,
new ControlAction(this, "sqrt") {
@Override
public boolean isMultiArg() {
return false;
}
@Override
public double performAction(ControlAction lastAction,
double previous, double current) {
return Math.sqrt(current);
}
}));
controls.setWidget(1, 0, new ControlButton(this,
new ControlAction(this, "*") {
@Override
public double performAction(ControlAction lastAction,
double previous, double current) {
return previous * current;
}
}));
controls.setWidget(1, 1, new ControlButton(this,
new ControlAction(this, "%") {
@Override
public double performAction(ControlAction lastAction,
double previous, double current) {
return previous % current;
}
}));
controls.setWidget(2, 0, new ControlButton(this,
new ControlAction(this, "-") {
@Override
public double performAction(ControlAction lastAction,
double previous, double current) {
return previous - current;
}
}));
controls.setWidget(2, 1, new ControlButton(this,
new ControlAction(this, "1/x") {
@Override
public boolean isMultiArg() {
return false;
}
@Override
public double performAction(ControlAction lastAction,
double previous, double current) {
return 1 / current;
}
}));
controls.setWidget(3, 0, new ControlButton(this,
new ControlAction(this, "+") {
@Override
public double performAction(ControlAction lastAction,
double previous, double current) {
return previous + current;
}
}));
controls.setWidget(3, 1, new ControlButton(this,
new ControlAction(this, "=") {
@Override
public boolean isMultiArg() {
return false;
}
@Override
public double performAction(ControlAction lastAction,
double previous, double current) {
if (lastAction == null) {
return current;
}
return lastAction.performAction(null, previous,
current);
}
}));
controls.setWidget(4, 0, new ControlButton(this,
new ControlAction(this, "bksp") {
@Override
public boolean isMultiArg() {
return false;
}
@Override
public double performAction(ControlAction lastAction,
double previous, double current) {
String cStr = current + "";
if (cStr.endsWith(".0")) {
cStr = cStr.substring(0, cStr.length() - 3);
} else {
cStr = cStr.substring(0, cStr.length() - 1);
}
if (cStr.equals("")) {
cStr = "0";
}
return Double.parseDouble(cStr);
}
}));
controls.setWidget(4, 1, new ControlButton(this,
new ControlAction(this, "clear") {
@Override
public boolean isMultiArg() {
return false;
}
@Override
public double performAction(ControlAction lastAction,
double previous, double current) {
return 0;
}
}));
dockPanel.add(numbersP, DockPanel.CENTER);
dockPanel.add(controls, DockPanel.EAST);
inputBox = new TextBox();
inputBox.addStyleName("ResultBox");
dockPanel.add(inputBox, DockPanel.NORTH);
ticker = new TextArea();
ticker.setSize("7em", "140px");
MultiWordSuggestOracle oracle = new MultiWordSuggestOracle();
oracle.add("Jill");
oracle.add("Jeff");
oracle.add("James");
oracle.add("Jennifer");
SuggestBox box = new SuggestBox(oracle);
box.addEventHandler(new SuggestionHandler() {
public void onSuggestionSelected(SuggestionEvent suggE) {
String selected = suggE.getSelectedSuggestion()
.getReplacementString();
// do something with selected suggestion
}
});
dockPanel.add(box, DockPanel.SOUTH);
HorizontalPanel mainP = new HorizontalPanel();
mainP.add(dockPanel);
mainP.add(ticker);
initWidget(mainP);
setResult(0);
}
public void actionClick(ControlAction action) {
if (action.isMultiArg()) {
lastNum = getCurrentNum();
setDoClearOnNextDigit(true);
this.lastAction = action;
} else {
setResult(action.performAction(lastAction, getLastNum(),
getCurrentNum()));
}
}
public void digitAction(String value) {
if (isDoClearOnNextDigit()) {
inputBox.setText("");
setDoClearOnNextDigit(false);
}
inputBox.setText(inputBox.getText() + value);
}
private double getCurrentNum() {
return Double.parseDouble(inputBox.getText());
}
private double getLastNum() {
return lastNum;
}
public boolean isDoClearOnNextDigit() {
return doClearOnNextDigit;
}
public void setDoClearOnNextDigit(boolean doClearOnNextDigit) {
this.doClearOnNextDigit = doClearOnNextDigit;
}
private void setResult(double res) {
inputBox.setText(nf.format(res));
ticker.setText(res + "\n" + ticker.getText());
GUIEffects.highlight(inputBox);
if (res == 0) {
setDoClearOnNextDigit(true);
}
}
}