Feat/gameui #244

Merged
j.kropff merged 5 commits from feat/gameui into main 2026-04-09 10:57:24 +02:00
10 changed files with 184 additions and 186 deletions
@@ -5,17 +5,17 @@ import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
/**
* Controller für die Casino-Spielfläche.
* Controller for the casino gaming area.
*
* <p>Verantwortlich für: - die Darstellung des Pokertisches und der Spieleroberfläche, - die
* Verarbeitung von Benutzereingaben, - die Schnittstelle zur GameEngine und zum Netzwerkprotokoll.
* <p>Responsible for: - the display of the poker table and the player interface, - the processing
* of user input, - the interface to the game engine and the network protocol.
*
* <p>Hinweise: - Die Methode `onTableClick()` dient aktuell nur als Test-Logik. Sie ist ggf. nicht
* mehr funktionsfähig und wird zukünftig durch die finale Spielinteraktion ersetzt.
* <p>Notes: - The `onTableClick()` method currently serves only as test logic. It may no longer be
* functional and will be replaced by the final game interaction in the future.
*/
public class CasinoGameController {
/** Standardkonstruktor. Wird von FXML verwendet. */
/** Standard constructor. Used by FXML. */
public CasinoGameController() {
// default constructor for FXML
}
@@ -23,13 +23,13 @@ public class CasinoGameController {
@FXML private Label welcomeText;
@FXML private VBox casinoTable;
// TODO: Test-Logik: wird durch echte Spielinteraktionen ersetzt,
// sobald die GameEngine fertig ist
// TODO: Test logic: will be replaced by real game interactions,
// once the game engine is finished
/**
* Temporäre Test-Methode, die bei Klick auf den Tisch eine Platzhalteraktion ausführt.
* Temporary test method that performs a placeholder action when the table is clicked.
*
* <p>Wird in der finalen Implementierung durch die Spiel-Logik ersetzt.
* <p>In the final implementation, this will be replaced by the game logic.
*/
@FXML
public void onTableClick() {
@@ -7,17 +7,17 @@ import javafx.scene.Scene;
import javafx.stage.Stage;
/**
* Hauptklasse für das Casino-Spiel-UI.
* Main class for the Casono Game UI.
*
* <p>Startet die JavaFX-Anwendung, lädt die grafische Oberfläche aus der FXML-Datei und
* initialisiert die Haupt-Stage für das Spiel.
* <p>Starts the JavaFX application, loads the graphical user interface from the FXML file, and
* initializes the main stage for the game.
*
* <p>Aufgaben: - Lädt die FXML-Oberfläche "/ui-structure/Casinogameui.fxml". - Lädt das
* Anwendungs-Icon aus "/images/logoinverted.png". - Startet die Anwendung im Vollbildmodus.
* <p>Tasks: - Loads the FXML interface "/ui-structure/Casinogameui.fxml". - Loads the application
* icon from "/images/logoinverted.png". - Starts the application in full-screen mode.
*/
public class CasinoGameUI extends Application {
/** Standardkonstruktor. */
/** default constructor */
public CasinoGameUI() {
// default no-arg constructor
}
@@ -26,10 +26,10 @@ public class CasinoGameUI extends Application {
private static final int DEFAULT_HEIGHT = 800;
/**
* Startet die Haupt-Stage der Anwendung.
* Starts the main stage of the application.
*
* @param stage Die vom System bereitgestellte Haupt-Stage.
* @throws IOException Wenn die FXML-Datei oder Ressourcen nicht geladen werden können.
* @param stage The main stage provided by the system.
* @throws IOException If the FXML file or resources cannot be loaded.
*/
@Override
public void start(Stage stage) throws IOException {
@@ -46,9 +46,9 @@ public class CasinoGameUI extends Application {
}
/**
* Startpunkt der Anwendung.
* Starting point of the application.
*
* @param args Befehlszeilenargumente.
* @param args Command line arguments.
*/
public static void main(String[] args) {
launch();
@@ -31,28 +31,27 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/**
* Experimenteller integrierter Browser für Casono.
* Experimental embedded browser for Casono.
*
* <p>Diese Klasse implementiert einen einfachen eingebetteten Webbrowser auf Basis von {@link
* javafx.scene.web.WebView}. Der Browser dient primär als Hilfswerkzeug innerhalb des Spiels, um
* externe Inhalte wie Webseiten oder Videos anzuzeigen.
* <p>This class implements a simple embedded web browser based on {@link javafx.scene.web.WebView}.
* The browser primarily serves as a utility within the game to display external content such as web
* pages or videos.
*
* <p>Status Der Browser befindet sich derzeit in einer experimentellen Phase. Einige
* Sicherheitsmechanismen basieren auf experimentellen KI-gestützten Empfehlungen und können sich in
* zukünftigen Versionen noch ändern.
* <p>Status The browser is currently in an experimental phase. Some security mechanisms are based
* on experimental AI-driven recommendations and may change in future versions.
*
* <p>Zweck Der Browser wird aktuell experimentell genutzt, um: Pokerregeln direkt im Spiel zu
* erklären Hilfeseiten oder Dokumentationen anzuzeigen Videos (z.B. Tutorials oder Erklärungen)
* über Plattformen wie YouTube abzuspielen
* <p>Purpose The browser is currently being used experimentally to: Explain poker rules directly
* within the game Display help pages or documentation Play videos (e.g., tutorials or explanations)
* via platforms such as YouTube
*
* <p>Sicherheitsmechanismen Da externe Webseiten geladen werden können, wurden einige grundlegende
* Schutzmaßnahmen integriert: - HTTPS-Zwang für Webseiten - Whitelist für bekannte Domains -
* Warnung bei unbekannten Webseiten - JavaScript standardmäßig deaktiviert (man kann es jedoch für
* Google etc. einschalten) - Popup-Blocker - Automatische Cookie-Löschung beim Schließen
* <p>Security Mechanisms Since external websites can be loaded, some basic protective measures have
* been integrated: - Mandatory HTTPS for websites - Whitelist for known domains - Warning for
* unknown websites - JavaScript disabled by default (but can be enabled for Google, etc.) - Pop-up
* blocker - Automatic cookie deletion upon closing
*/
public class CasinoBrowserController {
/** Standardkonstruktor. Initialisiert den CasinoBrowserController. */
/** Default constructor. Initializes the CasinoBrowserController. */
public CasinoBrowserController() {
// Intentionally left blank; controller initialization is FXML-driven.
}
@@ -101,7 +100,7 @@ public class CasinoBrowserController {
private static boolean javascriptEnabled = false;
/** Löscht alle gespeicherten Cookies der aktuellen Browser-Sitzung. */
/** Deletes all cookies stored during the current browser session. */
private static void clearCookies() {
try {
COOKIE_MANAGER.getCookieStore().removeAll();
@@ -110,12 +109,12 @@ public class CasinoBrowserController {
}
/**
* Öffnet ein neues Browserfenster und lädt eine angegebene Webseite.
* Opens a new browser window and loads a specified webpage.
*
* <p>Falls die Webseite nicht zur Liste vertrauenswürdiger Domains gehört, wird der Benutzer
* gefragt, ob die Seite dennoch geladen werden soll.
* <p>If the webpage is not on the list of trusted domains, the user will be asked whether the
* page should be loaded anyway.
*
* @param url die Startadresse der Webseite, die geladen werden soll
* @param url the URL of the webpage to be loaded
*/
public static void open(String url) {
Platform.runLater(
@@ -182,10 +181,10 @@ public class CasinoBrowserController {
}
/**
* WebView Container
* WebView container
*
* @param webView WebView Inhalt
* @return StackPane Container
* @param webView WebView content
* @return StackPane container
*/
public static StackPane createWebContainer(WebView webView) {
StackPane webContainer = new StackPane(webView);
@@ -198,7 +197,7 @@ public class CasinoBrowserController {
/**
* Popup Blocker
*
* @param engine WebEngine nutzen
* @param engine Use WebEngine
*/
public static void configurePopupBlocker(WebEngine engine) {
engine.setCreatePopupHandler(
@@ -212,8 +211,8 @@ public class CasinoBrowserController {
var stream = CasinoBrowserController.class.getResourceAsStream(LOGO_PATH);
Image logo = new Image(stream);
// Variable 'streamM' abgekürzt, um das 100-Zeichen-Limit (LineLength)
// einzuhalten
// Variable streamM abbreviated to comply with the 100-character
// limit (LineLength)
var streamM =
CasinoBrowserController.class.getResourceAsStream(LOGO_PATH_MAIN);
Image logomain = new Image(streamM);
@@ -232,7 +231,7 @@ public class CasinoBrowserController {
alert.setGraphic(logoView);
}
} catch (Exception e) {
LOGGER.error("Logo konnte nicht geladen werden");
LOGGER.error("The logo could not be loaded");
}
alert.showAndWait();
@@ -241,9 +240,9 @@ public class CasinoBrowserController {
}
/**
* Logos laden
* Load logos
*
* @param stage Fenster Stage
* @param stage Window Stage
* @return ImageView Logo
*/
private static ImageView loadLogos(Stage stage) {
@@ -253,8 +252,7 @@ public class CasinoBrowserController {
var stream = CasinoBrowserController.class.getResourceAsStream(LOGO_PATH);
Image logo = new Image(stream);
// Variable 'streamM' abgekürzt, um das 100-Zeichen-Limit (LineLength)
// einzuhalten
// Variable streamM abbreviated to comply with the 100-character limit (LineLength)
var streamM = CasinoBrowserController.class.getResourceAsStream(LOGO_PATH_MAIN);
Image logomain = new Image(streamM);
@@ -268,17 +266,17 @@ public class CasinoBrowserController {
browserLogo.setPreserveRatio(true);
}
} catch (Exception e) {
LOGGER.error("Logo konnte nicht geladen werden");
LOGGER.error("The logo could not be loaded");
}
return browserLogo;
}
/**
* URL Feld
* URL field
*
* @param url Start URL
* @return TextField Eingabe
* @return TextField input
*/
public static TextField createUrlField(String url) {
TextField urlField = new TextField(url);
@@ -289,12 +287,12 @@ public class CasinoBrowserController {
}
/**
* Sicherheits Label
* Security Label
*
* @return Label Anzeige
* @return Label display
*/
public static Label createSecurityLabel() {
Label securityLabel = new Label("SICHER");
Label securityLabel = new Label("SAFE");
securityLabel.getStyleClass().add("security-label");
return securityLabel;
@@ -303,8 +301,8 @@ public class CasinoBrowserController {
/**
* JS Toggle
*
* @param engine WebEngine nutzen
* @return Button Umschalten
* @param engine Use WebEngine
* @return Toggle button
*/
public static Button createJsToggle(WebEngine engine) {
Button jsToggle = new Button("JS EINSCHALTEN");
@@ -316,7 +314,7 @@ public class CasinoBrowserController {
engine.setJavaScriptEnabled(javascriptEnabled);
if (javascriptEnabled) {
jsToggle.setText("JS AUSSCHALTEN");
jsToggle.setText("JS TURN OFF");
jsToggle.getStyleClass().removeAll("red-button");
jsToggle.getStyleClass().add("yellow-button");
@@ -331,10 +329,10 @@ public class CasinoBrowserController {
}
/**
* Zurück Button
* Back Button
*
* @param engine WebEngine nutzen
* @return Button Zurück
* @param engine Use WebEngine
* @return Back button
*/
public static Button createBackButton(WebEngine engine) {
Button backBtn = new Button("<");
@@ -350,10 +348,10 @@ public class CasinoBrowserController {
}
/**
* Vorwärts Button
* Forward Button
*
* @param engine WebEngine nutzen
* @return Button Vorwärts
* @param engine Use WebEngine
* @return Forward button
*/
public static Button createForwardButton(WebEngine engine) {
Button fwdBtn = new Button(">");
@@ -373,8 +371,8 @@ public class CasinoBrowserController {
/**
* Reload Button
*
* @param engine WebEngine nutzen
* @return Button Reload
* @param engine Use WebEngine
* @return Reload button
*/
public static Button createReloadButton(WebEngine engine) {
Button reloadBtn = new Button("");
@@ -386,9 +384,9 @@ public class CasinoBrowserController {
/**
* Close Button
*
* @param stage Fenster Stage
* @param webView WebView Inhalt
* @return Button Schließen
* @param stage Window stage
* @param webView WebView content
* @return Close button
*/
public static Button createCloseButton(Stage stage, WebView webView) {
Button closeBtn = new Button("X");
@@ -406,9 +404,9 @@ public class CasinoBrowserController {
/**
* URL Events
*
* @param engine WebEngine nutzen
* @param urlField URL Textfeld
* @param securityLabel Sicherheits Label
* @param engine Use WebEngine
* @param urlField URL text field
* @param securityLabel Security label
*/
public static void configureUrlEvents(
WebEngine engine, TextField urlField, Label securityLabel) {
@@ -417,11 +415,11 @@ public class CasinoBrowserController {
}
/**
* Scene erstellen
* Create a scene
*
* @param taskbar Taskbar HBox
* @param webContainer Web Container
* @return Scene Fenster
* @param webContainer Web container
* @return Scene window
*/
public static Scene createScene(HBox taskbar, StackPane webContainer) {
VBox root = new VBox(VBOX_SPACING, taskbar, webContainer);
@@ -442,8 +440,8 @@ public class CasinoBrowserController {
/**
* Key Events
*
* @param scene Scene Fenster
* @param engine WebEngine nutzen
* @param scene Scene window
* @param engine Use WebEngine
*/
public static void configureKeyEvents(Scene scene, WebEngine engine) {
scene.setOnKeyPressed(
@@ -455,18 +453,18 @@ public class CasinoBrowserController {
}
/**
* Lädt eine URL in den Browser, nachdem grundlegende Sicherheitsprüfungen durchgeführt wurden.
* Loads a URL in the browser after performing basic security checks.
*
* <p>Vor dem Laden einer Seite werden folgende Prüfungen durchgeführt: - Überprüfung des
* Protokolls (nur HTTPS erlaubt) - Überprüfung der Domain gegen eine Whitelist - Schutz vor
* Domain-Spoofing (Domain-Vortäuschung)
* <p>Before loading a page, the following checks are performed: - Verification of the protocol
* (only HTTPS allowed) - Verification of the domain against a whitelist - Protection against
* domain spoofing
*
* <p>Falls eine Domain nicht als vertrauenswürdig eingestuft wird, muss der Benutzer
* bestätigen, dass die Seite dennoch geöffnet werden darf.
* <p>If a domain is not classified as trustworthy, the user must confirm that the page may
* still be opened.
*
* @param engine der WebEngine-Renderer des Browsers
* @param url die zu ladende Webadresse
* @param securityLabel Label zur Anzeige des aktuellen Sicherheitsstatus
* @param engine the browser's WebEngine renderer
* @param url the web address to be loaded
* @param securityLabel label for displaying the current security status
*/
private static void loadUrlSafely(WebEngine engine, String url, Label securityLabel) {
try {
@@ -476,9 +474,9 @@ public class CasinoBrowserController {
URI uri = new URI(url);
// HTTPS Pflicht
// HTTPS required
if (!"https".equalsIgnoreCase(uri.getScheme())) {
securityLabel.setText("BLOCKIERT");
securityLabel.setText("BLOCKED");
return;
}
@@ -488,19 +486,19 @@ public class CasinoBrowserController {
return;
}
// Sicherer Domain Check
// Secure Domain Check
boolean trusted =
TRUSTED_DOMAINS.stream()
.anyMatch(domain -> host.equals(domain) || host.endsWith("." + domain));
if (!trusted) {
if (!showUnknownWebsiteAlert(host)) {
securityLabel.setText("BLOCKIERT");
securityLabel.setText("BLOCKED");
return;
}
securityLabel.setText("UNBEKANNT");
} else {
securityLabel.setText("SICHER");
securityLabel.setText("SAFE");
}
engine.load(uri.toString());
} catch (Exception e) {
@@ -509,20 +507,20 @@ public class CasinoBrowserController {
}
/**
* Zeigt Warnung an.
* Displays a warning.
*
* @param host Website Host
* @return OK gedrückt
* @param host Website host
* @return OK pressed
*/
private static boolean showUnknownWebsiteAlert(String host) {
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
alert.setTitle("Unbekannte Website");
alert.setHeaderText("Diese Website ist nicht bekannt");
alert.setTitle("Unknown website");
alert.setHeaderText("This website is unknown");
String content =
host
+ "\n\nDiese Seite ist nicht vom Casono Browser verifiziert.\n"
+ "Möchten Sie sie trotzdem öffnen?";
+ "\n\nThis site has not been verified by the Casono browser.\n"
+ "Do you still want to open it?";
alert.setContentText(content);
var stream = CasinoBrowserController.class.getResourceAsStream(LOGO_PATH);
@@ -11,14 +11,14 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/**
* Controller für die interaktive Taskleiste innerhalb der Poker-UI.
* Controller for the interactive taskbar within the poker UI.
*
* <p>Verantwortlich für: - Drag-and-Drop-Verschieben der Taskleiste, - Eingabe und Verwaltung von
* Spieleinsätzen, - Steuerung allgemeiner Menüfunktionen wie Exit.
* <p>Responsible for: - Drag-and-drop movement of the taskbar, - Input and management of game
* stakes, - Control of general menu functions such as Exit.
*/
public class TaskbarController {
/** Standardkonstruktor. Wird von FXML verwendet. */
/** Standard constructor. Used by FXML. */
public TaskbarController() {
// default constructor for FXML
}
@@ -36,10 +36,10 @@ public class TaskbarController {
private static final int CREDIT_STEP = 5;
/**
* Wird aufgerufen, wenn die Taskleiste mit der Maus gedrückt wird. Speichert die relative
* Position, um später korrekt zu verschieben.
* Called when the taskbar is clicked with the mouse. Saves the relative position for later,
* correct repositioning.
*
* @param event Das Mausereignis
* @param event The mouse event
*/
@FXML
private void onTaskbarPressed(MouseEvent event) {
@@ -48,11 +48,10 @@ public class TaskbarController {
}
/**
* Wird aufgerufen, während die Taskleiste mit der Maus gezogen wird. Aktualisiert die Position
* und skaliert die Taskleiste leicht zur visuellen Rückmeldung.
* Called while dragging the taskbar with the mouse. Updates the position and slightly scales
* the taskbar for visual feedback.
*
* <p>TODO: Es muss noch gefixt werden, dass die Taskleiste nicht aus dem Fenster verschwinden
* kann.
* <p>TODO: It still needs to be fixed that the taskbar cannot disappear out of the window.
*
* @param event Das Mausereignis
*/
@@ -66,10 +65,10 @@ public class TaskbarController {
}
/**
* Wird aufgerufen, wenn die Maus über der Taskleiste losgelassen wird. Setzt die Skalierung der
* Taskleiste wieder auf Normalgröße.
* Called when the mouse cursor is released over the taskbar. Resets the taskbar scaling to
* normal size.
*
* @param event Das Mausereignis
* @param event The mouse event
*/
@FXML
private void onTaskbarReleased(MouseEvent event) {
@@ -78,9 +77,9 @@ public class TaskbarController {
}
/**
* Wird aufgerufen, wenn im Textfeld die Enter-Taste gedrückt wird.
* Called up when the Enter key is pressed in the text field.
*
* @param event Das Tastaturereignis
* @param event The keyboard event
*/
@FXML
private void onInputSubmitted(KeyEvent event) {
@@ -90,8 +89,8 @@ public class TaskbarController {
}
/**
* Wird aufgerufen, wenn der Submit-Button in der Taskleiste gedrückt wird. Löst die
* Verarbeitung des Einsatzes aus.
* Called when the submit button in the taskbar is pressed. Triggers the processing of the
* deployment.
*/
@FXML
private void onInputSubmittedAction() {
@@ -106,7 +105,7 @@ public class TaskbarController {
javafx.stage.Stage currentStage =
(javafx.stage.Stage) taskbar.getScene().getWindow();
currentStage.close();
// Lobby-UI starten
// Start lobby UI
try {
new Casinomainui().start(new javafx.stage.Stage());
} catch (Exception e) {
@@ -116,9 +115,9 @@ public class TaskbarController {
}
/**
* Verarbeitet den im Textfeld eingegebenen Einsatz. Es werden ausschließlich ganzzahlige Werte
* im Bereich von 5 bis 100.000 Credits akzeptiert, die einem Vielfachen von 5 entsprechen
* (5er-Schritte). Der Einsatz wird aktuell nur auf der Konsole ausgegeben.
* Processes the stake entered in the text field. Only integer values between 5 and 100,000
* credits are accepted, in multiples of 5 (in increments of 5). The stake is currently only
* displayed on the console.
*/
private void processBet() {
String input = taskbarInput.getText();
@@ -126,22 +125,22 @@ public class TaskbarController {
int credits = Integer.parseInt(input.trim());
if (credits >= MIN_CREDITS && credits <= MAX_CREDITS && credits % CREDIT_STEP == 0) {
// TODO: Credits müssen an die GameEngine gesendet werden
LOGGER.info("Einsatz gesetzt: {} Casono Credits", credits);
// TODO: Credits must be sent to the GameEngine
LOGGER.info("Bet set: {} Casono Credits", credits);
taskbarInput.clear();
} else {
LOGGER.info("Fehler: Nur 5er-Schritte (5, 10, ... 100.000) erlaubt!");
LOGGER.error("Error: Only increments of 5 (5, 10, ... 100,000) are allowed!");
}
} catch (NumberFormatException e) {
LOGGER.info("Fehler: Bitte nur eine Zahl eingeben!");
LOGGER.error("Error: Please enter only one number!");
}
}
/**
* Öffnet den integrierten Casono Webbrowser.
* Opens the integrated Casono web browser.
*
* <p>TODO: Ersetze die Start-URL durch die offizielle Projekt-Website (z.B. Tipps & Tricks
* Seite), sobald die Inhalte für Strategien und Support bereitstehen.
* <p>TODO: Replace the start URL with the official project website (e.g., Tips & Tricks page)
* once the content for strategies and support is available.
*/
@FXML
private void onBrowserButtonClick() {
@@ -51,8 +51,8 @@ public class Deck {
}
/**
* Sets the cards of the deck. This method replaces the internal list
* with a copy of the provided list.
* Sets the cards of the deck. This method replaces the internal list with a copy of the
* provided list.
*
* @param cards the new list of cards to set
*/
@@ -1,12 +1,12 @@
.root {
-fx-background-color: #000000;
-fx-font-family: "Monospaced", "Courier New"; /* Schriftart */
-fx-font-family: "Monospaced", "Courier New"; /* font */
}
.background {
-fx-background-image: url("/images/background.png");
-fx-background-size: cover; /* Bild füllt das ganze Fenster aus */
/* Zentriert das Bild und verhindert, dass es sich kachelartig wiederholt */
-fx-background-size: cover; /* Image fills the entire window */
/* Centers the image and prevents it from repeating in a tile-like pattern. */
-fx-background-position: center center;
-fx-background-repeat: no-repeat;
}
@@ -181,20 +181,20 @@
.status-label-small {
-fx-text-fill: #ffffff;
-fx-font-family: "Monospaced"; /* Schriftart */
-fx-font-family: "Monospaced"; /* font */
-fx-font-size: 15px;
}
.status-value-text {
-fx-text-fill: #ffffff;
-fx-font-family: "Monospaced"; /* Schriftart */
-fx-font-family: "Monospaced"; /* font */
-fx-font-size: 15px;
-fx-font-weight: bold;
}
.status-value-money {
-fx-text-fill: #ffffff;
-fx-font-family: "Monospaced"; /* Schriftart */
-fx-font-family: "Monospaced"; /* font */
-fx-font-size: 15px;
-fx-font-weight: bold;
}
@@ -5,7 +5,7 @@
<?import javafx.geometry.Insets?>
<?import javafx.scene.image.*?>
<!-- Hauptcontainer: Verknüpft die UI mit dem CasinoGameController und lädt Casinogameui.css -->
<!-- Main container: Links the UI to the CasinoGameController and loads 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"
@@ -14,28 +14,28 @@
<GridPane prefWidth="1200" prefHeight="800" AnchorPane.topAnchor="0" AnchorPane.bottomAnchor="0" AnchorPane.leftAnchor="0" AnchorPane.rightAnchor="0">
<columnConstraints>
<!-- Tisch-Box: 70% -->
<!-- Table-Box: 70% -->
<ColumnConstraints percentWidth="70.0" hgrow="ALWAYS" />
<!-- Leere-Box: 5% -->
<!-- Table-Box: 5% -->
<ColumnConstraints percentWidth="5.0" hgrow="ALWAYS" />
<!-- Chat-Box: 20% -->
<!-- Table-Box: 20% -->
<ColumnConstraints percentWidth="25.0" hgrow="ALWAYS" />
</columnConstraints>
<!-- Sorgt dafür, dass diese Zeile den gesamten verfügbaren vertikalen Platz nutzt -->
<!-- Ensures that this line uses all available vertical space -->
<rowConstraints>
<RowConstraints vgrow="ALWAYS" />
</rowConstraints>
<children>
<!-- Tisch-Box in Spalte 0 -->
<!-- Table box in column 0 -->
<StackPane GridPane.columnIndex="0">
<!-- Innenabstand: Hält den Inhalt 10 Pixel von oben/unten und 20 Pixel von den Seiten fern -->
<!-- Inner spacing: Keeps the content 10 pixels away from the top/bottom and 20 pixels from the sides -->
<padding>
<Insets top="20" right="10" bottom="120" left="20"/>
</padding>
<!-- Zentraler Casinotisch: Zentriert den Inhalt und nutzt durch die maximale Größe (1.7976931348623157E308) das gesamte Fenster -->
<!-- Central Casino Table: Centers the content and utilizes the entire window due to its maximum size (1.7976931348623157E308) -->
<VBox fx:id="casinoTable"
alignment="CENTER"
styleClass="casino-table"
@@ -44,7 +44,7 @@
maxWidth="Infinity"
maxHeight="Infinity">
<!-- TODO: Platzhalter für die Poker-Spielfläche: Hier werden später dynamisch Karten, Chips und Einsätze der Gegner angezeigt -->
<!-- TODO: Placeholder for the poker playing area: Cards, chips and opponents' bets will be dynamically displayed here later -->
<HBox alignment="CENTER" spacing="15">
<VBox styleClass="dealer-box" prefWidth="80" prefHeight="120" />
<VBox styleClass="dealer-box" prefWidth="80" prefHeight="120" />
@@ -52,7 +52,7 @@
</HBox>
<VBox alignment="CENTER" spacing="10">
<!-- Label mit Logo -->
<!-- Label with logo -->
<Label text="CAS0NO" styleClass="table-title">
<graphic>
<ImageView fitHeight="30.0" preserveRatio="true">
@@ -63,32 +63,32 @@
</graphic>
</Label>
<!-- TODO: Platzhalter: Wird ersetzt, sobald die GameEngine fertig ist und echte Einsätze verarbeiten kann -->
<!-- TODO: Placeholder: Will be replaced once the game engine is finished and can process real-world scenarios -->
<Label fx:id="welcomeText" text="Setzen Sie Ihren Einsatz" styleClass="table-title" />
</VBox>
</VBox>
</StackPane>
<!-- Leere-Box in Spalte 1: Schafft Platz zwischen dem Tisch-Box und der Chat-Box -->
<!-- Empty box in column 1: Creates space between the table box and the chat box -->
<VBox GridPane.columnIndex="1"
alignment="CENTER"
minWidth="100"
minHeight="100">
<!-- Bleibt leer -->
<!-- Leave blank -->
</VBox>
<!-- TODO: Platzhalter: Chat-Box in Spalte 2: -->
<!-- TODO: Placeholder: Chat box in column 2: -->
<fx:include source="components/Chatbox.fxml" GridPane.columnIndex="2"/>
</children>
</GridPane>
<!-- verschiebbare Taskbar -->
<!-- movable taskbar -->
<AnchorPane>
<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 -->
<!-- Opponent Status 1: One of three panels displaying the opponent's icon, name, and account balance -->
<GridPane AnchorPane.leftAnchor="0.0"
AnchorPane.rightAnchor="0.0"
AnchorPane.topAnchor="50">
@@ -103,7 +103,7 @@
</children>
</GridPane>
<!-- Gegner-Status 2: Eines von drei Panels, das Icon, Name und Kontostand des Mitspielers anzeigt -->
<!-- Opponent Status 2: One of three panels displaying the opponent's icon, name, and account balance -->
<GridPane AnchorPane.leftAnchor="0.0"
AnchorPane.rightAnchor="0.0"
AnchorPane.topAnchor="20">
@@ -118,7 +118,7 @@
</children>
</GridPane>
<!-- Gegner-Status 3: Eines von drei Panels, das Icon, Name und Kontostand des Mitspielers anzeigt -->
<!-- Opponent Status 3: One of three panels that displays the opponent's icon, name, and account balance -->
<GridPane AnchorPane.leftAnchor="0.0"
AnchorPane.rightAnchor="0.0"
AnchorPane.topAnchor="50">
@@ -5,16 +5,16 @@
<?import javafx.geometry.Insets?>
<!--
Dieses Fenster wird später mit den Serveranfragen verknüpft,
um Nachrichten von Mitspielern und Systemmeldungen in Echtzeit anzuzeigen.
This window will later be linked to the server requests,
to display messages from other players and system messages in real time.
Der Chat unterscheidet intern zwischen:
- Player-to-Player (Privater 2-Personen-Chat)
- Lobby-Chat (Aktueller Raum)
- Globaler Chat (Gesamter Server)
The chat internally distinguishes between:
- Player-to-Player (Private 2-person chat)
- Lobby Chat (Current room)
- Global Chat (Entire server)
Features, die später implementiert werden sollen:
- Schicke Chat-Bubbles mit Namen und Uhrzeit.
Features planned for later implementation:
- Stylish chat bubbles with names and timestamps.
-->
<VBox xmlns="http://javafx.com/javafx/21"
@@ -23,7 +23,7 @@
alignment="CENTER"
stylesheets="@Chatui.css">
<!-- Innenabstand: Schafft oben, rechts und unten 30 Pixel Platz, links nur 10 Pixel (asymmetrisch) -->
<!-- Inner spacing: Creates 30 pixels of space at the top, right and bottom, only 10 pixels on the left (asymmetrical) -->
<padding>
<Insets top="30" right="30" bottom="30" left="10"/>
</padding>
@@ -38,16 +38,16 @@
<Label text="== CHAT ==" styleClass="chat-header" alignment="CENTER" maxWidth="Infinity"/>
<Region minHeight="4" styleClass="chat-separator"/>
<!-- Chatnachrichten werden hier hinzugefügt -->
<!-- Chat messages will be added here -->
<ScrollPane fx:id="chatScrollPane" fitToWidth="true" vbarPolicy="AS_NEEDED" hbarPolicy="NEVER" VBox.vgrow="ALWAYS" styleClass="chat-scroll-pane">
<content>
<VBox fx:id="chatVBox" spacing="10" styleClass="chat-VBox"/>
</content>
</ScrollPane>
<!-- Eingabebereich -->
<!-- Input area -->
<HBox spacing="10">
<!-- TODO: Größe des TextFields dynamisch anpassen -->
<!-- TODO: Dynamically adjust the size of the text field -->
<TextField fx:id="inputField" HBox.hgrow="ALWAYS" promptText="Nachricht eingeben..." styleClass="gray-input-field" onAction="#sendMessage"/>
<Button fx:id="sendButton" text="SENDEN" onAction="#sendMessage" styleClass="yellow-button"/>
</HBox>
@@ -5,10 +5,11 @@
<?import javafx.geometry.Insets?>
<!--
TODO: Haupt-platzhalter für spieler-status & eingabe.
Dieses Layout dient aktuell der visuellen Struktur. Sobald die GameEngine und
Serveranfragen (API/Requests) durchgeführt werden können, werden Name, Kontostand
und Status-Anzeigen dynamisch mit Echtzeit-Daten vom Server befüllt.
TODO: Main placeholder for player status & input.
This layout currently serves as a visual structure. As soon as the game engine and
server requests (API/requests) can be processed, the name, account balance
and status displays will be dynamically populated with real-time data from the server.
-->
<VBox fx:id="playerStatusBox"
@@ -20,7 +21,7 @@
spacing="0">
<children>
<!-- Bereich für den Spielernamen -->
<!-- Area for player name -->
<HBox styleClass="status-inner-box-top"
alignment="CENTER_LEFT"
maxWidth="Infinity"
@@ -31,11 +32,11 @@
</padding>
<Label text="NAME: " styleClass="status-label-small"/>
<!-- TODO: fx:id="playerName": Wird später durch den User-Namen aus der Server-Abfrage ersetzt -->
<!-- TODO: fx:id="playerName": Will later be replaced by the username from the server query -->
<Label fx:id="playerName" text="SPIELER" styleClass="status-value-text"/>
</HBox>
<!-- Schaft platz zwischen den Boxen -->
<!-- Shaft space between the boxes -->
<HBox styleClass="status-inner-box-midle"
alignment="CENTER_LEFT"
maxWidth="Infinity"
@@ -46,7 +47,7 @@
</padding>
</HBox>
<!-- Anzeige des Kapitals/Geldstands -->
<!-- Display of capital/money balance -->
<HBox styleClass="status-inner-box-bottom"
alignment="CENTER_LEFT"
maxWidth="Infinity"
@@ -60,7 +61,7 @@
<Label fx:id="playerMoney" text="0 $" styleClass="status-value-money"/>
</HBox>
<!-- TODO: User-Logo oder Icon: Platzhalter für das Profilbild oder das individuelle Logo des Spielers -->
<!-- TODO: User logo or icon: Placeholder for the profile picture or the player's individual logo -->
<Pane prefHeight="0" maxWidth="Infinity">
<Region styleClass="status-circle"
layoutX="-10"
@@ -4,7 +4,7 @@
<?import javafx.scene.layout.*?>
<?import javafx.geometry.Insets?>
<!-- verschiebbare Taskbar -->
<!-- movable taskbar -->
<HBox xmlns="http://javafx.com/javafx/21"
xmlns:fx="http://javafx.com/fxml/1"
fx:controller="ch.unibas.dmi.dbis.cs108.casono.client.ui.gameui.gameuicomponents.TaskbarController"
@@ -17,36 +17,36 @@
onMouseReleased="#onTaskbarReleased"
layoutX="50.0" layoutY="710.0">
<!-- Platzhalter-Buttons -->
<!-- Placeholder buttons -->
<Button text="EINSTELLUNGEN" styleClass="gray-button" />
<Button text="INFO" styleClass="gray-button" />
<!-- Buten für den Casono Browser -->
<!-- Buten for the Casono Browser -->
<Button text="HILFE" onAction="#onBrowserButtonClick" styleClass="gray-button" />
<!-- Vertikale-Trennlinie: Erzeugt eine optische Abgrenzung zwischen zwei Butten-Bereichen -->
<!-- Vertical dividing line: Creates a visual separation between two button areas -->
<Separator orientation="VERTICAL" prefHeight="20" opacity="0.3" />
<!-- Eingabefeld: Reagiert auf die Enter-Taste, um den Einsatz zu bestätigen -->
<!-- Input field: Responds to the Enter key to confirm the entry -->
<TextField fx:id="taskbarInput"
promptText="Betrag setzen..."
onKeyPressed="#onInputSubmitted"
styleClass="gray-input-field"
prefWidth="150" />
<!-- Bestätigungs-Button: Alternative zum Enter-Key, um den Einsatz abzusenden -->
<!-- Confirmation button: Alternative to the Enter key to submit the entry -->
<Button text="SETZTEN"
onAction="#onInputSubmittedAction"
styleClass="yellow-button"/>
<!-- Vertikale-Trennlinie: Erzeugt eine optische Abgrenzung zwischen zwei Butten-Bereichen -->
<!-- Vertical dividing line: Creates a visual separation between two button areas -->
<Separator orientation="VERTICAL" prefHeight="20" opacity="0.3" />
<!-- Menü-Button: Bricht das aktuelle Spiel ab und kehrt zum Hauptmenü zurück -->
<!-- Menu button: Cancels the current game and returns to the main menu -->
<Button text="VERLASSEN"
onAction="#onExitButtonClick"
styleClass="red-button"/>
<!-- Innenabstand: Hält den Inhalt 10 Pixel von oben/unten und 20 Pixel von den Seiten fern -->
<!-- Inner spacing: Keeps the content 10 pixels away from the top/bottom and 20 pixels from the sides -->
<padding>
<Insets top="10" right="20" bottom="10" left="20"/>
</padding>