diff --git a/client/src/main/java/EntropyMain.java b/client/src/main/java/EntropyMain.java index 018f1384..872a0ce2 100644 --- a/client/src/main/java/EntropyMain.java +++ b/client/src/main/java/EntropyMain.java @@ -5,10 +5,13 @@ import javax.swing.WindowConstants; import logging.LoggerUncaughtExceptionHandler; +import preference.PreferenceSetting; import screen.MainScreen; import screen.ScreenCache; import util.*; +import static preference.PreferenceSettingKt.getPreference; +import static util.ClientGlobals.preferenceStore; import static utils.CoreGlobals.logger; public class EntropyMain implements Registry @@ -59,7 +62,7 @@ private static void setLookAndFeel() String lookAndFeel = null; try { - lookAndFeel = prefs.get(PREFERENCES_STRING_LOOK_AND_FEEL, "Metal"); + lookAndFeel = getPreference(PreferenceSetting.LookAndFeel); if (ClientUtil.isAppleOs() && lookAndFeel.equals("Metal")) { @@ -80,7 +83,7 @@ private static void setLookAndFeel() { logger.warn("laf.failed", "Failed to load LookAndFeel " + lookAndFeel + ". Caught " + e); DialogUtil.showError("Failed to load Look & Feel '" + lookAndFeel + "'. \nEntropy will use the default instead."); - prefs.put(PREFERENCES_STRING_LOOK_AND_FEEL, "Metal"); + preferenceStore.delete(PreferenceSetting.LookAndFeel); } } @@ -116,7 +119,7 @@ private static boolean bindOnPort(int portNumber) private static void checkForUpdatesIfRequired() { - boolean checkForUpdates = Registry.prefs.getBoolean(PREFERENCES_BOOLEAN_CHECK_FOR_UPDATES, true); + boolean checkForUpdates = getPreference(PreferenceSetting.CheckForUpdates); if (!checkForUpdates || ClientUtil.devMode) { diff --git a/client/src/main/java/bean/ComboBoxItem.java b/client/src/main/java/bean/ComboBoxItem.java deleted file mode 100644 index 940b43e8..00000000 --- a/client/src/main/java/bean/ComboBoxItem.java +++ /dev/null @@ -1,43 +0,0 @@ -package bean; - -public class ComboBoxItem -{ - private Object visibleData; - private E hiddenData; - private boolean enabled = true; - - public ComboBoxItem(E hiddenData, Object visibleData) - { - this.hiddenData = hiddenData; - this.visibleData = visibleData; - } - - public Object getVisibleData() - { - return visibleData; - } - public E getHiddenData() - { - return hiddenData; - } - - public boolean isEnabled() - { - return enabled; - } - public void setEnabled(boolean enabled) - { - this.enabled = enabled; - } - - @Override - public String toString() - { - if (enabled) - { - return "" + visibleData; - } - - return "" + visibleData + ""; - } -} diff --git a/client/src/main/java/object/BidListCellRenderer.java b/client/src/main/java/object/BidListCellRenderer.java deleted file mode 100644 index 4da78c8c..00000000 --- a/client/src/main/java/object/BidListCellRenderer.java +++ /dev/null @@ -1,73 +0,0 @@ -package object; - -import game.BidAction; -import game.PlayerAction; -import util.StringUtil; - -import java.awt.Component; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -import javax.swing.DefaultListCellRenderer; -import javax.swing.JList; - -import static game.RenderingUtilKt.getCardHtml; -import static game.SuitKt.MOONS_SYMBOL; -import static utils.ColourUtilKt.getColourForPlayerNumber; - -public class BidListCellRenderer extends DefaultListCellRenderer -{ - private Map hmNameToColour = new HashMap<>(); - - @Override - public Component getListCellRendererComponent(JList list, Object value, - int index, boolean isSelected, boolean cellHasFocus) - { - PlayerAction bid = (PlayerAction)value; - String text = toHtmlString(bid); - - return super.getListCellRendererComponent(list, text, index, isSelected, - cellHasFocus); - } - - public void updateColours(Collection players) { - this.hmNameToColour.clear(); - - for (Player player : players) { - hmNameToColour.put(player.getName(), player.getColour()); - } - } - - public void updateColours(Map map) { - this.hmNameToColour = map; - } - - public String toHtmlString(PlayerAction action) - { - String playerName = action.getPlayerName(); - playerName = StringUtil.escapeHtml(playerName); - - String colour = hmNameToColour.get(playerName); - String playerNamePrefix = playerName + ": "; - - if (action.getBlind()) - { - playerNamePrefix = "[" + playerName + "]: "; - } - - String text = "" + playerNamePrefix; - text += ""; - text += action.htmlString(); - - if (action instanceof BidAction bid && bid.getCardToReveal() != null) { - text += "&emsp(Shows: "; - text += getCardHtml(bid.getCardToReveal()); - text += ")"; - } - - //The unicode for a moon doesn't work in HTML. Also shrink to match the size of the other suits. - text = text.replaceAll(MOONS_SYMBOL, "🌙"); - return text; - } -} diff --git a/client/src/main/java/object/CardLabel.java b/client/src/main/java/object/CardLabel.java index 9fe48c1d..650506f4 100644 --- a/client/src/main/java/object/CardLabel.java +++ b/client/src/main/java/object/CardLabel.java @@ -3,12 +3,14 @@ import javax.swing.ImageIcon; import javax.swing.JLabel; +import preference.PreferenceSetting; import screen.EntropyScreen; import util.GameUtil; import util.Registry; +import static preference.PreferenceSettingKt.getPreference; + public class CardLabel extends JLabel - implements Registry { private String card = ""; private boolean faceUp = false; @@ -21,11 +23,11 @@ public void refreshIcon() { return; } - - String deckDirectory = prefs.get(PREFERENCES_STRING_DECK_DIRECTORY, Registry.DECK_DIRECTORY_CLASSIC); - String jokerDirectory = prefs.get(PREFERENCES_STRING_JOKER_DIRECTORY, Registry.JOKER_DIRECTORY_CLASSIC); - String numberOfColours = prefs.get(PREFERENCES_STRING_NUMBER_OF_COLOURS, Registry.TWO_COLOURS); - String back = prefs.get(PREFERENCES_STRING_CARD_BACKS, Registry.BACK_CODE_CLASSIC_BLUE); + + String deckDesign = getPreference(PreferenceSetting.DeckDesign); + String jokerDesign = getPreference(PreferenceSetting.JokerDesign); + String numberOfColours = getPreference(PreferenceSetting.NumberOfColours); + String back = getPreference(PreferenceSetting.CardBacks); if (faded) { back = "backFaded"; @@ -33,15 +35,15 @@ public void refreshIcon() if (!faceUp) { - setIcon(new ImageIcon(EntropyScreen.class.getResource("/backs/" + back + ".png"))); + setIcon(new ImageIcon(getClass().getResource("/backs/" + back + ".png"))); } else if (faded) { - setIcon(GameUtil.getFadedImageForCard(card, deckDirectory, jokerDirectory)); + setIcon(GameUtil.getFadedImageForCard(card, deckDesign, jokerDesign)); } else { - setIcon(GameUtil.getImageForCard(card, deckDirectory, jokerDirectory, numberOfColours)); + setIcon(GameUtil.getImageForCard(card, deckDesign, jokerDesign, numberOfColours)); } } diff --git a/client/src/main/java/object/DisabledComboBoxModel.java b/client/src/main/java/object/DisabledComboBoxModel.java index 274bf83a..5df8339a 100644 --- a/client/src/main/java/object/DisabledComboBoxModel.java +++ b/client/src/main/java/object/DisabledComboBoxModel.java @@ -31,7 +31,7 @@ public void setSelectedComboBoxItem(ComboBoxItem comboBoxItem) { if (comboBoxItem != null) { - if (comboBoxItem.isEnabled()) + if (comboBoxItem.getEnabled()) { super.setSelectedItem(comboBoxItem); } diff --git a/client/src/main/java/object/ReplayTable.java b/client/src/main/java/object/ReplayTable.java index 3d9b7338..03bf23ac 100644 --- a/client/src/main/java/object/ReplayTable.java +++ b/client/src/main/java/object/ReplayTable.java @@ -25,6 +25,7 @@ import javax.swing.table.TableModel; import javax.swing.table.TableRowSorter; +import preference.PreferenceSetting; import screen.ReplayDialog; import screen.ReplayFilterPanel; import screen.ScreenCache; @@ -37,12 +38,12 @@ import util.ReplayRowWrapper; import util.TableUtil; +import static preference.PreferenceSettingKt.getPreference; import static screen.ScreenCacheKt.FILE_REPLAY; import static utils.CoreGlobals.logger; public class ReplayTable extends JTable - implements MouseListener, - Registry + implements MouseListener { private static final int INDEX_OF_DATETIME_COLUMN = 0; private static final int INDEX_OF_NAME_COLUMN = INDEX_OF_DATETIME_COLUMN + 1; @@ -167,11 +168,11 @@ private void stripOutHiddenAndRemovedColumns() removeColumn(getColumnModel().getColumn(INDEX_OF_COMPLETED_COLUMN)); removeColumn(getColumnModel().getColumn(INDEX_OF_FILENAME_COLUMN)); - boolean showGameMode = prefs.getBoolean(PREFERENCES_BOOLEAN_INCLUDE_GAME_MODE_COLUMN, true); - boolean showRounds = prefs.getBoolean(PREFERENCES_BOOLEAN_INCLUDE_ROUNDS_COLUMN, false); - boolean showPlayers = prefs.getBoolean(PREFERENCES_BOOLEAN_INCLUDE_PLAYERS_COLUMN, true); - boolean showCards = prefs.getBoolean(PREFERENCES_BOOLEAN_INCLUDE_CARDS_COLUMN, false); - boolean showRoomName = prefs.getBoolean(PREFERENCES_BOOLEAN_INCLUDE_ROOM_NAME_COLUMN, false); + boolean showGameMode = getPreference(PreferenceSetting.IncludeGameModeColumn); + boolean showRounds = getPreference(PreferenceSetting.IncludeRoundsColumn); + boolean showPlayers = getPreference(PreferenceSetting.IncludePlayersColumn); + boolean showCards = getPreference(PreferenceSetting.IncludeCardsColumn); + boolean showRoomName = getPreference(PreferenceSetting.IncludeRoomNameColumn); if (!showCards) { diff --git a/client/src/main/java/object/RewardStar.java b/client/src/main/java/object/RewardStar.java deleted file mode 100644 index 272d9b83..00000000 --- a/client/src/main/java/object/RewardStar.java +++ /dev/null @@ -1,57 +0,0 @@ -package object; - -import javax.swing.Icon; -import javax.swing.JLabel; - -@SuppressWarnings("serial") -public class RewardStar extends JLabel -{ - private int threshold; - private String hoverDesc; - private String imageName; - - public RewardStar(int threshold, String hoverDesc, String imageName) - { - super(); - this.threshold = threshold; - this.hoverDesc = hoverDesc; - this.imageName = imageName; - } - - public boolean isUnlocked(int achievementsEarned) - { - return achievementsEarned >= threshold; - } - - public String getHoverDesc() - { - return hoverDesc; - } - - public String getImageName() - { - return imageName; - } - - @Override - public void setIcon(Icon icon) - { - Icon currentIcon = getIcon(); - - if (currentIcon == null || !icon.equals(currentIcon)) - { - super.setIcon(icon); - } - } - - @Override - public void setToolTipText(String text) - { - String currentText = getToolTipText(); - - if (currentText == null || !text.equals(currentText)) - { - super.setToolTipText(text); - } - } -} diff --git a/client/src/main/java/online/screen/GameRoom.java b/client/src/main/java/online/screen/GameRoom.java index dc8455ea..53fb20ee 100644 --- a/client/src/main/java/online/screen/GameRoom.java +++ b/client/src/main/java/online/screen/GameRoom.java @@ -1,10 +1,13 @@ package online.screen; +import achievement.Reward; +import bean.BidListCellRenderer; import game.*; import http.dto.RoomSummary; import object.*; import online.util.XmlBuilderClient; import org.w3c.dom.Document; +import preference.PreferenceSetting; import screen.*; import util.*; @@ -24,6 +27,7 @@ import java.util.prefs.Preferences; import static game.RegistryUtilKt.writeActions; +import static preference.PreferenceSettingKt.getPreference; import static utils.ColourUtilKt.getColourForPlayerNumber; import static utils.CoreGlobals.logger; @@ -212,15 +216,13 @@ else if (mode == GameMode.Vectropy) private void setIcon() { - boolean unlockedExtraSuits = rewards.getBoolean(REWARDS_BOOLEAN_EXTRA_SUITS, false); - ArrayList suits = new ArrayList<>(); suits.add("club"); suits.add("diamond"); suits.add("heart"); suits.add("spade"); - if (unlockedExtraSuits) + if (Reward.ExtraSuits.isUnlocked()) { suits.add("moon"); suits.add("star"); @@ -704,7 +706,7 @@ public void startGame(int personToStart) } adjustPlayersBasedOnHands(); - playBlind = prefs.getBoolean(PREFERENCES_BOOLEAN_PLAY_BLIND, false); + playBlind = getPreference(PreferenceSetting.PlayBlind); hasActedBlindThisGame = false; handPanel.setHasViewedHandThisGame(false); handPanel.setViewCardsVisibility(playBlind && playerIsEnabled(playerNumberLocal)); @@ -1349,7 +1351,7 @@ public boolean bidHistoryContainsBid() @Override public void requestFocus() { - boolean popUpRoom = prefs.getBoolean(PREFERENCES_BOOLEAN_POP_UP_ROOMS, true); + boolean popUpRoom = getPreference(PreferenceSetting.PopUpRooms); if (popUpRoom) { diff --git a/client/src/main/java/online/util/ResponseHandler.java b/client/src/main/java/online/util/ResponseHandler.java index bc95c904..a24853a2 100644 --- a/client/src/main/java/online/util/ResponseHandler.java +++ b/client/src/main/java/online/util/ResponseHandler.java @@ -10,6 +10,7 @@ import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; +import preference.PreferenceSetting; import screen.ScreenCache; import util.*; import utils.CoreGlobals; @@ -18,6 +19,7 @@ import java.util.HashMap; import java.util.List; +import static preference.PreferenceSettingKt.getPreference; import static utils.CoreGlobals.logger; public class ResponseHandler implements XmlConstants @@ -233,7 +235,7 @@ private static void handleNewRoundResponse(Element root, EntropyLobby lobby) */ private static void pauseDuringChallenge() { - int sleepMillis = 1000 * Registry.prefs.getInt(Registry.PREFERENCES_INT_AUTO_START_SECONDS, 2); + int sleepMillis = 1000 * getPreference(PreferenceSetting.AutoStartSeconds); try { Thread.sleep(sleepMillis); } catch (Throwable t) {} } diff --git a/client/src/main/java/screen/AbstractAboutDialog.java b/client/src/main/java/screen/AbstractAboutDialog.java index f33094a7..0abe6aff 100644 --- a/client/src/main/java/screen/AbstractAboutDialog.java +++ b/client/src/main/java/screen/AbstractAboutDialog.java @@ -30,11 +30,11 @@ public AbstractAboutDialog() lblProductDesc.setBounds(15, 8, 184, 25); lblProductDesc.setHorizontalAlignment(SwingConstants.CENTER); getContentPane().add(lblProductDesc); - JLabel lblCreatedByAlex = new JLabel("Created by Alex Burlton"); - lblCreatedByAlex.setFont(new Font("Tahoma", Font.PLAIN, 12)); - lblCreatedByAlex.setBounds(0, 29, 214, 25); - lblCreatedByAlex.setHorizontalAlignment(SwingConstants.CENTER); - getContentPane().add(lblCreatedByAlex); + JLabel lblCreatedBy = new JLabel("Created by Alyssa Burling"); + lblCreatedBy.setFont(new Font("Tahoma", Font.PLAIN, 12)); + lblCreatedBy.setBounds(0, 29, 214, 25); + lblCreatedBy.setHorizontalAlignment(SwingConstants.CENTER); + getContentPane().add(lblCreatedBy); lblViewChangelog.setBounds(65, 65, 84, 25); lblViewChangelog.setForeground(Color.BLUE); lblViewChangelog.setFont(new Font("Tahoma", Font.BOLD, 12)); diff --git a/client/src/main/java/screen/AbstractPreferencesPanel.java b/client/src/main/java/screen/AbstractPreferencesPanel.java deleted file mode 100644 index ba069429..00000000 --- a/client/src/main/java/screen/AbstractPreferencesPanel.java +++ /dev/null @@ -1,35 +0,0 @@ -package screen; - -import java.awt.event.ActionListener; - -import javax.swing.AbstractButton; -import javax.swing.JPanel; - -import util.Registry; - -public abstract class AbstractPreferencesPanel extends JPanel - implements Registry, - ActionListener -{ - protected PreferencesDialog parent = null; - - public abstract void initVariables(); - public abstract boolean valid(); - public abstract void savePreferences(); - - protected void toggleLockedComponent(AbstractButton c, String rewardsStr) - { - boolean unlocked = rewards.getBoolean(rewardsStr, false); - String text = unlocked? c.getText() : "Locked"; - String toolTipText = unlocked? c.getToolTipText() : ""; - - c.setText(text); - c.setToolTipText(toolTipText); - c.setEnabled(unlocked); - } - - public void setParent(PreferencesDialog parent) - { - this.parent = parent; - } -} diff --git a/client/src/main/java/screen/ClearDataDialog.java b/client/src/main/java/screen/ClearDataDialog.java index 039a4abc..27df28a2 100644 --- a/client/src/main/java/screen/ClearDataDialog.java +++ b/client/src/main/java/screen/ClearDataDialog.java @@ -1,6 +1,6 @@ package screen; -import achievement.AchievementSetting; +import screen.achievement.AchievementsDialog; import util.*; import javax.swing.*; @@ -9,7 +9,7 @@ import java.awt.event.ActionListener; import java.awt.event.WindowEvent; -import static util.ClientGlobals.achievementStore; +import static util.ClientGlobals.*; public class ClearDataDialog extends JDialog implements ActionListener, @@ -109,7 +109,7 @@ private void clearData() } achievementStore.clear(); - RegistryUtil.clearNode(rewards); + rewardStore.clear(); RegistryUtil.clearNode(savedGame); resetPreferences(); DialogUtilNew.showInfo("Achievements and statistics were reset successfully."); @@ -168,29 +168,12 @@ else if (!result.isEmpty()) private void removeStatisticsVariablesFromNode() { ScreenCache.get(MainScreen.class).resetStartTime(); - achievementStore.delete(AchievementSetting.TimePlayed); - achievementStore.delete(AchievementSetting.BestStreak); - achievementStore.delete(AchievementSetting.CurrentStreak); - achievementStore.delete(AchievementSetting.EntropyGamesPlayed); - achievementStore.delete(AchievementSetting.VectropyGamesPlayed); - achievementStore.delete(AchievementSetting.EntropyGamesWon); - achievementStore.delete(AchievementSetting.VectropyGamesWon); + achievementStore.clear(); } private void resetPreferences() { - prefs.remove(PREFERENCES_BOOLEAN_PLAY_BLIND); - prefs.remove(PREFERENCES_BOOLEAN_PLAY_WITH_HANDICAP); - prefs.remove(PREFERENCES_XML_API_SETTINGS); - prefs.remove(PREFERENCES_STRING_GAME_MODE); - prefs.remove(PREFERENCES_INT_HANDICAP_AMOUNT); - prefs.remove(SHARED_INT_JOKER_QUANTITY); - prefs.remove(SHARED_INT_JOKER_VALUE); - prefs.remove(PREFERENCES_STRING_CARD_BACKS); - prefs.remove(PREFERENCES_STRING_LOOK_AND_FEEL); - prefs.remove(PREFERENCES_STRING_DECK_DIRECTORY); - prefs.remove(PREFERENCES_STRING_JOKER_DIRECTORY); - prefs.remove(PREFERENCES_STRING_NUMBER_OF_COLOURS); + preferenceStore.clear(); } private void closeDialog() diff --git a/client/src/main/java/screen/ConfigureColumnsDialog.java b/client/src/main/java/screen/ConfigureColumnsDialog.java index f9fe80ed..1f9b20ce 100644 --- a/client/src/main/java/screen/ConfigureColumnsDialog.java +++ b/client/src/main/java/screen/ConfigureColumnsDialog.java @@ -8,11 +8,14 @@ import javax.swing.JDialog; import javax.swing.JPanel; +import preference.PreferenceSetting; import util.Debug; import util.Registry; +import static preference.PreferenceSettingKt.getPreference; +import static util.ClientGlobals.preferenceStore; + public class ConfigureColumnsDialog extends JDialog - implements Registry { private boolean showGameMode = false; private boolean showRounds = false; @@ -56,11 +59,11 @@ public ConfigureColumnsDialog() private void initVariables() { - showGameMode = prefs.getBoolean(PREFERENCES_BOOLEAN_INCLUDE_GAME_MODE_COLUMN, true); - showRounds = prefs.getBoolean(PREFERENCES_BOOLEAN_INCLUDE_ROUNDS_COLUMN, false); - showPlayers = prefs.getBoolean(PREFERENCES_BOOLEAN_INCLUDE_PLAYERS_COLUMN, true); - showCards = prefs.getBoolean(PREFERENCES_BOOLEAN_INCLUDE_CARDS_COLUMN, false); - showRoomName = prefs.getBoolean(PREFERENCES_BOOLEAN_INCLUDE_ROOM_NAME_COLUMN, false); + showGameMode = getPreference(PreferenceSetting.IncludeGameModeColumn); + showRounds = getPreference(PreferenceSetting.IncludeRoundsColumn); + showPlayers = getPreference(PreferenceSetting.IncludePlayersColumn); + showCards = getPreference(PreferenceSetting.IncludeCardsColumn); + showRoomName = getPreference(PreferenceSetting.IncludeRoomNameColumn); chckbxGameMode.setSelected(showGameMode); chckbxRounds.setSelected(showRounds); @@ -71,11 +74,11 @@ private void initVariables() private void saveSettings() { - prefs.putBoolean(PREFERENCES_BOOLEAN_INCLUDE_GAME_MODE_COLUMN, chckbxGameMode.isSelected()); - prefs.putBoolean(PREFERENCES_BOOLEAN_INCLUDE_ROOM_NAME_COLUMN, chckbxRoomName.isSelected()); - prefs.putBoolean(PREFERENCES_BOOLEAN_INCLUDE_ROUNDS_COLUMN, chckbxRounds.isSelected()); - prefs.putBoolean(PREFERENCES_BOOLEAN_INCLUDE_PLAYERS_COLUMN, chckbxPlayers.isSelected()); - prefs.putBoolean(PREFERENCES_BOOLEAN_INCLUDE_CARDS_COLUMN, chckbxCards.isSelected()); + preferenceStore.save(PreferenceSetting.IncludeGameModeColumn, chckbxGameMode.isSelected()); + preferenceStore.save(PreferenceSetting.IncludeRoomNameColumn, chckbxRoomName.isSelected()); + preferenceStore.save(PreferenceSetting.IncludeRoundsColumn, chckbxRounds.isSelected()); + preferenceStore.save(PreferenceSetting.IncludePlayersColumn, chckbxPlayers.isSelected()); + preferenceStore.save(PreferenceSetting.IncludeCardsColumn, chckbxCards.isSelected()); dispose(); } diff --git a/client/src/main/java/screen/EntropyBidPanel.java b/client/src/main/java/screen/EntropyBidPanel.java index fb637ef5..9add7466 100644 --- a/client/src/main/java/screen/EntropyBidPanel.java +++ b/client/src/main/java/screen/EntropyBidPanel.java @@ -24,11 +24,17 @@ import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; +import achievement.Reward; import game.EntropyBidAction; +import game.RenderingUtilKt; import game.Suit; +import preference.PreferenceSetting; import util.Debug; import util.Registry; +import static preference.PreferenceSettingKt.FOUR_COLOURS; +import static preference.PreferenceSettingKt.getPreference; + public class EntropyBidPanel extends BidPanel implements ActionListener, ChangeListener, @@ -181,7 +187,7 @@ public void init(int maxBid, int totalNumberOfCards, boolean online, boolean inc setBidButtonColours(); totalCardsLabel.setText("x " + totalNumberOfCards); - String back = prefs.get(PREFERENCES_STRING_CARD_BACKS, Registry.BACK_CODE_CLASSIC_BLUE); + String back = getPreference(PreferenceSetting.CardBacks); smallCardIcon.setIcon(new ImageIcon(EntropyScreen.class.getResource("/backs/" + back + "Small.png"))); } @@ -189,7 +195,7 @@ private void setIllegalButtonState() { if (!online) { - illegalAllowed |= rewards.getBoolean(REWARDS_BOOLEAN_ILLEGAL, false); + illegalAllowed |= Reward.Illegal.isUnlocked(); } btnIllegal.setVisible(illegalAllowed); @@ -265,7 +271,7 @@ private void updateSelectionForLastBidSuit() { @Override public void fireAppearancePreferencesChange() { - String back = prefs.get(PREFERENCES_STRING_CARD_BACKS, Registry.BACK_CODE_CLASSIC_BLUE); + String back = getPreference(PreferenceSetting.CardBacks); smallCardIcon.setIcon(new ImageIcon(EntropyScreen.class.getResource("/backs/" + back + "Small.png"))); updateBidAmountDisplay(); @@ -276,13 +282,13 @@ private void updateBidAmountDisplay() { String spaceStr = bidSuit == Suit.Moons ? "":" "; bidAmountDisplay.setText(bidSlider.getValue() + spaceStr + bidSuit.getUnicodeStr()); - bidAmountDisplay.setForeground(bidSuit.getColour()); + bidAmountDisplay.setForeground(RenderingUtilKt.getColour(bidSuit)); } private void setBidButtonColours() { - String numberOfColoursStr = prefs.get(PREFERENCES_STRING_NUMBER_OF_COLOURS, Registry.TWO_COLOURS); - boolean fourColours = (numberOfColoursStr.equals(Registry.FOUR_COLOURS)); + String numberOfColoursStr = getPreference(PreferenceSetting.NumberOfColours); + boolean fourColours = (numberOfColoursStr.equals(FOUR_COLOURS)); if (fourColours) { @@ -344,7 +350,7 @@ public void loadState(Preferences savedGame) String label = savedGame.get(SAVED_GAME_STRING_TOTAL_CARDS_LABEL, "0"); totalCardsLabel.setText(label); - String back = prefs.get(PREFERENCES_STRING_CARD_BACKS, Registry.BACK_CODE_CLASSIC_BLUE); + String back = getPreference(PreferenceSetting.CardBacks); smallCardIcon.setIcon(new ImageIcon(EntropyScreen.class.getResource("/backs/" + back + "Small.png"))); } diff --git a/client/src/main/java/screen/EntropyScreen.java b/client/src/main/java/screen/EntropyScreen.java index 58cab24b..eb9c7e92 100644 --- a/client/src/main/java/screen/EntropyScreen.java +++ b/client/src/main/java/screen/EntropyScreen.java @@ -6,12 +6,14 @@ import game.GameMode; import game.Suit; import object.EntropyAchievementsTracker; +import preference.PreferenceSetting; import util.Registry; import static game.CardsUtilKt.countSuit; import static game.CheatUtilKt.getMaxBidString; import static game.EntropyUtilKt.perfectBidAmount; import static game.EntropyUtilKt.perfectBidSuit; +import static preference.PreferenceSettingKt.getPreference; public class EntropyScreen extends GameScreen { @@ -22,7 +24,7 @@ public class EntropyScreen extends GameScreen public EntropyScreen() { setFocusable(true); - bidPanel = new EntropyBidPanel(prefs.get(PREFERENCES_STRING_PLAYER_NAME, "Player"), handPanel); + bidPanel = new EntropyBidPanel(getPreference(PreferenceSetting.PlayerName), handPanel); bidPanel.showBidPanel(false); setLayout(new BorderLayout(0, 0)); diff --git a/client/src/main/java/screen/GameScreen.java b/client/src/main/java/screen/GameScreen.java index e8be0f7b..a4d724da 100644 --- a/client/src/main/java/screen/GameScreen.java +++ b/client/src/main/java/screen/GameScreen.java @@ -1,9 +1,10 @@ package screen; import achievement.AchievementSetting; +import bean.BidListCellRenderer; import game.*; -import object.BidListCellRenderer; import object.Player; +import preference.PreferenceSetting; import util.*; import javax.swing.*; @@ -16,8 +17,10 @@ import static game.CheatUtilKt.containsNonJoker; import static game.RegistryUtilKt.populateActions; import static game.RegistryUtilKt.writeActions; +import static preference.PreferenceSettingKt.getPreference; import static screen.ScreenCacheKt.IN_GAME_REPLAY; import static util.ClientGlobals.achievementStore; +import static util.ClientGlobals.preferenceStore; import static utils.CoreGlobals.logger; public abstract class GameScreen> extends TransparentPanel @@ -305,16 +308,25 @@ else if (opponentOne.isEnabled()) private void getNewGameVariablesFromRegistry() { - playBlind = prefs.getBoolean(PREFERENCES_BOOLEAN_PLAY_BLIND, false); - playWithHandicap = prefs.getBoolean(PREFERENCES_BOOLEAN_PLAY_WITH_HANDICAP, false); - handicapAmount = prefs.getInt(PREFERENCES_INT_HANDICAP_AMOUNT, 1); - opponentTwo.setEnabled(prefs.getBoolean(PREFERENCES_BOOLEAN_OPPONENT_TWO_ENABLED, true)); - opponentThree.setEnabled(prefs.getBoolean(PREFERENCES_BOOLEAN_OPPONENT_THREE_ENABLED, true)); - opponentOne.setStrategy(prefs.get(PREFERENCES_STRING_OPPONENT_ONE_STRATEGY, "Basic")); - opponentTwo.setStrategy(prefs.get(PREFERENCES_STRING_OPPONENT_TWO_STRATEGY, "Basic")); - opponentThree.setStrategy(prefs.get(PREFERENCES_STRING_OPPONENT_THREE_STRATEGY, "Basic")); + playBlind = getPreference(PreferenceSetting.PlayBlind); + playWithHandicap = getPreference(PreferenceSetting.PlayWithHandicap); + handicapAmount = getPreference(PreferenceSetting.HandicapAmount); + opponentTwo.setEnabled(getPreference(PreferenceSetting.OpponentTwoEnabled)); + opponentThree.setEnabled(getPreference(PreferenceSetting.OpponentThreeEnabled)); + opponentOne.setStrategy(getPreference(PreferenceSetting.OpponentOneStrategy)); + opponentTwo.setStrategy(getPreference(PreferenceSetting.OpponentTwoStrategy)); + opponentThree.setStrategy(getPreference(PreferenceSetting.OpponentThreeStrategy)); - settings = GameSettings.fromRegistry(prefs, getGameMode()); + settings = new GameSettings( + getGameMode(), + getPreference(PreferenceSetting.StartingCards), + getPreference(PreferenceSetting.JokerQuantity), + getPreference(PreferenceSetting.JokerValue), + getPreference(PreferenceSetting.IncludeMoons), + getPreference(PreferenceSetting.IncludeStars), + getPreference(PreferenceSetting.NegativeJacks), + getPreference(PreferenceSetting.CardReveal), + true); handPanel.fireAppearancePreferencesChange(); handPanel.initPlayerNames(); @@ -430,12 +442,12 @@ protected void roundEnded(int playerLastToAct) else { currentlyOnChallenge = true; - boolean autoStart = prefs.getBoolean(PREFERENCES_BOOLEAN_AUTO_START_NEXT_ROUND, false); + boolean autoStart = getPreference(PreferenceSetting.AutoStartNextRound); if (autoStart) { - int seconds = prefs.getInt(PREFERENCES_INT_AUTO_START_SECONDS, 2); - nextRoundTimer.schedule(new NewRoundTask(), seconds * 1000); + int seconds = getPreference(PreferenceSetting.AutoStartSeconds); + nextRoundTimer.schedule(new NewRoundTask(), seconds * 1000L); } else { @@ -887,9 +899,7 @@ public void processCpuTurn(int opponentNumber) handPanel.selectPlayerInAwtThread(opponentNumber, true); bidPanel.enableBidPanel(false); - int gameSpeed = prefs.getInt(PREFERENCES_INT_GAME_SPEED, 1000); - - cpuTurn.schedule(new DelayedOpponentTurn(currentPlayer), gameSpeed); + cpuTurn.schedule(new DelayedOpponentTurn(currentPlayer), getPreference(PreferenceSetting.GameSpeed)); } private Collection allPlayers() { diff --git a/client/src/main/java/screen/HandPanelMk2.java b/client/src/main/java/screen/HandPanelMk2.java index 42f17bb2..8dec0a81 100644 --- a/client/src/main/java/screen/HandPanelMk2.java +++ b/client/src/main/java/screen/HandPanelMk2.java @@ -4,6 +4,7 @@ import object.CardLabel; import object.PlayerLabel; import online.screen.EntropyLobby; +import preference.PreferenceSetting; import util.*; import javax.swing.*; @@ -21,6 +22,7 @@ import java.util.prefs.Preferences; import static game.CardsUtilKt.isCardRelevant; +import static preference.PreferenceSettingKt.getPreference; public class HandPanelMk2 extends TransparentPanel implements ActionListener, @@ -738,10 +740,10 @@ public void fireAppearancePreferencesChange() public void initPlayerNames() { - playerName = prefs.get(PREFERENCES_STRING_PLAYER_NAME, "Player"); - opponentOneName = prefs.get(PREFERENCES_STRING_OPPONENT_ONE_NAME, "Mark"); - opponentTwoName = prefs.get(PREFERENCES_STRING_OPPONENT_TWO_NAME, "Dave"); - opponentThreeName = prefs.get(PREFERENCES_STRING_OPPONENT_THREE_NAME, "Tom"); + playerName = getPreference(PreferenceSetting.PlayerName); + opponentOneName = getPreference(PreferenceSetting.OpponentOneName); + opponentTwoName = getPreference(PreferenceSetting.OpponentTwoName); + opponentThreeName = getPreference(PreferenceSetting.OpponentThreeName); } public void loadPlayerNames(Preferences savedGame) diff --git a/client/src/main/java/screen/MainScreen.java b/client/src/main/java/screen/MainScreen.java index fb98d6cb..e1f2696d 100644 --- a/client/src/main/java/screen/MainScreen.java +++ b/client/src/main/java/screen/MainScreen.java @@ -2,15 +2,19 @@ import achievement.AchievementSetting; import achievement.AchievementUtilKt; +import achievement.Reward; import bean.AbstractDevScreen; +import bean.BidListCellRenderer; import game.GameMode; import game.PlayerAction; -import object.BidListCellRenderer; import object.Player; import online.screen.EntropyLobby; import online.screen.TestHarness; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import preference.PreferenceSetting; +import screen.achievement.AchievementsDialog; +import screen.preference.PreferencesDialog; import settings.Setting; import settings.SettingChangeListener; import util.*; @@ -30,6 +34,8 @@ import java.util.prefs.Preferences; import static achievement.AchievementUtilKt.getAchievementsEarned; +import static achievement.AchievementUtilKt.unlockRewards; +import static preference.PreferenceSettingKt.getPreference; import static screen.ScreenCacheKt.IN_GAME_REPLAY; import static screen.online.PlayOnlineDialogKt.showPlayOnlineDialog; import static util.ClientGlobals.achievementStore; @@ -258,7 +264,7 @@ public void startNewGame() { if (overwriteSavedGame() && quitCurrentGame()) { - gameMode = GameMode.valueOf(prefs.get(Registry.PREFERENCES_STRING_GAME_MODE, GameMode.Entropy.name())); + gameMode = GameMode.valueOf(getPreference(PreferenceSetting.GameMode)); selectGameScreen(gameMode); lblBidHistory.setVisible(true); btnReplay.setVisible(true); @@ -470,7 +476,7 @@ private void doStuffOnExit() private void saveGame() throws Throwable { - boolean autosave = prefs.getBoolean(Registry.PREFERENCES_BOOLEAN_AUTOSAVE, false); + boolean autosave = getPreference(PreferenceSetting.AutoSave); if (autosave) { @@ -648,7 +654,7 @@ private void selectGameScreen(GameMode gameMode) public boolean commandsEnabled() { return ClientUtil.devMode - || rewards.getBoolean(Registry.REWARDS_BOOLEAN_CHEATS, false); + || Reward.Cheats.isUnlocked(); } @Override @@ -720,7 +726,7 @@ else if (command.startsWith("unlock ")) { int spaceIndex = command.indexOf(' '); int achievements = Integer.parseInt(command.substring(spaceIndex+1)); - AchievementsUtil.unlockRewards(achievements); + unlockRewards(achievements); } else if (command.equals("stacks")) { @@ -751,7 +757,7 @@ public void onStart() setViewLogsVisibility(); restartTimers(); - AchievementsUtil.unlockRewards(getAchievementsEarned()); + unlockRewards(getAchievementsEarned()); } private void cleanUpReplayNodes() @@ -928,8 +934,8 @@ else if (source == mntmAchievements) } else if (source == mntmViewReplays) { - int width = prefs.getInt(Registry.PREFERENCES_INT_REPLAY_VIEWER_WIDTH, 875); - int height = prefs.getInt(Registry.PREFERENCES_INT_REPLAY_VIEWER_HEIGHT, 475); + int width = getPreference(PreferenceSetting.ReplayViewerWidth); + int height = getPreference(PreferenceSetting.ReplayViewerHeight); ReplayInterface replayInterface = ScreenCache.get(ReplayInterface.class); replayInterface.setTitle("Replay Viewer"); diff --git a/client/src/main/java/screen/PreferencesDialog.java b/client/src/main/java/screen/PreferencesDialog.java deleted file mode 100644 index 24aeced5..00000000 --- a/client/src/main/java/screen/PreferencesDialog.java +++ /dev/null @@ -1,143 +0,0 @@ -package screen; - -import java.awt.BorderLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.ArrayList; - -import javax.swing.BorderFactory; -import javax.swing.JButton; -import javax.swing.JDialog; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTabbedPane; -import javax.swing.SwingConstants; - -import game.GameMode; -import util.ApiUtil; -import util.Debug; -import util.Registry; - -/** - * Created by Alex Burlton (08/10/13) - */ -public class PreferencesDialog extends JDialog - implements Registry, - ActionListener -{ - public PreferencesDialog() - { - try - { - getContentPane().setLayout(new BorderLayout(0, 0)); - tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); - getContentPane().add(tabbedPane); - appearanceScrollPane.getVerticalScrollBar().setUnitIncrement(16); - tabbedPane.addTab("Gameplay", null, gameplayPanel, null); - tabbedPane.addTab("Players", null, playersPanel, null); - appearanceScrollPane.setViewportView(appearancePanel); - tabbedPane.addTab("Appearance", null, appearanceScrollPane, null); - tabbedPane.addTab("Miscellaneous", null, miscPanel, null); - getContentPane().add(okCancelPanel, BorderLayout.SOUTH); - okCancelPanel.setBorder(BorderFactory.createEmptyBorder(10, 150, 10, 150)); - okCancelPanel.setLayout(new BorderLayout(0, 0)); - okCancelPanel.add(btnOk, BorderLayout.WEST); - okCancelPanel.add(btnCancel, BorderLayout.EAST); - - btnOk.addActionListener(this); - btnCancel.addActionListener(this); - - initVariables(); - } - catch (Throwable t) - { - Debug.stackTrace(t); - } - } - - private final JTabbedPane tabbedPane = new JTabbedPane(SwingConstants.TOP); - private final PreferencesPanelGameplay gameplayPanel = new PreferencesPanelGameplay(); - private final JScrollPane appearanceScrollPane = new JScrollPane(); - private final PreferencesPanelAppearance appearancePanel = new PreferencesPanelAppearance(); - private final PreferencesPanelPlayers playersPanel = new PreferencesPanelPlayers(); - private final PreferencesPanelMisc miscPanel = new PreferencesPanelMisc(); - private final JPanel okCancelPanel = new JPanel(); - private final JButton btnOk = new JButton("Ok"); - private final JButton btnCancel = new JButton("Cancel"); - - public void initVariables() - { - ArrayList childPanels = getChildPanels(); - for (int i=0; i childPanels = getChildPanels(); - for (int i=0; i getChildPanels() - { - ArrayList ret = new ArrayList<>(); - - ret.add(gameplayPanel); - ret.add(appearancePanel); - ret.add(playersPanel); - ret.add(miscPanel); - - return ret; - } - - @Override - public void actionPerformed(ActionEvent arg0) - { - Object source = arg0.getSource(); - - if (source == btnOk) - { - if (valid()) - { - gameplayPanel.savePreferences(); - appearancePanel.savePreferences(); - playersPanel.savePreferences(); - miscPanel.savePreferences(); - closeDialog(); - } - } - else if (source == btnCancel) - { - closeDialog(); - } - else - { - Debug.stackTrace("Unexpected actionPerformed: " + source); - } - } - - private void closeDialog() - { - ApiUtil.clearCache(); - dispose(); - } -} \ No newline at end of file diff --git a/client/src/main/java/screen/PreferencesPanelAppearance.java b/client/src/main/java/screen/PreferencesPanelAppearance.java deleted file mode 100644 index 94946223..00000000 --- a/client/src/main/java/screen/PreferencesPanelAppearance.java +++ /dev/null @@ -1,426 +0,0 @@ -package screen; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.event.ActionEvent; -import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; -import java.util.Vector; - -import javax.swing.BorderFactory; -import javax.swing.ButtonGroup; -import javax.swing.ComboBoxModel; -import javax.swing.DefaultComboBoxModel; -import javax.swing.ImageIcon; -import javax.swing.JCheckBox; -import javax.swing.JComboBox; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JRadioButton; -import javax.swing.JSeparator; -import javax.swing.JTextPane; -import javax.swing.SwingConstants; -import javax.swing.UIManager; -import javax.swing.UIManager.LookAndFeelInfo; -import javax.swing.border.LineBorder; -import javax.swing.text.DefaultCaret; - -import bean.ComboBoxItem; -import object.DisabledComboBoxModel; -import util.GameUtil; - -public class PreferencesPanelAppearance extends AbstractPreferencesPanel - implements ItemListener -{ - private String deckDirectory = DECK_DIRECTORY_CLASSIC; - private String jokerDirectory = JOKER_DIRECTORY_CLASSIC; - private String cardBacks = BACK_CODE_CLASSIC_BLUE; - private String numberOfColours = FOUR_COLOURS; - private String lookAndFeel = DEFAULT_LOOK_AND_FEEL; - - public PreferencesPanelAppearance() - { - setPreferredSize(new Dimension(400, 760)); - setLayout(null); - - bgDeckDesign.add(rdbtnClassicDesign); - bgDeckDesign.add(rdbtnMinimalistDesign); - bgJokerDesign.add(rdbtnClassicJokers); - bgJokerDesign.add(rdbtnDeveloperJokers); - deckDesignPanel.setBounds(17, 80, 374, 58); - add(deckDesignPanel); - deckDesignPanel.setBorder(new LineBorder(Color.GRAY)); - deckDesignPanel.setLayout(null); - rdbtnClassicDesign.setBounds(6, 30, 72, 23); - deckDesignPanel.add(rdbtnClassicDesign); - rdbtnMinimalistDesign.setBounds(80, 30, 146, 23); - deckDesignPanel.add(rdbtnMinimalistDesign); - deckDesignPanel.add(lblCardDesign); - deckPreviewPanel.setBounds(17, 137, 374, 136); - add(deckPreviewPanel); - deckPreviewPanel.setBorder(new LineBorder(Color.GRAY)); - deckPreviewPanel.setLayout(null); - labelKh.setBounds(187, 20, 72, 96); - deckPreviewPanel.add(labelKh); - labelJc.setBounds(43, 20, 72, 96); - deckPreviewPanel.add(labelJc); - labelQd.setBounds(115, 20, 72, 96); - deckPreviewPanel.add(labelQd); - labelAs.setBounds(259, 20, 72, 96); - deckPreviewPanel.add(labelAs); - lblCardDesign.setHorizontalAlignment(SwingConstants.CENTER); - lblCardDesign.setFont(new Font("Tahoma", Font.BOLD, 14)); - lblCardDesign.setBounds(131, 8, 113, 17); - lblVisualPreferences.setHorizontalAlignment(SwingConstants.CENTER); - lblVisualPreferences.setBounds(178, 12, 72, 17); - add(lblVisualPreferences); - lblVisualPreferences.setFont(new Font("Tahoma", Font.PLAIN, 14)); - add(separator_1); - jokerDesignPanel.setLayout(null); - jokerDesignPanel.setBorder(new LineBorder(Color.GRAY)); - jokerDesignPanel.setBounds(17, 288, 374, 58); - add(jokerDesignPanel); - rdbtnClassicJokers.setBounds(6, 30, 72, 23); - jokerDesignPanel.add(rdbtnClassicJokers); - rdbtnDeveloperJokers.setBounds(80, 30, 102, 23); - jokerDesignPanel.add(rdbtnDeveloperJokers); - separator_1.setBounds(0, 38, 429, 2); - lblJokerDesign.setHorizontalAlignment(SwingConstants.CENTER); - lblJokerDesign.setFont(new Font("Tahoma", Font.BOLD, 14)); - lblJokerDesign.setBounds(136, 8, 102, 17); - jokerDesignPanel.add(lblJokerDesign); - jokerPreviewPanel.setLayout(null); - jokerPreviewPanel.setBorder(new LineBorder(Color.GRAY)); - jokerPreviewPanel.setBounds(17, 345, 374, 136); - add(jokerPreviewPanel); - labelJo2.setBounds(187, 20, 72, 96); - jokerPreviewPanel.add(labelJo2); - labelJo0.setBounds(43, 20, 72, 96); - jokerPreviewPanel.add(labelJo0); - labelJo1.setBounds(115, 20, 72, 96); - jokerPreviewPanel.add(labelJo1); - labelJo3.setBounds(259, 20, 72, 96); - jokerPreviewPanel.add(labelJo3); - cbFourColour.setBounds(17, 48, 135, 23); - add(cbFourColour); - backDesignPanel.setLayout(null); - backDesignPanel.setBorder(new LineBorder(Color.GRAY)); - backDesignPanel.setBounds(17, 496, 374, 114); - add(backDesignPanel); - lblCardBacks.setHorizontalAlignment(SwingConstants.CENTER); - lblCardBacks.setFont(new Font("Tahoma", Font.BOLD, 14)); - lblCardBacks.setBounds(127, 8, 102, 17); - backDesignPanel.add(lblCardBacks); - labelBack.setBounds(23, 9, 72, 96); - backDesignPanel.add(labelBack); - comboBoxBacks.setBounds(121, 46, 190, 22); - backDesignPanel.add(comboBoxBacks); - panelLookAndFeel.setLayout(null); - panelLookAndFeel.setBorder(new LineBorder(Color.GRAY)); - panelLookAndFeel.setBounds(17, 625, 374, 114); - add(panelLookAndFeel); - lblLookFeel.setHorizontalAlignment(SwingConstants.CENTER); - lblLookFeel.setFont(new Font("Tahoma", Font.BOLD, 14)); - lblLookFeel.setBounds(127, 8, 102, 17); - panelLookAndFeel.add(lblLookFeel); - comboBoxLookAndFeel.setBounds(86, 81, 190, 22); - panelLookAndFeel.add(comboBoxLookAndFeel); - DefaultCaret caret = new DefaultCaret(); - caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE); - txtpnLookAndFeelDisclaimer.setCaret(caret); - txtpnLookAndFeelDisclaimer.setText("Note: These options are experimental. You will need to restart for this to take effect."); - txtpnLookAndFeelDisclaimer.setBounds(10, 28, 354, 40); - txtpnLookAndFeelDisclaimer.setOpaque(false); - txtpnLookAndFeelDisclaimer.setBorder(BorderFactory.createEmptyBorder()); - txtpnLookAndFeelDisclaimer.setBackground(new Color(0,0,0,0)); - txtpnLookAndFeelDisclaimer.setEditable(false); - panelLookAndFeel.add(txtpnLookAndFeelDisclaimer); - - rdbtnClassicDesign.addActionListener(this); - rdbtnMinimalistDesign.addActionListener(this); - rdbtnClassicJokers.addActionListener(this); - rdbtnDeveloperJokers.addActionListener(this); - comboBoxBacks.addActionListener(this); - cbFourColour.addItemListener(this); - } - - private final JLabel lblVisualPreferences = new JLabel("Appearance"); - private final JSeparator separator_1 = new JSeparator(); - private final JPanel deckDesignPanel = new JPanel(); - private final ButtonGroup bgDeckDesign = new ButtonGroup(); - private final JLabel lblCardDesign = new JLabel("Card Design"); - private final JRadioButton rdbtnClassicDesign = new JRadioButton("Classic"); - private final JRadioButton rdbtnMinimalistDesign = new JRadioButton("Minimalist"); - private final JPanel deckPreviewPanel = new JPanel(); - private final JLabel labelJc = new JLabel(); - private final JLabel labelQd = new JLabel(); - private final JLabel labelKh = new JLabel(); - private final JLabel labelAs = new JLabel(); - private final JPanel jokerDesignPanel = new JPanel(); - private final ButtonGroup bgJokerDesign = new ButtonGroup(); - private final JRadioButton rdbtnClassicJokers = new JRadioButton("Classic"); - private final JRadioButton rdbtnDeveloperJokers = new JRadioButton("Developers"); - private final JLabel lblJokerDesign = new JLabel("Joker Design"); - private final JPanel jokerPreviewPanel = new JPanel(); - private final JLabel labelJo0 = new JLabel(); - private final JLabel labelJo1 = new JLabel(); - private final JLabel labelJo2 = new JLabel(); - private final JLabel labelJo3 = new JLabel(); - private final JCheckBox cbFourColour = new JCheckBox("Use 4 colour deck"); - private final JPanel backDesignPanel = new JPanel(); - private final JLabel lblCardBacks = new JLabel("Back Design"); - private final JComboBox> comboBoxBacks = new JComboBox<>(); - private final JComboBox comboBoxLookAndFeel = new JComboBox<>(); - private final JLabel labelBack = new JLabel(); - private final JLabel lblLookFeel = new JLabel("Look & Feel"); - private final JTextPane txtpnLookAndFeelDisclaimer = new JTextPane(); - private final JPanel panelLookAndFeel = new JPanel(); - - /** - * Abstract methods - */ - @Override - public void initVariables() - { - getVariablesFromPrefs(); - - selectRadioButtonsBasedOnDirectories(); - refreshDeckPreview(); - refreshJokerPreview(); - - selectCardBackBasedOnPreference(); - refreshCardBackPreview(); - setLookAndFeelComboBoxModel(); - - hideLockedFields(); - } - - @Override - public boolean valid() - { - return true; - } - - @Override - public void savePreferences() - { - prefs.put(PREFERENCES_STRING_DECK_DIRECTORY, deckDirectory); - prefs.put(PREFERENCES_STRING_JOKER_DIRECTORY, jokerDirectory); - prefs.put(PREFERENCES_STRING_NUMBER_OF_COLOURS, numberOfColours); - prefs.put(PREFERENCES_STRING_CARD_BACKS, cardBacks); - prefs.put(PREFERENCES_STRING_LOOK_AND_FEEL, (String)comboBoxLookAndFeel.getSelectedItem()); - - ScreenCache.get(MainScreen.class).fireAppearancePreferencesChange(); - } - - private void getVariablesFromPrefs() - { - deckDirectory = prefs.get(PREFERENCES_STRING_DECK_DIRECTORY, DECK_DIRECTORY_CLASSIC); - jokerDirectory = prefs.get(PREFERENCES_STRING_JOKER_DIRECTORY, JOKER_DIRECTORY_CLASSIC); - numberOfColours = prefs.get(PREFERENCES_STRING_NUMBER_OF_COLOURS, TWO_COLOURS); - cardBacks = prefs.get(PREFERENCES_STRING_CARD_BACKS, BACK_CODE_CLASSIC_BLUE); - lookAndFeel = prefs.get(PREFERENCES_STRING_LOOK_AND_FEEL, DEFAULT_LOOK_AND_FEEL); - } - - private void hideLockedFields() - { - toggleLockedComponent(cbFourColour, REWARDS_BOOLEAN_FOUR_COLOURS); - toggleLockedComponent(rdbtnMinimalistDesign, REWARDS_BOOLEAN_MINIMALIST_DECK); - toggleLockedComponent(rdbtnDeveloperJokers, REWARDS_BOOLEAN_DEVELOPER_JOKERS); - } - - private void refreshDeckPreview() - { - ImageIcon jackClubs = GameUtil.getImageForCard("Jc", deckDirectory, jokerDirectory, numberOfColours); - ImageIcon queenDiamonds = GameUtil.getImageForCard("Qd", deckDirectory, jokerDirectory, numberOfColours); - ImageIcon kingHearts = GameUtil.getImageForCard("Kh", deckDirectory, jokerDirectory, numberOfColours); - ImageIcon aceSpades = GameUtil.getImageForCard("As", deckDirectory, jokerDirectory, numberOfColours); - labelJc.setIcon(jackClubs); - labelQd.setIcon(queenDiamonds); - labelKh.setIcon(kingHearts); - labelAs.setIcon(aceSpades); - } - - private void refreshJokerPreview() - { - ImageIcon jo0 = GameUtil.getImageForCard("Jo0", deckDirectory, jokerDirectory, numberOfColours); - ImageIcon jo1 = GameUtil.getImageForCard("Jo1", deckDirectory, jokerDirectory, numberOfColours); - ImageIcon jo2 = GameUtil.getImageForCard("Jo2", deckDirectory, jokerDirectory, numberOfColours); - ImageIcon jo3 = GameUtil.getImageForCard("Jo3", deckDirectory, jokerDirectory, numberOfColours); - labelJo0.setIcon(jo0); - labelJo1.setIcon(jo1); - labelJo2.setIcon(jo2); - labelJo3.setIcon(jo3); - } - - private void selectCardBackBasedOnPreference() - { - Vector> backs = initialiseBacksVector(); - - ComboBoxModel> model = new DisabledComboBoxModel<>(backs); - comboBoxBacks.setModel(model); - - ComboBoxItem selectedItem = getSelectedItemForCode(backs, cardBacks); - if (selectedItem == null) - { - selectedItem = new ComboBoxItem<>(BACK_CODE_CLASSIC_BLUE, "Blue"); - } - - comboBoxBacks.setSelectedItem(selectedItem); - } - - private Vector> initialiseBacksVector() - { - Vector> backs = new Vector<>(); - - backs.addElement(new ComboBoxItem<>(BACK_CODE_CLASSIC_BLUE, "Blue")); - backs.addElement(new ComboBoxItem<>("backRed", "Red")); - - addIfUnlocked(backs, new ComboBoxItem<>("backGreen", "Green"), 5, REWARDS_BOOLEAN_FOUR_COLOURS); - addIfUnlocked(backs, new ComboBoxItem<>("backPurple", "Purple"), 10, REWARDS_BOOLEAN_NEGATIVE_JACKS); - addIfUnlocked(backs, new ComboBoxItem<>("backOrange", "Orange"), 15, REWARDS_BOOLEAN_BLIND); - addIfUnlocked(backs, new ComboBoxItem<>("backLightBlue", "Light Blue"), 20, REWARDS_BOOLEAN_MINIMALIST_DECK); - addIfUnlocked(backs, new ComboBoxItem<>("backPink", "Pink"), 25, REWARDS_BOOLEAN_VECTROPY); - addIfUnlocked(backs, new ComboBoxItem<>("backSilver", "Silver"), 30, REWARDS_BOOLEAN_CARD_REVEAL); - addIfUnlocked(backs, new ComboBoxItem<>("backGold", "Gold"), 35, REWARDS_BOOLEAN_EXTRA_SUITS); - addIfUnlocked(backs, new ComboBoxItem<>("backMatrix", "Matrix"), 40, REWARDS_BOOLEAN_ILLEGAL); - addIfUnlocked(backs, new ComboBoxItem<>("backCosmic", "Cosmic"), 45, REWARDS_BOOLEAN_DEVELOPER_JOKERS); - addIfUnlocked(backs, new ComboBoxItem<>("backRainbow", "Rainbow"), 50, REWARDS_BOOLEAN_CHEATS); - - return backs; - } - private void addIfUnlocked(Vector> backs, ComboBoxItem item, - int achievementsRequired, String rewardStr) - { - boolean unlocked = rewards.getBoolean(rewardStr, false); - if (unlocked) - { - backs.addElement(item); - } - else - { - ComboBoxItem disabledItem = new ComboBoxItem<>("", achievementsRequired + " achievements to unlock"); - disabledItem.setEnabled(false); - backs.addElement(disabledItem); - } - } - - private void setLookAndFeelComboBoxModel() - { - Vector backs = new Vector<>(); - for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) - { - String lookAndFeelName = info.getName(); - backs.add(lookAndFeelName); - } - - ComboBoxModel model = new DefaultComboBoxModel<>(backs); - comboBoxLookAndFeel.setModel(model); - comboBoxLookAndFeel.setSelectedItem(lookAndFeel); - } - - private ComboBoxItem getSelectedItemForCode(Vector> backs, String code) - { - int size = backs.size(); - for (int i=0; i back = backs.get(i); - String backCode = back.getHiddenData(); - - if (backCode.equals(code)) - { - return back; - } - } - - return null; - } - - @SuppressWarnings("unchecked") - private void refreshCardBackPreview() - { - ComboBoxItem selection = (ComboBoxItem)comboBoxBacks.getSelectedItem(); - if (selection == null) - { - cardBacks = BACK_CODE_CLASSIC_BLUE; - } - else - { - cardBacks = selection.getHiddenData(); - } - - ImageIcon back = new ImageIcon(getClass().getResource("/backs/" + cardBacks + ".png")); - labelBack.setIcon(back); - } - - private void selectRadioButtonsBasedOnDirectories() - { - cbFourColour.setSelected(numberOfColours.equals(FOUR_COLOURS)); - - if (deckDirectory.equals(DECK_DIRECTORY_CLASSIC)) - { - rdbtnClassicDesign.setSelected(true); - } - else if (deckDirectory.equals(DECK_DIRECTORY_ALTERNATE)) - { - rdbtnMinimalistDesign.setSelected(true); - } - - if (jokerDirectory.equals(JOKER_DIRECTORY_CLASSIC)) - { - rdbtnClassicJokers.setSelected(true); - } - else if (jokerDirectory.equals(JOKER_DIRECTORY_DEVELOPERS)) - { - rdbtnDeveloperJokers.setSelected(true); - } - } - - @Override - public void actionPerformed(ActionEvent arg0) - { - Object source = arg0.getSource(); - if (source == rdbtnClassicDesign) - { - deckDirectory = DECK_DIRECTORY_CLASSIC; - refreshDeckPreview(); - } - else if (source == rdbtnMinimalistDesign) - { - deckDirectory = DECK_DIRECTORY_ALTERNATE; - refreshDeckPreview(); - } - else if (source == rdbtnClassicJokers) - { - jokerDirectory = JOKER_DIRECTORY_CLASSIC; - refreshJokerPreview(); - } - else if (source == rdbtnDeveloperJokers) - { - jokerDirectory = JOKER_DIRECTORY_DEVELOPERS; - refreshJokerPreview(); - } - else if (source == comboBoxBacks) - { - refreshCardBackPreview(); - } - } - - @Override - public void itemStateChanged(ItemEvent arg0) - { - boolean enabled = cbFourColour.isSelected(); - if (enabled) - { - numberOfColours = FOUR_COLOURS; - } - else - { - numberOfColours = TWO_COLOURS; - } - - refreshDeckPreview(); - refreshJokerPreview(); - } -} diff --git a/client/src/main/java/screen/PreferencesPanelGameplay.java b/client/src/main/java/screen/PreferencesPanelGameplay.java deleted file mode 100644 index b158e5db..00000000 --- a/client/src/main/java/screen/PreferencesPanelGameplay.java +++ /dev/null @@ -1,330 +0,0 @@ -package screen; - -import java.awt.FlowLayout; -import java.awt.Font; -import java.awt.GridLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; - -import javax.swing.ButtonGroup; -import javax.swing.JCheckBox; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JRadioButton; -import javax.swing.JSeparator; -import javax.swing.JSlider; -import javax.swing.JSpinner; -import javax.swing.SpinnerNumberModel; -import javax.swing.border.EmptyBorder; -import javax.swing.border.TitledBorder; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; - -import game.GameMode; -import util.Debug; - -public class PreferencesPanelGameplay extends AbstractPreferencesPanel - implements ChangeListener, - ItemListener -{ - private GameMode gameMode = GameMode.Entropy; - private boolean includeJokers = false; - private int numberOfCards = 5; - private int jokerQuantity = 2; - private int jokerValue = 2; - private boolean playBlind = false; - private boolean playWithHandicap = false; - private int handicapAmount = 1; - private boolean includeStars = false; - private boolean includeMoons = false; - private boolean negativeJacks = false; - private boolean cardReveal = false; - - public PreferencesPanelGameplay() - { - setLayout(null); - separatorTitle.setBounds(0, 38, 429, 2); - add(separatorTitle); - lblGameplay.setBounds(184, 12, 60, 17); - add(lblGameplay); - lblGameplay.setFont(new Font("Tahoma", Font.PLAIN, 14)); - lblWarning.setBounds(65, 395, 304, 14); - add(lblWarning); - lblWarning.setFont(new Font("Tahoma", Font.ITALIC, 11)); - panelGameMode.setBorder(new TitledBorder(null, "Mode", TitledBorder.LEADING, TitledBorder.TOP, null, null)); - panelGameMode.setBounds(20, 51, 165, 73); - add(panelGameMode); - panelGameMode.setLayout(new FlowLayout(FlowLayout.LEADING, 5, 10)); - panelGameMode.add(rdbtnEntropy); - rdbtnEntropy.setFont(new Font("Tahoma", Font.PLAIN, 11)); - bgMode.add(rdbtnEntropy); - panelGameMode.add(rdbtnVectropy); - rdbtnVectropy.setFont(new Font("Tahoma", Font.PLAIN, 11)); - bgMode.add(rdbtnVectropy); - panelDeck.setBorder(new TitledBorder(null, "Deck", TitledBorder.LEADING, TitledBorder.TOP, null, null)); - panelDeck.setBounds(20, 253, 393, 131); - add(panelDeck); - panelDeck.setLayout(new GridLayout(0, 1, 0, 0)); - FlowLayout fl_panelJokers = (FlowLayout) panelJokers.getLayout(); - fl_panelJokers.setAlignment(FlowLayout.LEFT); - panelJokers.setBorder(new EmptyBorder(0, -5, 0, 0)); - panelDeck.add(panelJokers); - panelJokers.add(cbJokers); - cbJokers.setFont(new Font("Tahoma", Font.PLAIN, 11)); - jokerQuantitySpinner.setFont(new Font("Tahoma", Font.PLAIN, 11)); - panelJokers.add(jokerQuantitySpinner); - lblWorth.setFont(new Font("Tahoma", Font.PLAIN, 11)); - panelJokers.add(lblWorth); - jokerValueSpinner.setFont(new Font("Tahoma", Font.PLAIN, 11)); - panelJokers.add(jokerValueSpinner); - cbJokers.addItemListener(this); - panelDeck.add(cbNegativeJacks); - cbNegativeJacks.setSelected(false); - cbNegativeJacks.setFont(new Font("Tahoma", Font.PLAIN, 11)); - panelDeck.add(cbIncludeMoons); - cbIncludeMoons.setFont(new Font("Tahoma", Font.PLAIN, 11)); - panelDeck.add(cbIncludeStars); - cbIncludeStars.setFont(new Font("Tahoma", Font.PLAIN, 11)); - panelGameplay.setBorder(new TitledBorder(null, "Gameplay", TitledBorder.LEADING, TitledBorder.TOP, null, null)); - panelGameplay.setBounds(20, 135, 393, 107); - add(panelGameplay); - panelGameplay.setLayout(new GridLayout(0, 1, 0, 0)); - handicapPanel.setBorder(new EmptyBorder(0, -5, 0, 0)); - FlowLayout flowLayout_1 = (FlowLayout) handicapPanel.getLayout(); - flowLayout_1.setAlignment(FlowLayout.LEADING); - panelGameplay.add(handicapPanel); - handicapPanel.add(cbHandicap); - cbHandicap.setFont(new Font("Tahoma", Font.PLAIN, 11)); - cbHandicap.setToolTipText("Start with fewer cards than your opponents."); - handicapAmountSpinner.setFont(new Font("Tahoma", Font.PLAIN, 11)); - handicapPanel.add(handicapAmountSpinner); - handicapAmountSpinner.setToolTipText("Start with this many cards less than your opponents."); - cbHandicap.addItemListener(this); - panelGameplay.add(cbPlayBlind); - cbPlayBlind.setFont(new Font("Tahoma", Font.PLAIN, 11)); - cbPlayBlind.setToolTipText("Your hand will be face-down each round until you choose to view it manually."); - cbPlayersRevealCards.setFont(new Font("Tahoma", Font.PLAIN, 11)); - panelGameplay.add(cbPlayersRevealCards); - panelStartingCards.setBorder(new TitledBorder(null, "Starting cards", TitledBorder.LEADING, TitledBorder.TOP, null, null)); - panelStartingCards.setBounds(195, 51, 218, 73); - add(panelStartingCards); - numberOfCardsSlider.setFont(new Font("Tahoma", Font.PLAIN, 11)); - panelStartingCards.add(numberOfCardsSlider); - numberOfCardsSlider.setMinorTickSpacing(1); - numberOfCardsSlider.setPaintTicks(true); - numberOfCardsSlider.setPaintLabels(true); - numberOfCardsSlider.setMajorTickSpacing(4); - numberOfCardsSlider.setToolTipText(""); - numberOfCardsSlider.setMinimum(1); - numberOfCardsSlider.setMaximum(5); - numberOfCardsSlider.addChangeListener(this); - handicapAmountSpinner.addChangeListener(this); - - rdbtnEntropy.addActionListener(this); - rdbtnVectropy.addActionListener(this); - } - - private final JLabel lblGameplay = new JLabel("Gameplay"); - private final JSeparator separatorTitle = new JSeparator(); - private final JPanel panelGameMode = new JPanel(); - private final ButtonGroup bgMode = new ButtonGroup(); - private final JRadioButton rdbtnEntropy = new JRadioButton("Entropy"); - private final JRadioButton rdbtnVectropy = new JRadioButton("Vectropy"); - private final JPanel panelStartingCards = new JPanel(); - private final JSlider numberOfCardsSlider = new JSlider(); - private final JPanel panelGameplay = new JPanel(); - private final JPanel handicapPanel = new JPanel(); - private final JCheckBox cbHandicap = new JCheckBox("Handicap:"); - private final JSpinner handicapAmountSpinner = new JSpinner(); - private final JCheckBox cbPlayBlind = new JCheckBox("Play Blind"); - private final JCheckBox cbPlayersRevealCards = new JCheckBox("Players reveal cards"); - private final JPanel panelDeck = new JPanel(); - private final JPanel panelJokers = new JPanel(); - private final JCheckBox cbJokers = new JCheckBox("Jokers"); - private final JSpinner jokerQuantitySpinner = new JSpinner(); - private final JLabel lblWorth = new JLabel("worth"); - private final JSpinner jokerValueSpinner = new JSpinner(); - private final JCheckBox cbNegativeJacks = new JCheckBox("Jacks worth -1"); - private final JCheckBox cbIncludeMoons = new JCheckBox("Include Moons"); - private final JCheckBox cbIncludeStars = new JCheckBox("Include Stars"); - private final JLabel lblWarning = new JLabel("Note: Changes will not take effect until you start a new game."); - - @Override - public void initVariables() - { - getVariablesFromPreferences(); - - cbJokers.setSelected(includeJokers); - cbNegativeJacks.setSelected(negativeJacks); - cbPlayersRevealCards.setSelected(cardReveal); - jokerQuantitySpinner.setModel(new SpinnerNumberModel(jokerQuantity, 1, 4, 1)); - jokerValueSpinner.setModel(new SpinnerNumberModel(jokerValue, 2, 4, 1)); - numberOfCardsSlider.setValue(numberOfCards); - jokerQuantitySpinner.setValue(jokerQuantity); - jokerValueSpinner.setValue(jokerValue); - cbPlayBlind.setSelected(playBlind); - cbHandicap.setSelected(playWithHandicap); - jokerQuantitySpinner.setEnabled(includeJokers); - lblWorth.setEnabled(includeJokers); - jokerValueSpinner.setEnabled(includeJokers); - handicapAmountSpinner.setEnabled(playWithHandicap); - - adjustHandicapSpinner(); - - cbIncludeStars.setSelected(includeStars); - cbIncludeMoons.setSelected(includeMoons); - - rdbtnEntropy.setSelected(gameMode == GameMode.Entropy); - rdbtnVectropy.setSelected(gameMode == GameMode.Vectropy); - - hideLockedFields(); - } - - @Override - public boolean valid() - { - return true; - } - - @Override - public void savePreferences() - { - numberOfCards = numberOfCardsSlider.getValue(); - negativeJacks = cbNegativeJacks.isSelected(); - cardReveal = cbPlayersRevealCards.isSelected(); - jokerQuantity = includeJokers ? (int) jokerQuantitySpinner.getValue() : 0; - jokerValue = (int) jokerValueSpinner.getValue(); - handicapAmount = (int) handicapAmountSpinner.getValue(); - playBlind = cbPlayBlind.isSelected(); - includeStars = cbIncludeStars.isSelected(); - includeMoons = cbIncludeMoons.isSelected(); - - prefs.putInt(SHARED_INT_NUMBER_OF_CARDS, numberOfCards); - prefs.putBoolean(SHARED_BOOLEAN_NEGATIVE_JACKS, negativeJacks); - prefs.putInt(SHARED_INT_JOKER_QUANTITY, jokerQuantity); - prefs.putInt(SHARED_INT_JOKER_VALUE, jokerValue); - prefs.putBoolean(PREFERENCES_BOOLEAN_PLAY_WITH_HANDICAP, playWithHandicap); - prefs.putInt(PREFERENCES_INT_HANDICAP_AMOUNT, handicapAmount); - prefs.putBoolean(PREFERENCES_BOOLEAN_PLAY_BLIND, playBlind); - prefs.putBoolean(SHARED_BOOLEAN_INCLUDE_STARS, includeStars); - prefs.putBoolean(SHARED_BOOLEAN_INCLUDE_MOONS, includeMoons); - prefs.putBoolean(SHARED_BOOLEAN_CARD_REVEAL, cardReveal); - prefs.put(PREFERENCES_STRING_GAME_MODE, gameMode.name()); - } - - private void getVariablesFromPreferences() - { - numberOfCards = prefs.getInt(SHARED_INT_NUMBER_OF_CARDS, 5); - jokerQuantity = prefs.getInt(SHARED_INT_JOKER_QUANTITY, 2); - includeJokers = jokerQuantity > 0; - jokerValue = prefs.getInt(SHARED_INT_JOKER_VALUE, 2); - playWithHandicap = prefs.getBoolean(PREFERENCES_BOOLEAN_PLAY_WITH_HANDICAP, false); - handicapAmount = Math.max(prefs.getInt(PREFERENCES_INT_HANDICAP_AMOUNT, 1), 1); - playBlind = prefs.getBoolean(PREFERENCES_BOOLEAN_PLAY_BLIND, false); - includeStars = prefs.getBoolean(SHARED_BOOLEAN_INCLUDE_STARS, false); - includeMoons = prefs.getBoolean(SHARED_BOOLEAN_INCLUDE_MOONS, false); - negativeJacks = prefs.getBoolean(SHARED_BOOLEAN_NEGATIVE_JACKS, false); - cardReveal = prefs.getBoolean(SHARED_BOOLEAN_CARD_REVEAL, false); - gameMode = GameMode.valueOf(prefs.get(PREFERENCES_STRING_GAME_MODE, GameMode.Entropy.name())); - } - - private void adjustHandicapSpinner() - { - if (numberOfCards == 1) - { - cbHandicap.setSelected(false); - cbHandicap.setEnabled(false); - handicapAmountSpinner.setEnabled(false); - } - else - { - cbHandicap.setEnabled(true); - handicapAmountSpinner.setEnabled(cbHandicap.isSelected()); - - int newMax = numberOfCards - 1; - if (handicapAmount > newMax) - { - handicapAmount = newMax; - } - - handicapAmountSpinner.setModel(new SpinnerNumberModel(handicapAmount, 1, newMax, 1)); - } - } - - private void hideLockedFields() - { - toggleLockedComponent(cbNegativeJacks, REWARDS_BOOLEAN_NEGATIVE_JACKS); - toggleLockedComponent(cbPlayBlind, REWARDS_BOOLEAN_BLIND); - toggleLockedComponent(rdbtnVectropy, REWARDS_BOOLEAN_VECTROPY); - toggleLockedComponent(cbPlayersRevealCards, REWARDS_BOOLEAN_CARD_REVEAL); - toggleLockedComponent(cbIncludeMoons, REWARDS_BOOLEAN_EXTRA_SUITS); - toggleLockedComponent(cbIncludeStars, REWARDS_BOOLEAN_EXTRA_SUITS); - } - - @Override - public void actionPerformed(ActionEvent arg0) - { - GameMode originalGameMode = gameMode; - - Object source = arg0.getSource(); - if (source == rdbtnEntropy) - { - gameMode = GameMode.Entropy; - } - else if (source == rdbtnVectropy) - { - gameMode = GameMode.Vectropy; - } - - if (originalGameMode != gameMode) - { - parent.gameModeChanged(gameMode); - } - } - - @Override - public void stateChanged(ChangeEvent arg0) - { - Object source = arg0.getSource(); - if (source == numberOfCardsSlider) - { - if (!numberOfCardsSlider.getValueIsAdjusting()) - { - numberOfCards = numberOfCardsSlider.getValue(); - adjustHandicapSpinner(); - } - } - else if (source == handicapAmountSpinner) - { - handicapAmount = (int)handicapAmountSpinner.getValue(); - } - else - { - Debug.stackTrace("Unexpected stateChanged: [" + source + "]"); - } - - } - - @Override - public void itemStateChanged(ItemEvent arg0) - { - Object source = arg0.getSource(); - if (source == cbJokers) - { - includeJokers = cbJokers.isSelected(); - lblWorth.setEnabled(includeJokers); - jokerQuantitySpinner.setEnabled(includeJokers); - jokerValueSpinner.setEnabled(includeJokers); - } - else if (source == cbHandicap) - { - playWithHandicap = cbHandicap.isSelected(); - handicapAmountSpinner.setEnabled(playWithHandicap); - } - else - { - Debug.stackTrace("Unexpected itemStateChanged: [" + source + "]"); - } - } -} \ No newline at end of file diff --git a/client/src/main/java/screen/PreferencesPanelMisc.java b/client/src/main/java/screen/PreferencesPanelMisc.java deleted file mode 100644 index dea054de..00000000 --- a/client/src/main/java/screen/PreferencesPanelMisc.java +++ /dev/null @@ -1,308 +0,0 @@ -package screen; - -import java.awt.Font; -import java.awt.event.ActionEvent; -import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; -import java.io.File; - -import javax.swing.ButtonGroup; -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JFileChooser; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JRadioButton; -import javax.swing.JSeparator; -import javax.swing.JSpinner; -import javax.swing.JTextField; -import javax.swing.SpinnerNumberModel; -import javax.swing.SwingConstants; - -import util.Debug; -import util.DialogUtil; -import util.Registry; -import util.ReplayFileUtil; - -public class PreferencesPanelMisc extends AbstractPreferencesPanel - implements ItemListener -{ - private static final int GAME_SPEED_SLOW = 1500; - private static final int GAME_SPEED_MEDIUM = 1000; - private static final int GAME_SPEED_FAST = 500; - - private boolean autosave = false; - private int gameSpeed = GAME_SPEED_MEDIUM; - private boolean saveReplays = false; - private String replayDirectory = ""; - private int replayDefault = OPEN_ON_FIRST_ROUND; - private boolean autoStartNextRound = false; - private int autoStartSeconds = 2; //2 seconds - private boolean popUpRoomsOnline = true; - private boolean checkForUpdates = true; - - public PreferencesPanelMisc() - { - setLayout(null); - - bgReplayRound.add(rdbtnFirstRound); - bgReplayRound.add(rdbtnLastRound); - bgSpeed.add(rdbtnSlow); - bgSpeed.add(rdbtnMedium); - bgSpeed.add(rdbtnFast); - chckbxSaveReplays.setFont(new Font("Tahoma", Font.PLAIN, 11)); - chckbxSaveReplays.setBounds(20, 67, 91, 22); - add(chckbxSaveReplays); - lblOtherOptions.setFont(new Font("Tahoma", Font.PLAIN, 14)); - lblOtherOptions.setBounds(171, 12, 86, 17); - add(lblOtherOptions); - separator_3.setBounds(0, 38, 429, 2); - add(separator_3); - chosenDirectory.setBounds(116, 67, 180, 22); - chosenDirectory.setEditable(false); - add(chosenDirectory); - chosenDirectory.setColumns(10); - btnSelectDirectory.setBounds(296, 67, 20, 22); - add(btnSelectDirectory); - chckbxAutosave.setBounds(20, 180, 127, 22); - add(chckbxAutosave); - chckbxAutosave.setFont(new Font("Tahoma", Font.PLAIN, 11)); - lblReplayViewerDefaults.setFont(new Font("Tahoma", Font.PLAIN, 11)); - lblReplayViewerDefaults.setBounds(20, 112, 127, 14); - add(lblReplayViewerDefaults); - rdbtnFirstRound.setFont(new Font("Tahoma", Font.PLAIN, 11)); - rdbtnFirstRound.setBounds(144, 109, 91, 20); - add(rdbtnFirstRound); - rdbtnLastRound.setFont(new Font("Tahoma", Font.PLAIN, 11)); - rdbtnLastRound.setBounds(237, 109, 91, 20); - add(rdbtnLastRound); - lblGameSpeed.setBounds(20, 148, 86, 14); - add(lblGameSpeed); - lblGameSpeed.setHorizontalAlignment(SwingConstants.LEFT); - lblGameSpeed.setFont(new Font("Tahoma", Font.PLAIN, 11)); - rdbtnSlow.setBounds(144, 144, 60, 20); - add(rdbtnSlow); - rdbtnSlow.setFont(new Font("Tahoma", Font.PLAIN, 11)); - rdbtnMedium.setBounds(206, 144, 70, 20); - add(rdbtnMedium); - rdbtnMedium.setFont(new Font("Tahoma", Font.PLAIN, 11)); - rdbtnFast.setBounds(274, 144, 54, 20); - add(rdbtnFast); - rdbtnFast.setFont(new Font("Tahoma", Font.PLAIN, 11)); - chckbxAutoStartNextRound.setFont(new Font("Tahoma", Font.PLAIN, 11)); - chckbxAutoStartNextRound.setBounds(20, 205, 208, 23); - add(chckbxAutoStartNextRound); - chckbxPopUpRooms.setFont(new Font("Tahoma", Font.PLAIN, 11)); - chckbxPopUpRooms.setBounds(20, 230, 208, 23); - add(chckbxPopUpRooms); - spinnerAutoStartSeconds.setBounds(228, 205, 38, 22); - add(spinnerAutoStartSeconds); - lblSeconds.setFont(new Font("Tahoma", Font.PLAIN, 11)); - lblSeconds.setBounds(275, 206, 55, 20); - add(lblSeconds); - chckbxCheckForUpdates.setFont(new Font("Tahoma", Font.PLAIN, 11)); - chckbxCheckForUpdates.setBounds(20, 256, 237, 23); - add(chckbxCheckForUpdates); - fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); - - rdbtnFast.addActionListener(this); - rdbtnMedium.addActionListener(this); - rdbtnSlow.addActionListener(this); - btnSelectDirectory.addActionListener(this); - chckbxSaveReplays.addItemListener(this); - chckbxAutoStartNextRound.addItemListener(this); - } - - private final JLabel lblOtherOptions = new JLabel("Other Options"); - private final JSeparator separator_3 = new JSeparator(); - private final JFileChooser fc = new JFileChooser(); - private final JTextField chosenDirectory = new JTextField(); - private final JCheckBox chckbxSaveReplays = new JCheckBox("Save replays"); - private final JButton btnSelectDirectory = new JButton("..."); - private final JCheckBox chckbxAutosave = new JCheckBox("Autosave on exit"); - private final ButtonGroup bgSpeed = new ButtonGroup(); - private final JRadioButton rdbtnSlow = new JRadioButton("Slow"); - private final JRadioButton rdbtnMedium = new JRadioButton("Medium"); - private final JRadioButton rdbtnFast = new JRadioButton("Fast"); - private final JLabel lblGameSpeed = new JLabel("Game speed"); - private final JCheckBox chckbxAutoStartNextRound = new JCheckBox("Automatically start next round after"); - private final JCheckBox chckbxPopUpRooms = new JCheckBox("Pop up online rooms on my turn"); - private final JSpinner spinnerAutoStartSeconds = new JSpinner(); - private final JLabel lblSeconds = new JLabel("seconds"); - private final JLabel lblReplayViewerDefaults = new JLabel("Replay viewer default"); - private final ButtonGroup bgReplayRound = new ButtonGroup(); - private final JRadioButton rdbtnFirstRound = new JRadioButton("First Round"); - private final JRadioButton rdbtnLastRound = new JRadioButton("Last Round"); - private final JCheckBox chckbxCheckForUpdates = new JCheckBox("Automatically check for updates"); - - /** - * Abstract methods - */ - @Override - public void initVariables() - { - getVariablesFromPrefs(); - - spinnerAutoStartSeconds.setModel(new SpinnerNumberModel(autoStartSeconds, 1, 5, 1)); - chosenDirectory.setText(replayDirectory + "\\Replays"); - chckbxAutosave.setSelected(autosave); - rdbtnSlow.setSelected(gameSpeed == GAME_SPEED_SLOW); - rdbtnMedium.setSelected(gameSpeed == GAME_SPEED_MEDIUM); - rdbtnFast.setSelected(gameSpeed == GAME_SPEED_FAST); - chckbxSaveReplays.setSelected(saveReplays); - chosenDirectory.setText(replayDirectory + "\\Replays"); - chosenDirectory.setEnabled(saveReplays); - btnSelectDirectory.setEnabled(saveReplays); - chckbxAutoStartNextRound.setSelected(autoStartNextRound); - chckbxPopUpRooms.setSelected(popUpRoomsOnline); - chckbxCheckForUpdates.setSelected(checkForUpdates); - spinnerAutoStartSeconds.setEnabled(autoStartNextRound); - lblSeconds.setEnabled(autoStartNextRound); - spinnerAutoStartSeconds.setValue(autoStartSeconds); - rdbtnFirstRound.setSelected(replayDefault == Registry.OPEN_ON_FIRST_ROUND); - rdbtnLastRound.setSelected(replayDefault == Registry.OPEN_ON_LAST_ROUND); - } - - @Override - public boolean valid() - { - return confirmChangeOfDirectory(); - } - - @Override - public void savePreferences() - { - autosave = chckbxAutosave.isSelected(); - replayDefault = rdbtnFirstRound.isSelected() ? Registry.OPEN_ON_FIRST_ROUND:Registry.OPEN_ON_LAST_ROUND; - autoStartSeconds = (int)spinnerAutoStartSeconds.getValue(); - popUpRoomsOnline = chckbxPopUpRooms.isSelected(); - checkForUpdates = chckbxCheckForUpdates.isSelected(); - - prefs.putBoolean(PREFERENCES_BOOLEAN_SAVE_REPLAYS, saveReplays); - prefs.putBoolean(PREFERENCES_BOOLEAN_AUTOSAVE, autosave); - prefs.put(PREFERENCES_STRING_REPLAY_DIRECTORY, replayDirectory); - prefs.putInt(PREFERENCES_INT_REPLAY_DEFAULT, replayDefault); - prefs.putBoolean(PREFERENCES_BOOLEAN_AUTO_START_NEXT_ROUND, autoStartNextRound); - prefs.putInt(PREFERENCES_INT_AUTO_START_SECONDS, autoStartSeconds); - prefs.putBoolean(PREFERENCES_BOOLEAN_POP_UP_ROOMS, popUpRoomsOnline); - prefs.putBoolean(PREFERENCES_BOOLEAN_CHECK_FOR_UPDATES, checkForUpdates); - prefs.putInt(PREFERENCES_INT_GAME_SPEED, gameSpeed); - } - - private void getVariablesFromPrefs() - { - autosave = prefs.getBoolean(PREFERENCES_BOOLEAN_AUTOSAVE, false); - gameSpeed = prefs.getInt(PREFERENCES_INT_GAME_SPEED, GAME_SPEED_MEDIUM); - saveReplays = prefs.getBoolean(PREFERENCES_BOOLEAN_SAVE_REPLAYS, false); - replayDirectory = prefs.get(PREFERENCES_STRING_REPLAY_DIRECTORY, System.getProperty("user.dir")); - replayDefault = prefs.getInt(PREFERENCES_INT_REPLAY_DEFAULT, Registry.OPEN_ON_LAST_ROUND); - autoStartNextRound = prefs.getBoolean(PREFERENCES_BOOLEAN_AUTO_START_NEXT_ROUND, false); - autoStartSeconds = prefs.getInt(PREFERENCES_INT_AUTO_START_SECONDS, 2); - popUpRoomsOnline = prefs.getBoolean(PREFERENCES_BOOLEAN_POP_UP_ROOMS, true); - checkForUpdates = prefs.getBoolean(PREFERENCES_BOOLEAN_CHECK_FOR_UPDATES, true); - } - - private boolean confirmChangeOfDirectory() - { - String originalReplayDirectory = prefs.get(PREFERENCES_STRING_REPLAY_DIRECTORY, System.getProperty("user.dir")); - - File[] myExistingFiles = new File(originalReplayDirectory + "//Replays//" + ReplayFileUtil.FOLDER_PERSONAL_REPLAYS).listFiles(); - int myExistingFilesLength = 0; - if (myExistingFiles != null) - { - myExistingFilesLength = myExistingFiles.length; - } - - File[] importedExistingFiles = new File(originalReplayDirectory + "//Replays//"+ ReplayFileUtil.FOLDER_IMPORTED_REPLAYS).listFiles(); - int importedExistingFilesLength = 0; - if (importedExistingFiles != null) - { - importedExistingFilesLength = importedExistingFiles.length; - } - - if (!replayDirectory.equals(originalReplayDirectory) && (myExistingFilesLength != 0 || importedExistingFilesLength != 0)) - { - int choice = DialogUtil.showQuestion("You have changed your replay directory but there are still files in the old one. " - + "\nWould you like to move these files to the new location?", true); - - if (choice == JOptionPane.YES_OPTION) - { - ReplayFileUtil.moveReplays(myExistingFiles, importedExistingFiles, originalReplayDirectory, replayDirectory); - } - else if (choice == JOptionPane.CANCEL_OPTION) - { - return false; - } - else - { - DialogUtil.showInfo("Existing replay files were left in the old directory and will have to be deleted or moved manually."); - } - } - - return true; - } - - private void selectReplayDirectory() - { - try - { - int returnVal = fc.showOpenDialog(this); - if (returnVal == JFileChooser.APPROVE_OPTION) - { - File file = fc.getSelectedFile(); - - replayDirectory = file.getPath(); - chosenDirectory.setText(replayDirectory + "\\Replays"); - Debug.append("Selected " + file.getPath() + " as replay directory.", true); - } - else - { - Debug.append("Directory selection cancelled by user.", true); - } - } - catch (Throwable t) - { - Debug.stackTrace(t); - } - } - - @Override - public void actionPerformed(ActionEvent arg0) - { - Object source = arg0.getSource(); - if (source == rdbtnFast) - { - gameSpeed = GAME_SPEED_FAST; - } - else if (source == rdbtnMedium) - { - gameSpeed = GAME_SPEED_MEDIUM; - } - else if (source == rdbtnSlow) - { - gameSpeed = GAME_SPEED_SLOW; - } - else if (source == btnSelectDirectory) - { - selectReplayDirectory(); - } - } - - @Override - public void itemStateChanged(ItemEvent arg0) - { - Object source = arg0.getSource(); - if (source == chckbxSaveReplays) - { - saveReplays = chckbxSaveReplays.isSelected(); - chosenDirectory.setEnabled(saveReplays); - btnSelectDirectory.setEnabled(saveReplays); - } - else if (source == chckbxAutoStartNextRound) - { - autoStartNextRound = chckbxAutoStartNextRound.isSelected(); - lblSeconds.setEnabled(autoStartNextRound); - spinnerAutoStartSeconds.setEnabled(autoStartNextRound); - } - } -} \ No newline at end of file diff --git a/client/src/main/java/screen/PreferencesPanelPlayers.java b/client/src/main/java/screen/PreferencesPanelPlayers.java deleted file mode 100644 index fc82bc20..00000000 --- a/client/src/main/java/screen/PreferencesPanelPlayers.java +++ /dev/null @@ -1,464 +0,0 @@ -package screen; - -import java.awt.Font; -import java.awt.Point; -import java.awt.event.ActionEvent; -import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.util.ArrayList; -import java.util.Vector; - -import javax.swing.ComboBoxModel; -import javax.swing.DefaultComboBoxModel; -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JComboBox; -import javax.swing.JLabel; -import javax.swing.JMenuItem; -import javax.swing.JOptionPane; -import javax.swing.JPopupMenu; -import javax.swing.JScrollPane; -import javax.swing.JSeparator; -import javax.swing.JTable; -import javax.swing.JTextField; -import javax.swing.ListSelectionModel; -import javax.swing.SwingConstants; -import javax.swing.SwingUtilities; -import javax.swing.table.TableModel; -import javax.swing.table.TableRowSorter; - -import game.GameMode; -import object.ApiStrategy; -import object.LimitedDocument; -import util.ApiUtil; -import util.CpuStrategies; -import util.Debug; -import util.DialogUtil; -import util.TableUtil; -import util.TableUtil.DefaultModel; - -public class PreferencesPanelPlayers extends AbstractPreferencesPanel - implements MouseListener, - ItemListener -{ - private String playerName = "Player"; - private String opponentOneName = "Mark"; - private String opponentTwoName = "Dave"; - private String opponentThreeName = "Tom"; - private boolean opponentTwoEnabled = false; - private boolean opponentThreeEnabled = false; - private String opponentOneStrategy = "Mark"; - private String opponentTwoStrategy = "Basic"; - private String opponentThreeStrategy = "Basic"; - private ArrayList apiStrategies = null; - private GameMode gameMode = GameMode.Entropy; - - public PreferencesPanelPlayers() - { - setLayout(null); - - separator_2.setBounds(0, 38, 434, 2); - add(separator_2); - lblPlayers.setBounds(172, 12, 70, 17); - add(lblPlayers); - lblPlayers.setHorizontalAlignment(SwingConstants.CENTER); - lblPlayers.setFont(new Font("Tahoma", Font.PLAIN, 14)); - playerNameField.setDocument(new LimitedDocument(10)); - opponentOneNameField.setDocument(new LimitedDocument(10)); - opponentTwoNameField.setDocument(new LimitedDocument(10)); - opponentThreeNameField.setDocument(new LimitedDocument(10)); - opponentOneNameField.setBounds(60, 102, 86, 22); - add(opponentOneNameField); - opponentOneNameField.setText(opponentOneName); - opponentOneNameField.setColumns(10); - cbOpponentTwo.setBounds(22, 143, 29, 23); - add(cbOpponentTwo); - cbOpponentThree.setBounds(22, 185, 29, 23); - add(cbOpponentThree); - opponentTwoNameField.setBounds(60, 144, 86, 22); - add(opponentTwoNameField); - opponentTwoNameField.setText(opponentTwoName); - opponentTwoNameField.setColumns(10); - opponentThreeNameField.setBounds(60, 186, 86, 22); - add(opponentThreeNameField); - opponentThreeNameField.setText(opponentThreeName); - opponentThreeNameField.setColumns(10); - opponentTwoStrat.setBounds(172, 144, 197, 22); - add(opponentTwoStrat); - opponentThreeStrat.setBounds(172, 186, 197, 22); - add(opponentThreeStrat); - opponentOneStrat.setBounds(172, 102, 197, 22); - add(opponentOneStrat); - playerNameField.setBounds(212, 60, 86, 22); - add(playerNameField); - playerNameField.setColumns(10); - lblPlayerName.setBounds(122, 60, 80, 22); - add(lblPlayerName); - label.setFont(new Font("Tahoma", Font.ITALIC, 11)); - label.setBounds(65, 395, 304, 14); - add(label); - lblApiHeader.setHorizontalAlignment(SwingConstants.CENTER); - lblApiHeader.setFont(new Font("Tahoma", Font.PLAIN, 14)); - lblApiHeader.setBounds(171, 240, 86, 17); - add(lblApiHeader); - separator_4.setBounds(0, 265, 429, 2); - add(separator_4); - scrollPane.setBounds(17, 307, 402, 80); - add(scrollPane); - tableApiStrategies.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - scrollPane.setViewportView(tableApiStrategies); - btnNewApiStrategy.setBounds(17, 278, 151, 23); - add(btnNewApiStrategy); - tableApiStrategies.getTableHeader().setReorderingAllowed(false); - popupMenu.add(enableItem); - popupMenu.add(amendItem); - popupMenu.add(deleteItem); - - btnNewApiStrategy.addActionListener(this); - enableItem.addActionListener(this); - deleteItem.addActionListener(this); - amendItem.addActionListener(this); - tableApiStrategies.addMouseListener(this); - cbOpponentTwo.addItemListener(this); - cbOpponentThree.addItemListener(this); - } - - private final JLabel lblPlayers = new JLabel("Players"); - private final JSeparator separator_2 = new JSeparator(); - private final JLabel lblPlayerName = new JLabel("Player Name"); - private final JTextField playerNameField = new JTextField(); - private final JTextField opponentOneNameField = new JTextField(); - private final JTextField opponentTwoNameField = new JTextField(); - private final JTextField opponentThreeNameField = new JTextField(); - private final JCheckBox cbOpponentTwo = new JCheckBox(); - private final JCheckBox cbOpponentThree = new JCheckBox(); - private final JComboBox opponentOneStrat = new JComboBox<>(); - private final JComboBox opponentTwoStrat = new JComboBox<>(); - private final JComboBox opponentThreeStrat = new JComboBox<>(); - private final JLabel label = new JLabel("Note: Changes will not take effect until you start a new game."); - private final JSeparator separator_4 = new JSeparator(); - private final JLabel lblApiHeader = new JLabel("API Options"); - private final JScrollPane scrollPane = new JScrollPane(); - private final JTable tableApiStrategies = new JTable(); - private final JPopupMenu popupMenu = new JPopupMenu(); - private final JMenuItem amendItem = new JMenuItem("Amend"); - private final JMenuItem deleteItem = new JMenuItem("Delete"); - private final JMenuItem enableItem = new JMenuItem("Enable"); - private final JButton btnNewApiStrategy = new JButton("New API Strategy"); - - /** - * Abstract methods - */ - @Override - public void initVariables() - { - getVariablesFromPrefs(); - buildApiTable(); - setPlayerNames(); - setOpponentEnablementAndStrategies(); - setOpponentStrategies(); - } - - @Override - public boolean valid() - { - String nameOne = playerNameField.getText(); - String nameTwo = opponentOneNameField.getText(); - String nameThree = opponentTwoNameField.getText(); - String nameFour = opponentThreeNameField.getText(); - - if (nameOne.length() == 0 - || nameTwo.length() == 0 - || nameThree.length() == 0 - || nameFour.length() == 0) - { - DialogUtil.showError("You must enter a name for each player."); - return false; - } - - return true; - } - - @Override - public void savePreferences() - { - playerName = playerNameField.getText(); - opponentOneName = opponentOneNameField.getText(); - opponentTwoName = opponentTwoNameField.getText(); - opponentThreeName = opponentThreeNameField.getText(); - opponentOneStrategy = (String) opponentOneStrat.getSelectedItem(); - opponentTwoStrategy = (String) opponentTwoStrat.getSelectedItem(); - opponentThreeStrategy = (String) opponentThreeStrat.getSelectedItem(); - - prefs.put(PREFERENCES_STRING_PLAYER_NAME, playerName); - prefs.put(PREFERENCES_STRING_OPPONENT_ONE_NAME, opponentOneName); - prefs.put(PREFERENCES_STRING_OPPONENT_TWO_NAME, opponentTwoName); - prefs.put(PREFERENCES_STRING_OPPONENT_THREE_NAME, opponentThreeName); - prefs.putBoolean(PREFERENCES_BOOLEAN_OPPONENT_TWO_ENABLED, opponentTwoEnabled); - prefs.putBoolean(PREFERENCES_BOOLEAN_OPPONENT_THREE_ENABLED, opponentThreeEnabled); - prefs.put(PREFERENCES_STRING_OPPONENT_ONE_STRATEGY, opponentOneStrategy); - prefs.put(PREFERENCES_STRING_OPPONENT_TWO_STRATEGY, opponentTwoStrategy); - prefs.put(PREFERENCES_STRING_OPPONENT_THREE_STRATEGY, opponentThreeStrategy); - - ApiUtil.saveApiStrategiesToPreferences(apiStrategies); - } - - - private void getVariablesFromPrefs() - { - playerName = prefs.get(PREFERENCES_STRING_PLAYER_NAME, "Player"); - opponentOneName = prefs.get(PREFERENCES_STRING_OPPONENT_ONE_NAME, "Mark"); - opponentTwoName = prefs.get(PREFERENCES_STRING_OPPONENT_TWO_NAME, "Dave"); - opponentThreeName = prefs.get(PREFERENCES_STRING_OPPONENT_THREE_NAME, "Tom"); - opponentTwoEnabled = prefs.getBoolean(PREFERENCES_BOOLEAN_OPPONENT_TWO_ENABLED, true); - opponentThreeEnabled = prefs.getBoolean(PREFERENCES_BOOLEAN_OPPONENT_THREE_ENABLED, true); - opponentOneStrategy = prefs.get(PREFERENCES_STRING_OPPONENT_ONE_STRATEGY, "Basic"); - opponentTwoStrategy = prefs.get(PREFERENCES_STRING_OPPONENT_TWO_STRATEGY, "Basic"); - opponentThreeStrategy = prefs.get(PREFERENCES_STRING_OPPONENT_THREE_STRATEGY, "Basic"); - apiStrategies = ApiUtil.getApiStrategiesFromPreferences(); - - gameMode = GameMode.valueOf(prefs.get(PREFERENCES_STRING_GAME_MODE, GameMode.Entropy.name())); - } - - private void setPlayerNames() - { - playerNameField.setText(playerName); - opponentOneNameField.setText(opponentOneName); - opponentTwoNameField.setText(opponentTwoName); - opponentThreeNameField.setText(opponentThreeName); - } - - private void setOpponentEnablementAndStrategies() - { - cbOpponentThree.setEnabled(opponentTwoEnabled); - cbOpponentTwo.setEnabled(!opponentThreeEnabled); - - cbOpponentTwo.setSelected(opponentTwoEnabled); - cbOpponentThree.setSelected(opponentThreeEnabled); - opponentTwoNameField.setEnabled(opponentTwoEnabled); - opponentThreeNameField.setEnabled(opponentThreeEnabled); - opponentTwoStrat.setEnabled(opponentTwoEnabled); - opponentThreeStrat.setEnabled(opponentThreeEnabled); - } - - private void setOpponentStrategies() - { - opponentOneStrat.setSelectedItem(opponentOneStrategy); - opponentTwoStrat.setSelectedItem(opponentTwoStrategy); - opponentThreeStrat.setSelectedItem(opponentThreeStrategy); - } - - private void buildApiTable() - { - DefaultModel model = new TableUtil.DefaultModel(); - tableApiStrategies.setModel(model); - - //Columns - model.addColumn("Name"); - model.addColumn("Port"); - model.addColumn("Game"); - model.addColumn("Messaging"); - model.addColumn("Enabled"); - - //Centre rendering for everything but the last column - for (int i=0; i sorter = new TableRowSorter<>(model); - tableApiStrategies.setRowSorter(sorter); - - //Populate the rows - for (int i=0; i allStrategies = CpuStrategies.getAllStrategies(gameMode == GameMode.Entropy, apiStrategies); - - ComboBoxModel comboModel = new DefaultComboBoxModel<>(allStrategies); - opponentOneStrat.setModel(comboModel); - comboModel = new DefaultComboBoxModel<>(allStrategies); - opponentTwoStrat.setModel(comboModel); - comboModel = new DefaultComboBoxModel<>(allStrategies); - opponentThreeStrat.setModel(comboModel); - } - - private void enableApi(ApiStrategy strategy) - { - String question = "Strategy " + strategy.getName() + " was disabled due to the following error:" - + "\n\n" + strategy.getError() - + "\n\nWould you like to re-enable it?"; - - int option = DialogUtil.showQuestion(question, false); - if (option == JOptionPane.YES_OPTION) - { - strategy.setError(""); - buildApiTable(); - } - } - - private void amendApi(ApiStrategy strategy) - { - ApiAmendDialog.amendStrategy(strategy); - buildApiTable(); - } - - private void deleteApi(ApiStrategy strategy) - { - String question = "Are you sure you want to delete the " + strategy.getName() + " strategy?"; - int option = DialogUtil.showQuestion(question, false); - if (option == JOptionPane.YES_OPTION) - { - apiStrategies.remove(strategy); - buildApiTable(); - } - } - - private ApiStrategy getSelectedStrategyFromTable() - { - int row = tableApiStrategies.getSelectedRow(); - if (row == -1) - { - return null; - } - - int internalRow = tableApiStrategies.convertRowIndexToModel(row); - DefaultModel model = (DefaultModel)tableApiStrategies.getModel(); - String name = (String)model.getValueAt(internalRow, 0); - - int size = apiStrategies.size(); - for (int i=0; i Preferences > Gameplay and ticking 'Play Blind'."; - - rewardDescription.setText(rewardStr); - setSize(new Dimension(400, 410)); - } - else if (imageName.equals(REWARD_BANNER_DEVELOPERS)) - { - rewardTitle.setText("'Developers' joker set unlocked!"); - rewardStr = "These jokers feature the faces of four people who helped to develop Entropy." - + "\n\nUse them by going to Tools > Preferences > Appearance and selecting 'Developers' as the Joker Design."; - - rewardDescription.setText(rewardStr); - setSize(new Dimension(400, 330)); - } - else if (imageName.equals(REWARD_BANNER_FOUR_COLOUR)) - { - rewardTitle.setText("Four colour deck unlocked!"); - rewardStr = "You can now play with a four-colour deck, where clubs are green and diamonds are blue." - + "\n\nEnable this option by going to Tools > Preferences > Appearance and ticking 'Use 4 colour deck'."; - - rewardDescription.setText(rewardStr); - setSize(new Dimension(400, 330)); - } - else if (imageName.equals(REWARD_BANNER_CARD_REVEAL)) - { - rewardTitle.setText("Card reveal unlocked!"); - rewardStr = "Add extra pressure to the game by forcing players to reveal their cards!" - + "\n\nWith this option set, players will be forced to show a card each time they make a bid. " - + "Players do not have to reveal their last card so not all cards will be shown." - + "\n\nEnable this option by going to Tools > Preferences > Gameplay and ticking 'Players reveal cards'."; - - rewardDescription.setText(rewardStr); - setSize(new Dimension(400, 390)); - } - else if (imageName.equals(REWARD_BANNER_NEGATIVE_JACKS)) - { - rewardTitle.setText("Negative jacks unlocked!"); - rewardStr = "Spice up the deck by makings Jacks worth -1 of their suit!" - + "\n\nEnable this option by going to Tools > Preferences > Gameplay and ticking 'Jacks worth -1'"; - - rewardDescription.setText(rewardStr); - setSize(new Dimension(400, 310)); - } - else if (imageName.equals(REWARD_BANNER_MINIMALIST)) - { - rewardTitle.setText("'Minimalist' deck design unlocked!"); - rewardStr = "Go for a more minimalist feel with this new deck design." - + "\n\nUse it by going to Tools > Preferences > Appearance and selecting 'Minimalist' as the Deck Design."; - - rewardDescription.setText(rewardStr); - setSize(new Dimension(400, 310)); - } - else if (imageName.equals(REWARD_BANNER_VECTROPY)) - { - rewardTitle.setText("Vectropy unlocked!"); - rewardStr = "Vectropy is a variant where you have to bid in all four suits at once. " - + "New help pages have been added that detail the rules for this new game." - + "\n\nPlay Vectropy by going to Tools > Preferences > Gameplay and selecting 'Vectropy' (under Game Mode)."; - - rewardDescription.setText(rewardStr); - setSize(new Dimension(400, 350)); - } - else if (imageName.equals(REWARD_BANNER_ILLEGAL)) - { - rewardTitle.setText("'Illegal' option unlocked!"); - rewardStr = "You can now shout 'Illegal!' in response to a bid that you think is perfect! " - + "\n\nIf you're right your opponent loses a card, but if you're wrong you'll lose one - even if a challenge would have been correct!" - + "\n\nYou will see the new 'Illegal!' option the next time you play a game."; - - rewardDescription.setText(rewardStr); - setSize(new Dimension(400, 370)); - } - else if (imageName.equals(REWARD_BANNER_EXTRA_SUITS)) - { - rewardTitle.setText("Extra suits unlocked!"); - rewardStr = "You can now play with Stars and Moons, making for up to 6 suits in total! " - + "\nSuit order remains alphabetical, making Stars the strongest suit if they are in play." - + "\n\nChoose which suits to play with by going to Tools > Preferences > Gameplay and using the options under 'Deck Setup'."; - - rewardDescription.setText(rewardStr); - setSize(new Dimension(400, 370)); - } - else if (imageName.equals(REWARD_BANNER_CHEATS)) - { - rewardTitle.setText("Cheats unlocked!"); - rewardStr = "Now you can use certain codes to cheat on your opponents, and even access hidden screens!" - + "\n\nThese were first created to speed up testing, especially for things that relied on being good - seriously, who has time for that?" - + "\n\nA full list of cheats can be found under Help > Miscellaneous > Cheat Codes."; - - rewardDescription.setText(rewardStr); - setSize(new Dimension(400, 390)); - } - } -} diff --git a/client/src/main/java/screen/SimpleDialog.java b/client/src/main/java/screen/SimpleDialog.java deleted file mode 100644 index 451bbff0..00000000 --- a/client/src/main/java/screen/SimpleDialog.java +++ /dev/null @@ -1,67 +0,0 @@ -package screen; - -import java.awt.BorderLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -import javax.swing.JButton; -import javax.swing.JDialog; -import javax.swing.JPanel; - -import util.Debug; - -public abstract class SimpleDialog extends JDialog - implements ActionListener -{ - public SimpleDialog() - { - getContentPane().add(panelOkCancel, BorderLayout.SOUTH); - - panelOkCancel.add(btnOk); - panelOkCancel.add(btnCancel); - - btnCancel.setVisible(allowCancel()); - - btnOk.addActionListener(this); - btnCancel.addActionListener(this); - } - - protected final JPanel panelOkCancel = new JPanel(); - private final JButton btnOk = new JButton("Ok"); - private final JButton btnCancel = new JButton("Cancel"); - - /** - * Abstract methods - */ - public abstract void okPressed(); - - /** - * Default methods - */ - public boolean allowCancel() - { - return true; - } - public void cancelPressed() - { - dispose(); - } - - @Override - public void actionPerformed(ActionEvent arg0) - { - JButton src = (JButton)arg0.getSource(); - if (src == btnOk) - { - okPressed(); - } - else if (src == btnCancel) - { - cancelPressed(); - } - else - { - Debug.stackTrace("Unexpected button pressed: " + src.getText()); - } - } -} diff --git a/client/src/main/java/screen/StatisticsDialog.java b/client/src/main/java/screen/StatisticsDialog.java index 15ab3be0..7fb579ae 100644 --- a/client/src/main/java/screen/StatisticsDialog.java +++ b/client/src/main/java/screen/StatisticsDialog.java @@ -24,6 +24,7 @@ import javax.swing.SwingConstants; import achievement.AchievementSetting; +import achievement.Reward; import util.DateUtil; import util.Debug; import util.Registry; @@ -42,7 +43,7 @@ public StatisticsDialog() { try { - vectropyUnlocked = rewards.getBoolean(REWARDS_BOOLEAN_VECTROPY, false); + vectropyUnlocked = Reward.Vectropy.isUnlocked(); getContentPane().setLayout(new BorderLayout(0, 0)); panel_1 = new Panel(); diff --git a/client/src/main/java/screen/VectropyBidPanel.java b/client/src/main/java/screen/VectropyBidPanel.java index cca33d54..87622d0d 100644 --- a/client/src/main/java/screen/VectropyBidPanel.java +++ b/client/src/main/java/screen/VectropyBidPanel.java @@ -24,12 +24,17 @@ import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; +import achievement.Reward; +import game.RenderingUtilKt; import game.Suit; import game.VectropyBidAction; +import preference.PreferenceSetting; import util.Debug; import util.EntropyColour; import util.Registry; +import static preference.PreferenceSettingKt.getPreference; + public class VectropyBidPanel extends BidPanel implements ActionListener, ChangeListener, @@ -231,7 +236,7 @@ public void init(int maxBid, int totalNumberOfCards, boolean online, boolean inc starsPanel.setVisible(includeStars); totalCardsLabel.setText("x " + totalNumberOfCards); - String back = prefs.get(PREFERENCES_STRING_CARD_BACKS, Registry.BACK_CODE_CLASSIC_BLUE); + String back = getPreference(PreferenceSetting.CardBacks); smallCardIcon.setIcon(new ImageIcon(EntropyScreen.class.getResource("/backs/" + back + "Small.png"))); lastBid = null; @@ -256,7 +261,7 @@ private void setIllegalButtonState() { if (!online) { - illegalAllowed |= rewards.getBoolean(REWARDS_BOOLEAN_ILLEGAL, false); + illegalAllowed |= Reward.Illegal.isUnlocked(); } btnIllegal.setVisible(illegalAllowed); @@ -264,9 +269,9 @@ private void setIllegalButtonState() private void updateSpinnerColours() { - clubLabel.setForeground(Suit.Clubs.getColour()); - diamondLabel.setForeground(Suit.Diamonds.getColour()); - moonLabel.setForeground(Suit.Moons.getColour()); + clubLabel.setForeground(RenderingUtilKt.getColour(Suit.Clubs)); + diamondLabel.setForeground(RenderingUtilKt.getColour(Suit.Diamonds)); + moonLabel.setForeground(RenderingUtilKt.getColour(Suit.Moons)); } private void setBidButtonState() @@ -291,7 +296,7 @@ private VectropyBidAction getBidFromSpinners() @Override public void fireAppearancePreferencesChange() { - String back = prefs.get(PREFERENCES_STRING_CARD_BACKS, Registry.BACK_CODE_CLASSIC_BLUE); + String back = getPreference(PreferenceSetting.CardBacks); smallCardIcon.setIcon(new ImageIcon(EntropyScreen.class.getResource("/backs/" + back + "Small.png"))); updateSpinnerColours(); @@ -323,7 +328,7 @@ public void loadState(Preferences savedGame) String label = savedGame.get(SAVED_GAME_STRING_TOTAL_CARDS_LABEL, "0"); totalCardsLabel.setText(label); - String back = prefs.get(PREFERENCES_STRING_CARD_BACKS, Registry.BACK_CODE_CLASSIC_BLUE); + String back = getPreference(PreferenceSetting.CardBacks); smallCardIcon.setIcon(new ImageIcon(EntropyScreen.class.getResource("/backs/" + back + "Small.png"))); } diff --git a/client/src/main/java/screen/VectropyScreen.java b/client/src/main/java/screen/VectropyScreen.java index 9d90c67d..e5f00178 100644 --- a/client/src/main/java/screen/VectropyScreen.java +++ b/client/src/main/java/screen/VectropyScreen.java @@ -5,12 +5,14 @@ import game.GameMode; import game.Suit; import game.VectropyBidAction; +import preference.PreferenceSetting; import util.AchievementsUtil; import util.Debug; import util.Registry; import static game.CheatUtilKt.getMaxBidString; import static game.RenderingUtilKt.getVectropyResult; +import static preference.PreferenceSettingKt.getPreference; public class VectropyScreen extends GameScreen { @@ -26,7 +28,7 @@ public VectropyScreen() setLayout(new BorderLayout(0, 0)); add(handPanel, BorderLayout.CENTER); handPanel.setOpaque(false); - bidPanel = new VectropyBidPanel(prefs.get(PREFERENCES_STRING_PLAYER_NAME, "Player"), handPanel); + bidPanel = new VectropyBidPanel(getPreference(PreferenceSetting.PlayerName), handPanel); add(bidPanel, BorderLayout.SOUTH); bidPanel.showBidPanel(false); diff --git a/client/src/main/java/util/AchievementsUtil.java b/client/src/main/java/util/AchievementsUtil.java index 90150945..dea20efa 100644 --- a/client/src/main/java/util/AchievementsUtil.java +++ b/client/src/main/java/util/AchievementsUtil.java @@ -5,9 +5,7 @@ import game.PlayerAction; import object.Player; import online.screen.EntropyLobby; -import screen.HelpDialog; import screen.MainScreen; -import screen.RewardDialog; import screen.ScreenCache; import utils.Achievement; @@ -20,7 +18,7 @@ import static achievement.AchievementUtilKt.unlockAchievement; import static util.ClientGlobals.achievementStore; -public class AchievementsUtil implements Registry +public class AchievementsUtil { private static final int FULL_GAME_STARTING_CARDS = 5; private static final int OMNISCIENT_THRESHOLD = 10; @@ -448,32 +446,6 @@ public static void unlockBlueScreenOfDeath() { unlockAchievement(Achievement.BlueScreenOfDeath); } - - public static void unlockRewards(int achievementsEarned) - { - unlockIfRequired(achievementsEarned, 5, REWARDS_BOOLEAN_FOUR_COLOURS, RewardDialog.REWARD_BANNER_FOUR_COLOUR); - unlockIfRequired(achievementsEarned, 10, REWARDS_BOOLEAN_NEGATIVE_JACKS, RewardDialog.REWARD_BANNER_NEGATIVE_JACKS); - unlockIfRequired(achievementsEarned, 15, REWARDS_BOOLEAN_BLIND, RewardDialog.REWARD_BANNER_BLIND); - unlockIfRequired(achievementsEarned, 20, REWARDS_BOOLEAN_MINIMALIST_DECK, RewardDialog.REWARD_BANNER_MINIMALIST); - unlockIfRequired(achievementsEarned, 25, REWARDS_BOOLEAN_VECTROPY, RewardDialog.REWARD_BANNER_VECTROPY); - unlockIfRequired(achievementsEarned, 30, REWARDS_BOOLEAN_CARD_REVEAL, RewardDialog.REWARD_BANNER_CARD_REVEAL); - unlockIfRequired(achievementsEarned, 35, REWARDS_BOOLEAN_EXTRA_SUITS, RewardDialog.REWARD_BANNER_EXTRA_SUITS); - unlockIfRequired(achievementsEarned, 40, REWARDS_BOOLEAN_ILLEGAL, RewardDialog.REWARD_BANNER_ILLEGAL); - unlockIfRequired(achievementsEarned, 45, REWARDS_BOOLEAN_DEVELOPER_JOKERS, RewardDialog.REWARD_BANNER_DEVELOPERS); - unlockIfRequired(achievementsEarned, 50, REWARDS_BOOLEAN_CHEATS, RewardDialog.REWARD_BANNER_CHEATS); - - //Always refresh here in case there are new pages - ScreenCache.get(HelpDialog.class).refreshNodes(""); - } - private static void unlockIfRequired(int achievementsEarned, int threshold, String registryNode, String imageName) - { - if (achievementsEarned >= threshold - && !rewards.getBoolean(registryNode, false)) - { - rewards.putBoolean(registryNode, true); - RewardDialog.showDialog(imageName); - } - } public static void updateAndUnlockSocial(ConcurrentHashMap hmPlayerByAdjustedPlayerNumber) { diff --git a/client/src/main/java/util/ApiUtil.java b/client/src/main/java/util/ApiUtil.java index 9044f023..10234324 100644 --- a/client/src/main/java/util/ApiUtil.java +++ b/client/src/main/java/util/ApiUtil.java @@ -2,17 +2,18 @@ import game.BidAction; import game.GameMode; -import game.GameSettings; import game.PlayerAction; -import object.*; +import object.ApiStrategy; +import object.Player; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; +import preference.PreferenceSetting; +import settings.Setting; import utils.CoreGlobals; import javax.swing.*; import java.io.BufferedReader; -import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.InetAddress; @@ -21,7 +22,10 @@ import java.net.SocketTimeoutException; import java.util.*; -public class ApiUtil implements Registry +import static preference.PreferenceSettingKt.getPreference; +import static util.ClientGlobals.preferenceStore; + +public class ApiUtil { public static final String API_PREFIX = "API: "; public static final String MESSAGE_TYPE_XML = "XML"; @@ -29,6 +33,14 @@ public class ApiUtil implements Registry private static final String ROOT_TAG_API_MESSAGE = "ApiMessage"; private static final InetAddress INET_ADDRESS_LOCALHOST = MessageUtil.factoryInetAddress("localhost"); + + private static final String PREFERENCES_TAG_API = "Api"; + private static final String PREFERENCES_ATTR_API_NAME = "ApiName"; + private static final String PREFERENCES_ATTR_PORT_NUMNER = "PortNumber"; + private static final String PREFERENCES_ATTR_MESSAGE_TYPE = "MessageType"; + private static final String PREFERENCES_ATTR_SUPPORTS_ENTROPY = "Entropy"; + private static final String PREFERENCES_ATTR_SUPPORTS_VECTROPY = "Vectropy"; + private static final String PREFERENCES_ATTR_ERROR = "Error"; //Cache this for speed in the simulator private static HashMap hmNameToApiStrategy = null; @@ -248,8 +260,13 @@ private static void showMalformedResponseError(String response) private static void initialiseStrategyHashMap() { HashMap temp = new HashMap<>(); - - Document apiXml = RegistryUtil.getAttributeXml(prefs, PREFERENCES_XML_API_SETTINGS); + + String apiStrategies = getPreference(PreferenceSetting.ApiStrategies); + if (apiStrategies.isBlank()) { + return; + } + + Document apiXml = XmlUtil.getDocumentFromXmlString(apiStrategies); if (apiXml == null) { hmNameToApiStrategy = temp; @@ -316,7 +333,7 @@ public static ApiStrategy getApiStrategy(String name) return hmNameToApiStrategy.get(name); } - public static void saveApiStrategiesToPreferences(ArrayList strategies) + public static void saveApiStrategiesToPreferences(List strategies) { //Construct a document with any old root element Document apiDoc = XmlUtil.factoryNewDocument(); @@ -342,7 +359,8 @@ public static void saveApiStrategiesToPreferences(ArrayList strateg apiDoc.appendChild(rootElement); //Save to the Registry - RegistryUtil.setAttributeXml(prefs, PREFERENCES_XML_API_SETTINGS, apiDoc); + String xmlStr = XmlUtil.getStringFromDocument(apiDoc); + preferenceStore.save(PreferenceSetting.ApiStrategies, xmlStr); //Clear the cache clearCache(); @@ -369,17 +387,17 @@ public static void saveStrategyErrorAndUnsetStrategies(ApiStrategy strategy, Str saveApiStrategiesToPreferences(apiStrategies); - resetCpuStrategy(PREFERENCES_STRING_OPPONENT_ONE_STRATEGY, name); - resetCpuStrategy(PREFERENCES_STRING_OPPONENT_TWO_STRATEGY, name); - resetCpuStrategy(PREFERENCES_STRING_OPPONENT_THREE_STRATEGY, name); + resetCpuStrategy(PreferenceSetting.OpponentOneStrategy, name); + resetCpuStrategy(PreferenceSetting.OpponentTwoStrategy, name); + resetCpuStrategy(PreferenceSetting.OpponentThreeStrategy, name); } - private static void resetCpuStrategy(String prefsKey, String apiName) + private static void resetCpuStrategy(Setting strategySetting, String apiName) { - String strategy = prefs.get(prefsKey, ""); + String strategy = getPreference(strategySetting); if (strategy.equals("API: " + apiName)) { - prefs.put(prefsKey, CpuStrategies.STRATEGY_BASIC); + preferenceStore.save(strategySetting, CpuStrategies.STRATEGY_BASIC); } } } diff --git a/client/src/main/java/util/CpuStrategies.java b/client/src/main/java/util/CpuStrategies.java index 54213ef0..ae030c4f 100644 --- a/client/src/main/java/util/CpuStrategies.java +++ b/client/src/main/java/util/CpuStrategies.java @@ -15,7 +15,7 @@ public class CpuStrategies public static final String STRATEGY_BASIC = "Easy"; public static final String STRATEGY_EV = "Hard"; - public static Vector getAllStrategies(boolean entropy, ArrayList apiStrategies) + public static Vector getAllStrategies(boolean entropy, List apiStrategies) { Vector allStrategies = getFixedStrategies(entropy); @@ -30,7 +30,7 @@ public static Vector getAllStrategies(boolean entropy, ArrayList allStrategies, - ArrayList apiStrategies, boolean entropy) + List apiStrategies, boolean entropy) { int size = apiStrategies.size(); for (int i=0; i= REPLAY_VERSION) { diff --git a/client/src/main/java/util/ReplayFileUtil.java b/client/src/main/java/util/ReplayFileUtil.java index cf09eb4d..6b2b2d69 100644 --- a/client/src/main/java/util/ReplayFileUtil.java +++ b/client/src/main/java/util/ReplayFileUtil.java @@ -5,6 +5,7 @@ import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; +import preference.PreferenceSetting; import screen.ReplayDialog; import java.io.File; @@ -20,6 +21,9 @@ import java.util.prefs.BackingStoreException; import java.util.prefs.Preferences; +import static preference.PreferenceSettingKt.getPreference; +import static util.ClientGlobals.preferenceStore; + public final class ReplayFileUtil implements Registry { public static final String FOLDER_PERSONAL_REPLAYS = "Personal"; @@ -115,7 +119,7 @@ public static void saveOnlineReplayToFile(String roomId, String username) private static void saveReplayToFile(Preferences replay) { - boolean save = prefs.getBoolean(PREFERENCES_BOOLEAN_SAVE_REPLAYS, false); + boolean save = getPreference(PreferenceSetting.SaveReplays); if (!save) { return; @@ -353,7 +357,7 @@ private static void addChatHistoryElement(Preferences replay, Document document, public static String getDirectoryFromPreferences() { - return prefs.get(PREFERENCES_STRING_REPLAY_DIRECTORY, System.getProperty("user.dir")); + return preferenceStore.get(PreferenceSetting.ReplayDirectory); } private static String factoryFileNameForReplay(Preferences replay) diff --git a/client/src/main/kotlin/achievement/AchievementUtil.kt b/client/src/main/kotlin/achievement/AchievementUtil.kt index beb30b90..deb00035 100644 --- a/client/src/main/kotlin/achievement/AchievementUtil.kt +++ b/client/src/main/kotlin/achievement/AchievementUtil.kt @@ -1,11 +1,12 @@ package achievement import javax.swing.ImageIcon -import screen.AchievementsDialog +import screen.HelpDialog import screen.MainScreen import screen.ScreenCache +import screen.achievement.AchievementsDialog +import screen.achievement.RewardDialog import settings.Setting -import util.AchievementsUtil import util.ClientGlobals import util.ClientGlobals.achievementStore import util.ClientUtil @@ -40,7 +41,19 @@ fun unlockAchievement(achievement: Achievement) { ClientGlobals.sessionApi.updateAchievementCount(achievementsEarned) } - AchievementsUtil.unlockRewards(achievementsEarned) + unlockRewards(achievementsEarned) +} + +fun unlockRewards(achievementsEarned: Int) { + Reward.entries.forEach { reward -> + if (achievementsEarned >= reward.threshold && !reward.isUnlocked()) { + reward.unlock() + RewardDialog.showDialog(reward) + } + } + + // Always refresh here in case there are new pages + ScreenCache.get().refreshNodes("") } fun updateAndUnlockVanity() { diff --git a/client/src/main/kotlin/achievement/Reward.kt b/client/src/main/kotlin/achievement/Reward.kt new file mode 100644 index 00000000..a57c5f25 --- /dev/null +++ b/client/src/main/kotlin/achievement/Reward.kt @@ -0,0 +1,28 @@ +package achievement + +import java.net.URL +import settings.Setting +import util.ClientGlobals + +enum class Reward(val settingName: String, val threshold: Int) { + FourColours("fourColours", 5), + NegativeJacks("negativeJacks", 10), + Blind("blind", 15), + MinimalistDeck("minimalist", 20), + Vectropy("vectropy", 25), + CardReveal("cardReveal", 30), + ExtraSuits("extraSuits", 35), + Illegal("illegal", 40), + DeveloperSet("developerSet", 45), + Cheats("cheats", 50); + + private val setting: Setting = Setting(settingName, false) + + fun isUnlocked() = ClientGlobals.rewardStore.get(setting) + + fun unlock() { + ClientGlobals.rewardStore.save(setting, true) + } + + fun getResource(): URL? = javaClass.getResource("/rewards/$settingName.png") +} diff --git a/client/src/main/kotlin/bean/AchievementBadge.kt b/client/src/main/kotlin/bean/AchievementBadge.kt index 40045449..be562c01 100644 --- a/client/src/main/kotlin/bean/AchievementBadge.kt +++ b/client/src/main/kotlin/bean/AchievementBadge.kt @@ -5,10 +5,9 @@ import achievement.isUnlocked import java.awt.Dimension import javax.swing.JLabel import util.Images -import util.Registry import utils.Achievement -class AchievementBadge(private val achievement: Achievement) : JLabel(), Registry { +class AchievementBadge(private val achievement: Achievement) : JLabel() { val explanation = achievement.explanation val description = achievement.description diff --git a/client/src/main/kotlin/bean/BidListCellRenderer.kt b/client/src/main/kotlin/bean/BidListCellRenderer.kt new file mode 100644 index 00000000..05f634f3 --- /dev/null +++ b/client/src/main/kotlin/bean/BidListCellRenderer.kt @@ -0,0 +1,64 @@ +package bean + +import game.BidAction +import game.MOONS_SYMBOL +import game.PlayerAction +import game.getCardHtml +import game.htmlString +import java.awt.Component +import javax.swing.DefaultListCellRenderer +import javax.swing.JList +import `object`.Player +import util.StringUtil + +class BidListCellRenderer : DefaultListCellRenderer() { + private var hmNameToColour: Map = mapOf() + + override fun getListCellRendererComponent( + list: JList<*>?, + value: Any?, + index: Int, + isSelected: Boolean, + cellHasFocus: Boolean, + ): Component? { + val bid = value as PlayerAction + val text = toHtmlString(bid) + + return super.getListCellRendererComponent(list, text, index, isSelected, cellHasFocus) + } + + fun updateColours(players: MutableCollection) { + this.hmNameToColour = players.associate { it.name to it.colour } + } + + fun updateColours(map: Map) { + this.hmNameToColour = map + } + + fun toHtmlString(action: PlayerAction): String { + var playerName = action.playerName + playerName = StringUtil.escapeHtml(playerName) + + val colour = hmNameToColour.get(playerName) + var playerNamePrefix = "$playerName: " + + if (action.blind) { + playerNamePrefix = "[$playerName]: " + } + + var text = "$playerNamePrefix" + text += action.htmlString() + + if (action is BidAction<*> && action.cardToReveal != null) { + text += "&emsp(Shows: " + text += getCardHtml(action.cardToReveal!!) + text += ")" + } + + // The unicode for a moon doesn't work in HTML. Also shrink to match the size of the other + // suits. + text = text.replace(MOONS_SYMBOL.toRegex(), "🌙") + text += "" + return text + } +} diff --git a/client/src/main/kotlin/bean/ComboBoxItem.kt b/client/src/main/kotlin/bean/ComboBoxItem.kt new file mode 100644 index 00000000..ff4bb7ec --- /dev/null +++ b/client/src/main/kotlin/bean/ComboBoxItem.kt @@ -0,0 +1,6 @@ +package bean + +data class ComboBoxItem(val hiddenData: E, val visibleData: String, val enabled: Boolean) { + override fun toString() = + if (enabled) visibleData else "$visibleData" +} diff --git a/client/src/main/kotlin/game/RenderingUtil.kt b/client/src/main/kotlin/game/RenderingUtil.kt index 3db955cd..458e2389 100644 --- a/client/src/main/kotlin/game/RenderingUtil.kt +++ b/client/src/main/kotlin/game/RenderingUtil.kt @@ -1,5 +1,11 @@ package game +import java.awt.Color +import preference.FOUR_COLOURS +import preference.PreferenceSetting +import util.ClientGlobals +import utils.toHexCode + fun getCardHtml(card: String): String { if (card.contains("Jo")) { return "Jo" @@ -26,3 +32,17 @@ fun getVectropyResult( return "(${htmlStrings.joinToString(", ")})" } + +fun PlayerAction.htmlString() = + when (this) { + is EntropyBidAction -> + "$amount${suit.unicodeStr}" + else -> plainString() + } + +fun Suit.getColour(): Color { + val numberOfColoursStr = ClientGlobals.preferenceStore.get(PreferenceSetting.NumberOfColours) + return if (numberOfColoursStr == FOUR_COLOURS) fourColour else twoColour +} + +fun Suit.getColourHex() = getColour().toHexCode() diff --git a/client/src/main/kotlin/game/StrategyUtil.kt b/client/src/main/kotlin/game/StrategyUtil.kt index ad2451ec..f081e3bd 100644 --- a/client/src/main/kotlin/game/StrategyUtil.kt +++ b/client/src/main/kotlin/game/StrategyUtil.kt @@ -89,7 +89,6 @@ fun getBasicVectropyOpening( val map = suits.associateWith { suit -> val myCount = countSuit(suit, hand, settings.jokerValue) - println(myCount) maxOf(0, myCount + random.nextInt(3) - 1) } diff --git a/client/src/main/kotlin/help/FundamentalsGlossary.kt b/client/src/main/kotlin/help/FundamentalsGlossary.kt index e199d1dd..00812256 100644 --- a/client/src/main/kotlin/help/FundamentalsGlossary.kt +++ b/client/src/main/kotlin/help/FundamentalsGlossary.kt @@ -1,12 +1,12 @@ package help +import achievement.Reward import java.awt.Color import java.awt.Font import javax.swing.JTextPane import util.EntropyColour -import util.Registry -class FundamentalsGlossary : HelpPanel(), Registry { +class FundamentalsGlossary : HelpPanel() { override val nodeName = "Glossary" private val title = JTextPane() @@ -31,11 +31,9 @@ class FundamentalsGlossary : HelpPanel(), Registry { override fun searchTermsToExclude() = listOf("perfect", "challenge") override fun refresh() { - val blindUnlocked = Registry.rewards.getBoolean(Registry.REWARDS_BOOLEAN_BLIND, false) - var glossaryText = "\r\n
    \r\n" - if (blindUnlocked) { + if (Reward.Blind.isUnlocked()) { glossaryText += "
  • Blind: Playing blind means not looking at your cards.
  • \r\n" } diff --git a/client/src/main/kotlin/help/FundamentalsTheDeck.kt b/client/src/main/kotlin/help/FundamentalsTheDeck.kt index 9e95debf..91da840a 100644 --- a/client/src/main/kotlin/help/FundamentalsTheDeck.kt +++ b/client/src/main/kotlin/help/FundamentalsTheDeck.kt @@ -1,5 +1,6 @@ package help +import achievement.Reward import game.CLUBS_SYMBOL import game.DIAMONDS_SYMBOL import game.HEARTS_SYMBOL @@ -12,9 +13,8 @@ import javax.swing.JLabel import javax.swing.JTextPane import javax.swing.SwingConstants import util.EntropyColour -import util.Registry -class FundamentalsTheDeck : HelpPanel(), Registry { +class FundamentalsTheDeck : HelpPanel() { override val nodeName = "The Deck" private var clubString = "clubs (${CLUBS_SYMBOL})" @@ -102,7 +102,7 @@ class FundamentalsTheDeck : HelpPanel(), Registry { override fun searchTermsToExclude() = listOf("bidding") - private fun setPaneOneText(moonsAndStars: Boolean) { + private fun setPaneOneText() { var paneOneText = ("For the standard game, a normal deck of 52 cards is used. This deck is made up of four suits: " + clubString + @@ -111,7 +111,7 @@ class FundamentalsTheDeck : HelpPanel(), Registry { ", hearts (${HEARTS_SYMBOL}) and spades (${SPADES_SYMBOL}), " + "each of 13 cards. ") - if (moonsAndStars) { + if (Reward.ExtraSuits.isUnlocked()) { paneOneText += "Two optional suits, $moonString and stars " paneOneText += "(" + @@ -148,8 +148,7 @@ class FundamentalsTheDeck : HelpPanel(), Registry { MOONS_SYMBOL + ")" - val moonsAndStars = Registry.rewards.getBoolean(Registry.REWARDS_BOOLEAN_EXTRA_SUITS, false) - setPaneOneText(moonsAndStars) + setPaneOneText() if (fourColours) { clubLabel.foreground = Color(0, 128, 0) @@ -163,9 +162,7 @@ class FundamentalsTheDeck : HelpPanel(), Registry { } private fun refreshSuitRankingVisibility() { - val moonsAndStars = Registry.rewards.getBoolean(Registry.REWARDS_BOOLEAN_EXTRA_SUITS, false) - - if (moonsAndStars) { + if (Reward.ExtraSuits.isUnlocked()) { moonLabel.isVisible = true starLabel.isVisible = true rightmostLabel.isVisible = true diff --git a/client/src/main/kotlin/help/HelpPanel.kt b/client/src/main/kotlin/help/HelpPanel.kt index 936d04c5..cf1575af 100644 --- a/client/src/main/kotlin/help/HelpPanel.kt +++ b/client/src/main/kotlin/help/HelpPanel.kt @@ -10,9 +10,11 @@ import javax.swing.JPanel import javax.swing.JTextPane import javax.swing.text.DefaultHighlighter.DefaultHighlightPainter import javax.swing.text.Highlighter +import preference.FOUR_COLOURS +import preference.PreferenceSetting import screen.HelpDialog import screen.ScreenCache -import util.Registry +import util.ClientGlobals.preferenceStore import utils.CoreGlobals.logger import utils.getAllChildComponentsForType @@ -223,8 +225,7 @@ abstract class HelpPanel : JPanel() { override fun toString() = nodeName protected fun useFourColours() = - Registry.prefs[Registry.PREFERENCES_STRING_NUMBER_OF_COLOURS, Registry.TWO_COLOURS] == - Registry.FOUR_COLOURS + preferenceStore.get(PreferenceSetting.NumberOfColours) == FOUR_COLOURS open fun refresh() { // to be overridden by any pages that have dynamic content diff --git a/client/src/main/kotlin/help/RulesVectropyBidding.kt b/client/src/main/kotlin/help/RulesVectropyBidding.kt index 181dca78..70e145de 100644 --- a/client/src/main/kotlin/help/RulesVectropyBidding.kt +++ b/client/src/main/kotlin/help/RulesVectropyBidding.kt @@ -1,12 +1,12 @@ package help +import achievement.Reward import java.awt.Color import java.awt.Font import javax.swing.JTextPane import util.EntropyColour -import util.Registry -class RulesVectropyBidding : HelpPanel(), Registry { +class RulesVectropyBidding : HelpPanel() { override val nodeName = "Bidding" private val title = JTextPane() @@ -58,8 +58,6 @@ class RulesVectropyBidding : HelpPanel(), Registry { } private fun setPaneOneText() { - val extraSuits = Registry.rewards.getBoolean(Registry.REWARDS_BOOLEAN_EXTRA_SUITS, false) - var text = "A round starts with the first person to play bidding. At the start of a new game, " text += @@ -74,7 +72,7 @@ class RulesVectropyBidding : HelpPanel(), Registry { "(\u2663, \u2666, " text += "\u2665, \u2660). " - if (extraSuits) { + if (Reward.ExtraSuits.isUnlocked()) { text += "This vector naturally extends if additional suits are in play. " } diff --git a/client/src/main/kotlin/help/ToolsGameplaySettings.kt b/client/src/main/kotlin/help/ToolsGameplaySettings.kt index da087b1c..8767c571 100644 --- a/client/src/main/kotlin/help/ToolsGameplaySettings.kt +++ b/client/src/main/kotlin/help/ToolsGameplaySettings.kt @@ -1,5 +1,6 @@ package help +import achievement.Reward import java.awt.Color import java.awt.Dimension import java.awt.Font @@ -8,9 +9,8 @@ import javax.swing.JLabel import javax.swing.JPanel import javax.swing.JTextPane import util.EntropyColour -import util.Registry -class ToolsGameplaySettings : HelpPanel(), Registry { +class ToolsGameplaySettings : HelpPanel() { override val nodeName = "Gameplay Settings" private val title = JTextPane() @@ -132,7 +132,7 @@ class ToolsGameplaySettings : HelpPanel(), Registry { } override fun refresh() { - val unlockedBlind = Registry.rewards.getBoolean(Registry.REWARDS_BOOLEAN_BLIND, false) + val unlockedBlind = Reward.Blind.isUnlocked() blindPanel.isVisible = unlockedBlind if (unlockedBlind) { diff --git a/client/src/main/kotlin/preference/PreferenceSetting.kt b/client/src/main/kotlin/preference/PreferenceSetting.kt new file mode 100644 index 00000000..b06ce523 --- /dev/null +++ b/client/src/main/kotlin/preference/PreferenceSetting.kt @@ -0,0 +1,74 @@ +package preference + +import settings.Setting +import util.ClientGlobals.preferenceStore +import util.CpuStrategies.STRATEGY_BASIC + +const val TWO_COLOURS = "twocolour" +const val FOUR_COLOURS = "fourcolour" +const val DECK_DESIGN_CLASSIC = "classic" +const val DECK_DESIGN_ALTERNATE = "alternate" +const val JOKER_DESIGN_CLASSIC = "classic" +const val JOKER_DESIGN_DEVELOPERS = "developers" + +const val GAME_SPEED_SLOW = 1500 +const val GAME_SPEED_MEDIUM = 1000 +const val GAME_SPEED_FAST = 500 + +fun getPreference(setting: Setting) = preferenceStore.get(setting) + +object PreferenceSetting { + // Gameplay + @JvmField val GameMode = Setting("gameMode", game.GameMode.Entropy.name) + @JvmField val PlayWithHandicap = Setting("playWithHandicap", false) + @JvmField val HandicapAmount = Setting("handicapAmount", 1) + @JvmField val PlayBlind = Setting("playBlind", false) + @JvmField val StartingCards = Setting("startingCards", 5) + @JvmField val JokerQuantity = Setting("jokerQuantity", 2) + @JvmField val JokerValue = Setting("jokerValue", 2) + @JvmField val NegativeJacks = Setting("negativeJacks", false) + @JvmField val IncludeMoons = Setting("includeMoons", false) + @JvmField val IncludeStars = Setting("includeStars", false) + @JvmField val CardReveal = Setting("cardReveal", false) + + // Players + @JvmField val PlayerName = Setting("playerName", "Player") + @JvmField val OpponentOneName = Setting("opponentOneName", "Mark") + @JvmField val OpponentTwoName = Setting("opponentTwoName", "David") + @JvmField val OpponentThreeName = Setting("opponentThreeName", "Tom") + @JvmField val OpponentOneStrategy = Setting("opponentOneStrategy", STRATEGY_BASIC) + @JvmField val OpponentTwoStrategy = Setting("opponentTwoStrategy", STRATEGY_BASIC) + @JvmField val OpponentThreeStrategy = Setting("opponentThreeStrategy", STRATEGY_BASIC) + @JvmField val OpponentTwoEnabled = Setting("opponentTwoEnabled", false) + @JvmField val OpponentThreeEnabled = Setting("opponentThreeEnabled", false) + @JvmField val ApiStrategies = Setting("apiStrategies", "") + + // Appearance + @JvmField val DeckDesign = Setting("deckDesign", DECK_DESIGN_CLASSIC) + @JvmField val JokerDesign = Setting("jokerDesign", JOKER_DESIGN_CLASSIC) + @JvmField val NumberOfColours = Setting("numberOfColours", TWO_COLOURS) + @JvmField val CardBacks = Setting("cardBacks", "backBlue") + @JvmField val LookAndFeel = Setting("lookAndFeel", "Metal") + + // Misc + @JvmField val SaveReplays = Setting("saveReplays", false) + @JvmField val ReplayDirectory = Setting("replayDirectory", System.getProperty("user.dir")) + @JvmField val OpenReplayOnFirstRound = Setting("openReplayOnFirstRound", false) + @JvmField val GameSpeed = Setting("gameSpeed", GAME_SPEED_MEDIUM) + @JvmField val AutoSave = Setting("autoSave", false) + @JvmField val AutoStartNextRound = Setting("autoStartNextRound", false) + @JvmField val AutoStartSeconds = Setting("autoStartSeconds", 2) + @JvmField val PopUpRooms = Setting("popUpRooms", true) + @JvmField val CheckForUpdates = Setting("checkForUpdates", true) + + // Replay table preferences + @JvmField val IncludeGameModeColumn = Setting("includeGameModeColumn", true) + @JvmField val IncludeRoundsColumn = Setting("includeRoundsColumn", false) + @JvmField val IncludePlayersColumn = Setting("includePlayersColumn", true) + @JvmField val IncludeCardsColumn = Setting("includeCardsColumn", false) + @JvmField val IncludeRoomNameColumn = Setting("includeRoomNameColumn", false) + + // Invisible preferences + @JvmField val ReplayViewerHeight = Setting("rvheight", 475) + @JvmField val ReplayViewerWidth = Setting("rvwidth", 875) +} diff --git a/client/src/main/kotlin/screen/HelpDialog.kt b/client/src/main/kotlin/screen/HelpDialog.kt index fad48e9f..6544453d 100644 --- a/client/src/main/kotlin/screen/HelpDialog.kt +++ b/client/src/main/kotlin/screen/HelpDialog.kt @@ -1,6 +1,7 @@ package screen import achievement.AchievementSetting +import achievement.Reward import achievement.isUnlocked import help.FundamentalsGlossary import help.FundamentalsTheDeck @@ -42,6 +43,7 @@ import javax.swing.tree.TreeNode import javax.swing.tree.TreePath import javax.swing.tree.TreeSelectionModel import kotlin.math.max +import screen.achievement.AchievementsDialog import util.AchievementsUtil.UnlockAchievementTask import util.ClientGlobals.achievementStore import util.Registry @@ -225,7 +227,7 @@ class HelpDialog : JFrame(), TreeSelectionListener, WindowListener, Registry { gameRules.add(entropyRules) } - if (Registry.rewards.getBoolean(Registry.REWARDS_BOOLEAN_VECTROPY, false)) { + if (Reward.Vectropy.isUnlocked()) { val vectropyRules = DefaultMutableTreeNode("Vectropy") addNodeBasedOnString(vectropyRules, rulesVectropyIntroduction, searchStr) addNodeBasedOnString(vectropyRules, rulesVectropyBidding, searchStr) @@ -236,7 +238,7 @@ class HelpDialog : JFrame(), TreeSelectionListener, WindowListener, Registry { } } - if (Registry.rewards.getBoolean(Registry.REWARDS_BOOLEAN_ILLEGAL, false)) { + if (Reward.Illegal.isUnlocked()) { addNodeBasedOnString(gameRules, rulesIllegal, searchStr) } @@ -262,7 +264,7 @@ class HelpDialog : JFrame(), TreeSelectionListener, WindowListener, Registry { addNodeBasedOnString(misc, miscBugReport, searchStr) addNodeBasedOnString(misc, miscClearingSaveData, searchStr) - if (Registry.rewards.getBoolean(Registry.REWARDS_BOOLEAN_CHEATS, false)) { + if (Reward.Cheats.isUnlocked()) { addNodeBasedOnString(misc, miscCheatCodes, searchStr) } diff --git a/client/src/main/kotlin/screen/SimpleDialog.kt b/client/src/main/kotlin/screen/SimpleDialog.kt index 9d2c79fd..0ecd1d19 100644 --- a/client/src/main/kotlin/screen/SimpleDialog.kt +++ b/client/src/main/kotlin/screen/SimpleDialog.kt @@ -8,7 +8,7 @@ import javax.swing.JDialog import javax.swing.JPanel import utils.CoreGlobals.logger -abstract class SimpleDialog : JDialog(), ActionListener { +abstract class SimpleDialog(includeCancel: Boolean = true) : JDialog(), ActionListener { protected val panelOkCancel = JPanel() protected val btnOk = JButton("Ok") protected val btnCancel = JButton("Cancel") @@ -19,10 +19,12 @@ abstract class SimpleDialog : JDialog(), ActionListener { isResizable = false panelOkCancel.add(btnOk) - panelOkCancel.add(btnCancel) - btnOk.addActionListener(this) - btnCancel.addActionListener(this) + + if (includeCancel) { + panelOkCancel.add(btnCancel) + btnCancel.addActionListener(this) + } } /** Abstract methods */ diff --git a/client/src/main/kotlin/screen/AchievementsDialog.kt b/client/src/main/kotlin/screen/achievement/AchievementsDialog.kt similarity index 69% rename from client/src/main/kotlin/screen/AchievementsDialog.kt rename to client/src/main/kotlin/screen/achievement/AchievementsDialog.kt index 1ec3143a..17798c0f 100644 --- a/client/src/main/kotlin/screen/AchievementsDialog.kt +++ b/client/src/main/kotlin/screen/achievement/AchievementsDialog.kt @@ -1,5 +1,6 @@ -package screen +package screen.achievement +import achievement.Reward import achievement.getAchievementsEarned import bean.AchievementBadge import java.awt.Color @@ -7,9 +8,9 @@ import java.awt.Font import java.awt.event.ActionEvent import java.awt.event.ActionListener import java.awt.event.MouseEvent -import java.awt.event.MouseListener import java.awt.event.MouseMotionListener -import java.util.* +import java.util.Timer +import java.util.TimerTask import javax.swing.ImageIcon import javax.swing.JButton import javax.swing.JFrame @@ -18,11 +19,9 @@ import javax.swing.JPanel import javax.swing.JSeparator import javax.swing.SwingConstants import javax.swing.border.EmptyBorder -import `object`.RewardStar -import util.Images import utils.getAllChildComponentsForType -class AchievementsDialog : JFrame(), MouseMotionListener, MouseListener, ActionListener { +class AchievementsDialog : JFrame(), MouseMotionListener, ActionListener { private var currentPage = 0 private var progressShowing = 0 @@ -36,25 +35,16 @@ class AchievementsDialog : JFrame(), MouseMotionListener, MouseListener, ActionL private val btnRight = JButton("\u25B6") private val testTube = JLabel("") - private val reward5: RewardStar = - RewardStar(5, "Four Colours", RewardDialog.REWARD_BANNER_FOUR_COLOUR) - private val reward10: RewardStar = - RewardStar(10, "Negative Jacks", RewardDialog.REWARD_BANNER_NEGATIVE_JACKS) - private val reward15: RewardStar = - RewardStar(15, "Blind Play", RewardDialog.REWARD_BANNER_BLIND) - private val reward20: RewardStar = - RewardStar(20, "New Deck Design", RewardDialog.REWARD_BANNER_MINIMALIST) - private val reward25: RewardStar = - RewardStar(25, "Vectropy", RewardDialog.REWARD_BANNER_VECTROPY) - private val reward30: RewardStar = - RewardStar(30, "Card Reveal", RewardDialog.REWARD_BANNER_CARD_REVEAL) - private val reward35: RewardStar = - RewardStar(35, "Extra Suits", RewardDialog.REWARD_BANNER_EXTRA_SUITS) - private val reward40: RewardStar = - RewardStar(40, "Illegal!", RewardDialog.REWARD_BANNER_ILLEGAL) - private val reward45: RewardStar = - RewardStar(45, "New Joker Design", RewardDialog.REWARD_BANNER_DEVELOPERS) - private val reward50: RewardStar = RewardStar(50, "Cheats", RewardDialog.REWARD_BANNER_CHEATS) + private val reward5: RewardStar = RewardStar("Four Colours", Reward.FourColours) + private val reward10: RewardStar = RewardStar("Negative Jacks", Reward.NegativeJacks) + private val reward15: RewardStar = RewardStar("Blind Play", Reward.Blind) + private val reward20: RewardStar = RewardStar("New Deck Design", Reward.MinimalistDeck) + private val reward25: RewardStar = RewardStar("Vectropy", Reward.Vectropy) + private val reward30: RewardStar = RewardStar("Card Reveal", Reward.CardReveal) + private val reward35: RewardStar = RewardStar("Extra Suits", Reward.ExtraSuits) + private val reward40: RewardStar = RewardStar("Illegal!", Reward.Illegal) + private val reward45: RewardStar = RewardStar("New Joker Design", Reward.DeveloperSet) + private val reward50: RewardStar = RewardStar("Cheats", Reward.Cheats) private val title = JLabel("") private val achievementName = JLabel("Achievement Name") @@ -137,7 +127,6 @@ class AchievementsDialog : JFrame(), MouseMotionListener, MouseListener, ActionL } populateBadgeListAndAddMotionListeners() - populateStarListAndAddMouseListeners() } fun init() { @@ -153,10 +142,6 @@ class AchievementsDialog : JFrame(), MouseMotionListener, MouseListener, ActionL getAllChildComponentsForType().forEach { it.addMouseMotionListener(this) } } - private fun populateStarListAndAddMouseListeners() { - getAllChildComponentsForType().forEach { it.addMouseListener(this) } - } - private fun animateTestTube() { redrawing = true @@ -172,7 +157,6 @@ class AchievementsDialog : JFrame(), MouseMotionListener, MouseListener, ActionL private fun updateTestTube() { progressShowing = getAchievementsEarned() testTube.icon = getTubeIconForIndex(getAchievementsEarned()) - redrawStars() } private fun getTubeIconForIndex(i: Int): ImageIcon { @@ -180,20 +164,6 @@ class AchievementsDialog : JFrame(), MouseMotionListener, MouseListener, ActionL return ImageIcon(AchievementsDialog::class.java.getResource("/tubes/$name")) } - private fun redrawStars() { - getAllChildComponentsForType().forEach { star -> - if (star.isUnlocked(getAchievementsEarned())) { - star.setIcon(Images.REWARD_UNLOCKED) - star.setToolTipText(star.hoverDesc) - } else { - star.setIcon(Images.REWARD_LOCKED) - star.setToolTipText("Locked") - } - - star.repaint() - } - } - fun refresh(restartTube: Boolean) { if (restartTube) { animateTestTube() @@ -201,6 +171,7 @@ class AchievementsDialog : JFrame(), MouseMotionListener, MouseListener, ActionL updateTestTube() } + getAllChildComponentsForType().forEach { it.toggle() } getAllChildComponentsForType().forEach { it.toggle() } updateTitle() @@ -238,7 +209,6 @@ class AchievementsDialog : JFrame(), MouseMotionListener, MouseListener, ActionL } testTube.icon = getTubeIconForIndex(progressShowing) - redrawStars() if (progressShowing == getAchievementsEarned()) { redrawing = false @@ -247,41 +217,6 @@ class AchievementsDialog : JFrame(), MouseMotionListener, MouseListener, ActionL } } - override fun mouseClicked(e: MouseEvent) { - val c: RewardStar = e.component as RewardStar - if (c.isUnlocked(getAchievementsEarned()) && !redrawing) { - RewardDialog.showDialog(c.imageName) - } - } - - override fun mouseEntered(e: MouseEvent) { - val source: RewardStar = e.component as RewardStar - if (source.isUnlocked(progressShowing) && !redrawing) { - source.setIcon(Images.REWARD_UNLOCKED_HOVERED) - } - } - - override fun mouseExited(e: MouseEvent) { - val source: RewardStar = e.component as RewardStar - if (source.isUnlocked(progressShowing) && !redrawing) { - source.setIcon(Images.REWARD_UNLOCKED) - } - } - - override fun mousePressed(e: MouseEvent) { - val source: RewardStar = e.component as RewardStar - if (source.isUnlocked(getAchievementsEarned()) && !redrawing) { - source.setIcon(Images.REWARD_UNLOCKED_CLICKED) - } - } - - override fun mouseReleased(e: MouseEvent) { - val source: RewardStar = e.component as RewardStar - if (source.isUnlocked(getAchievementsEarned()) && !redrawing) { - source.setIcon(Images.REWARD_UNLOCKED) - } - } - override fun actionPerformed(arg0: ActionEvent) { if (arg0.source === btnLeft) { currentPage-- diff --git a/client/src/main/kotlin/screen/AchievementsPanel.kt b/client/src/main/kotlin/screen/achievement/AchievementsPanel.kt similarity index 95% rename from client/src/main/kotlin/screen/AchievementsPanel.kt rename to client/src/main/kotlin/screen/achievement/AchievementsPanel.kt index 49f6bb8c..d27885ba 100644 --- a/client/src/main/kotlin/screen/AchievementsPanel.kt +++ b/client/src/main/kotlin/screen/achievement/AchievementsPanel.kt @@ -1,4 +1,4 @@ -package screen +package screen.achievement import bean.AchievementBadge import javax.swing.JPanel diff --git a/client/src/main/kotlin/screen/achievement/RewardDialog.kt b/client/src/main/kotlin/screen/achievement/RewardDialog.kt new file mode 100644 index 00000000..05069dc1 --- /dev/null +++ b/client/src/main/kotlin/screen/achievement/RewardDialog.kt @@ -0,0 +1,151 @@ +package screen.achievement + +import achievement.Reward +import java.awt.BorderLayout +import java.awt.Color +import java.awt.Dimension +import java.awt.Font +import javax.swing.BorderFactory +import javax.swing.ImageIcon +import javax.swing.JLabel +import javax.swing.JPanel +import javax.swing.JTextPane +import javax.swing.SwingConstants +import screen.SimpleDialog + +class RewardDialog(reward: Reward) : SimpleDialog(false) { + private val rewardTitle = JLabel("Title") + private val imageBanner = JLabel("") + private val rewardDescription = JTextPane() + private val topPanel = JPanel() + private val buttonPanel = JPanel() + + init { + topPanel.setLayout(BorderLayout(0, 0)) + rewardTitle.setFont(Font("Tahoma", Font.BOLD, 16)) + rewardTitle.setHorizontalAlignment(SwingConstants.CENTER) + rewardTitle.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0)) + topPanel.add(rewardTitle, BorderLayout.NORTH) + val banner = ImageIcon(reward.getResource()) + imageBanner.setHorizontalAlignment(SwingConstants.CENTER) + imageBanner.setIcon(banner) + topPanel.add(imageBanner, BorderLayout.SOUTH) + contentPane.add(topPanel, BorderLayout.NORTH) + + setRewardDescriptionAndDialogSize(reward) + rewardDescription.setEditable(false) + rewardDescription.setOpaque(false) + rewardDescription.setBorder(BorderFactory.createEmptyBorder(15, 10, 10, 10)) + rewardDescription.setBackground(Color(0, 0, 0, 0)) + contentPane.add(rewardDescription, BorderLayout.CENTER) + + buttonPanel.add(btnOk) + contentPane.add(buttonPanel, BorderLayout.SOUTH) + } + + override fun okPressed() { + dispose() + } + + private fun setRewardDescriptionAndDialogSize(reward: Reward) { + var rewardStr: String + + if (reward == Reward.Blind) { + rewardTitle.setText("Blind play unlocked!") + rewardStr = + ("Ramp up the challenge by making decisions without looking at your cards!" + + "\n\nWith this option enabled, your cards will be dealt face-down by default. You can look at any time " + + "by clicking the eye but be warned: some achievements require you to go an entire game without peeking once!" + + "\n\nEnable this option by going to Tools > Preferences > Gameplay and ticking 'Play Blind'.") + + rewardDescription.setText(rewardStr) + size = Dimension(400, 410) + } else if (reward == Reward.DeveloperSet) { + rewardTitle.setText("'Developers' joker set unlocked!") + rewardStr = + ("These jokers feature the faces of four people who helped to develop Entropy." + + "\n\nUse them by going to Tools > Preferences > Appearance and selecting 'Developers' as the Joker Design.") + + rewardDescription.setText(rewardStr) + size = Dimension(400, 330) + } else if (reward == Reward.FourColours) { + rewardTitle.setText("Four colour deck unlocked!") + rewardStr = + ("You can now play with a four-colour deck, where clubs are green and diamonds are blue." + + "\n\nEnable this option by going to Tools > Preferences > Appearance and ticking 'Use 4 colour deck'.") + + rewardDescription.setText(rewardStr) + size = Dimension(400, 330) + } else if (reward == Reward.CardReveal) { + rewardTitle.setText("Card reveal unlocked!") + rewardStr = + ("Add extra pressure to the game by forcing players to reveal their cards!" + + "\n\nWith this option set, players will be forced to show a card each time they make a bid. " + + "Players do not have to reveal their last card so not all cards will be shown." + + "\n\nEnable this option by going to Tools > Preferences > Gameplay and ticking 'Players reveal cards'.") + + rewardDescription.setText(rewardStr) + size = Dimension(400, 390) + } else if (reward == Reward.NegativeJacks) { + rewardTitle.setText("Negative jacks unlocked!") + rewardStr = + ("Spice up the deck by makings Jacks worth -1 of their suit!" + + "\n\nEnable this option by going to Tools > Preferences > Gameplay and ticking 'Jacks worth -1'") + + rewardDescription.setText(rewardStr) + size = Dimension(400, 310) + } else if (reward == Reward.MinimalistDeck) { + rewardTitle.setText("'Minimalist' deck design unlocked!") + rewardStr = + ("Go for a more minimalist feel with this new deck design." + + "\n\nUse it by going to Tools > Preferences > Appearance and selecting 'Minimalist' as the Deck Design.") + + rewardDescription.setText(rewardStr) + size = Dimension(400, 310) + } else if (reward == Reward.Vectropy) { + rewardTitle.setText("Vectropy unlocked!") + rewardStr = + ("Vectropy is a variant where you have to bid in all four suits at once. " + + "New help pages have been added that detail the rules for this new game." + + "\n\nPlay Vectropy by going to Tools > Preferences > Gameplay and selecting 'Vectropy' (under Game Mode).") + + rewardDescription.setText(rewardStr) + size = Dimension(400, 350) + } else if (reward == Reward.Illegal) { + rewardTitle.setText("'Illegal' option unlocked!") + rewardStr = + ("You can now shout 'Illegal!' in response to a bid that you think is perfect! " + + "\n\nIf you're right your opponent loses a card, but if you're wrong you'll lose one - even if a challenge would have been correct!" + + "\n\nYou will see the new 'Illegal!' option the next time you play a game.") + + rewardDescription.setText(rewardStr) + size = Dimension(400, 370) + } else if (reward == Reward.ExtraSuits) { + rewardTitle.setText("Extra suits unlocked!") + rewardStr = + ("You can now play with Stars and Moons, making for up to 6 suits in total! " + + "\nSuit order remains alphabetical, making Stars the strongest suit if they are in play." + + "\n\nChoose which suits to play with by going to Tools > Preferences > Gameplay and using the options under 'Deck Setup'.") + + rewardDescription.setText(rewardStr) + size = Dimension(400, 370) + } else if (reward == Reward.Cheats) { + rewardTitle.setText("Cheats unlocked!") + rewardStr = + ("Now you can use certain codes to cheat on your opponents, and even access hidden screens!" + + "\n\nThese were first created to speed up testing, especially for things that relied on being good - seriously, who has time for that?" + + "\n\nA full list of cheats can be found under Help > Miscellaneous > Cheat Codes.") + + rewardDescription.setText(rewardStr) + size = Dimension(400, 390) + } + } + + companion object { + fun showDialog(reward: Reward) { + val dialog = RewardDialog(reward) + dialog.setLocationRelativeTo(null) + dialog.isVisible = true + } + } +} diff --git a/client/src/main/kotlin/screen/achievement/RewardStar.kt b/client/src/main/kotlin/screen/achievement/RewardStar.kt new file mode 100644 index 00000000..f1ff4f60 --- /dev/null +++ b/client/src/main/kotlin/screen/achievement/RewardStar.kt @@ -0,0 +1,59 @@ +package screen.achievement + +import achievement.Reward +import java.awt.Dimension +import java.awt.event.MouseEvent +import java.awt.event.MouseListener +import javax.swing.JLabel +import util.Images + +class RewardStar(val hoverDesc: String, val reward: Reward) : JLabel(), MouseListener { + + init { + preferredSize = Dimension(17, 16) + addMouseListener(this) + toggle() + } + + fun toggle() { + if (reward.isUnlocked()) { + setIcon(Images.REWARD_UNLOCKED) + toolTipText = hoverDesc + } else { + setIcon(Images.REWARD_LOCKED) + toolTipText = "Locked" + } + + repaint() + } + + override fun mouseClicked(e: MouseEvent?) { + if (reward.isUnlocked()) { + RewardDialog.showDialog(reward) + } + } + + override fun mousePressed(e: MouseEvent?) { + if (reward.isUnlocked()) { + setIcon(Images.REWARD_UNLOCKED_CLICKED) + } + } + + override fun mouseReleased(e: MouseEvent?) { + if (reward.isUnlocked()) { + setIcon(Images.REWARD_UNLOCKED) + } + } + + override fun mouseEntered(e: MouseEvent?) { + if (reward.isUnlocked()) { + setIcon(Images.REWARD_UNLOCKED_HOVERED) + } + } + + override fun mouseExited(e: MouseEvent?) { + if (reward.isUnlocked()) { + setIcon(Images.REWARD_UNLOCKED) + } + } +} diff --git a/client/src/main/kotlin/screen/preference/AbstractPreferencesPanel.kt b/client/src/main/kotlin/screen/preference/AbstractPreferencesPanel.kt new file mode 100644 index 00000000..15d412a9 --- /dev/null +++ b/client/src/main/kotlin/screen/preference/AbstractPreferencesPanel.kt @@ -0,0 +1,27 @@ +package screen.preference + +import achievement.Reward +import java.awt.event.ActionListener +import javax.swing.AbstractButton +import javax.swing.JPanel + +abstract class AbstractPreferencesPanel(protected val parentDialog: PreferencesDialog) : + JPanel(), ActionListener { + abstract fun initVariables() + + abstract fun valid(): Boolean + + abstract fun savePreferences() + + protected fun toggleLockedComponent(c: AbstractButton, requiredReward: Reward) { + val unlocked = requiredReward.isUnlocked() + val text = if (unlocked) c.text else "Locked" + val toolTipText = + if (unlocked) c.toolTipText + else "Unlock at " + requiredReward.threshold + " achievements" + + c.setText(text) + c.setToolTipText(toolTipText) + c.setEnabled(unlocked) + } +} diff --git a/client/src/main/kotlin/screen/preference/PreferencesDialog.kt b/client/src/main/kotlin/screen/preference/PreferencesDialog.kt new file mode 100644 index 00000000..27c1f029 --- /dev/null +++ b/client/src/main/kotlin/screen/preference/PreferencesDialog.kt @@ -0,0 +1,74 @@ +package screen.preference + +import game.GameMode +import java.awt.BorderLayout +import javax.swing.BorderFactory +import javax.swing.JPanel +import javax.swing.JScrollPane +import javax.swing.JTabbedPane +import javax.swing.SwingConstants +import screen.SimpleDialog +import util.ApiUtil +import utils.getAllChildComponentsForType + +class PreferencesDialog : SimpleDialog() { + private val tabbedPane = JTabbedPane(SwingConstants.TOP) + private val gameplayPanel = PreferencesPanelGameplay(this) + private val appearanceScrollPane = JScrollPane() + private val appearancePanel = PreferencesPanelAppearance(this) + private val playersPanel = PreferencesPanelPlayers(this) + private val miscPanel = PreferencesPanelMisc(this) + private val okCancelPanel = JPanel() + + init { + contentPane.setLayout(BorderLayout(0, 0)) + tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT) + contentPane.add(tabbedPane) + appearanceScrollPane.getVerticalScrollBar().setUnitIncrement(16) + tabbedPane.addTab("Gameplay", null, gameplayPanel, null) + tabbedPane.addTab("Players", null, playersPanel, null) + appearanceScrollPane.setViewportView(appearancePanel) + tabbedPane.addTab("Appearance", null, appearanceScrollPane, null) + tabbedPane.addTab("Miscellaneous", null, miscPanel, null) + contentPane.add(okCancelPanel, BorderLayout.SOUTH) + okCancelPanel.setBorder(BorderFactory.createEmptyBorder(10, 150, 10, 150)) + okCancelPanel.setLayout(BorderLayout(0, 0)) + okCancelPanel.add(btnOk, BorderLayout.WEST) + okCancelPanel.add(btnCancel, BorderLayout.EAST) + + childPanels().forEach { panel -> panel.initVariables() } + } + + private fun valid(): Boolean { + childPanels().forEach { panel -> + if (!panel.valid()) { + tabbedPane.selectedComponent = panel + return false + } + } + + return true + } + + fun gameModeChanged(gameMode: GameMode) { + playersPanel.updateStrategySelection(gameMode) + } + + private fun childPanels() = getAllChildComponentsForType() + + override fun okPressed() { + if (valid()) { + childPanels().forEach { it.savePreferences() } + closeDialog() + } + } + + override fun cancelPressed() { + closeDialog() + } + + private fun closeDialog() { + ApiUtil.clearCache() + dispose() + } +} diff --git a/client/src/main/kotlin/screen/preference/PreferencesPanelAppearance.kt b/client/src/main/kotlin/screen/preference/PreferencesPanelAppearance.kt new file mode 100644 index 00000000..bd2ffba5 --- /dev/null +++ b/client/src/main/kotlin/screen/preference/PreferencesPanelAppearance.kt @@ -0,0 +1,369 @@ +package screen.preference + +import achievement.Reward +import bean.ComboBoxItem +import java.awt.Color +import java.awt.Dimension +import java.awt.Font +import java.awt.event.ActionEvent +import java.awt.event.ItemEvent +import java.awt.event.ItemListener +import java.util.Vector +import javax.swing.BorderFactory +import javax.swing.ButtonGroup +import javax.swing.ComboBoxModel +import javax.swing.DefaultComboBoxModel +import javax.swing.ImageIcon +import javax.swing.JCheckBox +import javax.swing.JComboBox +import javax.swing.JLabel +import javax.swing.JPanel +import javax.swing.JRadioButton +import javax.swing.JSeparator +import javax.swing.JTextPane +import javax.swing.SwingConstants +import javax.swing.UIManager +import javax.swing.border.LineBorder +import javax.swing.text.DefaultCaret +import `object`.DisabledComboBoxModel +import preference.DECK_DESIGN_ALTERNATE +import preference.DECK_DESIGN_CLASSIC +import preference.FOUR_COLOURS +import preference.JOKER_DESIGN_CLASSIC +import preference.JOKER_DESIGN_DEVELOPERS +import preference.PreferenceSetting +import preference.TWO_COLOURS +import preference.getPreference +import screen.MainScreen +import screen.ScreenCache +import util.ClientGlobals.preferenceStore +import util.GameUtil + +class PreferencesPanelAppearance(parent: PreferencesDialog) : + AbstractPreferencesPanel(parent), ItemListener { + private var deckDesign = "" + private var jokerDesign = "" + private var cardBacks = "" + private var numberOfColours = "" + private var lookAndFeel = "" + + private val lblVisualPreferences = JLabel("Appearance") + private val separator_1 = JSeparator() + private val deckDesignPanel = JPanel() + private val bgDeckDesign = ButtonGroup() + private val lblCardDesign = JLabel("Card Design") + private val rdbtnClassicDesign = JRadioButton("Classic") + private val rdbtnMinimalistDesign = JRadioButton("Minimalist") + private val deckPreviewPanel = JPanel() + private val labelJc = JLabel() + private val labelQd = JLabel() + private val labelKh = JLabel() + private val labelAs = JLabel() + private val jokerDesignPanel = JPanel() + private val bgJokerDesign = ButtonGroup() + private val rdbtnClassicJokers = JRadioButton("Classic") + private val rdbtnDeveloperJokers = JRadioButton("Developers") + private val lblJokerDesign = JLabel("Joker Design") + private val jokerPreviewPanel = JPanel() + private val labelJo0 = JLabel() + private val labelJo1 = JLabel() + private val labelJo2 = JLabel() + private val labelJo3 = JLabel() + private val cbFourColour = JCheckBox("Use 4 colour deck") + private val backDesignPanel = JPanel() + private val lblCardBacks = JLabel("Back Design") + private val comboBoxBacks = JComboBox>() + private val comboBoxLookAndFeel = JComboBox() + private val labelBack = JLabel() + private val lblLookFeel = JLabel("Look & Feel") + private val txtpnLookAndFeelDisclaimer = JTextPane() + private val panelLookAndFeel = JPanel() + + init { + preferredSize = Dimension(400, 760) + setLayout(null) + + bgDeckDesign.add(rdbtnClassicDesign) + bgDeckDesign.add(rdbtnMinimalistDesign) + bgJokerDesign.add(rdbtnClassicJokers) + bgJokerDesign.add(rdbtnDeveloperJokers) + deckDesignPanel.setBounds(17, 80, 374, 58) + add(deckDesignPanel) + deckDesignPanel.setBorder(LineBorder(Color.GRAY)) + deckDesignPanel.setLayout(null) + rdbtnClassicDesign.setBounds(6, 30, 72, 23) + deckDesignPanel.add(rdbtnClassicDesign) + rdbtnMinimalistDesign.name = "MinimalistDesignRadio" + rdbtnMinimalistDesign.setBounds(80, 30, 146, 23) + deckDesignPanel.add(rdbtnMinimalistDesign) + deckDesignPanel.add(lblCardDesign) + deckPreviewPanel.setBounds(17, 137, 374, 136) + add(deckPreviewPanel) + deckPreviewPanel.setBorder(LineBorder(Color.GRAY)) + deckPreviewPanel.setLayout(null) + labelKh.setBounds(187, 20, 72, 96) + deckPreviewPanel.add(labelKh) + labelJc.setBounds(43, 20, 72, 96) + deckPreviewPanel.add(labelJc) + labelQd.setBounds(115, 20, 72, 96) + deckPreviewPanel.add(labelQd) + labelAs.setBounds(259, 20, 72, 96) + deckPreviewPanel.add(labelAs) + lblCardDesign.setHorizontalAlignment(SwingConstants.CENTER) + lblCardDesign.setFont(Font("Tahoma", Font.BOLD, 14)) + lblCardDesign.setBounds(131, 8, 113, 17) + lblVisualPreferences.setHorizontalAlignment(SwingConstants.CENTER) + lblVisualPreferences.setBounds(178, 12, 72, 17) + add(lblVisualPreferences) + lblVisualPreferences.setFont(Font("Tahoma", Font.PLAIN, 14)) + add(separator_1) + jokerDesignPanel.setLayout(null) + jokerDesignPanel.setBorder(LineBorder(Color.GRAY)) + jokerDesignPanel.setBounds(17, 288, 374, 58) + add(jokerDesignPanel) + rdbtnClassicJokers.setBounds(6, 30, 72, 23) + jokerDesignPanel.add(rdbtnClassicJokers) + rdbtnDeveloperJokers.name = "DeveloperJokersRadio" + rdbtnDeveloperJokers.setBounds(80, 30, 102, 23) + jokerDesignPanel.add(rdbtnDeveloperJokers) + separator_1.setBounds(0, 38, 429, 2) + lblJokerDesign.setHorizontalAlignment(SwingConstants.CENTER) + lblJokerDesign.setFont(Font("Tahoma", Font.BOLD, 14)) + lblJokerDesign.setBounds(136, 8, 102, 17) + jokerDesignPanel.add(lblJokerDesign) + jokerPreviewPanel.setLayout(null) + jokerPreviewPanel.setBorder(LineBorder(Color.GRAY)) + jokerPreviewPanel.setBounds(17, 345, 374, 136) + add(jokerPreviewPanel) + labelJo2.setBounds(187, 20, 72, 96) + jokerPreviewPanel.add(labelJo2) + labelJo0.setBounds(43, 20, 72, 96) + jokerPreviewPanel.add(labelJo0) + labelJo1.setBounds(115, 20, 72, 96) + jokerPreviewPanel.add(labelJo1) + labelJo3.setBounds(259, 20, 72, 96) + jokerPreviewPanel.add(labelJo3) + cbFourColour.name = "FourColourCheckbox" + cbFourColour.setBounds(17, 48, 135, 23) + add(cbFourColour) + backDesignPanel.setLayout(null) + backDesignPanel.setBorder(LineBorder(Color.GRAY)) + backDesignPanel.setBounds(17, 496, 374, 114) + add(backDesignPanel) + lblCardBacks.setHorizontalAlignment(SwingConstants.CENTER) + lblCardBacks.setFont(Font("Tahoma", Font.BOLD, 14)) + lblCardBacks.setBounds(127, 8, 102, 17) + backDesignPanel.add(lblCardBacks) + labelBack.name = "BackPreview" + labelBack.setBounds(23, 9, 72, 96) + backDesignPanel.add(labelBack) + comboBoxBacks.name = "backs" + comboBoxBacks.setBounds(121, 46, 190, 22) + backDesignPanel.add(comboBoxBacks) + panelLookAndFeel.setLayout(null) + panelLookAndFeel.setBorder(LineBorder(Color.GRAY)) + panelLookAndFeel.setBounds(17, 625, 374, 114) + add(panelLookAndFeel) + lblLookFeel.setHorizontalAlignment(SwingConstants.CENTER) + lblLookFeel.setFont(Font("Tahoma", Font.BOLD, 14)) + lblLookFeel.setBounds(127, 8, 102, 17) + panelLookAndFeel.add(lblLookFeel) + comboBoxLookAndFeel.setBounds(86, 81, 190, 22) + panelLookAndFeel.add(comboBoxLookAndFeel) + val caret = DefaultCaret() + caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE) + txtpnLookAndFeelDisclaimer.setCaret(caret) + txtpnLookAndFeelDisclaimer.setText( + "Note: These options are experimental. You will need to restart for this to take effect." + ) + txtpnLookAndFeelDisclaimer.setBounds(10, 28, 354, 40) + txtpnLookAndFeelDisclaimer.setOpaque(false) + txtpnLookAndFeelDisclaimer.setBorder(BorderFactory.createEmptyBorder()) + txtpnLookAndFeelDisclaimer.setBackground(Color(0, 0, 0, 0)) + txtpnLookAndFeelDisclaimer.setEditable(false) + panelLookAndFeel.add(txtpnLookAndFeelDisclaimer) + + rdbtnClassicDesign.addActionListener(this) + rdbtnMinimalistDesign.addActionListener(this) + rdbtnClassicJokers.addActionListener(this) + rdbtnDeveloperJokers.addActionListener(this) + comboBoxBacks.addActionListener(this) + cbFourColour.addItemListener(this) + } + + /** Abstract methods */ + override fun initVariables() { + getVariablesFromPrefs() + + selectRadioButtonsBasedOnDirectories() + refreshDeckPreview() + refreshJokerPreview() + + selectCardBackBasedOnPreference() + refreshCardBackPreview() + setLookAndFeelComboBoxModel() + + hideLockedFields() + } + + override fun valid(): Boolean { + return true + } + + override fun savePreferences() { + preferenceStore.save(PreferenceSetting.DeckDesign, deckDesign) + preferenceStore.save(PreferenceSetting.JokerDesign, jokerDesign) + preferenceStore.save(PreferenceSetting.NumberOfColours, numberOfColours) + preferenceStore.save(PreferenceSetting.CardBacks, cardBacks) + preferenceStore.save( + PreferenceSetting.LookAndFeel, + comboBoxLookAndFeel.selectedItem as String, + ) + + ScreenCache.get().fireAppearancePreferencesChange() + } + + private fun getVariablesFromPrefs() { + deckDesign = getPreference(PreferenceSetting.DeckDesign) + jokerDesign = getPreference(PreferenceSetting.JokerDesign) + numberOfColours = getPreference(PreferenceSetting.NumberOfColours) + cardBacks = getPreference(PreferenceSetting.CardBacks) + lookAndFeel = getPreference(PreferenceSetting.LookAndFeel) + } + + private fun hideLockedFields() { + toggleLockedComponent(cbFourColour, Reward.FourColours) + toggleLockedComponent(rdbtnMinimalistDesign, Reward.MinimalistDeck) + toggleLockedComponent(rdbtnDeveloperJokers, Reward.DeveloperSet) + } + + private fun refreshDeckPreview() { + val jackClubs = GameUtil.getImageForCard("Jc", deckDesign, jokerDesign, numberOfColours) + val queenDiamonds = GameUtil.getImageForCard("Qd", deckDesign, jokerDesign, numberOfColours) + val kingHearts = GameUtil.getImageForCard("Kh", deckDesign, jokerDesign, numberOfColours) + val aceSpades = GameUtil.getImageForCard("As", deckDesign, jokerDesign, numberOfColours) + labelJc.setIcon(jackClubs) + labelQd.setIcon(queenDiamonds) + labelKh.setIcon(kingHearts) + labelAs.setIcon(aceSpades) + } + + private fun refreshJokerPreview() { + val jo0 = GameUtil.getImageForCard("Jo0", deckDesign, jokerDesign, numberOfColours) + val jo1 = GameUtil.getImageForCard("Jo1", deckDesign, jokerDesign, numberOfColours) + val jo2 = GameUtil.getImageForCard("Jo2", deckDesign, jokerDesign, numberOfColours) + val jo3 = GameUtil.getImageForCard("Jo3", deckDesign, jokerDesign, numberOfColours) + labelJo0.setIcon(jo0) + labelJo1.setIcon(jo1) + labelJo2.setIcon(jo2) + labelJo3.setIcon(jo3) + } + + private fun selectCardBackBasedOnPreference() { + val backs = initialiseBacksVector() + + val model: ComboBoxModel> = DisabledComboBoxModel(backs) + comboBoxBacks.setModel(model) + + val selectedItem = backs.firstOrNull { it.hiddenData == cardBacks } ?: backs.firstElement() + comboBoxBacks.setSelectedItem(selectedItem) + } + + private fun initialiseBacksVector(): Vector> { + val backs = Vector>() + + backs.addElement(ComboBoxItem("backBlue", "Blue", true)) + backs.addElement(ComboBoxItem("backRed", "Red", true)) + + backs.addElement(makeComboBoxItem("backGreen", "Green", Reward.FourColours)) + backs.addElement(makeComboBoxItem("backPurple", "Purple", Reward.NegativeJacks)) + backs.addElement(makeComboBoxItem("backOrange", "Orange", Reward.Blind)) + backs.addElement(makeComboBoxItem("backLightBlue", "Light Blue", Reward.MinimalistDeck)) + backs.addElement(makeComboBoxItem("backPink", "Pink", Reward.Vectropy)) + backs.addElement(makeComboBoxItem("backSilver", "Silver", Reward.CardReveal)) + backs.addElement(makeComboBoxItem("backGold", "Gold", Reward.ExtraSuits)) + backs.addElement(makeComboBoxItem("backMatrix", "Matrix", Reward.Illegal)) + backs.addElement(makeComboBoxItem("backCosmic", "Cosmic", Reward.DeveloperSet)) + backs.addElement(makeComboBoxItem("backRainbow", "Rainbow", Reward.Cheats)) + + return backs + } + + private fun makeComboBoxItem(assetName: String, displayName: String, reward: Reward) = + if (reward.isUnlocked()) { + ComboBoxItem(assetName, displayName, true) + } else { + ComboBoxItem("", reward.threshold.toString() + " achievements to unlock", false) + } + + private fun setLookAndFeelComboBoxModel() { + val backs = Vector() + for (info in UIManager.getInstalledLookAndFeels()) { + val lookAndFeelName = info.getName() + backs.add(lookAndFeelName) + } + + val model: ComboBoxModel = DefaultComboBoxModel(backs) + comboBoxLookAndFeel.setModel(model) + comboBoxLookAndFeel.setSelectedItem(lookAndFeel) + } + + private fun refreshCardBackPreview() { + val selection = comboBoxBacks.selectedItem as ComboBoxItem? + if (selection == null) { + cardBacks = comboBoxBacks.getItemAt(0)!!.hiddenData + } else { + cardBacks = selection.hiddenData + } + + val back = ImageIcon(javaClass.getResource("/backs/$cardBacks.png")) + labelBack.setIcon(back) + } + + private fun selectRadioButtonsBasedOnDirectories() { + cbFourColour.setSelected(numberOfColours == FOUR_COLOURS) + + if (deckDesign == DECK_DESIGN_CLASSIC) { + rdbtnClassicDesign.setSelected(true) + } else if (deckDesign == DECK_DESIGN_ALTERNATE) { + rdbtnMinimalistDesign.setSelected(true) + } + + if (jokerDesign == JOKER_DESIGN_CLASSIC) { + rdbtnClassicJokers.setSelected(true) + } else if (jokerDesign == JOKER_DESIGN_DEVELOPERS) { + rdbtnDeveloperJokers.setSelected(true) + } + } + + override fun actionPerformed(arg0: ActionEvent) { + val source = arg0.getSource() + if (source === rdbtnClassicDesign) { + deckDesign = DECK_DESIGN_CLASSIC + refreshDeckPreview() + } else if (source === rdbtnMinimalistDesign) { + deckDesign = DECK_DESIGN_ALTERNATE + refreshDeckPreview() + } else if (source === rdbtnClassicJokers) { + jokerDesign = JOKER_DESIGN_CLASSIC + refreshJokerPreview() + } else if (source === rdbtnDeveloperJokers) { + jokerDesign = JOKER_DESIGN_DEVELOPERS + refreshJokerPreview() + } else if (source === comboBoxBacks) { + refreshCardBackPreview() + } + } + + override fun itemStateChanged(arg0: ItemEvent?) { + numberOfColours = + if (cbFourColour.isSelected) { + FOUR_COLOURS + } else { + TWO_COLOURS + } + + refreshDeckPreview() + refreshJokerPreview() + } +} diff --git a/client/src/main/kotlin/screen/preference/PreferencesPanelGameplay.kt b/client/src/main/kotlin/screen/preference/PreferencesPanelGameplay.kt new file mode 100644 index 00000000..1bd1e3ec --- /dev/null +++ b/client/src/main/kotlin/screen/preference/PreferencesPanelGameplay.kt @@ -0,0 +1,304 @@ +package screen.preference + +import achievement.Reward +import game.GameMode +import java.awt.FlowLayout +import java.awt.Font +import java.awt.GridLayout +import java.awt.event.ActionEvent +import java.awt.event.ItemEvent +import java.awt.event.ItemListener +import javax.swing.ButtonGroup +import javax.swing.JCheckBox +import javax.swing.JLabel +import javax.swing.JPanel +import javax.swing.JRadioButton +import javax.swing.JSeparator +import javax.swing.JSlider +import javax.swing.JSpinner +import javax.swing.SpinnerNumberModel +import javax.swing.border.EmptyBorder +import javax.swing.border.TitledBorder +import javax.swing.event.ChangeEvent +import javax.swing.event.ChangeListener +import kotlin.math.max +import preference.PreferenceSetting +import preference.getPreference +import util.ClientGlobals.preferenceStore +import util.Registry + +class PreferencesPanelGameplay(parent: PreferencesDialog) : + AbstractPreferencesPanel(parent), ChangeListener, ItemListener, Registry { + private var gameMode = GameMode.Entropy + private var includeJokers = false + private var numberOfCards = 5 + private var jokerQuantity = 2 + private var jokerValue = 2 + private var playBlind = false + private var playWithHandicap = false + private var handicapAmount = 1 + private var includeStars = false + private var includeMoons = false + private var negativeJacks = false + private var cardReveal = false + + private val lblGameplay = JLabel("Gameplay") + private val separatorTitle = JSeparator() + private val panelGameMode = JPanel() + private val bgMode = ButtonGroup() + private val rdbtnEntropy = JRadioButton("Entropy") + private val rdbtnVectropy = JRadioButton("Vectropy") + private val panelStartingCards = JPanel() + private val numberOfCardsSlider = JSlider() + private val panelGameplay = JPanel() + private val handicapPanel = JPanel() + private val cbHandicap = JCheckBox("Handicap:") + private val handicapAmountSpinner = JSpinner() + private val cbPlayBlind = JCheckBox("Play Blind") + private val cbPlayersRevealCards = JCheckBox("Players reveal cards") + private val panelDeck = JPanel() + private val panelJokers = JPanel() + private val cbJokers = JCheckBox("Jokers") + private val jokerQuantitySpinner = JSpinner() + private val lblWorth = JLabel("worth") + private val jokerValueSpinner = JSpinner() + private val cbNegativeJacks = JCheckBox("Jacks worth -1") + private val cbIncludeMoons = JCheckBox("Include Moons") + private val cbIncludeStars = JCheckBox("Include Stars") + private val lblWarning = + JLabel("Note: Changes will not take effect until you start a new game.") + + init { + setLayout(null) + separatorTitle.setBounds(0, 38, 429, 2) + add(separatorTitle) + lblGameplay.setBounds(184, 12, 60, 17) + add(lblGameplay) + lblGameplay.setFont(Font("Tahoma", Font.PLAIN, 14)) + lblWarning.setBounds(65, 395, 304, 14) + add(lblWarning) + lblWarning.setFont(Font("Tahoma", Font.ITALIC, 11)) + panelGameMode.setBorder( + TitledBorder(null, "Mode", TitledBorder.LEADING, TitledBorder.TOP, null, null) + ) + panelGameMode.setBounds(20, 51, 165, 73) + add(panelGameMode) + panelGameMode.setLayout(FlowLayout(FlowLayout.LEADING, 5, 10)) + panelGameMode.add(rdbtnEntropy) + rdbtnEntropy.setFont(Font("Tahoma", Font.PLAIN, 11)) + bgMode.add(rdbtnEntropy) + panelGameMode.add(rdbtnVectropy) + rdbtnVectropy.setFont(Font("Tahoma", Font.PLAIN, 11)) + bgMode.add(rdbtnVectropy) + panelDeck.setBorder( + TitledBorder(null, "Deck", TitledBorder.LEADING, TitledBorder.TOP, null, null) + ) + panelDeck.setBounds(20, 253, 393, 131) + add(panelDeck) + panelDeck.setLayout(GridLayout(0, 1, 0, 0)) + val fl_panelJokers = panelJokers.layout as FlowLayout + fl_panelJokers.setAlignment(FlowLayout.LEFT) + panelJokers.setBorder(EmptyBorder(0, -5, 0, 0)) + panelDeck.add(panelJokers) + panelJokers.add(cbJokers) + cbJokers.setFont(Font("Tahoma", Font.PLAIN, 11)) + jokerQuantitySpinner.setFont(Font("Tahoma", Font.PLAIN, 11)) + panelJokers.add(jokerQuantitySpinner) + lblWorth.setFont(Font("Tahoma", Font.PLAIN, 11)) + panelJokers.add(lblWorth) + jokerValueSpinner.setFont(Font("Tahoma", Font.PLAIN, 11)) + panelJokers.add(jokerValueSpinner) + cbJokers.addItemListener(this) + panelDeck.add(cbNegativeJacks) + cbNegativeJacks.setSelected(false) + cbNegativeJacks.setFont(Font("Tahoma", Font.PLAIN, 11)) + panelDeck.add(cbIncludeMoons) + cbIncludeMoons.setFont(Font("Tahoma", Font.PLAIN, 11)) + panelDeck.add(cbIncludeStars) + cbIncludeStars.setFont(Font("Tahoma", Font.PLAIN, 11)) + panelGameplay.setBorder( + TitledBorder(null, "Gameplay", TitledBorder.LEADING, TitledBorder.TOP, null, null) + ) + panelGameplay.setBounds(20, 135, 393, 107) + add(panelGameplay) + panelGameplay.setLayout(GridLayout(0, 1, 0, 0)) + handicapPanel.setBorder(EmptyBorder(0, -5, 0, 0)) + val flowLayout_1 = handicapPanel.layout as FlowLayout + flowLayout_1.setAlignment(FlowLayout.LEADING) + panelGameplay.add(handicapPanel) + handicapPanel.add(cbHandicap) + cbHandicap.setFont(Font("Tahoma", Font.PLAIN, 11)) + cbHandicap.setToolTipText("Start with fewer cards than your opponents.") + handicapAmountSpinner.setFont(Font("Tahoma", Font.PLAIN, 11)) + handicapPanel.add(handicapAmountSpinner) + handicapAmountSpinner.setToolTipText("Start with this many cards less than your opponents.") + cbHandicap.addItemListener(this) + panelGameplay.add(cbPlayBlind) + cbPlayBlind.setFont(Font("Tahoma", Font.PLAIN, 11)) + cbPlayBlind.setToolTipText( + "Your hand will be face-down each round until you choose to view it manually." + ) + cbPlayersRevealCards.setFont(Font("Tahoma", Font.PLAIN, 11)) + panelGameplay.add(cbPlayersRevealCards) + panelStartingCards.setBorder( + TitledBorder(null, "Starting cards", TitledBorder.LEADING, TitledBorder.TOP, null, null) + ) + panelStartingCards.setBounds(195, 51, 218, 73) + add(panelStartingCards) + numberOfCardsSlider.setFont(Font("Tahoma", Font.PLAIN, 11)) + panelStartingCards.add(numberOfCardsSlider) + numberOfCardsSlider.setMinorTickSpacing(1) + numberOfCardsSlider.setPaintTicks(true) + numberOfCardsSlider.setPaintLabels(true) + numberOfCardsSlider.setMajorTickSpacing(4) + numberOfCardsSlider.setToolTipText("") + numberOfCardsSlider.setMinimum(1) + numberOfCardsSlider.setMaximum(5) + numberOfCardsSlider.addChangeListener(this) + handicapAmountSpinner.addChangeListener(this) + + rdbtnEntropy.addActionListener(this) + rdbtnVectropy.addActionListener(this) + } + + override fun initVariables() { + this.getVariablesFromPreferences() + + cbJokers.setSelected(includeJokers) + cbNegativeJacks.setSelected(negativeJacks) + cbPlayersRevealCards.setSelected(cardReveal) + jokerQuantitySpinner.setModel(SpinnerNumberModel(jokerQuantity, 1, 4, 1)) + jokerValueSpinner.setModel(SpinnerNumberModel(jokerValue, 2, 4, 1)) + numberOfCardsSlider.setValue(numberOfCards) + jokerQuantitySpinner.value = jokerQuantity + jokerValueSpinner.value = jokerValue + cbPlayBlind.setSelected(playBlind) + cbHandicap.setSelected(playWithHandicap) + jokerQuantitySpinner.setEnabled(includeJokers) + lblWorth.setEnabled(includeJokers) + jokerValueSpinner.setEnabled(includeJokers) + handicapAmountSpinner.setEnabled(playWithHandicap) + + adjustHandicapSpinner() + + cbIncludeStars.setSelected(includeStars) + cbIncludeMoons.setSelected(includeMoons) + + rdbtnEntropy.setSelected(gameMode == GameMode.Entropy) + rdbtnVectropy.setSelected(gameMode == GameMode.Vectropy) + + hideLockedFields() + } + + override fun valid(): Boolean { + return true + } + + override fun savePreferences() { + numberOfCards = numberOfCardsSlider.value + negativeJacks = cbNegativeJacks.isSelected + cardReveal = cbPlayersRevealCards.isSelected + jokerQuantity = if (includeJokers) jokerQuantitySpinner.value as Int else 0 + jokerValue = jokerValueSpinner.value as Int + handicapAmount = handicapAmountSpinner.value as Int + playBlind = cbPlayBlind.isSelected + includeStars = cbIncludeStars.isSelected + includeMoons = cbIncludeMoons.isSelected + + preferenceStore.save(PreferenceSetting.StartingCards, numberOfCards) + preferenceStore.save(PreferenceSetting.StartingCards, numberOfCards) + preferenceStore.save(PreferenceSetting.NegativeJacks, negativeJacks) + preferenceStore.save(PreferenceSetting.JokerQuantity, jokerQuantity) + preferenceStore.save(PreferenceSetting.JokerValue, jokerValue) + + preferenceStore.save(PreferenceSetting.PlayWithHandicap, playWithHandicap) + preferenceStore.save(PreferenceSetting.HandicapAmount, handicapAmount) + preferenceStore.save(PreferenceSetting.PlayBlind, playBlind) + preferenceStore.save(PreferenceSetting.IncludeStars, includeStars) + preferenceStore.save(PreferenceSetting.IncludeMoons, includeMoons) + preferenceStore.save(PreferenceSetting.CardReveal, cardReveal) + preferenceStore.save(PreferenceSetting.GameMode, gameMode.name) + } + + private fun getVariablesFromPreferences() { + numberOfCards = getPreference(PreferenceSetting.StartingCards) + jokerQuantity = getPreference(PreferenceSetting.JokerQuantity) + includeJokers = jokerQuantity > 0 + jokerValue = getPreference(PreferenceSetting.JokerValue) + playWithHandicap = getPreference(PreferenceSetting.PlayWithHandicap) + handicapAmount = getPreference(PreferenceSetting.HandicapAmount) + playBlind = getPreference(PreferenceSetting.PlayBlind) + includeStars = getPreference(PreferenceSetting.IncludeStars) + includeMoons = getPreference(PreferenceSetting.IncludeMoons) + negativeJacks = getPreference(PreferenceSetting.NegativeJacks) + cardReveal = getPreference(PreferenceSetting.CardReveal) + gameMode = GameMode.valueOf(getPreference(PreferenceSetting.GameMode)) + } + + private fun adjustHandicapSpinner() { + if (numberOfCards == 1) { + cbHandicap.setSelected(false) + cbHandicap.setEnabled(false) + handicapAmountSpinner.setEnabled(false) + } else { + cbHandicap.setEnabled(true) + handicapAmountSpinner.setEnabled(cbHandicap.isSelected) + + val newMax = max(1, numberOfCards - 1) + if (handicapAmount > newMax) { + handicapAmount = newMax + } + + handicapAmountSpinner.setModel(SpinnerNumberModel(handicapAmount, 1, newMax, 1)) + } + } + + private fun hideLockedFields() { + toggleLockedComponent(cbNegativeJacks, Reward.NegativeJacks) + toggleLockedComponent(cbPlayBlind, Reward.Blind) + toggleLockedComponent(rdbtnVectropy, Reward.Vectropy) + toggleLockedComponent(cbPlayersRevealCards, Reward.CardReveal) + toggleLockedComponent(cbIncludeMoons, Reward.ExtraSuits) + toggleLockedComponent(cbIncludeStars, Reward.ExtraSuits) + } + + override fun actionPerformed(arg0: ActionEvent) { + val originalGameMode: GameMode? = gameMode + + val source = arg0.getSource() + if (source === rdbtnEntropy) { + gameMode = GameMode.Entropy + } else if (source === rdbtnVectropy) { + gameMode = GameMode.Vectropy + } + + if (originalGameMode != gameMode) { + parentDialog.gameModeChanged(gameMode) + } + } + + override fun stateChanged(arg0: ChangeEvent) { + val source = arg0.getSource() + if (source === numberOfCardsSlider) { + if (!numberOfCardsSlider.valueIsAdjusting) { + numberOfCards = numberOfCardsSlider.value + adjustHandicapSpinner() + } + } else if (source === handicapAmountSpinner) { + handicapAmount = handicapAmountSpinner.value as Int + } + } + + override fun itemStateChanged(arg0: ItemEvent) { + val source = arg0.getSource() + if (source === cbJokers) { + includeJokers = cbJokers.isSelected + lblWorth.setEnabled(includeJokers) + jokerQuantitySpinner.setEnabled(includeJokers) + jokerValueSpinner.setEnabled(includeJokers) + } else if (source === cbHandicap) { + playWithHandicap = cbHandicap.isSelected + handicapAmountSpinner.setEnabled(playWithHandicap) + } + } +} diff --git a/client/src/main/kotlin/screen/preference/PreferencesPanelMisc.kt b/client/src/main/kotlin/screen/preference/PreferencesPanelMisc.kt new file mode 100644 index 00000000..37892d82 --- /dev/null +++ b/client/src/main/kotlin/screen/preference/PreferencesPanelMisc.kt @@ -0,0 +1,282 @@ +package screen.preference + +import java.awt.Font +import java.awt.event.ActionEvent +import java.awt.event.ItemEvent +import java.awt.event.ItemListener +import java.io.File +import javax.swing.ButtonGroup +import javax.swing.JButton +import javax.swing.JCheckBox +import javax.swing.JFileChooser +import javax.swing.JLabel +import javax.swing.JOptionPane +import javax.swing.JRadioButton +import javax.swing.JSeparator +import javax.swing.JSpinner +import javax.swing.JTextField +import javax.swing.SpinnerNumberModel +import javax.swing.SwingConstants +import preference.GAME_SPEED_FAST +import preference.GAME_SPEED_MEDIUM +import preference.GAME_SPEED_SLOW +import preference.PreferenceSetting +import preference.getPreference +import util.ClientGlobals.preferenceStore +import util.DialogUtilNew +import util.ReplayFileUtil +import utils.CoreGlobals.logger + +class PreferencesPanelMisc(parent: PreferencesDialog) : + AbstractPreferencesPanel(parent), ItemListener { + private var autosave = false + private var gameSpeed: Int = GAME_SPEED_MEDIUM + private var saveReplays = false + private var replayDirectory = "" + private var openReplayOnFirstRound = false + private var autoStartNextRound = false + private var autoStartSeconds = 2 // 2 seconds + private var popUpRoomsOnline = true + private var checkForUpdates = true + + private val lblOtherOptions = JLabel("Other Options") + private val separator_3 = JSeparator() + private val fc = JFileChooser() + private val chosenDirectory = JTextField() + private val chckbxSaveReplays = JCheckBox("Save replays") + private val btnSelectDirectory = JButton("...") + private val chckbxAutosave = JCheckBox("Autosave on exit") + private val bgSpeed = ButtonGroup() + private val rdbtnSlow = JRadioButton("Slow") + private val rdbtnMedium = JRadioButton("Medium") + private val rdbtnFast = JRadioButton("Fast") + private val lblGameSpeed = JLabel("Game speed") + private val chckbxAutoStartNextRound = JCheckBox("Automatically start next round after") + private val chckbxPopUpRooms = JCheckBox("Pop up online rooms on my turn") + private val spinnerAutoStartSeconds = JSpinner() + private val lblSeconds = JLabel("seconds") + private val lblReplayViewerDefaults = JLabel("Replay viewer default") + private val bgReplayRound = ButtonGroup() + private val rdbtnFirstRound = JRadioButton("First Round") + private val rdbtnLastRound = JRadioButton("Last Round") + private val chckbxCheckForUpdates = JCheckBox("Automatically check for updates") + + init { + setLayout(null) + + bgReplayRound.add(rdbtnFirstRound) + bgReplayRound.add(rdbtnLastRound) + bgSpeed.add(rdbtnSlow) + bgSpeed.add(rdbtnMedium) + bgSpeed.add(rdbtnFast) + chckbxSaveReplays.setFont(Font("Tahoma", Font.PLAIN, 11)) + chckbxSaveReplays.setBounds(20, 67, 91, 22) + add(chckbxSaveReplays) + lblOtherOptions.setFont(Font("Tahoma", Font.PLAIN, 14)) + lblOtherOptions.setBounds(171, 12, 86, 17) + add(lblOtherOptions) + separator_3.setBounds(0, 38, 429, 2) + add(separator_3) + chosenDirectory.name = "replayDirectory" + chosenDirectory.setBounds(116, 67, 180, 22) + chosenDirectory.setEditable(false) + add(chosenDirectory) + chosenDirectory.setColumns(10) + btnSelectDirectory.setBounds(296, 67, 20, 22) + add(btnSelectDirectory) + chckbxAutosave.setBounds(20, 180, 127, 22) + add(chckbxAutosave) + chckbxAutosave.setFont(Font("Tahoma", Font.PLAIN, 11)) + lblReplayViewerDefaults.setFont(Font("Tahoma", Font.PLAIN, 11)) + lblReplayViewerDefaults.setBounds(20, 112, 127, 14) + add(lblReplayViewerDefaults) + rdbtnFirstRound.setFont(Font("Tahoma", Font.PLAIN, 11)) + rdbtnFirstRound.setBounds(144, 109, 91, 20) + add(rdbtnFirstRound) + rdbtnLastRound.setFont(Font("Tahoma", Font.PLAIN, 11)) + rdbtnLastRound.setBounds(237, 109, 91, 20) + add(rdbtnLastRound) + lblGameSpeed.setBounds(20, 148, 86, 14) + add(lblGameSpeed) + lblGameSpeed.setHorizontalAlignment(SwingConstants.LEFT) + lblGameSpeed.setFont(Font("Tahoma", Font.PLAIN, 11)) + rdbtnSlow.setBounds(144, 144, 60, 20) + add(rdbtnSlow) + rdbtnSlow.setFont(Font("Tahoma", Font.PLAIN, 11)) + rdbtnMedium.setBounds(206, 144, 70, 20) + add(rdbtnMedium) + rdbtnMedium.setFont(Font("Tahoma", Font.PLAIN, 11)) + rdbtnFast.setBounds(274, 144, 54, 20) + add(rdbtnFast) + rdbtnFast.setFont(Font("Tahoma", Font.PLAIN, 11)) + chckbxAutoStartNextRound.setFont(Font("Tahoma", Font.PLAIN, 11)) + chckbxAutoStartNextRound.setBounds(20, 205, 208, 23) + add(chckbxAutoStartNextRound) + chckbxPopUpRooms.setFont(Font("Tahoma", Font.PLAIN, 11)) + chckbxPopUpRooms.setBounds(20, 230, 208, 23) + add(chckbxPopUpRooms) + spinnerAutoStartSeconds.setBounds(228, 205, 38, 22) + add(spinnerAutoStartSeconds) + lblSeconds.setFont(Font("Tahoma", Font.PLAIN, 11)) + lblSeconds.setBounds(275, 206, 55, 20) + add(lblSeconds) + chckbxCheckForUpdates.setFont(Font("Tahoma", Font.PLAIN, 11)) + chckbxCheckForUpdates.setBounds(20, 256, 237, 23) + add(chckbxCheckForUpdates) + fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY) + + rdbtnFast.addActionListener(this) + rdbtnMedium.addActionListener(this) + rdbtnSlow.addActionListener(this) + btnSelectDirectory.addActionListener(this) + chckbxSaveReplays.addItemListener(this) + chckbxAutoStartNextRound.addItemListener(this) + } + + /** Abstract methods */ + override fun initVariables() { + getVariablesFromPrefs() + + spinnerAutoStartSeconds.setModel(SpinnerNumberModel(autoStartSeconds, 1, 5, 1)) + chosenDirectory.text = "$replayDirectory\\Replays" + chckbxAutosave.setSelected(autosave) + rdbtnSlow.setSelected(gameSpeed == GAME_SPEED_SLOW) + rdbtnMedium.setSelected(gameSpeed == GAME_SPEED_MEDIUM) + rdbtnFast.setSelected(gameSpeed == GAME_SPEED_FAST) + chckbxSaveReplays.setSelected(saveReplays) + chosenDirectory.text = "$replayDirectory\\Replays" + chosenDirectory.setEnabled(saveReplays) + btnSelectDirectory.setEnabled(saveReplays) + chckbxAutoStartNextRound.setSelected(autoStartNextRound) + chckbxPopUpRooms.setSelected(popUpRoomsOnline) + chckbxCheckForUpdates.setSelected(checkForUpdates) + spinnerAutoStartSeconds.setEnabled(autoStartNextRound) + lblSeconds.setEnabled(autoStartNextRound) + spinnerAutoStartSeconds.setValue(autoStartSeconds) + rdbtnFirstRound.setSelected(openReplayOnFirstRound) + rdbtnLastRound.setSelected(!openReplayOnFirstRound) + } + + override fun valid(): Boolean { + return confirmChangeOfDirectory() + } + + override fun savePreferences() { + autosave = chckbxAutosave.isSelected + openReplayOnFirstRound = rdbtnFirstRound.isSelected + autoStartSeconds = spinnerAutoStartSeconds.value as Int + popUpRoomsOnline = chckbxPopUpRooms.isSelected + checkForUpdates = chckbxCheckForUpdates.isSelected + + preferenceStore.save(PreferenceSetting.SaveReplays, saveReplays) + preferenceStore.save(PreferenceSetting.AutoSave, autosave) + preferenceStore.save(PreferenceSetting.ReplayDirectory, replayDirectory) + preferenceStore.save(PreferenceSetting.OpenReplayOnFirstRound, openReplayOnFirstRound) + preferenceStore.save(PreferenceSetting.AutoStartNextRound, autoStartNextRound) + preferenceStore.save(PreferenceSetting.AutoStartSeconds, autoStartSeconds) + preferenceStore.save(PreferenceSetting.PopUpRooms, popUpRoomsOnline) + preferenceStore.save(PreferenceSetting.CheckForUpdates, checkForUpdates) + preferenceStore.save(PreferenceSetting.GameSpeed, gameSpeed) + } + + private fun getVariablesFromPrefs() { + autosave = getPreference(PreferenceSetting.AutoSave) + gameSpeed = getPreference(PreferenceSetting.GameSpeed) + saveReplays = getPreference(PreferenceSetting.SaveReplays) + replayDirectory = getPreference(PreferenceSetting.ReplayDirectory)!! + openReplayOnFirstRound = getPreference(PreferenceSetting.OpenReplayOnFirstRound) + autoStartNextRound = getPreference(PreferenceSetting.AutoStartNextRound) + autoStartSeconds = getPreference(PreferenceSetting.AutoStartSeconds) + popUpRoomsOnline = getPreference(PreferenceSetting.PopUpRooms) + checkForUpdates = getPreference(PreferenceSetting.CheckForUpdates) + } + + private fun confirmChangeOfDirectory(): Boolean { + val originalReplayDirectory: String = preferenceStore.get(PreferenceSetting.ReplayDirectory) + + val myExistingFiles = + File(originalReplayDirectory + "//Replays//" + ReplayFileUtil.FOLDER_PERSONAL_REPLAYS) + .listFiles() + var myExistingFilesLength = 0 + if (myExistingFiles != null) { + myExistingFilesLength = myExistingFiles.size + } + + val importedExistingFiles = + File(originalReplayDirectory + "//Replays//" + ReplayFileUtil.FOLDER_IMPORTED_REPLAYS) + .listFiles() + var importedExistingFilesLength = 0 + if (importedExistingFiles != null) { + importedExistingFilesLength = importedExistingFiles.size + } + + if ( + replayDirectory != originalReplayDirectory && + (myExistingFilesLength != 0 || importedExistingFilesLength != 0) + ) { + val choice = + DialogUtilNew.showQuestion( + "You have changed your replay directory but there are still files in the old one. " + + "\nWould you like to move these files to the new location?", + true, + ) + + if (choice == JOptionPane.YES_OPTION) { + ReplayFileUtil.moveReplays( + myExistingFiles, + importedExistingFiles, + originalReplayDirectory, + replayDirectory, + ) + } else if (choice == JOptionPane.CANCEL_OPTION) { + return false + } else { + DialogUtilNew.showInfo( + "Existing replay files were left in the old directory and will have to be deleted or moved manually." + ) + } + } + + return true + } + + private fun selectReplayDirectory() { + val returnVal = fc.showOpenDialog(this) + if (returnVal == JFileChooser.APPROVE_OPTION) { + val file = fc.getSelectedFile() + + replayDirectory = file.getPath() + chosenDirectory.setText("$replayDirectory\\Replays") + + logger.info("replay.dir", "Selected ${file.path} as replay directory") + } else { + logger.info("replay.dir", "Cancelled directory selection") + } + } + + override fun actionPerformed(arg0: ActionEvent) { + val source = arg0.getSource() + if (source === rdbtnFast) { + gameSpeed = GAME_SPEED_FAST + } else if (source === rdbtnMedium) { + gameSpeed = GAME_SPEED_MEDIUM + } else if (source === rdbtnSlow) { + gameSpeed = GAME_SPEED_SLOW + } else if (source === btnSelectDirectory) { + selectReplayDirectory() + } + } + + override fun itemStateChanged(arg0: ItemEvent) { + val source = arg0.getSource() + if (source === chckbxSaveReplays) { + saveReplays = chckbxSaveReplays.isSelected() + chosenDirectory.setEnabled(saveReplays) + btnSelectDirectory.setEnabled(saveReplays) + } else if (source === chckbxAutoStartNextRound) { + autoStartNextRound = chckbxAutoStartNextRound.isSelected() + lblSeconds.setEnabled(autoStartNextRound) + spinnerAutoStartSeconds.setEnabled(autoStartNextRound) + } + } +} diff --git a/client/src/main/kotlin/screen/preference/PreferencesPanelPlayers.kt b/client/src/main/kotlin/screen/preference/PreferencesPanelPlayers.kt new file mode 100644 index 00000000..138e7119 --- /dev/null +++ b/client/src/main/kotlin/screen/preference/PreferencesPanelPlayers.kt @@ -0,0 +1,374 @@ +package screen.preference + +import game.GameMode +import java.awt.Font +import java.awt.event.ActionEvent +import java.awt.event.ItemEvent +import java.awt.event.ItemListener +import java.awt.event.MouseEvent +import java.awt.event.MouseListener +import javax.swing.ComboBoxModel +import javax.swing.DefaultComboBoxModel +import javax.swing.JButton +import javax.swing.JCheckBox +import javax.swing.JComboBox +import javax.swing.JLabel +import javax.swing.JMenuItem +import javax.swing.JOptionPane +import javax.swing.JPopupMenu +import javax.swing.JScrollPane +import javax.swing.JSeparator +import javax.swing.JTable +import javax.swing.JTextField +import javax.swing.ListSelectionModel +import javax.swing.SwingConstants +import javax.swing.SwingUtilities +import javax.swing.table.TableModel +import javax.swing.table.TableRowSorter +import `object`.ApiStrategy +import `object`.LimitedDocument +import preference.PreferenceSetting +import preference.getPreference +import screen.ApiAmendDialog +import util.ApiUtil +import util.ClientGlobals.preferenceStore +import util.CpuStrategies +import util.DialogUtilNew +import util.TableUtil.DefaultModel +import util.TableUtil.SimpleRenderer + +class PreferencesPanelPlayers(parent: PreferencesDialog) : + AbstractPreferencesPanel(parent), MouseListener, ItemListener { + private var playerName = "Player" + private var opponentOneName = "Mark" + private var opponentTwoName = "Dave" + private var opponentThreeName = "Tom" + private var opponentTwoEnabled = false + private var opponentThreeEnabled = false + private var opponentOneStrategy: String = "Mark" + private var opponentTwoStrategy: String = "Basic" + private var opponentThreeStrategy: String = "Basic" + private var apiStrategies: List = emptyList() + private var gameMode: GameMode = GameMode.Entropy + + private val lblPlayers = JLabel("Players") + private val separator_2 = JSeparator() + private val lblPlayerName = JLabel("Player Name") + private val playerNameField = JTextField() + private val opponentOneNameField = JTextField() + private val opponentTwoNameField = JTextField() + private val opponentThreeNameField = JTextField() + private val cbOpponentTwo = JCheckBox() + private val cbOpponentThree = JCheckBox() + private val opponentOneStrat = JComboBox() + private val opponentTwoStrat = JComboBox() + private val opponentThreeStrat = JComboBox() + private val label = JLabel("Note: Changes will not take effect until you start a new game.") + private val separator_4 = JSeparator() + private val lblApiHeader = JLabel("API Options") + private val scrollPane = JScrollPane() + private val tableApiStrategies = JTable() + private val popupMenu = JPopupMenu() + private val amendItem = JMenuItem("Amend") + private val deleteItem = JMenuItem("Delete") + private val enableItem = JMenuItem("Enable") + private val btnNewApiStrategy = JButton("New API Strategy") + + init { + setLayout(null) + + separator_2.setBounds(0, 38, 434, 2) + add(separator_2) + lblPlayers.setBounds(172, 12, 70, 17) + add(lblPlayers) + lblPlayers.setHorizontalAlignment(SwingConstants.CENTER) + lblPlayers.setFont(Font("Tahoma", Font.PLAIN, 14)) + playerNameField.setDocument(LimitedDocument(10)) + opponentOneNameField.setDocument(LimitedDocument(10)) + opponentTwoNameField.setDocument(LimitedDocument(10)) + opponentThreeNameField.setDocument(LimitedDocument(10)) + opponentOneNameField.setBounds(60, 102, 86, 22) + add(opponentOneNameField) + opponentOneNameField.text = opponentOneName + opponentOneNameField.setColumns(10) + cbOpponentTwo.setBounds(22, 143, 29, 23) + add(cbOpponentTwo) + cbOpponentThree.setBounds(22, 185, 29, 23) + add(cbOpponentThree) + opponentTwoNameField.setBounds(60, 144, 86, 22) + add(opponentTwoNameField) + opponentTwoNameField.text = opponentTwoName + opponentTwoNameField.setColumns(10) + opponentThreeNameField.setBounds(60, 186, 86, 22) + add(opponentThreeNameField) + opponentThreeNameField.text = opponentThreeName + opponentThreeNameField.setColumns(10) + opponentTwoStrat.setBounds(172, 144, 197, 22) + add(opponentTwoStrat) + opponentThreeStrat.setBounds(172, 186, 197, 22) + add(opponentThreeStrat) + opponentOneStrat.setBounds(172, 102, 197, 22) + add(opponentOneStrat) + playerNameField.setBounds(212, 60, 86, 22) + add(playerNameField) + playerNameField.setColumns(10) + lblPlayerName.setBounds(122, 60, 80, 22) + add(lblPlayerName) + label.setFont(Font("Tahoma", Font.ITALIC, 11)) + label.setBounds(65, 395, 304, 14) + add(label) + lblApiHeader.setHorizontalAlignment(SwingConstants.CENTER) + lblApiHeader.setFont(Font("Tahoma", Font.PLAIN, 14)) + lblApiHeader.setBounds(171, 240, 86, 17) + add(lblApiHeader) + separator_4.setBounds(0, 265, 429, 2) + add(separator_4) + scrollPane.setBounds(17, 307, 402, 80) + add(scrollPane) + tableApiStrategies.setSelectionMode(ListSelectionModel.SINGLE_SELECTION) + scrollPane.setViewportView(tableApiStrategies) + btnNewApiStrategy.setBounds(17, 278, 151, 23) + add(btnNewApiStrategy) + tableApiStrategies.getTableHeader().setReorderingAllowed(false) + popupMenu.add(enableItem) + popupMenu.add(amendItem) + popupMenu.add(deleteItem) + + btnNewApiStrategy.addActionListener(this) + enableItem.addActionListener(this) + deleteItem.addActionListener(this) + amendItem.addActionListener(this) + tableApiStrategies.addMouseListener(this) + cbOpponentTwo.addItemListener(this) + cbOpponentThree.addItemListener(this) + } + + /** Abstract methods */ + override fun initVariables() { + getVariablesFromPrefs() + + buildApiTable() + setPlayerNames() + setOpponentEnablementAndStrategies() + setOpponentStrategies() + } + + override fun valid(): Boolean { + val nameOne = playerNameField.getText() + val nameTwo = opponentOneNameField.getText() + val nameThree = opponentTwoNameField.getText() + val nameFour = opponentThreeNameField.getText() + + if (nameOne.isEmpty() || nameTwo.isEmpty() || nameThree.isEmpty() || nameFour.isEmpty()) { + DialogUtilNew.showError("You must enter a name for each player.") + return false + } + + return true + } + + override fun savePreferences() { + playerName = playerNameField.getText() + opponentOneName = opponentOneNameField.getText() + opponentTwoName = opponentTwoNameField.getText() + opponentThreeName = opponentThreeNameField.getText() + opponentOneStrategy = opponentOneStrat.selectedItem as String + opponentTwoStrategy = opponentTwoStrat.selectedItem as String + opponentThreeStrategy = opponentThreeStrat.selectedItem as String + + preferenceStore.save(PreferenceSetting.PlayerName, playerName) + preferenceStore.save(PreferenceSetting.OpponentOneName, opponentOneName) + preferenceStore.save(PreferenceSetting.OpponentTwoName, opponentTwoName) + preferenceStore.save(PreferenceSetting.OpponentThreeName, opponentThreeName) + preferenceStore.save(PreferenceSetting.OpponentTwoEnabled, opponentTwoEnabled) + preferenceStore.save(PreferenceSetting.OpponentThreeEnabled, opponentThreeEnabled) + preferenceStore.save(PreferenceSetting.OpponentOneStrategy, opponentOneStrategy) + preferenceStore.save(PreferenceSetting.OpponentTwoStrategy, opponentTwoStrategy) + preferenceStore.save(PreferenceSetting.OpponentThreeStrategy, opponentThreeStrategy) + + ApiUtil.saveApiStrategiesToPreferences(apiStrategies) + } + + private fun getVariablesFromPrefs() { + playerName = getPreference(PreferenceSetting.PlayerName) + opponentOneName = getPreference(PreferenceSetting.OpponentOneName) + opponentTwoName = getPreference(PreferenceSetting.OpponentTwoName) + opponentThreeName = getPreference(PreferenceSetting.OpponentThreeName) + opponentTwoEnabled = getPreference(PreferenceSetting.OpponentTwoEnabled) + opponentThreeEnabled = getPreference(PreferenceSetting.OpponentThreeEnabled) + opponentOneStrategy = getPreference(PreferenceSetting.OpponentOneStrategy) + opponentTwoStrategy = getPreference(PreferenceSetting.OpponentTwoStrategy) + opponentThreeStrategy = getPreference(PreferenceSetting.OpponentThreeStrategy) + apiStrategies = ApiUtil.getApiStrategiesFromPreferences() + + gameMode = GameMode.valueOf(getPreference(PreferenceSetting.GameMode)) + } + + private fun setPlayerNames() { + playerNameField.text = playerName + opponentOneNameField.text = opponentOneName + opponentTwoNameField.text = opponentTwoName + opponentThreeNameField.text = opponentThreeName + } + + private fun setOpponentEnablementAndStrategies() { + cbOpponentThree.setEnabled(opponentTwoEnabled) + cbOpponentTwo.setEnabled(!opponentThreeEnabled) + + cbOpponentTwo.setSelected(opponentTwoEnabled) + cbOpponentThree.setSelected(opponentThreeEnabled) + opponentTwoNameField.setEnabled(opponentTwoEnabled) + opponentThreeNameField.setEnabled(opponentThreeEnabled) + opponentTwoStrat.setEnabled(opponentTwoEnabled) + opponentThreeStrat.setEnabled(opponentThreeEnabled) + } + + private fun setOpponentStrategies() { + opponentOneStrat.setSelectedItem(opponentOneStrategy) + opponentTwoStrat.setSelectedItem(opponentTwoStrategy) + opponentThreeStrat.setSelectedItem(opponentThreeStrategy) + } + + private fun buildApiTable() { + val model = DefaultModel() + tableApiStrategies.setModel(model) + + // Columns + model.addColumn("Name") + model.addColumn("Port") + model.addColumn("Game") + model.addColumn("Messaging") + model.addColumn("Enabled") + + // Centre rendering for everything but the last column + for (i in 0..(model) + tableApiStrategies.setRowSorter(sorter) + + // Populate the rows + apiStrategies.forEach { model.addRow(it.tableModelRow) } + + updateStrategySelection(gameMode) + } + + fun updateStrategySelection(gameMode: GameMode) { + this.gameMode = gameMode + + val allStrategies = + CpuStrategies.getAllStrategies(gameMode == GameMode.Entropy, apiStrategies) + + var comboModel: ComboBoxModel = DefaultComboBoxModel(allStrategies) + opponentOneStrat.setModel(comboModel) + comboModel = DefaultComboBoxModel(allStrategies) + opponentTwoStrat.setModel(comboModel) + comboModel = DefaultComboBoxModel(allStrategies) + opponentThreeStrat.setModel(comboModel) + } + + private fun enableApi(strategy: ApiStrategy) { + val question = + "Strategy ${strategy.name} was disabled due to the following error:\n\n${strategy.error}\n\nWould you like to re-enable it?" + + val option = DialogUtilNew.showQuestion(question, false) + if (option == JOptionPane.YES_OPTION) { + strategy.error = "" + buildApiTable() + } + } + + private fun amendApi(strategy: ApiStrategy?) { + ApiAmendDialog.amendStrategy(strategy) + buildApiTable() + } + + private fun deleteApi(strategy: ApiStrategy) { + val question = "Are you sure you want to delete the " + strategy.getName() + " strategy?" + val option = DialogUtilNew.showQuestion(question, false) + if (option == JOptionPane.YES_OPTION) { + apiStrategies = apiStrategies - strategy + buildApiTable() + } + } + + private fun getSelectedStrategyFromTable(): ApiStrategy? { + val row = tableApiStrategies.selectedRow + if (row == -1) { + return null + } + + val internalRow = tableApiStrategies.convertRowIndexToModel(row) + val model = tableApiStrategies.model as DefaultModel + val name = model.getValueAt(internalRow, 0) as String + + return apiStrategies.find { it.name == name } + } + + override fun actionPerformed(arg0: ActionEvent) { + val source = arg0.getSource() + if (source === btnNewApiStrategy) { + val strategy: ApiStrategy? = ApiAmendDialog.createStrategy() + if (strategy != null) { + apiStrategies = apiStrategies + strategy + buildApiTable() + } + } else if (source === amendItem) { + getSelectedStrategyFromTable()?.let(::amendApi) + } else if (source === deleteItem) { + getSelectedStrategyFromTable()?.let(::deleteApi) + } else if (source === enableItem) { + getSelectedStrategyFromTable()?.let(::enableApi) + } + } + + override fun mousePressed(arg0: MouseEvent?) {} + + override fun mouseClicked(arg0: MouseEvent) { + val strategy: ApiStrategy? = getSelectedStrategyFromTable() + + if (SwingUtilities.isRightMouseButton(arg0)) { + val point = arg0.getPoint() + val row = tableApiStrategies.rowAtPoint(point) + if (!tableApiStrategies.isRowSelected(row)) { + val column = tableApiStrategies.columnAtPoint(point) + tableApiStrategies.changeSelection(row, column, false, false) + } + + if (strategy != null) { + enableItem.setEnabled(!strategy.isEnabled) + + // Show the popup menu + popupMenu.show(arg0.component, arg0.getX(), arg0.getY()) + } + } else if (arg0.getClickCount() == 2) { + // Double-click + if (strategy != null) { + if (!strategy.isEnabled) { + enableApi(strategy) + } else { + amendApi(strategy) + } + } + } + } + + override fun mouseExited(arg0: MouseEvent?) {} + + override fun mouseEntered(arg0: MouseEvent?) {} + + override fun mouseReleased(arg0: MouseEvent?) {} + + override fun itemStateChanged(arg0: ItemEvent) { + val source = arg0.getSource() + if (source === cbOpponentTwo) { + opponentTwoEnabled = cbOpponentTwo.isSelected + setOpponentEnablementAndStrategies() + } else if (source === cbOpponentThree) { + opponentThreeEnabled = cbOpponentThree.isSelected + setOpponentEnablementAndStrategies() + } + } +} diff --git a/client/src/main/kotlin/settings/AbstractSettingStore.kt b/client/src/main/kotlin/settings/AbstractSettingStore.kt index fa0d57ec..f2590b22 100644 --- a/client/src/main/kotlin/settings/AbstractSettingStore.kt +++ b/client/src/main/kotlin/settings/AbstractSettingStore.kt @@ -36,10 +36,10 @@ abstract class AbstractSettingStore { return setting.default } - val raw = findRaw(setting) ?: return setting.default - return convertFromRaw(setting, raw) + return find(setting) ?: return setting.default } + // TODO - Replace with inline fns and json serialisation private fun toRawValue(raw: T) = raw.toString() @Suppress("UNCHECKED_CAST") diff --git a/client/src/main/kotlin/util/ClientGlobals.kt b/client/src/main/kotlin/util/ClientGlobals.kt index 38a8e325..fd5e1e27 100644 --- a/client/src/main/kotlin/util/ClientGlobals.kt +++ b/client/src/main/kotlin/util/ClientGlobals.kt @@ -25,4 +25,6 @@ object ClientGlobals { var updateManager = UpdateManager() val webSocketReceiver = WebSocketReceiver() @JvmField var achievementStore: AbstractSettingStore = DefaultSettingStore("achievements") + @JvmField var preferenceStore: AbstractSettingStore = DefaultSettingStore("preferences") + @JvmField var rewardStore: AbstractSettingStore = DefaultSettingStore("rewards") } diff --git a/core/src/main/kotlin/utils/SwingUtils.kt b/client/src/main/kotlin/utils/SwingUtils.kt similarity index 89% rename from core/src/main/kotlin/utils/SwingUtils.kt rename to client/src/main/kotlin/utils/SwingUtils.kt index 7d0ef7cc..9c90042e 100644 --- a/core/src/main/kotlin/utils/SwingUtils.kt +++ b/client/src/main/kotlin/utils/SwingUtils.kt @@ -2,6 +2,7 @@ package utils import java.awt.Component import java.awt.Container +import javax.swing.JComboBox /** * Recurses through all child components, returning an ArrayList of all children of the appropriate @@ -32,3 +33,5 @@ fun addComponents(ret: MutableList, components: Array, desired } } } + +fun JComboBox.items() = (0 until itemCount).map { this.getItemAt(it) } diff --git a/client/src/main/resources/rewards/rewardBlind.png b/client/src/main/resources/rewards/blind.png similarity index 100% rename from client/src/main/resources/rewards/rewardBlind.png rename to client/src/main/resources/rewards/blind.png diff --git a/client/src/main/resources/rewards/rewardCardReveal.png b/client/src/main/resources/rewards/cardReveal.png similarity index 100% rename from client/src/main/resources/rewards/rewardCardReveal.png rename to client/src/main/resources/rewards/cardReveal.png diff --git a/client/src/main/resources/rewards/rewardCheats.png b/client/src/main/resources/rewards/cheats.png similarity index 100% rename from client/src/main/resources/rewards/rewardCheats.png rename to client/src/main/resources/rewards/cheats.png diff --git a/client/src/main/resources/rewards/rewardDevelopers.png b/client/src/main/resources/rewards/developerSet.png similarity index 100% rename from client/src/main/resources/rewards/rewardDevelopers.png rename to client/src/main/resources/rewards/developerSet.png diff --git a/client/src/main/resources/rewards/rewardExtraSuits.png b/client/src/main/resources/rewards/extraSuits.png similarity index 100% rename from client/src/main/resources/rewards/rewardExtraSuits.png rename to client/src/main/resources/rewards/extraSuits.png diff --git a/client/src/main/resources/rewards/rewardFourColour.png b/client/src/main/resources/rewards/fourColours.png similarity index 100% rename from client/src/main/resources/rewards/rewardFourColour.png rename to client/src/main/resources/rewards/fourColours.png diff --git a/client/src/main/resources/rewards/rewardIllegal.png b/client/src/main/resources/rewards/illegal.png similarity index 100% rename from client/src/main/resources/rewards/rewardIllegal.png rename to client/src/main/resources/rewards/illegal.png diff --git a/client/src/main/resources/rewards/rewardMinimalist.png b/client/src/main/resources/rewards/minimalist.png similarity index 100% rename from client/src/main/resources/rewards/rewardMinimalist.png rename to client/src/main/resources/rewards/minimalist.png diff --git a/client/src/main/resources/rewards/rewardNegativeJacks.png b/client/src/main/resources/rewards/negativeJacks.png similarity index 100% rename from client/src/main/resources/rewards/rewardNegativeJacks.png rename to client/src/main/resources/rewards/negativeJacks.png diff --git a/client/src/main/resources/rewards/rewardVectropy.png b/client/src/main/resources/rewards/vectropy.png similarity index 100% rename from client/src/main/resources/rewards/rewardVectropy.png rename to client/src/main/resources/rewards/vectropy.png diff --git a/client/src/main/resources/update/update.bat b/client/src/main/resources/update/update.bat index 92f8a7b1..9310e1e1 100644 --- a/client/src/main/resources/update/update.bat +++ b/client/src/main/resources/update/update.bat @@ -7,11 +7,11 @@ REM %4 = assetId echo Performing download of %1 bytes (Version %2) -curl -LJO -H "Accept: application/octet-stream" https://api.github.com/repos/alyssaburlton/Dartzee/releases/assets/%4 +curl -LJO -H "Accept: application/octet-stream" https://api.github.com/repos/alyssaruth/Entropy/releases/assets/%4 -ren Dartzee.jar Dartzee_OLD.jar -ren %3 Dartzee.jar -del Dartzee_OLD.jar +ren Entropy.jar Entropy_OLD.jar +ren %3 Entropy.jar +del Entropy_OLD.jar -start javaw -Xms256m -Xmx512m -jar Dartzee.jar justUpdated trueLaunch +start javaw -Xms256m -Xmx512m -jar Entropy.jar justUpdated trueLaunch exit \ No newline at end of file diff --git a/client/src/test/kotlin/achievement/AchievementUtilTest.kt b/client/src/test/kotlin/achievement/AchievementUtilTest.kt index 5b2d8a2a..ce643e66 100644 --- a/client/src/test/kotlin/achievement/AchievementUtilTest.kt +++ b/client/src/test/kotlin/achievement/AchievementUtilTest.kt @@ -9,9 +9,9 @@ import io.mockk.verify import javax.swing.ImageIcon import javax.swing.JLabel import org.junit.jupiter.api.Test -import screen.AchievementsDialog import screen.MainScreen import screen.ScreenCache +import screen.achievement.AchievementsDialog import settings.Setting import testCore.verifyNotCalled import util.AbstractClientTest diff --git a/client/src/test/kotlin/achievement/RewardTest.kt b/client/src/test/kotlin/achievement/RewardTest.kt new file mode 100644 index 00000000..57f4e8ad --- /dev/null +++ b/client/src/test/kotlin/achievement/RewardTest.kt @@ -0,0 +1,48 @@ +package achievement + +import io.kotest.assertions.withClue +import io.kotest.matchers.collections.shouldContainExactly +import io.kotest.matchers.collections.shouldHaveSize +import io.kotest.matchers.nulls.shouldNotBeNull +import io.kotest.matchers.shouldBe +import org.junit.jupiter.api.Test +import settings.Setting +import util.AbstractClientTest +import util.ClientGlobals + +class RewardTest : AbstractClientTest() { + @Test + fun `Should be increasing order by unlock threshold`() { + val sorted = Reward.entries.sortedBy { it.threshold } + Reward.entries shouldContainExactly sorted + } + + @Test + fun `Thresholds should be distinct`() { + val groups = Reward.entries.groupBy { it.threshold } + groups.forEach { threshold, rewards -> + withClue("should only be 1 reward with threshold $threshold") { + rewards.shouldHaveSize(1) + } + } + } + + @Test + fun `Image assets should exist`() { + Reward.entries.forEach { reward -> + withClue("asset ${reward.settingName}.png should exist") { + reward.getResource().shouldNotBeNull() + } + } + } + + @Test + fun `Should report whether its unlocked or not`() { + Reward.NegativeJacks.isUnlocked() shouldBe false + + Reward.NegativeJacks.unlock() + + Reward.NegativeJacks.isUnlocked() shouldBe true + ClientGlobals.rewardStore.get(Setting("negativeJacks", false)) shouldBe true + } +} diff --git a/client/src/test/kotlin/bean/BidListCellRendererTest.kt b/client/src/test/kotlin/bean/BidListCellRendererTest.kt new file mode 100644 index 00000000..0a12db73 --- /dev/null +++ b/client/src/test/kotlin/bean/BidListCellRendererTest.kt @@ -0,0 +1,39 @@ +package bean + +import game.ChallengeAction +import game.IllegalAction +import game.Suit +import io.kotest.matchers.shouldBe +import org.junit.jupiter.api.Test +import testCore.makeEntropyBidAction +import util.AbstractClientTest + +class BidListCellRendererTest : AbstractClientTest() { + @Test + fun `HTML rendering - blind challenge`() { + val challenge = ChallengeAction("Alyssa", true) + val result = makeRenderer().toHtmlString(challenge) + result shouldBe "[Alyssa]: Challenge" + } + + @Test + fun `HTML rendering - illegal`() { + val challenge = IllegalAction("Mark", false) + val result = makeRenderer().toHtmlString(challenge) + result shouldBe "Mark: Illegal!" + } + + @Test + fun `HTML rendering - bid with card to show`() { + val bid = makeEntropyBidAction(cardToReveal = "Ac", amount = 2, suit = Suit.Spades) + + val result = makeRenderer().toHtmlString(bid) + result shouldBe + "Alyssa: 2♠&emsp(Shows: Ac)" + } + + private fun makeRenderer() = + BidListCellRenderer().also { + it.updateColours(mapOf("Alyssa" to "red", "Mark" to "blue", "David" to "green")) + } +} diff --git a/client/src/test/kotlin/game/RenderingUtilTest.kt b/client/src/test/kotlin/game/RenderingUtilTest.kt index b684bb59..275149f8 100644 --- a/client/src/test/kotlin/game/RenderingUtilTest.kt +++ b/client/src/test/kotlin/game/RenderingUtilTest.kt @@ -1,8 +1,13 @@ package game import io.kotest.matchers.shouldBe +import java.awt.Color import org.junit.jupiter.api.Test +import preference.FOUR_COLOURS +import preference.PreferenceSetting +import testCore.makeEntropyBidAction import util.AbstractClientTest +import util.ClientGlobals class RenderingUtilTest : AbstractClientTest() { @Test @@ -33,4 +38,24 @@ class RenderingUtilTest : AbstractClientTest() { "2, " + "3)" } + + @Test + fun `HTML rendering for an entropy bid`() { + val bid = makeEntropyBidAction(suit = Suit.Diamonds, amount = 1) + bid.htmlString() shouldBe "1♦" + + ClientGlobals.preferenceStore.save(PreferenceSetting.NumberOfColours, FOUR_COLOURS) + bid.htmlString() shouldBe "1♦" + } + + @Test + fun `Should be able to get a suit colour`() { + Suit.Diamonds.getColour() shouldBe Color.red + Suit.Diamonds.getColourHex() shouldBe "#FF0000FF" + + ClientGlobals.preferenceStore.save(PreferenceSetting.NumberOfColours, FOUR_COLOURS) + + Suit.Diamonds.getColour() shouldBe Color.blue + Suit.Diamonds.getColourHex() shouldBe "#0000FFFF" + } } diff --git a/client/src/test/kotlin/screen/SimpleDialogTest.kt b/client/src/test/kotlin/screen/SimpleDialogTest.kt index f883bbef..9145ae17 100644 --- a/client/src/test/kotlin/screen/SimpleDialogTest.kt +++ b/client/src/test/kotlin/screen/SimpleDialogTest.kt @@ -2,7 +2,9 @@ package screen import com.github.alyssaburlton.swingtest.clickCancel import com.github.alyssaburlton.swingtest.clickOk +import com.github.alyssaburlton.swingtest.findChild import io.kotest.matchers.shouldBe +import javax.swing.AbstractButton import org.junit.jupiter.api.Test import testCore.AbstractTest import testCore.logger @@ -27,7 +29,18 @@ class SimpleDialogTest : AbstractTest() { verifyLog("ok.pressed") } - inner class SimpleDialogTestExtension : SimpleDialog() { + @Test + fun `Can exclude cancel button`() { + val dlg = SimpleDialogTestExtension(false) + dlg.findChild(text = "Cancel") shouldBe null + } + + inner class SimpleDialogTestExtension(includeCancel: Boolean = true) : + SimpleDialog(includeCancel) { + init { + isModal = false + } + override fun okPressed() { logger.info("ok.pressed", "pressed ok") } diff --git a/client/src/test/kotlin/screen/AchievementsDialogTest.kt b/client/src/test/kotlin/screen/achievement/AchievementsDialogTest.kt similarity index 98% rename from client/src/test/kotlin/screen/AchievementsDialogTest.kt rename to client/src/test/kotlin/screen/achievement/AchievementsDialogTest.kt index 29750fd7..8723c1fc 100644 --- a/client/src/test/kotlin/screen/AchievementsDialogTest.kt +++ b/client/src/test/kotlin/screen/achievement/AchievementsDialogTest.kt @@ -1,4 +1,4 @@ -package screen +package screen.achievement import achievement.unlockAchievement import bean.AchievementBadge diff --git a/client/src/test/kotlin/screen/AchievementsPanelTest.kt b/client/src/test/kotlin/screen/achievement/AchievementsPanelTest.kt similarity index 98% rename from client/src/test/kotlin/screen/AchievementsPanelTest.kt rename to client/src/test/kotlin/screen/achievement/AchievementsPanelTest.kt index b21d569b..078f0d3b 100644 --- a/client/src/test/kotlin/screen/AchievementsPanelTest.kt +++ b/client/src/test/kotlin/screen/achievement/AchievementsPanelTest.kt @@ -1,4 +1,4 @@ -package screen +package screen.achievement import bean.AchievementBadge import io.kotest.matchers.collections.shouldContainExactlyInAnyOrder diff --git a/client/src/test/kotlin/screen/achievement/RewardStarTest.kt b/client/src/test/kotlin/screen/achievement/RewardStarTest.kt new file mode 100644 index 00000000..2bf800a5 --- /dev/null +++ b/client/src/test/kotlin/screen/achievement/RewardStarTest.kt @@ -0,0 +1,52 @@ +package screen.achievement + +import achievement.Reward +import com.github.alyssaburlton.swingtest.doClick +import com.github.alyssaburlton.swingtest.doHover +import com.github.alyssaburlton.swingtest.doHoverAway +import com.github.alyssaburlton.swingtest.findWindow +import io.kotest.matchers.nulls.shouldNotBeNull +import io.kotest.matchers.shouldBe +import org.junit.jupiter.api.Test +import util.AbstractClientTest +import util.Images + +class RewardStarTest : AbstractClientTest() { + @Test + fun `Screenshot - locked`() { + val star = RewardStar("", Reward.NegativeJacks) + star.icon shouldBe Images.REWARD_LOCKED + } + + @Test + fun `Screenshot - unlocked`() { + Reward.NegativeJacks.unlock() + + val star = RewardStar("", Reward.NegativeJacks) + star.icon shouldBe Images.REWARD_UNLOCKED + + star.doHover() + star.icon shouldBe Images.REWARD_UNLOCKED_HOVERED + + star.doHoverAway() + star.icon shouldBe Images.REWARD_UNLOCKED + } + + @Test + fun `Should do nothing on click if locked`() { + Reward.NegativeJacks.unlock() + + val star = RewardStar("", Reward.NegativeJacks) + star.doClick(async = true) + + findWindow().shouldNotBeNull() + } + + @Test + fun `Should launch reward dialog on click`() { + val star = RewardStar("", Reward.NegativeJacks) + star.doClick(async = true) + + findWindow() shouldBe null + } +} diff --git a/client/src/test/kotlin/screen/online/PlayOnlineDialogTest.kt b/client/src/test/kotlin/screen/online/PlayOnlineDialogTest.kt index ff809f36..08d47ca4 100644 --- a/client/src/test/kotlin/screen/online/PlayOnlineDialogTest.kt +++ b/client/src/test/kotlin/screen/online/PlayOnlineDialogTest.kt @@ -19,7 +19,7 @@ import util.ClientGlobals class PlayOnlineDialogTest : AbstractTest() { @Test fun `Should not allow an empty name`() { - val dlg = PlayOnlineDialog() + val dlg = PlayOnlineDialog().also { it.isModal = false } dlg.isVisible = true dlg.clickOk(async = true) @@ -32,7 +32,7 @@ class PlayOnlineDialogTest : AbstractTest() { fun `Should invoke the session API`() { ClientGlobals.sessionApi = mockk(relaxed = true) - val dlg = PlayOnlineDialog() + val dlg = PlayOnlineDialog().also { it.isModal = false } dlg.isVisible = true dlg.getChild().text = "Alyssa" dlg.clickOk() diff --git a/client/src/test/kotlin/screen/preference/PreferencesPanelAppearanceTest.kt b/client/src/test/kotlin/screen/preference/PreferencesPanelAppearanceTest.kt new file mode 100644 index 00000000..1b9b1653 --- /dev/null +++ b/client/src/test/kotlin/screen/preference/PreferencesPanelAppearanceTest.kt @@ -0,0 +1,158 @@ +package screen.preference + +import achievement.Reward +import bean.ComboBoxItem +import com.github.alyssaburlton.swingtest.getChild +import com.github.alyssaburlton.swingtest.shouldBeDisabled +import com.github.alyssaburlton.swingtest.shouldBeEnabled +import com.github.alyssaburlton.swingtest.shouldMatch +import io.kotest.matchers.collections.shouldContainExactly +import io.kotest.matchers.shouldBe +import io.mockk.mockk +import javax.swing.ImageIcon +import javax.swing.JCheckBox +import javax.swing.JComboBox +import javax.swing.JLabel +import javax.swing.JRadioButton +import org.junit.jupiter.api.Test +import preference.PreferenceSetting +import util.AbstractClientTest +import util.ClientGlobals.preferenceStore +import utils.items + +class PreferencesPanelAppearanceTest : AbstractClientTest() { + @Test + fun `Should only show unlocked card backs`() { + Reward.FourColours.unlock() + + val panel = openPreferencePanel() + + val comboBox = panel.getChild>("backs") + comboBox + .items() + .shouldContainExactly( + ComboBoxItem("backBlue", "Blue", true), + ComboBoxItem("backRed", "Red", true), + ComboBoxItem("backGreen", "Green", true), + ComboBoxItem("", "10 achievements to unlock", false), + ComboBoxItem("", "15 achievements to unlock", false), + ComboBoxItem("", "20 achievements to unlock", false), + ComboBoxItem("", "25 achievements to unlock", false), + ComboBoxItem("", "30 achievements to unlock", false), + ComboBoxItem("", "35 achievements to unlock", false), + ComboBoxItem("", "40 achievements to unlock", false), + ComboBoxItem("", "45 achievements to unlock", false), + ComboBoxItem("", "50 achievements to unlock", false), + ) + + // Can't select a disabled entry + comboBox.selectedIndex = 3 + comboBox.selectedIndex shouldBe 0 + + // Can select an enabled entry + comboBox.selectedIndex = 2 + comboBox.selectedIndex shouldBe 2 + } + + @Test + fun `Backs combo box should update preview and saved preference`() { + Reward.FourColours.unlock() + val panel = openPreferencePanel() + val comboBox = panel.getChild>("backs") + + comboBox.selectedIndex = 1 + panel.backPreviewIcon().shouldMatch(ImageIcon(javaClass.getResource("/backs/backRed.png"))) + + comboBox.selectedIndex = 2 + panel + .backPreviewIcon() + .shouldMatch(ImageIcon(javaClass.getResource("/backs/backGreen.png"))) + + panel.savePreferences() + preferenceStore.get(PreferenceSetting.CardBacks) shouldBe "backGreen" + } + + @Test + fun `Backs combo box should load correct selection from preference`() { + preferenceStore.save(PreferenceSetting.CardBacks, "backRed") + + val panel = openPreferencePanel() + val comboBox = panel.getChild>("backs") + + comboBox.selectedItem shouldBe ComboBoxItem("backRed", "Red", true) + } + + @Test + fun `Backs combo box should revert to Blue if value stored in preference is no longer unlocked (eg due to wiped data)`() { + preferenceStore.save(PreferenceSetting.CardBacks, "backGreen") + + val panel = openPreferencePanel() + val comboBox = panel.getChild>("backs") + + comboBox.selectedItem shouldBe ComboBoxItem("backBlue", "Blue", true) + } + + @Test + fun `4 colour checkbox should be locked or unlocked as appropriate`() { + val panel = openPreferencePanel() + + val checkbox = panel.getChild("FourColourCheckbox") + checkbox.shouldBeDisabled() + checkbox.isSelected shouldBe false + checkbox.text shouldBe "Locked" + checkbox.toolTipText shouldBe "Unlock at 5 achievements" + + Reward.FourColours.unlock() + val panel2 = openPreferencePanel() + val checkbox2 = panel2.getChild("FourColourCheckbox") + + checkbox2.shouldBeEnabled() + checkbox2.text shouldBe "Use 4 colour deck" + checkbox2.toolTipText shouldBe null + } + + @Test + fun `Minimalist deck design radio button should be locked or unlocked as appropriate`() { + val panel = openPreferencePanel() + + val rdbtn = panel.getChild("MinimalistDesignRadio") + rdbtn.shouldBeDisabled() + rdbtn.isSelected shouldBe false + rdbtn.text shouldBe "Locked" + rdbtn.toolTipText shouldBe "Unlock at 20 achievements" + + Reward.MinimalistDeck.unlock() + val panel2 = openPreferencePanel() + val rdbtn2 = panel2.getChild("MinimalistDesignRadio") + + rdbtn2.shouldBeEnabled() + rdbtn2.text shouldBe "Minimalist" + rdbtn2.toolTipText shouldBe null + } + + @Test + fun `Developer jokers design radio button should be locked or unlocked as appropriate`() { + val panel = openPreferencePanel() + + val rdbtn = panel.getChild("DeveloperJokersRadio") + rdbtn.shouldBeDisabled() + rdbtn.isSelected shouldBe false + rdbtn.text shouldBe "Locked" + rdbtn.toolTipText shouldBe "Unlock at 45 achievements" + + Reward.DeveloperSet.unlock() + val panel2 = openPreferencePanel() + val rdbtn2 = panel2.getChild("DeveloperJokersRadio") + + rdbtn2.shouldBeEnabled() + rdbtn2.text shouldBe "Developers" + rdbtn2.toolTipText shouldBe null + } + + private fun PreferencesPanelAppearance.backPreviewIcon(): ImageIcon = + getChild("BackPreview").icon as ImageIcon + + private fun openPreferencePanel(): PreferencesPanelAppearance { + return PreferencesPanelAppearance(mockk(relaxed = true)).also { it.initVariables() } + } +} diff --git a/client/src/test/kotlin/screen/preference/PreferencesPanelMiscTest.kt b/client/src/test/kotlin/screen/preference/PreferencesPanelMiscTest.kt new file mode 100644 index 00000000..cf3b108f --- /dev/null +++ b/client/src/test/kotlin/screen/preference/PreferencesPanelMiscTest.kt @@ -0,0 +1,74 @@ +package screen.preference + +import com.github.alyssaburlton.swingtest.clickChild +import com.github.alyssaburlton.swingtest.getChild +import com.github.alyssaburlton.swingtest.shouldBeDisabled +import com.github.alyssaburlton.swingtest.shouldBeEnabled +import io.kotest.matchers.shouldBe +import io.mockk.mockk +import javax.swing.JButton +import javax.swing.JCheckBox +import javax.swing.JRadioButton +import javax.swing.JSpinner +import javax.swing.JTextField +import org.junit.jupiter.api.Test +import preference.GAME_SPEED_FAST +import preference.PreferenceSetting +import util.AbstractClientTest +import util.ClientGlobals.preferenceStore + +class PreferencesPanelMiscTest : AbstractClientTest() { + @Test + fun `Should load existing preferences`() { + preferenceStore.save(PreferenceSetting.SaveReplays, true) + preferenceStore.save(PreferenceSetting.AutoSave, true) + preferenceStore.save(PreferenceSetting.ReplayDirectory, "/foo/bar") + preferenceStore.save(PreferenceSetting.OpenReplayOnFirstRound, true) + preferenceStore.save(PreferenceSetting.AutoStartNextRound, true) + preferenceStore.save(PreferenceSetting.AutoStartSeconds, 4) + preferenceStore.save(PreferenceSetting.PopUpRooms, true) + preferenceStore.save(PreferenceSetting.CheckForUpdates, false) + preferenceStore.save(PreferenceSetting.GameSpeed, GAME_SPEED_FAST) + + val panel = PreferencesPanelMisc(mockk(relaxed = true)) + panel.initVariables() + + panel.getChild(text = "Save replays").isSelected shouldBe true + panel.getChild(text = "Autosave on exit").isSelected shouldBe true + panel.getChild("replayDirectory").shouldBeEnabled() + panel.getChild("replayDirectory").text shouldBe "/foo/bar\\Replays" + + panel.getChild(text = "First Round").isSelected shouldBe true + panel.getChild(text = "Last Round").isSelected shouldBe false + panel.getChild(text = "Automatically start next round after").isSelected shouldBe + true + + panel.getChild().value shouldBe 4 + + panel.getChild(text = "Pop up online rooms on my turn").isSelected shouldBe true + panel.getChild(text = "Automatically check for updates").isSelected shouldBe + false + + panel.getChild(text = "Slow").isSelected shouldBe false + panel.getChild(text = "Medium").isSelected shouldBe false + panel.getChild(text = "Fast").isSelected shouldBe true + } + + @Test + fun `Ticking and unticking save replays should toggle related components`() { + val panel = PreferencesPanelMisc(mockk(relaxed = true)) + panel.initVariables() + + panel.getChild(text = "Save replays").isSelected shouldBe false + panel.getChild("replayDirectory").shouldBeDisabled() + panel.getChild(text = "...").shouldBeDisabled() + + panel.clickChild(text = "Save replays") + panel.getChild("replayDirectory").shouldBeEnabled() + panel.getChild(text = "...").shouldBeEnabled() + + panel.clickChild(text = "Save replays") + panel.getChild("replayDirectory").shouldBeDisabled() + panel.getChild(text = "...").shouldBeDisabled() + } +} diff --git a/client/src/test/kotlin/util/AbstractClientTest.kt b/client/src/test/kotlin/util/AbstractClientTest.kt index a699780a..9878768a 100644 --- a/client/src/test/kotlin/util/AbstractClientTest.kt +++ b/client/src/test/kotlin/util/AbstractClientTest.kt @@ -12,6 +12,8 @@ abstract class AbstractClientTest : AbstractTest() { @BeforeEach fun beforeEach() { ClientGlobals.achievementStore = InMemorySettingStore() + ClientGlobals.rewardStore = InMemorySettingStore() + ClientGlobals.preferenceStore = InMemorySettingStore() ScreenCache.emptyCache() } diff --git a/core/src/main/java/util/Debug.java b/core/src/main/java/util/Debug.java index da04e529..3da865f4 100644 --- a/core/src/main/java/util/Debug.java +++ b/core/src/main/java/util/Debug.java @@ -8,6 +8,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; +@Deprecated public class Debug { private static DebugOutput output = null; diff --git a/core/src/main/java/util/Registry.java b/core/src/main/java/util/Registry.java index fd25d63b..6f82d7de 100644 --- a/core/src/main/java/util/Registry.java +++ b/core/src/main/java/util/Registry.java @@ -10,8 +10,6 @@ public interface Registry //Actual preference wrappers public static final Preferences savedGame = Preferences.userRoot().node("entropySavedgameNone"); - public static final Preferences prefs = Preferences.userRoot().node("entropyPreferencesTuuug"); - public static final Preferences rewards = Preferences.userRoot().node("entropyRewardsNone"); public static final Preferences inGameReplay = Preferences.userRoot().node("entropyReplayCurrent"); public static final Preferences fileReplay = Preferences.userRoot().node("entropyReplayFile"); public static final Preferences tempReplayStore = Preferences.userRoot().node("entropyTemp"); @@ -32,54 +30,7 @@ public interface Registry public static final String SHARED_INT_JOKER_VALUE = "jokerValue"; public static final String SHARED_INT_JOKER_QUANTITY = "jokerQuantity"; public static final String SHARED_INT_NUMBER_OF_CARDS = "numberOfCards"; - - //prefs - public static final String PREFERENCES_STRING_REPLAY_DIRECTORY = "replayDirectory"; - public static final String PREFERENCES_STRING_DECK_DIRECTORY = "deckDirectory"; - public static final String PREFERENCES_STRING_JOKER_DIRECTORY = "jokerDirectory"; - public static final String PREFERENCES_STRING_NUMBER_OF_COLOURS = "numberOfColours"; - public static final String PREFERENCES_STRING_CARD_BACKS = "cardBacks"; - public static final String PREFERENCES_STRING_LOOK_AND_FEEL = "lookAndFeel"; - public static final String PREFERENCES_STRING_OPPONENT_THREE_STRATEGY = "opponentThreeStrategy"; - public static final String PREFERENCES_STRING_OPPONENT_TWO_STRATEGY = "opponentTwoStrategy"; - public static final String PREFERENCES_STRING_OPPONENT_ONE_STRATEGY = "opponentOneStrategy"; - public static final String PREFERENCES_STRING_OPPONENT_THREE_NAME = "opponentThreeName"; - public static final String PREFERENCES_STRING_OPPONENT_TWO_NAME = "opponentTwoName"; - public static final String PREFERENCES_STRING_OPPONENT_ONE_NAME = "opponentOneName"; - public static final String PREFERENCES_STRING_PLAYER_NAME = "playerName"; - - public static final String PREFERENCES_BOOLEAN_SAVE_REPLAYS = "saveReplays"; - public static final String PREFERENCES_BOOLEAN_AUTOSAVE = "autosave"; - public static final String PREFERENCES_BOOLEAN_AUTO_START_NEXT_ROUND = "autoStart"; - public static final String PREFERENCES_BOOLEAN_POP_UP_ROOMS = "popUp"; - public static final String PREFERENCES_BOOLEAN_OPPONENT_THREE_ENABLED = "opponentThreeEnabled"; - public static final String PREFERENCES_BOOLEAN_OPPONENT_TWO_ENABLED = "opponentTwoEnabled"; - public static final String PREFERENCES_BOOLEAN_PLAY_BLIND = "playBlind"; - public static final String PREFERENCES_BOOLEAN_PLAY_WITH_HANDICAP = "playWithHandicap"; - public static final String PREFERENCES_BOOLEAN_INCLUDE_GAME_MODE_COLUMN = "includeMode"; - public static final String PREFERENCES_BOOLEAN_INCLUDE_ROUNDS_COLUMN = "includeRounds"; - public static final String PREFERENCES_BOOLEAN_INCLUDE_PLAYERS_COLUMN = "includePlayers"; - public static final String PREFERENCES_BOOLEAN_INCLUDE_CARDS_COLUMN = "includeCards"; - public static final String PREFERENCES_BOOLEAN_INCLUDE_ROOM_NAME_COLUMN = "includeRoomName"; - public static final String PREFERENCES_BOOLEAN_CHECK_FOR_UPDATES = "checkForUpdates"; - - public static final String PREFERENCES_INT_REPLAY_DEFAULT = "replayDefault"; - public static final String PREFERENCES_INT_GAME_SPEED = "gameSpeed"; - public static final String PREFERENCES_INT_AUTO_START_SECONDS = "autoStartMillis"; - public static final String PREFERENCES_INT_HANDICAP_AMOUNT = "handicapAmount"; - public static final String PREFERENCES_INT_REPLAY_VIEWER_HEIGHT = "rvheight"; - public static final String PREFERENCES_INT_REPLAY_VIEWER_WIDTH = "rvwidth"; - public static final String PREFERENCES_STRING_GAME_MODE = "gameMode"; - - public static final String PREFERENCES_XML_API_SETTINGS = "apiSettings"; - public static final String PREFERENCES_TAG_API = "Api"; - public static final String PREFERENCES_ATTR_API_NAME = "ApiName"; - public static final String PREFERENCES_ATTR_PORT_NUMNER = "PortNumber"; - public static final String PREFERENCES_ATTR_MESSAGE_TYPE = "MessageType"; - public static final String PREFERENCES_ATTR_SUPPORTS_ENTROPY = "Entropy"; - public static final String PREFERENCES_ATTR_SUPPORTS_VECTROPY = "Vectropy"; - public static final String PREFERENCES_ATTR_ERROR = "Error"; - + //replay public static final String REPLAY_STRING_OPPONENT_THREE_HAND = "opponentThreeHand"; public static final String REPLAY_STRING_OPPONENT_TWO_HAND = "opponentTwoHand"; @@ -126,20 +77,6 @@ public interface Registry public static final String REPLAY_INT_PLAYER_WON = "playerWon"; public static final String REPLAY_INT_GAME_MODE = "gameMode"; - //rewards - public static final String REWARDS_BOOLEAN_FOUR_COLOURS = "fourColours"; - //public static final String REWARDS_BOOLEAN_JOKERS = "jokers"; - public static final String REWARDS_BOOLEAN_NEGATIVE_JACKS = "negativeJacks"; - public static final String REWARDS_BOOLEAN_MINIMALIST_DECK = "minimalist"; - public static final String REWARDS_BOOLEAN_BLIND = "blind"; - public static final String REWARDS_BOOLEAN_VECTROPY = "vectropy"; - //public static final String REWARDS_BOOLEAN_HANDICAP = "handicap"; - public static final String REWARDS_BOOLEAN_CARD_REVEAL = "cardReveal"; - public static final String REWARDS_BOOLEAN_DEVELOPER_JOKERS = "developerSet"; - public static final String REWARDS_BOOLEAN_ILLEGAL = "illegal"; - public static final String REWARDS_BOOLEAN_EXTRA_SUITS = "extraSuits"; - public static final String REWARDS_BOOLEAN_CHEATS = "cheats"; - //savedGame public static final String SAVED_GAME_STRING_RESULT_TEXT = "resultText"; public static final String SAVED_GAME_STRING_TOTAL_CARDS_LABEL = "totalCardsLabel"; @@ -202,16 +139,4 @@ public interface Registry public static final String SAVED_GAME_INT_OPPONENT_ONE_NUMBER_OF_CARDS = "opponentOneNumberOfCards"; public static final String SAVED_GAME_INT_PLAYER_NUMBER_OF_CARDS = "playerNumberOfCards"; public static final String SAVED_GAME_STRING_GAME_MODE = "gameMode"; - - //statics for default values etc - public static final String TWO_COLOURS = "twocolour"; - public static final String FOUR_COLOURS = "fourcolour"; - public static final String DECK_DIRECTORY_CLASSIC = "classic"; - public static final String DECK_DIRECTORY_ALTERNATE = "alternate"; - public static final String JOKER_DIRECTORY_CLASSIC = "classic"; - public static final String JOKER_DIRECTORY_DEVELOPERS = "developers"; - public static final String BACK_CODE_CLASSIC_BLUE = "backBlue"; - public static final String DEFAULT_LOOK_AND_FEEL = "Metal"; - public static final int OPEN_ON_FIRST_ROUND = 0; - public static final int OPEN_ON_LAST_ROUND = 1; } \ No newline at end of file diff --git a/core/src/main/kotlin/game/EntropyBidAction.kt b/core/src/main/kotlin/game/EntropyBidAction.kt index 906afae5..e7bedc97 100644 --- a/core/src/main/kotlin/game/EntropyBidAction.kt +++ b/core/src/main/kotlin/game/EntropyBidAction.kt @@ -31,9 +31,6 @@ data class EntropyBidAction( override fun plainString() = "$amount ${suit.getDescription(amount)}" - override fun htmlString() = - "$amount${suit.unicodeStr}" - companion object { @JvmStatic fun fromJson(jsonString: String): EntropyBidAction = diff --git a/core/src/main/kotlin/game/PlayerAction.kt b/core/src/main/kotlin/game/PlayerAction.kt index 2170ab93..7f409a66 100644 --- a/core/src/main/kotlin/game/PlayerAction.kt +++ b/core/src/main/kotlin/game/PlayerAction.kt @@ -22,7 +22,5 @@ abstract class PlayerAction { abstract fun plainString(): String - open fun htmlString() = plainString() - fun toJsonString(): String = CoreGlobals.jsonMapper.writeValueAsString(this) } diff --git a/core/src/main/kotlin/game/Suit.kt b/core/src/main/kotlin/game/Suit.kt index e341c014..14fdadb9 100644 --- a/core/src/main/kotlin/game/Suit.kt +++ b/core/src/main/kotlin/game/Suit.kt @@ -1,11 +1,9 @@ package game import java.awt.Color -import util.Registry import utils.COLOUR_SUIT_GOLD import utils.COLOUR_SUIT_GREEN import utils.COLOUR_SUIT_PURPLE -import utils.toHexCode const val CLUBS_SYMBOL = "\u2663" const val DIAMONDS_SYMBOL = "\u2666" @@ -33,14 +31,6 @@ enum class Suit( return if (singular) lower.dropLast(1) else lower } - fun getColour(): Color { - val numberOfColoursStr = - Registry.prefs[Registry.PREFERENCES_STRING_NUMBER_OF_COLOURS, Registry.TWO_COLOURS] - return if (numberOfColoursStr == Registry.FOUR_COLOURS) fourColour else twoColour - } - - fun getColourHex() = getColour().toHexCode() - fun lessThan(other: Suit) = this < other fun next(includeMoons: Boolean, includeStars: Boolean): Suit { diff --git a/core/src/test/kotlin/game/EntropyBidActionTest.kt b/core/src/test/kotlin/game/EntropyBidActionTest.kt index fd27a63a..27685262 100644 --- a/core/src/test/kotlin/game/EntropyBidActionTest.kt +++ b/core/src/test/kotlin/game/EntropyBidActionTest.kt @@ -1,13 +1,11 @@ package game import io.kotest.matchers.shouldBe -import java.awt.Color import org.junit.jupiter.api.Test import testCore.AbstractTest import testCore.makeEntropyBidAction import testCore.makeGameSettings import utils.CoreGlobals -import utils.toHexCode class EntropyBidActionTest : AbstractTest() { @Test @@ -70,8 +68,5 @@ class EntropyBidActionTest : AbstractTest() { fun `Should have sensible description`() { makeEntropyBidAction(1, Suit.Diamonds).plainString() shouldBe "1 diamond" makeEntropyBidAction(3, Suit.Diamonds).plainString() shouldBe "3 diamonds" - - makeEntropyBidAction(1, Suit.Hearts).htmlString() shouldBe - "1♥" } } diff --git a/core/src/test/kotlin/game/VectropyBidActionTest.kt b/core/src/test/kotlin/game/VectropyBidActionTest.kt index 6a819918..97203c44 100644 --- a/core/src/test/kotlin/game/VectropyBidActionTest.kt +++ b/core/src/test/kotlin/game/VectropyBidActionTest.kt @@ -108,7 +108,6 @@ class VectropyBidActionTest : AbstractTest() { val allSuits = coreSuits + mapOf(Suit.Moons to 7, Suit.Stars to 9) VectropyBidAction("", false, allSuits).plainString() shouldBe "(3, 0, 2, 7, 1, 9)" - VectropyBidAction("", false, allSuits).htmlString() shouldBe "(3, 0, 2, 7, 1, 9)" } @Test