diff --git a/README.md b/README.md index 82c6217..e59d115 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,13 @@ -## Javafx template +# Javafx template -Template for single-module javafx projects, with maven setup for latest java and javafx, and jupiter and testfx for testing. +Template for single-module javafx project, with maven setup for Java 16 and JavaFX 16, and JUnit 5 (Jupiter) and TestFX for testing. + +To make the project more interesting, it is the start of an [RPN](https://en.wikipedia.org/wiki/Reverse_Polish_notation) calculator (look for `// TODO`) markers). The core logic is almost implemented (in [Calc.java](src/main/java/app/Calc.java)), the fxml file (in [App.fxml](src/main/resources/app/App.fxml) is almost complete, but the controller class (in [AppController.java](src/main/java/app/AppController.java) is pretty limited. And last, but not least, there is a TestFX-based test (in [AppTest.java](src/test/java/app/AppTest.java), see the [README](src/test/java/app/README.md) for details about what it tests. + +## Trying it out + +The project in javafx-template can be tried out in various ways: + +- compile with `mvn compile` (after `cd javafx-template` of course) +- test with `mvn test` (it should fail until you complete the RPN calculator) +- run with `mvn javafx:run` (it should open, but not work properly) diff --git a/javafx-template/src/main/java/app/AppController.java b/javafx-template/src/main/java/app/AppController.java index 9efef1c..1cbbd29 100644 --- a/javafx-template/src/main/java/app/AppController.java +++ b/javafx-template/src/main/java/app/AppController.java @@ -2,7 +2,6 @@ package app; import java.util.List; import java.util.function.BinaryOperator; -import java.util.function.Consumer; import java.util.function.UnaryOperator; import javafx.event.ActionEvent; @@ -39,16 +38,12 @@ public class AppController { updateOperandsView(); } - private int minOperandCount = 2; - private void updateOperandsView() { - while (calc.getOperandCount() < minOperandCount) { - calc.pushOperand(calc.getOperandCount(), 0.0); - } List operands = operandsView.getItems(); operands.clear(); - for (int i = 0; i < minOperandCount; i++) { - operands.add(calc.peekOperand(minOperandCount - i - 1)); + int elementCount = Math.min(calc.getOperandCount(), 3); + for (int i = 0; i < elementCount; i++) { + operands.add(calc.peekOperand(elementCount - i - 1)); } } @@ -68,33 +63,25 @@ public class AppController { operandView.setText(operandString); } - private void setOperand(double d) { - setOperand(Double.toString(d)); - } - - private void clearOperand() { - setOperand(""); - } - @FXML void handleEnter() { if (hasOperand()) { calc.pushOperand(getOperand()); } else { calc.dup(); - } - clearOperand(); + } + setOperand(""); updateOperandsView(); - } + } private void appendToOperand(String s) { - setOperand(operandView.getText() + s); + // TODO } @FXML void handleDigit(ActionEvent ae) { if (ae.getSource() instanceof Labeled l) { - appendToOperand(l.getText()); + // TODO append button label to operand } } @@ -102,70 +89,40 @@ public class AppController { void handlePoint() { var operandString = getOperandString(); if (operandString.contains(".")) { - setOperand(operandString.substring(0, operandString.indexOf(".") + 1)); + // TODO remove characters after point } else { - appendToOperand("."); + // TODO append point } } @FXML void handleClear() { - clearOperand(); - } - - private void withOperand(Runnable proc) { - if (hasOperand()) { - calc.pushOperand(getOperand()); - clearOperand(); - } - proc.run(); - updateOperandsView(); + // TODO clear operand } private void performOperation(UnaryOperator op) { - withOperand(() -> calc.performOperation(op)); + // TODO } private void performOperation(boolean swap, BinaryOperator op) { - withOperand(() -> { - if (swap) { - calc.swap(); - } - calc.performOperation(op); - }); + if (hasOperand()) { + // TODO push operand first + } + // TODO perform operation, but swap first if needed } @FXML void handleOpAdd() { - performOperation(false, (op1, op2) -> op1 + op2); + // TODO } @FXML void handleOpSub() { - performOperation(true, (op1, op2) -> op1 - op2); + // TODO } @FXML void handleOpMult() { - performOperation(false, (op1, op2) -> op1 * op2); - } - - @FXML - void handleOpDiv() { - performOperation(true, (op1, op2) -> op1 / op2); - } - - @FXML - void handleOpSquareRoot() { - performOperation(op1 -> Math.sqrt(op1)); - } - - @FXML - void handlePi() { - withOperand(() -> calc.pushOperand(Math.PI)); - } - - public static void main(String[] args) { - System.out.println("\u221A"); + // TODO } } diff --git a/javafx-template/src/main/java/app/Calc.java b/javafx-template/src/main/java/app/Calc.java index 7200359..6102e31 100644 --- a/javafx-template/src/main/java/app/Calc.java +++ b/javafx-template/src/main/java/app/Calc.java @@ -13,41 +13,79 @@ public class Calc { operandStack.addAll(List.of(operands)); } + /** + * @return the number of operands on the stack + */ public int getOperandCount() { return operandStack.size(); } + /** + * Pushes a new operand into the n'th place from the top. + * @param n the place to push + * @param d the new operand + */ public void pushOperand(int n, double d) { operandStack.add(operandStack.size() - n, d); } + /** + * Pushes a new operand onto top of the stack. + * @param d the new operand + */ public void pushOperand(double d) { pushOperand(0, d); } + /** + * @param n the place (from the top) to peek + * @return the n'th operand from the top + */ public double peekOperand(int n) { return operandStack.get(operandStack.size() - n - 1); } + /** + * @return the top operand + */ public double peekOperand() { return peekOperand(0); } + /** + * Removes and returns the n'th operand from the top. + * @param n the place from the top to remove + * @return the n'th operand from the top + */ public double popOperand(int n) { return operandStack.remove(operandStack.size() - n - 1); } + /** + * Removes and returns the top operand. + * @return the top operand + */ public double popOperand() { return popOperand(0); } + /** + * Performs the provided operation in the top operand, and + * replaces it with the result. + * @param op the operation to perform + * @return the result of performing the operation + */ public double performOperation(UnaryOperator op) { - var op1 = popOperand(); - var result = op.apply(op1); - pushOperand(result); - return result; + // TODO + return 0.0; } + /** + * Performs the provided operation in the two topmost operands, and + * replaces them with the result. + * @param op the operation to perform + * @return the result of performing the operation + */ public double performOperation(BinaryOperator op) { var op1 = popOperand(); var op2 = popOperand(); @@ -56,14 +94,17 @@ public class Calc { return result; } + /** + * Swaps the two topmost operands. + */ public void swap() { - var op1 = popOperand(); - var op2 = popOperand(); - pushOperand(op1); - pushOperand(op2); + // TODO } + /** + * Duplicates the top operand. + */ public void dup() { - pushOperand(peekOperand()); + // TODO } } \ No newline at end of file diff --git a/javafx-template/src/main/resources/app/App.fxml b/javafx-template/src/main/resources/app/App.fxml index 4669ea8..41f4e4f 100644 --- a/javafx-template/src/main/resources/app/App.fxml +++ b/javafx-template/src/main/resources/app/App.fxml @@ -13,6 +13,7 @@