GUI: improved main and battlefield menus (related to #11533):

- main menu: better naming for deck editor;
- battlefield menu: added deck view for computer players, better naming;
- network: improved experimental connection;
This commit is contained in:
Oleg Agafonov 2023-12-09 15:20:29 +04:00
parent ba8650b4e2
commit 6aaaa8cb46
11 changed files with 187 additions and 132 deletions

View file

@ -614,6 +614,8 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
Component[] windows = desktopPane.getComponentsInLayer(javax.swing.JLayeredPane.DEFAULT_LAYER);
MagePaneMenuItem menuItem;
// TODO: sort menu by games, not current component order
// lobby -> table 1 tourny, table 1 draft, table 1 game, table 2...
for (int i = 0; i < windows.length; i++) {
if (windows[i] instanceof MagePane) {
MagePane window = (MagePane) windows[i];
@ -1284,34 +1286,59 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
}
}
public void showDeckEditor(DeckEditorMode mode, Deck deck, UUID tableId, int time) {
private String prepareDeckEditorName(DeckEditorMode mode, Deck deck, UUID tableId) {
// GUI searching frame name for duplicates, so:
// - online editors must be unique;
// - offline editor must be single;
String name;
if (mode == DeckEditorMode.SIDEBOARDING
|| mode == DeckEditorMode.LIMITED_BUILDING
|| mode == DeckEditorMode.LIMITED_SIDEBOARD_BUILDING
|| mode == DeckEditorMode.VIEW_LIMITED_DECK) {
name = "Deck Editor - " + tableId.toString();
} else {
if (deck != null) {
name = "Deck Editor - " + deck.getName();
} else {
switch (mode) {
case FREE_BUILDING:
// offline
name = "Deck Editor";
}
// use already open editor
Component[] windows = desktopPane.getComponentsInLayer(JLayeredPane.DEFAULT_LAYER);
for (Component window : windows) {
if (window instanceof DeckEditorPane && ((MagePane) window).getTitle().equals(name)) {
setActive((MagePane) window);
return;
}
break;
case LIMITED_BUILDING:
case LIMITED_SIDEBOARD_BUILDING:
case SIDEBOARDING:
case VIEW_LIMITED_DECK:
// online
name = "Deck Editor - " + mode.getTitle();
break;
default:
throw new IllegalArgumentException("Unknown deck editor mode: " + mode);
}
// additional info about deck/player
if (deck != null && deck.getName() != null && !deck.getName().isEmpty()) {
name += " - " + deck.getName();
}
// additional info about game
if (tableId != null) {
name += " - table " + tableId;
}
return name;
}
public void showDeckEditor(DeckEditorMode mode, Deck deck, UUID tableId, int visibleTimer) {
// create or open new editor
String name = prepareDeckEditorName(mode, deck, tableId);
// already exists
Component[] windows = desktopPane.getComponentsInLayer(JLayeredPane.DEFAULT_LAYER);
for (Component window : windows) {
if (window instanceof DeckEditorPane && ((MagePane) window).getTitle().equals(name)) {
setActive((MagePane) window);
return;
}
}
DeckEditorPane deckEditorPane = new DeckEditorPane();
desktopPane.add(deckEditorPane, JLayeredPane.DEFAULT_LAYER);
deckEditorPane.setVisible(false);
deckEditorPane.show(mode, deck, name, tableId, time);
setActive(deckEditorPane);
// new editor
DeckEditorPane deckEditor = new DeckEditorPane();
desktopPane.add(deckEditor, JLayeredPane.DEFAULT_LAYER);
deckEditor.setVisible(false);
deckEditor.show(mode, deck, name, tableId, visibleTimer);
setActive(deckEditor);
}
public void showUserRequestDialog(final UserRequestMessage userRequestMessage) {

View file

@ -104,8 +104,8 @@ public final class SessionHandler {
session.connectStop(askForReconnect, keepMySessionActive);
}
public static void sendPlayerAction(PlayerAction playerAction, UUID gameId, Object relatedUserId) {
session.sendPlayerAction(playerAction, gameId, relatedUserId);
public static void sendPlayerAction(PlayerAction playerAction, UUID gameId, Object data) {
session.sendPlayerAction(playerAction, gameId, data);
}
public static void quitTournament(UUID tournamentId) {

View file

@ -101,12 +101,21 @@ public final class Constants {
}
public enum DeckEditorMode {
FREE_BUILDING(""),
LIMITED_BUILDING("building"),
LIMITED_SIDEBOARD_BUILDING("sideboard building"),
SIDEBOARDING("sideboarding"),
VIEW_LIMITED_DECK("view");
FREE_BUILDING,
LIMITED_BUILDING,
LIMITED_SIDEBOARD_BUILDING,
SIDEBOARDING,
VIEW_LIMITED_DECK
private String title;
DeckEditorMode(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
}
public enum SortBy {

View file

@ -45,20 +45,10 @@ public class DeckEditorPane extends MagePane {
deckEditorPanel1.changeGUISize();
}
public void show(DeckEditorMode mode, Deck deck, String name, UUID tableId, int time) {
public void show(DeckEditorMode mode, Deck deck, String name, UUID tableId, int visibleTimer) {
this.tableId = tableId;
if (mode == DeckEditorMode.SIDEBOARDING
|| mode == DeckEditorMode.LIMITED_BUILDING
|| mode == DeckEditorMode.LIMITED_SIDEBOARD_BUILDING) {
this.setTitle("Deck Editor - " + tableId.toString());
} else if (mode == DeckEditorMode.VIEW_LIMITED_DECK) {
this.setTitle("Deck Editor - Current Deck");
} else if (deck != null) {
this.setTitle("Deck Editor - " + deck.getName());
} else {
this.setTitle("Deck Editor");
}
this.deckEditorPanel1.showDeckEditor(mode, deck, tableId, time);
this.setTitle(name);
this.deckEditorPanel1.showDeckEditor(mode, deck, tableId, visibleTimer);
this.repaint();
}

View file

@ -200,7 +200,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
this.deckArea.changeGUISize();
}
public void showDeckEditor(DeckEditorMode mode, Deck deck, UUID tableId, int time) {
public void showDeckEditor(DeckEditorMode mode, Deck deck, UUID tableId, int visibleTimer) {
if (deck != null) {
this.deck = deck;
}
@ -236,7 +236,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
}
this.deckArea.showSideboard(true);
countdown.stop();
this.timeout = time;
this.timeout = visibleTimer;
setTimeout(timeout);
if (timeout != 0) {
countdown.start();
@ -278,8 +278,8 @@ public class DeckEditorPanel extends javax.swing.JPanel {
this.cardSelector.setVisible(false);
this.deckArea.setOrientation(/*limitedBuildingOrientation = */true);
this.deckArea.showSideboard(true);
this.lblDeckName.setVisible(false);
this.txtDeckName.setVisible(false);
this.lblDeckName.setVisible(true);
this.txtDeckName.setVisible(true);
this.txtTimeRemaining.setVisible(false);
break;
}

View file

@ -1,6 +1,5 @@
package mage.client.game;
import mage.cards.decks.importer.DeckImporter;
import mage.client.MageFrame;
import mage.client.SessionHandler;
import mage.client.cards.BigCard;
@ -32,6 +31,7 @@ public class PlayAreaPanel extends javax.swing.JPanel {
private final JPopupMenu popupMenu;
private UUID playerId;
private String playerName;
private UUID gameId;
private boolean isMe = false;
private boolean smallMode = false;
@ -67,6 +67,11 @@ public class PlayAreaPanel extends javax.swing.JPanel {
setOpaque(false);
battlefieldPanel.setOpaque(false);
// data init
init(player, bigCard, gameId, priorityTime);
update(null, player, null);
// init popup menu (must run after data init)
popupMenu = new JPopupMenu();
if (options.isPlayer) {
addPopupMenuPlayer(player.getUserData().isAllowRequestHandToAll());
@ -74,10 +79,8 @@ public class PlayAreaPanel extends javax.swing.JPanel {
addPopupMenuWatcher();
}
this.add(popupMenu);
setGUISize();
init(player, bigCard, gameId, priorityTime);
update(null, player, null);
setGUISize();
}
public void CleanUp() {
@ -311,49 +314,16 @@ public class PlayAreaPanel extends javax.swing.JPanel {
// Reset the replacement and yes/no dialogs that were auto selected for the game
menuItem.addActionListener(e -> SessionHandler.sendPlayerAction(PlayerAction.REQUEST_AUTO_ANSWER_RESET_ALL, gameId, null));
JMenu handCardsMenu = new JMenu("Cards on hand");
handCardsMenu.setMnemonic(KeyEvent.VK_H);
popupMenu.add(handCardsMenu);
if (!options.playerItself) {
menuItem = new JMenuItem("Request permission to see the hand cards");
menuItem.setMnemonic(KeyEvent.VK_P);
handCardsMenu.add(menuItem);
// Request to see hand cards
menuItem.addActionListener(e -> SessionHandler.sendPlayerAction(PlayerAction.REQUEST_PERMISSION_TO_SEE_HAND_CARDS, gameId, playerId));
} else {
allowViewHandCardsMenuItem = new JCheckBoxMenuItem("Allow hand requests from other users", allowRequestToShowHandCards);
allowViewHandCardsMenuItem.setMnemonic(KeyEvent.VK_A);
allowViewHandCardsMenuItem.setToolTipText("Watchers or other players can request your hand cards once per game. Re-activate it to allow new requests.");
handCardsMenu.add(allowViewHandCardsMenuItem);
// requests allowed (disable -> enable to reset requested list)
allowViewHandCardsMenuItem.addActionListener(e -> {
boolean requestsAllowed = ((JCheckBoxMenuItem) e.getSource()).getState();
PreferencesDialog.setPrefValue(KEY_GAME_ALLOW_REQUEST_SHOW_HAND_CARDS, requestsAllowed);
SessionHandler.sendPlayerAction(requestsAllowed ? PlayerAction.PERMISSION_REQUESTS_ALLOWED_ON : PlayerAction.PERMISSION_REQUESTS_ALLOWED_OFF, gameId, null);
});
menuItem = new JMenuItem("Revoke all permission(s) to see your hand cards");
menuItem.setMnemonic(KeyEvent.VK_R);
menuItem.setToolTipText("Revoke already granted permission for all spectators to see your hand cards.");
handCardsMenu.add(menuItem);
// revoke permissions to see hand cards
menuItem.addActionListener(e -> SessionHandler.sendPlayerAction(PlayerAction.REVOKE_PERMISSIONS_TO_SEE_HAND_CARDS, gameId, null));
}
JMenu rollbackMainItem = new JMenu("Rollback");
rollbackMainItem.setToolTipText("The game will be rolled back to the start of the requested turn if all players agree");
popupMenu.add(rollbackMainItem);
if (options.rollbackTurnsAllowed) {
ActionListener rollBackActionListener = e -> {
int turnsToRollBack = Integer.parseInt(e.getActionCommand());
SessionHandler.sendPlayerAction(PlayerAction.ROLLBACK_TURNS, gameId, turnsToRollBack);
};
JMenu rollbackMainItem = new JMenu("Rollback");
rollbackMainItem.setMnemonic(KeyEvent.VK_R);
rollbackMainItem.setToolTipText("The game will be rolled back to the start of the requested turn if all players agree.");
popupMenu.add(rollbackMainItem);
menuItem = new JMenuItem("To the start of the current turn");
menuItem.setMnemonic(KeyEvent.VK_C);
@ -378,7 +348,8 @@ public class PlayAreaPanel extends javax.swing.JPanel {
menuItem.setActionCommand("3");
menuItem.addActionListener(rollBackActionListener);
rollbackMainItem.add(menuItem);
} else {
rollbackMainItem.setText(rollbackMainItem.getText() + ", restricted");
}
JMenu concedeMenu = new JMenu("Concede");
@ -443,30 +414,65 @@ public class PlayAreaPanel extends javax.swing.JPanel {
}
});
popupMenu.addSeparator();
// view deck
menuItem = new JMenuItem("<html>View player's deck");
menuItem.setMnemonic(KeyEvent.VK_D);
// view hands
JMenu handCardsMenu = new JMenu(String.format("Cards on hand (%s)", (options.playerItself ? "me" : playerName)));
handCardsMenu.setMnemonic(KeyEvent.VK_H);
popupMenu.add(handCardsMenu);
if (!options.playerItself) {
menuItem = new JMenuItem("Request permission to see the hand cards");
menuItem.setMnemonic(KeyEvent.VK_P);
handCardsMenu.add(menuItem);
// Request to see hand cards
menuItem.addActionListener(e -> SessionHandler.sendPlayerAction(PlayerAction.REQUEST_PERMISSION_TO_SEE_HAND_CARDS, gameId, playerId));
} else {
allowViewHandCardsMenuItem = new JCheckBoxMenuItem("Allow hand requests from other users", allowRequestToShowHandCards);
allowViewHandCardsMenuItem.setMnemonic(KeyEvent.VK_A);
allowViewHandCardsMenuItem.setToolTipText("Watchers or other players can request your hand cards once per game. Re-activate it to allow new requests.");
handCardsMenu.add(allowViewHandCardsMenuItem);
// requests allowed (disable -> enable to reset requested list)
allowViewHandCardsMenuItem.addActionListener(e -> {
boolean requestsAllowed = ((JCheckBoxMenuItem) e.getSource()).getState();
PreferencesDialog.setPrefValue(KEY_GAME_ALLOW_REQUEST_SHOW_HAND_CARDS, requestsAllowed);
SessionHandler.sendPlayerAction(requestsAllowed ? PlayerAction.PERMISSION_REQUESTS_ALLOWED_ON : PlayerAction.PERMISSION_REQUESTS_ALLOWED_OFF, gameId, null);
});
menuItem = new JMenuItem("Revoke all permission(s) to see your hand cards");
menuItem.setMnemonic(KeyEvent.VK_R);
menuItem.setToolTipText("Revoke already granted permission for all spectators to see your hand cards.");
handCardsMenu.add(menuItem);
// revoke permissions to see hand cards
menuItem.addActionListener(e -> SessionHandler.sendPlayerAction(PlayerAction.REVOKE_PERMISSIONS_TO_SEE_HAND_CARDS, gameId, null));
}
// view deck (allows to view only own deck or computer)
// it's a client side checks... same checks must be on server side too (see PlayerView)
menuItem = new JMenuItem(String.format("<html>View deck (%s)", (options.playerItself ? "me" : playerName)));
popupMenu.add(menuItem);
menuItem.addActionListener(e -> {
SessionHandler.sendPlayerAction(PlayerAction.VIEW_LIMITED_DECK, gameId, null);
});
if (options.playerItself || !options.isHuman) {
menuItem.setMnemonic(KeyEvent.VK_D);
menuItem.addActionListener(e -> {
SessionHandler.sendPlayerAction(PlayerAction.VIEW_LIMITED_DECK, gameId, playerId);
});
} else {
menuItem.setText(menuItem.getText() + ", restricted");
}
// view sideboard (allows to view only own sideboard or computer)
// it's a client side checks... same checks must be on server side too (see PlayerView)
menuItem = new JMenuItem(String.format("<html>View sideboard (%s)", (options.playerItself ? "me" : playerName)));
popupMenu.add(menuItem);
if (options.playerItself || !options.isHuman) {
String menuCaption = "<html>View my sideboard";
if (!options.isHuman) {
menuCaption = "<html>View computer's sideboard";
}
menuItem = new JMenuItem(menuCaption);
menuItem.setMnemonic(KeyEvent.VK_S);
popupMenu.add(menuItem);
menuItem.addActionListener(e -> {
SessionHandler.sendPlayerAction(PlayerAction.VIEW_SIDEBOARD, gameId, playerId);
});
} else {
menuItem.setText(menuItem.getText() + ", restricted");
}
}
@ -485,10 +491,9 @@ public class PlayAreaPanel extends javax.swing.JPanel {
MageFrame.getInstance().showUserRequestDialog(message);
});
menuItem = new JMenuItem("Request permission to see hand cards");
popupMenu.add(menuItem);
// Request to see hand cards
menuItem = new JMenuItem(String.format("Request permission to see hand cards (%s)", playerName));
popupMenu.add(menuItem);
menuItem.addActionListener(e -> SessionHandler.sendPlayerAction(PlayerAction.REQUEST_PERMISSION_TO_SEE_HAND_CARDS, gameId, playerId));
battlefieldPanel.getMainPanel().addMouseListener(new MouseAdapter() {
@ -517,6 +522,7 @@ public class PlayAreaPanel extends javax.swing.JPanel {
this.battlefieldPanel.init(gameId, bigCard);
this.gameId = gameId;
this.playerId = player.getPlayerId();
this.playerName = player.getName();
this.isMe = player.getControlled();
this.btnCheat.setVisible(SessionHandler.isTestMode());
}

View file

@ -24,6 +24,7 @@ public final class DeckUtil {
public static Deck construct(DeckView view) {
Deck deck = new Deck();
deck.setName(view.getName());
for (SimpleCardView cardView : view.getCards().values()) {
CardInfo cardInfo = CardRepository.instance.findCard(cardView.getExpansionSetCode(), cardView.getCardNumber());
Card card = cardInfo != null ? cardInfo.getMockCard() : null;