Skip to content

Commit

Permalink
Merge branch 'branch-Level-10'
Browse files Browse the repository at this point in the history
Updated duke with GUI using JavaFX
  • Loading branch information
Sampy147 committed Sep 15, 2022
2 parents ecbc9fd + cc0eb58 commit 1bf6279
Show file tree
Hide file tree
Showing 20 changed files with 340 additions and 83 deletions.
27 changes: 24 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,34 @@ plugins {
id 'com.github.johnrengelman.shadow' version '5.1.0'
}

group 'org.example'
version '1.0-SNAPSHOT'

repositories {
mavenCentral()
}

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 {
useJUnitPlatform()

Expand All @@ -28,14 +47,16 @@ test {
}

application {
mainClassName = "duke.Duke"
// Change this to your main class.
mainClassName = "duke.Launcher"
}

shadowJar {
archiveBaseName = "duke"
archiveClassifier = null
}

run{
run {
enableAssertions = true
standardInput = System.in
}
}
48 changes: 31 additions & 17 deletions src/main/java/duke/Duke.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,43 +6,57 @@
import duke.task.TaskList;
import duke.ui.Ui;

import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

public class Duke {

private final String SAVED_PATH = "data/duke.txt";
private Storage storage;
private TaskList tasks;
private Ui ui;
private boolean isExit;

private Duke() {
public Duke() {
this.isExit = false;
this.storage = new Storage(SAVED_PATH);
try {
this.tasks = this.storage.load();
} catch (DukeException e) {
this.ui = new Ui(new TaskList());
ui.showError(e.getMessage());
System.exit(0);
exit();
}
this.ui = new Ui(this.tasks);
}

public void run() {
ui.showWelcome();
boolean isExit = false;
while (!isExit) {
try {
String fullCommand = ui.readCommand();
Command c = Parser.parse(fullCommand);
c.execute(tasks, ui, storage);
isExit = c.isExit();
} catch (DukeException e) {
ui.showError(e.getMessage());
public boolean exitNow() {
return this.isExit;
}

public void exit() {
Timer timer = new Timer();
TimerTask exitApp = new TimerTask() {
public void run() {
System.exit(0);
}
}
};
timer.schedule(exitApp, new Date(System.currentTimeMillis() + 3 * 1000));
}

public static void main(String[] args) {
Duke sampleDuke = new Duke();
sampleDuke.run();
public String getResponse(String input) {
try {
String fullCommand = input;
Command c = Parser.parse(input);
String output = c.execute(tasks, ui, storage);
if (c.isExit()) {
this.isExit = true;
}
return output;
} catch (DukeException e) {
return ui.showError(e.getMessage());
}
}

}
14 changes: 14 additions & 0 deletions src/main/java/duke/Launcher.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package duke;

import javafx.application.Application;

/**
* A launcher class to workaround classpath issues.
*/
public class Launcher {

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

}
32 changes: 32 additions & 0 deletions src/main/java/duke/Main.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package duke;

import java.io.IOException;

import duke.gui.MainWindow;
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.<MainWindow>getController().setDuke(duke);
stage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
}
4 changes: 2 additions & 2 deletions src/main/java/duke/Message.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

public class Message {

public static final String HORIZONTAL_BORDER = "________________________________________________________";
public static final String HORIZONTAL_BORDER = "______________________________________________________";
public static final String WELCOME_MESSAGE = "Hello! I'm Duke\nWhat can I do for you?";
public static final String BYE_MESSAGE = "Bye. Hope to see you again soon!";
public static final String BYE_MESSAGE = "Bye! I'll be closing soon, till we meet again!";
public static final String INVALID_TODO_INPUT = "The description of a todo cannot be empty.";
public static final String INVALID_DEADLINE_INPUT =
"Please use proper deadline formatting: deadline {task} /by {time}";
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/duke/command/AddCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ public boolean isExit() {
* @throws DukeException if the change cannot be saved in storage successfully
*/
@Override
public void execute(TaskList tasks, Ui ui, Storage storage) throws DukeException {
public String execute(TaskList tasks, Ui ui, Storage storage) throws DukeException {
tasks.add(this.task);
storage.save(this.task.toSimpleString());
ui.showAddition(this.task, tasks.getCount());
return ui.showAddition(this.task, tasks.getCount());
}
}
4 changes: 2 additions & 2 deletions src/main/java/duke/command/ByeCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ public boolean isExit() {
* @param storage the local storage
*/
@Override
public void execute(TaskList tasks, Ui ui, Storage storage) throws DukeException {
ui.showBye();
public String execute(TaskList tasks, Ui ui, Storage storage) throws DukeException {
return ui.showBye();
}

}
2 changes: 1 addition & 1 deletion src/main/java/duke/command/Command.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@ public abstract class Command {
* @param storage the local storage
* @throws DukeException if an exception is thrown when the command is executed
*/
public abstract void execute(TaskList tasks, Ui ui, Storage storage) throws DukeException;
public abstract String execute(TaskList tasks, Ui ui, Storage storage) throws DukeException;

}
4 changes: 2 additions & 2 deletions src/main/java/duke/command/DeleteCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@ public boolean isExit() {
* @throws DukeException if the change cannot be saved in storage successfully or task cannot be deleted
*/
@Override
public void execute(TaskList tasks, Ui ui, Storage storage) throws DukeException {
public String execute(TaskList tasks, Ui ui, Storage storage) throws DukeException {
try {
Task deletedTask = tasks.deleteTaskAtPos(this.index);
storage.save(tasks);
ui.showDeleted(deletedTask);
return ui.showDeleted(deletedTask);
} catch (IndexOutOfBoundsException e) {
if (tasks.getCount() == 0){
throw new DukeException(Message.INVALID_ACCESS_EMPTY_TASKLIST);
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/duke/command/FindCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ public boolean isExit() {
}

@Override
public void execute(TaskList tasks, Ui ui, Storage storage) throws DukeException {
public String execute(TaskList tasks, Ui ui, Storage storage) throws DukeException {
String foundTasks = tasks.findTasks(this.keyword);
ui.showFound(foundTasks);
return ui.showFound(foundTasks);
}

}
4 changes: 2 additions & 2 deletions src/main/java/duke/command/ListCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ public boolean isExit() {
* @param storage the local storage
*/
@Override
public void execute(TaskList tasks, Ui ui, Storage storage) throws DukeException {
ui.showList();
public String execute(TaskList tasks, Ui ui, Storage storage) throws DukeException {
return ui.showList();
}

}
4 changes: 2 additions & 2 deletions src/main/java/duke/command/MarkCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@ public boolean isExit() {
* @throws DukeException if the change cannot be saved in storage successfully or task cannot be marked
*/
@Override
public void execute(TaskList tasks, Ui ui, Storage storage) throws DukeException {
public String execute(TaskList tasks, Ui ui, Storage storage) throws DukeException {
try {
tasks.markTaskAtPos(this.index);
Task currentTask = tasks.getTask(this.index);
storage.save(tasks);
ui.showMarked(currentTask);
return ui.showMarked(currentTask);
} catch (IndexOutOfBoundsException e) {
if (tasks.getCount() == 0) {
throw new DukeException(Message.INVALID_ACCESS_EMPTY_TASKLIST);
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/duke/command/UnmarkCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@ public boolean isExit() {
* @throws DukeException if the change cannot be saved in storage successfully or task cannot be unmarked
*/
@Override
public void execute(TaskList tasks, Ui ui, Storage storage) throws DukeException {
public String execute(TaskList tasks, Ui ui, Storage storage) throws DukeException {
try {
tasks.unmarkTaskAtPos(this.index);
Task currentTask = tasks.getTask(this.index);
storage.save(tasks);
ui.showUnmarked(currentTask);
return ui.showUnmarked(currentTask);
} catch (IndexOutOfBoundsException e) {
if (tasks.getCount() == 0) {
throw new DukeException(Message.INVALID_ACCESS_EMPTY_TASKLIST);
Expand Down
69 changes: 69 additions & 0 deletions src/main/java/duke/gui/DialogBox.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package duke.gui;

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;
import javafx.scene.shape.Rectangle;

/**
* 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);

Rectangle clip = new Rectangle(
displayPicture.getFitWidth(), displayPicture.getFitHeight()
);
clip.setArcWidth(40);
clip.setArcHeight(40);
displayPicture.setClip(clip);
}

/**
* 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) {
return new DialogBox(text, img);
}

public static DialogBox getDukeDialog(String text, Image img) {
var db = new DialogBox(text, img);
db.flip();
return db;
}
}
Loading

0 comments on commit 1bf6279

Please sign in to comment.