/** * This file is part of JSkat. * * JSkat is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * JSkat is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with JSkat. If not, see <http://www.gnu.org/licenses/>. */ package org.jskat.gui.swing.table; import java.awt.Color; import javax.swing.ActionMap; import javax.swing.BorderFactory; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.border.Border; import org.jskat.data.JSkatOptions; import org.jskat.gui.img.JSkatGraphicRepository; import org.jskat.gui.swing.LayoutFactory; import org.jskat.util.Card; import org.jskat.util.CardList; import org.jskat.util.GameType; import org.jskat.util.JSkatResourceBundle; import org.jskat.util.Player; /** * Abstract class for a panel representing a players hand */ abstract class AbstractHandPanel extends JPanel { private static final long serialVersionUID = 1L; /** * Player position */ Player position; /** * Card images */ JSkatGraphicRepository bitmaps; /** * i18n strings */ JSkatResourceBundle strings; /** * Header panel */ JPanel header; /** * Header label */ JLabel headerLabel; /** * Icon panel */ IconPanel iconPanel; /** * Clock panel */ ClockPanel clockPanel; /** * Player name */ String playerName; /** * Player bid */ int bidValue; boolean showIssWidgets; ClickableCardPanel cardPanel; /** * Maximum card count */ int maxCardCount = 0; /** * Indicates whether this player is currently the active player */ boolean isActivePlayer = false; /** * Indicates whether this player is an AI player */ boolean isAIPlayer = false; boolean playerPassed = false; boolean playerGeschoben = false; boolean declarer = false; private boolean playerContra; private boolean playerRe; /** * Constructor * * @param actions * Action map * @param maxCards * the maximum number of cards * @param showIssWidgets * TRUE, if ISS widgets should be shown * @param isNeuralNetworkPlayer * TRUE, if this panel is for a neural network opponent */ AbstractHandPanel(final ActionMap actions, final int maxCards, final boolean showIssWidgets) { setActionMap(actions); this.bitmaps = JSkatGraphicRepository.INSTANCE; this.strings = JSkatResourceBundle.INSTANCE; this.maxCardCount = maxCards; this.showIssWidgets = showIssWidgets; setOpaque(false); this.headerLabel = new JLabel(" "); //$NON-NLS-1$ this.iconPanel = new IconPanel(); this.clockPanel = new ClockPanel(); initPanel(); } /** * Initializes the panel */ void initPanel() { setLayout(LayoutFactory.getMigLayout("fill, insets 0", "fill", "[shrink][grow]")); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ setBorder(getPanelBorder(this.isActivePlayer)); String headerInsets = "insets "; if (showIssWidgets) { headerInsets = headerInsets + "0 5 0 0"; } else { headerInsets = headerInsets + "5"; } this.header = new JPanel(LayoutFactory.getMigLayout("fill, " + headerInsets, "[shrink][grow][shrink]", "fill")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ this.header.add(this.headerLabel); // blank panel this.header.add(new JPanel()); this.header.add(this.iconPanel); if (this.showIssWidgets) { iconPanel.setShowIssWidgets(true); this.header.add(this.clockPanel); } add(this.header, "shrinky, wrap"); //$NON-NLS-1$ this.cardPanel = new ClickableCardPanel(this, 1.0, true); add(this.cardPanel, "growy"); //$NON-NLS-1$ if (JSkatOptions.instance().isCheatDebugMode().booleanValue()) { showCards(); } } /** * Retrieves the Border for the hand panel for that player. It visually * distinguishes between active and non-active players. * * @return */ private Border getPanelBorder(final boolean isActivePlayer) { Border resultingBorder = null; if (isActivePlayer) { resultingBorder = BorderFactory.createLineBorder(Color.yellow, 3); } else { resultingBorder = BorderFactory.createLineBorder(Color.black, 3); } return resultingBorder; } /** * Sets the player position * * @param newPosition * Position */ void setPosition(final Player newPosition) { this.position = newPosition; refreshHeader(); } void setBidValue(final int newBidValue) { this.bidValue = newBidValue; refreshHeader(); } /** * Gets the player position * * @return Player position */ Player getPosition() { return this.position; } /** * Refreshes the header of this hand panel, i.e. the text and the thinking * icon. */ private void refreshHeader() { final StringBuffer headerText = new StringBuffer(); headerText.append(this.playerName).append(": "); //$NON-NLS-1$ if (this.position != null) { switch (this.position) { case FOREHAND: headerText.append(this.strings.getString("forehand")); //$NON-NLS-1$ break; case MIDDLEHAND: headerText.append(this.strings.getString("middlehand")); //$NON-NLS-1$ break; case REARHAND: headerText.append(this.strings.getString("rearhand")); //$NON-NLS-1$ break; } headerText.append(" " + this.strings.getString("bid") + ": "); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ headerText.append(this.bidValue); if (playerPassed || playerGeschoben || playerContra || playerRe) { headerText.append(" ("); //$NON-NLS-1$ String passedGeschobenContraRe = ""; if (playerPassed) { passedGeschobenContraRe = strings.getString("passed"); //$NON-NLS-1$ } if (playerGeschoben) { passedGeschobenContraRe = strings.getString("geschoben"); //$NON-NLS-1$ } if (passedGeschobenContraRe.length() > 0 && (playerContra || playerRe)) { passedGeschobenContraRe += " "; } if (playerContra) { passedGeschobenContraRe += strings.getString("contra"); } if (playerRe) { passedGeschobenContraRe += strings.getString("re"); } headerText.append(passedGeschobenContraRe); headerText.append(")"); //$NON-NLS-1$ } if (this.declarer) { headerText.append(" (" + this.strings.getString("declarer") + ")"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ } } if (isActivePlayer && isAIPlayer) { iconPanel.setThinking(true); } else { iconPanel.setThinking(false); } this.headerLabel.setText(headerText.toString()); } /** * Adds a card to the panel * * @param newCard * Card */ void addCard(final Card newCard) { this.cardPanel.addCard(newCard); } /** * Adds a Collection of cards to the panel * * @param newCards * card collection */ void addCards(final CardList newCards) { this.cardPanel.addCards(newCards); } /** * Removes a card from the panel * * @param cardToRemove * Card */ void removeCard(final Card cardToRemove) { this.cardPanel.removeCard(cardToRemove); } /** * Removes all cards from the panel */ void removeAllCards() { this.cardPanel.clearCards(); } /** * Removes all cards from the panel and resets other values */ void clearHandPanel() { this.cardPanel.clearCards(); this.bidValue = 0; this.playerPassed = false; this.playerGeschoben = false; this.playerContra = false; this.playerRe = false; this.declarer = false; this.iconPanel.reset(); refreshHeader(); setActivePlayer(false); hideCards(); } /** * Hides all cards on the panel */ void hideCards() { this.cardPanel.hideCards(); } /** * Shows all cards on the panel */ void showCards() { this.cardPanel.showCards(); } void setSortGameType(final GameType newGameType) { this.cardPanel.setSortType(newGameType); } boolean isHandFull() { return this.cardPanel.getCardCount() == this.maxCardCount; } public void setPlayerName(final String newName) { this.playerName = newName; refreshHeader(); } void setPlayerTime(final double newTime) { this.clockPanel.setPlayerTime(newTime); } void setChatEnabled(final boolean isChatEnabled) { this.iconPanel.setChatEnabled(isChatEnabled); } void setReadyToPlay(final boolean isReadyToPlay) { this.iconPanel.setReadyToPlay(isReadyToPlay); } void setResign(final boolean isResign) { this.iconPanel.setResign(isResign); } boolean isActivePlayer() { return this.isActivePlayer; } /** * Sets the flag that indicates whether this player is active (it is the * turn of this player). It also may change the visual indication whether * this player is thinking or not. * * @param isActivePlayer * whether this player is the active player */ void setActivePlayer(final boolean isActivePlayer) { this.isActivePlayer = isActivePlayer; // a refresh is needed to toggle the "is thinking" visual within the UI this.refreshHeader(); setBorder(getPanelBorder(this.isActivePlayer)); updateIssWidgets(isActivePlayer); } /** * Sets the flag that indicates whether this player is an AI player or not. * * @param isAIPlayer * TRUE, if the player is an AI player */ void setAIPlayer(final boolean isAIPlayer) { this.isAIPlayer = isAIPlayer; } private void updateIssWidgets(final boolean isActivePlayer) { if (this.showIssWidgets) { if (isActivePlayer) { this.clockPanel.setActive(); } else { this.clockPanel.setInactive(); } } } void setPass(final boolean isPassed) { this.playerPassed = isPassed; refreshHeader(); } void setDeclarer(final boolean isDeclarer) { this.declarer = isDeclarer; refreshHeader(); } public String getPlayerName() { return this.playerName; } public void setGeschoben() { this.playerGeschoben = true; refreshHeader(); } public void setContra() { this.playerContra = true; refreshHeader(); } public void setRe() { this.playerRe = true; refreshHeader(); } }