Feat/ui switch lobby game #222

Merged
jona.walpert merged 12 commits from feat/ui-switch-lobby-game into main 2026-04-01 12:34:31 +02:00
17 changed files with 127 additions and 56 deletions
@@ -41,6 +41,11 @@ public class ChatController {
chatScrollPane.vvalueProperty().bind(chatVBox.heightProperty());
}
/** Standardkonstruktor. Wird von FXML verwendet. */
public ChatController() {
// default constructor for FXML
}
/**
* Diese Methode wird vom Senden-Button oder Enter ausgelöst. Sie gibt die eigene Nachricht an
* das Netzwerkprotokoll weiter.
@@ -15,11 +15,22 @@ import javafx.scene.layout.VBox;
*/
public class CasinoGameController {
/** Standardkonstruktor. Wird von FXML verwendet. */
public CasinoGameController() {
// default constructor for FXML
}
@FXML private Label welcomeText;
@FXML private VBox casinoTable;
// TODO: Test-Logik: wird durch echte Spielinteraktionen ersetzt,
// sobald die GameEngine fertig ist
/**
* Temporäre Test-Methode, die bei Klick auf den Tisch eine Platzhalteraktion ausführt.
*
* <p>Wird in der finalen Implementierung durch die Spiel-Logik ersetzt.
*/
@FXML
public void onTableClick() {
welcomeText.setText("Einsatz akzeptiert!");
@@ -17,6 +17,11 @@ import javafx.stage.Stage;
*/
public class CasinoGameUI extends Application {
/** Standardkonstruktor. */
public CasinoGameUI() {
// default no-arg constructor
}
private static final int DEFAULT_WIDTH = 1200;
private static final int DEFAULT_HEIGHT = 800;
@@ -29,7 +34,7 @@ public class CasinoGameUI extends Application {
@Override
public void start(Stage stage) throws IOException {
FXMLLoader fxmlLoader =
new FXMLLoader(CasinoGameUI.class.getResource("/ui-structure/casinogameui.fxml"));
new FXMLLoader(CasinoGameUI.class.getResource("/ui-structure/Casinogameui.fxml"));
Scene scene = new Scene(fxmlLoader.load(), DEFAULT_WIDTH, DEFAULT_HEIGHT);
stage.setTitle("Casono (GAME)");
@@ -27,6 +27,8 @@ import javafx.scene.shape.Rectangle;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/**
* Experimenteller integrierter Browser für Casono.
@@ -50,13 +52,17 @@ import javafx.stage.Stage;
*/
public class CasinoBrowserController {
/** Standardkonstruktor. Initialisiert den CasinoBrowserController. */
public CasinoBrowserController() {
// Intentionally left blank; controller initialization is FXML-driven.
}
private static final Set<String> TRUSTED_DOMAINS = new HashSet<>();
private static final CookieManager COOKIE_MANAGER =
new CookieManager(null, CookiePolicy.ACCEPT_ORIGINAL_SERVER);
private static final org.apache.logging.log4j.Logger LOGGER =
org.apache.logging.log4j.LogManager.getLogger(CasinoBrowserController.class);
private static final Logger LOGGER = LogManager.getLogger(CasinoBrowserController.class);
private static final int LOGO_HEIGHT = 40;
private static final int CORNER_RADIUS = 40;
@@ -354,8 +360,9 @@ public class CasinoBrowserController {
fwdBtn.getStyleClass().add("gray-button");
fwdBtn.setOnAction(
e -> {
if (engine.getHistory().getCurrentIndex()
< engine.getHistory().getEntries().size() - 1) {
int currentIndex = engine.getHistory().getCurrentIndex();
int lastIndex = engine.getHistory().getEntries().size() - 1;
if (currentIndex < lastIndex) {
engine.getHistory().go(1);
}
});
@@ -423,7 +430,7 @@ public class CasinoBrowserController {
Scene scene = new Scene(root, WINDOW_WIDTH, WINDOW_HEIGHT);
var css = CasinoBrowserController.class.getResource("/ui-structure/casinogameui.css");
var css = CasinoBrowserController.class.getResource("/ui-structure/Casinogameui.css");
if (css != null) {
scene.getStylesheets().add(css.toExternalForm());
@@ -512,10 +519,11 @@ public class CasinoBrowserController {
alert.setTitle("Unbekannte Website");
alert.setHeaderText("Diese Website ist nicht bekannt");
alert.setContentText(
String content =
host
+ "\n\nDiese Seite ist nicht vom "
+ "Casono Browser verifiziert.\nMöchten Sie sie trotzdem öffnen?");
+ "\n\nDiese Seite ist nicht vom Casono Browser verifiziert.\n"
+ "Möchten Sie sie trotzdem öffnen?";
alert.setContentText(content);
var stream = CasinoBrowserController.class.getResourceAsStream(LOGO_PATH);
Image logo = new Image(stream);
@@ -1,12 +1,14 @@
package ch.unibas.dmi.dbis.cs108.casono.client.ui.gameui.gameuicomponents;
import javafx.application.Platform;
import ch.unibas.dmi.dbis.cs108.casono.client.ui.lobbyui.Casinomainui;
import javafx.fxml.FXML;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.HBox;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/**
* Controller für die interaktive Taskleiste innerhalb der Poker-UI.
@@ -16,8 +18,12 @@ import javafx.scene.layout.HBox;
*/
public class TaskbarController {
private static final org.apache.logging.log4j.Logger LOGGER =
org.apache.logging.log4j.LogManager.getLogger(CasinoBrowserController.class);
/** Standardkonstruktor. Wird von FXML verwendet. */
public TaskbarController() {
// default constructor for FXML
}
private static final Logger LOGGER = LogManager.getLogger(CasinoBrowserController.class);
@FXML private HBox taskbar;
@FXML private TextField taskbarInput;
@@ -92,15 +98,21 @@ public class TaskbarController {
processBet();
}
/**
* Wird aufgerufen, wenn der Exit-Button in der Taskleiste gedrückt wird.
*
* <p>TODO: Logik implementieren, um zur Lobby zurückzukehren, ohne die gesamte Anwendung zu
* schließen (kein System.exit/Platform.exit).
*/
@FXML
private void onExitButtonClick() {
Platform.exit();
javafx.application.Platform.runLater(
() -> {
// Close game stage
javafx.stage.Stage currentStage =
(javafx.stage.Stage) taskbar.getScene().getWindow();
currentStage.close();
// Lobby-UI starten
try {
new Casinomainui().start(new javafx.stage.Stage());
} catch (Exception e) {
LOGGER.error("Fehler beim Starten der Lobby-UI: {}", e.getMessage());
}
});
}
/**
@@ -28,6 +28,7 @@ public class CasinomainuiController {
private LobbyButtonGridManager gridManager;
private int nextButtonId = 1;
/** Default constructor for dependency injection by FXMLLoader. */
public CasinomainuiController() {
// Default constructor
}
@@ -39,7 +40,7 @@ public class CasinomainuiController {
subtitleLabel.setText("Texas Hold'em Poker");
logoView.setImage(new Image(getClass().getResource("/images/logo.png").toExternalForm()));
translationManager = new LobbyButtonTranslationManager();
translationManager = LobbyButtonTranslationManager.getInstance();
gridManager =
new LobbyButtonGridManager(new javafx.scene.layout.GridPane(), translationManager);
casinoTable.getChildren().clear();
@@ -17,6 +17,8 @@ import org.apache.logging.log4j.Logger;
* ButtonID to LobbyID.
*/
public class LobbyButtonGridManager {
private static final double BUTTON_WIDTH_MARGIN = 20.0;
private static final double BUTTON_MIN_SIZE = 10.0;
private static final Logger LOGGER = LogManager.getLogger(LobbyButtonGridManager.class);
/** GridPane for the button grid. */
@@ -46,7 +48,8 @@ public class LobbyButtonGridManager {
public LobbyButtonGridManager(
GridPane gridPane, LobbyButtonTranslationManager translationManager) {
this.gridPane = gridPane;
this.translationManager = translationManager;
// Singleton immer verwenden
this.translationManager = LobbyButtonTranslationManager.getInstance();
}
/**
@@ -65,8 +68,21 @@ public class LobbyButtonGridManager {
int buttonId = entry.getKey();
Button btn = new Button();
btn.setId("lobbyBtn-" + buttonId);
btn.setGraphic(
new ImageView(new Image(getClass().getResourceAsStream(BUTTON_IMAGE_PATH))));
ImageView imageView =
new ImageView(new Image(getClass().getResourceAsStream(BUTTON_IMAGE_PATH)));
imageView.setPreserveRatio(true);
// Dynamische Breite: Bindung an die Zellengröße
imageView
.fitWidthProperty()
.bind(gridPane.widthProperty().divide(COLS).subtract(BUTTON_WIDTH_MARGIN));
imageView.setSmooth(true);
btn.setGraphic(imageView);
btn.setMaxWidth(Double.MAX_VALUE);
btn.setMaxHeight(Double.MAX_VALUE);
btn.setMinWidth(BUTTON_MIN_SIZE);
btn.setMinHeight(BUTTON_MIN_SIZE);
GridPane.setHgrow(btn, javafx.scene.layout.Priority.ALWAYS);
GridPane.setVgrow(btn, javafx.scene.layout.Priority.ALWAYS);
btn.setOnAction(
e -> {
Integer lobbyId = translationManager.getLobbyIdForButton(buttonId);
@@ -99,8 +115,22 @@ public class LobbyButtonGridManager {
* @param lobbyId The lobbyId to join
*/
public void joinLobby(int lobbyId) {
// TODO: Replace with actual join logic
// Game-UI starten und Lobby-UI schließen
LOGGER.info("Joining lobby: {}", lobbyId);
javafx.application.Platform.runLater(
() -> {
// Lobby-Stage schließen
javafx.stage.Stage currentStage =
(javafx.stage.Stage) gridPane.getScene().getWindow();
currentStage.close();
// Game-UI starten
try {
new ch.unibas.dmi.dbis.cs108.casono.client.ui.gameui.CasinoGameUI()
.start(new javafx.stage.Stage());
} catch (Exception e) {
LOGGER.error("Fehler beim Starten der Game-UI: {}", e.getMessage());
}
});
}
/**
@@ -8,14 +8,31 @@ import java.util.Map;
* nur Laufzeitdatenstruktur.
*/
public class LobbyButtonTranslationManager {
// Singleton-Instanz
private static LobbyButtonTranslationManager instance;
// Singleton-Zugriff
/**
* Liefert die Singleton-Instanz des Managers.
*
* @return die einzige Instanz von {@code LobbyButtonTranslationManager}
*/
public static LobbyButtonTranslationManager getInstance() {
if (instance == null) {
instance = new LobbyButtonTranslationManager();
}
return instance;
}
/** Maximale Anzahl an Buttons/Lobbys */
private static final int MAX_BUTTONS = 8;
/** Zuordnung ButtonID → LobbyID */
private final Map<Integer, Integer> buttonIdToLobbyId = new HashMap<>();
/** Konstruktor: initialisiert die Zuordnung leer. */
public LobbyButtonTranslationManager() {
/** Privater Konstruktor für Singleton-Pattern */
private LobbyButtonTranslationManager() {
// Zuordnung bleibt leer beim Start
}
@@ -5,12 +5,12 @@
<?import javafx.geometry.Insets?>
<?import javafx.scene.image.*?>
<!-- Hauptcontainer: Verknüpft die UI mit dem CasinoGameController und lädt casinogameui.css -->
<!-- Hauptcontainer: Verknüpft die UI mit dem CasinoGameController und lädt Casinogameui.css -->
<AnchorPane xmlns="http://javafx.com/javafx/21"
xmlns:fx="http://javafx.com/fxml/1"
fx:controller="ch.unibas.dmi.dbis.cs108.casono.client.ui.gameui.CasinoGameController"
styleClass="background"
stylesheets="@casinogameui.css">
stylesheets="@Casinogameui.css">
<GridPane prefWidth="1200" prefHeight="800" AnchorPane.topAnchor="0" AnchorPane.bottomAnchor="0" AnchorPane.leftAnchor="0" AnchorPane.rightAnchor="0">
<columnConstraints>
@@ -78,14 +78,14 @@
</VBox>
<!-- TODO: Platzhalter: Chat-Box in Spalte 2: -->
<fx:include source="components/chatbox.fxml" GridPane.columnIndex="2"/>
<fx:include source="components/Chatbox.fxml" GridPane.columnIndex="2"/>
</children>
</GridPane>
<!-- verschiebbare Taskbar -->
<AnchorPane>
<fx:include fx:id="taskbarInclude" source="gameuicomponents/taskbar.fxml"/>
<fx:include fx:id="taskbarInclude" source="gameuicomponents/Taskbar.fxml"/>
</AnchorPane>
<!-- Gegner-Status 1: Eines von drei Panels, das Icon, Name und Kontostand des Mitspielers anzeigt -->
@@ -99,7 +99,7 @@
</columnConstraints>
<children>
<fx:include source="gameuicomponents/playerstatus.fxml" GridPane.columnIndex="1"/>
<fx:include source="gameuicomponents/Playerstatus.fxml" GridPane.columnIndex="1"/>
</children>
</GridPane>
@@ -114,7 +114,7 @@
</columnConstraints>
<children>
<fx:include source="gameuicomponents/playerstatus.fxml" GridPane.columnIndex="1"/>
<fx:include source="gameuicomponents/Playerstatus.fxml" GridPane.columnIndex="1"/>
</children>
</GridPane>
@@ -129,7 +129,7 @@
</columnConstraints>
<children>
<fx:include source="gameuicomponents/playerstatus.fxml" GridPane.columnIndex="1"/>
<fx:include source="gameuicomponents/Playerstatus.fxml" GridPane.columnIndex="1"/>
</children>
</GridPane>
</AnchorPane>
@@ -106,20 +106,7 @@
</VBox>
<!-- RECHTER BEREICH (Info-Box) -->
<VBox GridPane.columnIndex="2" alignment="CENTER">
<padding>
<Insets top="30" right="30" bottom="30" left="10"/>
</padding>
<VBox VBox.vgrow="ALWAYS" styleClass="floating-chat-box" spacing="10" maxWidth="Infinity">
<Label text="== INFO ==" styleClass="chat-header" alignment="CENTER" maxWidth="Infinity"/>
<Region minHeight="4" style="-fx-background-color: #ffffff;" />
<VBox spacing="15" VBox.vgrow="ALWAYS" styleClass="info-content">
<Label text="> CREDITS: 1000" styleClass="info-text"/>
<Label text="> JACKPOT: 9999" styleClass="info-text"/>
<Label text="> SYSTEM: OK" styleClass="info-text"/>
</VBox>
</VBox>
</VBox>
<fx:include source="components/Chatbox.fxml" GridPane.columnIndex="2"/>
</children>
</GridPane>
</AnchorPane>
@@ -21,7 +21,7 @@
xmlns:fx="http://javafx.com/fxml/1"
fx:controller="ch.unibas.dmi.dbis.cs108.casono.client.ui.chatui.ChatController"
alignment="CENTER"
stylesheets="@chatui.css">
stylesheets="@Chatui.css">
<!-- Innenabstand: Schafft oben, rechts und unten 30 Pixel Platz, links nur 10 Pixel (asymmetrisch) -->
<padding>
@@ -13,7 +13,7 @@ class LobbyButtonGridManagerTest {
@BeforeEach
void setUp() {
gridPane = new GridPane();
translationManager = new LobbyButtonTranslationManager();
translationManager = LobbyButtonTranslationManager.getInstance();
translationManager.getButtonIdToLobbyId().clear();
gridManager = new LobbyButtonGridManager(gridPane, translationManager);
}
@@ -23,10 +23,4 @@ class LobbyButtonGridManagerTest {
int lobbyId = gridManager.createLobby();
assertTrue(lobbyId > 0);
}
@Test
void testJoinLobbyPlaceholder() {
// check if exception is thrown
assertDoesNotThrow(() -> gridManager.joinLobby(123));
}
}
@@ -6,11 +6,12 @@ import java.util.Map;
import org.junit.jupiter.api.*;
class LobbyButtonTranslationManagerTest {
LobbyButtonTranslationManager manager;
@BeforeEach
void setUp() {
manager = new LobbyButtonTranslationManager();
manager = LobbyButtonTranslationManager.getInstance();
manager.getButtonIdToLobbyId().clear();
}