Skip to content

Commit

Permalink
Add JavaFX GUI
Browse files Browse the repository at this point in the history
  • Loading branch information
junweimoo committed Sep 9, 2022
1 parent 5f24147 commit 05ec52e
Show file tree
Hide file tree
Showing 19 changed files with 278 additions and 76 deletions.
22 changes: 16 additions & 6 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
plugins {
id 'java'
id 'application'
id 'org.openjfx.javafxplugin' version '0.0.10'
id 'com.github.johnrengelman.shadow' version '5.1.0'
}

Expand All @@ -11,6 +12,20 @@ repositories {
dependencies {
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.5.0'
testRuntimeOnly group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.5.0'

String javaFxVersion = '11'
implementation group: 'org.openjfx', name: 'javafx-base', version: javaFxVersion, classifier: 'win'
implementation group: 'org.openjfx', name: 'javafx-base', version: javaFxVersion, classifier: 'mac'
implementation group: 'org.openjfx', name: 'javafx-base', version: javaFxVersion, classifier: 'linux'
implementation group: 'org.openjfx', name: 'javafx-controls', version: javaFxVersion, classifier: 'win'
implementation group: 'org.openjfx', name: 'javafx-controls', version: javaFxVersion, classifier: 'mac'
implementation group: 'org.openjfx', name: 'javafx-controls', version: javaFxVersion, classifier: 'linux'
implementation group: 'org.openjfx', name: 'javafx-fxml', version: javaFxVersion, classifier: 'win'
implementation group: 'org.openjfx', name: 'javafx-fxml', version: javaFxVersion, classifier: 'mac'
implementation group: 'org.openjfx', name: 'javafx-fxml', version: javaFxVersion, classifier: 'linux'
implementation group: 'org.openjfx', name: 'javafx-graphics', version: javaFxVersion, classifier: 'win'
implementation group: 'org.openjfx', name: 'javafx-graphics', version: javaFxVersion, classifier: 'mac'
implementation group: 'org.openjfx', name: 'javafx-graphics', version: javaFxVersion, classifier: 'linux'
}

test {
Expand All @@ -28,12 +43,7 @@ test {
}

application {
mainClassName = "duke.Duke"
}

shadowJar {
archiveBaseName = "duke"
archiveClassifier = null
mainClassName = "duke.Launcher"
}

run{
Expand Down
1 change: 1 addition & 0 deletions savedata.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
[D] | 1 | say bye | 2022-09-01
[E] | 0 | jellyfish catching | 2022-09-02
[T] | 1 | catch jellyfish
[T] | 0 | say DUKE!
58 changes: 31 additions & 27 deletions src/main/java/duke/Duke.java
Original file line number Diff line number Diff line change
@@ -1,52 +1,56 @@
package duke;

import duke.commands.Command;
import duke.controllers.MainWindow;
import duke.tasks.*;
import duke.ui.Ui;
import duke.utils.InputParser;
import duke.utils.Storage;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Scanner;

public class Duke {
public class Duke extends Application {

private TaskList taskList;
private Storage storage;

private Ui ui;

private InputParser inputParser;
private static final File saveFile = new File("savedata.txt");

public static void main(String[] args) {
Duke duke = new Duke();
duke.start();
}
private static final File SAVE_FILE = new File("savedata.txt");
private static final URL MAIN_WINDOW_FXML = Duke.class.getResource("/view/MainWindow.fxml");

public Duke() {
@Override
public void start(Stage stage) throws Exception {
inputParser = new InputParser();
ui = new Ui();
}

public void start() {
Scanner sc = new Scanner(System.in);
storage = new Storage(saveFile);
ui.showLogo();
storage = new Storage(SAVE_FILE);
taskList = new TaskList(storage.loadFromFile());
ui.showWelcome();
loop(sc);
loadMainWindow(stage);
}

public void loop(Scanner sc) {
while (sc.hasNext()) {
try {
String input = sc.nextLine().trim();
Command cmd = inputParser.parse(input, taskList, storage, ui);
cmd.execute();
} catch (Exception e) {
e.printStackTrace();
}
private void loadMainWindow(Stage stage) {
try {
FXMLLoader fxmlLoader = new FXMLLoader(MAIN_WINDOW_FXML);
AnchorPane ap = fxmlLoader.load();
Scene scene = new Scene(ap);
stage.setScene(scene);
fxmlLoader.<MainWindow>getController().setDuke(this);
stage.show();
} catch (IOException e) {
e.printStackTrace();
}
}

public String getResponse(String input) {
Command cmd = inputParser.parse(input, taskList, storage, ui);
String response = cmd.execute();
return response;
}
}
11 changes: 11 additions & 0 deletions src/main/java/duke/Launcher.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package duke;

import javafx.application.Application;

public class Launcher {

public static void main(String[] args) {
Application.launch(Duke.class, args);
}

}
14 changes: 9 additions & 5 deletions src/main/java/duke/commands/AddTaskCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,21 @@ public AddTaskCommand(Storage storage, Ui ui, TaskList tasks, TaskType type, Str
}

@Override
public boolean execute() {
public String execute() {
try {
Task newTask = TaskParser.stringToTask(type, taskString);
tasks.addTask(newTask);
ui.showAddTaskResponse(newTask, tasks);
storage.saveToFile(tasks.getList());

String response = String.format(
"Got it. I've added this task:\n %s\nNow you have %d tasks in the list.",
newTask, tasks.getSize());
return response;
} catch (EmptyTaskDescException | EmptyTaskDateException | NoSuchTaskTypeException |
UnrecognisedDateException e) {
ui.showError(e);
return false;

String response = String.format("Oops! %s", e.getMessage());
return response;
}
return true;
}
}
6 changes: 1 addition & 5 deletions src/main/java/duke/commands/Command.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@

public abstract class Command {

/**
* Executes the command.
* @return True if the command executed successfully and false otherwise.
*/
public abstract boolean execute();
public abstract String execute();

}
18 changes: 11 additions & 7 deletions src/main/java/duke/commands/DeleteTaskCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,22 @@ public DeleteTaskCommand(Storage storage, Ui ui, TaskList tasks, String index) {
}

@Override
public boolean execute() {
public String execute() {
try {
Task deletedTask = tasks.deleteTask(Integer.parseInt(index) - 1);
ui.showDeleteTaskResponse(deletedTask, tasks);
storage.saveToFile(tasks.getList());
return true;

String response = String.format(
"Noted. I've removed this task:\n %s\nNow you have %d tasks in the list",
deletedTask, tasks.getSize()
);
return response;
} catch (TaskNotFoundException e) {
ui.showError(e);
return false;
String response = String.format("Oops! %s", e.getMessage());
return response;
} catch (NumberFormatException e) {
ui.showInvalidFormatError(index);
return false;
String response = String.format("Oops! I could not recognise this format: %s", index);
return response;
}
}
}
5 changes: 2 additions & 3 deletions src/main/java/duke/commands/ExitCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@ public ExitCommand(Ui ui) {
}

@Override
public boolean execute() {
ui.showBye();
public String execute() {
System.exit(0);
return true;
return "";
}
}
5 changes: 2 additions & 3 deletions src/main/java/duke/commands/FindTaskCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public FindTaskCommand(TaskList tasks, Ui ui, String searchTerm) {
}

@Override
public boolean execute() {
public String execute() {
List<Task> matchingTasks = tasks.find(searchTerm);

StringBuilder sb = new StringBuilder();
Expand All @@ -30,8 +30,7 @@ public boolean execute() {
sb.append(String.format("%d.%s\n", i, task.toString()));
++i;
}
System.out.print(sb.toString());
return true;
return sb.toString();
}

}
17 changes: 10 additions & 7 deletions src/main/java/duke/commands/MarkTaskCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,21 @@ public MarkTaskCommand(Storage storage, Ui ui, TaskList tasks, String index) {
}

@Override
public boolean execute() {
public String execute() {
try {
Task markedTask = tasks.markTask(Integer.parseInt(index) - 1);
ui.showMarkTaskResponse(markedTask);
storage.saveToFile(tasks.getList());
return true;

String response = String.format(
"Nice! I've marked this task as done:\n %s",
markedTask);
return response;
} catch (TaskNotFoundException e) {
ui.showError(e);
return false;
String response = String.format("Oops! %s", e.getMessage());
return response;
} catch (NumberFormatException e) {
ui.showInvalidFormatError(index);
return false;
String response = String.format("Oops! I could not recognise this format: %s\n", index);
return response;
}
}

Expand Down
7 changes: 4 additions & 3 deletions src/main/java/duke/commands/PrintTasksCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ public PrintTasksCommand(Ui ui, TaskList tasks) {
}

@Override
public boolean execute() {
ui.showTasks(tasks);
return true;
public String execute() {
StringBuilder sb = new StringBuilder();
sb.append("Here are the tasks in your list:\n").append(tasks.toString());
return sb.toString();
}
}
17 changes: 10 additions & 7 deletions src/main/java/duke/commands/UnmarkTaskCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,21 @@ public UnmarkTaskCommand(Storage storage, Ui ui, TaskList tasks, String index) {
}

@Override
public boolean execute() {
public String execute() {
try {
Task unmarkedTask = tasks.unmarkTask(Integer.parseInt(index) - 1);
ui.showUnmarkTaskResponse(unmarkedTask);
storage.saveToFile(tasks.getList());
return true;

String response = String.format(
"OK, I've marked this task as not done yet:\n %s`",
unmarkedTask);
return response;
} catch (TaskNotFoundException e) {
ui.showError(e);
return false;
String response = String.format("Oops! %s", e.getMessage());
return response;
} catch (NumberFormatException e) {
ui.showInvalidFormatError(index);
return false;
String response = String.format("Oops! I could not recognise this format: %s\n", index);
return response;
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/main/java/duke/commands/UnrecognisedCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ public UnrecognisedCommand(Ui ui) {
}

@Override
public boolean execute() {
ui.showCommandUnknown();
return true;
public String execute() {
String response = "Oops! I'm sorry, but I don't know what that means.";
return response;
}
}
69 changes: 69 additions & 0 deletions src/main/java/duke/controllers/DialogBox.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package duke.controllers;

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.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Circle;

/**
* 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 {
@FXML
private Label dialog;
@FXML
private ImageView displayPicture;

private DialogBox(String text, Image img) {
try {
FXMLLoader fxmlLoader = new FXMLLoader(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);
displayPicture.setClip(new Circle(50, 50, 45));
}

/**
* Flips the dialog box such that the ImageView is on the left and text on the right.
*/
private void flip() {
ObservableList<Node> tmp = FXCollections.observableArrayList(this.getChildren());
Collections.reverse(tmp);
getChildren().setAll(tmp);
setAlignment(Pos.TOP_LEFT);
}

public static DialogBox getUserDialog(String text, Image img) {
var db = new DialogBox(text, img);
db.setStyle("-fx-background-color: azure;");
return db;
}

public static DialogBox getDukeDialog(String text, Image img) {
var db = new DialogBox(text, img);
db.setStyle("-fx-background-color: blanchedalmond;");
db.flip();
return db;
}
}
Loading

0 comments on commit 05ec52e

Please sign in to comment.