Merge branch 'historicformats' into 'master'

Formatting and preparation of historicformats

See merge request core-developers/forge!342
This commit is contained in:
Sol
2018-05-16 01:40:34 +00:00
663 changed files with 5593 additions and 90 deletions

View File

@@ -7,10 +7,13 @@ import forge.itemmanager.filters.*;
import forge.model.FModel;
import forge.quest.QuestWorld;
import forge.quest.data.QuestPreferences;
import forge.screens.home.quest.DialogChooseFormats;
import forge.screens.home.quest.DialogChooseSets;
import forge.screens.match.controllers.CDetailPicture;
import javax.swing.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;
@@ -82,7 +85,7 @@ public class CardManager extends ItemManager<PaperCard> {
GuiUtils.addSeparator(menu); //separate from current search item
JMenu fmt = GuiUtils.createMenu("Format");
for (final GameFormat f : FModel.getFormats().getOrderedList()) {
for (final GameFormat f : FModel.getFormats().getFilterList()) {
GuiUtils.addMenuItem(fmt, f.getName(), null, new Runnable() {
@Override
public void run() {
@@ -92,6 +95,27 @@ public class CardManager extends ItemManager<PaperCard> {
}
menu.add(fmt);
GuiUtils.addMenuItem(menu, "Formats...", null, new Runnable() {
@Override public void run() {
final CardSetFilter existingFilter = itemManager.getFilter(CardSetFilter.class);
if (existingFilter != null) {
existingFilter.edit();
} else {
final DialogChooseFormats dialog = new DialogChooseFormats();
dialog.setOkCallback(new Runnable() {
@Override public void run() {
final List<GameFormat> formats = dialog.getSelectedFormats();
if (!formats.isEmpty()) {
for(GameFormat format: formats) {
itemManager.addFilter(new CardFormatFilter(itemManager, format));
}
}
}
});
}
}
});
GuiUtils.addMenuItem(menu, "Sets...", null, new Runnable() {
@Override
public void run() {

View File

@@ -4,18 +4,15 @@ import java.awt.Component;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.util.HashMap;
import java.util.TreeSet;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.Map.Entry;
import java.util.SortedSet;
import javax.swing.JMenu;
import javax.swing.JTable;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import forge.screens.home.quest.DialogChooseFormats;
import org.apache.commons.lang3.StringUtils;
import forge.Singletons;
@@ -176,7 +173,7 @@ public final class DeckManager extends ItemManager<DeckProxy> implements IHasGam
menu.add(folder);
final JMenu fmt = GuiUtils.createMenu("Format");
for (final GameFormat f : FModel.getFormats().getOrderedList()) {
for (final GameFormat f : FModel.getFormats().getFilterList()) {
GuiUtils.addMenuItem(fmt, f.getName(), null, new Runnable() {
@Override
public void run() {
@@ -186,6 +183,29 @@ public final class DeckManager extends ItemManager<DeckProxy> implements IHasGam
}
menu.add(fmt);
GuiUtils.addMenuItem(menu, "Formats...", null, new Runnable() {
@Override public void run() {
final DeckFormatFilter existingFilter = getFilter(DeckFormatFilter.class);
if (existingFilter != null) {
existingFilter.edit();
} else {
final DialogChooseFormats dialog = new DialogChooseFormats();
dialog.setOkCallback(new Runnable() {
@Override public void run() {
final List<GameFormat> formats = dialog.getSelectedFormats();
if (!formats.isEmpty()) {
for(GameFormat format: formats) {
addFilter(new DeckFormatFilter(DeckManager.this, format));
}
}
}
});
}
}
});
GuiUtils.addMenuItem(menu, "Sets...", null, new Runnable() {
@Override public void run() {
final DeckSetFilter existingFilter = getFilter(DeckSetFilter.class);

View File

@@ -6,6 +6,7 @@ import forge.game.GameFormat;
import forge.deck.DeckProxy;
import forge.itemmanager.ItemManager;
import forge.itemmanager.SFilterUtil;
import forge.screens.home.quest.DialogChooseFormats;
public class DeckFormatFilter extends FormatFilter<DeckProxy> {
@@ -27,4 +28,16 @@ public class DeckFormatFilter extends FormatFilter<DeckProxy> {
protected final Predicate<DeckProxy> buildPredicate() {
return DeckProxy.createPredicate(SFilterUtil.buildFormatFilter(this.formats, this.allowReprints));
}
public void edit() {
final DialogChooseFormats dialog = new DialogChooseFormats(this.formats);
dialog.setOkCallback(new Runnable() {
@Override
public void run() {
allowReprints = dialog.getWantReprints();
formats.clear();
formats.addAll(dialog.getSelectedFormats());
}
});
}
}

View File

@@ -27,6 +27,7 @@ public abstract class FormatFilter<T extends InventoryItem> extends ListLabelFil
protected String getTooltip() {
Set<String> sets = new HashSet<String>();
Set<String> bannedCards = new HashSet<String>();
Set<String> additionalCards = new HashSet<>();
for (GameFormat format : this.formats) {
List<String> formatSets = format.getAllowedSetCodes();
@@ -37,6 +38,10 @@ public abstract class FormatFilter<T extends InventoryItem> extends ListLabelFil
if (formatBannedCards != null) {
bannedCards.addAll(formatBannedCards);
}
List<String> formatAdditionalCards = format.getAdditionalCards();
if (formatAdditionalCards != null) {
additionalCards.addAll(formatAdditionalCards);
}
}
//use HTML tooltips so we can insert line breaks
@@ -58,7 +63,9 @@ public abstract class FormatFilter<T extends InventoryItem> extends ListLabelFil
}
CardEdition edition = editions.get(code);
tooltip.append(" ").append(edition.getName()).append(" (").append(code).append("),");
if(edition!=null) {
tooltip.append(" ").append(edition.getName()).append(" (").append(code).append("),");
}
lineLen = tooltip.length() - lastLen;
}
@@ -90,6 +97,27 @@ public abstract class FormatFilter<T extends InventoryItem> extends ListLabelFil
// chop off last semicolon
tooltip.delete(tooltip.length() - 1, tooltip.length());
}
if (!additionalCards.isEmpty()) {
tooltip.append("<br><br>Additional:");
lastLen += lineLen;
lineLen = 0;
for (String cardName : additionalCards) {
// don't let a single line get too long
if (50 < lineLen) {
tooltip.append("<br>");
lastLen += lineLen;
lineLen = 0;
}
tooltip.append(" ").append(cardName).append(";");
lineLen = tooltip.length() - lastLen;
}
// chop off last semicolon
tooltip.delete(tooltip.length() - 1, tooltip.length());
}
tooltip.append("</html>");
return tooltip.toString();
}

View File

@@ -90,6 +90,24 @@ public enum CSubmenuQuestData implements ICDoc {
}
});
view.getBtnSelectFormat().setCommand(new UiCommand() {
@Override
public void run() {
final DialogChooseFormats dialog = new DialogChooseFormats();
dialog.setOkCallback(new Runnable() {
@Override
public void run() {
customFormatCodes.clear();
Set<String> sets = new HashSet<String>();
for(GameFormat format:dialog.getSelectedFormats()){
sets.addAll(format.getAllowedSetCodes());
}
customFormatCodes.addAll(sets);
}
});
}
});
view.getBtnPrizeCustomFormat().setCommand(new UiCommand() {
@Override
public void run() {
@@ -104,6 +122,24 @@ public enum CSubmenuQuestData implements ICDoc {
}
});
view.getBtnPrizeSelectFormat().setCommand(new UiCommand() {
@Override
public void run() {
final DialogChooseFormats dialog = new DialogChooseFormats();
dialog.setOkCallback(new Runnable() {
@Override
public void run() {
customPrizeFormatCodes.clear();
Set<String> sets = new HashSet<String>();
for(GameFormat format:dialog.getSelectedFormats()){
sets.addAll(format.getAllowedSetCodes());
}
customPrizeFormatCodes.addAll(sets);
}
});
}
});
view.getBtnPreferredColors().setCommand(new UiCommand() {
@Override
public void run() {
@@ -197,10 +233,11 @@ public enum CSubmenuQuestData implements ICDoc {
if (worldFormat == null) {
switch(view.getStartingPoolType()) {
case Rotating:
case Sanctioned:
fmtStartPool = view.getRotatingFormat();
break;
case Casual:
case CustomFormat:
if (customFormatCodes.isEmpty()) {
if (!FOptionPane.showConfirmDialog("You have defined a custom format that doesn't contain any sets.\nThis will start a game without restriction.\n\nContinue?")) {
@@ -257,6 +294,7 @@ public enum CSubmenuQuestData implements ICDoc {
case Complete:
fmtPrizes = null;
break;
case Casual:
case CustomFormat:
if (customPrizeFormatCodes.isEmpty()) {
if (!FOptionPane.showConfirmDialog("You have defined custom format as containing no sets.\nThis will choose all editions without restriction as prizes.\n\nContinue?")) {
@@ -265,7 +303,7 @@ public enum CSubmenuQuestData implements ICDoc {
}
fmtPrizes = customPrizeFormatCodes.isEmpty() ? null : new GameFormat("Custom Prizes", customPrizeFormatCodes, null); // chosen sets and no banned cards
break;
case Rotating:
case Sanctioned:
fmtPrizes = view.getPrizedRotatingFormat();
break;
default:

View File

@@ -0,0 +1,160 @@
package forge.screens.home.quest;
import forge.assets.FSkinProp;
import forge.card.CardEdition;
import forge.game.GameFormat;
import forge.gui.SOverlayUtils;
import forge.model.FModel;
import forge.toolbox.*;
import forge.util.TextUtil;
import net.miginfocom.swing.MigLayout;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;
public class DialogChooseFormats {
private List<GameFormat> selectedFormats = new ArrayList<>() ;
private boolean wantReprints = true;
private Runnable okCallback;
private final List<FCheckBox> choices = new ArrayList<>();
private final FCheckBox cbWantReprints = new FCheckBox("Allow compatible reprints from other sets");
public DialogChooseFormats(){
this(null);
}
public DialogChooseFormats(Set<GameFormat> preselectedFormats) {
List<FCheckBox> sanctioned = new ArrayList<>();
List<FCheckBox> casual = new ArrayList<>();
List<FCheckBox> historic = new ArrayList<>();
for (GameFormat format : FModel.getFormats().getOrderedList()){
FCheckBox box = new FCheckBox(format.getName());
box.setName(format.getName());
switch (format.getFormatType()){
case Sanctioned:
sanctioned.add(box);
break;
case Historic:
historic.add(box);
break;
case Custom:
case Casual:
case Digital:
default:
casual.add(box);
break;
}
box.setSelected(null != preselectedFormats && preselectedFormats.contains(format));
}
FPanel panel = new FPanel(new MigLayout("insets 0, gap 0, center, wrap 3"));
panel.setOpaque(false);
panel.setBackgroundTexture(FSkin.getIcon(FSkinProp.BG_TEXTURE));
panel.add(new FLabel.Builder().text("Choose formats").fontSize(18).build(), "center, span, wrap, gaptop 10");
String constraints = "aligny top";
panel.add(makeCheckBoxList(sanctioned, "Sanctioned", true), constraints);
panel.add(makeCheckBoxList(casual, "Other", false), constraints);
panel.add(makeCheckBoxList(historic, "Historic", false), constraints);
final JPanel overlay = FOverlay.SINGLETON_INSTANCE.getPanel();
overlay.setLayout(new MigLayout("insets 0, gap 0, wrap, ax center, ay center"));
final Runnable cleanup = new Runnable() {
@Override
public void run() {
SOverlayUtils.hideOverlay();
}
};
FButton btnOk = new FButton("OK");
btnOk.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
cleanup.run();
handleOk();
}
});
FButton btnCancel = new FButton("Cancel");
btnCancel.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
cleanup.run();
}
});
JPanel southPanel = new JPanel(new MigLayout("insets 10, gap 20, ax center"));
southPanel.setOpaque(false);
southPanel.add(cbWantReprints, "center, span, wrap");
southPanel.add(btnOk, "center, w 40%, h 20!");
southPanel.add(btnCancel, "center, w 40%, h 20!");
panel.add(southPanel, "dock south, gapBottom 10");
overlay.add(panel);
panel.getRootPane().setDefaultButton(btnOk);
SOverlayUtils.showOverlay();
}
public void setOkCallback(Runnable onOk) {
okCallback = onOk;
}
public List<GameFormat> getSelectedFormats() {
return selectedFormats;
}
public boolean getWantReprints() {
return wantReprints;
}
private JPanel makeCheckBoxList(List<FCheckBox> formats, String title, boolean focused) {
choices.addAll(formats);
final FCheckBoxList<FCheckBox> cbl = new FCheckBoxList<>(false);
cbl.setListData(formats.toArray(new FCheckBox[formats.size()]));
cbl.setVisibleRowCount(Math.min(20, formats.size()));
if (focused) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
cbl.requestFocusInWindow();
}
});
}
JPanel pnl = new JPanel(new MigLayout("center, wrap"));
pnl.setOpaque(false);
pnl.add(new FLabel.Builder().text(title).build());
pnl.add(new FScrollPane(cbl, true));
return pnl;
}
private void handleOk() {
for (FCheckBox box : choices) {
if (box.isSelected()) {
selectedFormats.add(FModel.getFormats().getFormat(box.getName()));
}
wantReprints = cbWantReprints.isSelected();
}
if (null != okCallback) {
okCallback.run();
}
}
}

View File

@@ -82,6 +82,8 @@ public enum VSubmenuQuestData implements IVSubmenu<CSubmenuQuestData> {
private final FComboBoxWrapper<Deck> cbxCustomDeck = new FComboBoxWrapper<>();
private final FLabel btnDefineCustomFormat = new FLabel.Builder().opaque(true).hoverable(true).text("Define custom format").build();
private final FLabel btnSelectFormat = new FLabel.Builder().opaque(true).hoverable(true).text("Select format").build();
private final FCheckBox boxCompleteSet = new FCheckBox("Start with all cards in selected sets");
private final FCheckBox boxAllowDuplicates = new FCheckBox("Allow duplicate cards");
@@ -91,6 +93,8 @@ public enum VSubmenuQuestData implements IVSubmenu<CSubmenuQuestData> {
private final FLabel btnPrizeDefineCustomFormat = new FLabel.Builder().opaque(true).hoverable(true).text("Define custom format").build();
private final FLabel btnPrizeSelectFormat = new FLabel.Builder().opaque(true).hoverable(true).text("Select format").build();
private final FLabel lblPrizedCards = new FLabel.Builder().text("Prized cards:").build();
private final FComboBoxWrapper<Object> cbxPrizedCards = new FComboBoxWrapper<>();
@@ -116,10 +120,11 @@ public enum VSubmenuQuestData implements IVSubmenu<CSubmenuQuestData> {
lblPreconDeck.setVisible(newVal == StartingPoolType.Precon);
cbxPreconDeck.setVisible(newVal == StartingPoolType.Precon);
lblFormat.setVisible(newVal == StartingPoolType.Rotating);
cbxFormat.setVisible(newVal == StartingPoolType.Rotating);
lblFormat.setVisible(newVal == StartingPoolType.Sanctioned);
cbxFormat.setVisible(newVal == StartingPoolType.Sanctioned);
btnDefineCustomFormat.setVisible(newVal == StartingPoolType.CustomFormat);
btnSelectFormat.setVisible(newVal == StartingPoolType.Casual);
final boolean usesDeckList = newVal == StartingPoolType.SealedDeck || newVal == StartingPoolType.DraftDeck || newVal == StartingPoolType.Cube;
@@ -152,9 +157,10 @@ public enum VSubmenuQuestData implements IVSubmenu<CSubmenuQuestData> {
lblPrizeUnrestricted.setVisible(newVal == StartingPoolType.Complete);
cboAllowUnlocks.setVisible(newVal != StartingPoolType.Complete);
lblPrizeFormat.setVisible(newVal == StartingPoolType.Rotating);
cbxPrizeFormat.setVisible(newVal == StartingPoolType.Rotating);
lblPrizeFormat.setVisible(newVal == StartingPoolType.Sanctioned);
cbxPrizeFormat.setVisible(newVal == StartingPoolType.Sanctioned);
btnPrizeDefineCustomFormat.setVisible(newVal == StartingPoolType.CustomFormat);
btnPrizeSelectFormat.setVisible(newVal == StartingPoolType.Casual);
lblPrizeSameAsStarting.setVisible(newVal == null);
}
};
@@ -200,7 +206,8 @@ public enum VSubmenuQuestData implements IVSubmenu<CSubmenuQuestData> {
boxAllowDuplicates.setToolTipText("When your starting pool is generated, duplicates of cards may be included.");
cbxStartingPool.addItem(StartingPoolType.Complete);
cbxStartingPool.addItem(StartingPoolType.Rotating);
cbxStartingPool.addItem(StartingPoolType.Sanctioned);
cbxStartingPool.addItem(StartingPoolType.Casual);
cbxStartingPool.addItem(StartingPoolType.CustomFormat);
cbxStartingPool.addItem(StartingPoolType.Precon);
cbxStartingPool.addItem(StartingPoolType.DraftDeck);
@@ -214,11 +221,12 @@ public enum VSubmenuQuestData implements IVSubmenu<CSubmenuQuestData> {
cbxPrizedCards.addItem("Same as starting pool");
cbxPrizedCards.addItem(StartingPoolType.Complete);
cbxPrizedCards.addItem(StartingPoolType.Rotating);
cbxPrizedCards.addItem(StartingPoolType.Sanctioned);
cbxPrizedCards.addItem(StartingPoolType.Casual);
cbxPrizedCards.addItem(StartingPoolType.CustomFormat);
cbxPrizedCards.addActionListener(alPrizesPool);
for (final GameFormat gf : FModel.getFormats().getOrderedList()) {
for (final GameFormat gf : FModel.getFormats().getSanctionedList()) {
cbxFormat.addItem(gf);
cbxPrizeFormat.addItem(gf);
}
@@ -311,6 +319,7 @@ public enum VSubmenuQuestData implements IVSubmenu<CSubmenuQuestData> {
cbxFormat.addTo(pnlRestrictions, constraints + cboWidthStart + " cell 1 1");
pnlRestrictions.add(btnDefineCustomFormat, btnStartingCustomFormatWidth + constraints + hidemode + " cell 1 1");
pnlRestrictions.add(btnSelectFormat, btnStartingCustomFormatWidth + constraints + hidemode + " cell 1 1");
pnlRestrictions.add(boxAllowDuplicates, "h 15px!, cell 1 2");
pnlRestrictions.add(boxCompleteSet, "h 15px!, cell 1 3");
@@ -325,6 +334,7 @@ public enum VSubmenuQuestData implements IVSubmenu<CSubmenuQuestData> {
pnlRestrictions.add(lblPrizeFormat, constraints + hidemode + "cell 0 6");
cbxPrizeFormat.addTo(pnlRestrictions, constraints + cboWidthStart + "cell 1 6"); // , skip 1
pnlRestrictions.add(btnPrizeDefineCustomFormat, btnStartingCustomFormatWidth + constraints + hidemode + "cell 1 6");
pnlRestrictions.add(btnPrizeSelectFormat, btnStartingCustomFormatWidth + constraints + hidemode + "cell 1 6");
pnlRestrictions.add(lblPrizeSameAsStarting, constraints + hidemode + "cell 1 6");
pnlRestrictions.add(lblPrizeUnrestricted, constraints + hidemode + "cell 1 6");
@@ -498,9 +508,23 @@ public enum VSubmenuQuestData implements IVSubmenu<CSubmenuQuestData> {
return cbxPrizeFormat.getSelectedItem();
}
public GameFormat getCasualFormat() {
return cbxFormat.getSelectedItem();
}
public GameFormat getPrizedCasualFormat() {
return cbxPrizeFormat.getSelectedItem();
}
public FLabel getBtnCustomFormat() {
return btnDefineCustomFormat;
}
public FLabel getBtnSelectFormat() {
return btnSelectFormat;
}
public FLabel getBtnPrizeSelectFormat() {
return btnPrizeSelectFormat;
}
public FLabel getBtnPrizeCustomFormat() {
return btnPrizeDefineCustomFormat;
}

View File

@@ -134,6 +134,9 @@ public enum CSubmenuPreferences implements ICDoc {
lstControls.add(Pair.of(view.getCbLoadCardsLazily(), FPref.LOAD_CARD_SCRIPTS_LAZILY));
lstControls.add(Pair.of(view.getCbLoadHistoricFormats(), FPref.LOAD_HISTORIC_FORMATS));
for(final Pair<JCheckBox, FPref> kv : lstControls) {
kv.getKey().addItemListener(new ItemListener() {
@Override

View File

@@ -65,6 +65,7 @@ public enum VSubmenuPreferences implements IVSubmenu<CSubmenuPreferences> {
private final JCheckBox cbManaLostPrompt = new OptionsCheckBox("Prompt Mana Pool Emptying");
private final JCheckBox cbDevMode = new OptionsCheckBox("Developer Mode");
private final JCheckBox cbLoadCardsLazily = new OptionsCheckBox("Load Card Scripts Lazily");
private final JCheckBox cbLoadHistoricFormats = new OptionsCheckBox("Load Historic Formats");
private final JCheckBox cbWorkshopSyntax = new OptionsCheckBox("Workshop Syntax Checker");
private final JCheckBox cbEnforceDeckLegality = new OptionsCheckBox("Deck Conformance");
private final JCheckBox cbImageFetcher = new OptionsCheckBox("Automatically Download Missing Card Art");
@@ -239,6 +240,9 @@ public enum VSubmenuPreferences implements IVSubmenu<CSubmenuPreferences> {
pnlPrefs.add(cbLoadCardsLazily, titleConstraints);
pnlPrefs.add(new NoteLabel("If turned on, Forge will load card scripts as they're needed instead of at start up. (Warning: Experimental)"), descriptionConstraints);
pnlPrefs.add(cbLoadHistoricFormats, titleConstraints);
pnlPrefs.add(new NoteLabel("If turned on, Forge will load all historic format definitions, this may take slightly longer to load at startup."), descriptionConstraints);
// Graphic Options
pnlPrefs.add(new SectionLabel("Graphic Options"), sectionConstraints + ", gaptop 2%");
@@ -586,6 +590,11 @@ public enum VSubmenuPreferences implements IVSubmenu<CSubmenuPreferences> {
return cbLoadCardsLazily;
}
/** @return {@link javax.swing.JCheckBox} */
public JCheckBox getCbLoadHistoricFormats() {
return cbLoadHistoricFormats;
}
public JCheckBox getCbWorkshopSyntax() {
return cbWorkshopSyntax;
}