diff --git a/src/main/java/DialogBox.java b/src/main/java/DialogBox.java new file mode 100644 index 0000000000..cc2ffc5a7a --- /dev/null +++ b/src/main/java/DialogBox.java @@ -0,0 +1,51 @@ +package duke; + +import javafx.geometry.Pos; +import javafx.scene.control.Label; +import javafx.scene.image.ImageView; +import javafx.scene.layout.HBox; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.geometry.Pos; +import javafx.scene.Node; +import javafx.scene.control.Label; +import javafx.scene.image.ImageView; +import javafx.scene.layout.HBox; + +public class DialogBox extends HBox { + + private Label text; + 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); + } + + /** + * 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); + } + + public static DialogBox getUserDialog(Label l, ImageView iv) { + return new DialogBox(l, iv); + } + + public static DialogBox getDukeDialog(Label l, ImageView iv) { + var db = new DialogBox(l, iv); + db.flip(); + return db; + } +} \ No newline at end of file diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index ed7e4c6078..215846b07a 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -1,23 +1,123 @@ package duke; +import javafx.application.Application; +import javafx.scene.Scene; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.control.ScrollPane; +import javafx.scene.control.TextField; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.layout.AnchorPane; +import javafx.scene.layout.Region; +import javafx.scene.layout.VBox; +import javafx.stage.Stage; + + /** * Application class for Duke. */ -public class Duke { +public class Duke extends Application { + private ScrollPane scrollPane; + private VBox dialogContainer; + private TextField userInput; + private Button sendButton; + private Scene scene; + private Image user = new Image(this.getClass().getResourceAsStream("/resources/DaUser.png")); + private Image duke = new Image(this.getClass().getResourceAsStream("/resources/DaDuke.png")); + + private Main main; + /** * Main method for Duke. * * @param args Arguments entered when main method is executed. */ public static void main(String[] args) { - String logo = " ____ _ \n" - + "| _ \\ _ _| | _____ \n" - + "| | | | | | | |/ / _ \\\n" - + "| |_| | |_| | < __/\n" - + "|____/ \\__,_|_|\\_\\___|\n"; - System.out.println("Hello from\n" + logo); - - Main main = new Main("../../../data/duke.txt"); - main.run(); + Main duke = new Main("data/duke.txt"); + duke.run(); + } + + @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(); + + //Step 2. Formatting the window to look as expected + 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); + + main = new Main("data/duke.txt"); + + //Part 3. Add functionality to handle user input. + sendButton.setOnMouseClicked((event) -> { + handleUserInput(); + }); + + userInput.setOnAction((event) -> { + handleUserInput(); + }); + //Scroll down to the end every time dialogContainer's height changes. + dialogContainer.heightProperty().addListener((observable) -> scrollPane.setVvalue(1.0)); + } + + /** + * 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(); + } + + private String getResponse(String input) { + return main.step(input); } } diff --git a/src/main/java/Launcher.java b/src/main/java/Launcher.java new file mode 100644 index 0000000000..cef3c40d17 --- /dev/null +++ b/src/main/java/Launcher.java @@ -0,0 +1,12 @@ +package duke; + +import javafx.application.Application; + +/** + * A launcher class to workaround classpath issues. + */ +public class Launcher { + public static void main(String[] args) { + Application.launch(Duke.class, args); + } +} \ No newline at end of file diff --git a/src/main/java/Main.java b/src/main/java/Main.java index d99167a517..e0cb4d3010 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -1,40 +1,30 @@ package duke; -import duke.DukeException; -import duke.Parser; -import duke.Ui; -import duke.Storage; -import duke.TaskList; +import duke.exception.DukeException; +import duke.util.Parser; +import duke.util.Ui; +import duke.util.Storage; +import duke.task.TaskList; import duke.command.Command; -import java.util.Scanner; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.util.ArrayList; -/** - * Main class of Duke. - * Contains run() method. - */ public class Main { private Storage storage; private TaskList tasks; private Ui ui; /** - * Constructor of Main class. + * Constructor of Duke class. * * @param filePath Path to text file where save data is stored. */ public Main(String filePath) { - ui = new Ui(); - storage = new Storage(filePath); + this.ui = new Ui(); + this.storage = new Storage(filePath); try { - tasks = storage.load(); + this.tasks = this.storage.load(); } catch (DukeException e) { - ui.showLoadingError(); - tasks = new TaskList(); + this.ui.showLoadingError(); + this.tasks = new TaskList(); } } @@ -42,6 +32,12 @@ public Main(String filePath) { * Run method of Duke. */ public void run() { + String logo = " ____ _ \n" + + "| _ \\ _ _| | _____ \n" + + "| | | | | | | |/ / _ \\\n" + + "| |_| | |_| | < __/\n" + + "|____/ \\__,_|_|\\_\\___|\n"; + System.out.println("Hello from\n" + logo); this.ui.showWelcome(); boolean isExit = false; @@ -50,10 +46,22 @@ public void run() { String fullCommand = ui.readCommand(); Command c = Parser.parse(fullCommand); c.execute(tasks, ui, storage); + storage.save(tasks); isExit = c.isExit(); } catch (DukeException e) { ui.showError(e.getMessage()); } } } + + public String step(String input) { + try { + Command c = Parser.parse(input); + c.execute(tasks, ui, storage); + this.storage.save(tasks); + } catch(DukeException e) { + ui.showError(e.getMessage()); + } + return this.ui.getOutput(); + } } \ No newline at end of file diff --git a/src/main/java/AddCommand.java b/src/main/java/command/AddCommand.java similarity index 91% rename from src/main/java/AddCommand.java rename to src/main/java/command/AddCommand.java index 007a56f8f1..91533794a3 100644 --- a/src/main/java/AddCommand.java +++ b/src/main/java/command/AddCommand.java @@ -1,10 +1,10 @@ package duke.command; -import duke.DukeException; -import duke.Parser; -import duke.Ui; -import duke.Storage; -import duke.TaskList; +import duke.exception.DukeException; +import duke.util.Parser; +import duke.util.Ui; +import duke.util.Storage; +import duke.task.TaskList; import duke.task.Task; /** diff --git a/src/main/java/Command.java b/src/main/java/command/Command.java similarity index 89% rename from src/main/java/Command.java rename to src/main/java/command/Command.java index 9a631e0401..8d5aa357c4 100644 --- a/src/main/java/Command.java +++ b/src/main/java/command/Command.java @@ -1,9 +1,9 @@ package duke.command; -import duke.TaskList; -import duke.Ui; -import duke.Storage; -import duke.DukeException; +import duke.task.TaskList; +import duke.util.Ui; +import duke.util.Storage; +import duke.exception.DukeException; /** * Abstract Command class that contains execute() for diff --git a/src/main/java/DeleteCommand.java b/src/main/java/command/DeleteCommand.java similarity index 92% rename from src/main/java/DeleteCommand.java rename to src/main/java/command/DeleteCommand.java index f092f56dbd..8b64cd95e5 100644 --- a/src/main/java/DeleteCommand.java +++ b/src/main/java/command/DeleteCommand.java @@ -1,10 +1,10 @@ package duke.command; -import duke.DukeException; -import duke.Parser; -import duke.Ui; -import duke.Storage; -import duke.TaskList; +import duke.exception.DukeException; +import duke.util.Parser; +import duke.util.Ui; +import duke.util.Storage; +import duke.task.TaskList; import duke.task.Task; /** diff --git a/src/main/java/DoneCommand.java b/src/main/java/command/DoneCommand.java similarity index 92% rename from src/main/java/DoneCommand.java rename to src/main/java/command/DoneCommand.java index 722b9090be..3cfef136f1 100644 --- a/src/main/java/DoneCommand.java +++ b/src/main/java/command/DoneCommand.java @@ -1,10 +1,10 @@ package duke.command; -import duke.DukeException; -import duke.Parser; -import duke.Ui; -import duke.Storage; -import duke.TaskList; +import duke.exception.DukeException; +import duke.util.Parser; +import duke.util.Ui; +import duke.util.Storage; +import duke.task.TaskList; import duke.task.Task; /** diff --git a/src/main/java/ExitCommand.java b/src/main/java/command/ExitCommand.java similarity index 94% rename from src/main/java/ExitCommand.java rename to src/main/java/command/ExitCommand.java index 4bda058632..bf8712bafb 100644 --- a/src/main/java/ExitCommand.java +++ b/src/main/java/command/ExitCommand.java @@ -1,8 +1,8 @@ package duke.command; -import duke.Ui; -import duke.Storage; -import duke.TaskList; +import duke.util.Ui; +import duke.util.Storage; +import duke.task.TaskList; /** * Command containing method for exiting program. diff --git a/src/main/java/FindCommand.java b/src/main/java/command/FindCommand.java similarity index 92% rename from src/main/java/FindCommand.java rename to src/main/java/command/FindCommand.java index b60a6f1b19..de85afba73 100644 --- a/src/main/java/FindCommand.java +++ b/src/main/java/command/FindCommand.java @@ -1,10 +1,10 @@ package duke.command; -import duke.DukeException; -import duke.Parser; -import duke.Ui; -import duke.Storage; -import duke.TaskList; +import duke.exception.DukeException; +import duke.util.Parser; +import duke.util.Ui; +import duke.util.Storage; +import duke.task.TaskList; import duke.task.Task; /** diff --git a/src/main/java/ListCommand.java b/src/main/java/command/ListCommand.java similarity index 94% rename from src/main/java/ListCommand.java rename to src/main/java/command/ListCommand.java index 020fd4e81e..a5a500f038 100644 --- a/src/main/java/ListCommand.java +++ b/src/main/java/command/ListCommand.java @@ -1,8 +1,8 @@ package duke.command; -import duke.Ui; -import duke.Storage; -import duke.TaskList; +import duke.util.Ui; +import duke.util.Storage; +import duke.task.TaskList; /** * Command containing method for listing Tasks in TaskList. diff --git a/src/main/java/data/duke.txt b/src/main/java/data/duke.txt new file mode 100644 index 0000000000..026c0d8e3c Binary files /dev/null and b/src/main/java/data/duke.txt differ diff --git a/src/main/java/duke/DialogBox.class b/src/main/java/duke/DialogBox.class new file mode 100644 index 0000000000..8de21724db Binary files /dev/null and b/src/main/java/duke/DialogBox.class differ diff --git a/src/main/java/duke/Duke.class b/src/main/java/duke/Duke.class index e6d1e04582..20606bd93e 100644 Binary files a/src/main/java/duke/Duke.class and b/src/main/java/duke/Duke.class differ diff --git a/src/main/java/duke/DukeException.class b/src/main/java/duke/DukeException.class deleted file mode 100644 index 2fc7a39c06..0000000000 Binary files a/src/main/java/duke/DukeException.class and /dev/null differ diff --git a/src/main/java/duke/Launcher.class b/src/main/java/duke/Launcher.class new file mode 100644 index 0000000000..7864f47338 Binary files /dev/null and b/src/main/java/duke/Launcher.class differ diff --git a/src/main/java/duke/Main.class b/src/main/java/duke/Main.class index 5801d5d62e..5d6a9497bf 100644 Binary files a/src/main/java/duke/Main.class and b/src/main/java/duke/Main.class differ diff --git a/src/main/java/duke/Parser.class b/src/main/java/duke/Parser.class deleted file mode 100644 index f8239ddc8d..0000000000 Binary files a/src/main/java/duke/Parser.class and /dev/null differ diff --git a/src/main/java/duke/Ui.class b/src/main/java/duke/Ui.class deleted file mode 100644 index da44202073..0000000000 Binary files a/src/main/java/duke/Ui.class and /dev/null differ diff --git a/src/main/java/duke/command/AddCommand.class b/src/main/java/duke/command/AddCommand.class index 81e45b6b41..7973b4cdcd 100644 Binary files a/src/main/java/duke/command/AddCommand.class and b/src/main/java/duke/command/AddCommand.class differ diff --git a/src/main/java/duke/command/Command.class b/src/main/java/duke/command/Command.class index cdc2caefdd..61eccb1dc2 100644 Binary files a/src/main/java/duke/command/Command.class and b/src/main/java/duke/command/Command.class differ diff --git a/src/main/java/duke/command/DeleteCommand.class b/src/main/java/duke/command/DeleteCommand.class index 175bff6e33..71cf32e34a 100644 Binary files a/src/main/java/duke/command/DeleteCommand.class and b/src/main/java/duke/command/DeleteCommand.class differ diff --git a/src/main/java/duke/command/DoneCommand.class b/src/main/java/duke/command/DoneCommand.class index ccf61be833..2296ecbc43 100644 Binary files a/src/main/java/duke/command/DoneCommand.class and b/src/main/java/duke/command/DoneCommand.class differ diff --git a/src/main/java/duke/command/ExitCommand.class b/src/main/java/duke/command/ExitCommand.class index c974318209..667e8cc4ba 100644 Binary files a/src/main/java/duke/command/ExitCommand.class and b/src/main/java/duke/command/ExitCommand.class differ diff --git a/src/main/java/duke/command/FindCommand.class b/src/main/java/duke/command/FindCommand.class index 791301e8d1..1148b71e9f 100644 Binary files a/src/main/java/duke/command/FindCommand.class and b/src/main/java/duke/command/FindCommand.class differ diff --git a/src/main/java/duke/command/ListCommand.class b/src/main/java/duke/command/ListCommand.class index cee7c16ab2..da52629dc3 100644 Binary files a/src/main/java/duke/command/ListCommand.class and b/src/main/java/duke/command/ListCommand.class differ diff --git a/src/main/java/duke/exception/DukeException.class b/src/main/java/duke/exception/DukeException.class new file mode 100644 index 0000000000..98e508329b Binary files /dev/null and b/src/main/java/duke/exception/DukeException.class differ diff --git a/src/main/java/duke/TaskList.class b/src/main/java/duke/task/TaskList.class similarity index 91% rename from src/main/java/duke/TaskList.class rename to src/main/java/duke/task/TaskList.class index f1b1b4c32f..734713d3e8 100644 Binary files a/src/main/java/duke/TaskList.class and b/src/main/java/duke/task/TaskList.class differ diff --git a/src/main/java/duke/util/Parser.class b/src/main/java/duke/util/Parser.class new file mode 100644 index 0000000000..bccfa71e57 Binary files /dev/null and b/src/main/java/duke/util/Parser.class differ diff --git a/src/main/java/duke/Storage.class b/src/main/java/duke/util/Storage.class similarity index 58% rename from src/main/java/duke/Storage.class rename to src/main/java/duke/util/Storage.class index 60ddbe3a2c..78d564f963 100644 Binary files a/src/main/java/duke/Storage.class and b/src/main/java/duke/util/Storage.class differ diff --git a/src/main/java/duke/util/Ui.class b/src/main/java/duke/util/Ui.class new file mode 100644 index 0000000000..c4b4ba472a Binary files /dev/null and b/src/main/java/duke/util/Ui.class differ diff --git a/src/main/java/DukeException.java b/src/main/java/exception/DukeException.java similarity index 92% rename from src/main/java/DukeException.java rename to src/main/java/exception/DukeException.java index 347503193f..daa62a2058 100644 --- a/src/main/java/DukeException.java +++ b/src/main/java/exception/DukeException.java @@ -1,4 +1,4 @@ -package duke; +package duke.exception; /** * Exception class for Duke. diff --git a/src/main/java/resources/DaDuke.png b/src/main/java/resources/DaDuke.png new file mode 100644 index 0000000000..d893658717 Binary files /dev/null and b/src/main/java/resources/DaDuke.png differ diff --git a/src/main/java/resources/DaUser.png b/src/main/java/resources/DaUser.png new file mode 100644 index 0000000000..3c82f45461 Binary files /dev/null and b/src/main/java/resources/DaUser.png differ diff --git a/src/main/java/Deadline.java b/src/main/java/task/Deadline.java similarity index 100% rename from src/main/java/Deadline.java rename to src/main/java/task/Deadline.java diff --git a/src/main/java/Event.java b/src/main/java/task/Event.java similarity index 100% rename from src/main/java/Event.java rename to src/main/java/task/Event.java diff --git a/src/main/java/Task.java b/src/main/java/task/Task.java similarity index 100% rename from src/main/java/Task.java rename to src/main/java/task/Task.java diff --git a/src/main/java/TaskList.java b/src/main/java/task/TaskList.java similarity index 98% rename from src/main/java/TaskList.java rename to src/main/java/task/TaskList.java index 63d565ec89..b5a2b86af3 100644 --- a/src/main/java/TaskList.java +++ b/src/main/java/task/TaskList.java @@ -1,4 +1,4 @@ -package duke; +package duke.task; import duke.task.Task; import java.io.Serializable; diff --git a/src/main/java/Todo.java b/src/main/java/task/Todo.java similarity index 100% rename from src/main/java/Todo.java rename to src/main/java/task/Todo.java diff --git a/src/main/java/Parser.java b/src/main/java/util/Parser.java similarity index 77% rename from src/main/java/Parser.java rename to src/main/java/util/Parser.java index 2e00806377..990338c5b5 100644 --- a/src/main/java/Parser.java +++ b/src/main/java/util/Parser.java @@ -1,4 +1,4 @@ -package duke; +package duke.util; import duke.command.Command; import duke.command.AddCommand; @@ -11,8 +11,9 @@ import duke.task.Todo; import duke.task.Deadline; import duke.task.Event; -import duke.DukeException; +import duke.exception.DukeException; import java.util.HashMap; +import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; @@ -116,34 +117,37 @@ public static Task parseTask(String input) throws DukeException { String type = words[0]; String info = input.substring((type + " ").length()); - switch (type) { - case "todo": - if (info.equals("")) { - throw new DukeException("☹ OOPS!!! The description of a todo cannot be empty."); - } - return new Todo(info); - case "deadline": - String[] args = info.split("/by"); - String description = args[0].trim(); - Date date; - try { - date = dateFormatter.parse(args[1].trim()); - } catch (Exception e) { - throw new DukeException("☹ OOPS!!! Incorrect date format."); - } - return new Deadline(description, date); - case "event": - args = info.split("/at"); - description = args[0].trim(); - try { - date = dateFormatter.parse(args[1].trim()); - } catch (Exception e) { - throw new DukeException("☹ OOPS!!! Incorrect date format."); + try { + switch (type) { + case "todo": + if (info.equals("")) { + throw new DukeException("☹ OOPS!!! The description of a todo cannot be empty."); + } + return new Todo(info); + case "deadline": + String[] args = info.split("/by"); + String description = args[0].trim(); + Date date; + try { + date = dateFormatter.parse(args[1].trim()); + } catch (ParseException e) { + throw new DukeException("☹ OOPS!!! Incorrect date format."); + } + return new Deadline(description, date); + case "event": + args = info.split("/at"); + description = args[0].trim(); + try { + date = dateFormatter.parse(args[1].trim()); + } catch (ParseException e) { + throw new DukeException("☹ OOPS!!! Incorrect date format."); + } + return new Event(description, date); } - return new Event(description, date); - default: + } catch (IndexOutOfBoundsException e) { throw new DukeException("Invalid task input."); } + throw new DukeException("Invalid task input."); } /** diff --git a/src/main/java/Storage.java b/src/main/java/util/Storage.java similarity index 94% rename from src/main/java/Storage.java rename to src/main/java/util/Storage.java index bb42cafd25..b99057110f 100644 --- a/src/main/java/Storage.java +++ b/src/main/java/util/Storage.java @@ -1,7 +1,7 @@ -package duke; +package duke.util; -import duke.TaskList; -import duke.DukeException; +import duke.task.TaskList; +import duke.exception.DukeException; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; diff --git a/src/main/java/Ui.java b/src/main/java/util/Ui.java similarity index 91% rename from src/main/java/Ui.java rename to src/main/java/util/Ui.java index 770390eef6..c22ca0bea3 100644 --- a/src/main/java/Ui.java +++ b/src/main/java/util/Ui.java @@ -1,4 +1,4 @@ -package duke; +package duke.util; import java.util.Scanner; @@ -6,6 +6,8 @@ * Ui class that handles output of Duke to the console. */ public class Ui { + public String buffer; + String format(String output) { return " ____________________________________________________________\n" + indent(output) @@ -27,9 +29,14 @@ String indent(String output) { * Prints output of Duke. */ public void printResponse(String output) { + this.buffer = format(output); System.out.println(format(output)); } + public String getOutput() { + return this.buffer; + } + /** * Reads input of user from the console. *