Better Games In Match Selection (#8098)

* Add GamesInMatch combo box selection to booster draft page

Also updated combo box default to be seeded with the stored preferences

* Working comboboxes for desktop version

* Working linked buttons on Mobile

* Add binder classes for preferences and other Model components

* Move to pref binders for mobile GUI
This commit is contained in:
Matthew Scott Krafczyk
2025-07-25 09:07:19 -05:00
committed by GitHub
parent 79845eff1d
commit ab2b06500b
11 changed files with 220 additions and 17 deletions

View File

@@ -0,0 +1,26 @@
package forge.gui;
import javax.swing.*;
import java.awt.event.ItemEvent;
import forge.localinstance.properties.ForgePreferences;
import forge.model.FPrefsBinder;
public class SwingPrefBinders {
public static final class ComboBox extends FPrefsBinder<JComboBox<String>, String> {
public ComboBox(ForgePreferences.FPref key, JComboBox<String> box) {
super(
key,
box,
b -> (String) b.getSelectedItem(),
(b, s) -> b.setSelectedItem(s),
s -> s,
s -> s);
box.addItemListener(e -> {
if (e.getStateChange() == ItemEvent.SELECTED) {
this.save();
}
});
}
}
}

View File

@@ -54,6 +54,7 @@ public class CLobby {
// General updates when switching back to this view
view.getBtnStart().requestFocusInWindow();
});
view.getGamesInMatchBinder().load();
}
public void initialize() {

View File

@@ -34,6 +34,7 @@ import forge.gamemodes.match.LobbySlotType;
import forge.gamemodes.net.event.UpdateLobbyPlayerEvent;
import forge.gui.CardDetailPanel;
import forge.gui.GuiBase;
import forge.gui.SwingPrefBinders;
import forge.gui.interfaces.ILobbyView;
import forge.gui.util.SOptionPane;
import forge.interfaces.IPlayerChangeListener;
@@ -74,7 +75,9 @@ public class VLobby implements ILobbyView {
private final StartButton btnStart = new StartButton();
private final JPanel pnlStart = new JPanel(new MigLayout("insets 0, gap 0, wrap 2"));
private final JComboBox gamesInMatch = new JComboBox(new String[] {"1","3","5"});
private final JComboBox<String> gamesInMatch = new JComboBox<String>(new String[] {"1","3","5"});
private final SwingPrefBinders.ComboBox gamesInMatchBinder =
new SwingPrefBinders.ComboBox(FPref.UI_MATCHES_PER_GAME, gamesInMatch);
private final JPanel gamesInMatchFrame = new JPanel(new MigLayout("insets 0, gap 0, wrap 2"));
private final JPanel constructedFrame = new JPanel(new MigLayout("insets 0, gap 0, wrap 2")); // Main content frame
@@ -182,17 +185,19 @@ public class VLobby implements ILobbyView {
btnStart.addActionListener(arg0 -> {
Runnable startGame = lobby.startGame();
if (startGame != null) {
if (!gamesInMatch.getSelectedItem().equals(FPref.UI_MATCHES_PER_GAME)) {
FModel.getPreferences().setPref(FPref.UI_MATCHES_PER_GAME, (String) gamesInMatch.getSelectedItem());
}
startGame.run();
}
});
}
String defaultGamesInMatch = FModel.getPreferences().getPref(FPref.UI_MATCHES_PER_GAME);
if (defaultGamesInMatch == null || defaultGamesInMatch.isEmpty()) {
defaultGamesInMatch = "3";
}
gamesInMatchFrame.add(newLabel(localizer.getMessage("lblGamesInMatch")), "w 150px!, h 30px!");
gamesInMatchFrame.add(gamesInMatch, "w 50px!, h 30px!");
gamesInMatchFrame.setOpaque(false);
gamesInMatch.setSelectedItem("3");
pnlStart.add(gamesInMatchFrame);
}
@@ -855,6 +860,11 @@ public class VLobby implements ILobbyView {
return nonRandomAiAvatars;
}
/** Return the gamesInMatchBinder */
public SwingPrefBinders.ComboBox getGamesInMatchBinder() {
return gamesInMatchBinder;
}
/** Populate vanguard lists. */
private void populateVanguardLists() {
humanListData.add("Use deck's default avatar (random if unavailable)");

View File

@@ -97,12 +97,15 @@ public enum CSubmenuDraft implements ICDoc {
view.getBtnBuildDeck().requestFocusInWindow();
}
});
view.getGamesInMatchBinder().load();
}
private void startGame(final GameType gameType) {
final Localizer localizer = Localizer.getInstance();
final boolean gauntlet = VSubmenuDraft.SINGLETON_INSTANCE.isGauntlet();
final DeckProxy humanDeck = VSubmenuDraft.SINGLETON_INSTANCE.getLstDecks().getSelectedItem();
final VSubmenuDraft view = VSubmenuDraft.SINGLETON_INSTANCE;
final boolean gauntlet = view.isGauntlet();
final DeckProxy humanDeck = view.getLstDecks().getSelectedItem();
if (humanDeck == null) {
FOptionPane.showErrorDialog(localizer.getMessage("lblNoDeckSelected"), localizer.getMessage("lblNoDeck"));
@@ -245,5 +248,4 @@ public enum CSubmenuDraft implements ICDoc {
combo.addItem("5");
}
}
}

View File

@@ -13,6 +13,7 @@ import forge.game.GameType;
import forge.gui.framework.DragCell;
import forge.gui.framework.DragTab;
import forge.gui.framework.EDocID;
import forge.gui.SwingPrefBinders;
import forge.itemmanager.DeckManager;
import forge.itemmanager.ItemManagerContainer;
import forge.screens.deckeditor.CDeckEditorUI;
@@ -26,6 +27,8 @@ import forge.toolbox.FLabel;
import forge.toolbox.FRadioButton;
import forge.toolbox.FSkin;
import forge.toolbox.JXButtonPanel;
import forge.localinstance.properties.ForgePreferences.FPref;
import forge.model.FModel;
import forge.util.Localizer;
import net.miginfocom.swing.MigLayout;
@@ -57,6 +60,11 @@ public enum VSubmenuDraft implements IVSubmenu<CSubmenuDraft> {
private final JComboBox<String> cbOpponent = new JComboBox<>();
private final JComboBox<String> gamesInMatch = new JComboBox<String>(new String[] {"1","3","5"});
private final SwingPrefBinders.ComboBox gamesInMatchBinder =
new SwingPrefBinders.ComboBox(FPref.UI_MATCHES_PER_GAME, gamesInMatch);
private final JPanel gamesInMatchFrame = new JPanel(new MigLayout("insets 0, gap 0, wrap 2"));
private final JLabel lblInfo = new FLabel.Builder()
.fontAlign(SwingConstants.LEFT).fontSize(16).fontStyle(Font.BOLD)
.text(localizer.getMessage("lblBuildorselectadeck")).build();
@@ -73,6 +81,10 @@ public enum VSubmenuDraft implements IVSubmenu<CSubmenuDraft> {
.text(localizer.getMessage("lblDraftText3"))
.fontSize(12).build();
private final FLabel lblGamesInMatch = new FLabel.Builder()
.text(localizer.getMessage("lblGamesInMatch"))
.fontSize(12).build();
private final FLabel btnBuildDeck = new FLabel.ButtonBuilder().text(localizer.getMessage("lblNewBoosterDraftGame")).fontSize(16).build();
/**
@@ -91,10 +103,22 @@ public enum VSubmenuDraft implements IVSubmenu<CSubmenuDraft> {
radSingle.setSelected(true);
grpPanel.add(cbOpponent, "w 200px!, h 30px!");
pnlStart.setLayout(new MigLayout("insets 0, gap 0, wrap 2"));
pnlStart.setLayout(new MigLayout("insets 0, gap 0",
"[grow][pref!]",
"[pref!][grow,fill][pref!]"));
pnlStart.setOpaque(false);
pnlStart.add(grpPanel, "gapright 20");
pnlStart.add(btnStart);
pnlStart.add(grpPanel, "cell 0 0 1 3, growy, gapright 20");
String defaultGamesInMatch = FModel.getPreferences().getPref(FPref.UI_MATCHES_PER_GAME);
if (defaultGamesInMatch == null || defaultGamesInMatch.isEmpty()) {
defaultGamesInMatch = "3";
}
gamesInMatchFrame.add(lblGamesInMatch, "w 150px!, h 30px!");
gamesInMatchFrame.add(gamesInMatch, "w 50px!, h 30px!");
gamesInMatchFrame.setOpaque(false);
pnlStart.add(gamesInMatchFrame, "cell 1 0, alignx center, aligny top");
pnlStart.add(btnStart, "cell 1 2, alignx center, aligny bottom");
}
/* (non-Javadoc)
@@ -147,6 +171,7 @@ public enum VSubmenuDraft implements IVSubmenu<CSubmenuDraft> {
public JRadioButton getRadSingle() { return radSingle; }
public JRadioButton getRadMultiple() { return radMultiple; }
public JRadioButton getRadAll() { return radAll; }
public SwingPrefBinders.ComboBox getGamesInMatchBinder() { return gamesInMatchBinder; }
//========== Overridden from IVDoc