diff --git a/DukeData/tasks.txt b/DukeData/tasks.txt index 33b32f7a63..d68525d98f 100644 --- a/DukeData/tasks.txt +++ b/DukeData/tasks.txt @@ -1,2 +1,2 @@ T|1|borrow book -D|1|return book |2023-02-28 2359 +D|0|return book |2022-12-12 2359 diff --git a/src/main/java/duke/DialogBox.java b/src/main/java/duke/DialogBox.java index 44abed7dc1..7d7fbe50a2 100644 --- a/src/main/java/duke/DialogBox.java +++ b/src/main/java/duke/DialogBox.java @@ -1,47 +1,61 @@ package duke; +import java.io.IOException; +import java.util.Collections; + import javafx.collections.FXCollections; import javafx.collections.ObservableList; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; import javafx.geometry.Pos; import javafx.scene.Node; import javafx.scene.control.Label; +import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.HBox; +/** + * An example of a custom control using FXML. + * This control represents a dialog box consisting of an ImageView to represent the speaker's face and a label + * containing text from the speaker. + */ public class DialogBox extends HBox { - - private Label text; + @FXML + private Label dialog; + @FXML private ImageView displayPicture; - public DialogBox(Label l, ImageView iv) { - text = l; - displayPicture = iv; - - text.setWrapText(true); - displayPicture.setFitWidth(100.0); - displayPicture.setFitHeight(100.0); - - this.setAlignment(Pos.TOP_RIGHT); - this.getChildren().addAll(text, displayPicture); + private DialogBox(String text, Image img) { + try { + FXMLLoader fxmlLoader = new FXMLLoader(duke.MainWindow.class.getResource("/view/DialogBox.fxml")); + fxmlLoader.setController(this); + fxmlLoader.setRoot(this); + fxmlLoader.load(); + } catch (IOException e) { + e.printStackTrace(); + } + + dialog.setText(text); + displayPicture.setImage(img); } /** * Flips the dialog box such that the ImageView is on the left and text on the right. */ private void flip() { - this.setAlignment(Pos.TOP_LEFT); ObservableList tmp = FXCollections.observableArrayList(this.getChildren()); - FXCollections.reverse(tmp); - this.getChildren().setAll(tmp); + Collections.reverse(tmp); + getChildren().setAll(tmp); + setAlignment(Pos.TOP_LEFT); } - public static DialogBox getUserDialog(Label l, ImageView iv) { - return new DialogBox(l, iv); + public static DialogBox getUserDialog(String text, Image img) { + return new DialogBox(text, img); } - public static DialogBox getDukeDialog(Label l, ImageView iv) { - var db = new DialogBox(l, iv); + public static DialogBox getDukeDialog(String text, Image img) { + var db = new DialogBox(text, img); db.flip(); return db; } -} +} \ No newline at end of file diff --git a/src/main/java/duke/Duke.java b/src/main/java/duke/Duke.java index 0a7fa1fc84..0cbc4ef4b4 100644 --- a/src/main/java/duke/Duke.java +++ b/src/main/java/duke/Duke.java @@ -4,34 +4,12 @@ import java.io.IOException; -import javafx.application.Application; -import javafx.scene.Scene; -import javafx.scene.control.Button; -import javafx.scene.control.ScrollPane; -import javafx.scene.control.TextField; -import javafx.scene.layout.AnchorPane; -import javafx.scene.layout.VBox; -import javafx.stage.Stage; -import javafx.scene.layout.Region; -import javafx.scene.control.Label; - -import javafx.scene.image.Image; -import javafx.scene.image.ImageView; - -public class Duke extends Application { - - private Image user = new Image(this.getClass().getResourceAsStream("/images/DaUser.png")); - private Image duke = new Image(this.getClass().getResourceAsStream("/images/DaDuke.png")); +public class Duke { private Storage storage; private Ui ui; private TaskList taskList; - - private ScrollPane scrollPane; - private VBox dialogContainer; - private TextField userInput; - private Button sendButton; - private Scene scene; + private boolean isExit = false; public Duke() { this.storage = new Storage(); @@ -45,123 +23,34 @@ public Duke() { } } - public void run() { - ui.printGreet(); - boolean ongoing = true; - while (ongoing) { - try { - String fullCommand = ui.getCommand(); - Command c = Parser.stringToCommand(fullCommand); - c.execute(ui, storage, taskList); - ongoing = c.isExit(); - storage.saveTasks(taskList); - } catch (DukeException e) { - System.out.println(e.getMessage()); - } - } - } public static void main(String[] args) { - new Duke().run(); + new Duke(); } - @Override - public void start(Stage stage) { - //Step 1. Setting up required components - - //The container for the content of the chat to scroll. - scrollPane = new ScrollPane(); - dialogContainer = new VBox(); - scrollPane.setContent(dialogContainer); - - userInput = new TextField(); - sendButton = new Button("Send"); - - AnchorPane mainLayout = new AnchorPane(); - mainLayout.getChildren().addAll(scrollPane, userInput, sendButton); - - scene = new Scene(mainLayout); - - stage.setScene(scene); - stage.show(); - - stage.setTitle("Duke"); - stage.setResizable(false); - stage.setMinHeight(600.0); - stage.setMinWidth(400.0); - - mainLayout.setPrefSize(400.0, 600.0); - - scrollPane.setPrefSize(385, 535); - scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER); - scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS); - - scrollPane.setVvalue(1.0); - scrollPane.setFitToWidth(true); - - // You will need to import `javafx.scene.layout.Region` for this. - dialogContainer.setPrefHeight(Region.USE_COMPUTED_SIZE); - - userInput.setPrefWidth(325.0); - - sendButton.setPrefWidth(55.0); - - AnchorPane.setTopAnchor(scrollPane, 1.0); - - AnchorPane.setBottomAnchor(sendButton, 1.0); - AnchorPane.setRightAnchor(sendButton, 1.0); - - AnchorPane.setLeftAnchor(userInput , 1.0); - AnchorPane.setBottomAnchor(userInput, 1.0); - - sendButton.setOnMouseClicked((event) -> { - dialogContainer.getChildren().add(getDialogLabel(userInput.getText())); - userInput.clear(); - }); - - userInput.setOnAction((event) -> { - dialogContainer.getChildren().add(getDialogLabel(userInput.getText())); - userInput.clear(); - }); - - dialogContainer.heightProperty().addListener((observable) -> scrollPane.setVvalue(1.0)); - - //Part 3. Add functionality to handle user input. - sendButton.setOnMouseClicked((event) -> { - handleUserInput(); - }); - - userInput.setOnAction((event) -> { - handleUserInput(); - }); - // more code to be added here later - + public Ui getUi() { + return ui; } - private Label getDialogLabel(String text) { - // You will need to import `javafx.scene.control.Label`. - Label textToAdd = new Label(text); - textToAdd.setWrapText(true); - - return textToAdd; + public boolean getIsExit() { + return isExit; } - /** - * Iteration 2: - * Creates two dialog boxes, one echoing user input and the other containing Duke's reply and then appends them to - * the dialog container. Clears the user input after processing. - */ - private void handleUserInput() { - Label userText = new Label(userInput.getText()); - Label dukeText = new Label(getResponse(userInput.getText())); - dialogContainer.getChildren().addAll( - DialogBox.getUserDialog(userText, new ImageView(user)), - DialogBox.getDukeDialog(dukeText, new ImageView(duke)) - ); - userInput.clear(); + public void exitDuke() { + isExit = true; } - private String getResponse(String input) { - return "Duke heard: " + input; - } + public String getResponse(String input) { + try { + Command c = Parser.stringToCommand(input); + String to_Return = c.execute(ui, storage, taskList); + storage.saveTasks(taskList); + if (c.isExit()) { + this.exitDuke(); + } + return to_Return; + } catch (DukeException e) { + return ui.showError(e.getMessage()); + } + } } diff --git a/src/main/java/duke/Launcher.java b/src/main/java/duke/Launcher.java index 9438ec7d71..e4ef6b4628 100644 --- a/src/main/java/duke/Launcher.java +++ b/src/main/java/duke/Launcher.java @@ -7,6 +7,6 @@ */ public class Launcher { public static void main(String[] args) { - Application.launch(Duke.class, args); + Application.launch(Main.class, args); } } diff --git a/src/main/java/duke/Main.java b/src/main/java/duke/Main.java new file mode 100644 index 0000000000..db593707b5 --- /dev/null +++ b/src/main/java/duke/Main.java @@ -0,0 +1,31 @@ +package duke; + +import java.io.IOException; + +import javafx.application.Application; +import javafx.fxml.FXMLLoader; +import javafx.scene.Scene; +import javafx.scene.layout.AnchorPane; +import javafx.stage.Stage; + +/** + * A GUI for Duke using FXML. + */ +public class Main extends Application { + + private Duke duke = new Duke(); + + @Override + public void start(Stage stage) { + try { + FXMLLoader fxmlLoader = new FXMLLoader(Main.class.getResource("/view/MainWindow.fxml")); + AnchorPane ap = fxmlLoader.load(); + Scene scene = new Scene(ap); + stage.setScene(scene); + fxmlLoader.getController().setDuke(duke); + stage.show(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/duke/MainWindow.java b/src/main/java/duke/MainWindow.java new file mode 100644 index 0000000000..b45b740a84 --- /dev/null +++ b/src/main/java/duke/MainWindow.java @@ -0,0 +1,59 @@ +package duke; + +import javafx.fxml.FXML; +import javafx.scene.control.Button; +import javafx.scene.control.ScrollPane; +import javafx.scene.control.TextField; +import javafx.scene.image.Image; +import javafx.scene.layout.AnchorPane; +import javafx.scene.layout.VBox; +import javafx.application.Platform; + +/** + * Controller for MainWindow. Provides the layout for the other controls. + */ +public class MainWindow extends AnchorPane { + @FXML + private ScrollPane scrollPane; + @FXML + private VBox dialogContainer; + @FXML + private TextField userInput; + @FXML + private Button sendButton; + + private Duke duke; + + private Image userImage = new Image(this.getClass().getResourceAsStream("/images/DaUser.png")); + private Image dukeImage = new Image(this.getClass().getResourceAsStream("/images/DaDuke.png")); + + @FXML + public void initialize() { + scrollPane.vvalueProperty().bind(dialogContainer.heightProperty()); + } + + public void setDuke(Duke d) { + duke = d; + dialogContainer.getChildren().add(DialogBox.getDukeDialog(this.duke.getUi().printGreet(), + dukeImage)); + } + + /** + * Creates two dialog boxes, one echoing user input and the other containing Duke's reply and then appends them to + * the dialog container. Clears the user input after processing. + */ + @FXML + private void handleUserInput() { + String input = userInput.getText(); + String response = duke.getResponse(input); + dialogContainer.getChildren().addAll( + DialogBox.getUserDialog(input, userImage), + DialogBox.getDukeDialog(response, dukeImage) + ); + userInput.clear(); + if (duke.getIsExit()) { + Platform.exit(); + System.exit(0); + } + } +} diff --git a/src/main/java/duke/TaskList.java b/src/main/java/duke/TaskList.java index 93fa19aa95..fe92ef4da5 100644 --- a/src/main/java/duke/TaskList.java +++ b/src/main/java/duke/TaskList.java @@ -88,14 +88,18 @@ public Task deleteTask(int index) throws DukeException { /** * Prints all the tasks in the TaskList. */ - public void printTasks() throws DukeException { + public String printTasks() throws DukeException { if (num_tasks == 0) { throw new DukeException("You currently have no tasks mate!"); } + StringBuilder sb = new StringBuilder(); for (int i = 0; i < num_tasks; i++) { Task ref = tasks.get(i); - System.out.println((i + 1) + "." + ref.toString()); + String taskToPrint = String.format("%d.%s\n", (i + 1) , ref.toString()); + sb.append(taskToPrint); } + + return sb.toString(); } public ArrayList getTasksByKeyWord(String keyWord) throws DukeException { diff --git a/src/main/java/duke/Ui.java b/src/main/java/duke/Ui.java index 34bcee29bf..1b03eb9fab 100644 --- a/src/main/java/duke/Ui.java +++ b/src/main/java/duke/Ui.java @@ -2,6 +2,7 @@ import duke.tasks.Task; +import javax.print.DocFlavor; import java.util.Scanner; import java.util.ArrayList; @@ -33,22 +34,24 @@ public String getCommand() { * * @param e_message DukeException's error messages. */ - public void showError(String e_message) { - System.out.println(e_message); + public String showError(String e_message) { + return e_message; } /** * Greets the user. + * + * @return */ - public void printGreet() { - System.out.println(GREET_MSG); + public String printGreet() { + return GREET_MSG; } /** * Says goodbye to the user. */ - public void printBye() { - System.out.println(BYE_MSG); + public String printBye() { + return BYE_MSG; } @@ -57,13 +60,12 @@ public void printBye() { * * @param taskList his current TaskList. */ - public void showList(TaskList taskList) { + public String showList(TaskList taskList) throws DukeException { try { - taskList.printTasks(); + return taskList.printTasks(); } catch (DukeException e) { - this.showError(e.getMessage()); + return this.showError(e.getMessage()); } - System.out.println(""); } /** @@ -71,8 +73,8 @@ public void showList(TaskList taskList) { * * @param markedTask task that is to be marked by the user */ - public void printMarkTask(Task markedTask) { - System.out.println("Nice! I have marked this task as Done:\n" + markedTask.toString() + "\n"); + public String printMarkTask(Task markedTask) { + return "Nice! I have marked this task as Done:\n" + markedTask.toString() + "\n"; } /** @@ -82,9 +84,8 @@ public void printMarkTask(Task markedTask) { * @param num_tasks number of total tasks after addition. * @param to_add the task that's to be added . */ - public void printAddTask(Task to_add, Integer num_tasks) { - System.out.println(ADD_MSG + to_add.toString()); - System.out.println("You currently have " + num_tasks + " tasks in this list!\n"); + public String printAddTask(Task to_add, Integer num_tasks) { + return ADD_MSG + to_add.toString() + "\nYou currently have " + num_tasks + " tasks in this list!\n"; } /** @@ -92,9 +93,9 @@ public void printAddTask(Task to_add, Integer num_tasks) { * * @param unmarkedTask the task thats been unmarked by user. */ - public void printUnmarkTask(Task unmarkedTask) { - System.out.println("Ok! I have marked this task as not done yet:\n" + - unmarkedTask.toString() + "\n"); + public String printUnmarkTask(Task unmarkedTask) { + return "Ok! I have marked this task as not done yet:\n" + + unmarkedTask.toString() + "\n"; } /** @@ -103,19 +104,20 @@ public void printUnmarkTask(Task unmarkedTask) { * @param removedTask the tasks that's removed. * @param num_tasks number of total tasks after deletion. */ - public void printDeleteTask(Task removedTask, Integer num_tasks) { - System.out.println("Noted!I have deleted the task for you:\n " + + public String printDeleteTask(Task removedTask, Integer num_tasks) { + return "Noted!I have deleted the task for you:\n " + removedTask.toString() + "\nyou currently have " + num_tasks + - " tasks in this list!\n"); + " tasks in this list!\n"; } - public void printTaskByKeyWord(TaskList taskList, String keyWord) throws DukeException { + public String printTaskByKeyWord(TaskList taskList, String keyWord) throws DukeException { ArrayList allFoundTasks = taskList.getTasksByKeyWord(keyWord); - System.out.println("Here are the matching tasks in your list:"); int index = 1; + StringBuilder sb = new StringBuilder("Here are the matching tasks in your list:\n"); for (Task task : allFoundTasks) { - System.out.println(String.format("%d.%s", index, task.toString())); + sb.append(String.format("%d.%s\n", index, task.toString())); index++; } + return sb.toString(); } } diff --git a/src/main/java/duke/command/AddCommand.java b/src/main/java/duke/command/AddCommand.java index c4852e80ae..489ed93d89 100644 --- a/src/main/java/duke/command/AddCommand.java +++ b/src/main/java/duke/command/AddCommand.java @@ -16,9 +16,9 @@ public AddCommand(String textCmd) { } @Override - public void execute(Ui ui, Storage storage, TaskList taskList) throws DukeException { + public String execute(Ui ui, Storage storage, TaskList taskList) throws DukeException { Task to_add = taskAssigner.assignTask(textCmd); taskList.add(to_add); - ui.printAddTask(to_add, taskList.getNumTasks()); + return ui.printAddTask(to_add, taskList.getNumTasks()); } } diff --git a/src/main/java/duke/command/Command.java b/src/main/java/duke/command/Command.java index a44ac0a721..6146e71cc8 100644 --- a/src/main/java/duke/command/Command.java +++ b/src/main/java/duke/command/Command.java @@ -11,10 +11,10 @@ public abstract class Command { public Command(String textCmd) { this.textCmd = textCmd; - this.isExit = true; + this.isExit = false; } - public void execute(Ui ui, Storage storage, TaskList taskList) throws DukeException {} + public abstract String execute(Ui ui, Storage storage, TaskList taskList) throws DukeException; public boolean isExit() { return isExit; } diff --git a/src/main/java/duke/command/DeleteCommand.java b/src/main/java/duke/command/DeleteCommand.java index f868e8aa16..ae066d17c8 100644 --- a/src/main/java/duke/command/DeleteCommand.java +++ b/src/main/java/duke/command/DeleteCommand.java @@ -13,9 +13,9 @@ public DeleteCommand(String textCmd) { super(textCmd); } - public void execute(Ui ui, Storage storage, TaskList taskList) throws DukeException { + public String execute(Ui ui, Storage storage, TaskList taskList) throws DukeException { Task removedTask = taskList.deleteTask( Parser.stringToInt(textCmd.substring(7))); - ui.printDeleteTask(removedTask, taskList.getNumTasks()); + return ui.printDeleteTask(removedTask, taskList.getNumTasks()); } } diff --git a/src/main/java/duke/command/ErrorCommand.java b/src/main/java/duke/command/ErrorCommand.java index 265a11180f..8ab1df82ff 100644 --- a/src/main/java/duke/command/ErrorCommand.java +++ b/src/main/java/duke/command/ErrorCommand.java @@ -11,7 +11,7 @@ public ErrorCommand(String textCmd) { } @Override - public void execute(Ui ui, Storage storage, TaskList taskList) throws DukeException { + public String execute(Ui ui, Storage storage, TaskList taskList) throws DukeException { throw new DukeException("I have no idea whats that command mate!\n"); } } diff --git a/src/main/java/duke/command/ExitCommand.java b/src/main/java/duke/command/ExitCommand.java index 732489aba8..01b73c9371 100644 --- a/src/main/java/duke/command/ExitCommand.java +++ b/src/main/java/duke/command/ExitCommand.java @@ -12,8 +12,8 @@ public ExitCommand(String textCmd) { } @Override - public void execute(Ui ui, Storage storage, TaskList taskList) throws DukeException { - this.isExit = false; - ui.printBye(); + public String execute(Ui ui, Storage storage, TaskList taskList) throws DukeException { + this.isExit = true; + return ui.printBye(); } } diff --git a/src/main/java/duke/command/FindCommand.java b/src/main/java/duke/command/FindCommand.java index 8bf3b7820b..2b5c746525 100644 --- a/src/main/java/duke/command/FindCommand.java +++ b/src/main/java/duke/command/FindCommand.java @@ -15,7 +15,7 @@ public FindCommand(String textCmd) { } @Override - public void execute(Ui ui, Storage storage, TaskList taskList) throws DukeException { + public String execute(Ui ui, Storage storage, TaskList taskList) throws DukeException { String[] commandSplit = textCmd.split(" "); String typeOfCommand = commandSplit[0]; @@ -29,6 +29,6 @@ public void execute(Ui ui, Storage storage, TaskList taskList) throws DukeExcept } String keyWord = textCmd.substring(5); - ui.printTaskByKeyWord(taskList, keyWord); + return ui.printTaskByKeyWord(taskList, keyWord); } } diff --git a/src/main/java/duke/command/ListCommand.java b/src/main/java/duke/command/ListCommand.java index 2db7c77dae..aca29ea342 100644 --- a/src/main/java/duke/command/ListCommand.java +++ b/src/main/java/duke/command/ListCommand.java @@ -10,7 +10,7 @@ public ListCommand(String textCmd) { super(textCmd); } - public void execute(Ui ui, Storage storage, TaskList taskList) throws DukeException { - ui.showList(taskList); + public String execute(Ui ui, Storage storage, TaskList taskList) throws DukeException { + return ui.showList(taskList); } } diff --git a/src/main/java/duke/command/MarkCommand.java b/src/main/java/duke/command/MarkCommand.java index ffe7193606..90affb1982 100644 --- a/src/main/java/duke/command/MarkCommand.java +++ b/src/main/java/duke/command/MarkCommand.java @@ -13,8 +13,8 @@ public MarkCommand(String textCmd) { } @Override - public void execute(Ui ui, Storage storage, TaskList taskList) throws DukeException { + public String execute(Ui ui, Storage storage, TaskList taskList) throws DukeException { Task markedTask = taskList.markTask(Parser.stringToInt(textCmd.substring(5))); - ui.printMarkTask(markedTask); + return ui.printMarkTask(markedTask); } } diff --git a/src/main/java/duke/command/UnmarkCommand.java b/src/main/java/duke/command/UnmarkCommand.java index 93be9324f7..7395f8b5ce 100644 --- a/src/main/java/duke/command/UnmarkCommand.java +++ b/src/main/java/duke/command/UnmarkCommand.java @@ -13,9 +13,8 @@ public UnmarkCommand(String textCmd) { } @Override - public void execute(Ui ui, Storage storage, TaskList taskList) throws DukeException { + public String execute(Ui ui, Storage storage, TaskList taskList) throws DukeException { Task unmarkedTask = taskList.unmarkTask(Parser.stringToInt(textCmd.substring(7))); - ui.printUnmarkTask(unmarkedTask); - + return ui.printUnmarkTask(unmarkedTask); } } diff --git a/src/main/resources/images/DaDuke.png b/src/main/resources/images/DaDuke.png index d893658717..836034c645 100644 Binary files a/src/main/resources/images/DaDuke.png and b/src/main/resources/images/DaDuke.png differ diff --git a/src/main/resources/images/DaUser.png b/src/main/resources/images/DaUser.png index 3c82f45461..051cffb558 100644 Binary files a/src/main/resources/images/DaUser.png and b/src/main/resources/images/DaUser.png differ diff --git a/src/main/resources/view/DialogBox.fxml b/src/main/resources/view/DialogBox.fxml new file mode 100644 index 0000000000..e433809947 --- /dev/null +++ b/src/main/resources/view/DialogBox.fxml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/view/MainWindow.fxml b/src/main/resources/view/MainWindow.fxml new file mode 100644 index 0000000000..832f84382e --- /dev/null +++ b/src/main/resources/view/MainWindow.fxml @@ -0,0 +1,19 @@ + + + + + + + + + + + +