Add: visual indicator for current player in Game UI
This commit is contained in:
+328
-10
@@ -6,6 +6,7 @@ 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.GameState;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.client.game.Player;
|
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.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.ClientService;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.client.ui.gameui.gameuicomponents.PlayerStatusController;
|
import ch.unibas.dmi.dbis.cs108.casono.client.ui.gameui.gameuicomponents.PlayerStatusController;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.client.ui.gameui.gameuicomponents.TaskbarController;
|
import ch.unibas.dmi.dbis.cs108.casono.client.ui.gameui.gameuicomponents.TaskbarController;
|
||||||
@@ -138,11 +139,14 @@ public class CasinoGameController {
|
|||||||
private static final long CHIP_STAGGER_DELAY_MULTIPLIER = 35L;
|
private static final long CHIP_STAGGER_DELAY_MULTIPLIER = 35L;
|
||||||
private static final double CHAT_WIDTH = 400;
|
private static final double CHAT_WIDTH = 400;
|
||||||
private static final double CHAT_HEIGHT = 600;
|
private static final double CHAT_HEIGHT = 600;
|
||||||
|
private static final String ACTIVE_CARD_BOX_STYLE_CLASS = "player-cards-active-turn";
|
||||||
|
|
||||||
private String chatUsername;
|
private String chatUsername;
|
||||||
private ClientService chatClientService;
|
private ClientService chatClientService;
|
||||||
private int chatLobbyId = -1;
|
private int chatLobbyId = -1;
|
||||||
private boolean chatInitialized;
|
private boolean chatInitialized;
|
||||||
|
private boolean gameFinished;
|
||||||
|
private String lastWinnerName;
|
||||||
|
|
||||||
/** Standard constructor. Used by FXML. */
|
/** Standard constructor. Used by FXML. */
|
||||||
public CasinoGameController() {
|
public CasinoGameController() {
|
||||||
@@ -230,6 +234,7 @@ public class CasinoGameController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
myDealerIcon.setVisible(false);
|
myDealerIcon.setVisible(false);
|
||||||
|
tableText.setWrapText(true);
|
||||||
|
|
||||||
javafx.stage.Screen screen = javafx.stage.Screen.getPrimary();
|
javafx.stage.Screen screen = javafx.stage.Screen.getPrimary();
|
||||||
double screenHeight = screen.getBounds().getHeight();
|
double screenHeight = screen.getBounds().getHeight();
|
||||||
@@ -477,7 +482,7 @@ public class CasinoGameController {
|
|||||||
*/
|
*/
|
||||||
private void applyState(GameState s) {
|
private void applyState(GameState s) {
|
||||||
|
|
||||||
if (s == null) {
|
if (s == null || gameFinished) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -490,6 +495,24 @@ public class CasinoGameController {
|
|||||||
+ (s.players != null ? s.players.size() : 0));
|
+ (s.players != null ? s.players.size() : 0));
|
||||||
|
|
||||||
List<Player> players = (s.players != null) ? s.players : List.of();
|
List<Player> players = (s.players != null) ? s.players : List.of();
|
||||||
|
String winnerName = resolveWinnerName(s);
|
||||||
|
if (winnerName != null && !winnerName.isBlank()) {
|
||||||
|
lastWinnerName = winnerName;
|
||||||
|
} else if (!isTerminalPhase(s.phase)) {
|
||||||
|
lastWinnerName = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isGameFinishedState(s, winnerName)) {
|
||||||
|
updatePlayers(players, -1);
|
||||||
|
syncWhisperTargetsFromPlayers(players);
|
||||||
|
updateGameInfo(s);
|
||||||
|
highlightDealer(s);
|
||||||
|
updateTaskbar(s);
|
||||||
|
clearActiveTurnHighlights();
|
||||||
|
finishGameUiLoop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
List<Card> community = (s.communityCards != null) ? s.communityCards : List.of();
|
List<Card> community = (s.communityCards != null) ? s.communityCards : List.of();
|
||||||
List<Card> myCards = getMyCards(players);
|
List<Card> myCards = getMyCards(players);
|
||||||
|
|
||||||
@@ -510,7 +533,7 @@ public class CasinoGameController {
|
|||||||
renderPot(s.pot);
|
renderPot(s.pot);
|
||||||
}
|
}
|
||||||
|
|
||||||
updatePlayers(players);
|
updatePlayers(players, s.activePlayer);
|
||||||
syncWhisperTargetsFromPlayers(players);
|
syncWhisperTargetsFromPlayers(players);
|
||||||
updateGameInfo(s);
|
updateGameInfo(s);
|
||||||
highlightDealer(s);
|
highlightDealer(s);
|
||||||
@@ -610,14 +633,28 @@ public class CasinoGameController {
|
|||||||
*/
|
*/
|
||||||
private void updateGameInfo(GameState s) {
|
private void updateGameInfo(GameState s) {
|
||||||
|
|
||||||
String text = "Phase: " + s.phase;
|
if (s == null) {
|
||||||
|
tableText.setText("Phase: -");
|
||||||
if (s.winnerIndex >= 0 && s.winnerIndex < s.players.size()) {
|
return;
|
||||||
Player winner = s.players.get(s.winnerIndex);
|
|
||||||
text = "Winner: " + winner.getName();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tableText.setText(text);
|
String winnerName = resolveWinnerName(s);
|
||||||
|
if (winnerName != null && !winnerName.isBlank()) {
|
||||||
|
tableText.setText("Winner: " + winnerName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String phaseText = formatPhaseText(s.phase);
|
||||||
|
StringBuilder text = new StringBuilder("Phase: ").append(phaseText);
|
||||||
|
|
||||||
|
tableText.setText(text.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private String formatPhaseText(String phase) {
|
||||||
|
if (phase == null || phase.isBlank()) {
|
||||||
|
return "-";
|
||||||
|
}
|
||||||
|
return phase.toUpperCase().replace("_", " ");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -645,7 +682,7 @@ public class CasinoGameController {
|
|||||||
* opponents and update their display in the UI accordingly. If the list is null or empty,
|
* opponents and update their display in the UI accordingly. If the list is null or empty,
|
||||||
* all opponent slots will be cleared.
|
* all opponent slots will be cleared.
|
||||||
*/
|
*/
|
||||||
private void updatePlayers(List<Player> players) {
|
private void updatePlayers(List<Player> players, int activePlayerIndex) {
|
||||||
if (players == null || players.isEmpty()) {
|
if (players == null || players.isEmpty()) {
|
||||||
clearOpponentSlots();
|
clearOpponentSlots();
|
||||||
return;
|
return;
|
||||||
@@ -671,6 +708,7 @@ public class CasinoGameController {
|
|||||||
safeRefresh(player1Controller);
|
safeRefresh(player1Controller);
|
||||||
safeRefresh(player2Controller);
|
safeRefresh(player2Controller);
|
||||||
safeRefresh(player3Controller);
|
safeRefresh(player3Controller);
|
||||||
|
updateActiveTurnHighlights(players, activePlayerIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -695,7 +733,7 @@ public class CasinoGameController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
PlayerId pid = p.getId();
|
PlayerId pid = p.getId();
|
||||||
boolean isMe = myPlayerId != null && pid != null && pid.equals(myPlayerId);
|
boolean isMe = myPlayerId != null && myPlayerId.equals(pid);
|
||||||
|
|
||||||
if (isMe) {
|
if (isMe) {
|
||||||
meFound = true;
|
meFound = true;
|
||||||
@@ -767,6 +805,286 @@ public class CasinoGameController {
|
|||||||
safeRefresh(player1Controller);
|
safeRefresh(player1Controller);
|
||||||
safeRefresh(player2Controller);
|
safeRefresh(player2Controller);
|
||||||
safeRefresh(player3Controller);
|
safeRefresh(player3Controller);
|
||||||
|
clearActiveTurnHighlights();
|
||||||
|
setTaskbarTurnHighlight(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear all visual highlights in the UI that indicate the active player's turn.
|
||||||
|
*/
|
||||||
|
private void clearActiveTurnHighlights() {
|
||||||
|
if (player1Controller != null) {
|
||||||
|
player1Controller.setTurnHighlighted(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player2Controller != null) {
|
||||||
|
player2Controller.setTurnHighlighted(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player3Controller != null) {
|
||||||
|
player3Controller.setTurnHighlighted(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (playerStatusController != null) {
|
||||||
|
playerStatusController.setTurnHighlighted(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
setPlayerCardsTurnHighlighted(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the visual highlight state of the player's hole cards to indicate whether it is
|
||||||
|
* currently the player's turn in the game.
|
||||||
|
*
|
||||||
|
* @param highlighted true to highlight the player's hole cards, indicating that it is their turn,
|
||||||
|
* or false to remove the highlight when it is not their turn.
|
||||||
|
*/
|
||||||
|
private void setPlayerCardsTurnHighlighted(boolean highlighted) {
|
||||||
|
if (playerCardsBox == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Node child : playerCardsBox.getChildren()) {
|
||||||
|
if (child instanceof ImageView) {
|
||||||
|
toggleStyleClass(child, ACTIVE_CARD_BOX_STYLE_CLASS, highlighted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the visual highlights in the UI to indicate which player's turn it is based on the active.
|
||||||
|
*
|
||||||
|
* @param players The list of players currently in the game, used to identify the active
|
||||||
|
* player and update the turn highlights accordingly.
|
||||||
|
* @param activePlayerIndex The index of the active player in the players list, which is used to determine
|
||||||
|
* whose turn it is and update the UI highlights to reflect that.
|
||||||
|
*/
|
||||||
|
private void updateActiveTurnHighlights(List<Player> players, int activePlayerIndex) {
|
||||||
|
clearActiveTurnHighlights();
|
||||||
|
|
||||||
|
Player activePlayer = getPlayerAtIndex(players, activePlayerIndex);
|
||||||
|
if (activePlayer == null || activePlayer.getId() == null) {
|
||||||
|
setTaskbarTurnHighlight(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (myPlayerId != null && myPlayerId.equals(activePlayer.getId())) {
|
||||||
|
setPlayerCardsTurnHighlighted(true);
|
||||||
|
setTaskbarTurnHighlight(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setTaskbarTurnHighlight(false);
|
||||||
|
|
||||||
|
if (player1Controller != null && player1Controller.hasPlayer(activePlayer)) {
|
||||||
|
player1Controller.setTurnHighlighted(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player2Controller != null && player2Controller.hasPlayer(activePlayer)) {
|
||||||
|
player2Controller.setTurnHighlighted(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player3Controller != null && player3Controller.hasPlayer(activePlayer)) {
|
||||||
|
player3Controller.setTurnHighlighted(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the turn highlight state in the taskbar controller, which visually indicates whether
|
||||||
|
* it is the current player's turn in the game.
|
||||||
|
*
|
||||||
|
* @param highlighted true to highlight the turn in the taskbar, false to remove the highlight.
|
||||||
|
*/
|
||||||
|
private void setTaskbarTurnHighlight(boolean highlighted) {
|
||||||
|
TaskbarController taskbarCtrl = resolveTaskbarController();
|
||||||
|
if (taskbarCtrl != null) {
|
||||||
|
taskbarCtrl.setTurnHighlighted(highlighted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the Player object at the specified index from the list of players.
|
||||||
|
*
|
||||||
|
* @param players The list of players from which to retrieve the player at the specified index.
|
||||||
|
* @param index The index of the player to retrieve from the list.
|
||||||
|
* @return The Player object at the specified index if it exists and is valid, or null if the
|
||||||
|
* index is out of bounds or if the players list is null or empty.
|
||||||
|
*/
|
||||||
|
private Player getPlayerAtIndex(List<Player> players, int index) {
|
||||||
|
if (players == null || index < 0 || index >= players.size()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return players.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve the winner of the hand based on the game state.
|
||||||
|
*
|
||||||
|
* @param s The current game state, which may contain information about the players,
|
||||||
|
* their states, and the winner index.
|
||||||
|
* @return The Player object representing the winner if it can be determined from the
|
||||||
|
* game state, or null if the winner cannot be resolved or if the game is still in progress.
|
||||||
|
*/
|
||||||
|
private Player resolveWinner(GameState s) {
|
||||||
|
if (s == null || s.players == null || s.players.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s.winnerIndex >= 0 && s.winnerIndex < s.players.size()) {
|
||||||
|
return s.players.get(s.winnerIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
Player remaining = null;
|
||||||
|
int remainingCount = 0;
|
||||||
|
for (Player player : s.players) {
|
||||||
|
if (player == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (player.getState() == PlayerState.FOLDED) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (remainingCount > 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
remaining = player;
|
||||||
|
remainingCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remaining != null && remainingCount == 1) {
|
||||||
|
return remaining;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve the name of the winner based on the game state.
|
||||||
|
*
|
||||||
|
* @param s The current game state, which may contain information about the players,
|
||||||
|
* their states, and the winner index.
|
||||||
|
* @return The name of the winner if it can be determined from the game state,
|
||||||
|
* or null if the winner cannot be resolved or if the game is still in progress.
|
||||||
|
*/
|
||||||
|
private String resolveWinnerName(GameState s) {
|
||||||
|
Player winner = resolveWinner(s);
|
||||||
|
if (winner != null) {
|
||||||
|
String name = winner.getName();
|
||||||
|
if (name != null && !name.isBlank()) {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isTerminalPhase(s != null ? s.phase : null)
|
||||||
|
&& lastWinnerName != null
|
||||||
|
&& !lastWinnerName.isBlank()) {
|
||||||
|
return lastWinnerName;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the game is in a finished state based on the game state and the presence of a winner name.
|
||||||
|
*
|
||||||
|
* @param s The current game state, which may be null or contain information about the phase, players,
|
||||||
|
* and winner index.
|
||||||
|
* @param winnerName The name of the winner, which may be null or blank if the winner is not yet determined
|
||||||
|
* or if the game is still in progress.
|
||||||
|
* @return true if the game is considered finished based on the provided state and winner information,
|
||||||
|
* false otherwise.
|
||||||
|
*/
|
||||||
|
private boolean isGameFinishedState(GameState s, String winnerName) {
|
||||||
|
if (s == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean winnerKnown = winnerName != null && !winnerName.isBlank();
|
||||||
|
if (!winnerKnown) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isTerminalPhase(s.phase)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s.winnerIndex >= 0 && s.players != null && s.winnerIndex < s.players.size()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hasSingleRemainingPlayer(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if there is only one remaining active player in the game state.
|
||||||
|
*
|
||||||
|
* @param s The current game state, which may be null or contain a list of players.
|
||||||
|
* @return true if there is exactly one active player remaining (not folded), false otherwise.
|
||||||
|
*/
|
||||||
|
private boolean hasSingleRemainingPlayer(GameState s) {
|
||||||
|
if (s == null || s.players == null || s.players.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int remaining = 0;
|
||||||
|
for (Player player : s.players) {
|
||||||
|
if (player == null || player.getState() == PlayerState.FOLDED) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
remaining++;
|
||||||
|
if (remaining > 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return remaining == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the current phase of the game is a terminal phase, such as "FINISHED" or "SHOWDOWN".
|
||||||
|
*
|
||||||
|
* @param phase The current phase of the game, which may be null or blank.
|
||||||
|
* @return true if the phase is considered terminal, indicating that the hand has ended
|
||||||
|
* and a winner can be declared, false otherwise.
|
||||||
|
*/
|
||||||
|
private boolean isTerminalPhase(String phase) {
|
||||||
|
return "FINISHED".equalsIgnoreCase(phase) || "SHOWDOWN".equalsIgnoreCase(phase);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finish the game UI loop by stopping the timeline that updates the UI.
|
||||||
|
*/
|
||||||
|
private void finishGameUiLoop() {
|
||||||
|
if (gameFinished) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
gameFinished = true;
|
||||||
|
if (timeline != null) {
|
||||||
|
timeline.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggle a CSS style class on a JavaFX Node based on the active state.
|
||||||
|
*
|
||||||
|
* @param node The JavaFX Node on which to toggle the style class.
|
||||||
|
* @param styleClass The name of the CSS style class to toggle.
|
||||||
|
* @param active A boolean indicating whether to add (true)
|
||||||
|
* or remove (false) the style class from the node.
|
||||||
|
*/
|
||||||
|
private void toggleStyleClass(Node node, String styleClass, boolean active) {
|
||||||
|
if (node == null || styleClass == null || styleClass.isBlank()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (active) {
|
||||||
|
if (!node.getStyleClass().contains(styleClass)) {
|
||||||
|
node.getStyleClass().add(styleClass);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
node.getStyleClass().remove(styleClass);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+61
-2
@@ -2,12 +2,15 @@ package ch.unibas.dmi.dbis.cs108.casono.client.ui.gameui.gameuicomponents;
|
|||||||
|
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.client.game.Player;
|
import ch.unibas.dmi.dbis.cs108.casono.client.game.Player;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.client.game.PlayerState;
|
import ch.unibas.dmi.dbis.cs108.casono.client.game.PlayerState;
|
||||||
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.image.Image;
|
import javafx.scene.image.Image;
|
||||||
import javafx.scene.image.ImageView;
|
import javafx.scene.image.ImageView;
|
||||||
import javafx.scene.layout.Pane;
|
import javafx.scene.layout.Pane;
|
||||||
|
import javafx.scene.layout.VBox;
|
||||||
|
import javafx.scene.layout.HBox;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controller for displaying a player's status in the poker game, including their name, chip count
|
* Controller for displaying a player's status in the poker game, including their name, chip count
|
||||||
@@ -21,11 +24,16 @@ public class PlayerStatusController {
|
|||||||
@FXML private Label playerMoney;
|
@FXML private Label playerMoney;
|
||||||
@FXML private ImageView dealerIcon;
|
@FXML private ImageView dealerIcon;
|
||||||
@FXML private Pane parent;
|
@FXML private Pane parent;
|
||||||
|
@FXML private VBox playerStatusBox;
|
||||||
|
@FXML private HBox statusInnerBoxTop;
|
||||||
|
@FXML private HBox statusInnerBoxBottom;
|
||||||
|
|
||||||
private Image dealerImage;
|
private Image dealerImage;
|
||||||
private Player player;
|
private Player player;
|
||||||
|
private boolean turnHighlighted;
|
||||||
private static final String DEALER_IMAGE_PATH = "/images/chip-dealer-blue-3.png";
|
private static final String DEALER_IMAGE_PATH = "/images/chip-dealer-blue-3.png";
|
||||||
private static final double DEALER_ICON_X_FACTOR = 0.8;
|
private static final double DEALER_ICON_X_FACTOR = 0.8;
|
||||||
|
private static final String TURN_HIGHLIGHT_STYLE_CLASS = "player-status-active-turn";
|
||||||
|
|
||||||
/** Initialize the controller, load dealer image, and set up bindings. */
|
/** Initialize the controller, load dealer image, and set up bindings. */
|
||||||
@FXML
|
@FXML
|
||||||
@@ -42,8 +50,7 @@ public class PlayerStatusController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOGGER.severe("Error: loading dealer image:");
|
LOGGER.log(Level.SEVERE, "Error loading dealer image", e);
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dealerIcon.layoutXProperty().bind(parent.widthProperty().multiply(DEALER_ICON_X_FACTOR));
|
dealerIcon.layoutXProperty().bind(parent.widthProperty().multiply(DEALER_ICON_X_FACTOR));
|
||||||
@@ -57,13 +64,20 @@ public class PlayerStatusController {
|
|||||||
*/
|
*/
|
||||||
public void setPlayer(Player player) {
|
public void setPlayer(Player player) {
|
||||||
this.player = player;
|
this.player = player;
|
||||||
|
if (player == null) {
|
||||||
|
turnHighlighted = false;
|
||||||
|
}
|
||||||
refresh();
|
refresh();
|
||||||
|
updateTurnHighlightStyle();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Refresh UI safely */
|
/** Refresh UI safely */
|
||||||
public void refresh() {
|
public void refresh() {
|
||||||
|
|
||||||
if (player == null) {
|
if (player == null) {
|
||||||
|
playerName.setText("-");
|
||||||
|
playerMoney.setText("0 $");
|
||||||
|
dealerIcon.setVisible(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,6 +98,30 @@ public class PlayerStatusController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Highlight or unhighlight this player slot as the currently active turn.
|
||||||
|
*
|
||||||
|
* @param highlighted true if this slot should be highlighted, false otherwise.
|
||||||
|
*/
|
||||||
|
public void setTurnHighlighted(boolean highlighted) {
|
||||||
|
this.turnHighlighted = highlighted;
|
||||||
|
updateTurnHighlightStyle();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether the controller is currently bound to the provided player.
|
||||||
|
*
|
||||||
|
* @param candidate the player to compare against.
|
||||||
|
* @return true if both represent the same player.
|
||||||
|
*/
|
||||||
|
public boolean hasPlayer(Player candidate) {
|
||||||
|
if (player == null || candidate == null || player.getId() == null || candidate.getId() == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return player.getId().equals(candidate.getId());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* External quick update
|
* External quick update
|
||||||
*
|
*
|
||||||
@@ -107,4 +145,25 @@ public class PlayerStatusController {
|
|||||||
dealerIcon.setImage(dealerImage);
|
dealerIcon.setImage(dealerImage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the visual style of the player status box to indicate whether it's currently this player's turn.
|
||||||
|
*/
|
||||||
|
private void updateTurnHighlightStyle() {
|
||||||
|
if (statusInnerBoxTop == null || statusInnerBoxBottom == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (turnHighlighted) {
|
||||||
|
if (!statusInnerBoxTop.getStyleClass().contains(TURN_HIGHLIGHT_STYLE_CLASS)) {
|
||||||
|
statusInnerBoxTop.getStyleClass().add(TURN_HIGHLIGHT_STYLE_CLASS);
|
||||||
|
}
|
||||||
|
if (!statusInnerBoxBottom.getStyleClass().contains(TURN_HIGHLIGHT_STYLE_CLASS)) {
|
||||||
|
statusInnerBoxBottom.getStyleClass().add(TURN_HIGHLIGHT_STYLE_CLASS);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
statusInnerBoxTop.getStyleClass().remove(TURN_HIGHLIGHT_STYLE_CLASS);
|
||||||
|
statusInnerBoxBottom.getStyleClass().remove(TURN_HIGHLIGHT_STYLE_CLASS);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user