Skip to content
This repository has been archived by the owner on Sep 29, 2022. It is now read-only.

Commit

Permalink
Add chat pane to GUI (#9)
Browse files Browse the repository at this point in the history
* Update AboutUs.adoc for team members to commit

* Add a newline in AboutUs.adoc

* Add more use cases to Developer Guide

* Fix missing endline

* Update GUI to include chat pane

* Add newlines for FXML files

* Update various docs to display TagLine

* Add placeholder image

* Fix minor typo in user guide

* Update Tagline to TagLine

* Update team name

* Fix some typos in user guide and developer guide

* Change chat pane layout

* Clean up UI code

* Add icon for response messages
  • Loading branch information
tanlk99 authored and stevenwjy committed Oct 8, 2019
1 parent a55d673 commit abe7585
Show file tree
Hide file tree
Showing 11 changed files with 291 additions and 82 deletions.
68 changes: 68 additions & 0 deletions src/main/java/tagline/ui/ChatPane.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package tagline.ui;

import static java.util.Objects.requireNonNull;

import javafx.fxml.FXML;
import javafx.scene.control.ScrollPane;
import javafx.scene.image.Image;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import tagline.ui.CommandBox.CommandExecutor;

/**
* The UI component that stores the chat window.
*/
public class ChatPane extends UiPart<GridPane> {

private static final String FXML = "ChatPane.fxml";
private static final String TAGLINE_RESPONSE_IMAGE = "/images/tagline_icon.png";

private CommandBox commandBox;

@FXML
private StackPane commandBoxPlaceholder;

@FXML
private ScrollPane dialogScrollPane;

@FXML
private VBox dialogContainer;

private Image image = new Image(getClass().getResourceAsStream(TAGLINE_RESPONSE_IMAGE));

public ChatPane(CommandExecutor commandExecutor) {
super(FXML);

commandBox = new CommandBox(commandExecutor);
commandBox.getRoot().prefWidthProperty().bind(getRoot().widthProperty());
commandBoxPlaceholder.getChildren().add(commandBox.getRoot());

//setting vvalue to 1.0 doesn't work
dialogScrollPane.vvalueProperty().bind(dialogContainer.heightProperty());
}

/**
* Displays a new command from the user in the chat window.
* @param commandFromUser Command entered by user
*/
public void setCommandFromUser(String commandFromUser) {
requireNonNull(commandFromUser);

//Don't display empty messages
if (commandFromUser.isEmpty()) {
return;
}

dialogContainer.getChildren().add(DialogBox.getCommandDialog(commandFromUser).getRoot());
}

/**
* Displays the feedback returned by TagLine in the chat window.
* @param feedbackToUser Feedback to user
*/
public void setFeedbackToUser(String feedbackToUser) {
requireNonNull(feedbackToUser);
dialogContainer.getChildren().add(DialogBox.getResponseDialog(feedbackToUser, image).getRoot());
}
}
101 changes: 101 additions & 0 deletions src/main/java/tagline/ui/DialogBox.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package tagline.ui;

import javafx.animation.FadeTransition;
import javafx.fxml.FXML;
import javafx.geometry.Pos;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.scene.shape.Circle;
import javafx.util.Duration;

/**
* A dialog box to display chat messages.
*/
class DialogBox extends UiPart<HBox> {

private static final String FXML = "DialogBox.fxml";

private static final String COMMAND_DIALOG = "command-dialog";
private static final String RESPONSE_DIALOG = "response-dialog";

private static final double TRANSITION_DURATION = 0.5;
private static final double TRANSITION_OPACITY_FROM = 0.5;
private static final double TRANSITION_OPACITY_TO = 1.0;

@FXML
private Label dialog;

@FXML
private ImageView displayPicture;

private FadeTransition fadeTransition;

/**
* Creates a new DialogBox.
*
* @param text Text to place in the dialog box
*/
private DialogBox(String text) {
super(FXML);

dialog.setText(text);
prepareAnimation();

double radius = displayPicture.getFitHeight() / 2;
displayPicture.setClip(new Circle(radius, radius, radius));
}

/**
* Prepares the fade-in transition of the dialog box.
*/
private void prepareAnimation() {
fadeTransition = new FadeTransition();
fadeTransition.setDuration(Duration.seconds(TRANSITION_DURATION));
fadeTransition.setFromValue(TRANSITION_OPACITY_FROM);
fadeTransition.setToValue(TRANSITION_OPACITY_TO);

fadeTransition.setNode(dialog);
}

/**
* Flips the dialog box so that the text is aligned on the left.
*/
private void flip() {
getRoot().setAlignment(Pos.TOP_LEFT);
}

/**
* Creates a dialog box for commands from the user.
* The text box is aligned to the right.
*
* @param text Text to place in the dialog box
* @return A DialogBox object for the message
*/
public static DialogBox getCommandDialog(String text) {
DialogBox db = new DialogBox(text);

db.dialog.getStyleClass().add(COMMAND_DIALOG);
db.fadeTransition.play();
return db;
}

/**
* Creates a dialog box for response messages.
* The text box is aligned to the left.
*
* @param text Text to place in the dialog box
* @param image Image to place as the icon
* @return A DialogBox object for the message
*/
public static DialogBox getResponseDialog(String text, Image image) {
DialogBox db = new DialogBox(text);
db.flip();

db.displayPicture.setImage(image);
db.dialog.getStyleClass().add(RESPONSE_DIALOG);
db.fadeTransition.play();
return db;
}
}
31 changes: 13 additions & 18 deletions src/main/java/tagline/ui/MainWindow.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,24 +31,21 @@ public class MainWindow extends UiPart<Stage> {
private Logic logic;

// Independent Ui parts residing in this Ui container
private ChatPane chatPane;
private PersonListPanel personListPanel;
private ResultDisplay resultDisplay;
private HelpWindow helpWindow;

@FXML
private StackPane commandBoxPlaceholder;

@FXML
private MenuItem helpMenuItem;

@FXML
private StackPane personListPanelPlaceholder;

@FXML
private StackPane resultDisplayPlaceholder;
private StackPane statusbarPlaceholder;

@FXML
private StackPane statusbarPlaceholder;
private StackPane chatPanePlaceholder;

public MainWindow(Stage primaryStage, Logic logic) {
super(FXML, primaryStage);
Expand Down Expand Up @@ -86,14 +83,13 @@ private void setAccelerator(MenuItem menuItem, KeyCombination keyCombination) {
* is fixed in later version of SDK.
*
* According to the bug report, TextInputControl (TextField, TextArea) will
* consume function-key events. Because CommandBox contains a TextField, and
* ResultDisplay contains a TextArea, thus some accelerators (e.g F1) will
* not work when the focus is in them because the key event is consumed by
* the TextInputControl(s).
* consume function-key events. Because CommandBox contains a TextField, thus
* some accelerators (e.g F1) will not work when the focus is in them because
* the key event is consumed by the TextInputControl(s).
*
* For now, we add following event filter to capture such key events and open
* help window purposely so to support accelerators even when focus is
* in CommandBox or ResultDisplay.
* in CommandBox.
*/
getRoot().addEventFilter(KeyEvent.KEY_PRESSED, event -> {
if (event.getTarget() instanceof TextInputControl && keyCombination.match(event)) {
Expand All @@ -110,14 +106,11 @@ void fillInnerParts() {
personListPanel = new PersonListPanel(logic.getFilteredPersonList());
personListPanelPlaceholder.getChildren().add(personListPanel.getRoot());

resultDisplay = new ResultDisplay();
resultDisplayPlaceholder.getChildren().add(resultDisplay.getRoot());

StatusBarFooter statusBarFooter = new StatusBarFooter(logic.getAddressBookFilePath());
statusbarPlaceholder.getChildren().add(statusBarFooter.getRoot());

CommandBox commandBox = new CommandBox(this::executeCommand);
commandBoxPlaceholder.getChildren().add(commandBox.getRoot());
chatPane = new ChatPane(this::executeCommand);
chatPanePlaceholder.getChildren().add(chatPane.getRoot());
}

/**
Expand Down Expand Up @@ -170,10 +163,12 @@ public PersonListPanel getPersonListPanel() {
* @see tagline.logic.Logic#execute(String)
*/
private CommandResult executeCommand(String commandText) throws CommandException, ParseException {
chatPane.setCommandFromUser(commandText);

try {
CommandResult commandResult = logic.execute(commandText);
logger.info("Result: " + commandResult.getFeedbackToUser());
resultDisplay.setFeedbackToUser(commandResult.getFeedbackToUser());
chatPane.setFeedbackToUser(commandResult.getFeedbackToUser());

if (commandResult.isShowHelp()) {
handleHelp();
Expand All @@ -186,7 +181,7 @@ private CommandResult executeCommand(String commandText) throws CommandException
return commandResult;
} catch (CommandException | ParseException e) {
logger.info("Invalid command: " + commandText);
resultDisplay.setFeedbackToUser(e.getMessage());
chatPane.setFeedbackToUser(e.getMessage());
throw e;
}
}
Expand Down
28 changes: 0 additions & 28 deletions src/main/java/tagline/ui/ResultDisplay.java

This file was deleted.

Binary file added src/main/resources/images/tagline_icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
32 changes: 32 additions & 0 deletions src/main/resources/view/ChatPane.fxml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.geometry.Insets?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.layout.RowConstraints?>

<GridPane xmlns="http://javafx.com/javafx/8"
xmlns:fx="http://javafx.com/fxml/1" VBox.vgrow="ALWAYS">
<rowConstraints>
<RowConstraints vgrow="ALWAYS" valignment="TOP"/>
<RowConstraints vgrow="NEVER" valignment="BOTTOM"/>
</rowConstraints>
<children>
<StackPane VBox.vgrow="ALWAYS" styleClass="stack-pane" GridPane.rowIndex="0">
<ScrollPane fx:id="dialogScrollPane" hbarPolicy="NEVER" fitToWidth="true">
<content>
<VBox fx:id="dialogContainer" />
</content>
</ScrollPane>
</StackPane>

<StackPane VBox.vgrow="NEVER" fx:id="commandBoxPlaceholder" styleClass="stack-pane"
GridPane.rowIndex="1">
<padding>
<Insets top="5" right="10" bottom="5" left="10" />
</padding>
</StackPane>
</children>
</GridPane>
20 changes: 15 additions & 5 deletions src/main/resources/view/CommandBox.fxml
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.StackPane?>

<StackPane styleClass="stack-pane" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<TextField fx:id="commandTextField" onAction="#handleCommandEntered" promptText="Enter command here..."/>
</StackPane>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>

<GridPane styleClass="stack-pane" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<columnConstraints>
<ColumnConstraints hgrow="ALWAYS" halignment="LEFT"/>
<ColumnConstraints hgrow="NEVER" prefWidth="5.0" minWidth="5.0"/>
<ColumnConstraints hgrow="NEVER" minWidth="60.0"/>
</columnConstraints>
<children>
<TextField fx:id="commandTextField" onAction="#handleCommandEntered" promptText="Enter command here..."
GridPane.columnIndex="0"/>
<Button onAction="#handleCommandEntered" text="Send" GridPane.columnIndex="2"/>
</children>
</GridPane>
35 changes: 34 additions & 1 deletion src/main/resources/view/DarkTheme.css
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@
* http://pixelduke.wordpress.com/2012/10/23/jmetro-windows-8-controls-on-java/
*/
.button {
-fx-padding: 5 22 5 22;
-fx-padding: 5 15 5 15;
-fx-border-color: #e2e2e2;
-fx-border-width: 2;
-fx-background-radius: 0;
Expand Down Expand Up @@ -350,3 +350,36 @@
-fx-background-radius: 2;
-fx-font-size: 11;
}

.scroll-pane {
-fx-background-color: transparent;
}

.scroll-pane > .viewport {
-fx-background-color: transparent;
}

.dialog-box {
-fx-spacing: 15;
-fx-pref-width: 400;
-fx-background-color: #383838;
}

.dialog-box > .message-content {
-fx-padding: 10 10 10 10;
-fx-border-radius: 13;
-fx-background-radius: 13;
-fx-font-size: 13px;
-fx-wrap-text: true;
-fx-font-family: "Segoe UI Light";
}

.dialog-box > .response-dialog {
-fx-text-fill: #EEEEEE;
-fx-background-color: #6890BC;
}

.dialog-box > .command-dialog {
-fx-text-fill: #DDDDDD;
-fx-background-color: #666666;
}
Loading

0 comments on commit abe7585

Please sign in to comment.