Feat: Improving the Game UI and implementing new Features:
- Improve dealer chip Rendering. - Improve pot Rendering. - Uses names instead of IDs as identifiers. - Users are displayed one after another as they enter the Game UI. - Correct order of opponents <- B <-> S <-> D <-> O -> in the Game UI. - The boxes for the opponents should have a working hover effect. - Improve the rendering of the table text. - Remove hover animations from cards and the pot for improved handling and a more stable Game UI.
This commit is contained in:
@@ -18,4 +18,6 @@ public class GameState {
|
||||
public int dealer;
|
||||
public int activePlayer;
|
||||
public int winnerIndex = -1;
|
||||
public List<String> winnerNames = new ArrayList<>();
|
||||
public int potPerWinner;
|
||||
}
|
||||
|
||||
@@ -111,6 +111,7 @@ public class GameClient {
|
||||
GameState s = new GameState();
|
||||
s.players = new ArrayList<>();
|
||||
s.communityCards = new ArrayList<>();
|
||||
s.winnerNames = new ArrayList<>();
|
||||
|
||||
ParseState state = new ParseState();
|
||||
for (String raw : input.split("\n")) {
|
||||
@@ -155,6 +156,14 @@ public class GameClient {
|
||||
s.winnerIndex = intVal(l);
|
||||
yield true;
|
||||
}
|
||||
case String l when l.startsWith("WINNER_NAME=") -> {
|
||||
s.winnerNames.add(value(l));
|
||||
yield true;
|
||||
}
|
||||
case String l when l.startsWith("POT_PER_WINNER=") -> {
|
||||
s.potPerWinner = intVal(l);
|
||||
yield true;
|
||||
}
|
||||
case String l when l.startsWith("HIGHSCORE=") -> {
|
||||
s.highscoreEntries.add(value(l));
|
||||
yield true;
|
||||
@@ -224,6 +233,13 @@ public class GameClient {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (line.startsWith("ID=")) {
|
||||
if (state.currentPlayer.getId() == null) {
|
||||
state.currentPlayer.setId(PlayerId.of(value(line)));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (line.startsWith("CHIPS=")) {
|
||||
state.currentPlayer.setChips(intVal(line));
|
||||
return true;
|
||||
|
||||
@@ -244,6 +244,33 @@ public class LobbyClient {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the current lobby members from GET_LOBBY_STATUS and returns their usernames in order.
|
||||
*
|
||||
* @param lobbyId id of the lobby to inspect
|
||||
* @return list of usernames currently known in the lobby
|
||||
*/
|
||||
public List<String> fetchLobbyPlayerNames(int lobbyId) {
|
||||
List<String> lines = client.processCommand("GET_LOBBY_STATUS ID=" + lobbyId);
|
||||
List<RequestParameter> params = ClientService.convertToRequestParameters(lines);
|
||||
|
||||
List<String> names = new ArrayList<>();
|
||||
for (RequestParameter parameter : params) {
|
||||
if (!"USERNAME".equalsIgnoreCase(parameter.key())) {
|
||||
continue;
|
||||
}
|
||||
String name = parameter.value();
|
||||
if (name != null) {
|
||||
String trimmed = name.trim();
|
||||
if (!trimmed.isEmpty() && !names.contains(trimmed)) {
|
||||
names.add(trimmed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
/** Simple data holder for lobby metadata returned by the server. */
|
||||
public static final class LobbyInfo {
|
||||
public final int id;
|
||||
|
||||
+454
-62
@@ -10,7 +10,10 @@ 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.ClientService;
|
||||
import ch.unibas.dmi.dbis.cs108.casono.client.network.LobbyClient;
|
||||
import ch.unibas.dmi.dbis.cs108.casono.client.ui.gameui.gameuicomponents.NotebookController;
|
||||
import ch.unibas.dmi.dbis.cs108.casono.client.ui.gameui.gameuicomponents.PlayerStatusController;
|
||||
import ch.unibas.dmi.dbis.cs108.casono.client.ui.gameui.gameuicomponents.SettingsController;
|
||||
import ch.unibas.dmi.dbis.cs108.casono.client.ui.gameui.gameuicomponents.TaskbarController;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
@@ -21,6 +24,7 @@ import java.util.concurrent.CompletableFuture;
|
||||
import java.util.logging.Logger;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.image.Image;
|
||||
@@ -60,8 +64,13 @@ public class CasinoGameController {
|
||||
|
||||
private GameService gameService;
|
||||
private PlayerId myPlayerId;
|
||||
private String myPlayerName;
|
||||
@FXML private TaskbarController taskbarIncludeController;
|
||||
private TaskbarController taskbarController;
|
||||
@FXML private NotebookController notebookIncludeController;
|
||||
private NotebookController notebookController;
|
||||
@FXML private SettingsController settingsIncludeController;
|
||||
// private SettingsController settingsController;
|
||||
private Image dealerImage;
|
||||
private javafx.animation.Timeline timeline;
|
||||
private boolean gameStarted = false;
|
||||
@@ -73,6 +82,7 @@ public class CasinoGameController {
|
||||
public static final double CHAT_CONTAINER_CONSTANT = 6.0;
|
||||
private static final int TOTAL_SLOTS = 5;
|
||||
private static final int PLAYER_SLOTS = 2;
|
||||
private static final int MAX_OPPONENTS_TO_RENDER = 3;
|
||||
private int pot = 0;
|
||||
private static final String BACKSIDE = "/images/card-background-3.png";
|
||||
private static final String DEALER_IMAGE_PATH = "/images/chip-dealer-blue-3.png";
|
||||
@@ -115,6 +125,8 @@ public class CasinoGameController {
|
||||
private static final double COMMUNITY_CARD_WIDTH_RATIO = 0.11;
|
||||
private static final double PLAYER_CARD_HEIGHT_RATIO = 0.30;
|
||||
private static final double PLAYER_CARD_WIDTH_RATIO = 0.15;
|
||||
private static final double DEALER_HEIGHT_RATIO = 0.13;
|
||||
private static final double DEALER_WIDTH_RATIO = 0.13;
|
||||
private static final double PLAYER_CARDS_Y_OFFSET_FACTOR = 0.10;
|
||||
private static final int[] CHIP_VALUES = {
|
||||
100000, 50000, 20000, 10000,
|
||||
@@ -139,6 +151,12 @@ public class CasinoGameController {
|
||||
private static final long CHIP_SCALE_DURATION_MS = 220;
|
||||
private static final long CHIP_DROP_DURATION_MS = 250;
|
||||
private static final long CHIP_STAGGER_DELAY_MULTIPLIER = 35L;
|
||||
private static final int MAX_POT_ROWS = 2;
|
||||
private static final double POT_CHIP_H_GAP = 6.0;
|
||||
private static final double POT_CHIP_V_GAP = 6.0;
|
||||
private static final double POT_WIDTH_FACTOR = 0.45;
|
||||
private static final double FALLBACK_POT_WIDTH = 500.0;
|
||||
private static final double FALLBACK_CHIP_WIDTH = 36.0;
|
||||
private static final double CHAT_WIDTH = 400;
|
||||
private static final double CHAT_HEIGHT = 600;
|
||||
private static final String ACTIVE_CARD_BOX_STYLE_CLASS = "player-cards-active-turn";
|
||||
@@ -156,6 +174,8 @@ public class CasinoGameController {
|
||||
private static final int SMALL_BLIND = 100;
|
||||
private static final int BIG_BLIND = 200;
|
||||
private static final int NO_BET = 0;
|
||||
private boolean myDealerIconSizeBound;
|
||||
private java.util.List<String> lobbyPlayerNames = java.util.List.of();
|
||||
|
||||
/** Standard constructor. Used by FXML. */
|
||||
public CasinoGameController() {
|
||||
@@ -230,6 +250,16 @@ public class CasinoGameController {
|
||||
if (taskbarController != null && gameService != null && myPlayerId != null) {
|
||||
taskbarController.setGameService(gameService, myPlayerId);
|
||||
}
|
||||
|
||||
notebookController = resolveNotebookController();
|
||||
if (taskbarController != null && notebookController != null) {
|
||||
taskbarController.setNotebookController(notebookController);
|
||||
}
|
||||
|
||||
if (taskbarController != null && settingsIncludeController != null) {
|
||||
taskbarController.setSettingsController(settingsIncludeController);
|
||||
settingsIncludeController.setThemeChangeListener(this::applyTheme);
|
||||
}
|
||||
configureTaskbarLobbyActionAnnouncements();
|
||||
|
||||
if (communityCardsBox == null) {
|
||||
@@ -251,6 +281,7 @@ public class CasinoGameController {
|
||||
}
|
||||
|
||||
myDealerIcon.setVisible(false);
|
||||
styleMyDealerIcon();
|
||||
tableText.setWrapText(true);
|
||||
|
||||
javafx.stage.Screen screen = javafx.stage.Screen.getPrimary();
|
||||
@@ -267,6 +298,8 @@ public class CasinoGameController {
|
||||
renderPlayerCards(List.of());
|
||||
|
||||
chatContainer.toFront();
|
||||
|
||||
javafx.application.Platform.runLater(() -> applyTheme("standard"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -475,6 +508,7 @@ public class CasinoGameController {
|
||||
.thenAccept(
|
||||
state -> {
|
||||
if (state == null) {
|
||||
refreshLobbyOpponentsBeforeGameStart();
|
||||
LOGGER.info("No state received yet.");
|
||||
return;
|
||||
}
|
||||
@@ -492,6 +526,35 @@ public class CasinoGameController {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the list of opponents in the lobby before the game starts by fetching the latest player.
|
||||
*/
|
||||
private void refreshLobbyOpponentsBeforeGameStart() {
|
||||
if (gameService != null && gameService.peekStateOrNull() != null) {
|
||||
return;
|
||||
}
|
||||
if (chatClientService == null || chatLobbyId < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
LobbyClient lobbyClient = new LobbyClient(chatClientService);
|
||||
List<String> latestNames = lobbyClient.fetchLobbyPlayerNames(chatLobbyId);
|
||||
if (latestNames == null) {
|
||||
latestNames = List.of();
|
||||
}
|
||||
if (latestNames.equals(lobbyPlayerNames)) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> namesToRender = List.copyOf(latestNames);
|
||||
javafx.application.Platform.runLater(() -> setLobbyPlayerNames(namesToRender));
|
||||
} catch (Exception e) {
|
||||
String msg = "Could not refresh lobby player names: " + e.getMessage();
|
||||
LOGGER.fine(msg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all visual UI components with the data from the provided GameState. This includes
|
||||
* community cards, pot, player information, and the taskbar.
|
||||
@@ -621,12 +684,12 @@ public class CasinoGameController {
|
||||
*/
|
||||
private List<Card> getMyCards(List<Player> players) {
|
||||
|
||||
if (myPlayerId == null || players == null) {
|
||||
if (players == null) {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
for (Player p : players) {
|
||||
if (p.getId() != null && p.getId().equals(myPlayerId)) {
|
||||
if (isCurrentPlayer(p)) {
|
||||
return p.getCards() != null ? p.getCards() : List.of();
|
||||
}
|
||||
}
|
||||
@@ -641,13 +704,13 @@ public class CasinoGameController {
|
||||
*/
|
||||
private void updatePlayerCards(GameState s) {
|
||||
|
||||
if (s.players == null || myPlayerId == null) {
|
||||
if (s.players == null) {
|
||||
renderPlayerCards(List.of());
|
||||
return;
|
||||
}
|
||||
|
||||
for (Player p : s.players) {
|
||||
if (p.getId().equals(myPlayerId)) {
|
||||
if (isCurrentPlayer(p)) {
|
||||
renderPlayerCards(p.getCards());
|
||||
return;
|
||||
}
|
||||
@@ -672,7 +735,18 @@ public class CasinoGameController {
|
||||
|
||||
String winnerName = resolveWinnerName(s);
|
||||
if (winnerName != null && !winnerName.isBlank()) {
|
||||
tableText.setText("Winner: " + winnerName);
|
||||
StringBuilder winnerText = new StringBuilder("Winner");
|
||||
|
||||
if (s.winnerNames != null && s.winnerNames.size() > 1) {
|
||||
winnerText.append("s: ").append(String.join(", ", s.winnerNames));
|
||||
if (s.potPerWinner > 0) {
|
||||
winnerText.append(" (").append(s.potPerWinner).append(" each)");
|
||||
}
|
||||
} else {
|
||||
winnerText.append(": ").append(winnerName);
|
||||
}
|
||||
|
||||
tableText.setText(winnerText.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -770,13 +844,13 @@ public class CasinoGameController {
|
||||
*/
|
||||
private void updateTaskbar(GameState s) {
|
||||
TaskbarController controller = resolveTaskbarController();
|
||||
if (controller == null || myPlayerId == null) {
|
||||
if (controller == null) {
|
||||
return;
|
||||
}
|
||||
if (gameService != null) {
|
||||
controller.setGameService(gameService, myPlayerId);
|
||||
}
|
||||
controller.update(s, myPlayerId);
|
||||
controller.update(s, myPlayerName);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -832,30 +906,50 @@ public class CasinoGameController {
|
||||
* opponents.
|
||||
*/
|
||||
private java.util.List<Player> buildOpponents(List<Player> players) {
|
||||
java.util.List<Player> opponents = new java.util.ArrayList<>();
|
||||
boolean meFound = false;
|
||||
|
||||
for (Player p : players) {
|
||||
if (p == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
PlayerId pid = p.getId();
|
||||
boolean isMe = myPlayerId != null && myPlayerId.equals(pid);
|
||||
|
||||
if (isMe) {
|
||||
meFound = true;
|
||||
} else {
|
||||
opponents.add(p);
|
||||
}
|
||||
if (players == null || players.isEmpty()) {
|
||||
return java.util.List.of();
|
||||
}
|
||||
|
||||
if (!meFound) {
|
||||
opponents.clear();
|
||||
opponents.addAll(players);
|
||||
int myIndex = findCurrentPlayerIndex(players);
|
||||
if (myIndex < 0) {
|
||||
java.util.List<Player> fallback = new java.util.ArrayList<>();
|
||||
for (Player player : players) {
|
||||
if (player != null) {
|
||||
fallback.add(player);
|
||||
}
|
||||
}
|
||||
return fallback;
|
||||
}
|
||||
|
||||
return opponents;
|
||||
java.util.List<Player> ordered = new java.util.ArrayList<>(Math.max(0, players.size() - 1));
|
||||
for (int offset = 1; offset < players.size(); offset++) {
|
||||
int index = (myIndex + offset) % players.size();
|
||||
Player player = players.get(index);
|
||||
if (player != null) {
|
||||
ordered.add(player);
|
||||
}
|
||||
}
|
||||
return ordered;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the index of the current player in the provided list of players by comparing their PlayerId
|
||||
* with myPlayerId.
|
||||
*
|
||||
* @param players The list of players to search through, which may include the current player and their opponents.
|
||||
* @return The index of the current player in the list if found, or -1 if the current player is not present in the
|
||||
* list or if the list is null or empty.
|
||||
*/
|
||||
private int findCurrentPlayerIndex(List<Player> players) {
|
||||
if (players == null || players.isEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
for (int i = 0; i < players.size(); i++) {
|
||||
if (isCurrentPlayer(players.get(i))) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -970,12 +1064,12 @@ public class CasinoGameController {
|
||||
clearActiveTurnHighlights();
|
||||
|
||||
Player activePlayer = getPlayerAtIndex(players, activePlayerIndex);
|
||||
if (activePlayer == null || activePlayer.getId() == null) {
|
||||
if (activePlayer == null) {
|
||||
setTaskbarTurnHighlight(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (myPlayerId != null && myPlayerId.equals(activePlayer.getId())) {
|
||||
if (isCurrentPlayer(activePlayer)) {
|
||||
setPlayerCardsTurnHighlighted(true);
|
||||
setTaskbarTurnHighlight(true);
|
||||
return;
|
||||
@@ -1104,11 +1198,7 @@ public class CasinoGameController {
|
||||
}
|
||||
|
||||
Player winner = resolveWinner(s);
|
||||
boolean isLocalWinner =
|
||||
winner != null
|
||||
&& winner.getId() != null
|
||||
&& myPlayerId != null
|
||||
&& myPlayerId.equals(winner.getId());
|
||||
boolean isLocalWinner = winner != null && isCurrentPlayer(winner);
|
||||
|
||||
if (!isLocalWinner && lastWinnerName != null && !lastWinnerName.isBlank()) {
|
||||
String localName =
|
||||
@@ -1255,11 +1345,11 @@ public class CasinoGameController {
|
||||
}
|
||||
|
||||
Player dealerPlayer = s.players.get(s.dealer);
|
||||
if (dealerPlayer == null || dealerPlayer.getId() == null) {
|
||||
if (dealerPlayer == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (myPlayerId != null && myPlayerId.equals(dealerPlayer.getId())) {
|
||||
if (isCurrentPlayer(dealerPlayer)) {
|
||||
myDealerIcon.setVisible(true);
|
||||
return;
|
||||
}
|
||||
@@ -1292,10 +1382,17 @@ public class CasinoGameController {
|
||||
* otherwise.
|
||||
*/
|
||||
private boolean samePlayer(Player a, Player b) {
|
||||
if (a == null || b == null || a.getId() == null || b.getId() == null) {
|
||||
if (a == null || b == null) {
|
||||
return false;
|
||||
}
|
||||
return a.getId().equals(b.getId());
|
||||
|
||||
String aName = normalizeIdentifier(a.getName());
|
||||
String bName = normalizeIdentifier(b.getName());
|
||||
if (aName != null && bName != null) {
|
||||
return aName.equals(bName);
|
||||
}
|
||||
|
||||
return a.getId() != null && b.getId() != null && a.getId().equals(b.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1326,8 +1423,8 @@ public class CasinoGameController {
|
||||
|
||||
view.setImage(image);
|
||||
|
||||
view.setOnMouseEntered(e -> animateCardHover(view, true));
|
||||
view.setOnMouseExited(e -> animateCardHover(view, false));
|
||||
// view.setOnMouseEntered(e -> animateCardHover(view, true));
|
||||
// view.setOnMouseExited(e -> animateCardHover(view, false));
|
||||
|
||||
view.setOpacity(CARD_START_OPACITY);
|
||||
|
||||
@@ -1370,8 +1467,8 @@ public class CasinoGameController {
|
||||
|
||||
view.setImage(image);
|
||||
|
||||
view.setOnMouseEntered(e -> animateCardHover(view, true));
|
||||
view.setOnMouseExited(e -> animateCardHover(view, false));
|
||||
// view.setOnMouseEntered(e -> animateCardHover(view, true));
|
||||
// view.setOnMouseExited(e -> animateCardHover(view, false));
|
||||
|
||||
view.setOpacity(CARD_START_OPACITY);
|
||||
|
||||
@@ -1384,6 +1481,47 @@ public class CasinoGameController {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply styling to the myDealerIcon ImageView.
|
||||
*/
|
||||
private void styleMyDealerIcon() {
|
||||
if (myDealerIcon == null || playerCardsBox == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
myDealerIcon.setPreserveRatio(true);
|
||||
myDealerIcon.setSmooth(true);
|
||||
|
||||
javafx.scene.Scene scene = playerCardsBox.getScene();
|
||||
if (scene != null) {
|
||||
bindMyDealerIconSize(scene);
|
||||
} else {
|
||||
playerCardsBox
|
||||
.sceneProperty()
|
||||
.addListener(
|
||||
(obs, oldScene, newScene) -> {
|
||||
if (newScene != null) {
|
||||
bindMyDealerIconSize(newScene);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind the size of the myDealerIcon ImageView to the dimensions of the scene using predefined ratios.
|
||||
*
|
||||
* @param scene The JavaFX Scene to which the myDealerIcon belongs, used for binding the size properties.
|
||||
*/
|
||||
private void bindMyDealerIconSize(javafx.scene.Scene scene) {
|
||||
if (myDealerIconSizeBound || scene == null || myDealerIcon == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
myDealerIcon.fitHeightProperty().bind(scene.heightProperty().multiply(DEALER_HEIGHT_RATIO));
|
||||
myDealerIcon.fitWidthProperty().bind(scene.widthProperty().multiply(DEALER_WIDTH_RATIO));
|
||||
myDealerIconSizeBound = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load an image from the given path safely, falling back to a default backside image if the
|
||||
* specified image cannot be found.
|
||||
@@ -1551,28 +1689,30 @@ public class CasinoGameController {
|
||||
* Animate a card hover effect by scaling and lifting the card when hovered and resetting it
|
||||
* when not hovered.
|
||||
*
|
||||
* However, we have removed the hover animations from the cards and the pot for improved handling and a more stable Game UI.
|
||||
*
|
||||
* @param view The ImageView representing the card to animate on hover.
|
||||
* @param hover A boolean indicating whether the card is being hovered (true) or not (false).
|
||||
*/
|
||||
private void animateCardHover(ImageView view, boolean hover) {
|
||||
|
||||
double scale = hover ? HOVER_SCALE_ON : HOVER_SCALE_OFF;
|
||||
double lift = hover ? HOVER_LIFT_ON : HOVER_LIFT_OFF;
|
||||
|
||||
javafx.animation.ScaleTransition st =
|
||||
new javafx.animation.ScaleTransition(
|
||||
javafx.util.Duration.millis(HOVER_DURATION_MS), view);
|
||||
st.setToX(scale);
|
||||
st.setToY(scale);
|
||||
|
||||
javafx.animation.TranslateTransition tt =
|
||||
new javafx.animation.TranslateTransition(
|
||||
javafx.util.Duration.millis(HOVER_DURATION_MS), view);
|
||||
tt.setToY(lift);
|
||||
|
||||
st.play();
|
||||
tt.play();
|
||||
}
|
||||
// private void animateCardHover(ImageView view, boolean hover) {
|
||||
//
|
||||
// double scale = hover ? HOVER_SCALE_ON : HOVER_SCALE_OFF;
|
||||
// double lift = hover ? HOVER_LIFT_ON : HOVER_LIFT_OFF;
|
||||
//
|
||||
// javafx.animation.ScaleTransition st =
|
||||
// new javafx.animation.ScaleTransition(
|
||||
// javafx.util.Duration.millis(HOVER_DURATION_MS), view);
|
||||
// st.setToX(scale);
|
||||
// st.setToY(scale);
|
||||
//
|
||||
// javafx.animation.TranslateTransition tt =
|
||||
// new javafx.animation.TranslateTransition(
|
||||
// javafx.util.Duration.millis(HOVER_DURATION_MS), view);
|
||||
// tt.setToY(lift);
|
||||
//
|
||||
// st.play();
|
||||
// tt.play();
|
||||
// }
|
||||
|
||||
/**
|
||||
* Position the player's hole cards box on the screen based on a predefined offset factor
|
||||
@@ -1640,13 +1780,26 @@ public class CasinoGameController {
|
||||
|
||||
potBox.getChildren().clear();
|
||||
|
||||
int chipsPerRow = resolveChipsPerPotRow();
|
||||
int maxVisibleChips = chipsPerRow * MAX_POT_ROWS;
|
||||
HBox topRow = createPotRow();
|
||||
HBox bottomRow = createPotRow();
|
||||
VBox rows = new VBox(POT_CHIP_V_GAP, topRow, bottomRow);
|
||||
rows.setAlignment(Pos.CENTER);
|
||||
potBox.getChildren().add(rows);
|
||||
|
||||
int remaining = pot;
|
||||
|
||||
int index = 0;
|
||||
boolean limitReached = false;
|
||||
|
||||
for (int chipValue : CHIP_VALUES) {
|
||||
|
||||
while (remaining >= chipValue) {
|
||||
if (index >= maxVisibleChips) {
|
||||
limitReached = true;
|
||||
break;
|
||||
}
|
||||
|
||||
ImageView chip =
|
||||
new ImageView(loadImageSafe("/images/chip-" + chipValue + "-5.png"));
|
||||
@@ -1658,18 +1811,66 @@ public class CasinoGameController {
|
||||
|
||||
styleChip(chip);
|
||||
|
||||
potBox.getChildren().add(chip);
|
||||
if (index < chipsPerRow) {
|
||||
topRow.getChildren().add(chip);
|
||||
} else {
|
||||
bottomRow.getChildren().add(chip);
|
||||
}
|
||||
|
||||
animateChipAppear(chip, index);
|
||||
|
||||
remaining -= chipValue;
|
||||
index++;
|
||||
}
|
||||
|
||||
if (limitReached) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// LOGGER.info("POT RENDERED: " + pot + " -> remaining: " + remaining);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new HBox to represent a row of chips in the pot display, with predefined horizontal.
|
||||
*
|
||||
* @return A new HBox instance configured for displaying a row of chips in the pot,
|
||||
* with appropriate spacing and alignment.
|
||||
*/
|
||||
private HBox createPotRow() {
|
||||
HBox row = new HBox(POT_CHIP_H_GAP);
|
||||
row.setAlignment(Pos.CENTER);
|
||||
return row;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the number of chips that can be displayed per row in the pot based on the available width.
|
||||
*
|
||||
* @return The calculated number of chips that can fit in a single row of the pot display.
|
||||
*/
|
||||
private int resolveChipsPerPotRow() {
|
||||
double availableWidth = potBox != null ? potBox.getWidth() : 0.0;
|
||||
if (availableWidth <= 0 && potBox != null && potBox.getScene() != null) {
|
||||
availableWidth = potBox.getScene().getWidth() * POT_WIDTH_FACTOR;
|
||||
}
|
||||
if (availableWidth <= 0) {
|
||||
availableWidth = FALLBACK_POT_WIDTH;
|
||||
}
|
||||
|
||||
double estimatedChipWidth = FALLBACK_CHIP_WIDTH;
|
||||
if (potBox != null && potBox.getScene() != null) {
|
||||
estimatedChipWidth =
|
||||
Math.max(FALLBACK_CHIP_WIDTH, potBox.getScene().getWidth() * CHIP_WIDTH_RATIO);
|
||||
}
|
||||
|
||||
int chipsPerRow =
|
||||
(int)
|
||||
Math.floor(
|
||||
(availableWidth + POT_CHIP_H_GAP)
|
||||
/ (estimatedChipWidth + POT_CHIP_H_GAP));
|
||||
return Math.max(1, chipsPerRow);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply styling to the given ImageView for chips, including CSS classes and size bindings.
|
||||
*
|
||||
@@ -1769,13 +1970,126 @@ public class CasinoGameController {
|
||||
*/
|
||||
public void setMyPlayerId(PlayerId id) {
|
||||
this.myPlayerId = id;
|
||||
this.myPlayerName = id != null ? normalizeIdentifier(id.value()) : null;
|
||||
TaskbarController controller = resolveTaskbarController();
|
||||
if (controller != null && gameService != null && myPlayerId != null) {
|
||||
controller.setGameService(gameService, myPlayerId);
|
||||
}
|
||||
renderLobbyOpponentsIfNeeded();
|
||||
configureTaskbarLobbyActionAnnouncements();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets lobby player names to be shown before the first game-state update is available.
|
||||
*
|
||||
* @param names player names currently present in the lobby
|
||||
*/
|
||||
public void setLobbyPlayerNames(List<String> names) {
|
||||
if (names == null || names.isEmpty()) {
|
||||
this.lobbyPlayerNames = java.util.List.of();
|
||||
} else {
|
||||
this.lobbyPlayerNames = java.util.List.copyOf(names);
|
||||
}
|
||||
renderLobbyOpponentsIfNeeded();
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the opponents in the lobby based on the list of lobby player names, but only if the game
|
||||
* service is not yet initialized or if there is no game state available.
|
||||
*/
|
||||
private void renderLobbyOpponentsIfNeeded() {
|
||||
if (gameService != null && gameService.peekStateOrNull() != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (lobbyPlayerNames == null || lobbyPlayerNames.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
java.util.List<String> opponents = new java.util.ArrayList<>();
|
||||
for (String rawName : lobbyPlayerNames) {
|
||||
String normalized = normalizeIdentifier(rawName);
|
||||
if (normalized == null) {
|
||||
continue;
|
||||
}
|
||||
if (myPlayerName != null && myPlayerName.equals(normalized)) {
|
||||
continue;
|
||||
}
|
||||
if (!opponents.contains(rawName.trim())) {
|
||||
opponents.add(rawName.trim());
|
||||
}
|
||||
if (opponents.size() >= MAX_OPPONENTS_TO_RENDER) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
setLobbyOpponent(player1Controller, opponents, 0);
|
||||
setLobbyOpponent(player2Controller, opponents, 1);
|
||||
setLobbyOpponent(player3Controller, opponents, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the lobby opponent information in the given PlayerStatusController slot based on the list
|
||||
* of opponent names and the specified index.
|
||||
*
|
||||
* @param slot The PlayerStatusController instance representing the UI slot for an opponent,
|
||||
* which will be updated with the opponent's name if available.
|
||||
* @param opponents The list of opponent names currently in the lobby, which may be null or
|
||||
* contain fewer entries than the index.
|
||||
* @param index The index of the opponent in the opponents list to be displayed in the given slot, where
|
||||
* 0 corresponds to the first opponent, 1 to the second, and so on.
|
||||
*/
|
||||
private void setLobbyOpponent(PlayerStatusController slot, List<String> opponents, int index) {
|
||||
if (slot == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (opponents == null || index >= opponents.size()) {
|
||||
slot.setPlayer(null);
|
||||
safeRefresh(slot);
|
||||
return;
|
||||
}
|
||||
|
||||
slot.setPlayer(null);
|
||||
slot.updatePlayer(opponents.get(index), 0);
|
||||
slot.setDealer(false);
|
||||
slot.setTurnHighlighted(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given Player object represents the current player based on the
|
||||
* player's name and ID compared to the stored myPlayerName and myPlayerId values.
|
||||
*
|
||||
* @param player The Player object to check, which may be null or contain name and ID information.
|
||||
* @return true if the given Player is identified as the current player based on name or ID matching, false otherwise.
|
||||
*/
|
||||
private boolean isCurrentPlayer(Player player) {
|
||||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String candidateName = normalizeIdentifier(player.getName());
|
||||
if (myPlayerName != null && candidateName != null && myPlayerName.equals(candidateName)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return myPlayerId != null && player.getId() != null && myPlayerId.equals(player.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize a player name or identifier by trimming whitespace and converting to lowercase, returning null if the result is empty.
|
||||
*
|
||||
* @param value The raw player name or identifier to normalize, which may be null or contain leading/trailing whitespace.
|
||||
* @return The normalized identifier in lowercase without leading/trailing whitespace, or null if the input is null or empty after trimming.
|
||||
*/
|
||||
private String normalizeIdentifier(String value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
String trimmed = value.trim();
|
||||
return trimmed.isEmpty() ? null : trimmed.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the TaskbarController to announce lobby actions by sending chat messages when
|
||||
* certain actions occur in the game, such as winning a hand.
|
||||
@@ -1833,4 +2147,82 @@ public class CasinoGameController {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the NotebookController for displaying tips and game information.
|
||||
*
|
||||
* @return The NotebookController instance, which may be the directly injected
|
||||
* notebookController or the one obtained from the notebookIncludeController.
|
||||
*/
|
||||
private NotebookController resolveNotebookController() {
|
||||
if (notebookController != null) {
|
||||
return notebookController;
|
||||
}
|
||||
if (notebookIncludeController != null) {
|
||||
notebookController = notebookIncludeController;
|
||||
return notebookController;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the SettingsController for theme switching.
|
||||
*
|
||||
* @return The SettingsController instance, which may be the directly injected
|
||||
* settingsController or the one obtained from the settingsIncludeController.
|
||||
*/
|
||||
public SettingsController getSettingsController() {
|
||||
return settingsIncludeController;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies a UI theme by switching the application's stylesheet.
|
||||
*
|
||||
* @param theme The theme name: "standard", "blackwhite", or "glass"
|
||||
*/
|
||||
private void applyTheme(String theme) {
|
||||
if (theme == null || theme.isBlank()) {
|
||||
LOGGER.warning("Theme is null or empty -> ignoring theme change");
|
||||
return;
|
||||
}
|
||||
|
||||
javafx.scene.Scene scene = casinoTable != null ? casinoTable.getScene() : null;
|
||||
|
||||
if (scene == null) {
|
||||
LOGGER.warning("Scene not ready yet -> cannot apply theme: " + theme);
|
||||
return;
|
||||
}
|
||||
|
||||
String cssPath =
|
||||
switch (theme.toLowerCase()) {
|
||||
case "blackwhite" -> "/ui-structure/Casinogameui-blackwhite.css";
|
||||
case "glass" -> "/ui-structure/Casinogameui-glass.css";
|
||||
default -> "/ui-structure/Casinogameui.css";
|
||||
};
|
||||
|
||||
java.net.URL cssUrl = getClass().getResource(cssPath);
|
||||
|
||||
if (cssUrl == null) {
|
||||
LOGGER.severe("CSS resource not found: " + cssPath);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
String cssExternalForm = cssUrl.toExternalForm();
|
||||
|
||||
scene.getStylesheets()
|
||||
.removeIf(
|
||||
s ->
|
||||
s.contains("Casinogameui.css")
|
||||
|| s.contains("Casinogameui-blackwhite.css")
|
||||
|| s.contains("Casinogameui-glass.css"));
|
||||
|
||||
scene.getStylesheets().add(cssExternalForm);
|
||||
|
||||
LOGGER.info("Theme switched successfully to: " + theme);
|
||||
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Failed to apply theme '" + theme + "': " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ 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;
|
||||
import ch.unibas.dmi.dbis.cs108.casono.client.network.GameClient;
|
||||
import ch.unibas.dmi.dbis.cs108.casono.client.network.LobbyClient;
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Logger;
|
||||
@@ -130,6 +131,13 @@ public class CasinoGameUI extends Application {
|
||||
controller.setMyPlayerId(PlayerId.of(effectiveUsername));
|
||||
controller.setChatContext(effectiveUsername, clientService, lobbyId);
|
||||
|
||||
try {
|
||||
LobbyClient lobbyClient = new LobbyClient(clientService);
|
||||
controller.setLobbyPlayerNames(lobbyClient.fetchLobbyPlayerNames(lobbyId));
|
||||
} catch (Exception e) {
|
||||
LOG.fine("Could not preload lobby player names: " + e.getMessage());
|
||||
}
|
||||
|
||||
controller.startChat(chatController);
|
||||
|
||||
Scene scene = new Scene(root, DEFAULT_WIDTH, DEFAULT_HEIGHT);
|
||||
|
||||
+18
-5
@@ -115,14 +115,27 @@ public class PlayerStatusController {
|
||||
* @return true if both represent the same player.
|
||||
*/
|
||||
public boolean hasPlayer(Player candidate) {
|
||||
if (player == null
|
||||
|| candidate == null
|
||||
|| player.getId() == null
|
||||
|| candidate.getId() == null) {
|
||||
if (player == null || candidate == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return player.getId().equals(candidate.getId());
|
||||
String currentName = normalizeIdentifier(player.getName());
|
||||
String candidateName = normalizeIdentifier(candidate.getName());
|
||||
if (currentName != null && candidateName != null) {
|
||||
return currentName.equals(candidateName);
|
||||
}
|
||||
|
||||
return player.getId() != null
|
||||
&& candidate.getId() != null
|
||||
&& player.getId().equals(candidate.getId());
|
||||
}
|
||||
|
||||
private String normalizeIdentifier(String value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
String trimmed = value.trim();
|
||||
return trimmed.isEmpty() ? null : trimmed.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+161
-14
@@ -51,15 +51,19 @@ public class TaskbarController {
|
||||
|
||||
private GameService gameService;
|
||||
private PlayerId myPlayerId;
|
||||
private String myPlayerName;
|
||||
private GameState lastState;
|
||||
private double xOffset = 0;
|
||||
private double yOffset = 0;
|
||||
private NotebookController notebookController;
|
||||
private SettingsController settingsController;
|
||||
private static final double TASKBAR_SCALE = 0.95;
|
||||
private static final double PREFLOP_BLOCK_RATIO = 0.50;
|
||||
private static final double FLOP_WARN_RATIO = 0.50;
|
||||
private static final double FLOP_BLOCK_RATIO = 0.80;
|
||||
private static final double TURN_RIVER_WARN_RATIO = 0.80;
|
||||
private static final double TURN_RIVER_BLOCK_RATIO = 1.00;
|
||||
private static final int SMALLEST_VALUE = 5;
|
||||
private static final int SMALL_BLIND = 100;
|
||||
private static final int BIG_BLIND = 200;
|
||||
private static final String STYLE_YELLOW_BUTTON = "yellow-button";
|
||||
@@ -230,6 +234,17 @@ public class TaskbarController {
|
||||
public void setGameService(GameService gameService, PlayerId myPlayerId) {
|
||||
this.gameService = gameService;
|
||||
this.myPlayerId = myPlayerId;
|
||||
this.myPlayerName = myPlayerId != null ? normalizeIdentifier(myPlayerId.value()) : null;
|
||||
}
|
||||
|
||||
/** Sets the NotebookController reference for showing/hiding tips. */
|
||||
public void setNotebookController(NotebookController notebookController) {
|
||||
this.notebookController = notebookController;
|
||||
}
|
||||
|
||||
/** Sets the SettingsController reference for theme switching. */
|
||||
public void setSettingsController(SettingsController settingsController) {
|
||||
this.settingsController = settingsController;
|
||||
}
|
||||
|
||||
/** Sets an optional callback that publishes simple action labels to lobby chat. */
|
||||
@@ -340,6 +355,37 @@ public class TaskbarController {
|
||||
return "RAISE +" + raiseBy + " TO " + raiseamout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the typed input as the additional amount the player wants to contribute.
|
||||
*
|
||||
* <p>If the player has already invested chips in the current betting round, the typed value is
|
||||
* interpreted as an additional amount on top of that investment. This lets the user enter the
|
||||
* amount they still need to put in directly (for example: already invested 200, type 400 ->
|
||||
* total target 600).
|
||||
*
|
||||
* @param state current game state
|
||||
* @param rawInput text from the input field
|
||||
* @return total target bet, or null if the input is invalid
|
||||
*/
|
||||
private Integer resolveTypedContributionTarget(GameState state, String rawInput) {
|
||||
Integer input = parseInputTarget(rawInput);
|
||||
if (input == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (state == null || state.players == null) {
|
||||
return input;
|
||||
}
|
||||
|
||||
Player me = findCurrentPlayer(state);
|
||||
if (me == null) {
|
||||
return input;
|
||||
}
|
||||
|
||||
int alreadyInvested = Math.max(0, me.getBet());
|
||||
return alreadyInvested > 0 ? alreadyInvested + input : input;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the taskbar based on the current game state and the player's status.
|
||||
*
|
||||
@@ -352,8 +398,30 @@ public class TaskbarController {
|
||||
* and whether they are out of the game.
|
||||
*/
|
||||
public void update(GameState state, PlayerId myPlayerId) {
|
||||
this.myPlayerId = myPlayerId;
|
||||
this.myPlayerName = myPlayerId != null ? normalizeIdentifier(myPlayerId.value()) : null;
|
||||
update(state);
|
||||
}
|
||||
|
||||
if (state == null || state.players == null || myPlayerId == null) {
|
||||
/**
|
||||
* Updates the taskbar based on the current game state and the player's name.
|
||||
*
|
||||
* @param state current game state
|
||||
* @param myPlayerName local player name
|
||||
*/
|
||||
public void update(GameState state, String myPlayerName) {
|
||||
this.myPlayerName = normalizeIdentifier(myPlayerName);
|
||||
update(state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the taskbar based on the current game state.
|
||||
*
|
||||
* @param state current game state
|
||||
*/
|
||||
private void update(GameState state) {
|
||||
|
||||
if (state == null || state.players == null) {
|
||||
LOGGER.warn("Cannot update taskbar: invalid input");
|
||||
return;
|
||||
}
|
||||
@@ -364,11 +432,7 @@ public class TaskbarController {
|
||||
lastReferenceBet = state.currentBet;
|
||||
}
|
||||
|
||||
Player me =
|
||||
state.players.stream()
|
||||
.filter(p -> myPlayerId.equals(p.getId()))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
Player me = findCurrentPlayer(state);
|
||||
|
||||
if (me == null) {
|
||||
LOGGER.error("Player not found in GameState!");
|
||||
@@ -876,7 +940,8 @@ public class TaskbarController {
|
||||
return input != null ? input : callTarget + BIG_BLIND;
|
||||
}
|
||||
|
||||
return parseInputTarget(taskbarInput.getText());
|
||||
return resolveTypedContributionTarget(
|
||||
state, taskbarInput != null ? taskbarInput.getText() : null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1011,7 +1076,7 @@ public class TaskbarController {
|
||||
try {
|
||||
int value = Integer.parseInt(text.trim());
|
||||
|
||||
if (value % SMALL_BLIND != 0) {
|
||||
if (value % SMALLEST_VALUE != 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1033,7 +1098,7 @@ public class TaskbarController {
|
||||
* current game state.
|
||||
*/
|
||||
private ValidationResult validateTypedAmount(GameState state, String text) {
|
||||
Integer target = parseInputTarget(text);
|
||||
Integer target = resolveTypedContributionTarget(state, text);
|
||||
if (target == null || state == null) {
|
||||
return ValidationResult.blocked("Invalid input");
|
||||
}
|
||||
@@ -1491,15 +1556,53 @@ public class TaskbarController {
|
||||
submitAction(ActionType.INPUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the current player in the given game state based on the player's name or ID.
|
||||
*
|
||||
* @param state The current GameState object representing the state of the game,
|
||||
* which includes a list of players and their details.
|
||||
* @return The Player object representing the current player if found in the game state.
|
||||
*/
|
||||
private Player findCurrentPlayer(GameState state) {
|
||||
if (state == null || state.players == null || myPlayerId == null) {
|
||||
if (state == null || state.players == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return state.players.stream()
|
||||
.filter(player -> player != null && myPlayerId.equals(player.getId()))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
return state.players.stream().filter(this::isCurrentPlayer).findFirst().orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given player matches the current player's identity based on name or ID.
|
||||
*
|
||||
* @param player The Player object to check against the current player's identity,
|
||||
* which includes the player's name and ID.
|
||||
* @return A boolean value indicating whether the given player matches the current player's identity.
|
||||
*/
|
||||
private boolean isCurrentPlayer(Player player) {
|
||||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String playerName = normalizeIdentifier(player.getName());
|
||||
if (myPlayerName != null && playerName != null && myPlayerName.equals(playerName)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return myPlayerId != null && myPlayerId.equals(player.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes a player identifier (name or ID) by trimming whitespace and converting to lowercase.
|
||||
*
|
||||
* @param value The string value representing a player identifier, such as a name or ID.
|
||||
* @return A normalized version of the player identifier, where leading and trailing whitespace is removed.
|
||||
*/
|
||||
private String normalizeIdentifier(String value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
String trimmed = value.trim();
|
||||
return trimmed.isEmpty() ? null : trimmed.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1550,6 +1653,50 @@ public class TaskbarController {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the integrated Casono Web Browser.
|
||||
*/
|
||||
@FXML
|
||||
private void onBrowserButtonClickWiki() {
|
||||
try {
|
||||
|
||||
CasinoBrowserController.open("https://www.wikipedia.org/");
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the integrated Casono Web Browser.
|
||||
*/
|
||||
@FXML
|
||||
private void onBrowserButtonClickBrave() {
|
||||
try {
|
||||
|
||||
CasinoBrowserController.open("https://search.brave.com");
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/** Opens the tips notebook if it's currently closed. */
|
||||
@FXML
|
||||
private void onShowTipsButtonClick() {
|
||||
if (notebookController != null) {
|
||||
notebookController.showTips();
|
||||
}
|
||||
}
|
||||
|
||||
/** Opens the settings box for theme selection. */
|
||||
@FXML
|
||||
private void onSettingsButtonClick() {
|
||||
if (settingsController != null) {
|
||||
settingsController.show();
|
||||
}
|
||||
}
|
||||
|
||||
/** Opens the highscore popup window from the taskbar. */
|
||||
@FXML
|
||||
private void onHighscoreButtonClick() {
|
||||
|
||||
Reference in New Issue
Block a user