GUI: reworked GUI to support non-blocking UI:

- GUI: added non-blocking UI to almost all app and game dialogs;
- GUI: it allows to switch between UI dialogs and use any UI elements at any moment;
- GUI: it allows to use chat, card popup, battlefield, concede and other features while choosing (related to #12670);
- GUI: it allows to download images while playing (related to #4160, not fully tested);
- GUI: enabled by default, can be disabled by java option: -Dxmage.guiModalMode=true
- connection: auto-connect will be visible in main menu on startup;
- connection: removed some unused features (auto-connect by command line);
- connection: added <ESC> button to close connection dialog;
- download: added background images download (see non-blocking UI);
- download: improved cancel stability and fixes that it can't stop preparing/downloading process in some use cases;
- app: fixed freezes on macOS systems in some use cases (related to #12431, #11292, #9300, #4920);
This commit is contained in:
Oleg Agafonov 2024-09-08 00:40:13 +04:00
parent 2fc4e94b3a
commit 6625db1be1
40 changed files with 614 additions and 532 deletions

View file

@ -277,10 +277,10 @@ public final class GamePanel extends javax.swing.JPanel {
pnlShortCuts.add(btnStopWatching);
pickNumber = new PickNumberDialog();
MageFrame.getDesktop().add(pickNumber, JLayeredPane.MODAL_LAYER);
MageFrame.getDesktop().add(pickNumber, pickNumber.isModal() ? JLayeredPane.MODAL_LAYER : JLayeredPane.PALETTE_LAYER);
pickMultiNumber = new PickMultiNumberDialog();
MageFrame.getDesktop().add(pickMultiNumber, JLayeredPane.MODAL_LAYER);
MageFrame.getDesktop().add(pickMultiNumber, pickMultiNumber.isModal() ? JLayeredPane.MODAL_LAYER : JLayeredPane.PALETTE_LAYER);
this.feedbackPanel.setConnectedChatPanel(this.userChatPanel);
@ -1226,7 +1226,7 @@ public final class GamePanel extends javax.swing.JPanel {
if (exileWindow == null) {
exileWindow = new CardInfoWindowDialog(ShowType.EXILE, exile.getName());
exiles.put(exile.getId(), exileWindow);
MageFrame.getDesktop().add(exileWindow, JLayeredPane.PALETTE_LAYER);
MageFrame.getDesktop().add(exileWindow, exileWindow.isModal() ? JLayeredPane.MODAL_LAYER : JLayeredPane.PALETTE_LAYER);
exileWindow.show();
}
exileWindow.loadCardsAndShow(exile, bigCard, gameId);
@ -1607,7 +1607,7 @@ public final class GamePanel extends javax.swing.JPanel {
}
CardInfoWindowDialog newGraveyard = new CardInfoWindowDialog(ShowType.GRAVEYARD, playerName);
graveyardWindows.put(playerName, newGraveyard);
MageFrame.getDesktop().add(newGraveyard, JLayeredPane.PALETTE_LAYER);
MageFrame.getDesktop().add(newGraveyard, newGraveyard.isModal() ? JLayeredPane.MODAL_LAYER : JLayeredPane.PALETTE_LAYER);
// use graveyards to sync selection (don't use player data here)
newGraveyard.loadCardsAndShow(graveyards.get(playerName), bigCard, gameId, false);
}
@ -1632,7 +1632,7 @@ public final class GamePanel extends javax.swing.JPanel {
newDialog.setSize(GUISizeHelper.dialogGuiScaleSize(newDialog.getSize()));
newDialog.setGameData(this.lastGameData.game, this.gameId, this.bigCard);
cardHintsWindows.put(code + UUID.randomUUID(), newDialog);
MageFrame.getDesktop().add(newDialog, JLayeredPane.PALETTE_LAYER);
MageFrame.getDesktop().add(newDialog, newDialog.isModal() ? JLayeredPane.MODAL_LAYER : JLayeredPane.PALETTE_LAYER);
newDialog.loadHints(lastGameData.game);
}
@ -1661,7 +1661,7 @@ public final class GamePanel extends javax.swing.JPanel {
CardInfoWindowDialog windowDialog = new CardInfoWindowDialog(ShowType.SIDEBOARD, playerView.getName());
sideboardWindows.put(playerView.getName(), windowDialog);
MageFrame.getDesktop().add(windowDialog, JLayeredPane.PALETTE_LAYER);
MageFrame.getDesktop().add(windowDialog, windowDialog.isModal() ? JLayeredPane.MODAL_LAYER : JLayeredPane.PALETTE_LAYER);
// use sideboards to sync selection (don't use player data here)
windowDialog.loadCardsAndShow(sideboards.get(playerView.getName()), bigCard, gameId, false);
}
@ -1714,7 +1714,7 @@ public final class GamePanel extends javax.swing.JPanel {
if (!windowMap.containsKey(name)) {
cardInfoWindowDialog = new CardInfoWindowDialog(showType, name);
windowMap.put(name, cardInfoWindowDialog);
MageFrame.getDesktop().add(cardInfoWindowDialog, JLayeredPane.PALETTE_LAYER);
MageFrame.getDesktop().add(cardInfoWindowDialog, cardInfoWindowDialog.isModal() ? JLayeredPane.MODAL_LAYER : JLayeredPane.PALETTE_LAYER);
} else {
cardInfoWindowDialog = windowMap.get(name);
}
@ -2153,12 +2153,13 @@ public final class GamePanel extends javax.swing.JPanel {
hideAll();
DialogManager.getManager(gameId).fadeOut();
pickNumber.showDialog(min, max, message);
if (pickNumber.isCancel()) {
SessionHandler.sendPlayerBoolean(gameId, false);
} else {
SessionHandler.sendPlayerInteger(gameId, pickNumber.getAmount());
}
pickNumber.showDialog(min, max, message, () -> {
if (pickNumber.isCancel()) {
SessionHandler.sendPlayerBoolean(gameId, false);
} else {
SessionHandler.sendPlayerInteger(gameId, pickNumber.getAmount());
}
});
}
public void getMultiAmount(int messageId, GameView gameView, List<MultiAmountMessage> messages, Map<String, Serializable> options,
@ -2167,12 +2168,13 @@ public final class GamePanel extends javax.swing.JPanel {
hideAll();
DialogManager.getManager(gameId).fadeOut();
pickMultiNumber.showDialog(messages, min, max, lastGameData.options);
if (pickMultiNumber.isCancel()) {
SessionHandler.sendPlayerBoolean(gameId, false);
} else {
SessionHandler.sendPlayerString(gameId, pickMultiNumber.getMultiAmount());
}
pickMultiNumber.showDialog(messages, min, max, lastGameData.options, () -> {
if (pickMultiNumber.isCancel()) {
SessionHandler.sendPlayerBoolean(gameId, false);
} else {
SessionHandler.sendPlayerString(gameId, pickMultiNumber.getMultiAmount());
}
});
}
public void getChoice(int messageId, GameView gameView, Map<String, Serializable> options, Choice choice, UUID objectId) {
@ -2182,23 +2184,23 @@ public final class GamePanel extends javax.swing.JPanel {
// TODO: remember last choices and search incremental for same events?
PickChoiceDialog pickChoice = new PickChoiceDialog();
pickChoice.showDialog(choice, null, objectId, choiceWindowState, bigCard);
pickChoice.showDialog(choice, null, objectId, choiceWindowState, bigCard, () -> {
// special mode adds # to the answer (server side code must process that prefix, see replacementEffectChoice)
String specialPrefix = choice.isChosenSpecial() ? "#" : "";
// special mode adds # to the answer (server side code must process that prefix, see replacementEffectChoice)
String specialPrefix = choice.isChosenSpecial() ? "#" : "";
String valueToSend;
if (choice.isKeyChoice()) {
valueToSend = choice.getChoiceKey();
} else {
valueToSend = choice.getChoice();
}
SessionHandler.sendPlayerString(gameId, valueToSend == null ? null : specialPrefix + valueToSend);
String valueToSend;
if (choice.isKeyChoice()) {
valueToSend = choice.getChoiceKey();
} else {
valueToSend = choice.getChoice();
}
SessionHandler.sendPlayerString(gameId, valueToSend == null ? null : specialPrefix + valueToSend);
// keep dialog position
choiceWindowState = new MageDialogState(pickChoice);
// keep dialog position
choiceWindowState = new MageDialogState(pickChoice);
pickChoice.removeDialog();
pickChoice.removeDialog();
});
}
public void pickPile(int messageId, GameView gameView, Map<String, Serializable> options, String message, CardsView pile1, CardsView pile2) {
@ -2212,12 +2214,11 @@ public final class GamePanel extends javax.swing.JPanel {
PickPileDialog pickPileDialog = new PickPileDialog();
this.pickPile.add(pickPileDialog);
pickPileDialog.loadCards(message, pile1, pile2, bigCard, gameId);
if (pickPileDialog.isPickedOK()) {
SessionHandler.sendPlayerBoolean(gameId, pickPileDialog.isPickedPile1());
}
pickPileDialog.cleanUp();
pickPileDialog.removeDialog();
pickPileDialog.showDialog(message, pile1, pile2, bigCard, gameId, () -> {
if (pickPileDialog.isPickedOK()) {
SessionHandler.sendPlayerBoolean(gameId, pickPileDialog.isPickedPile1());
}
});
}
public Map<UUID, PlayAreaPanel> getPlayers() {