Merge branch 'develop' into f/groupMessages
This commit is contained in:
commit
a3f3a9dcbb
3
.github/PULL_REQUEST_TEMPLATE/bugfix.md
vendored
3
.github/PULL_REQUEST_TEMPLATE/bugfix.md
vendored
@ -5,6 +5,7 @@ labels: bug
|
|||||||
assignees: CyB3RC0nN0R, delvh, DieGurke
|
assignees: CyB3RC0nN0R, delvh, DieGurke
|
||||||
reviewers: CyB3RC0nN0R, delvh
|
reviewers: CyB3RC0nN0R, delvh
|
||||||
projects: Envoy
|
projects: Envoy
|
||||||
milestone: Envoy v0.3-alpha
|
milestone: Envoy v0.1-beta
|
||||||
|
|
||||||
---
|
---
|
||||||
Fixes #{issue}
|
Fixes #{issue}
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
---
|
---
|
||||||
name: Feature integration
|
name: Feature integration
|
||||||
title: Added feature
|
title: Added feature
|
||||||
labels: enhancement
|
labels: feature
|
||||||
assignees: CyB3RC0nN0R, delvh, DieGurke
|
assignees: CyB3RC0nN0R, delvh, DieGurke
|
||||||
reviewers: CyB3RC0nN0R, delvh
|
reviewers: CyB3RC0nN0R, delvh
|
||||||
projects: Envoy
|
projects: Envoy
|
||||||
milestone: Envoy v0.3-alpha
|
milestone: Envoy v0.1-beta
|
||||||
|
|
||||||
---
|
---
|
||||||
|
@ -5,5 +5,6 @@ labels: documentation
|
|||||||
assignees: CyB3RC0nN0R, delvh
|
assignees: CyB3RC0nN0R, delvh
|
||||||
reviewers: CyB3RC0nN0R, delvh
|
reviewers: CyB3RC0nN0R, delvh
|
||||||
projects: Envoy
|
projects: Envoy
|
||||||
milestone: Envoy v0.3-alpha
|
milestone: Envoy v0.1-beta
|
||||||
|
|
||||||
---
|
---
|
15
.github/workflows/maven.yml
vendored
15
.github/workflows/maven.yml
vendored
@ -4,14 +4,25 @@ on: [push]
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v2
|
||||||
- name: Set up JDK 11
|
- name: Set up JDK 11
|
||||||
uses: actions/setup-java@v1
|
uses: actions/setup-java@v1
|
||||||
with:
|
with:
|
||||||
java-version: 11
|
java-version: 11
|
||||||
|
- name: Cache Maven packages
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: ~/.m2
|
||||||
|
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
|
||||||
|
restore-keys: ${{ runner.os }}-m2
|
||||||
- name: Build with Maven
|
- name: Build with Maven
|
||||||
run: mvn -B package --file pom.xml
|
run: mvn -B package --file pom.xml
|
||||||
|
- name: Stage build artifacts
|
||||||
|
run: mkdir staging && cp target/*.jar staging
|
||||||
|
- uses: actions/upload-artifact@v1
|
||||||
|
with:
|
||||||
|
name: envoy-client-artifacts
|
||||||
|
path: staging
|
||||||
|
@ -114,6 +114,21 @@ public final class Chat implements Serializable {
|
|||||||
*/
|
*/
|
||||||
public boolean isUnread() { return !messages.isEmpty() && messages.get(messages.size() - 1).getStatus() != MessageStatus.READ; }
|
public boolean isUnread() { return !messages.isEmpty() && messages.get(messages.size() - 1).getStatus() != MessageStatus.READ; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts a message at the correct place according to its creation date.
|
||||||
|
*
|
||||||
|
* @param message the message to insert
|
||||||
|
* @since Envoy Client v0.1-beta
|
||||||
|
*/
|
||||||
|
public void insert(Message message) {
|
||||||
|
for (int i = messages.size() - 1; i >= 0; --i)
|
||||||
|
if (message.getCreationDate().isAfter(messages.get(i).getCreationDate())) {
|
||||||
|
messages.add(i + 1, message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
messages.add(0, message);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return all messages in the current chat
|
* @return all messages in the current chat
|
||||||
* @since Envoy Client v0.1-beta
|
* @since Envoy Client v0.1-beta
|
||||||
|
174
src/main/java/envoy/client/ui/ClearableTextField.java
Normal file
174
src/main/java/envoy/client/ui/ClearableTextField.java
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
package envoy.client.ui;
|
||||||
|
|
||||||
|
import javafx.beans.property.BooleanProperty;
|
||||||
|
import javafx.beans.property.ObjectProperty;
|
||||||
|
import javafx.beans.property.StringProperty;
|
||||||
|
import javafx.event.ActionEvent;
|
||||||
|
import javafx.event.EventHandler;
|
||||||
|
import javafx.scene.control.*;
|
||||||
|
import javafx.scene.image.ImageView;
|
||||||
|
import javafx.scene.layout.Background;
|
||||||
|
import javafx.scene.layout.ColumnConstraints;
|
||||||
|
import javafx.scene.layout.GridPane;
|
||||||
|
|
||||||
|
import envoy.client.data.Settings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class offers a text field that is automatically equipped with a clear
|
||||||
|
* button.
|
||||||
|
* <p>
|
||||||
|
* Project: <strong>envoy-client</strong><br>
|
||||||
|
* File: <strong>ClearableTextField.java</strong><br>
|
||||||
|
* Created: <strong>25.06.2020</strong><br>
|
||||||
|
*
|
||||||
|
* @author Leon Hofmeister
|
||||||
|
* @since Envoy Client v0.1-beta
|
||||||
|
*/
|
||||||
|
public class ClearableTextField extends GridPane {
|
||||||
|
|
||||||
|
private final TextField textField;
|
||||||
|
|
||||||
|
private final Button clearButton;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new {@code ClearableTextField} with no initial text and icon
|
||||||
|
* size 16.
|
||||||
|
*
|
||||||
|
* @since Envoy Client v0.1-beta
|
||||||
|
*/
|
||||||
|
public ClearableTextField() { this("", 16); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new {@code ClearableTextField} with initial text and a
|
||||||
|
* predetermined icon size.
|
||||||
|
*
|
||||||
|
* @param text the text that should be displayed by default
|
||||||
|
* @param size the size of the icon
|
||||||
|
* @since Envoy Client v0.1-beta
|
||||||
|
*/
|
||||||
|
public ClearableTextField(String text, int size) {
|
||||||
|
// initializing the textField and the button
|
||||||
|
textField = new TextField(text);
|
||||||
|
clearButton = new Button("",
|
||||||
|
new ImageView(IconUtil.load(
|
||||||
|
Settings.getInstance().getCurrentTheme().equals("dark") ? "/icons/clear_button_white.png" : "/icons/clear_button_black.png",
|
||||||
|
size)));
|
||||||
|
clearButton.setOnAction(e -> textField.clear());
|
||||||
|
clearButton.setFocusTraversable(false);
|
||||||
|
clearButton.getStyleClass().clear();
|
||||||
|
clearButton.setBackground(Background.EMPTY);
|
||||||
|
// Adding the two elements to the GridPane
|
||||||
|
add(textField, 0, 0, 2, 1);
|
||||||
|
add(clearButton, 1, 0, 1, 1);
|
||||||
|
// Setting the percent - widths of the two columns.
|
||||||
|
// Used to locate the button on the right.
|
||||||
|
final var columnConstraints = new ColumnConstraints();
|
||||||
|
columnConstraints.setPercentWidth(90);
|
||||||
|
getColumnConstraints().add(columnConstraints);
|
||||||
|
final var columnConstraints2 = new ColumnConstraints();
|
||||||
|
columnConstraints2.setPercentWidth(10);
|
||||||
|
getColumnConstraints().add(columnConstraints2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the underlying {@code textField}
|
||||||
|
* @since Envoy Client v0.1-beta
|
||||||
|
*/
|
||||||
|
public TextField getTextField() { return textField; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method offers the freedom to perform custom actions when the
|
||||||
|
* {@code clearButton} has been pressed.
|
||||||
|
* <p>
|
||||||
|
* The default is
|
||||||
|
* <b><code> e -> {clearableTextField.getTextField().clear();}</code></b>
|
||||||
|
*
|
||||||
|
* @param onClearButtonAction the action that should be performed
|
||||||
|
* @since Envoy Client v0.1-beta
|
||||||
|
*/
|
||||||
|
public void setClearButtonListener(EventHandler<ActionEvent> onClearButtonAction) { clearButton.setOnAction(onClearButtonAction); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the current property of the prompt text
|
||||||
|
* @see javafx.scene.control.TextInputControl#promptTextProperty()
|
||||||
|
* @since Envoy Client v0.1-beta
|
||||||
|
*/
|
||||||
|
public final StringProperty promptTextProperty() { return textField.promptTextProperty(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the current prompt text
|
||||||
|
* @see javafx.scene.control.TextInputControl#getPromptText()
|
||||||
|
* @since Envoy Client v0.1-beta
|
||||||
|
*/
|
||||||
|
public final String getPromptText() { return textField.getPromptText(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param value the prompt text to display
|
||||||
|
* @see javafx.scene.control.TextInputControl#setPromptText(java.lang.String)
|
||||||
|
* @since Envoy Client v0.1-beta
|
||||||
|
*/
|
||||||
|
public final void setPromptText(String value) { textField.setPromptText(value); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the current property of the tooltip
|
||||||
|
* @see javafx.scene.control.Control#tooltipProperty()
|
||||||
|
* @since Envoy Client v0.1-beta
|
||||||
|
*/
|
||||||
|
public final ObjectProperty<Tooltip> tooltipProperty() { return textField.tooltipProperty(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param value the new tooltip
|
||||||
|
* @see javafx.scene.control.Control#setTooltip(javafx.scene.control.Tooltip)
|
||||||
|
* @since Envoy Client v0.1-beta
|
||||||
|
*/
|
||||||
|
public final void setTooltip(Tooltip value) { textField.setTooltip(value); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the current tooltip
|
||||||
|
* @see javafx.scene.control.Control#getTooltip()
|
||||||
|
* @since Envoy Client v0.1-beta
|
||||||
|
*/
|
||||||
|
public final Tooltip getTooltip() { return textField.getTooltip(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the current property of the context menu
|
||||||
|
* @see javafx.scene.control.Control#contextMenuProperty()
|
||||||
|
* @since Envoy Client v0.1-beta
|
||||||
|
*/
|
||||||
|
public final ObjectProperty<ContextMenu> contextMenuProperty() { return textField.contextMenuProperty(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param value the new context menu
|
||||||
|
* @see javafx.scene.control.Control#setContextMenu(javafx.scene.control.ContextMenu)
|
||||||
|
* @since Envoy Client v0.1-beta
|
||||||
|
*/
|
||||||
|
public final void setContextMenu(ContextMenu value) { textField.setContextMenu(value); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the current context menu
|
||||||
|
* @see javafx.scene.control.Control#getContextMenu()
|
||||||
|
* @since Envoy Client v0.1-beta
|
||||||
|
*/
|
||||||
|
public final ContextMenu getContextMenu() { return textField.getContextMenu(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param value whether this ClearableTextField should be editable
|
||||||
|
* @see javafx.scene.control.TextInputControl#setEditable(boolean)
|
||||||
|
* @since Envoy Client v0.1-beta
|
||||||
|
*/
|
||||||
|
public final void setEditable(boolean value) { textField.setEditable(value); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the current property whether this ClearableTextField is editable
|
||||||
|
* @see javafx.scene.control.TextInputControl#editableProperty()
|
||||||
|
* @since Envoy Client v0.1-beta
|
||||||
|
*/
|
||||||
|
public final BooleanProperty editableProperty() { return textField.editableProperty(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return whether this {@code ClearableTextField} is editable
|
||||||
|
* @see javafx.scene.control.TextInputControl#isEditable()
|
||||||
|
* @since Envoy Client v0.1-beta
|
||||||
|
*/
|
||||||
|
public final boolean isEditable() { return textField.isEditable(); }
|
||||||
|
}
|
@ -1,49 +0,0 @@
|
|||||||
package envoy.client.ui;
|
|
||||||
|
|
||||||
import javafx.scene.control.Label;
|
|
||||||
import javafx.scene.control.ListCell;
|
|
||||||
import javafx.scene.layout.VBox;
|
|
||||||
|
|
||||||
import envoy.data.Contact;
|
|
||||||
import envoy.data.Group;
|
|
||||||
import envoy.data.User;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Project: <strong>envoy-client</strong><br>
|
|
||||||
* File: <strong>UserListCell.java</strong><br>
|
|
||||||
* Created: <strong>28.03.2020</strong><br>
|
|
||||||
*
|
|
||||||
* @author Kai S. K. Engelbart
|
|
||||||
* @since Envoy Client v0.1-beta
|
|
||||||
*/
|
|
||||||
public class ContactListCell extends ListCell<Contact> {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Displays the name of a contact. If the contact is a user, their online status
|
|
||||||
* is displayed as well.
|
|
||||||
*
|
|
||||||
* @since Envoy Client v0.1-beta
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected void updateItem(Contact contact, boolean empty) {
|
|
||||||
super.updateItem(contact, empty);
|
|
||||||
if (empty || contact == null) {
|
|
||||||
setText(null);
|
|
||||||
setGraphic(null);
|
|
||||||
} else {
|
|
||||||
// Container with contact name
|
|
||||||
final var vbox = new VBox(new Label(contact.getName()));
|
|
||||||
if (contact instanceof User) {
|
|
||||||
// Online status
|
|
||||||
final var user = (User) contact;
|
|
||||||
final var statusLabel = new Label(user.getStatus().toString());
|
|
||||||
statusLabel.getStyleClass().add(user.getStatus().toString().toLowerCase());
|
|
||||||
vbox.getChildren().add(statusLabel);
|
|
||||||
} else {
|
|
||||||
// Member count
|
|
||||||
vbox.getChildren().add(new Label(((Group) contact).getContacts().size() + " members"));
|
|
||||||
}
|
|
||||||
setGraphic(vbox);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,60 +0,0 @@
|
|||||||
package envoy.client.ui;
|
|
||||||
|
|
||||||
import java.time.format.DateTimeFormatter;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import javafx.geometry.Insets;
|
|
||||||
import javafx.scene.control.Label;
|
|
||||||
import javafx.scene.control.ListCell;
|
|
||||||
import javafx.scene.image.Image;
|
|
||||||
import javafx.scene.image.ImageView;
|
|
||||||
import javafx.scene.layout.VBox;
|
|
||||||
|
|
||||||
import envoy.data.Message;
|
|
||||||
import envoy.data.Message.MessageStatus;
|
|
||||||
import envoy.data.User;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Displays a single message inside the message list.
|
|
||||||
* <p>
|
|
||||||
* Project: <strong>envoy-client</strong><br>
|
|
||||||
* File: <strong>MessageListCell.java</strong><br>
|
|
||||||
* Created: <strong>28.03.2020</strong><br>
|
|
||||||
*
|
|
||||||
* @author Kai S. K. Engelbart
|
|
||||||
* @since Envoy Client v0.1-beta
|
|
||||||
*/
|
|
||||||
public class MessageListCell extends ListCell<Message> {
|
|
||||||
|
|
||||||
private static User client;
|
|
||||||
private static final DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm");
|
|
||||||
private static final Map<MessageStatus, Image> statusImages = IconUtil.loadByEnum(MessageStatus.class, 16);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Displays the text, the data of creation and the status of a message.
|
|
||||||
*
|
|
||||||
* @since Envoy v0.1-beta
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected void updateItem(Message message, boolean empty) {
|
|
||||||
super.updateItem(message, empty);
|
|
||||||
if (empty || message == null) {
|
|
||||||
setText(null);
|
|
||||||
setGraphic(null);
|
|
||||||
} else {
|
|
||||||
final var cell = new VBox(new Label(dateFormat.format(message.getCreationDate())), new Label(message.getText()));
|
|
||||||
if (message.getRecipientID() == client.getID()) {
|
|
||||||
cell.getChildren().add(new Label("", new ImageView(statusImages.get(message.getStatus()))));
|
|
||||||
cell.getStyleClass().add("own-message");
|
|
||||||
} else cell.getStyleClass().add("received-message");
|
|
||||||
cell.paddingProperty().setValue(new Insets(5, 20, 5, 20));
|
|
||||||
setGraphic(cell);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param client the user who chats with another person
|
|
||||||
* @since Envoy Client v0.1-beta
|
|
||||||
*/
|
|
||||||
public static void setUser(User client) { MessageListCell.client = client; }
|
|
||||||
}
|
|
25
src/main/java/envoy/client/ui/Restorable.java
Normal file
25
src/main/java/envoy/client/ui/Restorable.java
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package envoy.client.ui;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interface defines an action that should be performed when a scene gets
|
||||||
|
* restored from the scene stack in {@link SceneContext}.
|
||||||
|
* <p>
|
||||||
|
* Project: <strong>envoy-client</strong><br>
|
||||||
|
* File: <strong>Restorable.java</strong><br>
|
||||||
|
* Created: <strong>03.07.2020</strong><br>
|
||||||
|
*
|
||||||
|
* @author Leon Hofmeister
|
||||||
|
* @since Envoy Client v0.1-beta
|
||||||
|
*/
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface Restorable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is getting called when a scene gets restored.<br>
|
||||||
|
* Hence, it can contain anything that should be done when the underlying scene
|
||||||
|
* gets restored.
|
||||||
|
*
|
||||||
|
* @since Envoy Client v0.1-beta
|
||||||
|
*/
|
||||||
|
void onRestore();
|
||||||
|
}
|
@ -40,21 +40,21 @@ public final class SceneContext {
|
|||||||
public enum SceneInfo {
|
public enum SceneInfo {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The main scene in which chats are displayed.
|
* The main scene in which the chat screen is displayed.
|
||||||
*
|
*
|
||||||
* @since Envoy Client v0.1-beta
|
* @since Envoy Client v0.1-beta
|
||||||
*/
|
*/
|
||||||
CHAT_SCENE("/fxml/ChatScene.fxml"),
|
CHAT_SCENE("/fxml/ChatScene.fxml"),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The scene in which settings are displayed.
|
* The scene in which the settings screen is displayed.
|
||||||
*
|
*
|
||||||
* @since Envoy Client v0.1-beta
|
* @since Envoy Client v0.1-beta
|
||||||
*/
|
*/
|
||||||
SETTINGS_SCENE("/fxml/SettingsScene.fxml"),
|
SETTINGS_SCENE("/fxml/SettingsScene.fxml"),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The scene in which the contact search is displayed.
|
* The scene in which the contact search screen is displayed.
|
||||||
*
|
*
|
||||||
* @since Envoy Client v0.1-beta
|
* @since Envoy Client v0.1-beta
|
||||||
*/
|
*/
|
||||||
@ -72,7 +72,14 @@ public final class SceneContext {
|
|||||||
*
|
*
|
||||||
* @since Envoy Client v0.1-beta
|
* @since Envoy Client v0.1-beta
|
||||||
*/
|
*/
|
||||||
LOGIN_SCENE("/fxml/LoginScene.fxml");
|
LOGIN_SCENE("/fxml/LoginScene.fxml"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The scene in which the info screen is displayed.
|
||||||
|
*
|
||||||
|
* @since Envoy Client v0.1-beta
|
||||||
|
*/
|
||||||
|
MESSAGE_INFO_SCENE("/fxml/MessageInfoScene.fxml");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The path to the FXML resource.
|
* The path to the FXML resource.
|
||||||
@ -85,6 +92,7 @@ public final class SceneContext {
|
|||||||
private final Stage stage;
|
private final Stage stage;
|
||||||
private final FXMLLoader loader = new FXMLLoader();
|
private final FXMLLoader loader = new FXMLLoader();
|
||||||
private final Stack<Scene> sceneStack = new Stack<>();
|
private final Stack<Scene> sceneStack = new Stack<>();
|
||||||
|
private final Stack<Object> controllerStack = new Stack<>();
|
||||||
|
|
||||||
private static final Settings settings = Settings.getInstance();
|
private static final Settings settings = Settings.getInstance();
|
||||||
|
|
||||||
@ -113,6 +121,7 @@ public final class SceneContext {
|
|||||||
try {
|
try {
|
||||||
final var rootNode = (Parent) loader.load(getClass().getResourceAsStream(sceneInfo.path));
|
final var rootNode = (Parent) loader.load(getClass().getResourceAsStream(sceneInfo.path));
|
||||||
final var scene = new Scene(rootNode);
|
final var scene = new Scene(rootNode);
|
||||||
|
controllerStack.push(loader.getController());
|
||||||
|
|
||||||
sceneStack.push(scene);
|
sceneStack.push(scene);
|
||||||
stage.setScene(scene);
|
stage.setScene(scene);
|
||||||
@ -132,10 +141,16 @@ public final class SceneContext {
|
|||||||
*/
|
*/
|
||||||
public void pop() {
|
public void pop() {
|
||||||
sceneStack.pop();
|
sceneStack.pop();
|
||||||
|
controllerStack.pop();
|
||||||
if (!sceneStack.isEmpty()) {
|
if (!sceneStack.isEmpty()) {
|
||||||
stage.setScene(sceneStack.peek());
|
final var newScene = sceneStack.peek();
|
||||||
|
stage.setScene(newScene);
|
||||||
applyCSS();
|
applyCSS();
|
||||||
stage.sizeToScene();
|
stage.sizeToScene();
|
||||||
|
// If the controller implements the Restorable interface,
|
||||||
|
// the actions to perform on restoration will be executed here
|
||||||
|
final var controller = controllerStack.peek();
|
||||||
|
if (controller instanceof Restorable) ((Restorable) controller).onRestore();
|
||||||
}
|
}
|
||||||
stage.show();
|
stage.show();
|
||||||
}
|
}
|
||||||
@ -154,7 +169,7 @@ public final class SceneContext {
|
|||||||
* @return the controller used by the current scene
|
* @return the controller used by the current scene
|
||||||
* @since Envoy Client v0.1-beta
|
* @since Envoy Client v0.1-beta
|
||||||
*/
|
*/
|
||||||
public <T> T getController() { return loader.getController(); }
|
public <T> T getController() { return (T) controllerStack.peek(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the stage in which the scenes are displayed
|
* @return the stage in which the scenes are displayed
|
||||||
|
@ -16,7 +16,6 @@ import javafx.scene.image.ImageView;
|
|||||||
import javafx.scene.input.KeyCode;
|
import javafx.scene.input.KeyCode;
|
||||||
import javafx.scene.input.KeyEvent;
|
import javafx.scene.input.KeyEvent;
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
import javafx.scene.paint.Paint;
|
|
||||||
|
|
||||||
import envoy.client.data.Chat;
|
import envoy.client.data.Chat;
|
||||||
import envoy.client.data.LocalDB;
|
import envoy.client.data.LocalDB;
|
||||||
@ -24,7 +23,12 @@ import envoy.client.data.Settings;
|
|||||||
import envoy.client.event.MessageCreationEvent;
|
import envoy.client.event.MessageCreationEvent;
|
||||||
import envoy.client.net.Client;
|
import envoy.client.net.Client;
|
||||||
import envoy.client.net.WriteProxy;
|
import envoy.client.net.WriteProxy;
|
||||||
import envoy.client.ui.*;
|
import envoy.client.ui.IconUtil;
|
||||||
|
import envoy.client.ui.Restorable;
|
||||||
|
import envoy.client.ui.SceneContext;
|
||||||
|
import envoy.client.ui.listcell.ContactListCellFactory;
|
||||||
|
import envoy.client.ui.listcell.MessageControl;
|
||||||
|
import envoy.client.ui.listcell.MessageListCellFactory;
|
||||||
import envoy.data.*;
|
import envoy.data.*;
|
||||||
import envoy.event.*;
|
import envoy.event.*;
|
||||||
import envoy.event.contact.ContactOperation;
|
import envoy.event.contact.ContactOperation;
|
||||||
@ -38,7 +42,7 @@ import envoy.util.EnvoyLog;
|
|||||||
* @author Kai S. K. Engelbart
|
* @author Kai S. K. Engelbart
|
||||||
* @since Envoy Client v0.1-beta
|
* @since Envoy Client v0.1-beta
|
||||||
*/
|
*/
|
||||||
public final class ChatScene {
|
public final class ChatScene implements Restorable {
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private Label contactLabel;
|
private Label contactLabel;
|
||||||
@ -90,26 +94,16 @@ public final class ChatScene {
|
|||||||
private void initialize() {
|
private void initialize() {
|
||||||
|
|
||||||
// Initialize message and user rendering
|
// Initialize message and user rendering
|
||||||
messageList.setCellFactory(listView -> new MessageListCell());
|
messageList.setCellFactory(MessageListCellFactory::new);
|
||||||
userList.setCellFactory(listView -> new ContactListCell());
|
userList.setCellFactory(ContactListCellFactory::new);
|
||||||
|
|
||||||
settingsButton.setGraphic(new ImageView(IconUtil.load("/icons/settings.png", 16)));
|
settingsButton.setGraphic(new ImageView(IconUtil.load("/icons/settings.png", 16)));
|
||||||
|
|
||||||
// Listen to received messages
|
// Listen to received messages
|
||||||
eventBus.register(MessageCreationEvent.class, e -> {
|
eventBus.register(MessageCreationEvent.class, e -> {
|
||||||
final var message = e.get();
|
final var message = e.get();
|
||||||
if (message.getClass().equals(Message.class)) {
|
localDB.getChat(message instanceof GroupMessage ? message.getSenderID() : message.getRecipientID()).ifPresent(chat -> {
|
||||||
localDB.getChat(message.getSenderID()).ifPresent(chat -> {
|
chat.insert(message);
|
||||||
chat.getMessages().add(message);
|
|
||||||
|
|
||||||
// Update UI if in current chat
|
|
||||||
if (chat == currentChat)
|
|
||||||
Platform.runLater(messageList::refresh);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
localDB.getChat(message.getRecipientID()).ifPresent(chat -> {
|
|
||||||
chat.getMessages().add(message);
|
|
||||||
|
|
||||||
if (chat.equals(currentChat)) {
|
if (chat.equals(currentChat)) {
|
||||||
try {
|
try {
|
||||||
currentChat.read(writeProxy);
|
currentChat.read(writeProxy);
|
||||||
@ -119,7 +113,6 @@ public final class ChatScene {
|
|||||||
Platform.runLater(() -> { messageList.refresh(); scrollToMessageListEnd(); });
|
Platform.runLater(() -> { messageList.refresh(); scrollToMessageListEnd(); });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Listen to message status changes
|
// Listen to message status changes
|
||||||
@ -180,10 +173,13 @@ public final class ChatScene {
|
|||||||
|
|
||||||
userList.setItems(FXCollections.observableList(localDB.getChats().stream().map(Chat::getRecipient).collect(Collectors.toList())));
|
userList.setItems(FXCollections.observableList(localDB.getChats().stream().map(Chat::getRecipient).collect(Collectors.toList())));
|
||||||
contactLabel.setText(localDB.getUser().getName());
|
contactLabel.setText(localDB.getUser().getName());
|
||||||
MessageListCell.setUser(localDB.getUser());
|
MessageControl.setUser(localDB.getUser());
|
||||||
if (!client.isOnline()) updateInfoLabel("You are offline", Color.YELLOW);
|
if (!client.isOnline()) updateInfoLabel("You are offline", "infoLabel-info");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRestore() { updateRemainingCharsLabel(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Actions to perform when the list of contacts has been clicked.
|
* Actions to perform when the list of contacts has been clicked.
|
||||||
*
|
*
|
||||||
@ -193,7 +189,6 @@ public final class ChatScene {
|
|||||||
private void userListClicked() {
|
private void userListClicked() {
|
||||||
final Contact user = userList.getSelectionModel().getSelectedItem();
|
final Contact user = userList.getSelectionModel().getSelectedItem();
|
||||||
if (user != null && (currentChat == null || !user.equals(currentChat.getRecipient()))) {
|
if (user != null && (currentChat == null || !user.equals(currentChat.getRecipient()))) {
|
||||||
logger.log(Level.FINEST, "Loading chat with " + user);
|
|
||||||
|
|
||||||
// LEON: JFC <===> JAVA FRIED CHICKEN <=/=> Java Foundation Classes
|
// LEON: JFC <===> JAVA FRIED CHICKEN <=/=> Java Foundation Classes
|
||||||
|
|
||||||
@ -201,6 +196,9 @@ public final class ChatScene {
|
|||||||
currentChat = localDB.getChat(user.getID()).get();
|
currentChat = localDB.getChat(user.getID()).get();
|
||||||
|
|
||||||
messageList.setItems(FXCollections.observableList(currentChat.getMessages()));
|
messageList.setItems(FXCollections.observableList(currentChat.getMessages()));
|
||||||
|
final var scrollIndex = messageList.getItems().size() - 1;
|
||||||
|
messageList.scrollTo(scrollIndex);
|
||||||
|
logger.log(Level.FINEST, "Loading chat with " + user + " at index " + scrollIndex);
|
||||||
deleteContactMenuItem.setText("Delete " + user.getName());
|
deleteContactMenuItem.setText("Delete " + user.getName());
|
||||||
|
|
||||||
// Read the current chat
|
// Read the current chat
|
||||||
@ -271,7 +269,7 @@ public final class ChatScene {
|
|||||||
if (!infoLabel.getText().equals(noMoreMessaging))
|
if (!infoLabel.getText().equals(noMoreMessaging))
|
||||||
// Informing the user that he is a f*cking moron and should use Envoy online
|
// Informing the user that he is a f*cking moron and should use Envoy online
|
||||||
// because he ran out of messageIDs to use
|
// because he ran out of messageIDs to use
|
||||||
updateInfoLabel(noMoreMessaging, Color.RED);
|
updateInfoLabel(noMoreMessaging, "infoLabel-error");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -317,35 +315,24 @@ public final class ChatScene {
|
|||||||
postButton.setDisable(true);
|
postButton.setDisable(true);
|
||||||
messageTextArea.setDisable(true);
|
messageTextArea.setDisable(true);
|
||||||
messageTextArea.clear();
|
messageTextArea.clear();
|
||||||
updateInfoLabel("You need to go online to send more messages", Color.RED);
|
updateInfoLabel("You need to go online to send more messages", "infoLabel-error");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final var text = messageTextArea.getText().strip();
|
final var text = messageTextArea.getText().strip();
|
||||||
if (text.isBlank()) throw new IllegalArgumentException("A message without visible text can not be sent.");
|
if (text.isBlank()) throw new IllegalArgumentException("A message without visible text can not be sent.");
|
||||||
try {
|
try {
|
||||||
if (currentChat.getRecipient().getClass().equals(Group.class)) {
|
|
||||||
// Create and send groupMessage
|
|
||||||
final var groupMessage = new MessageBuilder(localDB.getUser().getID(), currentChat.getRecipient().getID(), localDB.getIDGenerator())
|
|
||||||
.setText(messageTextArea.getText().strip())
|
|
||||||
.buildGroupMessage((Group) currentChat.getRecipient());
|
|
||||||
|
|
||||||
// Send groupMessage
|
|
||||||
writeProxy.writeMessage(groupMessage);
|
|
||||||
|
|
||||||
// Add message to LocalDB and update UI
|
|
||||||
messageList.getItems().add(groupMessage);
|
|
||||||
} else {
|
|
||||||
// Create and send message
|
// Create and send message
|
||||||
final var message = new MessageBuilder(localDB.getUser().getID(), currentChat.getRecipient().getID(), localDB.getIDGenerator())
|
final var builder = new MessageBuilder(localDB.getUser().getID(), currentChat.getRecipient().getID(), localDB.getIDGenerator())
|
||||||
.setText(messageTextArea.getText().strip())
|
.setText(text);
|
||||||
.build();
|
final var message = currentChat.getRecipient() instanceof Group ? builder.buildGroupMessage((Group) currentChat.getRecipient())
|
||||||
|
: builder.build();
|
||||||
|
|
||||||
// Send message
|
// Send message
|
||||||
writeProxy.writeMessage(message);
|
writeProxy.writeMessage(message);
|
||||||
|
|
||||||
// Add message to LocalDB and update UI
|
// Add message to LocalDB and update UI
|
||||||
messageList.getItems().add(message);
|
currentChat.insert(message);
|
||||||
}
|
messageList.refresh();
|
||||||
scrollToMessageListEnd();
|
scrollToMessageListEnd();
|
||||||
|
|
||||||
// Request a new ID generator if all IDs were used
|
// Request a new ID generator if all IDs were used
|
||||||
@ -373,12 +360,13 @@ public final class ChatScene {
|
|||||||
* Updates the {@code infoLabel}.
|
* Updates the {@code infoLabel}.
|
||||||
*
|
*
|
||||||
* @param text the text to use
|
* @param text the text to use
|
||||||
* @param textfill the color in which to display information
|
* @param infoLabelID the id the the {@code infoLabel} should have so that it
|
||||||
|
* can be styled accordingly in CSS
|
||||||
* @since Envoy Client v0.1-beta
|
* @since Envoy Client v0.1-beta
|
||||||
*/
|
*/
|
||||||
private void updateInfoLabel(String text, Paint textfill) {
|
private void updateInfoLabel(String text, String infoLabelID) {
|
||||||
infoLabel.setText(text);
|
infoLabel.setText(text);
|
||||||
infoLabel.setTextFill(textfill);
|
infoLabel.setId(infoLabelID);
|
||||||
infoLabel.setVisible(true);
|
infoLabel.setVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -414,4 +402,7 @@ public final class ChatScene {
|
|||||||
updateRemainingCharsLabel();
|
updateRemainingCharsLabel();
|
||||||
postButton.setDisable(messageText.isBlank());
|
postButton.setDisable(messageText.isBlank());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private void loadMessageInfoScene() { try {} catch (final NullPointerException e) {} }
|
||||||
}
|
}
|
||||||
|
@ -5,13 +5,16 @@ import java.util.logging.Logger;
|
|||||||
|
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.scene.control.*;
|
import javafx.scene.control.Alert;
|
||||||
import javafx.scene.control.Alert.AlertType;
|
import javafx.scene.control.Alert.AlertType;
|
||||||
|
import javafx.scene.control.ButtonType;
|
||||||
|
import javafx.scene.control.ListView;
|
||||||
|
|
||||||
import envoy.client.data.LocalDB;
|
import envoy.client.data.LocalDB;
|
||||||
import envoy.client.event.SendEvent;
|
import envoy.client.event.SendEvent;
|
||||||
import envoy.client.ui.ContactListCell;
|
import envoy.client.ui.ClearableTextField;
|
||||||
import envoy.client.ui.SceneContext;
|
import envoy.client.ui.SceneContext;
|
||||||
|
import envoy.client.ui.listcell.ContactListCellFactory;
|
||||||
import envoy.data.Contact;
|
import envoy.data.Contact;
|
||||||
import envoy.event.ElementOperation;
|
import envoy.event.ElementOperation;
|
||||||
import envoy.event.EventBus;
|
import envoy.event.EventBus;
|
||||||
@ -31,19 +34,7 @@ import envoy.util.EnvoyLog;
|
|||||||
public class ContactSearchScene {
|
public class ContactSearchScene {
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private Button backButton;
|
private ClearableTextField searchBar;
|
||||||
|
|
||||||
@FXML
|
|
||||||
private Button clearButton;
|
|
||||||
|
|
||||||
@FXML
|
|
||||||
private Button searchButton;
|
|
||||||
|
|
||||||
@FXML
|
|
||||||
private Button newGroupButton;
|
|
||||||
|
|
||||||
@FXML
|
|
||||||
private TextField searchBar;
|
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private ListView<Contact> contactList;
|
private ListView<Contact> contactList;
|
||||||
@ -67,7 +58,8 @@ public class ContactSearchScene {
|
|||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private void initialize() {
|
private void initialize() {
|
||||||
contactList.setCellFactory(e -> new ContactListCell());
|
contactList.setCellFactory(ContactListCellFactory::new);
|
||||||
|
searchBar.setClearButtonListener(e -> { searchBar.getTextField().clear(); contactList.getItems().clear(); });
|
||||||
eventBus.register(ContactSearchResult.class,
|
eventBus.register(ContactSearchResult.class,
|
||||||
response -> Platform.runLater(() -> { contactList.getItems().clear(); contactList.getItems().addAll(response.get()); }));
|
response -> Platform.runLater(() -> { contactList.getItems().clear(); contactList.getItems().addAll(response.get()); }));
|
||||||
}
|
}
|
||||||
@ -78,20 +70,12 @@ public class ContactSearchScene {
|
|||||||
* @since Envoy Client v0.1-beta
|
* @since Envoy Client v0.1-beta
|
||||||
*/
|
*/
|
||||||
@FXML
|
@FXML
|
||||||
private void checkClearButton() {
|
private void sendRequest() {
|
||||||
final var containsContent = searchBar.getText().strip().isEmpty();
|
final var text = searchBar.getTextField().getText().strip();
|
||||||
clearButton.setDisable(containsContent);
|
if (!text.isBlank()) eventBus.dispatch(new SendEvent(new ContactSearchRequest(text)));
|
||||||
searchButton.setDisable(containsContent);
|
else contactList.getItems().clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends a {@link ContactSearchRequest} to the server.
|
|
||||||
*
|
|
||||||
* @since Envoy Client v0.1-beta
|
|
||||||
*/
|
|
||||||
@FXML
|
|
||||||
private void suggestContacts() { eventBus.dispatch(new SendEvent(new ContactSearchRequest(searchBar.getText()))); }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears the text in the search bar and the items shown in the list.
|
* Clears the text in the search bar and the items shown in the list.
|
||||||
* Additionally disables both clear and search button.
|
* Additionally disables both clear and search button.
|
||||||
@ -100,10 +84,8 @@ public class ContactSearchScene {
|
|||||||
*/
|
*/
|
||||||
@FXML
|
@FXML
|
||||||
private void clear() {
|
private void clear() {
|
||||||
searchBar.setText(null);
|
searchBar.getTextField().setText(null);
|
||||||
contactList.getItems().clear();
|
contactList.getItems().clear();
|
||||||
clearButton.setDisable(true);
|
|
||||||
searchButton.setDisable(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -119,14 +101,17 @@ public class ContactSearchScene {
|
|||||||
final var alert = new Alert(AlertType.CONFIRMATION);
|
final var alert = new Alert(AlertType.CONFIRMATION);
|
||||||
alert.setTitle("Add Contact to Contact List");
|
alert.setTitle("Add Contact to Contact List");
|
||||||
alert.setHeaderText("Add the user " + contact.getName() + " to your contact list?");
|
alert.setHeaderText("Add the user " + contact.getName() + " to your contact list?");
|
||||||
alert.showAndWait().filter(btn -> btn == ButtonType.OK).ifPresent(btn -> {
|
// Normally, this would be total BS (we are already on the FX Thread), however
|
||||||
|
// it could be proven that the creation of this dialog wrapped in
|
||||||
|
// Platform.runLater is less error-prone than without it
|
||||||
|
Platform.runLater(() -> alert.showAndWait().filter(btn -> btn == ButtonType.OK).ifPresent(btn -> {
|
||||||
final var event = new ContactOperation(contact, ElementOperation.ADD);
|
final var event = new ContactOperation(contact, ElementOperation.ADD);
|
||||||
// Sends the event to the server
|
// Sends the event to the server
|
||||||
eventBus.dispatch(new SendEvent(event));
|
eventBus.dispatch(new SendEvent(event));
|
||||||
// Updates the UI
|
// Updates the UI
|
||||||
eventBus.dispatch(event);
|
eventBus.dispatch(event);
|
||||||
logger.log(Level.INFO, "Added contact " + contact);
|
logger.log(Level.INFO, "Added contact " + contact);
|
||||||
});
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,8 +9,9 @@ import javafx.scene.control.Alert.AlertType;
|
|||||||
|
|
||||||
import envoy.client.data.LocalDB;
|
import envoy.client.data.LocalDB;
|
||||||
import envoy.client.event.SendEvent;
|
import envoy.client.event.SendEvent;
|
||||||
import envoy.client.ui.ContactListCell;
|
import envoy.client.ui.ClearableTextField;
|
||||||
import envoy.client.ui.SceneContext;
|
import envoy.client.ui.SceneContext;
|
||||||
|
import envoy.client.ui.listcell.ContactListCellFactory;
|
||||||
import envoy.data.Contact;
|
import envoy.data.Contact;
|
||||||
import envoy.event.EventBus;
|
import envoy.event.EventBus;
|
||||||
import envoy.event.GroupCreation;
|
import envoy.event.GroupCreation;
|
||||||
@ -30,7 +31,7 @@ public class GroupCreationScene {
|
|||||||
private Button createButton;
|
private Button createButton;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private TextField groupNameField;
|
private ClearableTextField groupNameField;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private ListView<Contact> contactList;
|
private ListView<Contact> contactList;
|
||||||
@ -41,8 +42,9 @@ public class GroupCreationScene {
|
|||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private void initialize() {
|
private void initialize() {
|
||||||
contactList.setCellFactory(e -> new ContactListCell());
|
contactList.setCellFactory(ContactListCellFactory::new);
|
||||||
contactList.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
|
contactList.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
|
||||||
|
groupNameField.setClearButtonListener(e -> { groupNameField.getTextField().clear(); createButton.setDisable(true); });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -63,7 +65,18 @@ public class GroupCreationScene {
|
|||||||
* @since Envoy Client v0.1-beta
|
* @since Envoy Client v0.1-beta
|
||||||
*/
|
*/
|
||||||
@FXML
|
@FXML
|
||||||
private void contactListClicked() { createButton.setDisable(contactList.getSelectionModel().isEmpty()); }
|
private void contactListClicked() {
|
||||||
|
createButton.setDisable(contactList.getSelectionModel().isEmpty() || groupNameField.getTextField().getText().isBlank());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks, whether the {@code createButton} can be enabled because text is
|
||||||
|
* present in the textfield.
|
||||||
|
*
|
||||||
|
* @since Envoy Client v0.1-beta
|
||||||
|
*/
|
||||||
|
@FXML
|
||||||
|
private void textUpdated() { createButton.setDisable(groupNameField.getTextField().getText().isBlank()); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a {@link GroupCreation} to the server and closes this scene.
|
* Sends a {@link GroupCreation} to the server and closes this scene.
|
||||||
@ -74,10 +87,10 @@ public class GroupCreationScene {
|
|||||||
*/
|
*/
|
||||||
@FXML
|
@FXML
|
||||||
private void createButtonClicked() {
|
private void createButtonClicked() {
|
||||||
final var name = groupNameField.getText();
|
final var name = groupNameField.getTextField().getText();
|
||||||
if (!Bounds.isValidContactName(name)) {
|
if (!Bounds.isValidContactName(name)) {
|
||||||
new Alert(AlertType.ERROR, "The entered group name is not valid (" + Bounds.CONTACT_NAME_PATTERN + ")").showAndWait();
|
new Alert(AlertType.ERROR, "The entered group name is not valid (" + Bounds.CONTACT_NAME_PATTERN + ")").showAndWait();
|
||||||
groupNameField.clear();
|
groupNameField.getTextField().clear();
|
||||||
} else {
|
} else {
|
||||||
eventBus.dispatch(new SendEvent(new GroupCreation(name,
|
eventBus.dispatch(new SendEvent(new GroupCreation(name,
|
||||||
contactList.getSelectionModel().getSelectedItems().stream().map(Contact::getID).collect(Collectors.toSet()))));
|
contactList.getSelectionModel().getSelectedItems().stream().map(Contact::getID).collect(Collectors.toSet()))));
|
||||||
|
@ -13,6 +13,7 @@ import javafx.scene.control.Alert.AlertType;
|
|||||||
|
|
||||||
import envoy.client.data.*;
|
import envoy.client.data.*;
|
||||||
import envoy.client.net.Client;
|
import envoy.client.net.Client;
|
||||||
|
import envoy.client.ui.ClearableTextField;
|
||||||
import envoy.client.ui.SceneContext;
|
import envoy.client.ui.SceneContext;
|
||||||
import envoy.client.ui.Startup;
|
import envoy.client.ui.Startup;
|
||||||
import envoy.data.*;
|
import envoy.data.*;
|
||||||
@ -34,7 +35,7 @@ import envoy.util.EnvoyLog;
|
|||||||
public final class LoginScene {
|
public final class LoginScene {
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private TextField userTextField;
|
private ClearableTextField userTextField;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private PasswordField passwordField;
|
private PasswordField passwordField;
|
||||||
@ -119,17 +120,17 @@ public final class LoginScene {
|
|||||||
if (registerCheckBox.isSelected() && !passwordField.getText().equals(repeatPasswordField.getText())) {
|
if (registerCheckBox.isSelected() && !passwordField.getText().equals(repeatPasswordField.getText())) {
|
||||||
new Alert(AlertType.ERROR, "The entered password is unequal to the repeated one").showAndWait();
|
new Alert(AlertType.ERROR, "The entered password is unequal to the repeated one").showAndWait();
|
||||||
repeatPasswordField.clear();
|
repeatPasswordField.clear();
|
||||||
} else if (!Bounds.isValidContactName(userTextField.getText())) {
|
} else if (!Bounds.isValidContactName(userTextField.getTextField().getText())) {
|
||||||
new Alert(AlertType.ERROR, "The entered user name is not valid (" + Bounds.CONTACT_NAME_PATTERN + ")").showAndWait();
|
new Alert(AlertType.ERROR, "The entered user name is not valid (" + Bounds.CONTACT_NAME_PATTERN + ")").showAndWait();
|
||||||
userTextField.clear();
|
userTextField.getTextField().clear();
|
||||||
} else
|
} else performHandshake(new LoginCredentials(userTextField.getTextField().getText(), passwordField.getText().toCharArray(),
|
||||||
performHandshake(
|
registerCheckBox.isSelected(), Startup.VERSION));
|
||||||
new LoginCredentials(userTextField.getText(), passwordField.getText().toCharArray(), registerCheckBox.isSelected(), Startup.VERSION));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private void offlineModeButtonPressed() {
|
private void offlineModeButtonPressed() {
|
||||||
attemptOfflineMode(new LoginCredentials(userTextField.getText(), passwordField.getText().toCharArray(), false, Startup.VERSION));
|
attemptOfflineMode(
|
||||||
|
new LoginCredentials(userTextField.getTextField().getText(), passwordField.getText().toCharArray(), false, Startup.VERSION));
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
@ -162,8 +163,7 @@ public final class LoginScene {
|
|||||||
loadChatScene();
|
loadChatScene();
|
||||||
}
|
}
|
||||||
} catch (IOException | InterruptedException | TimeoutException e) {
|
} catch (IOException | InterruptedException | TimeoutException e) {
|
||||||
logger.log(Level.WARNING, "Could not connect to server: ", e);
|
logger.log(Level.INFO, "Could not connect to server. Entering offline mode...");
|
||||||
logger.log(Level.FINER, "Attempting offline mode...");
|
|
||||||
attemptOfflineMode(credentials);
|
attemptOfflineMode(credentials);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
40
src/main/java/envoy/client/ui/listcell/ContactControl.java
Normal file
40
src/main/java/envoy/client/ui/listcell/ContactControl.java
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
package envoy.client.ui.listcell;
|
||||||
|
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.layout.VBox;
|
||||||
|
|
||||||
|
import envoy.data.Contact;
|
||||||
|
import envoy.data.Group;
|
||||||
|
import envoy.data.User;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class formats a single {@link Contact} into a UI component.
|
||||||
|
* <p>
|
||||||
|
* Project: <strong>envoy-client</strong><br>
|
||||||
|
* File: <strong>ContactControl.java</strong><br>
|
||||||
|
* Created: <strong>01.07.2020</strong><br>
|
||||||
|
*
|
||||||
|
* @author Leon Hofmeister
|
||||||
|
* @since Envoy Client v0.1-beta
|
||||||
|
*/
|
||||||
|
public class ContactControl extends VBox {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param contact the contact that should be formatted
|
||||||
|
* @since Envoy Client v0.1-beta
|
||||||
|
*/
|
||||||
|
public ContactControl(Contact contact) {
|
||||||
|
// Container with contact name
|
||||||
|
final var nameLabel = new Label(contact.getName());
|
||||||
|
nameLabel.setWrapText(true);
|
||||||
|
getChildren().add(nameLabel);
|
||||||
|
if (contact instanceof User) {
|
||||||
|
// Online status
|
||||||
|
final var user = (User) contact;
|
||||||
|
final var statusLabel = new Label(user.getStatus().toString());
|
||||||
|
statusLabel.getStyleClass().add(user.getStatus().toString().toLowerCase());
|
||||||
|
getChildren().add(statusLabel);
|
||||||
|
} else // Member count
|
||||||
|
getChildren().add(new Label(((Group) contact).getContacts().size() + " members"));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
package envoy.client.ui.listcell;
|
||||||
|
|
||||||
|
import javafx.scene.control.ListCell;
|
||||||
|
import javafx.scene.control.ListView;
|
||||||
|
|
||||||
|
import envoy.data.Contact;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Project: <strong>envoy-client</strong><br>
|
||||||
|
* File: <strong>UserListCell.java</strong><br>
|
||||||
|
* Created: <strong>28.03.2020</strong><br>
|
||||||
|
*
|
||||||
|
* @author Kai S. K. Engelbart
|
||||||
|
* @since Envoy Client v0.1-beta
|
||||||
|
*/
|
||||||
|
public class ContactListCellFactory extends ListCell<Contact> {
|
||||||
|
|
||||||
|
private final ListView<Contact> listView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param listView the list view inside which this cell is contained
|
||||||
|
* @since Envoy Client v0.1-beta
|
||||||
|
*/
|
||||||
|
public ContactListCellFactory(ListView<Contact> listView) { this.listView = listView; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays the name of a contact. If the contact is a user, their online status
|
||||||
|
* is displayed as well.
|
||||||
|
*
|
||||||
|
* @since Envoy Client v0.1-beta
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void updateItem(Contact contact, boolean empty) {
|
||||||
|
super.updateItem(contact, empty);
|
||||||
|
if (empty || contact == null) {
|
||||||
|
setText(null);
|
||||||
|
setGraphic(null);
|
||||||
|
} else {
|
||||||
|
final var control = new ContactControl(contact);
|
||||||
|
prefWidthProperty().bind(listView.widthProperty().subtract(40));
|
||||||
|
setGraphic(control);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
60
src/main/java/envoy/client/ui/listcell/MessageControl.java
Normal file
60
src/main/java/envoy/client/ui/listcell/MessageControl.java
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
package envoy.client.ui.listcell;
|
||||||
|
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javafx.geometry.Insets;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.image.Image;
|
||||||
|
import javafx.scene.image.ImageView;
|
||||||
|
import javafx.scene.layout.VBox;
|
||||||
|
|
||||||
|
import envoy.client.ui.IconUtil;
|
||||||
|
import envoy.data.Message;
|
||||||
|
import envoy.data.Message.MessageStatus;
|
||||||
|
import envoy.data.User;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class formats a single {@link Message} into a UI component.
|
||||||
|
* <p>
|
||||||
|
* Project: <strong>envoy-client</strong><br>
|
||||||
|
* File: <strong>MessageControl.java</strong><br>
|
||||||
|
* Created: <strong>01.07.2020</strong><br>
|
||||||
|
*
|
||||||
|
* @author Leon Hofmeister
|
||||||
|
* @since Envoy Client v0.1-beta
|
||||||
|
*/
|
||||||
|
public class MessageControl extends VBox {
|
||||||
|
|
||||||
|
private static User client;
|
||||||
|
private static final DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm");
|
||||||
|
private static final Map<MessageStatus, Image> statusImages = IconUtil.loadByEnum(MessageStatus.class, 16);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param message the message that should be formatted
|
||||||
|
* @since Envoy Client v0.1-beta
|
||||||
|
*/
|
||||||
|
public MessageControl(Message message) {
|
||||||
|
// Creating the underlying VBox, the dateLabel and the textLabel
|
||||||
|
super(new Label(dateFormat.format(message.getCreationDate())));
|
||||||
|
final var textLabel = new Label(message.getText());
|
||||||
|
textLabel.setWrapText(true);
|
||||||
|
getChildren().add(textLabel);
|
||||||
|
// Setting the message status icon and background color
|
||||||
|
if (message.getRecipientID() != client.getID()) {
|
||||||
|
final var statusIcon = new ImageView(statusImages.get(message.getStatus()));
|
||||||
|
statusIcon.setPreserveRatio(true);
|
||||||
|
getChildren().add(statusIcon);
|
||||||
|
getStyleClass().add("own-message");
|
||||||
|
} else getStyleClass().add("received-message");
|
||||||
|
// Adjusting height and weight of the cell to the corresponding ListView
|
||||||
|
paddingProperty().setValue(new Insets(5, 20, 5, 20));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param client the user who has logged in
|
||||||
|
* @since Envoy Client v0.1-beta
|
||||||
|
*/
|
||||||
|
public static void setUser(User client) { MessageControl.client = client; }
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
package envoy.client.ui.listcell;
|
||||||
|
|
||||||
|
import javafx.scene.control.ListCell;
|
||||||
|
import javafx.scene.control.ListView;
|
||||||
|
import javafx.scene.control.Tooltip;
|
||||||
|
import javafx.stage.PopupWindow.AnchorLocation;
|
||||||
|
|
||||||
|
import envoy.data.Message;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays a single message inside the message list.
|
||||||
|
* <p>
|
||||||
|
* Project: <strong>envoy-client</strong><br>
|
||||||
|
* File: <strong>MessageListCellFactory.java</strong><br>
|
||||||
|
* Created: <strong>28.03.2020</strong><br>
|
||||||
|
*
|
||||||
|
* @author Kai S. K. Engelbart
|
||||||
|
* @since Envoy Client v0.1-beta
|
||||||
|
*/
|
||||||
|
public class MessageListCellFactory extends ListCell<Message> {
|
||||||
|
|
||||||
|
private final ListView<Message> listView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param listView the list view inside which this cell is contained
|
||||||
|
* @since Envoy Client v0.1-beta
|
||||||
|
*/
|
||||||
|
public MessageListCellFactory(ListView<Message> listView) { this.listView = listView; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays the text, the data of creation and the status of a message.
|
||||||
|
*
|
||||||
|
* @since Envoy v0.1-beta
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void updateItem(Message message, boolean empty) {
|
||||||
|
super.updateItem(message, empty);
|
||||||
|
if (empty || message == null) {
|
||||||
|
setText(null);
|
||||||
|
setGraphic(null);
|
||||||
|
} else {
|
||||||
|
final var control = new MessageControl(message);
|
||||||
|
control.prefWidthProperty().bind(listView.widthProperty().subtract(40));
|
||||||
|
// Creating the Tooltip to deselect a message
|
||||||
|
final var tooltip = new Tooltip("You can select a message by clicking on it \nand deselect it by pressing \"ctrl\" and clicking on it");
|
||||||
|
tooltip.setWrapText(true);
|
||||||
|
tooltip.setAnchorLocation(AnchorLocation.WINDOW_TOP_LEFT);
|
||||||
|
setTooltip(tooltip);
|
||||||
|
setGraphic(control);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
src/main/java/envoy/client/ui/listcell/package-info.java
Normal file
12
src/main/java/envoy/client/ui/listcell/package-info.java
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
/**
|
||||||
|
* This package contains custom list cells that are used to display certain
|
||||||
|
* things.
|
||||||
|
* <p>
|
||||||
|
* Project: <strong>envoy-client</strong><br>
|
||||||
|
* File: <strong>package-info.java</strong><br>
|
||||||
|
* Created: <strong>30.06.2020</strong><br>
|
||||||
|
*
|
||||||
|
* @author Leon Hofmeister
|
||||||
|
* @since Envoy Client v0.1-beta
|
||||||
|
*/
|
||||||
|
package envoy.client.ui.listcell;
|
BIN
src/main/other/CustomComponents.jar
Normal file
BIN
src/main/other/CustomComponents.jar
Normal file
Binary file not shown.
@ -3,7 +3,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.context-menu, .context-menu > * {
|
.context-menu, .context-menu > * {
|
||||||
-fx-background-radius: 15px;
|
-fx-background-radius: 15.0px;
|
||||||
/*TODO: solution below does not work */
|
/*TODO: solution below does not work */
|
||||||
-fx-background-color: transparent;
|
-fx-background-color: transparent;
|
||||||
}
|
}
|
||||||
@ -58,3 +58,19 @@
|
|||||||
-fx-text-fill: #00FF00;
|
-fx-text-fill: #00FF00;
|
||||||
-fx-background-color: transparent;
|
-fx-background-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#infoLabel-success {
|
||||||
|
-fx-text-fill: #00FF00;
|
||||||
|
}
|
||||||
|
|
||||||
|
#infoLabel-info {
|
||||||
|
-fx-text-fill: yellow;
|
||||||
|
}
|
||||||
|
|
||||||
|
#infoLabel-warning {
|
||||||
|
-fx-text-fill: orange;
|
||||||
|
}
|
||||||
|
|
||||||
|
#infoLabel-error {
|
||||||
|
-fx-text-fill: red;
|
||||||
|
}
|
||||||
|
@ -12,9 +12,9 @@
|
|||||||
<?import javafx.scene.layout.GridPane?>
|
<?import javafx.scene.layout.GridPane?>
|
||||||
<?import javafx.scene.layout.RowConstraints?>
|
<?import javafx.scene.layout.RowConstraints?>
|
||||||
|
|
||||||
<GridPane maxHeight="-Infinity" maxWidth="-Infinity"
|
<GridPane hgap="5.0" maxHeight="-Infinity" maxWidth="-Infinity"
|
||||||
minHeight="400.0" minWidth="350.0" prefHeight="400.0" prefWidth="600.0"
|
minHeight="400.0" minWidth="350.0" prefHeight="400.0" prefWidth="600.0"
|
||||||
xmlns="http://javafx.com/javafx/11.0.1"
|
vgap="2.0" xmlns="http://javafx.com/javafx/11.0.1"
|
||||||
xmlns:fx="http://javafx.com/fxml/1"
|
xmlns:fx="http://javafx.com/fxml/1"
|
||||||
fx:controller="envoy.client.ui.controller.ChatScene">
|
fx:controller="envoy.client.ui.controller.ChatScene">
|
||||||
<columnConstraints>
|
<columnConstraints>
|
||||||
@ -47,7 +47,7 @@
|
|||||||
prefHeight="211.0" prefWidth="300.0" GridPane.rowIndex="1"
|
prefHeight="211.0" prefWidth="300.0" GridPane.rowIndex="1"
|
||||||
GridPane.rowSpan="2147483647">
|
GridPane.rowSpan="2147483647">
|
||||||
<GridPane.margin>
|
<GridPane.margin>
|
||||||
<Insets bottom="10.0" left="10.0" right="5.0" top="5.0" />
|
<Insets bottom="10.0" left="10.0" />
|
||||||
</GridPane.margin>
|
</GridPane.margin>
|
||||||
<padding>
|
<padding>
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
@ -64,7 +64,7 @@
|
|||||||
<Label fx:id="contactLabel" prefHeight="16.0" prefWidth="250.0"
|
<Label fx:id="contactLabel" prefHeight="16.0" prefWidth="250.0"
|
||||||
text="Select a contact to chat with" GridPane.columnSpan="2">
|
text="Select a contact to chat with" GridPane.columnSpan="2">
|
||||||
<GridPane.margin>
|
<GridPane.margin>
|
||||||
<Insets left="15.0" right="5.0" top="5.0" />
|
<Insets left="10.0" />
|
||||||
</GridPane.margin>
|
</GridPane.margin>
|
||||||
<padding>
|
<padding>
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
@ -75,17 +75,18 @@
|
|||||||
GridPane.columnIndex="1" GridPane.columnSpan="2"
|
GridPane.columnIndex="1" GridPane.columnSpan="2"
|
||||||
GridPane.halignment="RIGHT" GridPane.valignment="CENTER">
|
GridPane.halignment="RIGHT" GridPane.valignment="CENTER">
|
||||||
<GridPane.margin>
|
<GridPane.margin>
|
||||||
<Insets bottom="10.0" left="5.0" right="10.0" top="10.0" />
|
<Insets bottom="10.0" right="10.0" top="10.0" />
|
||||||
</GridPane.margin>
|
</GridPane.margin>
|
||||||
<padding>
|
<padding>
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
</padding>
|
</padding>
|
||||||
</Button>
|
</Button>
|
||||||
<ListView fx:id="messageList" prefHeight="257.0"
|
<ListView fx:id="messageList" prefHeight="257.0"
|
||||||
prefWidth="465.0" GridPane.columnIndex="1" GridPane.columnSpan="2"
|
prefWidth="465.0" GridPane.columnIndex="1"
|
||||||
GridPane.rowIndex="1" GridPane.rowSpan="2">
|
GridPane.columnSpan="2147483647" GridPane.rowIndex="1"
|
||||||
|
GridPane.rowSpan="2">
|
||||||
<GridPane.margin>
|
<GridPane.margin>
|
||||||
<Insets bottom="5.0" left="5.0" right="10.0" top="5.0" />
|
<Insets left="5.0" right="10.0" />
|
||||||
</GridPane.margin>
|
</GridPane.margin>
|
||||||
<padding>
|
<padding>
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
@ -101,6 +102,8 @@
|
|||||||
onAction="#forwardMessage" text="Forward" />
|
onAction="#forwardMessage" text="Forward" />
|
||||||
<MenuItem mnemonicParsing="false"
|
<MenuItem mnemonicParsing="false"
|
||||||
onAction="#quoteMessage" text="Quote" />
|
onAction="#quoteMessage" text="Quote" />
|
||||||
|
<MenuItem mnemonicParsing="false"
|
||||||
|
onAction="#loadMessageInfoScene" text="Info" />
|
||||||
</items>
|
</items>
|
||||||
</ContextMenu>
|
</ContextMenu>
|
||||||
</contextMenu>
|
</contextMenu>
|
||||||
@ -111,11 +114,8 @@
|
|||||||
GridPane.halignment="CENTER" GridPane.rowIndex="4"
|
GridPane.halignment="CENTER" GridPane.rowIndex="4"
|
||||||
GridPane.valignment="BOTTOM">
|
GridPane.valignment="BOTTOM">
|
||||||
<GridPane.margin>
|
<GridPane.margin>
|
||||||
<Insets bottom="10.0" left="5.0" right="10.0" />
|
<Insets bottom="10.0" right="10.0" />
|
||||||
</GridPane.margin>
|
</GridPane.margin>
|
||||||
<padding>
|
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
|
||||||
</padding>
|
|
||||||
<tooltip>
|
<tooltip>
|
||||||
<Tooltip anchorLocation="WINDOW_TOP_LEFT" autoHide="true"
|
<Tooltip anchorLocation="WINDOW_TOP_LEFT" autoHide="true"
|
||||||
maxWidth="350.0"
|
maxWidth="350.0"
|
||||||
@ -130,6 +130,9 @@
|
|||||||
</items>
|
</items>
|
||||||
</ContextMenu>
|
</ContextMenu>
|
||||||
</contextMenu>
|
</contextMenu>
|
||||||
|
<padding>
|
||||||
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
|
</padding>
|
||||||
</Button>
|
</Button>
|
||||||
<TextArea fx:id="messageTextArea" disable="true"
|
<TextArea fx:id="messageTextArea" disable="true"
|
||||||
onInputMethodTextChanged="#messageTextUpdated"
|
onInputMethodTextChanged="#messageTextUpdated"
|
||||||
@ -137,7 +140,7 @@
|
|||||||
prefHeight="200.0" prefWidth="200.0" wrapText="true"
|
prefHeight="200.0" prefWidth="200.0" wrapText="true"
|
||||||
GridPane.columnIndex="1" GridPane.rowIndex="4">
|
GridPane.columnIndex="1" GridPane.rowIndex="4">
|
||||||
<GridPane.margin>
|
<GridPane.margin>
|
||||||
<Insets bottom="10.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="10.0" left="5.0" top="3.0" />
|
||||||
</GridPane.margin>
|
</GridPane.margin>
|
||||||
<opaqueInsets>
|
<opaqueInsets>
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
@ -163,7 +166,7 @@
|
|||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
</GridPane.margin>
|
</GridPane.margin>
|
||||||
<padding>
|
<padding>
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="5.0" top="5.0" />
|
||||||
</padding>
|
</padding>
|
||||||
<opaqueInsets>
|
<opaqueInsets>
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
@ -175,8 +178,8 @@
|
|||||||
</tooltip>
|
</tooltip>
|
||||||
</Label>
|
</Label>
|
||||||
<Label fx:id="infoLabel" text="Something happened"
|
<Label fx:id="infoLabel" text="Something happened"
|
||||||
textFill="#faa007" visible="false" GridPane.columnIndex="1"
|
wrapText="true" textFill="#faa007" visible="false"
|
||||||
GridPane.rowIndex="1">
|
GridPane.columnIndex="1" GridPane.rowIndex="1">
|
||||||
<GridPane.margin>
|
<GridPane.margin>
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
</GridPane.margin>
|
</GridPane.margin>
|
||||||
|
@ -1,53 +1,44 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<?import envoy.client.ui.ClearableTextField?>
|
||||||
<?import javafx.geometry.Insets?>
|
<?import javafx.geometry.Insets?>
|
||||||
<?import javafx.scene.control.Button?>
|
<?import javafx.scene.control.Button?>
|
||||||
<?import javafx.scene.control.ListView?>
|
<?import javafx.scene.control.ListView?>
|
||||||
<?import javafx.scene.control.TextField?>
|
|
||||||
<?import javafx.scene.control.Tooltip?>
|
<?import javafx.scene.control.Tooltip?>
|
||||||
<?import javafx.scene.layout.HBox?>
|
<?import javafx.scene.layout.HBox?>
|
||||||
<?import javafx.scene.layout.VBox?>
|
<?import javafx.scene.layout.VBox?>
|
||||||
|
|
||||||
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="envoy.client.ui.controller.ContactSearchScene">
|
<VBox maxHeight="-Infinity" maxWidth="-Infinity"
|
||||||
|
minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0"
|
||||||
|
prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1"
|
||||||
|
xmlns:fx="http://javafx.com/fxml/1"
|
||||||
|
fx:controller="envoy.client.ui.controller.ContactSearchScene">
|
||||||
<children>
|
<children>
|
||||||
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0">
|
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0">
|
||||||
<children>
|
<children>
|
||||||
<TextField fx:id="searchBar" onInputMethodTextChanged="#checkClearButton" onKeyTyped="#checkClearButton" prefColumnCount="22" promptText="Enter username to search for">
|
<ClearableTextField fx:id="searchBar"
|
||||||
|
prefWidth="310.0">
|
||||||
|
<textField onInputMethodTextChanged="#sendRequest"
|
||||||
|
onKeyTyped="#sendRequest" prefColumnCount="22"
|
||||||
|
promptText="Enter username to search for">
|
||||||
|
</textField>
|
||||||
<HBox.margin>
|
<HBox.margin>
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="5.0" left="5.0" right="5.0" top="15.0" />
|
||||||
</HBox.margin>
|
</HBox.margin>
|
||||||
<padding>
|
<padding>
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
</padding>
|
</padding>
|
||||||
<tooltip>
|
<tooltip>
|
||||||
<Tooltip text="Enter a name. If an account by that name exists, it will be displayed below." wrapText="true" />
|
<Tooltip
|
||||||
</tooltip>
|
text="Enter a name. If an account by that name exists, it will be displayed below."
|
||||||
</TextField>
|
wrapText="true" />
|
||||||
<Button fx:id="clearButton" disable="true" mnemonicParsing="true" onAction="#clear" prefHeight="26.0" prefWidth="110.0" text="Clea_r">
|
|
||||||
<tooltip>
|
|
||||||
<Tooltip autoHide="true" text="Clears the text to the left and the elements below" wrapText="true" />
|
|
||||||
</tooltip>
|
</tooltip>
|
||||||
|
</ClearableTextField>
|
||||||
|
<Button mnemonicParsing="false"
|
||||||
|
onAction="#newGroupButtonClicked" prefHeight="26.0"
|
||||||
|
prefWidth="139.0" text="New Group">
|
||||||
<HBox.margin>
|
<HBox.margin>
|
||||||
<Insets bottom="5.0" left="5.0" right="10.0" top="5.0" />
|
<Insets bottom="5.0" left="30.0" right="5.0" top="5.0" />
|
||||||
</HBox.margin>
|
|
||||||
<padding>
|
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
|
||||||
</padding>
|
|
||||||
</Button>
|
|
||||||
<Button fx:id="searchButton" defaultButton="true" disable="true" mnemonicParsing="true" onAction="#suggestContacts" prefHeight="26.0" prefWidth="124.0" text="_Search" textOverrun="LEADING_WORD_ELLIPSIS">
|
|
||||||
<padding>
|
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
|
||||||
</padding>
|
|
||||||
<HBox.margin>
|
|
||||||
<Insets bottom="5.0" right="20.0" top="5.0" />
|
|
||||||
</HBox.margin>
|
|
||||||
<tooltip>
|
|
||||||
<Tooltip autoHide="true" text="Search for accounts with the name entered to the left" wrapText="true" />
|
|
||||||
</tooltip>
|
|
||||||
</Button>
|
|
||||||
<Button mnemonicParsing="false" onAction="#newGroupButtonClicked" prefHeight="26.0" prefWidth="139.0" text="New Group">
|
|
||||||
<HBox.margin>
|
|
||||||
<Insets bottom="5.0" left="20.0" right="5.0" top="5.0" />
|
|
||||||
</HBox.margin>
|
</HBox.margin>
|
||||||
<padding>
|
<padding>
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
@ -55,22 +46,28 @@
|
|||||||
</Button>
|
</Button>
|
||||||
</children>
|
</children>
|
||||||
</HBox>
|
</HBox>
|
||||||
<ListView fx:id="contactList" onMouseClicked="#contactListClicked" prefHeight="314.0" prefWidth="600.0">
|
<ListView fx:id="contactList"
|
||||||
|
onMouseClicked="#contactListClicked" prefHeight="314.0"
|
||||||
|
prefWidth="600.0">
|
||||||
<padding>
|
<padding>
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
</padding>
|
</padding>
|
||||||
<VBox.margin>
|
<VBox.margin>
|
||||||
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
|
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
|
||||||
</VBox.margin></ListView>
|
</VBox.margin>
|
||||||
<Button fx:id="backButton" cancelButton="true" mnemonicParsing="true" onAction="#backButtonClicked" text="_Back">
|
</ListView>
|
||||||
|
<Button cancelButton="true" mnemonicParsing="true"
|
||||||
|
onAction="#backButtonClicked" text="_Back">
|
||||||
<VBox.margin>
|
<VBox.margin>
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="10.0" left="10.0" />
|
||||||
</VBox.margin>
|
</VBox.margin>
|
||||||
<padding>
|
<padding>
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
</padding>
|
</padding>
|
||||||
<tooltip>
|
<tooltip>
|
||||||
<Tooltip autoHide="true" text="Takes you back to the screen where you can chat with others" wrapText="true" />
|
<Tooltip autoHide="true"
|
||||||
|
text="Takes you back to the screen where you can chat with others"
|
||||||
|
wrapText="true" />
|
||||||
</tooltip>
|
</tooltip>
|
||||||
</Button>
|
</Button>
|
||||||
</children>
|
</children>
|
||||||
|
@ -1,20 +1,28 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<?import envoy.client.ui.ClearableTextField?>
|
||||||
<?import javafx.geometry.Insets?>
|
<?import javafx.geometry.Insets?>
|
||||||
<?import javafx.scene.control.Button?>
|
<?import javafx.scene.control.Button?>
|
||||||
<?import javafx.scene.control.Label?>
|
<?import javafx.scene.control.Label?>
|
||||||
<?import javafx.scene.control.ListView?>
|
<?import javafx.scene.control.ListView?>
|
||||||
<?import javafx.scene.control.TextField?>
|
|
||||||
<?import javafx.scene.control.Tooltip?>
|
<?import javafx.scene.control.Tooltip?>
|
||||||
|
<?import javafx.scene.layout.BorderPane?>
|
||||||
<?import javafx.scene.layout.HBox?>
|
<?import javafx.scene.layout.HBox?>
|
||||||
<?import javafx.scene.layout.VBox?>
|
<?import javafx.scene.layout.VBox?>
|
||||||
<?import javafx.scene.text.Font?>
|
<?import javafx.scene.text.Font?>
|
||||||
|
|
||||||
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="envoy.client.ui.controller.GroupCreationScene">
|
<VBox maxHeight="-Infinity" maxWidth="-Infinity"
|
||||||
|
minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0"
|
||||||
|
prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1"
|
||||||
|
xmlns:fx="http://javafx.com/fxml/1"
|
||||||
|
fx:controller="envoy.client.ui.controller.GroupCreationScene">
|
||||||
<children>
|
<children>
|
||||||
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0">
|
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0">
|
||||||
<children>
|
<children>
|
||||||
<TextField fx:id="groupNameField" prefColumnCount="22" promptText="Enter Group Name">
|
<ClearableTextField fx:id="groupNameField">
|
||||||
|
<textField prefColumnCount="22"
|
||||||
|
promptText="Enter Group Name"
|
||||||
|
onInputMethodTextChanged="#textUpdated" onKeyTyped="#textUpdated" />
|
||||||
<HBox.margin>
|
<HBox.margin>
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
</HBox.margin>
|
</HBox.margin>
|
||||||
@ -22,46 +30,62 @@
|
|||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
</padding>
|
</padding>
|
||||||
<tooltip>
|
<tooltip>
|
||||||
<Tooltip text="Enter a name. If an account by that name exists, it will be displayed below." wrapText="true" />
|
<Tooltip
|
||||||
|
text="Enter something. A group with this name will be created."
|
||||||
|
wrapText="true" />
|
||||||
</tooltip>
|
</tooltip>
|
||||||
</TextField>
|
</ClearableTextField>
|
||||||
</children>
|
</children>
|
||||||
</HBox>
|
</HBox>
|
||||||
<Label text="Choose Members:">
|
<Label text="Choose Members:">
|
||||||
<font>
|
<font>
|
||||||
<Font size="16.0" />
|
<Font size="16.0" />
|
||||||
</font>
|
</font>
|
||||||
<VBox.margin>
|
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
|
||||||
</VBox.margin>
|
|
||||||
<padding>
|
<padding>
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
</padding>
|
</padding>
|
||||||
</Label>
|
</Label>
|
||||||
<ListView fx:id="contactList" onMouseClicked="#contactListClicked" prefHeight="314.0" prefWidth="600.0">
|
<ListView fx:id="contactList"
|
||||||
|
onMouseClicked="#contactListClicked" prefHeight="314.0"
|
||||||
|
prefWidth="600.0">
|
||||||
<VBox.margin>
|
<VBox.margin>
|
||||||
<Insets bottom="5.0" left="10.0" right="10.0" top="5.0" />
|
<Insets bottom="5.0" left="10.0" right="10.0" top="5.0" />
|
||||||
</VBox.margin>
|
</VBox.margin>
|
||||||
<padding>
|
<padding>
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
</padding></ListView>
|
</padding>
|
||||||
<Button fx:id="createButton" defaultButton="true" disable="true" mnemonicParsing="false" onAction="#createButtonClicked" text="Create">
|
</ListView>
|
||||||
<VBox.margin>
|
<BorderPane prefHeight="50.0">
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<left>
|
||||||
</VBox.margin>
|
<Button cancelButton="true" mnemonicParsing="true"
|
||||||
<padding>
|
onAction="#backButtonClicked" text="_Back"
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
BorderPane.alignment="CENTER">
|
||||||
</padding></Button>
|
|
||||||
<Button cancelButton="true" mnemonicParsing="true" onAction="#backButtonClicked" text="_Back">
|
|
||||||
<VBox.margin>
|
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
|
||||||
</VBox.margin>
|
|
||||||
<padding>
|
<padding>
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
</padding>
|
</padding>
|
||||||
<tooltip>
|
<tooltip>
|
||||||
<Tooltip autoHide="true" text="Takes you back to the screen where you can chat with others" wrapText="true" />
|
<Tooltip autoHide="true"
|
||||||
|
text="Takes you back to the screen where you can chat with others"
|
||||||
|
wrapText="true" />
|
||||||
</tooltip>
|
</tooltip>
|
||||||
|
<BorderPane.margin>
|
||||||
|
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
|
||||||
|
</BorderPane.margin>
|
||||||
</Button>
|
</Button>
|
||||||
|
</left>
|
||||||
|
<right>
|
||||||
|
<Button fx:id="createButton" alignment="CENTER_RIGHT"
|
||||||
|
defaultButton="true" disable="true" mnemonicParsing="false"
|
||||||
|
onAction="#createButtonClicked" text="Create"
|
||||||
|
BorderPane.alignment="CENTER">
|
||||||
|
<padding>
|
||||||
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
|
</padding>
|
||||||
|
<BorderPane.margin>
|
||||||
|
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
|
||||||
|
</BorderPane.margin>
|
||||||
|
</Button>
|
||||||
|
</right>
|
||||||
|
</BorderPane>
|
||||||
</children>
|
</children>
|
||||||
</VBox>
|
</VBox>
|
||||||
|
@ -1,19 +1,22 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<?import envoy.client.ui.ClearableTextField?>
|
||||||
<?import javafx.geometry.Insets?>
|
<?import javafx.geometry.Insets?>
|
||||||
<?import javafx.scene.control.Button?>
|
<?import javafx.scene.control.Button?>
|
||||||
<?import javafx.scene.control.ButtonBar?>
|
|
||||||
<?import javafx.scene.control.CheckBox?>
|
<?import javafx.scene.control.CheckBox?>
|
||||||
<?import javafx.scene.control.Label?>
|
<?import javafx.scene.control.Label?>
|
||||||
<?import javafx.scene.control.PasswordField?>
|
<?import javafx.scene.control.PasswordField?>
|
||||||
<?import javafx.scene.control.TextField?>
|
<?import javafx.scene.layout.BorderPane?>
|
||||||
<?import javafx.scene.layout.ColumnConstraints?>
|
<?import javafx.scene.layout.ColumnConstraints?>
|
||||||
<?import javafx.scene.layout.GridPane?>
|
<?import javafx.scene.layout.GridPane?>
|
||||||
<?import javafx.scene.layout.RowConstraints?>
|
<?import javafx.scene.layout.RowConstraints?>
|
||||||
<?import javafx.scene.layout.VBox?>
|
<?import javafx.scene.layout.VBox?>
|
||||||
<?import javafx.scene.text.Font?>
|
<?import javafx.scene.text.Font?>
|
||||||
|
|
||||||
<VBox prefHeight="206.0" prefWidth="440.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="envoy.client.ui.controller.LoginScene">
|
<VBox prefHeight="206.0" prefWidth="440.0"
|
||||||
|
xmlns="http://javafx.com/javafx/11.0.1"
|
||||||
|
xmlns:fx="http://javafx.com/fxml/1"
|
||||||
|
fx:controller="envoy.client.ui.controller.LoginScene">
|
||||||
<children>
|
<children>
|
||||||
<Label text="User Login">
|
<Label text="User Login">
|
||||||
<font>
|
<font>
|
||||||
@ -26,15 +29,20 @@
|
|||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
</padding>
|
</padding>
|
||||||
</Label>
|
</Label>
|
||||||
<GridPane>
|
<GridPane hgap="5.0" vgap="10.0">
|
||||||
<columnConstraints>
|
<columnConstraints>
|
||||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="40.0" prefWidth="100.0" />
|
<ColumnConstraints hgrow="SOMETIMES"
|
||||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
minWidth="10.0" percentWidth="40.0" prefWidth="100.0" />
|
||||||
|
<ColumnConstraints hgrow="SOMETIMES"
|
||||||
|
minWidth="10.0" prefWidth="100.0" />
|
||||||
</columnConstraints>
|
</columnConstraints>
|
||||||
<rowConstraints>
|
<rowConstraints>
|
||||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
<RowConstraints minHeight="10.0" prefHeight="30.0"
|
||||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
vgrow="SOMETIMES" />
|
||||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
<RowConstraints minHeight="10.0" prefHeight="30.0"
|
||||||
|
vgrow="SOMETIMES" />
|
||||||
|
<RowConstraints minHeight="10.0" prefHeight="30.0"
|
||||||
|
vgrow="SOMETIMES" />
|
||||||
</rowConstraints>
|
</rowConstraints>
|
||||||
<children>
|
<children>
|
||||||
<Label text="User Name:">
|
<Label text="User Name:">
|
||||||
@ -43,62 +51,99 @@
|
|||||||
</GridPane.margin>
|
</GridPane.margin>
|
||||||
<padding>
|
<padding>
|
||||||
<Insets bottom="2.0" left="2.0" right="2.0" top="2.0" />
|
<Insets bottom="2.0" left="2.0" right="2.0" top="2.0" />
|
||||||
</padding></Label>
|
</padding>
|
||||||
<Label text="Password" GridPane.rowIndex="1">
|
</Label>
|
||||||
|
<Label text="Password:" GridPane.rowIndex="1">
|
||||||
<padding>
|
<padding>
|
||||||
<Insets bottom="2.0" left="2.0" right="2.0" top="2.0" />
|
<Insets bottom="2.0" left="2.0" right="2.0" top="2.0" />
|
||||||
</padding>
|
</padding>
|
||||||
<GridPane.margin>
|
<GridPane.margin>
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
</GridPane.margin></Label>
|
</GridPane.margin>
|
||||||
<Label fx:id="repeatPasswordLabel" text="Repeat Password:" visible="false" GridPane.rowIndex="2">
|
</Label>
|
||||||
|
<Label fx:id="repeatPasswordLabel" text="Repeat Password:"
|
||||||
|
visible="false" GridPane.rowIndex="2">
|
||||||
<GridPane.margin>
|
<GridPane.margin>
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
</GridPane.margin>
|
</GridPane.margin>
|
||||||
<padding>
|
<padding>
|
||||||
<Insets bottom="2.0" left="2.0" right="2.0" top="2.0" />
|
<Insets bottom="2.0" left="2.0" right="2.0" top="2.0" />
|
||||||
</padding></Label>
|
</padding>
|
||||||
<TextField fx:id="userTextField" GridPane.columnIndex="1">
|
</Label>
|
||||||
|
<ClearableTextField fx:id="userTextField"
|
||||||
|
GridPane.columnIndex="1">
|
||||||
<GridPane.margin>
|
<GridPane.margin>
|
||||||
<Insets bottom="10.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="10.0" left="5.0" right="5.0" top="5.0" />
|
||||||
</GridPane.margin>
|
</GridPane.margin>
|
||||||
<padding>
|
</ClearableTextField>
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<PasswordField fx:id="passwordField"
|
||||||
</padding></TextField>
|
GridPane.columnIndex="1" GridPane.rowIndex="1">
|
||||||
<PasswordField fx:id="passwordField" GridPane.columnIndex="1" GridPane.rowIndex="1">
|
|
||||||
<GridPane.margin>
|
<GridPane.margin>
|
||||||
<Insets bottom="10.0" left="5.0" right="5.0" top="10.0" />
|
<Insets bottom="10.0" left="5.0" right="5.0" top="10.0" />
|
||||||
</GridPane.margin>
|
</GridPane.margin>
|
||||||
<padding>
|
<padding>
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
</padding></PasswordField>
|
</padding>
|
||||||
<PasswordField fx:id="repeatPasswordField" visible="false" GridPane.columnIndex="1" GridPane.rowIndex="2">
|
</PasswordField>
|
||||||
|
<PasswordField fx:id="repeatPasswordField"
|
||||||
|
visible="false" GridPane.columnIndex="1" GridPane.rowIndex="2">
|
||||||
<GridPane.margin>
|
<GridPane.margin>
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="10.0" />
|
<Insets bottom="5.0" left="5.0" right="5.0" top="10.0" />
|
||||||
</GridPane.margin>
|
</GridPane.margin>
|
||||||
<padding>
|
<padding>
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
</padding></PasswordField>
|
|
||||||
</children>
|
|
||||||
</GridPane>
|
|
||||||
<CheckBox fx:id="registerCheckBox" mnemonicParsing="true" onAction="#registerCheckboxChanged" prefHeight="17.0" prefWidth="181.0" text="_Register">
|
|
||||||
<padding>
|
|
||||||
<Insets bottom="2.0" left="2.0" right="2.0" top="2.0" />
|
|
||||||
</padding>
|
</padding>
|
||||||
|
</PasswordField>
|
||||||
|
</children>
|
||||||
<VBox.margin>
|
<VBox.margin>
|
||||||
<Insets bottom="3.0" left="3.0" right="3.0" top="3.0" />
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
</VBox.margin></CheckBox>
|
</VBox.margin>
|
||||||
<Label fx:id="connectionLabel" />
|
</GridPane>
|
||||||
<ButtonBar prefHeight="40.0" prefWidth="200.0">
|
<CheckBox fx:id="registerCheckBox" mnemonicParsing="true"
|
||||||
<buttons>
|
onAction="#registerCheckboxChanged" prefHeight="17.0"
|
||||||
<Button mnemonicParsing="false" onAction="#abortLogin" text="Close">
|
prefWidth="181.0" text="_Register">
|
||||||
|
<VBox.margin>
|
||||||
|
<Insets left="5.0" right="3.0" />
|
||||||
|
</VBox.margin>
|
||||||
|
</CheckBox>
|
||||||
|
<Label fx:id="connectionLabel">
|
||||||
|
<VBox.margin>
|
||||||
|
<Insets left="5.0" />
|
||||||
|
</VBox.margin>
|
||||||
|
</Label>
|
||||||
|
<BorderPane prefWidth="200.0">
|
||||||
|
<left>
|
||||||
|
<Button cancelButton="true" mnemonicParsing="false"
|
||||||
|
onAction="#abortLogin" text="Close" BorderPane.alignment="CENTER">
|
||||||
<padding>
|
<padding>
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
</padding>
|
</padding>
|
||||||
|
<BorderPane.margin>
|
||||||
|
<Insets />
|
||||||
|
</BorderPane.margin>
|
||||||
</Button>
|
</Button>
|
||||||
<Button mnemonicParsing="false" onAction="#offlineModeButtonPressed" text="Offline mode" />
|
</left>
|
||||||
<Button defaultButton="true" mnemonicParsing="false" onAction="#loginButtonPressed" text="Login" />
|
<center>
|
||||||
</buttons>
|
<Button mnemonicParsing="false"
|
||||||
</ButtonBar>
|
onAction="#offlineModeButtonPressed" text="Offline mode"
|
||||||
|
BorderPane.alignment="CENTER">
|
||||||
|
<BorderPane.margin>
|
||||||
|
<Insets />
|
||||||
|
</BorderPane.margin>
|
||||||
|
</Button>
|
||||||
|
</center>
|
||||||
|
<right>
|
||||||
|
<Button defaultButton="true" mnemonicParsing="false"
|
||||||
|
onAction="#loginButtonPressed" text="Login"
|
||||||
|
BorderPane.alignment="CENTER">
|
||||||
|
<BorderPane.margin>
|
||||||
|
<Insets />
|
||||||
|
</BorderPane.margin>
|
||||||
|
</Button>
|
||||||
|
</right>
|
||||||
|
<VBox.margin>
|
||||||
|
<Insets bottom="5.0" left="5.0" right="5.0" />
|
||||||
|
</VBox.margin>
|
||||||
|
</BorderPane>
|
||||||
</children>
|
</children>
|
||||||
</VBox>
|
</VBox>
|
||||||
|
@ -7,11 +7,18 @@
|
|||||||
<?import javafx.scene.layout.HBox?>
|
<?import javafx.scene.layout.HBox?>
|
||||||
<?import javafx.scene.layout.VBox?>
|
<?import javafx.scene.layout.VBox?>
|
||||||
|
|
||||||
<VBox alignment="TOP_RIGHT" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="envoy.client.ui.controller.SettingsScene">
|
<VBox alignment="TOP_RIGHT" maxHeight="-Infinity"
|
||||||
|
maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity"
|
||||||
|
prefHeight="400.0" prefWidth="600.0"
|
||||||
|
xmlns="http://javafx.com/javafx/11.0.1"
|
||||||
|
xmlns:fx="http://javafx.com/fxml/1"
|
||||||
|
fx:controller="envoy.client.ui.controller.SettingsScene">
|
||||||
<children>
|
<children>
|
||||||
<HBox prefHeight="389.0" prefWidth="600.0">
|
<HBox prefHeight="389.0" prefWidth="600.0">
|
||||||
<children>
|
<children>
|
||||||
<ListView fx:id="settingsList" onMouseClicked="#settingsListClicked" prefHeight="200.0" prefWidth="200.0">
|
<ListView fx:id="settingsList"
|
||||||
|
onMouseClicked="#settingsListClicked" prefHeight="200.0"
|
||||||
|
prefWidth="200.0">
|
||||||
<opaqueInsets>
|
<opaqueInsets>
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
</opaqueInsets>
|
</opaqueInsets>
|
||||||
@ -20,17 +27,21 @@
|
|||||||
</HBox.margin>
|
</HBox.margin>
|
||||||
<padding>
|
<padding>
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
</padding></ListView>
|
</padding>
|
||||||
<TitledPane fx:id="titledPane" collapsible="false" prefHeight="325.0" prefWidth="300.0">
|
</ListView>
|
||||||
|
<TitledPane fx:id="titledPane" collapsible="false"
|
||||||
|
prefHeight="325.0" prefWidth="300.0">
|
||||||
<HBox.margin>
|
<HBox.margin>
|
||||||
<Insets bottom="10.0" left="5.0" right="10.0" top="10.0" />
|
<Insets bottom="10.0" left="5.0" right="10.0" top="10.0" />
|
||||||
</HBox.margin>
|
</HBox.margin>
|
||||||
<padding>
|
<padding>
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
</padding></TitledPane>
|
</padding>
|
||||||
|
</TitledPane>
|
||||||
</children>
|
</children>
|
||||||
</HBox>
|
</HBox>
|
||||||
<Button defaultButton="true" mnemonicParsing="true" onMouseClicked="#backButtonClicked" text="_Back">
|
<Button defaultButton="true" mnemonicParsing="true"
|
||||||
|
onMouseClicked="#backButtonClicked" text="_Back">
|
||||||
<opaqueInsets>
|
<opaqueInsets>
|
||||||
<Insets />
|
<Insets />
|
||||||
</opaqueInsets>
|
</opaqueInsets>
|
||||||
|
BIN
src/main/resources/icons/clear_button_black.png
Normal file
BIN
src/main/resources/icons/clear_button_black.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
BIN
src/main/resources/icons/clear_button_white.png
Normal file
BIN
src/main/resources/icons/clear_button_white.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.8 KiB |
Reference in New Issue
Block a user