diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/gameui/gameuicomponents/HighscoreViewController.java b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/gameui/gameuicomponents/HighscoreViewController.java new file mode 100644 index 0000000..e395b68 --- /dev/null +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/gameui/gameuicomponents/HighscoreViewController.java @@ -0,0 +1,114 @@ +package ch.unibas.dmi.dbis.cs108.casono.client.ui.gameui.gameuicomponents; + +import ch.unibas.dmi.dbis.cs108.casono.client.network.LobbyClient; +import java.util.List; +import javafx.fxml.FXML; +import javafx.scene.Node; +import javafx.scene.control.Label; +import javafx.scene.control.ListView; +import javafx.scene.input.MouseEvent; +import javafx.stage.Stage; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +/** Controller for the highscore popup window. */ +public class HighscoreViewController { + + private static final Logger LOGGER = LogManager.getLogger(HighscoreViewController.class); + + @FXML private ListView highscoreList; + @FXML private Label statusLabel; + @FXML private Node highscoreRoot; + + private LobbyClient lobbyClient; + private double dragOffsetX; + private double dragOffsetY; + + public void setLobbyClient(LobbyClient lobbyClient) { + this.lobbyClient = lobbyClient; + } + + /** Starts dragging the window from anywhere in the popup. */ + @FXML + public void onPopupPressed(MouseEvent event) { + Stage stage = getStage(); + if (stage == null) { + return; + } + + dragOffsetX = stage.getX() - event.getScreenX(); + dragOffsetY = stage.getY() - event.getScreenY(); + } + + /** Moves the popup window while the mouse is dragged anywhere on the popup. */ + @FXML + public void onPopupDragged(MouseEvent event) { + Stage stage = getStage(); + if (stage == null) { + return; + } + + stage.setX(event.getScreenX() + dragOffsetX); + stage.setY(event.getScreenY() + dragOffsetY); + } + + /** Returns the popup stage if the root is already attached to a scene. */ + private Stage getStage() { + if (highscoreRoot == null || highscoreRoot.getScene() == null) { + return null; + } + + return (Stage) highscoreRoot.getScene().getWindow(); + } + + /** Loads current highscores from the server and refreshes the list. */ + @FXML + public void refreshHighscores() { + if (highscoreList == null || statusLabel == null) { + return; + } + + if (lobbyClient == null) { + statusLabel.setText("Lobby client not initialized."); + return; + } + + try { + List entries = lobbyClient.getHighscores(); + highscoreList.getItems().setAll(entries); + statusLabel.setText( + entries.isEmpty() ? "No highscores yet." : entries.size() + " entries loaded."); + } catch (RuntimeException e) { + LOGGER.error("Failed to load highscores: {}", e.getMessage()); + statusLabel.setText("Failed to load highscores."); + } + } + + /** Clears all highscores globally on the server and reloads the list. */ + @FXML + public void clearHighscores() { + if (lobbyClient == null || statusLabel == null) { + return; + } + + try { + lobbyClient.clearHighscores(); + refreshHighscores(); + statusLabel.setText("Highscores cleared."); + } catch (RuntimeException e) { + LOGGER.error("Failed to clear highscores: {}", e.getMessage()); + statusLabel.setText("Failed to clear highscores."); + } + } + + /** Closes the highscore popup window. */ + @FXML + public void closeWindow() { + if (highscoreList == null || highscoreList.getScene() == null) { + return; + } + + Stage stage = (Stage) highscoreList.getScene().getWindow(); + stage.close(); + } +} diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/gameui/gameuicomponents/TaskbarController.java b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/gameui/gameuicomponents/TaskbarController.java index cd3a34e..ca3dadd 100644 --- a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/gameui/gameuicomponents/TaskbarController.java +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/gameui/gameuicomponents/TaskbarController.java @@ -1,10 +1,12 @@ package ch.unibas.dmi.dbis.cs108.casono.client.ui.gameui.gameuicomponents; +import ch.unibas.dmi.dbis.cs108.casono.client.ClientApp; import ch.unibas.dmi.dbis.cs108.casono.client.game.GameService; import ch.unibas.dmi.dbis.cs108.casono.client.game.GameState; import ch.unibas.dmi.dbis.cs108.casono.client.game.Player; import ch.unibas.dmi.dbis.cs108.casono.client.game.PlayerId; import ch.unibas.dmi.dbis.cs108.casono.client.game.PlayerState; +import ch.unibas.dmi.dbis.cs108.casono.client.network.LobbyClient; import ch.unibas.dmi.dbis.cs108.casono.client.ui.lobbyui.Casinomainui; import javafx.fxml.FXML; import javafx.scene.control.Alert; @@ -1079,4 +1081,47 @@ public class TaskbarController { private void onBrowserButtonClick() { CasinoBrowserController.open("wikipedia.org"); } + + /** Opens the highscore popup window from the taskbar. */ + @FXML + private void onHighscoreButtonClick() { + try { + var shared = ClientApp.getSharedClientService(); + if (shared == null || shared.isOffline()) { + Alert alert = new Alert(Alert.AlertType.INFORMATION); + alert.setTitle("Info"); + alert.setHeaderText(null); + alert.setContentText("No active server connection for highscores."); + alert.showAndWait(); + return; + } + + javafx.fxml.FXMLLoader loader = + new javafx.fxml.FXMLLoader( + getClass() + .getResource( + "/ui-structure/gameuicomponents/HighscoreView.fxml")); + javafx.scene.Parent root = loader.load(); + + HighscoreViewController controller = loader.getController(); + controller.setLobbyClient(new LobbyClient(shared)); + controller.refreshHighscores(); + + javafx.stage.Stage stage = new javafx.stage.Stage(); + stage.initStyle(javafx.stage.StageStyle.TRANSPARENT); + stage.setTitle("Casono Highscores"); + javafx.scene.image.Image icon = + new javafx.scene.image.Image( + getClass().getResource("/images/logoinverted.png").toExternalForm()); + stage.getIcons().add(icon); + javafx.scene.Scene scene = new javafx.scene.Scene(root); + scene.setFill(javafx.scene.paint.Color.TRANSPARENT); + stage.setScene(scene); + stage.show(); + stage.setAlwaysOnTop(true); + stage.toFront(); + } catch (Exception e) { + LOGGER.error("Could not open highscore window from taskbar: {}", e.getMessage()); + } + } } 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 37587cc..db644f4 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 @@ -4,12 +4,15 @@ 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.gameuicomponents.HighscoreViewController; import java.io.IOException; import java.net.URL; import javafx.application.Platform; import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; import javafx.scene.Node; +import javafx.scene.Parent; +import javafx.scene.Scene; import javafx.scene.control.Alert; import javafx.scene.control.Alert.AlertType; import javafx.scene.control.Button; @@ -20,6 +23,8 @@ import javafx.scene.image.ImageView; import javafx.scene.layout.AnchorPane; import javafx.scene.layout.VBox; import javafx.scene.shape.Rectangle; +import javafx.stage.Stage; +import javafx.stage.StageStyle; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -287,4 +292,36 @@ public class CasinomainuiController { LOGGER.error("Failed to create or add lobby: {}", e.getMessage()); } } + + /** Opens the highscore popup from the lobby UI. */ + @FXML + public void handleOpenHighscores() { + try { + FXMLLoader loader = + new FXMLLoader( + getClass() + .getResource( + "/ui-structure/gameuicomponents/HighscoreView.fxml")); + Parent root = loader.load(); + + HighscoreViewController controller = loader.getController(); + controller.setLobbyClient(lobbyClient); + controller.refreshHighscores(); + + Stage stage = new Stage(); + stage.initStyle(StageStyle.TRANSPARENT); + stage.setTitle("Casono Highscores"); + String iconPath = getClass().getResource("/images/logoinverted.png").toExternalForm(); + stage.getIcons().add(new Image(iconPath)); + Scene scene = new Scene(root); + scene.setFill(javafx.scene.paint.Color.TRANSPARENT); + stage.setScene(scene); + stage.show(); + stage.setAlwaysOnTop(true); + stage.toFront(); + } catch (IOException e) { + LOGGER.warn("Could not open highscore window: {}", e.getMessage()); + showAlert("Could not open highscore window."); + } + } } diff --git a/src/main/resources/ui-structure/Casinomainui.fxml b/src/main/resources/ui-structure/Casinomainui.fxml index ee3b43a..b5df10b 100644 --- a/src/main/resources/ui-structure/Casinomainui.fxml +++ b/src/main/resources/ui-structure/Casinomainui.fxml @@ -81,15 +81,17 @@ - - - - - + + + + + + + +