package rocks.zipcode.calcskin; import javafx.application.Application; import javafx.beans.binding.Bindings; import javafx.beans.property.*; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.geometry.Pos; import javafx.scene.Scene; import javafx.scene.control.*; import javafx.scene.input.KeyEvent; import javafx.scene.layout.*; import javafx.stage.Stage; import javafx.stage.StageStyle; import rocks.zipcode.calcskin.CalcEngine; import java.util.HashMap; import java.util.Map; /* - Making a simple 4-function calculator should be trivial for you at this stage. - BUT, how about adding a column of buttons for x-squared, square-root, inverse (1/x), and exponent (x^y). - Then you might add a column of buttons that do the Memory functions. (What should you add to the UI to make this easier??) Finally, work on adding the trig and log functions from the original lab. Feel free to work in your original groups, get everyone up to speed on this! */ // a simple JavaFX calculator. public class CalcSkin extends Application { public static void main(String[] args){ launch(args); } private static final String[][] template = { { "7", "8", "9", "/" }, { "4", "5", "6", "*" }, { "1", "2", "3", "-" }, { "0", "c", "=", "+" }, { "x^2", "rt", "1/x", "x^y" }, { "cos", "sin", "tan", "log10" }, { "acos","asin", "atan" }, {"store", "use","reset" } }; private final Map accelerators = new HashMap<>(); private DoubleProperty previousValue = new SimpleDoubleProperty(); private DoubleProperty currentValue = new SimpleDoubleProperty(); private DoubleProperty memoryValue = new SimpleDoubleProperty(); private CalcEngine calcEngine = new CalcEngine(); private enum Op { NOOP, ADD, SUBTRACT, MULTIPLY, DIVIDE, SQUARE, ROOT, INVERSE, EXPO, COS, SIN, TAN, LOG, ACOS, ASIN, ATAN, STORE, USE, RESET } private Op curOp = Op.NOOP; private Op stackOp = Op.NOOP; public static void launchCalc(String... args) { launch(args); } @Override public void start(Stage stage) { final TextField screen = createScreen(); final TilePane buttons = createButtons(); stage.setTitle("Calc"); stage.initStyle(StageStyle.UTILITY); stage.setResizable(false); stage.setScene(new Scene(createLayout(screen, buttons))); stage.show(); } private VBox createLayout(TextField screen, TilePane buttons) { final VBox layout = new VBox(20); layout.setAlignment(Pos.CENTER); layout.setStyle("-fx-background-color: silver; -fx-padding: 20; -fx-font-size: 20;"); layout.getChildren().setAll(screen, buttons); handleAccelerators(layout); screen.prefWidthProperty().bind(buttons.widthProperty()); return layout; } private void handleAccelerators(VBox layout) { layout.addEventFilter(KeyEvent.KEY_PRESSED, new EventHandler() { @Override public void handle(KeyEvent keyEvent) { Button activated = accelerators.get(keyEvent.getText()); if (activated != null) { System.out.println("line 94 fired"); activated.fire(); } } }); } private TextField createScreen() { final TextField screen = new TextField(); screen.setStyle("-fx-background-color: aquamarine;"); screen.setAlignment(Pos.CENTER_RIGHT); screen.setEditable(false); screen.textProperty().bind(Bindings.format("%.2f", currentValue)); return screen; } private TilePane createButtons() { TilePane buttons = new TilePane(); buttons.setVgap(7); buttons.setHgap(7); buttons.setPrefColumns(template[0].length); for (String[] r: template) { for (String s: r) { buttons.getChildren().add(createButton(s)); } } return buttons; } private Button createButton(final String s) { Button button = makeStandardButton(s); if (s.matches("[0-9]")) { makeNumericButton(s, button); } else { final ObjectProperty triggerOp = determineOperand(s); if (triggerOp.get() != Op.NOOP) { System.out.println(triggerOp.get()); makeOperandButton(button, triggerOp); } else if ("c".equals(s)) { makeClearButton(button); } else if ("=".equals(s)) { makeEqualsButton(button); } else if("x^2".equals(s)) { makeSquareBtn(button); } else if("rt".equals(s)) { makeSquareRtBtn(button); } else if("1/x".equals(s)){ makeInverseBtn(button); } else if("cos".equals(s)){ makeCOSBtn(button); } else if("sin".equals(s)){ makeSINBtn(button); } else if("tan".equals(s)){ makeTANBtn(button); } else if("log10".equals(s)){ makeLOGBtn(button); } else if("acos".equals(s)){ makeCOSBtn(button); } else if("asin".equals(s)){ makeSINBtn(button); } else if("atan".equals(s)){ makeTANBtn(button); }else if("store".equals(s)){ makeStoreBtn(button); } else if("use".equals(s)){ makeUseBtn(button); } else if("reset".equals(s)) { makeResetBtn(button); } } return button; } private ObjectProperty determineOperand(String s) { final ObjectProperty triggerOp = new SimpleObjectProperty<>(Op.NOOP); switch (s) { case "+": triggerOp.set(Op.ADD); break; case "-": triggerOp.set(Op.SUBTRACT); break; case "*": triggerOp.set(Op.MULTIPLY); break; case "/": triggerOp.set(Op.DIVIDE); break; case "x^y" : triggerOp.set(Op.EXPO); break; } return triggerOp; } private void makeOperandButton(Button button, final ObjectProperty triggerOp) { button.setStyle("-fx-base: lightgray;"); button.setOnAction(new EventHandler() { @Override public void handle(ActionEvent actionEvent) { System.out.println("Fire line: 169"); curOp = triggerOp.get(); System.out.println(curOp); } }); } private Button makeStandardButton(String s) { Button button = new Button(s); button.setStyle("-fx-base: beige;"); accelerators.put(s, button); button.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE); return button; } private void makeNumericButton(final String s, Button button) { button.setOnAction(new EventHandler() { @Override public void handle(ActionEvent actionEvent) { if (curOp == Op.NOOP) { currentValue.set(currentValue.get() * 10 + Integer.parseInt(s)); } else { previousValue.set(currentValue.get()); currentValue.set(Integer.parseInt(s)); stackOp = curOp; curOp = Op.NOOP; } } }); } private void makeClearButton(Button button) { button.setStyle("-fx-base: mistyrose;"); button.setOnAction(new EventHandler() { @Override public void handle(ActionEvent actionEvent) { currentValue.set(0); } }); } private void makeEqualsButton(Button button) { button.setStyle("-fx-base: ghostwhite;"); button.setOnAction(new EventHandler() { @Override public void handle(ActionEvent actionEvent) { System.out.println("Fire line 221"); switch (stackOp) { case ADD: currentValue.set(calcEngine.add(previousValue.get(), currentValue.get())); break; case SUBTRACT: currentValue.set(calcEngine.subtract(previousValue.get(), currentValue.get())); break; case MULTIPLY: currentValue.set(calcEngine.multiply(previousValue.get(), currentValue.get())); break; case DIVIDE: currentValue.set(calcEngine.divide(previousValue.get(), currentValue.get())); break; case EXPO: currentValue.set(calcEngine.expo(previousValue.get(), currentValue.get())); break; } } }); } //CREATE THE SQUARED FUNCTION FOR THE X^2 BUTTON private void makeSquareBtn(Button button) { button.setStyle("-fx-base: lightgray;"); button.setOnAction(new EventHandler() { @Override public void handle(ActionEvent actionEvent) { currentValue.set(calcEngine.square(currentValue.get())); stackOp = Op.SQUARE; } }); } //CREATE THE SQUARED ROOT FUNCTION FOR THE RT BUTTON private void makeSquareRtBtn(Button button) { button.setStyle("-fx-base: lightgray;"); button.setOnAction(new EventHandler() { @Override public void handle(ActionEvent actionEvent) { currentValue.set(calcEngine.root(currentValue.get())); stackOp = Op.ROOT; } }); } //CREATE THE INVERSE FUNCTION FOR THE INV BUTTON private void makeInverseBtn(Button button) { button.setStyle("-fx-base: lightgray;"); button.setOnAction(new EventHandler() { @Override public void handle(ActionEvent actionEvent) { currentValue.set(calcEngine.inverse(currentValue.get())); stackOp = Op.INVERSE; } }); } //CREATE THE COS FUNCTION FOR THE COS BUTTON private void makeCOSBtn(Button button) { button.setStyle("-fx-base: lightgray;"); button.setOnAction(new EventHandler() { @Override public void handle(ActionEvent actionEvent) { currentValue.set(calcEngine.cos(currentValue.get())); stackOp = Op.COS; } }); } //CREATE THE SIN FUNCTION FOR THE SIN BUTTON private void makeSINBtn(Button button) { button.setStyle("-fx-base: lightgray;"); button.setOnAction(new EventHandler() { @Override public void handle(ActionEvent actionEvent) { currentValue.set(calcEngine.sin(currentValue.get())); stackOp = Op.SIN; } }); } //CREATE THE TAN FUNCTION FOR THE TAN BUTTON private void makeTANBtn(Button button) { button.setStyle("-fx-base: lightgray;"); button.setOnAction(new EventHandler() { @Override public void handle(ActionEvent actionEvent) { currentValue.set(calcEngine.tan(currentValue.get())); stackOp = Op.TAN; } }); } //CREATE THE ACOS FUNCTION FOR THE ACOS BUTTON private void makeACOSBtn(Button button) { button.setStyle("-fx-base: lightgray;"); button.setOnAction(new EventHandler() { @Override public void handle(ActionEvent actionEvent) { currentValue.set(calcEngine.acos(currentValue.get())); stackOp = Op.ACOS; } }); } //CREATE THE ASIN FUNCTION FOR THE ASIN BUTTON private void makeASINBtn(Button button) { button.setStyle("-fx-base: lightgray;"); button.setOnAction(new EventHandler() { @Override public void handle(ActionEvent actionEvent) { currentValue.set(calcEngine.asin(currentValue.get())); stackOp = Op.ASIN; } }); } //CREATE THE ATAN FUNCTION FOR THE ATAN BUTTON private void makeATANBtn(Button button) { button.setStyle("-fx-base: lightgray;"); button.setOnAction(new EventHandler() { @Override public void handle(ActionEvent actionEvent) { currentValue.set(calcEngine.atan(currentValue.get())); stackOp = Op.ATAN; } }); } //CREATE THE COS FUNCTION FOR THE COS BUTTON private void makeLOGBtn(Button button) { button.setStyle("-fx-base: lightgray;"); button.setOnAction(new EventHandler() { @Override public void handle(ActionEvent actionEvent) { currentValue.set(calcEngine.log(currentValue.get())); stackOp = Op.LOG; } }); } //CREATE THE STORE FUNCTION FOR THE STORE BUTTON private void makeStoreBtn(Button button) { button.setStyle("-fx-base: lightgray;"); button.setOnAction(new EventHandler() { @Override public void handle(ActionEvent actionEvent) { memoryValue.set(currentValue.get()); stackOp = Op.STORE; } }); } //CREATE THE USE FUNCTION FOR THE USE BUTTON private void makeUseBtn(Button button) { button.setStyle("-fx-base: lightgray;"); button.setOnAction(new EventHandler() { @Override public void handle(ActionEvent actionEvent) { if(curOp == Op.NOOP){ currentValue.set(currentValue.get() * 10 + memoryValue.get()); } else { previousValue.set(currentValue.get()); currentValue.set(memoryValue.get()); stackOp = Op.USE; stackOp = curOp; curOp = Op.NOOP; } } }); } //CREATE THE COS FUNCTION FOR THE COS BUTTON private void makeResetBtn(Button button) { button.setStyle("-fx-base: lightgray;"); button.setOnAction(new EventHandler() { @Override public void handle(ActionEvent actionEvent) { memoryValue.set(0); stackOp = Op.RESET; } }); } }