From 9e1585f1b70443f3b9ed18d0197b5bb626a7af6a Mon Sep 17 00:00:00 2001 From: RumbleBBU Date: Thu, 18 Oct 2012 10:29:00 +0000 Subject: [PATCH] Added a dialog to allow defining custom quest formats. --- .gitattributes | 1 + .../gui/home/quest/CSubmenuQuestData.java | 28 ++- .../gui/home/quest/DialogCustomFormat.java | 162 ++++++++++++++++++ .../gui/home/quest/VSubmenuQuestData.java | 31 +++- .../java/forge/quest/QuestController.java | 16 +- .../forge/quest/data/GameFormatQuest.java | 3 +- src/main/java/forge/quest/data/QuestData.java | 8 +- 7 files changed, 235 insertions(+), 14 deletions(-) create mode 100644 src/main/java/forge/gui/home/quest/DialogCustomFormat.java diff --git a/.gitattributes b/.gitattributes index 82318f13b2b..0d869f77642 100644 --- a/.gitattributes +++ b/.gitattributes @@ -12800,6 +12800,7 @@ src/main/java/forge/gui/home/quest/CSubmenuDuels.java -text src/main/java/forge/gui/home/quest/CSubmenuQuestData.java -text src/main/java/forge/gui/home/quest/CSubmenuQuestDecks.java -text src/main/java/forge/gui/home/quest/CSubmenuQuestPrefs.java -text +src/main/java/forge/gui/home/quest/DialogCustomFormat.java -text src/main/java/forge/gui/home/quest/IVQuestStats.java -text src/main/java/forge/gui/home/quest/PnlEvent.java -text src/main/java/forge/gui/home/quest/QuestFileLister.java -text diff --git a/src/main/java/forge/gui/home/quest/CSubmenuQuestData.java b/src/main/java/forge/gui/home/quest/CSubmenuQuestData.java index 7ab6e7c19d9..8a8fc8fb0da 100644 --- a/src/main/java/forge/gui/home/quest/CSubmenuQuestData.java +++ b/src/main/java/forge/gui/home/quest/CSubmenuQuestData.java @@ -22,6 +22,7 @@ import forge.properties.NewConstants; import forge.quest.QuestController; import forge.quest.QuestMode; import forge.quest.QuestStartPool; +import forge.quest.data.GameFormatQuest; import forge.quest.data.QuestData; import forge.quest.data.QuestPreferences.QPref; import forge.quest.io.QuestDataIO; @@ -37,6 +38,8 @@ public enum CSubmenuQuestData implements ICDoc { /** */ SINGLETON_INSTANCE; + private GameFormatQuest userFormat = new GameFormatQuest("Custom", new ArrayList(), new ArrayList()); + private final Map arrQuests = new HashMap(); private final VSubmenuQuestData view = VSubmenuQuestData.SINGLETON_INSTANCE; @@ -50,10 +53,23 @@ public enum CSubmenuQuestData implements ICDoc { private final ActionListener preconListener = new ActionListener() { @Override public void actionPerformed(ActionEvent actionEvent) { - view.getCbxFormat().setEnabled(view.getRadRotatingStart().isSelected()); + view.getCbxFormat().setEnabled(view.getRadRotatingStart().isSelected() && !view.getBoxCustom().isSelected()); view.getCbxPrecon().setEnabled(view.getRadPreconStart().isSelected()); view.getBoxPersist().setEnabled(view.getRadRotatingStart().isSelected()); + view.getBoxCustom().setEnabled(view.getRadRotatingStart().isSelected()); + view.getBtnCustom().setEnabled(view.getRadRotatingStart().isSelected() && view.getBoxCustom().isSelected()); } + }; + private final ActionListener customFormatListener = new ActionListener() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + if (actionEvent.getActionCommand().equals("Define")) { + new DialogCustomFormat(userFormat); + } else { + System.out.println("Custom Format button event = " + actionEvent.getActionCommand()); + } + } + }; /* (non-Javadoc) @@ -67,6 +83,8 @@ public enum CSubmenuQuestData implements ICDoc { view.getRadUnrestricted().addActionListener(preconListener); view.getRadRotatingStart().addActionListener(preconListener); view.getRadPreconStart().addActionListener(preconListener); + view.getBoxCustom().addActionListener(preconListener); + view.getBtnFormatCustom().addActionListener(customFormatListener); } /* (non-Javadoc) @@ -174,7 +192,13 @@ public enum CSubmenuQuestData implements ICDoc { } // Give the user a few cards to build a deck - Singletons.getModel().getQuest().newGame(questName, difficulty, mode, startPool, rotatingFormat, startPrecon, view.getBoxPersist().isSelected()); + final boolean useCustomFormat = (view.getRadRotatingStart().isSelected() && view.getBoxCustom().isSelected()); + if (useCustomFormat && userFormat != null) { + userFormat.updateFilters(); + } + Singletons.getModel().getQuest().newGame(questName, difficulty, mode, startPool, rotatingFormat, startPrecon, + useCustomFormat ? userFormat : null, + view.getBoxPersist().isSelected()); Singletons.getModel().getQuest().save(); // Save in preferences. diff --git a/src/main/java/forge/gui/home/quest/DialogCustomFormat.java b/src/main/java/forge/gui/home/quest/DialogCustomFormat.java new file mode 100644 index 00000000000..f01455db080 --- /dev/null +++ b/src/main/java/forge/gui/home/quest/DialogCustomFormat.java @@ -0,0 +1,162 @@ +package forge.gui.home.quest; + +import java.awt.BorderLayout; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.List; +import java.util.TreeMap; + + + +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JDialog; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.WindowConstants; + +import forge.card.CardEdition; +import forge.quest.data.GameFormatQuest; +import forge.Singletons; + +/** + * TODO: Write javadoc for this type. + * + */ +public class DialogCustomFormat extends JDialog { + + private static final long serialVersionUID = 3155211532871888181L; + private JScrollPane scrollPane; + private final JButton btnOK = new JButton("OK"); + private final JButton btnCancel = new JButton("Cancel"); + private final JPanel buttonPanel = new JPanel(); + private GameFormatQuest customFormat; + private JCheckBox [] choices; + private String [] codes; + + + /** + * Create the dialog. + * + * @param userFormat + * GameFormatQuest, the user-defined format to update + * + */ + public DialogCustomFormat(GameFormatQuest userFormat) { + + customFormat = userFormat; + if (customFormat == null) { + throw new RuntimeException("Null GameFormatQuest in DialogCustomFormat"); + } + + this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + TreeMap sortedMap = new TreeMap(); + + for (CardEdition ce : Singletons.getModel().getEditions()) { + if (isSelectable(ce.getCode())) { + sortedMap.put(new Integer(ce.getIndex()), ce); + } + } + + final int numEditions = sortedMap.size(); + final int rows = 30; + final int columns = numEditions <= rows ? 1 : 1 + ((numEditions - 1) / rows); + + List sortedEditions = new ArrayList(sortedMap.values()); + choices = new JCheckBox[rows * columns]; + codes = new String[rows * columns]; + + int getIdx = 0; + int putIdx = 0; + + JPanel p = new JPanel(); + p.setSize(600, 400); + p.setLayout(new GridLayout(rows, columns, 10, 0)); + + for (int row = 1; row < rows; row++) { + for (int col = 1; col < columns + 1; col++) { + getIdx = (row - 1) + ((col - 1) * (rows - 1)); + CardEdition edition = getIdx < numEditions ? sortedEditions.get(getIdx) : null; + choices[putIdx] = (edition != null ? new JCheckBox(edition.getName()) : new JCheckBox()); + + if (edition == null) { + choices[putIdx].setEnabled(false); + codes[putIdx] = new String(""); + } + else { + if (customFormat.isSetLegal(edition.getCode()) && !(customFormat.getAllowedSetCodes().isEmpty())) { + choices[putIdx].setSelected(true); + } + codes[putIdx] = new String(edition.getCode()); + } + p.add(choices[putIdx]); + putIdx++; + } + } + scrollPane = new JScrollPane(p); + + getContentPane().add(scrollPane, BorderLayout.CENTER); + btnOK.addActionListener(new ActionListener() { + @Override + public void actionPerformed(final ActionEvent arg0) { + updateCustomFormat(); + dispose(); + } + }); + buttonPanel.add(btnOK, BorderLayout.WEST); + btnCancel.addActionListener(new ActionListener() { + @Override + public void actionPerformed(final ActionEvent arg0) { + dispose(); + } + }); + buttonPanel.add(btnCancel, BorderLayout.EAST); + getContentPane().add(buttonPanel, BorderLayout.SOUTH); + + this.setSize(600, 450); + this.setLocationRelativeTo(null); + this.setTitle("Choose sets for custom format:"); + this.setVisible(true); + + } + + /** + * Make some sets unselectable (currently only Alpha and Beta). + * Note that these sets can still be (theoretically) unlocked + * later, for an exorbitant price. There'd be nothing to be + * gained from allowing these initially (Unlimited already covers + * their cardbase), and a lot to be lost (namely, easy early access + * to extremely expensive cards...) --BBU + * + * @param setCode + * String, set code + * @return boolean, this set can be selected. + * + */ + private boolean isSelectable(final String setCode) { + if (setCode == null) { + return true; + } + return !(setCode.equals("LEA") || setCode.equals("LEB")); + } + + /** + * Update the custom format in accordance with the selections. + */ + void updateCustomFormat() { + if (customFormat == null) { + return; + } + + + for (int i = 0; i < choices.length; i++) { + if (choices[i] != null) { + if (choices[i].isSelected()) { + customFormat.addAllowedSet(codes[i]); + } + } + } + } +} diff --git a/src/main/java/forge/gui/home/quest/VSubmenuQuestData.java b/src/main/java/forge/gui/home/quest/VSubmenuQuestData.java index a8c0e593387..6f2dfebebc8 100644 --- a/src/main/java/forge/gui/home/quest/VSubmenuQuestData.java +++ b/src/main/java/forge/gui/home/quest/VSubmenuQuestData.java @@ -5,6 +5,7 @@ import java.util.HashMap; import java.util.Map; import javax.swing.ButtonGroup; +import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JLabel; @@ -76,6 +77,8 @@ public enum VSubmenuQuestData implements IVSubmenu { private final JRadioButton radUnrestricted = new FRadioButton("Unrestricted Starting Pool"); private final JRadioButton radRotatingStart = new FRadioButton("Format: "); private final JComboBox cbxFormat = new JComboBox(); + private final FCheckBox boxFormatCustom = new FCheckBox("Custom"); + private final JButton btnFormatCustom = new JButton("Define"); private final JRadioButton radPreconStart = new FRadioButton("Preconstructed Deck: "); private final JComboBox cbxPrecon = new JComboBox(); @@ -145,6 +148,8 @@ public enum VSubmenuQuestData implements IVSubmenu { cbxFormat.setEnabled(false); boxFormatPersist.setSelected(true); boxFormatPersist.setEnabled(false); + boxFormatCustom.setEnabled(false); + btnFormatCustom.setEnabled(false); radUnrestricted.setSelected(true); cbxPrecon.setEnabled(false); radMedium.setEnabled(true); @@ -161,7 +166,9 @@ public enum VSubmenuQuestData implements IVSubmenu { pnlOptions.add(radUnrestricted, constraints); pnlOptions.add(radMedium, constraints + ", gap 1% 4% 0 5px"); - pnlOptions.add(radRotatingStart, constraints); + pnlOptions.add(radRotatingStart, constraints + ", w 23%!, h 27px!, split 3"); + pnlOptions.add(boxFormatCustom, constraints + ", w 12%!, h 27px!"); + pnlOptions.add(btnFormatCustom, constraints + ", w 12%!, h 27px!"); pnlOptions.add(radHard, constraints + ", gap 1% 4% 0 5px"); pnlOptions.add(cbxFormat, constraints); @@ -267,6 +274,20 @@ public enum VSubmenuQuestData implements IVSubmenu { return boxFormatPersist; } + /** + * @return {@link javax.swing.JCheckBox} + */ + public JCheckBox getBoxCustom() { + return boxFormatCustom; + } + + /** + * @return {@link javax.swing.JButton} + */ + public JButton getBtnCustom() { + return btnFormatCustom; + } + /** * @return {@link javax.swing.JRadioButton} */ @@ -311,6 +332,14 @@ public enum VSubmenuQuestData implements IVSubmenu { return btnEmbark; } + /** + * @return {@link forge.gui.toolbox.JButton} + */ + public JButton getBtnFormatCustom() { + return btnFormatCustom; + } + + //========== Overridden from IVDoc /* (non-Javadoc) diff --git a/src/main/java/forge/quest/QuestController.java b/src/main/java/forge/quest/QuestController.java index 6981f49bd98..49baa6cbc34 100644 --- a/src/main/java/forge/quest/QuestController.java +++ b/src/main/java/forge/quest/QuestController.java @@ -177,9 +177,6 @@ public class QuestController { this.questFormat = this.model == null ? null : this.model.getFormat(); this.currentEvent = null; - // if (questFormat == null) { System.out.println("No quest."); } - // else { System.out.println("Quest = " + questFormat.getName()); } - this.getChallengesManager().randomizeOpponents(); this.getDuelsManager().randomizeOpponents(); } @@ -211,16 +208,17 @@ public class QuestController { * @param startPool the start type * @param startFormat the format of starting pool * @param preconName the precon name + * @param userFormat user-defined format, if any * @param persist * enforce the format for the whole quest */ public void newGame(final String name, final int diff, final QuestMode mode, final QuestStartPool startPool, - final String startFormat, final String preconName, final boolean persist) { + final String startFormat, final String preconName, final GameFormatQuest userFormat, final boolean persist) { if (persist && startPool == QuestStartPool.Rotating) { - this.load(new QuestData(name, diff, mode, startFormat)); + this.load(new QuestData(name, diff, mode, startFormat, userFormat)); } else { - this.load(new QuestData(name, diff, mode, null)); + this.load(new QuestData(name, diff, mode, null, null)); } final Predicate filter; @@ -230,7 +228,11 @@ public class QuestController { return; case Rotating: - filter = Singletons.getModel().getFormats().getFormat(startFormat).getFilterPrinted(); + if (userFormat != null) { + filter = userFormat.getFilterPrinted(); + } else { + filter = Singletons.getModel().getFormats().getFormat(startFormat).getFilterPrinted(); + } break; default: // Unrestricted diff --git a/src/main/java/forge/quest/data/GameFormatQuest.java b/src/main/java/forge/quest/data/GameFormatQuest.java index 8fb434701c2..1eca3c5c5db 100644 --- a/src/main/java/forge/quest/data/GameFormatQuest.java +++ b/src/main/java/forge/quest/data/GameFormatQuest.java @@ -199,7 +199,6 @@ public final class GameFormatQuest { for (CardEdition ce : Singletons.getModel().getEditions()) { if (!isSetLegal(ce.getCode())) { - // System.out.println("Added " + ce.getCode() + " to the list."); exSets.add(ce.getCode()); } } @@ -219,8 +218,8 @@ public final class GameFormatQuest { } else if (this.allowedSetCodes.contains(setCode)) { return; // Already on the list } - // System.out.println("Adding " + setCode + " to allowed sets!"); this.allowedSetCodes.add(setCode); + updateFilters(); } /** diff --git a/src/main/java/forge/quest/data/QuestData.java b/src/main/java/forge/quest/data/QuestData.java index 7e966143787..5a35778b71f 100644 --- a/src/main/java/forge/quest/data/QuestData.java +++ b/src/main/java/forge/quest/data/QuestData.java @@ -67,11 +67,15 @@ public final class QuestData { * quest name * @param formatString * String, persistent format for the quest (null if none). + * @param userFormat + * user-defined format, if any (null if none). */ - public QuestData(String name2, int diff, QuestMode mode2, final String formatString) { + public QuestData(String name2, int diff, QuestMode mode2, final String formatString, GameFormatQuest userFormat) { this.name = name2; - if (formatString == null) { + if (userFormat != null) { + format = userFormat; + } else if (formatString == null) { format = null; } else { format = new GameFormatQuest(Singletons.getModel().getFormats().getFormat(formatString));