diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/chat/ChatController.java b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/chat/ChatController.java index b07c712..09d7838 100644 --- a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/chat/ChatController.java +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/chat/ChatController.java @@ -4,8 +4,10 @@ import ch.unibas.dmi.dbis.cs108.casono.client.ClientApp; import ch.unibas.dmi.dbis.cs108.casono.client.network.ChatClient; import ch.unibas.dmi.dbis.cs108.casono.client.network.ClientService; import ch.unibas.dmi.dbis.cs108.casono.client.ui.chatui.ChatBoxController; +import ch.unibas.dmi.dbis.cs108.casono.client.ui.chatui.ChatViewController; import ch.unibas.dmi.dbis.cs108.casono.server.network.command.parsing.RequestParameter; import java.util.ArrayList; +import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; @@ -39,7 +41,11 @@ public class ChatController { return chatBoxController; } - private final ChatBoxController chatBoxController; + public void setChatBoxController(ChatBoxController chatBoxController) { + this.chatBoxController = chatBoxController; + } + + private ChatBoxController chatBoxController; private int lobbyId = -1; private final Timer timer; private final Consumer> serverEventListener; @@ -61,6 +67,12 @@ public class ChatController { /** List of all users connected to the server, to safe them locally on the client */ private final List localUserList; + public List getLocalUserList() { + return this.localUserList; + } + + public final Map activeChatControllers; + private final Logger logger; /** @@ -78,6 +90,7 @@ public class ChatController { this.chatBoxController = new ChatBoxController(username, this); this.logger = LogManager.getLogger(ChatController.class); this.serverEventListener = this::handleServerEvent; + this.activeChatControllers = new HashMap<>(); registerAsActiveController(clientService); clientService.addEventListener(serverEventListener); @@ -126,7 +139,7 @@ public class ChatController { } ChatModel lobbyChatModel = new ChatModel(ChatType.LOBBY, username, lobbyId, null); chatModelMap.put(key, lobbyChatModel); - this.chatBoxController.addChatTab("Lobby", lobbyChatModel); + this.chatBoxController.addChatTab("LOBBY", lobbyChatModel, ChatType.LOBBY); } /** 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 1864601..26aa545 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 @@ -3,6 +3,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.ChatModel; import ch.unibas.dmi.dbis.cs108.casono.client.chat.ChatType; +import ch.unibas.dmi.dbis.cs108.casono.client.chat.Message; import java.io.IOException; import java.net.URL; import java.util.ArrayList; @@ -27,7 +28,7 @@ public class ChatBoxController { private String username; - private ChatController chatController; + private final ChatController chatController; @FXML private VBox chatBox; @@ -43,8 +44,6 @@ public class ChatBoxController { @FXML private final Map usernameTabMap; - private String ressource = "/ui-structure/components/chatui/chattab.fxml"; - /** * Constructor for the ChatBoxController, initializes the necessary fields and data structures * for managing chat tabs and whisper chats. @@ -73,11 +72,10 @@ public class ChatBoxController { */ @FXML public void initialize() { - ChatModel globalChatModel = new ChatModel(ChatType.GLOBAL, username, -1, null); - chatController - .getChatModelMap() - .put(new ChatController.ChatKey(ChatType.GLOBAL), globalChatModel); - addChatTab("GLOBAL", globalChatModel); + ChatType global = ChatType.GLOBAL; + 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()); } @@ -166,10 +164,11 @@ public class ChatBoxController { public void addWhisperChat(String target, ChatModel chatModel) { if (!activeWhisperChats.contains(target)) { activeWhisperChats.add(target); + ChatType whisper = ChatType.WHISPER; chatController .getChatModelMap() - .put(new ChatController.ChatKey(ChatType.WHISPER, target), chatModel); - addChatTab(target, chatModel); + .put(new ChatController.ChatKey(whisper, target), chatModel); + addChatTab(target, chatModel, whisper); } else { chatTabPane.getSelectionModel().select(usernameTabMap.get(target)); } @@ -184,7 +183,8 @@ 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) { + public void 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( @@ -193,6 +193,8 @@ public class ChatBoxController { ChatViewController chatViewController = new ChatViewController( this.chatController, chatModel, this.username); + chatController.activeChatControllers.put( + new ChatController.ChatKey(chatType), chatViewController); fxmlLoader.setController(chatViewController); Node load = fxmlLoader.load(); VBox.setVgrow(load, Priority.ALWAYS); @@ -239,4 +241,30 @@ public class ChatBoxController { } } } + + public void loadChats() { + Map chatModelMap = chatController.getChatModelMap(); + ChatController.ChatKey key = new ChatController.ChatKey(ChatType.GLOBAL); + ChatModel global = chatModelMap.get(key); + ChatViewController globalController = chatController.activeChatControllers.get(key); + + for (String user : chatController.getLocalUserList()) { + addWhisperUser(user); + } + + for (Message msg : global.messages) { + globalController.showMessage(msg); + } + for (String user : chatController.getLocalUserList()) { + ChatController.ChatKey whisperUserKey = + new ChatController.ChatKey(ChatType.WHISPER, user); + if (chatModelMap.containsKey(whisperUserKey)) { + ChatModel whisperChatModel = chatModelMap.get(whisperUserKey); + addWhisperChat(user, whisperChatModel); + for (Message msg : whisperChatModel.messages) { + chatController.activeChatControllers.get(whisperUserKey).showMessage(msg); + } + } + } + } } diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/gameui/CasinoGameController.java b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/gameui/CasinoGameController.java index 1a65be2..f3ab44d 100644 --- a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/gameui/CasinoGameController.java +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/gameui/CasinoGameController.java @@ -18,15 +18,13 @@ import java.util.concurrent.CompletableFuture; import java.util.logging.Logger; import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; -import javafx.scene.Parent; -import javafx.scene.Scene; +import javafx.scene.Node; import javafx.scene.control.Label; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.AnchorPane; import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; -import javafx.stage.Stage; /** * Controller for the casino gaming area. @@ -67,7 +65,9 @@ public class CasinoGameController { private java.util.List lastCommunityKeys = java.util.List.of(); private java.util.List lastMyCardKeys = java.util.List.of(); private int lastPot = Integer.MIN_VALUE; + private ChatController chatController; + public static final double CHAT_CONTAINER_CONSTANT = 6.0; private static final int TOTAL_SLOTS = 5; private static final int PLAYER_SLOTS = 2; private int pot = 0; @@ -139,7 +139,6 @@ public class CasinoGameController { private static final double CHAT_WIDTH = 400; private static final double CHAT_HEIGHT = 600; - private ChatController chatController; private String chatUsername; private ClientService chatClientService; private int chatLobbyId = -1; @@ -197,6 +196,11 @@ public class CasinoGameController { } } + public void startChat(ChatController chatController) { + this.chatController = chatController; + initializeChatIfPossible(); + } + /** Set the PlayerId of the current player. */ @FXML public void initialize() { @@ -239,7 +243,8 @@ public class CasinoGameController { // empty display only (optional) renderCommunityCards(List.of()); renderPlayerCards(List.of()); - initializeChatIfPossible(); + + chatContainer.toFront(); } /** @@ -257,7 +262,6 @@ public class CasinoGameController { this.chatUsername = username; this.chatClientService = clientService; this.chatLobbyId = lobbyId; - initializeChatIfPossible(); } /** @@ -265,42 +269,32 @@ public class CasinoGameController { * is available and the chat has not already been initialized. */ private void initializeChatIfPossible() { - if (chatInitialized || chatClientService == null || chatUsername == null) { + if (chatInitialized + || chatClientService == null + || chatUsername == null + || chatController == null) { return; } try { - chatController = new ChatController(chatUsername, chatClientService); + chatController.updateUsername(chatUsername); URL resource = getClass().getResource("/ui-structure/components/chatui/chatbox.fxml"); FXMLLoader loader = new FXMLLoader(resource); loader.setController(chatController.getChatBoxController()); + Node chatNode = loader.load(); + chatContainer.getChildren().setAll(chatNode); + AnchorPane.setTopAnchor(chatNode, CHAT_CONTAINER_CONSTANT); + AnchorPane.setBottomAnchor(chatNode, CHAT_CONTAINER_CONSTANT); + AnchorPane.setLeftAnchor(chatNode, 0.0); + AnchorPane.setRightAnchor(chatNode, CHAT_CONTAINER_CONSTANT); - Parent root = loader.load(); - - Stage chatStage = new Stage(); - - chatStage.setTitle("Casono"); - - String iconPath = getClass().getResource("/images/logoinverted.png").toExternalForm(); - chatStage.getIcons().add(new Image(iconPath)); - - Scene scene = new Scene(root); - chatStage.setScene(scene); - - chatStage.setWidth(CHAT_WIDTH); - chatStage.setHeight(CHAT_HEIGHT); - - chatStage.setOnCloseRequest(event -> chatInitialized = false); - - chatStage.show(); + chatController.getChatBoxController().loadChats(); + chatInitialized = true; if (chatLobbyId >= 0) { chatController.setLobbyChat(chatLobbyId); } - - chatInitialized = true; - } catch (IOException e) { LOGGER.warning("Could not initialize game chat UI: " + e.getMessage()); } diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/gameui/CasinoGameUI.java b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/gameui/CasinoGameUI.java index d6908c1..c82dfe1 100644 --- a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/gameui/CasinoGameUI.java +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/gameui/CasinoGameUI.java @@ -1,6 +1,7 @@ package ch.unibas.dmi.dbis.cs108.casono.client.ui.gameui; import ch.unibas.dmi.dbis.cs108.casono.client.ClientApp; +import ch.unibas.dmi.dbis.cs108.casono.client.chat.ChatController; import ch.unibas.dmi.dbis.cs108.casono.client.game.GameService; import ch.unibas.dmi.dbis.cs108.casono.client.game.PlayerId; import ch.unibas.dmi.dbis.cs108.casono.client.network.ClientService; @@ -25,6 +26,7 @@ public class CasinoGameUI extends Application { private static final Logger LOG = Logger.getLogger(CasinoGameUI.class.getName()); private static ClientService clientService; + private static ChatController chatController; private static String username; private static int lobbyId = -1; @@ -56,6 +58,10 @@ public class CasinoGameUI extends Application { CasinoGameUI.username = username; } + public static void setChatController(ChatController chatController) { + CasinoGameUI.chatController = chatController; + } + /** * Sets the lobby ID to be used by the application. * @@ -124,6 +130,8 @@ public class CasinoGameUI extends Application { controller.setMyPlayerId(PlayerId.of(effectiveUsername)); controller.setChatContext(effectiveUsername, clientService, lobbyId); + controller.startChat(chatController); + Scene scene = new Scene(root, DEFAULT_WIDTH, DEFAULT_HEIGHT); stage.setTitle("Casono"); diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/lobbyui/CasinomainuiController.java b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/lobbyui/CasinomainuiController.java index b3c2297..518b8cf 100644 --- a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/lobbyui/CasinomainuiController.java +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/lobbyui/CasinomainuiController.java @@ -141,6 +141,7 @@ public class CasinomainuiController { AnchorPane.setBottomAnchor(chatNode, 0.0); AnchorPane.setLeftAnchor(chatNode, 0.0); AnchorPane.setRightAnchor(chatNode, 0.0); + gridManager.setChatController(chatController); } catch (IOException e) { LOGGER.warn("Could not initialize lobby chat UI: {}", e.getMessage()); } diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/lobbyui/LobbyButtonGridManager.java b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/lobbyui/LobbyButtonGridManager.java index e3f1d01..c2c5163 100644 --- a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/lobbyui/LobbyButtonGridManager.java +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/lobbyui/LobbyButtonGridManager.java @@ -1,6 +1,7 @@ package ch.unibas.dmi.dbis.cs108.casono.client.ui.lobbyui; import ch.unibas.dmi.dbis.cs108.casono.client.ClientApp; +import ch.unibas.dmi.dbis.cs108.casono.client.chat.ChatController; import ch.unibas.dmi.dbis.cs108.casono.client.network.ClientService; import ch.unibas.dmi.dbis.cs108.casono.client.network.LobbyClient; import ch.unibas.dmi.dbis.cs108.casono.client.ui.gameui.CasinoGameUI; @@ -43,6 +44,8 @@ public class LobbyButtonGridManager { private final LobbyButtonTranslationManager translationManager; private final LobbyClient lobbyClient; + private ChatController chatController; + private final ConcurrentHashMap imageCache = new ConcurrentHashMap<>(); private final ExecutorService executor = Executors.newCachedThreadPool(); @@ -557,6 +560,7 @@ public class LobbyButtonGridManager { CasinoGameUI.setClientService(cs); CasinoGameUI.setLobbyId(lobbyId); + CasinoGameUI.setChatController(chatController); String username = ClientApp.getSharedUsername(); if (username == null || username.isBlank()) { @@ -586,4 +590,8 @@ public class LobbyButtonGridManager { public LobbyClient getLobbyClient() { return lobbyClient; } + + public void setChatController(ChatController chatController) { + this.chatController = chatController; + } } diff --git a/src/main/resources/ui-structure/Casinogameui.fxml b/src/main/resources/ui-structure/Casinogameui.fxml index a5d5514..6e4369f 100644 --- a/src/main/resources/ui-structure/Casinogameui.fxml +++ b/src/main/resources/ui-structure/Casinogameui.fxml @@ -76,12 +76,14 @@ @@ -99,6 +101,7 @@ styleClass="dealer-box" fitWidth="100" fitHeight="100" + GridPane.columnIndex="2" preserveRatio="true" visible="false"/> @@ -117,56 +120,48 @@ + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -