From 4c35596f1918c5e32323752277ca456d9c6d95f3 Mon Sep 17 00:00:00 2001 From: Mathis Ginkel Date: Tue, 21 Apr 2026 22:18:06 +0200 Subject: [PATCH 1/4] Feat: Change look of chat box --- .../components/chatui/chatbox.fxml | 7 ++- .../components/chatui/chattab.fxml | 2 +- .../ui-structure/components/chatui/chatui.css | 62 ++++++++++++++++--- 3 files changed, 57 insertions(+), 14 deletions(-) diff --git a/src/main/resources/ui-structure/components/chatui/chatbox.fxml b/src/main/resources/ui-structure/components/chatui/chatbox.fxml index e88c640..2a6c526 100644 --- a/src/main/resources/ui-structure/components/chatui/chatbox.fxml +++ b/src/main/resources/ui-structure/components/chatui/chatbox.fxml @@ -3,13 +3,14 @@ + - + styleClass="tab-pane"> diff --git a/src/main/resources/ui-structure/components/chatui/chattab.fxml b/src/main/resources/ui-structure/components/chatui/chattab.fxml index ce3bf95..7db08e1 100644 --- a/src/main/resources/ui-structure/components/chatui/chattab.fxml +++ b/src/main/resources/ui-structure/components/chatui/chattab.fxml @@ -8,7 +8,7 @@ Date: Sun, 26 Apr 2026 20:25:31 +0200 Subject: [PATCH 2/4] Fix: Reopen whisper chat when previously closed --- .../client/ui/chatui/ChatBoxController.java | 45 +++++++++++++++---- .../client/ui/chatui/ChatViewController.java | 28 +++++++++--- 2 files changed, 60 insertions(+), 13 deletions(-) diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/chatui/ChatBoxController.java b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/chatui/ChatBoxController.java index 26aa545..66b087b 100644 --- a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/chatui/ChatBoxController.java +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/chatui/ChatBoxController.java @@ -1,6 +1,7 @@ package ch.unibas.dmi.dbis.cs108.casono.client.ui.chatui; import ch.unibas.dmi.dbis.cs108.casono.client.chat.ChatController; +import ch.unibas.dmi.dbis.cs108.casono.client.chat.ChatController.ChatKey; import ch.unibas.dmi.dbis.cs108.casono.client.chat.ChatModel; import ch.unibas.dmi.dbis.cs108.casono.client.chat.ChatType; import ch.unibas.dmi.dbis.cs108.casono.client.chat.Message; @@ -167,9 +168,19 @@ public class ChatBoxController { ChatType whisper = ChatType.WHISPER; chatController .getChatModelMap() - .put(new ChatController.ChatKey(whisper, target), chatModel); - addChatTab(target, chatModel, whisper); + .put(new ChatKey(whisper, target), chatModel); + ChatViewController chatViewController = addChatTab(target, chatModel, whisper); + Tab chatTab = chatViewController.getChatTab(); + chatTab.setOnCloseRequest(_ -> { + chatViewController.tabIsOpen = false; + chatTabPane.getTabs().remove(chatTab); + }); } else { + ChatViewController chatViewController = chatController.activeChatControllers.get(new ChatKey(ChatType.WHISPER, target)); + if (!chatViewController.tabIsOpen) { + reopenChatTab(chatViewController.getChatTab()); + chatViewController.tabIsOpen = true; + } chatTabPane.getSelectionModel().select(usernameTabMap.get(target)); } } @@ -183,18 +194,25 @@ public class ChatBoxController { * @param chatModel The {@link ChatModel} containing the data and logic for this specific chat. * @throws RuntimeException If the FXML resource for the chat tab cannot be loaded. */ - public void addChatTab(String title, ChatModel chatModel, ChatType chatType) { + public ChatViewController addChatTab(String title, ChatModel chatModel, ChatType chatType) { String ressource = "/ui-structure/components/chatui/chattab.fxml"; URL resource = getClass().getResource(ressource); FXMLLoader fxmlLoader = new FXMLLoader(resource); - runOnPlatformSynchronized( + return runOnPlatformSynchronized( () -> { try { ChatViewController chatViewController = new ChatViewController( - this.chatController, chatModel, this.username); + this.chatController, chatModel, this.username, this); + + ChatKey chatKey; + if (chatType.equals(ChatType.WHISPER)) { + chatKey = new ChatKey(chatType, title); + } else { + chatKey = new ChatKey(chatType); + } chatController.activeChatControllers.put( - new ChatController.ChatKey(chatType), chatViewController); + chatKey, chatViewController); fxmlLoader.setController(chatViewController); Node load = fxmlLoader.load(); VBox.setVgrow(load, Priority.ALWAYS); @@ -204,9 +222,13 @@ public class ChatBoxController { chatModel.addListener((msg) -> chatViewController.showMessage(msg)); Tab newChat = new Tab(title, vbox); usernameTabMap.put(title, newChat); - this.chatTabPane.getTabs().add(newChat); + chatTabPane.getTabs().add(newChat); this.chatTabPane.getSelectionModel().select(newChat); - return newChat; + chatViewController.setChatTab(newChat); + if (!chatType.equals(ChatType.WHISPER)) { + newChat.setClosable(false); + } + return chatViewController; } catch (IOException e) { throw new RuntimeException(e); } @@ -267,4 +289,11 @@ public class ChatBoxController { } } } + + public void reopenChatTab(Tab chatTab) { + Platform.runLater(() -> { + chatTabPane.getTabs().add(chatTab); + chatTabPane.getSelectionModel().select(chatTab); + }); + } } diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/chatui/ChatViewController.java b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/chatui/ChatViewController.java index 2bad460..2a1ec5f 100644 --- a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/chatui/ChatViewController.java +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/chatui/ChatViewController.java @@ -2,22 +2,22 @@ package ch.unibas.dmi.dbis.cs108.casono.client.ui.chatui; import ch.unibas.dmi.dbis.cs108.casono.client.chat.ChatController; import ch.unibas.dmi.dbis.cs108.casono.client.chat.ChatModel; +import ch.unibas.dmi.dbis.cs108.casono.client.chat.ChatType; import ch.unibas.dmi.dbis.cs108.casono.client.chat.Message; import java.net.URL; +import java.util.Map; import java.util.ResourceBundle; import javafx.application.Platform; import javafx.fxml.FXML; import javafx.fxml.Initializable; -import javafx.scene.control.Button; -import javafx.scene.control.Label; -import javafx.scene.control.ScrollPane; -import javafx.scene.control.TextField; +import javafx.scene.control.*; import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; /** Responsible for the presentation of the ChatModel to the Client */ public class ChatViewController implements Initializable { + private final ChatBoxController chatBoxController; @FXML private Button sendButton; @FXML private TextField inputField; @@ -30,6 +30,18 @@ public class ChatViewController implements Initializable { @FXML private VBox chat; + public Tab getChatTab() { + return chatTab; + } + + public void setChatTab(Tab chatTab) { + this.chatTab = chatTab; + } + + @FXML private Tab chatTab; + + public Boolean tabIsOpen; + private final ChatModel chatModel; private final String username; @@ -38,10 +50,12 @@ public class ChatViewController implements Initializable { private static final int CHAT_PADDING = 20; - public ChatViewController(ChatController chatController, ChatModel chatModel, String username) { + public ChatViewController(ChatController chatController, ChatModel chatModel, String username, ChatBoxController chatBoxController) { this.controller = chatController; this.username = username; this.chatModel = chatModel; + this.chatBoxController = chatBoxController; + tabIsOpen = true; } /** @@ -88,6 +102,10 @@ public class ChatViewController implements Initializable { * @param msg The {@link Message} object containing the content and metadata to display. */ public void showMessage(Message msg) { + if (!tabIsOpen) { + tabIsOpen = true; + chatBoxController.reopenChatTab(chatTab); + } Platform.runLater( () -> { String msgText = -- 2.52.0 From efd91fbe5f11608bcf13200307272fb7185b9512 Mon Sep 17 00:00:00 2001 From: Mathis Ginkel Date: Sun, 26 Apr 2026 22:14:00 +0200 Subject: [PATCH 3/4] Style: Apply Spotless --- .../client/ui/chatui/ChatBoxController.java | 28 +++++++++---------- .../client/ui/chatui/ChatViewController.java | 14 +++++++--- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/chatui/ChatBoxController.java b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/chatui/ChatBoxController.java index 66b087b..bfb51b0 100644 --- a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/chatui/ChatBoxController.java +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/chatui/ChatBoxController.java @@ -166,17 +166,17 @@ public class ChatBoxController { if (!activeWhisperChats.contains(target)) { activeWhisperChats.add(target); ChatType whisper = ChatType.WHISPER; - chatController - .getChatModelMap() - .put(new ChatKey(whisper, target), chatModel); + chatController.getChatModelMap().put(new ChatKey(whisper, target), chatModel); ChatViewController chatViewController = addChatTab(target, chatModel, whisper); Tab chatTab = chatViewController.getChatTab(); - chatTab.setOnCloseRequest(_ -> { - chatViewController.tabIsOpen = false; - chatTabPane.getTabs().remove(chatTab); - }); + chatTab.setOnCloseRequest( + _ -> { + chatViewController.tabIsOpen = false; + chatTabPane.getTabs().remove(chatTab); + }); } else { - ChatViewController chatViewController = chatController.activeChatControllers.get(new ChatKey(ChatType.WHISPER, target)); + ChatViewController chatViewController = + chatController.activeChatControllers.get(new ChatKey(ChatType.WHISPER, target)); if (!chatViewController.tabIsOpen) { reopenChatTab(chatViewController.getChatTab()); chatViewController.tabIsOpen = true; @@ -211,8 +211,7 @@ public class ChatBoxController { } else { chatKey = new ChatKey(chatType); } - chatController.activeChatControllers.put( - chatKey, chatViewController); + chatController.activeChatControllers.put(chatKey, chatViewController); fxmlLoader.setController(chatViewController); Node load = fxmlLoader.load(); VBox.setVgrow(load, Priority.ALWAYS); @@ -291,9 +290,10 @@ public class ChatBoxController { } public void reopenChatTab(Tab chatTab) { - Platform.runLater(() -> { - chatTabPane.getTabs().add(chatTab); - chatTabPane.getSelectionModel().select(chatTab); - }); + Platform.runLater( + () -> { + chatTabPane.getTabs().add(chatTab); + chatTabPane.getSelectionModel().select(chatTab); + }); } } diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/chatui/ChatViewController.java b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/chatui/ChatViewController.java index 2a1ec5f..cb8dc1b 100644 --- a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/chatui/ChatViewController.java +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/chatui/ChatViewController.java @@ -2,15 +2,17 @@ package ch.unibas.dmi.dbis.cs108.casono.client.ui.chatui; import ch.unibas.dmi.dbis.cs108.casono.client.chat.ChatController; import ch.unibas.dmi.dbis.cs108.casono.client.chat.ChatModel; -import ch.unibas.dmi.dbis.cs108.casono.client.chat.ChatType; import ch.unibas.dmi.dbis.cs108.casono.client.chat.Message; import java.net.URL; -import java.util.Map; import java.util.ResourceBundle; import javafx.application.Platform; import javafx.fxml.FXML; import javafx.fxml.Initializable; -import javafx.scene.control.*; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.control.ScrollPane; +import javafx.scene.control.Tab; +import javafx.scene.control.TextField; import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; @@ -50,7 +52,11 @@ public class ChatViewController implements Initializable { private static final int CHAT_PADDING = 20; - public ChatViewController(ChatController chatController, ChatModel chatModel, String username, ChatBoxController chatBoxController) { + public ChatViewController( + ChatController chatController, + ChatModel chatModel, + String username, + ChatBoxController chatBoxController) { this.controller = chatController; this.username = username; this.chatModel = chatModel; -- 2.52.0 From d8d6dbb34f0750c616e9f90fe1058de30e476e3e Mon Sep 17 00:00:00 2001 From: Mathis Ginkel Date: Sun, 26 Apr 2026 22:19:57 +0200 Subject: [PATCH 4/4] Style: fixing some linter warnings in chat ui classes --- .../client/ui/chatui/ChatBoxController.java | 17 +++++------------ .../client/ui/chatui/ChatViewController.java | 13 ++----------- 2 files changed, 7 insertions(+), 23 deletions(-) diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/chatui/ChatBoxController.java b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/chatui/ChatBoxController.java index bfb51b0..46bfe4f 100644 --- a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/chatui/ChatBoxController.java +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/chatui/ChatBoxController.java @@ -21,7 +21,6 @@ import javafx.scene.control.MenuButton; import javafx.scene.control.MenuItem; import javafx.scene.control.Tab; import javafx.scene.control.TabPane; -import javafx.scene.layout.HBox; import javafx.scene.layout.Priority; import javafx.scene.layout.VBox; @@ -31,16 +30,10 @@ public class ChatBoxController { private final ChatController chatController; - @FXML private VBox chatBox; - @FXML private TabPane chatTabPane; @FXML private MenuButton addWhisperChatButton; - @FXML private HBox menuBox; - - private FXMLLoader fxmlLoader; - private final List activeWhisperChats; @FXML private final Map usernameTabMap; @@ -77,7 +70,7 @@ public class ChatBoxController { ChatModel globalChatModel = new ChatModel(global, username, -1, null); chatController.getChatModelMap().put(new ChatController.ChatKey(global), globalChatModel); addChatTab("GLOBAL", globalChatModel, global); - addWhisperChatButton.setOnAction(event -> addWhisperChatButton.show()); + addWhisperChatButton.setOnAction(_ -> addWhisperChatButton.show()); } /** @@ -97,7 +90,7 @@ public class ChatBoxController { MenuItem menuItem = new MenuItem(targetUserName); addWhisperChatButton.getItems().add(menuItem); menuItem.setOnAction( - event -> + _ -> addWhisperChat( targetUserName, new ChatModel( @@ -131,7 +124,7 @@ public class ChatBoxController { if (oldUsername.equals(item.getText())) { item.setText(newUsername); item.setOnAction( - event -> + _ -> addWhisperChat( newUsername, new ChatModel( @@ -203,7 +196,7 @@ public class ChatBoxController { try { ChatViewController chatViewController = new ChatViewController( - this.chatController, chatModel, this.username, this); + this.chatController, chatModel, this); ChatKey chatKey; if (chatType.equals(ChatType.WHISPER)) { @@ -218,7 +211,7 @@ public class ChatBoxController { VBox vbox = new VBox(); VBox.setVgrow(vbox, Priority.ALWAYS); vbox.getChildren().add(load); - chatModel.addListener((msg) -> chatViewController.showMessage(msg)); + chatModel.addListener(chatViewController::showMessage); Tab newChat = new Tab(title, vbox); usernameTabMap.put(title, newChat); chatTabPane.getTabs().add(newChat); diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/chatui/ChatViewController.java b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/chatui/ChatViewController.java index cb8dc1b..fc9bff8 100644 --- a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/chatui/ChatViewController.java +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/chatui/ChatViewController.java @@ -13,7 +13,6 @@ import javafx.scene.control.Label; import javafx.scene.control.ScrollPane; import javafx.scene.control.Tab; import javafx.scene.control.TextField; -import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; /** Responsible for the presentation of the ChatModel to the Client */ @@ -24,10 +23,6 @@ public class ChatViewController implements Initializable { @FXML private TextField inputField; - @FXML private VBox chatInterfaceVBox; - - @FXML private HBox controlBar; - @FXML private ScrollPane scrollPane; @FXML private VBox chat; @@ -46,8 +41,6 @@ public class ChatViewController implements Initializable { private final ChatModel chatModel; - private final String username; - private final ChatController controller; private static final int CHAT_PADDING = 20; @@ -55,10 +48,8 @@ public class ChatViewController implements Initializable { public ChatViewController( ChatController chatController, ChatModel chatModel, - String username, ChatBoxController chatBoxController) { this.controller = chatController; - this.username = username; this.chatModel = chatModel; this.chatBoxController = chatBoxController; tabIsOpen = true; @@ -74,8 +65,8 @@ public class ChatViewController implements Initializable { */ @Override public void initialize(URL location, ResourceBundle resourceBundle) { - inputField.setOnAction(event -> sendMessage()); - sendButton.setOnAction(event -> sendMessage()); + inputField.setOnAction(_ -> sendMessage()); + sendButton.setOnAction(_ -> sendMessage()); scrollPane.vvalueProperty().bind(chat.heightProperty()); } -- 2.52.0