Merged branch 'develop' into f/groups
Contains several bug fixes
This commit is contained in:
commit
4e2e47600b
@ -148,12 +148,22 @@ public abstract class LocalDB {
|
||||
* Searches for a message by ID.
|
||||
*
|
||||
* @param id the ID of the message to search for
|
||||
* @return the message with the corresponding ID, or {@code null} if no message
|
||||
* has been found
|
||||
* @return an optional containing the message
|
||||
* @since Envoy Client v0.1-beta
|
||||
*/
|
||||
public Message getMessage(long id) {
|
||||
return chats.stream().map(Chat::getMessages).flatMap(List::stream).filter(m -> m.getID() == id).findAny().orElse(null);
|
||||
public Optional<Message> getMessage(long id) {
|
||||
return chats.stream().map(Chat::getMessages).flatMap(List::stream).filter(m -> m.getID() == id).findAny();
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for a chat by recipient ID.
|
||||
*
|
||||
* @param recipientID the ID of the chat's recipient
|
||||
* @return an optional containing the chat
|
||||
* @since Envoy Client v0.1-beta
|
||||
*/
|
||||
public Optional<Chat> getChat(long recipientID) {
|
||||
return chats.stream().filter(c -> c.getRecipient().getID() == recipientID).findAny();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -91,7 +91,7 @@ public class Client implements Closeable {
|
||||
SerializationUtils.writeBytesWithLength(credentials, socket.getOutputStream());
|
||||
|
||||
// Wait for a maximum of five seconds to acquire the sender object
|
||||
long start = System.currentTimeMillis();
|
||||
final long start = System.currentTimeMillis();
|
||||
while (sender == null) {
|
||||
|
||||
// Quit immediately after handshake rejection
|
||||
@ -141,7 +141,7 @@ public class Client implements Closeable {
|
||||
receiver.registerProcessor(MessageStatusChangeEvent.class, new MessageStatusChangeEventProcessor());
|
||||
|
||||
// Process user status changes
|
||||
receiver.registerProcessor(UserStatusChangeEvent.class, new UserStatusChangeProcessor(localDB));
|
||||
receiver.registerProcessor(UserStatusChangeEvent.class, eventBus::dispatch);
|
||||
|
||||
// Process message ID generation
|
||||
receiver.registerProcessor(IDGenerator.class, localDB::setIDGenerator);
|
||||
@ -162,7 +162,7 @@ public class Client implements Closeable {
|
||||
eventBus.register(SendEvent.class, evt -> {
|
||||
try {
|
||||
sendEvent(evt.get());
|
||||
} catch (IOException e) {
|
||||
} catch (final IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
@ -221,7 +221,7 @@ public class Client implements Closeable {
|
||||
*/
|
||||
public Map<String, Contact> getUsers() {
|
||||
checkOnline();
|
||||
Map<String, Contact> users = new HashMap<>();
|
||||
final Map<String, Contact> users = new HashMap<>();
|
||||
contacts.forEach(u -> users.put(u.getName(), u));
|
||||
users.put(sender.getName(), sender);
|
||||
return users;
|
||||
|
@ -1,33 +0,0 @@
|
||||
package envoy.client.net;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import envoy.client.data.LocalDB;
|
||||
import envoy.data.User;
|
||||
import envoy.event.EventBus;
|
||||
import envoy.event.UserStatusChangeEvent;
|
||||
|
||||
/**
|
||||
* Project: <strong>envoy-client</strong><br>
|
||||
* File: <strong>UserStatusChangeProcessor.java</strong><br>
|
||||
* Created: <strong>2 Feb 2020</strong><br>
|
||||
*
|
||||
* @author Leon Hofmeister
|
||||
* @since Envoy Client v0.3-alpha
|
||||
*/
|
||||
public class UserStatusChangeProcessor implements Consumer<UserStatusChangeEvent> {
|
||||
|
||||
private final LocalDB localDB;
|
||||
|
||||
/**
|
||||
* @param localDB the local database in which status updates will by applied
|
||||
* @since Envoy Client v0.3-alpha
|
||||
*/
|
||||
public UserStatusChangeProcessor(LocalDB localDB) { this.localDB = localDB; }
|
||||
|
||||
@Override
|
||||
public void accept(UserStatusChangeEvent evt) {
|
||||
localDB.getUsers().values().stream().filter(u -> u.getID() == evt.getID()).map(User.class::cast).findFirst().get().setStatus(evt.get());
|
||||
EventBus.getInstance().dispatch(evt);
|
||||
}
|
||||
}
|
@ -49,7 +49,7 @@ public class WriteProxy {
|
||||
client.sendMessage(msg);
|
||||
|
||||
// Update message state to SENT in localDB
|
||||
localDB.getMessage(msg.getID()).nextStatus();
|
||||
localDB.getMessage(msg.getID()).ifPresent(Message::nextStatus);
|
||||
} catch (IOException e) {
|
||||
logger.log(Level.SEVERE, "Could not send cached message", e);
|
||||
}
|
||||
|
@ -3,8 +3,10 @@ package envoy.client.ui;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.ListCell;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.scene.paint.Color;
|
||||
|
||||
import envoy.data.Contact;
|
||||
import envoy.data.Group;
|
||||
import envoy.data.User;
|
||||
|
||||
/**
|
||||
@ -20,15 +22,42 @@ 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) {
|
||||
final var name = new Label(contact.getName());
|
||||
setGraphic(contact instanceof User ? new VBox(name, new Label(((User) contact).getStatus().toString())) : new VBox(name));
|
||||
if (empty || contact == null) {
|
||||
setText(null);
|
||||
setGraphic(null);
|
||||
} else {
|
||||
// the infoLabel displays specific contact info, i.e. status of a user or amount
|
||||
// of members in a group
|
||||
Label infoLabel = null;
|
||||
if (contact instanceof User) {
|
||||
// user specific info
|
||||
infoLabel = new Label(((User) contact).getStatus().toString());
|
||||
Color textColor = null;
|
||||
switch (((User) contact).getStatus()) {
|
||||
case ONLINE:
|
||||
textColor = Color.LIMEGREEN;
|
||||
break;
|
||||
case AWAY:
|
||||
textColor = Color.ORANGERED;
|
||||
break;
|
||||
case BUSY:
|
||||
textColor = Color.RED;
|
||||
break;
|
||||
case OFFLINE:
|
||||
textColor = Color.GRAY;
|
||||
break;
|
||||
}
|
||||
infoLabel.setTextFill(textColor);
|
||||
} else
|
||||
// group specific infos
|
||||
infoLabel = new Label(String.valueOf(((Group) contact).getContacts().size()) + " members");
|
||||
setGraphic(new VBox(new Label(contact.getName()), infoLabel));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -45,10 +45,15 @@ public class MessageListCell extends ListCell<Message> {
|
||||
@Override
|
||||
protected void updateItem(Message message, boolean empty) {
|
||||
super.updateItem(message, empty);
|
||||
setGraphic(!empty && message != null ? new HBox(
|
||||
if(empty || message == null) {
|
||||
setText(null);
|
||||
setGraphic(null);
|
||||
} else {
|
||||
setGraphic(new HBox(
|
||||
new VBox(
|
||||
new Label(dateFormat.format(message.getCreationDate())),
|
||||
new Label(message.getText())),
|
||||
new Label("", new ImageView(statusImages.get(message.getStatus())))) : null);
|
||||
new Label("", new ImageView(statusImages.get(message.getStatus())))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -115,6 +115,7 @@ public final class SceneContext {
|
||||
sceneStack.push(scene);
|
||||
stage.setScene(scene);
|
||||
applyCSS();
|
||||
stage.sizeToScene();
|
||||
stage.show();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
@ -131,6 +132,7 @@ public final class SceneContext {
|
||||
if (!sceneStack.isEmpty()) {
|
||||
stage.setScene(sceneStack.peek());
|
||||
applyCSS();
|
||||
stage.sizeToScene();
|
||||
}
|
||||
stage.show();
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import javafx.application.Platform;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.control.Alert.AlertType;
|
||||
import javafx.scene.input.KeyCode;
|
||||
import javafx.scene.input.KeyEvent;
|
||||
import javafx.scene.paint.Color;
|
||||
@ -22,9 +23,7 @@ import envoy.client.net.WriteProxy;
|
||||
import envoy.client.ui.ContactListCell;
|
||||
import envoy.client.ui.MessageListCell;
|
||||
import envoy.client.ui.SceneContext;
|
||||
import envoy.data.Contact;
|
||||
import envoy.data.Message;
|
||||
import envoy.data.MessageBuilder;
|
||||
import envoy.data.*;
|
||||
import envoy.event.EventBus;
|
||||
import envoy.event.MessageStatusChangeEvent;
|
||||
import envoy.event.UserStatusChangeEvent;
|
||||
@ -74,6 +73,11 @@ public final class ChatScene {
|
||||
private static final Logger logger = EnvoyLog.getLogger(ChatScene.class);
|
||||
private static final int MAX_MESSAGE_LENGTH = 255;
|
||||
|
||||
/**
|
||||
* Initializes the appearance of certain visual components.
|
||||
*
|
||||
* @since Envoy Client v0.1-beta
|
||||
*/
|
||||
@FXML
|
||||
private void initialize() {
|
||||
|
||||
@ -83,24 +87,36 @@ public final class ChatScene {
|
||||
|
||||
// Listen to received messages
|
||||
eventBus.register(MessageCreationEvent.class, e -> {
|
||||
final var message = e.get();
|
||||
final var chat = localDB.getChats().stream().filter(c -> c.getRecipient().getID() == message.getSenderID()).findAny().get();
|
||||
final var message = e.get();
|
||||
localDB.getChat(message.getSenderID()).ifPresent(chat -> {
|
||||
chat.getMessages().add(message);
|
||||
|
||||
// Update UI if in current chat
|
||||
if (chat == currentChat) Platform.runLater(() -> messageList.getItems().add(message));
|
||||
// Update UI if in current chat
|
||||
if (chat == currentChat)
|
||||
Platform.runLater(messageList::refresh);
|
||||
});
|
||||
});
|
||||
|
||||
// Listen to message status changes
|
||||
eventBus.register(MessageStatusChangeEvent.class, e -> {
|
||||
final var message = localDB.getMessage(e.getID());
|
||||
eventBus.register(MessageStatusChangeEvent.class, e ->
|
||||
localDB.getMessage(e.getID()).ifPresent(message -> {
|
||||
message.setStatus(e.get());
|
||||
|
||||
// Update UI if in current chat
|
||||
if (currentChat != null && message.getSenderID() == currentChat.getRecipient().getID()) Platform.runLater(messageList::refresh);
|
||||
});
|
||||
}));
|
||||
|
||||
// Listen to user status changes
|
||||
eventBus.register(UserStatusChangeEvent.class, e -> Platform.runLater(userList::refresh));
|
||||
eventBus.register(UserStatusChangeEvent.class, e ->
|
||||
userList.getItems()
|
||||
.stream()
|
||||
.filter(c -> c.getID() == e.getID())
|
||||
.findAny()
|
||||
.ifPresent(u -> {
|
||||
((User) u).setStatus(e.get());
|
||||
Platform.runLater(userList::refresh);
|
||||
})
|
||||
);
|
||||
|
||||
// Listen to contacts changes
|
||||
eventBus.register(ContactOperationEvent.class, e -> {
|
||||
@ -121,6 +137,8 @@ public final class ChatScene {
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes all necessary data via dependency injection-
|
||||
*
|
||||
* @param sceneContext the scene context used to load other scenes
|
||||
* @param localDB the local database form which chats and users are loaded
|
||||
* @param client the client used to request ID generators
|
||||
@ -137,6 +155,11 @@ public final class ChatScene {
|
||||
userList.setItems(FXCollections.observableList(localDB.getChats().stream().map(Chat::getRecipient).collect(Collectors.toList())));
|
||||
}
|
||||
|
||||
/**
|
||||
* Actions to perform when the list of contacts has been clicked.
|
||||
*
|
||||
* @since Envoy Client v0.1-beta
|
||||
*/
|
||||
@FXML
|
||||
private void userListClicked() {
|
||||
final Contact user = userList.getSelectionModel().getSelectedItem();
|
||||
@ -146,10 +169,8 @@ public final class ChatScene {
|
||||
// LEON: JFC <===> JAVA FRIED CHICKEN <=/=> Java Foundation Classes
|
||||
|
||||
// Load the chat or create a new one and add it to the LocalDB
|
||||
currentChat = localDB.getChats()
|
||||
.stream()
|
||||
.filter(c -> c.getRecipient().getID() == user.getID())
|
||||
.findAny()
|
||||
currentChat = localDB
|
||||
.getChat(user.getID())
|
||||
.orElseGet(() -> { final var chat = new Chat(user); localDB.getChats().add(chat); return chat; });
|
||||
|
||||
messageList.setItems(FXCollections.observableList(currentChat.getMessages()));
|
||||
@ -161,32 +182,35 @@ public final class ChatScene {
|
||||
messageTextArea.setDisable(currentChat == null);
|
||||
}
|
||||
|
||||
@FXML
|
||||
private void postButtonClicked() { postMessage(); }
|
||||
|
||||
/**
|
||||
* Actions to perform when the Settings Button has been clicked.
|
||||
*
|
||||
* @since Envoy Client v0.1-beta
|
||||
*/
|
||||
@FXML
|
||||
private void settingsButtonClicked() {
|
||||
sceneContext.load(SceneContext.SceneInfo.SETTINGS_SCENE);
|
||||
sceneContext.<SettingsScene>getController().initializeData(sceneContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Actions to perform when the "Add Contact" - Button has been clicked.
|
||||
*
|
||||
* @since Envoy Client v0.1-beta
|
||||
*/
|
||||
@FXML
|
||||
private void addContactButtonClicked() {
|
||||
sceneContext.load(SceneContext.SceneInfo.CONTACT_SEARCH_SCENE);
|
||||
sceneContext.<ContactSearchScene>getController().initializeData(sceneContext, localDB);
|
||||
}
|
||||
|
||||
/**
|
||||
* Actions to perform when the text was updated in the messageTextArea.
|
||||
*
|
||||
* @since Envoy Client v0.1-beta
|
||||
*/
|
||||
@FXML
|
||||
private void messageTextUpdated(KeyEvent e) {
|
||||
// TODO: Letting go of ctrl automatically posts a message. Needs to be fixed
|
||||
// soon.
|
||||
|
||||
// Automatic sending of messages via (ctrl +) enter
|
||||
if (!postButton.isDisabled() && settings.isEnterToSend() && e.getCode() == KeyCode.ENTER
|
||||
|| !settings.isEnterToSend() && e.getCode() == KeyCode.CONTROL)
|
||||
postMessage();
|
||||
else postButton.setDisable(messageTextArea.getText().isBlank() || currentChat == null);
|
||||
|
||||
private void messageTextUpdated() {
|
||||
// Truncating messages that are too long and staying at the same position
|
||||
if (messageTextArea.getText().length() >= MAX_MESSAGE_LENGTH) {
|
||||
messageTextArea.setText(messageTextArea.getText().substring(0, MAX_MESSAGE_LENGTH));
|
||||
@ -201,33 +225,34 @@ public final class ChatScene {
|
||||
remainingChars.setTextFill(Color.rgb(currentLength, remainingLength, 0, 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Actions to perform when a key has been entered.
|
||||
*
|
||||
* @param e the Keys that have been entered
|
||||
* @since Envoy Client v0.1-beta
|
||||
*/
|
||||
@FXML
|
||||
private void checkKeyCombination(KeyEvent e) {
|
||||
// Automatic sending of messages via (ctrl +) enter
|
||||
if (!postButton.isDisabled() && settings.isEnterToSend() && e.getCode() == KeyCode.ENTER
|
||||
|| !settings.isEnterToSend() && e.getCode() == KeyCode.ENTER && e.isControlDown())
|
||||
postMessage();
|
||||
postButton.setDisable(messageTextArea.getText().isBlank() || currentChat == null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a new message to the server based on the text entered in the
|
||||
* messageTextArea.
|
||||
*
|
||||
* @since Envoy Client v0.1-beta
|
||||
*/
|
||||
@FXML
|
||||
private void postMessage() {
|
||||
|
||||
// Create and send message
|
||||
sendMessage(new MessageBuilder(localDB.getUser().getID(), currentChat.getRecipient().getID(), localDB.getIDGenerator())
|
||||
.setText(messageTextArea.getText().strip())
|
||||
.build());
|
||||
|
||||
// Clear text field and disable post button
|
||||
messageTextArea.setText("");
|
||||
postButton.setDisable(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a message to the server and appends it to the current chat. If all
|
||||
* message IDs have been used, a new ID generator is requested.
|
||||
*
|
||||
* @param message the message to send
|
||||
* @since Envoy Client v0.1-beta
|
||||
*/
|
||||
private void sendMessage(Message message) {
|
||||
try {
|
||||
// Create and send message
|
||||
final var message = new MessageBuilder(localDB.getUser().getID(), currentChat.getRecipient().getID(), localDB.getIDGenerator())
|
||||
.setText(messageTextArea.getText().strip())
|
||||
.build();
|
||||
|
||||
// Send message
|
||||
writeProxy.writeMessage(message);
|
||||
@ -240,6 +265,11 @@ public final class ChatScene {
|
||||
|
||||
} catch (final IOException e) {
|
||||
logger.log(Level.SEVERE, "Error sending message", e);
|
||||
new Alert(AlertType.ERROR, "An error occured while sending the message!").showAndWait();
|
||||
}
|
||||
|
||||
// Clear text field and disable post button
|
||||
messageTextArea.setText("");
|
||||
postButton.setDisable(true);
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ import envoy.util.EnvoyLog;
|
||||
* Project: <strong>envoy-client</strong><br>
|
||||
* File: <strong>LoginDialog.java</strong><br>
|
||||
* Created: <strong>03.04.2020</strong><br>
|
||||
*
|
||||
*
|
||||
* @author Kai S. K. Engelbart
|
||||
* @since Envoy Client v0.1-beta
|
||||
*/
|
||||
@ -72,7 +72,7 @@ public final class LoginScene {
|
||||
|
||||
/**
|
||||
* Loads the login dialog using the FXML file {@code LoginDialog.fxml}.
|
||||
*
|
||||
*
|
||||
* @param client the client used to perform the handshake
|
||||
* @param localDB the local database used for offline login
|
||||
* @param receivedMessageCache the cache storing messages received during
|
||||
@ -104,9 +104,7 @@ public final class LoginScene {
|
||||
if (registerCheckBox.isSelected() && !passwordField.getText().equals(repeatPasswordField.getText())) {
|
||||
clearPasswordFields();
|
||||
new Alert(AlertType.ERROR, "The entered password is unequal to the repeated one").showAndWait();
|
||||
} else {
|
||||
performHandshake(new LoginCredentials(userTextField.getText(), passwordField.getText().toCharArray(), registerCheckBox.isSelected()));
|
||||
}
|
||||
} else performHandshake(new LoginCredentials(userTextField.getText(), passwordField.getText().toCharArray(), registerCheckBox.isSelected()));
|
||||
}
|
||||
|
||||
@FXML
|
||||
@ -120,7 +118,6 @@ public final class LoginScene {
|
||||
// Make repeat password field and label visible / invisible
|
||||
repeatPasswordField.setVisible(registerCheckBox.isSelected());
|
||||
repeatPasswordLabel.setVisible(registerCheckBox.isSelected());
|
||||
|
||||
clearPasswordFields();
|
||||
}
|
||||
|
||||
@ -148,12 +145,12 @@ public final class LoginScene {
|
||||
try {
|
||||
// Try entering offline mode
|
||||
localDB.loadUsers();
|
||||
User clientUser = (User) localDB.getUsers().get(credentials.getIdentifier());
|
||||
final User clientUser = (User) localDB.getUsers().get(credentials.getIdentifier());
|
||||
if (clientUser == null) throw new EnvoyException("Could not enter offline mode: user name unknown");
|
||||
client.setSender(clientUser);
|
||||
new Alert(AlertType.WARNING, "A connection to the server could not be established. Starting in offline mode.").showAndWait();
|
||||
loadChatScene();
|
||||
} catch (Exception e) {
|
||||
} catch (final Exception e) {
|
||||
new Alert(AlertType.ERROR, "Client error: " + e).showAndWait();
|
||||
System.exit(1);
|
||||
}
|
||||
|
@ -4,8 +4,8 @@
|
||||
* Project: <strong>envoy-client</strong><br>
|
||||
* File: <strong>package-info.java</strong><br>
|
||||
* Created: <strong>08.06.2020</strong><br>
|
||||
*
|
||||
*
|
||||
* @author Kai S. K. Engelbart
|
||||
* @since Envoy Client v0.1-beta
|
||||
*/
|
||||
package envoy.client.ui.controller;
|
||||
package envoy.client.ui.controller;
|
||||
|
@ -8,13 +8,14 @@ import javafx.scene.layout.VBox;
|
||||
import envoy.client.data.Settings;
|
||||
import envoy.client.data.SettingsItem;
|
||||
import envoy.client.event.ThemeChangeEvent;
|
||||
import envoy.data.User.UserStatus;
|
||||
import envoy.event.EventBus;
|
||||
|
||||
/**
|
||||
* Project: <strong>envoy-client</strong><br>
|
||||
* File: <strong>GeneralSettingsPane.java</strong><br>
|
||||
* Created: <strong>18.04.2020</strong><br>
|
||||
*
|
||||
*
|
||||
* @author Kai S. K. Engelbart
|
||||
* @since Envoy Client v0.1-beta
|
||||
*/
|
||||
@ -27,7 +28,7 @@ public class GeneralSettingsPane extends SettingsPane {
|
||||
*/
|
||||
public GeneralSettingsPane() {
|
||||
super("General");
|
||||
var vbox = new VBox();
|
||||
final var vbox = new VBox();
|
||||
|
||||
// TODO: Support other value types
|
||||
List.of("onCloseMode", "enterToSend")
|
||||
@ -36,7 +37,7 @@ public class GeneralSettingsPane extends SettingsPane {
|
||||
.map(i -> new SettingsCheckbox((SettingsItem<Boolean>) i))
|
||||
.forEach(vbox.getChildren()::add);
|
||||
|
||||
var combobox = new ComboBox<String>();
|
||||
final var combobox = new ComboBox<String>();
|
||||
combobox.getItems().add("dark");
|
||||
combobox.getItems().add("light");
|
||||
combobox.setValue(settings.getCurrentTheme());
|
||||
@ -44,6 +45,13 @@ public class GeneralSettingsPane extends SettingsPane {
|
||||
e -> { settings.setCurrentTheme(combobox.getValue()); EventBus.getInstance().dispatch(new ThemeChangeEvent(combobox.getValue())); });
|
||||
vbox.getChildren().add(combobox);
|
||||
|
||||
final var statusComboBox = new ComboBox<UserStatus>();
|
||||
statusComboBox.getItems().setAll(UserStatus.values());
|
||||
statusComboBox.setValue(UserStatus.ONLINE);
|
||||
// TODO add action when value is changed
|
||||
statusComboBox.setOnAction(e -> {});
|
||||
vbox.getChildren().add(statusComboBox);
|
||||
|
||||
getChildren().add(vbox);
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
.button{
|
||||
-fx-background-color: rgb(105,0,153);
|
||||
-fx-text-fill: white;
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,3 @@
|
||||
.button{
|
||||
-fx-background-color: snow;
|
||||
}
|
||||
}
|
||||
|
@ -26,8 +26,8 @@
|
||||
<Label fx:id="contactLabel" prefHeight="16.0" prefWidth="250.0" text="Select a contact to chat with" GridPane.columnSpan="2" />
|
||||
<Button fx:id="settingsButton" mnemonicParsing="true" onAction="#settingsButtonClicked" text="_Settings" GridPane.columnIndex="2" GridPane.halignment="CENTER" GridPane.valignment="CENTER" />
|
||||
<ListView fx:id="messageList" prefHeight="257.0" prefWidth="155.0" GridPane.columnIndex="1" GridPane.columnSpan="2" GridPane.rowIndex="1" GridPane.rowSpan="2" />
|
||||
<Button fx:id="postButton" defaultButton="true" disable="true" mnemonicParsing="true" onAction="#postButtonClicked" prefHeight="10.0" prefWidth="65.0" text="_Post" GridPane.columnIndex="2" GridPane.halignment="CENTER" GridPane.rowIndex="3" GridPane.valignment="CENTER" />
|
||||
<TextArea fx:id="messageTextArea" disable="true" onInputMethodTextChanged="#messageTextUpdated" onKeyPressed="#messageTextUpdated" onKeyTyped="#messageTextUpdated" prefHeight="200.0" prefWidth="200.0" wrapText="true" GridPane.columnIndex="1" GridPane.rowIndex="3" />
|
||||
<Button fx:id="postButton" defaultButton="true" disable="true" mnemonicParsing="true" onAction="#postMessage" prefHeight="10.0" prefWidth="65.0" text="_Post" GridPane.columnIndex="2" GridPane.halignment="CENTER" GridPane.rowIndex="3" GridPane.valignment="CENTER" />
|
||||
<TextArea fx:id="messageTextArea" disable="true" onInputMethodTextChanged="#messageTextUpdated" onKeyPressed="#checkKeyCombination" onKeyTyped="#messageTextUpdated" prefHeight="200.0" prefWidth="200.0" wrapText="true" GridPane.columnIndex="1" GridPane.rowIndex="3" />
|
||||
<Button mnemonicParsing="true" onAction="#addContactButtonClicked" text="_Add Contacts" GridPane.halignment="CENTER" GridPane.rowIndex="3" GridPane.valignment="CENTER">
|
||||
<padding>
|
||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||
|
Reference in New Issue
Block a user