Replace the Internal Event Bus with Event Bus 0.0.3 #20
@ -10,16 +10,7 @@ import envoy.event.Event;
|
||||
* @author Kai S. K. Engelbart
|
||||
* @since Envoy Client v0.2-alpha
|
||||
*/
|
||||
public final class ThemeChangeEvent extends Event<String> {
|
||||
public final class ThemeChangeEvent extends Event.Valueless {
|
||||
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
/**
|
||||
* Initializes a {@link ThemeChangeEvent} conveying information about the change
|
||||
* of the theme currently in use.
|
||||
*
|
||||
* @param theme the name of the new theme
|
||||
* @since Envoy Client v0.2-alpha
|
||||
*/
|
||||
public ThemeChangeEvent(String theme) { super(theme); }
|
||||
}
|
||||
|
@ -1,20 +1,19 @@
|
||||
package envoy.client.net;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.io.*;
|
||||
import java.net.Socket;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.logging.*;
|
||||
|
||||
import envoy.client.data.*;
|
||||
import envoy.client.event.SendEvent;
|
||||
import envoy.data.*;
|
||||
import envoy.event.*;
|
||||
import envoy.event.contact.ContactOperation;
|
||||
import envoy.event.contact.UserSearchResult;
|
||||
import envoy.util.EnvoyLog;
|
||||
import envoy.util.SerializationUtils;
|
||||
import envoy.event.Event;
|
||||
import envoy.event.contact.*;
|
||||
import envoy.util.*;
|
||||
|
||||
import dev.kske.eventbus.*;
|
||||
|
||||
/**
|
||||
* Establishes a connection to the server, performs a handshake and delivers
|
||||
@ -29,7 +28,7 @@ import envoy.util.SerializationUtils;
|
||||
* @author Leon Hofmeister
|
||||
* @since Envoy Client v0.1-alpha
|
||||
*/
|
||||
public final class Client implements Closeable {
|
||||
public final class Client implements EventListener, Closeable {
|
||||
|
||||
// Connection handling
|
||||
private Socket socket;
|
||||
@ -45,6 +44,15 @@ public final class Client implements Closeable {
|
||||
private static final Logger logger = EnvoyLog.getLogger(Client.class);
|
||||
private static final EventBus eventBus = EventBus.getInstance();
|
||||
|
||||
/**
|
||||
* Constructs a client and registers it as an event listener.
|
||||
*
|
||||
* @since Envoy Client v0.2-beta
|
||||
*/
|
||||
public Client() {
|
||||
eventBus.registerListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enters the online mode by acquiring a user ID from the server. As a
|
||||
* connection has to be established and a handshake has to be made, this method
|
||||
@ -164,22 +172,14 @@ public final class Client implements Closeable {
|
||||
// Process ProfilePicChanges
|
||||
receiver.registerProcessor(ProfilePicChange.class, eventBus::dispatch);
|
||||
|
||||
// Process requests to not send any more attachments as they will not be shown to
|
||||
// Process requests to not send any more attachments as they will not be shown
|
||||
// to
|
||||
// other users
|
||||
receiver.registerProcessor(NoAttachments.class, eventBus::dispatch);
|
||||
|
||||
// Process group creation results - they might have been disabled on the server
|
||||
receiver.registerProcessor(GroupCreationResult.class, eventBus::dispatch);
|
||||
|
||||
// Send event
|
||||
eventBus.register(SendEvent.class, evt -> {
|
||||
try {
|
||||
sendEvent(evt.get());
|
||||
} catch (final IOException e) {
|
||||
logger.log(Level.WARNING, "An error occurred when trying to send " + evt, e);
|
||||
}
|
||||
});
|
||||
|
||||
// Request a generator if none is present or the existing one is consumed
|
||||
if (!localDB.hasIDGenerator() || !localDB.getIDGenerator().hasNext()) requestIdGenerator();
|
||||
|
||||
@ -219,6 +219,21 @@ public final class Client implements Closeable {
|
||||
writeObject(new IDGeneratorRequest());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the value of a send event to the server.
|
||||
*
|
||||
* @param evt the send event to extract the value from
|
||||
* @since Envoy Client v0.2-beta
|
||||
*/
|
||||
@dev.kske.eventbus.Event
|
||||
private void onSendEvent(SendEvent evt) {
|
||||
try {
|
||||
sendEvent(evt.get());
|
||||
} catch (final IOException e) {
|
||||
logger.log(Level.WARNING, "An error occurred when trying to send " + evt, e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException { if (online) socket.close(); }
|
||||
|
||||
|
@ -4,10 +4,11 @@ import java.util.function.Consumer;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import envoy.data.Message.MessageStatus;
|
||||
import envoy.event.EventBus;
|
||||
import envoy.event.GroupMessageStatusChange;
|
||||
import envoy.util.EnvoyLog;
|
||||
|
||||
import dev.kske.eventbus.EventBus;
|
||||
|
||||
/**
|
||||
* Project: <strong>envoy-client</strong><br>
|
||||
* File: <strong>GroupMessageStatusChangePocessor.java</strong><br>
|
||||
@ -25,5 +26,4 @@ public final class GroupMessageStatusChangeProcessor implements Consumer<GroupMe
|
||||
if (evt.get().ordinal() < MessageStatus.RECEIVED.ordinal()) logger.warning("Received invalid group message status change " + evt);
|
||||
else EventBus.getInstance().dispatch(evt);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4,10 +4,11 @@ import java.util.function.Consumer;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import envoy.data.Message.MessageStatus;
|
||||
import envoy.event.EventBus;
|
||||
import envoy.event.MessageStatusChange;
|
||||
import envoy.util.EnvoyLog;
|
||||
|
||||
import dev.kske.eventbus.EventBus;
|
||||
|
||||
/**
|
||||
* Project: <strong>envoy-client</strong><br>
|
||||
* File: <strong>MessageStatusChangeProcessor.java</strong><br>
|
||||
|
@ -6,9 +6,10 @@ import java.util.logging.Logger;
|
||||
import envoy.client.event.MessageCreationEvent;
|
||||
import envoy.data.GroupMessage;
|
||||
import envoy.data.Message.MessageStatus;
|
||||
import envoy.event.EventBus;
|
||||
import envoy.util.EnvoyLog;
|
||||
|
||||
import dev.kske.eventbus.EventBus;
|
||||
|
||||
/**
|
||||
* Project: <strong>envoy-client</strong><br>
|
||||
* File: <strong>ReceivedGroupMessageProcessor.java</strong><br>
|
||||
|
@ -5,7 +5,8 @@ import java.util.function.Consumer;
|
||||
import envoy.client.event.MessageCreationEvent;
|
||||
import envoy.data.Message;
|
||||
import envoy.data.Message.MessageStatus;
|
||||
import envoy.event.EventBus;
|
||||
|
||||
import dev.kske.eventbus.EventBus;
|
||||
|
||||
/**
|
||||
* Project: <strong>envoy-client</strong><br>
|
||||
|
@ -6,15 +6,15 @@ import java.util.logging.Level;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.Parent;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.*;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
import envoy.client.data.Settings;
|
||||
import envoy.client.event.ThemeChangeEvent;
|
||||
import envoy.event.EventBus;
|
||||
import envoy.util.EnvoyLog;
|
||||
|
||||
import dev.kske.eventbus.*;
|
||||
|
||||
/**
|
||||
* Manages a stack of scenes. The most recently added scene is displayed inside
|
||||
* a stage. When a scene is removed from the stack, its predecessor is
|
||||
@ -30,7 +30,7 @@ import envoy.util.EnvoyLog;
|
||||
* @author Kai S. K. Engelbart
|
||||
* @since Envoy Client v0.1-beta
|
||||
*/
|
||||
public final class SceneContext {
|
||||
public final class SceneContext implements EventListener {
|
||||
|
||||
/**
|
||||
* Contains information about different scenes and their FXML resource files.
|
||||
@ -84,7 +84,7 @@ public final class SceneContext {
|
||||
*/
|
||||
public SceneContext(Stage stage) {
|
||||
this.stage = stage;
|
||||
EventBus.getInstance().register(ThemeChangeEvent.class, theme -> applyCSS());
|
||||
EventBus.getInstance().registerListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -152,6 +152,9 @@ public final class SceneContext {
|
||||
}
|
||||
}
|
||||
|
||||
@Event(priority = 150, eventType = ThemeChangeEvent.class)
|
||||
private void onThemeChange() { applyCSS(); }
|
||||
|
||||
/**
|
||||
* @param <T> the type of the controller
|
||||
* @return the controller used by the current scene
|
||||
|
@ -8,7 +8,9 @@ import javafx.stage.Stage;
|
||||
|
||||
import envoy.client.event.MessageCreationEvent;
|
||||
import envoy.data.Message;
|
||||
import envoy.event.EventBus;
|
||||
|
||||
import dev.kske.eventbus.*;
|
||||
import dev.kske.eventbus.Event;
|
||||
|
||||
/**
|
||||
* Project: <strong>envoy-client</strong><br>
|
||||
@ -18,7 +20,7 @@ import envoy.event.EventBus;
|
||||
* @author Kai S. K. Engelbart
|
||||
* @since Envoy Client v0.2-alpha
|
||||
*/
|
||||
public final class StatusTrayIcon {
|
||||
public final class StatusTrayIcon implements EventListener {
|
||||
|
||||
/**
|
||||
* The {@link TrayIcon} provided by the System Tray API for controlling the
|
||||
@ -67,14 +69,7 @@ public final class StatusTrayIcon {
|
||||
trayIcon.addActionListener(evt -> Platform.runLater(() -> { stage.setIconified(false); stage.toFront(); stage.requestFocus(); }));
|
||||
|
||||
// Start processing message events
|
||||
EventBus.getInstance().register(MessageCreationEvent.class, evt -> {
|
||||
if (displayMessages) trayIcon
|
||||
.displayMessage(
|
||||
evt.get().hasAttachment() ? "New " + evt.get().getAttachment().getType().toString().toLowerCase() + " message received"
|
||||
: "New message received",
|
||||
evt.get().getText(),
|
||||
MessageType.INFO);
|
||||
});
|
||||
EventBus.getInstance().registerListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -94,4 +89,11 @@ public final class StatusTrayIcon {
|
||||
* @since Envoy Client v0.2-beta
|
||||
*/
|
||||
public void hide() { SystemTray.getSystemTray().remove(trayIcon); }
|
||||
|
||||
@Event
|
||||
private void onMessageCreation(MessageCreationEvent evt) {
|
||||
if (displayMessages) trayIcon
|
||||
.displayMessage(evt.get().hasAttachment() ? "New " + evt.get().getAttachment().getType().toString().toLowerCase() + " message received"
|
||||
: "New message received", evt.get().getText(), MessageType.INFO);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,5 @@
|
||||
package envoy.client.ui.controller;
|
||||
|
||||
import static envoy.data.Message.MessageStatus.RECEIVED;
|
||||
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.datatransfer.StringSelection;
|
||||
import java.io.*;
|
||||
@ -36,11 +34,15 @@ import envoy.client.ui.listcell.*;
|
||||
import envoy.client.util.ReflectionUtil;
|
||||
import envoy.data.*;
|
||||
import envoy.data.Attachment.AttachmentType;
|
||||
import envoy.data.Message.MessageStatus;
|
||||
import envoy.event.*;
|
||||
import envoy.event.contact.ContactOperation;
|
||||
import envoy.exception.EnvoyException;
|
||||
import envoy.util.EnvoyLog;
|
||||
|
||||
import dev.kske.eventbus.*;
|
||||
import dev.kske.eventbus.Event;
|
||||
|
||||
/**
|
||||
* Project: <strong>envoy-client</strong><br>
|
||||
* File: <strong>ChatSceneController.java</strong><br>
|
||||
@ -49,7 +51,7 @@ import envoy.util.EnvoyLog;
|
||||
* @author Kai S. K. Engelbart
|
||||
* @since Envoy Client v0.1-beta
|
||||
*/
|
||||
public final class ChatScene implements Restorable {
|
||||
public final class ChatScene implements EventListener, Restorable {
|
||||
|
||||
@FXML
|
||||
private GridPane scene;
|
||||
@ -160,6 +162,8 @@ public final class ChatScene implements Restorable {
|
||||
*/
|
||||
@FXML
|
||||
private void initialize() {
|
||||
eventBus.registerListener(this);
|
||||
|
||||
// Initialize message and user rendering
|
||||
messageList.setCellFactory(MessageListCell::new);
|
||||
chatList.setCellFactory(new ListCellFactory<>(ChatControl::new));
|
||||
@ -201,110 +205,119 @@ public final class ChatScene implements Restorable {
|
||||
updateInfoLabel("You are offline", "info-label-warning");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Listen to backEvents
|
||||
eventBus.register(BackEvent.class, e -> tabPane.getSelectionModel().select(Tabs.CONTACT_LIST.ordinal()));
|
||||
@Event(eventType = BackEvent.class)
|
||||
private void onBackEvent() { tabPane.getSelectionModel().select(Tabs.CONTACT_LIST.ordinal()); }
|
||||
|
||||
// Listen to received messages
|
||||
eventBus.register(MessageCreationEvent.class, e -> {
|
||||
final var message = e.get();
|
||||
@Event
|
||||
private void onMessageCreation(MessageCreationEvent evt) {
|
||||
final var message = evt.get();
|
||||
|
||||
// The sender of the message is the recipient of the chat
|
||||
// Exceptions: this user is the sender (sync) or group message (group is
|
||||
// recipient)
|
||||
final var recipientID = message instanceof GroupMessage || message.getSenderID() == localDB.getUser().getID() ? message.getRecipientID()
|
||||
: message.getSenderID();
|
||||
localDB.getChat(recipientID).ifPresent(chat -> {
|
||||
chat.insert(message);
|
||||
if (chat.equals(currentChat)) {
|
||||
try {
|
||||
currentChat.read(writeProxy);
|
||||
} catch (final IOException e1) {
|
||||
logger.log(Level.WARNING, "Could not read current chat: ", e1);
|
||||
}
|
||||
Platform.runLater(() -> { ListViewRefresh.deepRefresh(messageList); scrollToMessageListEnd(); });
|
||||
// TODO: Increment unread counter for group messages with status < RECEIVED
|
||||
} else if (message.getSenderID() != localDB.getUser().getID() && message.getStatus() == RECEIVED) chat.incrementUnreadAmount();
|
||||
// The sender of the message is the recipient of the chat
|
||||
// Exceptions: this user is the sender (sync) or group message (group is
|
||||
// recipient)
|
||||
final var recipientID = message instanceof GroupMessage || message.getSenderID() == localDB.getUser().getID() ? message.getRecipientID()
|
||||
: message.getSenderID();
|
||||
localDB.getChat(recipientID).ifPresent(chat -> {
|
||||
chat.insert(message);
|
||||
if (chat.equals(currentChat)) {
|
||||
try {
|
||||
currentChat.read(writeProxy);
|
||||
} catch (final IOException e1) {
|
||||
logger.log(Level.WARNING, "Could not read current chat: ", e1);
|
||||
}
|
||||
Platform.runLater(() -> { ListViewRefresh.deepRefresh(messageList); scrollToMessageListEnd(); });
|
||||
// TODO: Increment unread counter for group messages with status < RECEIVED
|
||||
} else
|
||||
if (message.getSenderID() != localDB.getUser().getID() && message.getStatus() == MessageStatus.RECEIVED) chat.incrementUnreadAmount();
|
||||
|
||||
// Move chat with most recent unread messages to the top
|
||||
Platform.runLater(() -> {
|
||||
chats.getSource().remove(chat);
|
||||
((ObservableList<Chat>) chats.getSource()).add(0, chat);
|
||||
|
||||
if (chat.equals(currentChat)) chatList.getSelectionModel().select(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Listen to message status changes
|
||||
eventBus.register(MessageStatusChange.class, e -> localDB.getMessage(e.getID()).ifPresent(message -> {
|
||||
message.setStatus(e.get());
|
||||
// Update UI if in current chat and the current user was the sender of the
|
||||
// message
|
||||
if (currentChat != null && message.getSenderID() == client.getSender().getID()) Platform.runLater(messageList::refresh);
|
||||
}));
|
||||
|
||||
eventBus.register(GroupMessageStatusChange.class, e -> localDB.getMessage(e.getID()).ifPresent(groupMessage -> {
|
||||
((GroupMessage) groupMessage).getMemberStatuses().replace(e.getMemberID(), e.get());
|
||||
|
||||
// Update UI if in current chat
|
||||
if (currentChat != null && groupMessage.getRecipientID() == currentChat.getRecipient().getID()) Platform.runLater(messageList::refresh);
|
||||
}));
|
||||
|
||||
// Listen to user status changes
|
||||
eventBus.register(UserStatusChange.class,
|
||||
e -> chats.getSource()
|
||||
.stream()
|
||||
.filter(c -> c.getRecipient().getID() == e.getID())
|
||||
.findAny()
|
||||
.map(Chat::getRecipient)
|
||||
.ifPresent(u -> { ((User) u).setStatus(e.get()); Platform.runLater(() -> ListViewRefresh.deepRefresh(chatList)); }));
|
||||
|
||||
// Listen to contacts changes
|
||||
eventBus.register(ContactOperation.class, e -> {
|
||||
final var contact = e.get();
|
||||
switch (e.getOperationType()) {
|
||||
case ADD:
|
||||
if (contact instanceof User) localDB.getUsers().put(contact.getName(), (User) contact);
|
||||
final var chat = contact instanceof User ? new Chat(contact) : new GroupChat(client.getSender(), contact);
|
||||
Platform.runLater(() -> ((ObservableList<Chat>) chats.getSource()).add(0, chat));
|
||||
break;
|
||||
case REMOVE:
|
||||
Platform.runLater(() -> chats.getSource().removeIf(c -> c.getRecipient().equals(contact)));
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
// Disable attachment button if server says attachments will be filtered out
|
||||
eventBus.register(NoAttachments.class, e -> {
|
||||
// Move chat with most recent unread messages to the top
|
||||
Platform.runLater(() -> {
|
||||
attachmentButton.setDisable(true);
|
||||
voiceButton.setDisable(true);
|
||||
final var alert = new Alert(AlertType.ERROR);
|
||||
alert.setTitle("No attachments possible");
|
||||
alert.setHeaderText("Your current server does not support attachments.");
|
||||
alert.setContentText("If this is unplanned, please contact your server administrator.");
|
||||
alert.showAndWait();
|
||||
chats.getSource().remove(chat);
|
||||
((ObservableList<Chat>) chats.getSource()).add(0, chat);
|
||||
|
||||
if (chat.equals(currentChat)) chatList.getSelectionModel().select(0);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
eventBus.register(GroupCreationResult.class, e -> Platform.runLater(() -> { newGroupButton.setDisable(!e.get()); }));
|
||||
|
||||
eventBus.register(ThemeChangeEvent.class, e -> {
|
||||
settingsButton.setGraphic(new ImageView(IconUtil.loadIconThemeSensitive("settings", DEFAULT_ICON_SIZE)));
|
||||
voiceButton.setGraphic(new ImageView(IconUtil.loadIconThemeSensitive("microphone", DEFAULT_ICON_SIZE)));
|
||||
attachmentButton.setGraphic(new ImageView(IconUtil.loadIconThemeSensitive("attachment", DEFAULT_ICON_SIZE)));
|
||||
DEFAULT_ATTACHMENT_VIEW_IMAGE = IconUtil.loadIconThemeSensitive("attachment_present", 20);
|
||||
attachmentView.setImage(isCustomAttachmentImage ? attachmentView.getImage() : DEFAULT_ATTACHMENT_VIEW_IMAGE);
|
||||
messageSearchButton.setGraphic(new ImageView(IconUtil.loadIconThemeSensitive("search", DEFAULT_ICON_SIZE)));
|
||||
clientProfilePic.setImage(IconUtil.loadIconThemeSensitive("user_icon", 43));
|
||||
chatList.setCellFactory(new ListCellFactory<>(ChatControl::new));
|
||||
messageList.setCellFactory(MessageListCell::new);
|
||||
if (currentChat.getRecipient() instanceof User) recipientProfilePic.setImage(IconUtil.loadIconThemeSensitive("user_icon", 43));
|
||||
else recipientProfilePic.setImage(IconUtil.loadIconThemeSensitive("group_icon", 43));
|
||||
@Event
|
||||
private void onMessageStatusChange(MessageStatusChange evt) {
|
||||
localDB.getMessage(evt.getID()).ifPresent(message -> {
|
||||
message.setStatus(evt.get());
|
||||
// Update UI if in current chat and the current user was the sender of the
|
||||
// message
|
||||
if (currentChat != null && message.getSenderID() == client.getSender().getID()) Platform.runLater(messageList::refresh);
|
||||
});
|
||||
}
|
||||
|
||||
@Event
|
||||
private void onGroupMessageStatusChange(GroupMessageStatusChange evt) {
|
||||
localDB.getMessage(evt.getID()).ifPresent(groupMessage -> {
|
||||
((GroupMessage) groupMessage).getMemberStatuses().replace(evt.getMemberID(), evt.get());
|
||||
|
||||
// Update UI if in current chat
|
||||
if (currentChat != null && groupMessage.getRecipientID() == currentChat.getRecipient().getID()) Platform.runLater(messageList::refresh);
|
||||
});
|
||||
}
|
||||
|
||||
@Event
|
||||
private void onUserStatusChange(UserStatusChange evt) {
|
||||
chats.getSource()
|
||||
.stream()
|
||||
.filter(c -> c.getRecipient().getID() == evt.getID())
|
||||
.findAny()
|
||||
.map(Chat::getRecipient)
|
||||
.ifPresent(u -> { ((User) u).setStatus(evt.get()); Platform.runLater(() -> ListViewRefresh.deepRefresh(chatList)); });
|
||||
}
|
||||
|
||||
@Event
|
||||
private void onContactOperation(ContactOperation operation) {
|
||||
final var contact = operation.get();
|
||||
switch (operation.getOperationType()) {
|
||||
case ADD:
|
||||
if (contact instanceof User) localDB.getUsers().put(contact.getName(), (User) contact);
|
||||
final var chat = contact instanceof User ? new Chat(contact) : new GroupChat(client.getSender(), contact);
|
||||
Platform.runLater(() -> ((ObservableList<Chat>) chats.getSource()).add(0, chat));
|
||||
break;
|
||||
case REMOVE:
|
||||
Platform.runLater(() -> chats.getSource().removeIf(c -> c.getRecipient().equals(contact)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Event(eventType = NoAttachments.class)
|
||||
private void onNoAttachments() {
|
||||
Platform.runLater(() -> {
|
||||
attachmentButton.setDisable(true);
|
||||
voiceButton.setDisable(true);
|
||||
final var alert = new Alert(AlertType.ERROR);
|
||||
alert.setTitle("No attachments possible");
|
||||
alert.setHeaderText("Your current server does not support attachments.");
|
||||
alert.setContentText("If this is unplanned, please contact your server administrator.");
|
||||
alert.showAndWait();
|
||||
});
|
||||
}
|
||||
|
||||
@Event
|
||||
private void onGroupCreationResult(GroupCreationResult result) { Platform.runLater(() -> newGroupButton.setDisable(!result.get())); }
|
||||
|
||||
@Event(eventType = ThemeChangeEvent.class)
|
||||
private void onThemeChange() {
|
||||
settingsButton.setGraphic(new ImageView(IconUtil.loadIconThemeSensitive("settings", DEFAULT_ICON_SIZE)));
|
||||
voiceButton.setGraphic(new ImageView(IconUtil.loadIconThemeSensitive("microphone", DEFAULT_ICON_SIZE)));
|
||||
attachmentButton.setGraphic(new ImageView(IconUtil.loadIconThemeSensitive("attachment", DEFAULT_ICON_SIZE)));
|
||||
DEFAULT_ATTACHMENT_VIEW_IMAGE = IconUtil.loadIconThemeSensitive("attachment_present", 20);
|
||||
attachmentView.setImage(isCustomAttachmentImage ? attachmentView.getImage() : DEFAULT_ATTACHMENT_VIEW_IMAGE);
|
||||
messageSearchButton.setGraphic(new ImageView(IconUtil.loadIconThemeSensitive("search", DEFAULT_ICON_SIZE)));
|
||||
clientProfilePic.setImage(IconUtil.loadIconThemeSensitive("user_icon", 43));
|
||||
chatList.setCellFactory(new ListCellFactory<>(ChatControl::new));
|
||||
messageList.setCellFactory(MessageListCell::new);
|
||||
if (currentChat.getRecipient() instanceof User) recipientProfilePic.setImage(IconUtil.loadIconThemeSensitive("user_icon", 43));
|
||||
else recipientProfilePic.setImage(IconUtil.loadIconThemeSensitive("group_icon", 43));
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes all {@code SystemCommands} used in {@code ChatScene}.
|
||||
*
|
||||
|
@ -1,26 +1,21 @@
|
||||
package envoy.client.ui.controller;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.logging.*;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.control.Alert.AlertType;
|
||||
|
||||
import envoy.client.event.BackEvent;
|
||||
import envoy.client.event.SendEvent;
|
||||
import envoy.client.ui.listcell.ContactControl;
|
||||
import envoy.client.ui.listcell.ListCellFactory;
|
||||
import envoy.client.event.*;
|
||||
import envoy.client.ui.listcell.*;
|
||||
import envoy.data.User;
|
||||
import envoy.event.ElementOperation;
|
||||
import envoy.event.EventBus;
|
||||
import envoy.event.contact.ContactOperation;
|
||||
import envoy.event.contact.UserSearchRequest;
|
||||
import envoy.event.contact.UserSearchResult;
|
||||
import envoy.event.contact.*;
|
||||
import envoy.util.EnvoyLog;
|
||||
|
||||
import dev.kske.eventbus.*;
|
||||
|
||||
/**
|
||||
* Provides a search bar in which a user name (substring) can be entered. The
|
||||
* users with a matching name are then displayed inside a list view. A
|
||||
@ -39,7 +34,7 @@ import envoy.util.EnvoyLog;
|
||||
* @author Maximilian Käfer
|
||||
* @since Envoy Client v0.1-beta
|
||||
*/
|
||||
public class ContactSearchTab {
|
||||
public class ContactSearchTab implements EventListener {
|
||||
|
||||
@FXML
|
||||
private TextArea searchBar;
|
||||
@ -48,26 +43,29 @@ public class ContactSearchTab {
|
||||
private ListView<User> userList;
|
||||
|
||||
private Alert alert = new Alert(AlertType.CONFIRMATION);
|
||||
|
||||
private User currentlySelectedUser;
|
||||
|
||||
private final Consumer<ContactOperation> handler = e -> {
|
||||
final var contact = e.get();
|
||||
if (e.getOperationType() == ElementOperation.ADD) Platform.runLater(() -> {
|
||||
userList.getItems().remove(contact);
|
||||
if (currentlySelectedUser != null && currentlySelectedUser.equals(contact) && alert.isShowing()) alert.close();
|
||||
});
|
||||
};
|
||||
|
||||
private static final EventBus eventBus = EventBus.getInstance();
|
||||
private static final Logger logger = EnvoyLog.getLogger(ChatScene.class);
|
||||
|
||||
@FXML
|
||||
private void initialize() {
|
||||
eventBus.registerListener(this);
|
||||
userList.setCellFactory(new ListCellFactory<>(ContactControl::new));
|
||||
eventBus.register(UserSearchResult.class,
|
||||
response -> Platform.runLater(() -> { userList.getItems().clear(); userList.getItems().addAll(response.get()); }));
|
||||
eventBus.register(ContactOperation.class, handler);
|
||||
}
|
||||
|
||||
@Event
|
||||
private void onUserSearchResult(UserSearchResult result) {
|
||||
Platform.runLater(() -> { userList.getItems().clear(); userList.getItems().addAll(result.get()); });
|
||||
}
|
||||
|
||||
@Event
|
||||
private void onContactOperation(ContactOperation operation) {
|
||||
final var contact = operation.get();
|
||||
if (operation.getOperationType() == ElementOperation.ADD) Platform.runLater(() -> {
|
||||
userList.getItems().remove(contact);
|
||||
if (currentlySelectedUser != null && currentlySelectedUser.equals(contact) && alert.isShowing()) alert.close();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -8,20 +8,15 @@ import javafx.fxml.FXML;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.layout.HBox;
|
||||
|
||||
import envoy.client.data.Chat;
|
||||
import envoy.client.data.Context;
|
||||
import envoy.client.data.LocalDB;
|
||||
import envoy.client.event.BackEvent;
|
||||
import envoy.client.event.SendEvent;
|
||||
import envoy.client.ui.listcell.ContactControl;
|
||||
import envoy.client.ui.listcell.ListCellFactory;
|
||||
import envoy.data.Contact;
|
||||
import envoy.data.Group;
|
||||
import envoy.data.User;
|
||||
import envoy.event.EventBus;
|
||||
import envoy.client.data.*;
|
||||
import envoy.client.event.*;
|
||||
import envoy.client.ui.listcell.*;
|
||||
import envoy.data.*;
|
||||
import envoy.event.GroupCreation;
|
||||
import envoy.util.Bounds;
|
||||
|
||||
import dev.kske.eventbus.*;
|
||||
|
||||
/**
|
||||
* Provides a group creation interface. A group name can be entered in the text
|
||||
* field at the top. Available users (local chat recipients) are displayed
|
||||
@ -38,7 +33,7 @@ import envoy.util.Bounds;
|
||||
* @author Maximilian Käfer
|
||||
* @since Envoy Client v0.1-beta
|
||||
*/
|
||||
public class GroupCreationTab {
|
||||
public class GroupCreationTab implements EventListener {
|
||||
|
||||
@FXML
|
||||
private Button createButton;
|
||||
|
@ -1,9 +1,7 @@
|
||||
package envoy.client.ui.controller;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.logging.*;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.scene.control.*;
|
||||
@ -11,13 +9,12 @@ import javafx.scene.control.Alert.AlertType;
|
||||
import javafx.scene.image.ImageView;
|
||||
|
||||
import envoy.client.data.ClientConfig;
|
||||
import envoy.client.ui.IconUtil;
|
||||
import envoy.client.ui.Startup;
|
||||
import envoy.client.ui.*;
|
||||
import envoy.data.LoginCredentials;
|
||||
import envoy.event.EventBus;
|
||||
import envoy.event.HandshakeRejection;
|
||||
import envoy.util.Bounds;
|
||||
import envoy.util.EnvoyLog;
|
||||
import envoy.util.*;
|
||||
|
||||
import dev.kske.eventbus.*;
|
||||
|
||||
/**
|
||||
* Project: <strong>envoy-client</strong><br>
|
||||
@ -28,7 +25,7 @@ import envoy.util.EnvoyLog;
|
||||
* @author Maximilian Käfer
|
||||
* @since Envoy Client v0.1-beta
|
||||
*/
|
||||
public final class LoginScene {
|
||||
public final class LoginScene implements EventListener {
|
||||
|
||||
@FXML
|
||||
private TextField userTextField;
|
||||
@ -60,7 +57,6 @@ public final class LoginScene {
|
||||
private boolean registration = false;
|
||||
|
||||
private static final Logger logger = EnvoyLog.getLogger(LoginScene.class);
|
||||
private static final EventBus eventBus = EventBus.getInstance();
|
||||
private static final ClientConfig config = ClientConfig.getInstance();
|
||||
|
||||
@FXML
|
||||
@ -68,7 +64,7 @@ public final class LoginScene {
|
||||
connectionLabel.setText("Server: " + config.getServer() + ":" + config.getPort());
|
||||
|
||||
// Show an alert after an unsuccessful handshake
|
||||
eventBus.register(HandshakeRejection.class, e -> Platform.runLater(() -> { new Alert(AlertType.ERROR, e.get()).showAndWait(); }));
|
||||
EventBus.getInstance().registerListener(this);
|
||||
|
||||
logo.setImage(IconUtil.loadIcon("envoy_logo"));
|
||||
|
||||
@ -119,4 +115,7 @@ public final class LoginScene {
|
||||
logger.log(Level.INFO, "The login process has been cancelled. Exiting...");
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
@Event
|
||||
private void onHandshakeRejection(HandshakeRejection evt) { new Alert(AlertType.ERROR, evt.get()).showAndWait(); }
|
||||
}
|
||||
|
@ -7,9 +7,10 @@ import javafx.scene.input.InputEvent;
|
||||
import envoy.client.event.SendEvent;
|
||||
import envoy.client.util.IssueUtil;
|
||||
import envoy.data.User;
|
||||
import envoy.event.EventBus;
|
||||
import envoy.event.IssueProposal;
|
||||
|
||||
import dev.kske.eventbus.EventBus;
|
||||
|
||||
/**
|
||||
* This class offers the option for users to submit a bug report. Only the title
|
||||
* of a bug is needed to be sent.
|
||||
|
@ -1,12 +1,12 @@
|
||||
package envoy.client.ui.settings;
|
||||
|
||||
import javafx.scene.control.ComboBox;
|
||||
import javafx.scene.control.Tooltip;
|
||||
import javafx.scene.control.*;
|
||||
|
||||
import envoy.client.data.SettingsItem;
|
||||
import envoy.client.event.ThemeChangeEvent;
|
||||
import envoy.data.User.UserStatus;
|
||||
import envoy.event.EventBus;
|
||||
|
||||
import dev.kske.eventbus.EventBus;
|
||||
|
||||
/**
|
||||
* Project: <strong>envoy-client</strong><br>
|
||||
@ -44,7 +44,7 @@ public final class GeneralSettingsPane extends SettingsPane {
|
||||
combobox.setTooltip(new Tooltip("Determines the current theme Envoy will be displayed in."));
|
||||
combobox.setValue(settings.getCurrentTheme());
|
||||
combobox.setOnAction(
|
||||
e -> { settings.setCurrentTheme(combobox.getValue()); EventBus.getInstance().dispatch(new ThemeChangeEvent(combobox.getValue())); });
|
||||
e -> { settings.setCurrentTheme(combobox.getValue()); EventBus.getInstance().dispatch(new ThemeChangeEvent()); });
|
||||
getChildren().add(combobox);
|
||||
|
||||
final var statusComboBox = new ComboBox<UserStatus>();
|
||||
|
@ -1,31 +1,27 @@
|
||||
package envoy.client.ui.settings;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.logging.*;
|
||||
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.Cursor;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.control.Alert.AlertType;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.image.*;
|
||||
import javafx.scene.input.InputEvent;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.stage.FileChooser;
|
||||
|
||||
import envoy.client.event.SendEvent;
|
||||
import envoy.client.ui.IconUtil;
|
||||
import envoy.client.ui.SceneContext;
|
||||
import envoy.client.ui.*;
|
||||
import envoy.client.ui.custom.ProfilePicImageView;
|
||||
import envoy.data.User;
|
||||
import envoy.event.*;
|
||||
import envoy.util.Bounds;
|
||||
import envoy.util.EnvoyLog;
|
||||
import envoy.util.*;
|
||||
|
||||
import dev.kske.eventbus.EventBus;
|
||||
|
||||
/**
|
||||
* Project: <strong>envoy-client</strong><br>
|
||||
|
@ -7,19 +7,20 @@
|
||||
* @author Maximilian Käfer
|
||||
* @since Envoy Client v0.1-beta
|
||||
*/
|
||||
module envoy {
|
||||
module envoy.client {
|
||||
|
||||
requires transitive envoy.common;
|
||||
requires transitive java.desktop;
|
||||
requires transitive java.logging;
|
||||
requires transitive java.prefs;
|
||||
requires envoy.common;
|
||||
requires java.desktop;
|
||||
requires java.logging;
|
||||
requires java.prefs;
|
||||
requires javafx.controls;
|
||||
requires javafx.fxml;
|
||||
requires javafx.base;
|
||||
requires javafx.graphics;
|
||||
|
||||
opens envoy.client.ui to javafx.graphics, javafx.fxml;
|
||||
opens envoy.client.ui.controller to javafx.graphics, javafx.fxml, envoy.client.util;
|
||||
opens envoy.client.ui to javafx.graphics, javafx.fxml, dev.kske.eventbus;
|
||||
opens envoy.client.ui.controller to javafx.graphics, javafx.fxml, envoy.client.util, dev.kske.eventbus;
|
||||
opens envoy.client.ui.custom to javafx.graphics, javafx.fxml;
|
||||
opens envoy.client.ui.settings to envoy.client.util;
|
||||
opens envoy.client.net to dev.kske.eventbus;
|
||||
}
|
||||
|
@ -12,11 +12,24 @@
|
||||
<version>0.1-beta</version>
|
||||
</parent>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>kske-repo</id>
|
||||
<url>https://kske.dev/maven-repo</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>dev.kske</groupId>
|
||||
<artifactId>event-bus</artifactId>
|
||||
<version>0.0.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<version>5.5.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
|
@ -2,7 +2,13 @@ package envoy.event;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import dev.kske.eventbus.IEvent;
|
||||
|
||||
/**
|
||||
* This class serves as a convenience base class for all events. It implements
|
||||
* the {@link IEvent} interface and provides a generic value. For events without
|
||||
* a value there also is {@link envoy.event.Event.Valueless}.
|
||||
* <p>
|
||||
* Project: <strong>envoy-common</strong><br>
|
||||
* File: <strong>Event.java</strong><br>
|
||||
* Created: <strong>04.12.2019</strong><br>
|
||||
@ -11,7 +17,7 @@ import java.io.Serializable;
|
||||
* @param <T> the type of the Event
|
||||
* @since Envoy v0.2-alpha
|
||||
*/
|
||||
public abstract class Event<T> implements Serializable {
|
||||
public abstract class Event<T> implements IEvent, Serializable {
|
||||
|
||||
protected final T value;
|
||||
|
||||
|
@ -1,82 +0,0 @@
|
||||
package envoy.event;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* This class handles events by allowing event handlers to register themselves
|
||||
* and then be notified about certain events dispatched by the event bus.<br>
|
||||
* <br>
|
||||
* The event bus is a singleton and can be used across the entire application to
|
||||
* guarantee the propagation of events.<br>
|
||||
* <br>
|
||||
* Project: <strong>envoy-common</strong><br>
|
||||
* File: <strong>EventBus.java</strong><br>
|
||||
* Created: <strong>04.12.2019</strong><br>
|
||||
*
|
||||
* @author Kai S. K. Engelbart
|
||||
* @since Envoy v0.2-alpha
|
||||
*/
|
||||
public final class EventBus {
|
||||
|
||||
/**
|
||||
* Contains all event handler instances registered at this event bus as values
|
||||
* mapped to by their supported event classes.
|
||||
*/
|
||||
private Map<Class<? extends Event<?>>, List<Consumer<Event<?>>>> handlers = new HashMap<>();
|
||||
|
||||
/**
|
||||
* The singleton instance of this event bus that is used across the
|
||||
* entire application.
|
||||
*/
|
||||
private static EventBus eventBus = new EventBus();
|
||||
|
||||
/**
|
||||
* This constructor is not accessible from outside this class because a
|
||||
* singleton instance of it is provided by the {@link EventBus#getInstance()}
|
||||
* method.
|
||||
*/
|
||||
private EventBus() {}
|
||||
|
||||
/**
|
||||
* @return the singleton instance of the event bus
|
||||
* @since Envoy v0.2-alpha
|
||||
*/
|
||||
public static EventBus getInstance() { return eventBus; }
|
||||
|
||||
/**
|
||||
* Registers an event handler to be notified when an
|
||||
* event of a certain type is dispatched.
|
||||
*
|
||||
* @param <T> the type of event values to notify the handler about
|
||||
* @param eventClass the class which the event handler is subscribing to
|
||||
* @param handler the event handler to register
|
||||
* @since Envoy v0.2-alpha
|
||||
*/
|
||||
public <T extends Event<?>> void register(Class<T> eventClass, Consumer<T> handler) {
|
||||
if (!handlers.containsKey(eventClass)) handlers.put(eventClass, new ArrayList<>());
|
||||
handlers.get(eventClass).add((Consumer<Event<?>>) handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches an event to every event handler subscribed to it.
|
||||
*
|
||||
* @param event the {@link Event} to dispatch
|
||||
* @since Envoy v0.2-alpha
|
||||
*/
|
||||
public void dispatch(Event<?> event) {
|
||||
handlers.keySet()
|
||||
.stream()
|
||||
.filter(event.getClass()::equals)
|
||||
.map(handlers::get)
|
||||
.flatMap(List::stream)
|
||||
.forEach(h -> h.accept(event));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a map of all event handler instances currently registered at this
|
||||
* event bus with the event classes they are subscribed to as keys
|
||||
* @since Envoy v0.2-alpha
|
||||
*/
|
||||
public Map<Class<? extends Event<?>>, List<Consumer<Event<?>>>> getHandlers() { return handlers; }
|
||||
}
|
@ -16,4 +16,5 @@ module envoy.common {
|
||||
exports envoy.event.contact;
|
||||
|
||||
requires transitive java.logging;
|
||||
requires transitive dev.kske.eventbus;
|
||||
}
|
||||
|
@ -16,5 +16,4 @@ module envoy.server {
|
||||
requires transitive java.persistence;
|
||||
requires transitive java.sql;
|
||||
requires transitive org.hibernate.orm.core;
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user