Quick Commander and Build Commander Gauntlet both working on desktop

This commit is contained in:
LEGIONLAPTOP\dougc
2025-03-19 12:31:02 -04:00
committed by Chris H
parent a9df4ea424
commit 3788e01f38
8 changed files with 535 additions and 8 deletions

View File

@@ -63,7 +63,8 @@ public class FDeckChooser extends JPanel implements IDecksComboBoxListener {
//Show dialog to select a deck
public static Deck promptForDeck(final CDetailPicture cDetailPicture, final String title, final DeckType defaultDeckType, final boolean forAi) {
FThreads.assertExecutedByEdt(true);
final FDeckChooser chooser = new FDeckChooser(cDetailPicture, forAi, GameType.Constructed, false);
boolean isForCommander = defaultDeckType.equals(DeckType.COMMANDER_DECK);
final FDeckChooser chooser = new FDeckChooser(cDetailPicture, forAi, isForCommander? GameType.Commander : GameType.Constructed, isForCommander);
chooser.initialize(defaultDeckType);
chooser.populate();
final Dimension parentSize = JOptionPane.getRootFrame().getSize();

View File

@@ -68,7 +68,8 @@ public enum EDocID {
HOME_GAUNTLETBUILD (VSubmenuGauntletBuild.SINGLETON_INSTANCE),
HOME_GAUNTLETLOAD (VSubmenuGauntletLoad.SINGLETON_INSTANCE),
HOME_GAUNTLETQUICK (VSubmenuGauntletQuick.SINGLETON_INSTANCE),
HOME_GAUNTLETCOMMANDER (VSubmenuGauntletCommanderQuick.SINGLETON_INSTANCE),
HOME_GAUNTLETCOMMANDERQUICK (VSubmenuGauntletCommanderQuick.SINGLETON_INSTANCE),
HOME_GAUNTLETCOMMANDERBUILD (VSubmenuGauntletCommanderBuild.SINGLETON_INSTANCE),
HOME_GAUNTLETCONTESTS (VSubmenuGauntletContests.SINGLETON_INSTANCE),
HOME_PREFERENCES (VSubmenuPreferences.SINGLETON_INSTANCE),
HOME_ACHIEVEMENTS (VSubmenuAchievements.SINGLETON_INSTANCE),

View File

@@ -23,10 +23,7 @@ import forge.deck.*;
import forge.item.PaperCard;
import forge.screens.deckeditor.menus.DeckFileMenu;
import forge.screens.deckeditor.views.VCurrentDeck;
import forge.screens.home.gauntlet.VSubmenuGauntletBuild;
import forge.screens.home.gauntlet.VSubmenuGauntletCommanderQuick;
import forge.screens.home.gauntlet.VSubmenuGauntletContests;
import forge.screens.home.gauntlet.VSubmenuGauntletQuick;
import forge.screens.home.gauntlet.*;
import forge.screens.home.sanctioned.VSubmenuConstructed;
import forge.util.ItemPool;
import forge.util.Localizer;
@@ -359,6 +356,7 @@ public class DeckController<T extends DeckBase> {
VSubmenuGauntletQuick.SINGLETON_INSTANCE.updateDeckPanel();
VSubmenuGauntletContests.SINGLETON_INSTANCE.updateDeckPanel();
VSubmenuGauntletCommanderQuick.SINGLETON_INSTANCE.updateDeckPanel();
VSubmenuGauntletCommanderBuild.SINGLETON_INSTANCE.updateDeckPanel();
}
/**

View File

@@ -134,6 +134,7 @@ public enum VHomeUI implements IVTopLevelUI {
allSubmenus.add(VSubmenuGauntletLoad.SINGLETON_INSTANCE);
allSubmenus.add(VSubmenuGauntletContests.SINGLETON_INSTANCE);
allSubmenus.add(VSubmenuGauntletCommanderQuick.SINGLETON_INSTANCE);
allSubmenus.add(VSubmenuGauntletCommanderBuild.SINGLETON_INSTANCE);
allSubmenus.add(VSubmenuPuzzleSolve.SINGLETON_INSTANCE);
allSubmenus.add(VSubmenuPuzzleCreate.SINGLETON_INSTANCE);

View File

@@ -0,0 +1,224 @@
package forge.screens.home.gauntlet;
import forge.deck.Deck;
import forge.gamemodes.gauntlet.GauntletData;
import forge.gamemodes.gauntlet.GauntletIO;
import forge.gui.UiCommand;
import forge.gui.framework.ICDoc;
import forge.localinstance.properties.ForgeConstants;
import forge.toolbox.FOptionPane;
import org.apache.commons.lang3.ArrayUtils;
import javax.swing.*;
import javax.swing.filechooser.FileFilter;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/**
* Controls the "build edh gauntlet" submenu in the home UI.
*
* <br><br><i>(C at beginning of class name denotes a control class.)</i>
*
*/
public enum CSubmenuGauntletCommanderBuild implements ICDoc {
SINGLETON_INSTANCE;
private final VSubmenuGauntletCommanderBuild view = VSubmenuGauntletCommanderBuild.SINGLETON_INSTANCE;
private final List<Deck> workingDecks = new ArrayList<>();
private final File openStartDir = new File(ForgeConstants.GAUNTLET_DIR.userPrefLoc);
private final FileFilter filterDAT = new FileFilter() {
@Override
public boolean accept(final File f) {
if (f.isDirectory()) {
return true;
}
final String filename = f.getName();
return (!filename.startsWith(GauntletIO.PREFIX_QUICK) && filename.endsWith(GauntletIO.SUFFIX_DATA));
}
@Override
public String getDescription() {
return "Forge data file .dat";
}
};
private final UiCommand cmdAddDeck = this::addDeck;
private final UiCommand cmdRemoveDeck = this::removeDeck;
private final UiCommand cmdDeckUp = this::deckUp;
private final UiCommand cmdDeckDown = this::deckDown;
private final UiCommand cmdSave = this::saveGauntlet;
private final UiCommand cmdNew = this::newGauntlet;
private final UiCommand cmdOpen = this::openGauntlet;
/* (non-Javadoc)
* @see forge.gui.home.ICSubmenu#initialize()
*/
@Override
public void update() {
SwingUtilities.invokeLater(view::focusName);
}
@Override
public void register() {
}
/* (non-Javadoc)
* @see forge.gui.home.ICSubmenu#initialize()
*/
@Override
public void initialize() {
view.getLstRight().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
view.getBtnRight().setCommand(cmdAddDeck);
view.getBtnLeft().setCommand(cmdRemoveDeck);
view.getBtnUp().setCommand(cmdDeckUp);
view.getBtnDown().setCommand(cmdDeckDown);
view.getBtnSave().setCommand(cmdSave);
view.getBtnOpen().setCommand(cmdOpen);
view.getBtnNew().setCommand(cmdNew);
view.getLstLeft().initialize();
// updateDecks();
}
private void addDeck() {
final Deck deckToAdd = view.getLstLeft().getPlayer() != null ? view.getLstLeft().getPlayer().getDeck() : null;
if (null == deckToAdd) {
return;
}
workingDecks.add(deckToAdd);
view.getLblSave().setVisible(false);
dumpDecksIntoList();
}
private void removeDeck() {
final int selection = view.getLstRight().getSelectedIndex();
if (selection == -1) { return; }
workingDecks.remove(selection);
view.getLblSave().setVisible(false);
dumpDecksIntoList();
}
private void deckUp() {
final int oldIndex = view.getLstRight().getSelectedIndex();
if (oldIndex <= 0) { return; }
final Deck movingDeck = workingDecks.remove(oldIndex);
workingDecks.add(oldIndex - 1, movingDeck);
view.getLblSave().setVisible(false);
dumpDecksIntoList();
view.getLstRight().setSelectedIndex(oldIndex - 1);
}
private void deckDown() {
final int oldIndex = view.getLstRight().getSelectedIndex();
if (oldIndex == workingDecks.size() - 1) { return; }
final Deck movingDeck = workingDecks.remove(oldIndex);
workingDecks.add(oldIndex + 1, movingDeck);
view.getLblSave().setVisible(false);
dumpDecksIntoList();
view.getLstRight().setSelectedIndex(oldIndex + 1);
}
private void dumpDecksIntoList() {
final List<String> names = new ArrayList<>();
for (final Deck d : workingDecks) {
names.add(d.getName());
}
view.getLstRight().setListData(names.toArray(ArrayUtils.EMPTY_STRING_ARRAY));
}
private boolean saveGauntlet() {
final String name = view.getTxfFilename().getText();
final GauntletData gd;
// Warn if no name
if (name.isEmpty()) {
FOptionPane.showMessageDialog(
"Please name your gauntlet using the 'Gauntlet Name' box.",
"Save Error!",
FOptionPane.ERROR_ICON);
return false;
}
final File f = new File(ForgeConstants.GAUNTLET_DIR.userPrefLoc + name + ".dat");
// Confirm if overwrite
if (f.exists()) {
if (!FOptionPane.showConfirmDialog(
"There is already a gauntlet named '" + name + "'.\n"
+ "All progress and data will be overwritten. Continue?",
"Overwrite Gauntlet?")) { return false; }
gd = GauntletIO.loadGauntlet(f);
if (gd == null) { return false; }
}
// Confirm if a new gauntlet will be created
else {
if (!FOptionPane.showConfirmDialog(
"This will create a new gauntlet named '" + name + "'. Continue?",
"Create Gauntlet?")) { return false; }
gd = new GauntletData(true);
}
final List<String> names = new ArrayList<>();
for (final Deck d : workingDecks) {
names.add(d.getName());
}
gd.setEventNames(names);
gd.setDecks(workingDecks);
gd.setName(name);
gd.reset();
view.getLblSave().setVisible(false);
return true;
}
private boolean openGauntlet() {
final File file;
final JFileChooser open = new JFileChooser(openStartDir);
open.setDialogTitle("Import Deck");
open.addChoosableFileFilter(this.filterDAT);
final int returnVal = open.showOpenDialog(null);
if (returnVal == JFileChooser.APPROVE_OPTION) {
file = open.getSelectedFile();
}
else {
return false;
}
final GauntletData gd = GauntletIO.loadGauntlet(file);
if (gd == null) { return false; }
this.workingDecks.clear();
this.workingDecks.addAll(gd.getDecks());
view.getTxfFilename().setText(file.getName().substring(0, file.getName().lastIndexOf('.')));
dumpDecksIntoList();
return true;
}
private boolean newGauntlet() {
workingDecks.clear();
dumpDecksIntoList();
view.getTxfFilename().setText("");
return true;
}
}

View File

@@ -0,0 +1,298 @@
package forge.screens.home.gauntlet;
import forge.deckchooser.FDeckChooser;
import forge.game.GameType;
import forge.gamemodes.gauntlet.GauntletIO;
import forge.gui.framework.DragCell;
import forge.gui.framework.DragTab;
import forge.gui.framework.EDocID;
import forge.localinstance.skin.FSkinProp;
import forge.screens.home.EMenuGroup;
import forge.screens.home.IVSubmenu;
import forge.screens.home.VHomeUI;
import forge.toolbox.*;
import forge.util.Localizer;
import net.miginfocom.swing.MigLayout;
import javax.swing.*;
import java.awt.*;
/**
* Assembles Swing components of "build edh gauntlet" submenu singleton.
*
* <br><br><i>(V at beginning of class name denotes a view class.)</i>
*
*/
public enum VSubmenuGauntletCommanderBuild implements IVSubmenu<CSubmenuGauntletCommanderBuild> {
/** */
SINGLETON_INSTANCE;
final Localizer localizer = Localizer.getInstance();
// Fields used with interface IVDoc
private DragCell parentCell;
private final DragTab tab = new DragTab(localizer.getMessage("lblGauntletCommanderBuilder"));
// Other fields
private final FLabel lblTitle = new FLabel.Builder()
.text(localizer.getMessage("lblGauntletCommanderBuilder")).fontAlign(SwingConstants.CENTER)
.opaque(true).fontSize(16).build();
private final JPanel pnlFileHandling = new JPanel(new MigLayout("insets 0, gap 0, align center"));
private final JPanel pnlButtons = new JPanel();
private final JPanel pnlStrut = new JPanel();
private final JPanel pnlDirections = new JPanel();
private final FDeckChooser lstLeft = new FDeckChooser(null, false, GameType.CommanderGauntlet, true);
private final JList<String> lstRight = new FList<>();
private final FScrollPane scrRight = new FScrollPane(lstRight, true,
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
private final FTextField txfFilename = new FTextField.Builder().ghostText(GauntletIO.TXF_PROMPT).showGhostTextWithFocus().build();
private final FLabel lblDesc1 = new FLabel.Builder().text(localizer.getMessage("lblGauntletDesc1")).fontSize(12).build();
private final FLabel lblDesc2 = new FLabel.Builder()
.text(localizer.getMessage("lblGauntletDesc2"))
.fontSize(12).build();
private final FLabel lblDecklist = new FLabel.Builder()
.text(localizer.getMessage("lblDecklist"))
.fontSize(12).build();
private final JLabel lblSave = new FLabel.Builder().text(localizer.getMessage("lblChangesNotSave"))
.build();
private final FLabel btnUp = new FLabel.Builder()
.tooltip(localizer.getMessage("btnUp")).hoverable(true)
.iconScaleAuto(true).iconScaleFactor(1.0)
.icon(FSkin.getImage(FSkinProp.IMG_CUR_T)).build();
private final FLabel btnDown = new FLabel.Builder()
.tooltip(localizer.getMessage("btnDown")).hoverable(true)
.iconScaleAuto(true).iconScaleFactor(1.0)
.icon(FSkin.getImage(FSkinProp.IMG_CUR_B)).build();
private final FLabel btnRight = new FLabel.Builder()
.tooltip(localizer.getMessage("btnRight")).hoverable(true)
.iconScaleAuto(true).iconScaleFactor(1.0)
.icon(FSkin.getImage(FSkinProp.IMG_CUR_R)).build();
private final FLabel btnLeft = new FLabel.Builder()
.tooltip(localizer.getMessage("btnLeft")).hoverable(true)
.iconScaleAuto(true).iconScaleFactor(1.0)
.icon(FSkin.getImage(FSkinProp.IMG_CUR_L)).build();
private final FLabel btnSave = new FLabel.Builder()
.fontSize(14)
.tooltip(localizer.getMessage("btnSaveGauntlet"))
.iconInBackground(true)
.iconAlignX(SwingConstants.CENTER)
.icon(FSkin.getIcon(FSkinProp.ICO_SAVE))
.text(" ").hoverable(true).build();
private final FLabel btnNew = new FLabel.Builder()
.fontSize(14)
.tooltip(localizer.getMessage("btnNewGauntlet"))
.iconInBackground(true)
.iconAlignX(SwingConstants.CENTER)
.icon(FSkin.getIcon(FSkinProp.ICO_NEW))
.text(" ").hoverable(true).build();
private final FLabel btnOpen = new FLabel.Builder()
.fontSize(14)
.tooltip(localizer.getMessage("btnLoadaGauntlet"))
.iconInBackground(true)
.iconAlignX(SwingConstants.CENTER)
.icon(FSkin.getIcon(FSkinProp.ICO_OPEN))
.text(" ").hoverable(true).build();
VSubmenuGauntletCommanderBuild() {
lblTitle.setBackground(FSkin.getColor(FSkin.Colors.CLR_THEME2));
// File handling panel
final FLabel lblFilename = new FLabel.Builder()
.text( localizer.getMessage("lblGauntletName")+ ":").fontSize(14).build();
pnlFileHandling.setOpaque(false);
pnlFileHandling.add(lblFilename, "h 30px!, gap 0 5px 0");
pnlFileHandling.add(txfFilename, "h 30px!, w 200px!, gap 0 5px 0 0");
pnlFileHandling.add(btnSave, "h 30px!, w 30px!, gap 0 5px 0 0");
pnlFileHandling.add(btnNew, "h 30px!, w 30px!, gap 0 5px 0 0");
pnlFileHandling.add(btnOpen, "h 30px!, w 30px!, gap 0 5px 0 0");
// Directions panel
final JPanel pnlSpacer = new JPanel();
pnlSpacer.setOpaque(false);
pnlStrut.setOpaque(false);
lblSave.setForeground(Color.red);
lblSave.setVisible(false);
pnlDirections.setOpaque(false);
pnlDirections.setLayout(new MigLayout("insets 0, gap 0, wrap"));
pnlDirections.add(pnlSpacer, "w 100%!, pushy, growy");
pnlDirections.add(lblDesc1, "gap 1% 0 0 10px");
pnlDirections.add(lblDesc2, "gap 1% 0 0 10px");
pnlDirections.add(lblDecklist, "gap 1% 0 0 20px");
pnlDirections.add(lblSave, "ax center, gap 0 0 0 5px");
// Deck movement panel
pnlButtons.setLayout(new MigLayout("insets 0, gap 0, wrap, ay center"));
pnlButtons.setOpaque(false);
pnlButtons.add(btnRight, "h 40px!, w 100%!");
pnlButtons.add(btnLeft, "h 40px!, w 100%!");
pnlButtons.add(btnUp, "h 40px!, w 100%!, gap 0 0 50px 0, ay bottom");
pnlButtons.add(btnDown, "h 40px!, w 100%!, ay baseline");
}
public void updateDeckPanel() {
lstLeft.restoreSavedState();
}
public void focusName() {
txfFilename.requestFocusInWindow();
}
/* (non-Javadoc)
* @see forge.gui.home.IVSubmenu#getGroupEnum()
*/
@Override
public EMenuGroup getGroupEnum() {
return EMenuGroup.GAUNTLET;
}
/* (non-Javadoc)
* @see forge.gui.home.IVSubmenu#getMenuTitle()
*/
@Override
public String getMenuTitle() {
return localizer.getMessage("lblBuildACommanderGauntlet");
}
/* (non-Javadoc)
* @see forge.gui.home.IVSubmenu#getItemEnum()
*/
@Override
public EDocID getItemEnum() {
return EDocID.HOME_GAUNTLETCOMMANDERBUILD;
}
/* (non-Javadoc)
* @see forge.gui.home.IVSubmenu#populate()
*/
@Override
public void populate() {
VHomeUI.SINGLETON_INSTANCE.getPnlDisplay().removeAll();
VHomeUI.SINGLETON_INSTANCE.getPnlDisplay().setLayout(new MigLayout("insets 0, gap 0, wrap 3"));
lstLeft.populate();
VHomeUI.SINGLETON_INSTANCE.getPnlDisplay().add(lblTitle, "w 98%!, h 30px!, gap 1% 0 15px 15px, span 3");
VHomeUI.SINGLETON_INSTANCE.getPnlDisplay().add(pnlFileHandling, "w 98%!, gap 1% 0 1% 5px, span 3");
VHomeUI.SINGLETON_INSTANCE.getPnlDisplay().add(lstLeft, "w 48% - 20px!, gap 1% 0 0 25px, spany 2, growy");
VHomeUI.SINGLETON_INSTANCE.getPnlDisplay().add(pnlStrut, "w 40px!, gap 1% 1% 0 15px");
VHomeUI.SINGLETON_INSTANCE.getPnlDisplay().add(pnlDirections, "w 48% - 20px!, gap 0 0 0 15px");
// VHomeUI.SINGLETON_INSTANCE.getPnlDisplay().add(lstLeft, "w 48% - 20px!, gap 1% 0 0 25px, pushy, growy");
VHomeUI.SINGLETON_INSTANCE.getPnlDisplay().add(pnlButtons, "w 40px!, gap 1% 1% 0 25px, pushy, growy");
VHomeUI.SINGLETON_INSTANCE.getPnlDisplay().add(scrRight, "w 48% - 20px!, gap 0 0 0 25px, pushy, growy");
VHomeUI.SINGLETON_INSTANCE.getPnlDisplay().repaintSelf();
VHomeUI.SINGLETON_INSTANCE.getPnlDisplay().revalidate();
}
/** @return {@link javax.swing.JList} */
public FDeckChooser getLstLeft() {
return this.lstLeft;
}
/** @return {@link javax.swing.JList} */
public JList<String> getLstRight() {
return this.lstRight;
}
/** @return {@link forge.toolbox.FLabel} */
public FLabel getBtnUp() {
return btnUp;
}
/** @return {@link forge.toolbox.FLabel} */
public FLabel getBtnDown() {
return btnDown;
}
/** @return {@link forge.toolbox.FLabel} */
public FLabel getBtnRight() {
return btnRight;
}
/** @return {@link forge.toolbox.FLabel} */
public FLabel getBtnLeft() {
return btnLeft;
}
/** @return {@link javax.swing.JLabel} */
public FLabel getBtnSave() {
return btnSave;
}
/** @return {@link javax.swing.JLabel} */
public FLabel getBtnOpen() {
return btnOpen;
}
/** @return {@link javax.swing.JLabel} */
public FLabel getBtnNew() {
return btnNew;
}
/** @return {@link javax.swing.JLabel} */
public JLabel getLblSave() {
return lblSave;
}
/** @return {@link javax.swing.JTextField} */
public FTextField getTxfFilename() {
return txfFilename;
}
//========== Overridden from IVDoc
/* (non-Javadoc)
* @see forge.gui.framework.IVDoc#getDocumentID()
*/
@Override
public EDocID getDocumentID() {
return EDocID.HOME_GAUNTLETCOMMANDERBUILD;
}
/* (non-Javadoc)
* @see forge.gui.framework.IVDoc#getTabLabel()
*/
@Override
public DragTab getTabLabel() {
return tab;
}
/* (non-Javadoc)
* @see forge.gui.framework.IVDoc#getLayoutControl()
*/
@Override
public CSubmenuGauntletCommanderBuild getLayoutControl() {
return CSubmenuGauntletCommanderBuild.SINGLETON_INSTANCE;
}
/* (non-Javadoc)
* @see forge.gui.framework.IVDoc#setParentCell(forge.gui.framework.DragCell)
*/
@Override
public void setParentCell(DragCell cell0) {
this.parentCell = cell0;
}
/* (non-Javadoc)
* @see forge.gui.framework.IVDoc#getParentCell()
*/
@Override
public DragCell getParentCell() {
return parentCell;
}
}

View File

@@ -123,7 +123,7 @@ public enum VSubmenuGauntletCommanderQuick implements IVSubmenu<CSubmenuGauntlet
*/
@Override
public EDocID getItemEnum() {
return EDocID.HOME_GAUNTLETCOMMANDER;
return EDocID.HOME_GAUNTLETCOMMANDERQUICK;
}
/* (non-Javadoc)
@@ -184,7 +184,7 @@ public enum VSubmenuGauntletCommanderQuick implements IVSubmenu<CSubmenuGauntlet
*/
@Override
public EDocID getDocumentID() {
return EDocID.HOME_GAUNTLETCOMMANDER;
return EDocID.HOME_GAUNTLETCOMMANDERQUICK;
}
/* (non-Javadoc)

View File

@@ -698,6 +698,10 @@ btnLoadaGauntlet=Load a gauntlet
lblGauntletName=Gauntlet Name
lblBuildAGauntlet=Build A Gauntlet
lblChangesNotSave=Changes not yet saved.
#VSubmenuGauntletCommanderBuild
lblGauntletCommanderBuilder=Commander Gauntlet Builder
lblBuildACommanderGauntlet=Build An EDH Gauntlet
#QuestUtil.java
lblTravelBetweenWorlds=Travel between worlds.
lblWhereDoYouWishToTravel=Where do you wish to travel?