diff --git a/Mage.Client/src/main/java/mage/client/MageFrame.java b/Mage.Client/src/main/java/mage/client/MageFrame.java index 522d45505c0..2247134dd55 100644 --- a/Mage.Client/src/main/java/mage/client/MageFrame.java +++ b/Mage.Client/src/main/java/mage/client/MageFrame.java @@ -94,11 +94,8 @@ public class MageFrame extends javax.swing.JFrame implements MageClient { private static final String LITE_MODE_ARG = "-lite"; private static final String GRAY_MODE_ARG = "-gray"; private static final String FULL_SCREEN_PROP = "xmage.fullScreen"; // -Dxmage.fullScreen=false + private static final String GUI_MODAL_MODE_PROP = "xmage.guiModalMode"; // -Dxmage.guiModalMode=false private static final String SKIP_DONE_SYMBOLS = "-skipDoneSymbols"; - private static final String USER_ARG = "-user"; - private static final String PASSWORD_ARG = "-pw"; - private static final String SERVER_ARG = "-server"; - private static final String PORT_ARG = "-port"; private static final String DEBUG_ARG = "-debug"; // enable debug button in main menu private static final String NOT_CONNECTED_TEXT = ""; @@ -121,11 +118,8 @@ public class MageFrame extends javax.swing.JFrame implements MageClient { private static boolean grayMode = false; private static boolean macOsFullScreenEnabled = true; private static boolean skipSmallSymbolGenerationForExisting = false; - private static String startUser = null; - private static String startPassword = ""; - private static String startServer = "localhost"; - private static int startPort = -1; private static boolean debugMode = false; + private static boolean guiModalModeEnabled = false; // non-blocking UI mode enabled by default private JToggleButton switchPanelsButton = null; // from main menu private static String SWITCH_PANELS_BUTTON_NAME = "Switch panels"; @@ -167,6 +161,10 @@ public class MageFrame extends javax.swing.JFrame implements MageClient { return skipSmallSymbolGenerationForExisting; } + public static boolean isGuiModalModeEnabled() { + return guiModalModeEnabled; + } + @Override public MageVersion getVersion() { return VERSION; @@ -305,10 +303,10 @@ public class MageFrame extends javax.swing.JFrame implements MageClient { SessionHandler.startSession(this); callbackClient = new CallbackClientImpl(this); connectDialog = new ConnectDialog(); - desktopPane.add(connectDialog, JLayeredPane.MODAL_LAYER); + desktopPane.add(connectDialog, connectDialog.isModal() ? JLayeredPane.MODAL_LAYER : JLayeredPane.PALETTE_LAYER); errorDialog = new ErrorDialog(); errorDialog.setLocation(100, 100); - desktopPane.add(errorDialog, JLayeredPane.MODAL_LAYER); + desktopPane.add(errorDialog, errorDialog.isModal() ? JLayeredPane.MODAL_LAYER : JLayeredPane.PALETTE_LAYER); try { this.whatsNewDialog = new WhatsNewDialog(); @@ -387,15 +385,16 @@ public class MageFrame extends javax.swing.JFrame implements MageClient { setGUISize(); setConnectButtonText(NOT_CONNECTED_BUTTON); SwingUtilities.invokeLater(() -> { - disableButtons(); updateMemUsageTask.execute(); LOGGER.info("Client start up time: " + ((System.currentTimeMillis() - startTime) / 1000 + " seconds")); - if (autoConnect()) { - enableButtons(); + + if (Boolean.parseBoolean(MageFrame.getPreferences().get("autoConnect", "false"))) { + startAutoConnect(); } else { - connectDialog.showDialog(); + connectDialog.showDialog(this::setWindowTitle); } - setWindowTitle(); + + setWindowTitle(); // make sure title is actual on startup }); // run what's new checks (loading in background) @@ -866,13 +865,13 @@ public class MageFrame extends javax.swing.JFrame implements MageClient { public void showGameEndDialog(GameEndView gameEndView) { GameEndDialog gameEndDialog = new GameEndDialog(gameEndView); - desktopPane.add(gameEndDialog, JLayeredPane.MODAL_LAYER); + desktopPane.add(gameEndDialog, gameEndDialog.isModal() ? JLayeredPane.MODAL_LAYER : JLayeredPane.PALETTE_LAYER); gameEndDialog.showDialog(); } public void showTableWaitingDialog(UUID roomId, UUID tableId, boolean isTournament) { TableWaitingDialog tableWaitingDialog = new TableWaitingDialog(); - desktopPane.add(tableWaitingDialog, JLayeredPane.MODAL_LAYER); + desktopPane.add(tableWaitingDialog, tableWaitingDialog.isModal() ? JLayeredPane.MODAL_LAYER : JLayeredPane.PALETTE_LAYER); tableWaitingDialog.showDialog(roomId, tableId, isTournament); } @@ -886,14 +885,23 @@ public class MageFrame extends javax.swing.JFrame implements MageClient { return SessionHandler.stopConnecting(); } - public boolean autoConnect() { - boolean autoConnectParamValue = startUser != null || Boolean.parseBoolean(MageFrame.getPreferences().get("autoConnect", "false")); - boolean status = false; - if (autoConnectParamValue) { - LOGGER.info("Auto-connecting to " + MagePreferences.getServerAddress()); - status = performConnect(false); - } - return status; + public void startAutoConnect() { + LOGGER.info("Auto-connecting to " + MagePreferences.getServerAddress()); + setConnectButtonText("AUTO-CONNECT to " + MagePreferences.getLastServerAddress()); + + SwingUtilities.invokeLater(() -> { + // TODO: run it as task, not in GUI thread - it can help to enable auto-connect cancel button like ConnectionDialog + boolean isConnected = false; + try { + isConnected = performConnect(false); + } finally { + // on bad - change text manual + // on good - it will be changed inside connection code + if (!isConnected) { + setConnectButtonText(NOT_CONNECTED_BUTTON); + } + } + }); } private boolean performConnect(boolean reconnect) { @@ -907,7 +915,6 @@ public class MageFrame extends javax.swing.JFrame implements MageClient { ProxyType proxyType = ProxyType.valueByText(MageFrame.getPreferences().get("proxyType", "None")); String proxyUsername = MageFrame.getPreferences().get("proxyUsername", ""); String proxyPassword = MageFrame.getPreferences().get("proxyPassword", ""); - setCursor(new Cursor(Cursor.WAIT_CURSOR)); currentConnection = new Connection(); currentConnection.setUsername(userName); currentConnection.setPassword(password); @@ -927,6 +934,7 @@ public class MageFrame extends javax.swing.JFrame implements MageClient { setUserPrefsToConnection(currentConnection); } + setCursor(new Cursor(Cursor.WAIT_CURSOR)); try { LOGGER.debug("connecting (auto): " + currentConnection.getProxyType().toString() + ' ' + currentConnection.getProxyHost() + ' ' + currentConnection.getProxyPort() + ' ' + currentConnection.getProxyUsername()); @@ -1172,13 +1180,12 @@ public class MageFrame extends javax.swing.JFrame implements MageClient { if (SessionHandler.isConnected()) { tryDisconnectOrExit(false); } else { - connectDialog.showDialog(); - setWindowTitle(); + connectDialog.showDialog(this::setWindowTitle); } }//GEN-LAST:event_btnConnectActionPerformed public void btnAboutActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnAboutActionPerformed - JInternalFrame[] windows = desktopPane.getAllFramesInLayer(JLayeredPane.MODAL_LAYER); + JInternalFrame[] windows = desktopPane.getAllFrames(); for (JInternalFrame window : windows) { if (window instanceof AboutDialog) { // don't open the window twice. @@ -1186,7 +1193,7 @@ public class MageFrame extends javax.swing.JFrame implements MageClient { } } AboutDialog aboutDialog = new AboutDialog(); - desktopPane.add(aboutDialog, JLayeredPane.MODAL_LAYER); + desktopPane.add(aboutDialog, aboutDialog.isModal() ? JLayeredPane.MODAL_LAYER : JLayeredPane.PALETTE_LAYER); aboutDialog.showDialog(VERSION); }//GEN-LAST:event_btnAboutActionPerformed @@ -1286,16 +1293,6 @@ public class MageFrame extends javax.swing.JFrame implements MageClient { } } - public void enableButtons() { - btnConnect.setEnabled(true); - btnDeckEditor.setEnabled(true); - } - - public void disableButtons() { - btnConnect.setEnabled(true); - btnDeckEditor.setEnabled(true); - } - public void hideServerLobby() { this.tablesPane.hideTables(); updateSwitchPanelsButton(); @@ -1416,7 +1413,7 @@ public class MageFrame extends javax.swing.JFrame implements MageClient { private void innerShowUserRequestDialog(final UserRequestMessage userRequestMessage) { UserRequestDialog userRequestDialog = new UserRequestDialog(); userRequestDialog.setLocation(100, 100); - desktopPane.add(userRequestDialog, JLayeredPane.MODAL_LAYER); + desktopPane.add(userRequestDialog, userRequestDialog.isModal() ? JLayeredPane.MODAL_LAYER : JLayeredPane.PALETTE_LAYER); userRequestDialog.showDialog(userRequestMessage); } @@ -1463,8 +1460,10 @@ public class MageFrame extends javax.swing.JFrame implements MageClient { public void showErrorDialog(String errorType, String errorTitle, String errorText) { if (SwingUtilities.isEventDispatchThread()) { + // calls from gui errorDialog.showDialog(errorType, errorTitle, errorText); } else { + // calls from another thread like download images or game events SwingUtilities.invokeLater(() -> errorDialog.showDialog(errorType, errorTitle, errorText)); } } @@ -1519,33 +1518,21 @@ public class MageFrame extends javax.swing.JFrame implements MageClient { if (arg.startsWith(GRAY_MODE_ARG)) { grayMode = true; } - if (System.getProperty(FULL_SCREEN_PROP) != null) { - macOsFullScreenEnabled = Boolean.parseBoolean(System.getProperty(FULL_SCREEN_PROP)); - } if (arg.startsWith(SKIP_DONE_SYMBOLS)) { skipSmallSymbolGenerationForExisting = true; } - if (arg.startsWith(USER_ARG)) { - startUser = args[i + 1]; - i++; - } - if (arg.startsWith(PASSWORD_ARG)) { - startPassword = args[i + 1]; - i++; - } - if (arg.startsWith(SERVER_ARG)) { - startServer = args[i + 1]; - i++; - } - if (arg.startsWith(PORT_ARG)) { - startPort = Integer.parseInt(args[i + 1]); - i++; - } if (arg.startsWith(DEBUG_ARG)) { debugMode = true; } } + if (System.getProperty(FULL_SCREEN_PROP) != null) { + macOsFullScreenEnabled = Boolean.parseBoolean(System.getProperty(FULL_SCREEN_PROP)); + } + if (System.getProperty(GUI_MODAL_MODE_PROP) != null) { + guiModalModeEnabled = Boolean.parseBoolean(System.getProperty(GUI_MODAL_MODE_PROP)); + } + // enable debug menu by default for developer build (if you run it from source code) debugMode |= VERSION.isDeveloperBuild(); @@ -1571,19 +1558,19 @@ public class MageFrame extends javax.swing.JFrame implements MageClient { if (settingsVersion == 0) { // fresh install or first run after 2024-08-14 // find best GUI size settings due screen resolution and DPI - LOGGER.info("settings: it's a first run, trying to apply GUI size settings"); + LOGGER.info("Settings: it's a first run, trying to apply GUI size settings"); int screenDPI = Toolkit.getDefaultToolkit().getScreenResolution(); int screenHeight = Toolkit.getDefaultToolkit().getScreenSize().height; - LOGGER.info(String.format("settings: screen DPI - %d, screen height - %d", screenDPI, screenHeight)); + LOGGER.info(String.format("Settings: screen DPI - %d, screen height - %d", screenDPI, screenHeight)); // find preset for String preset = PreferencesDialog.getDefaultSizeSettings().findBestPreset(screenDPI, screenHeight); if (preset != null) { - LOGGER.info("settings: selected preset " + preset); + LOGGER.info("Settings: selected preset " + preset); PreferencesDialog.getDefaultSizeSettings().applyPreset(preset); } else { - LOGGER.info("settings: WARNING, can't find compatible preset, use Preferences - GUI Size to setup your app"); + LOGGER.info("Settings: WARNING, can't find compatible preset, use Preferences - GUI Size to setup your app"); } PreferencesDialog.saveValue(PreferencesDialog.KEY_SETTINGS_VERSION, String.valueOf(1)); @@ -1598,21 +1585,12 @@ public class MageFrame extends javax.swing.JFrame implements MageClient { } // debug menu + if (debugMode) { + LOGGER.info("Settings: debug menu enabled"); + } instance.separatorDebug.setVisible(debugMode); instance.btnDebug.setVisible(debugMode); - if (startUser != null) { - instance.currentConnection = new Connection(); - instance.currentConnection.setUsername(startUser); - instance.currentConnection.setHost(startServer); - if (startPort > 0) { - instance.currentConnection.setPort(startPort); - } else { - instance.currentConnection.setPort(MagePreferences.getServerPortWithDefault(ClientDefaultSettings.port)); - } - PreferencesDialog.setProxyInformation(instance.currentConnection); - instance.currentConnection.setPassword(startPassword); - } instance.setVisible(true); }); } @@ -1735,7 +1713,6 @@ public class MageFrame extends javax.swing.JFrame implements MageClient { public void connected(final String message) { SwingUtilities.invokeLater(() -> { setConnectButtonText(message); - enableButtons(); }); } @@ -1756,7 +1733,6 @@ public class MageFrame extends javax.swing.JFrame implements MageClient { // TODO: why it ignore askToReconnect here, but use custom reconnect dialog later?! Need research SessionHandler.disconnect(false, keepMySessionActive); setConnectButtonText(NOT_CONNECTED_BUTTON); - disableButtons(); hideGames(); hideServerLobby(); if (askToReconnect) { @@ -1845,9 +1821,7 @@ public class MageFrame extends javax.swing.JFrame implements MageClient { SessionHandler.removeTable(userRequestMessage.getRoomId(), userRequestMessage.getTableId()); break; case CLIENT_RECONNECT: - if (performConnect(true)) { - enableButtons(); - } + performConnect(true); break; case CLIENT_REPLAY_ACTION: SessionHandler.stopReplay(userRequestMessage.getGameId()); diff --git a/Mage.Client/src/main/java/mage/client/deck/generator/DeckGeneratorDialog.java b/Mage.Client/src/main/java/mage/client/deck/generator/DeckGeneratorDialog.java index de6986a7886..d445663c0c5 100644 --- a/Mage.Client/src/main/java/mage/client/deck/generator/DeckGeneratorDialog.java +++ b/Mage.Client/src/main/java/mage/client/deck/generator/DeckGeneratorDialog.java @@ -224,7 +224,12 @@ public class DeckGeneratorDialog { dlg = optionPane.createDialog("Generating Deck"); dlg.setResizable(false); dlg.setVisible(true); - dlg.dispose(); + if (dlg.isModal()) { + // on modal - it's done here + dlg.dispose(); + } else { + // on non-modal - it's do nothing yet + } } private void enableAdvancedPanel(boolean enable) { diff --git a/Mage.Client/src/main/java/mage/client/deckeditor/CardSelector.java b/Mage.Client/src/main/java/mage/client/deckeditor/CardSelector.java index 25144c8f093..1ef48a9400e 100644 --- a/Mage.Client/src/main/java/mage/client/deckeditor/CardSelector.java +++ b/Mage.Client/src/main/java/mage/client/deckeditor/CardSelector.java @@ -1468,44 +1468,45 @@ public class CardSelector extends javax.swing.JPanel implements ComponentListene private void btnExpansionSearchActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnExpansionSearchActionPerformed // search and check multiple items - int[] oldChecks = listCodeSelected.getCheckedIndices(); + final int[] oldChecks = listCodeSelected.getCheckedIndices(); // call dialog - FastSearchUtil.showFastSearchForStringComboBox(listCodeSelected, FastSearchUtil.DEFAULT_EXPANSION_SEARCH_MESSAGE); - - int[] newChecks = listCodeSelected.getCheckedIndices(); - if (Arrays.equals(oldChecks, newChecks)) { - // no changes or cancel - return; - } - - isSetsFilterLoading = true; - try { - // delete old item - if (cbExpansionSet.getItemAt(0).startsWith(MULTI_SETS_SELECTION_TEXT)) { - cbExpansionSet.removeItemAt(0); + FastSearchUtil.showFastSearchForStringComboBox(listCodeSelected, FastSearchUtil.DEFAULT_EXPANSION_SEARCH_MESSAGE, () -> { + // data update on good choice + int[] newChecks = listCodeSelected.getCheckedIndices(); + if (Arrays.equals(oldChecks, newChecks)) { + // no changes or cancel + return; } - // set new selection - if (newChecks.length == 0) { - // all - cbExpansionSet.setSelectedIndex(0); - } else if (newChecks.length == 1) { - // one - setSetsSelection(listCodeSelected.getModel().getElementAt(newChecks[0]).toString()); - } else { - // multiple - // insert custom text - String message = String.format("%s: %d", MULTI_SETS_SELECTION_TEXT, newChecks.length); - cbExpansionSet.insertItemAt(message, 0); - cbExpansionSet.setSelectedIndex(0); - } - } finally { - isSetsFilterLoading = false; - } + isSetsFilterLoading = true; + try { + // delete old item + if (cbExpansionSet.getItemAt(0).startsWith(MULTI_SETS_SELECTION_TEXT)) { + cbExpansionSet.removeItemAt(0); + } - // update data - filterCards(); + // set new selection + if (newChecks.length == 0) { + // all + cbExpansionSet.setSelectedIndex(0); + } else if (newChecks.length == 1) { + // one + setSetsSelection(listCodeSelected.getModel().getElementAt(newChecks[0]).toString()); + } else { + // multiple + // insert custom text + String message = String.format("%s: %d", MULTI_SETS_SELECTION_TEXT, newChecks.length); + cbExpansionSet.insertItemAt(message, 0); + cbExpansionSet.setSelectedIndex(0); + } + } finally { + isSetsFilterLoading = false; + } + + // update data + filterCards(); + }); }//GEN-LAST:event_btnExpansionSearchActionPerformed private void tbCommonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_tbCommonActionPerformed diff --git a/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java b/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java index 0bf3c137244..7671604596a 100644 --- a/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java +++ b/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java @@ -19,6 +19,7 @@ import mage.client.dialog.AddLandDialog; import mage.client.dialog.PreferencesDialog; import mage.client.plugins.impl.Plugins; import mage.client.util.Event; +import mage.client.util.GUISizeHelper; import mage.client.util.Listener; import mage.client.util.audio.AudioManager; import mage.components.CardInfoPane; @@ -30,6 +31,7 @@ import mage.util.XmageThreadFactory; import mage.view.CardView; import mage.view.SimpleCardView; import org.apache.log4j.Logger; +import org.mage.card.arcane.ManaSymbols; import javax.swing.*; import javax.swing.border.Border; @@ -674,7 +676,9 @@ public class DeckEditorPanel extends javax.swing.JPanel { } private void refreshDeck() { - refreshDeck(false); + if (this.isVisible()) { // TODO: test auto-close deck with active lands dialog, e.g. on timeout + refreshDeck(false); + } } private void refreshDeck(boolean useLayout) { @@ -786,31 +790,51 @@ public class DeckEditorPanel extends javax.swing.JPanel { private void importFromClipboard(ActionEvent evt) { final DeckImportClipboardDialog dialog = new DeckImportClipboardDialog(); - dialog.showDialog(); + dialog.showDialog(tempDeckPath -> { + if (!tempDeckPath.isEmpty()) { + loadDeck(tempDeckPath, false); + } + }); - if (!dialog.getTmpPath().isEmpty()) { - loadDeck(dialog.getTmpPath(), false); + if (dialog.isModal()) { + // on modal - it's done here + dialog.dispose(); + } else { + // on non-modal - it's do nothing yet } } + private void onImportReady(String deckPath) { + SwingUtilities.invokeLater(() -> { + if (deckPath.isEmpty()) { + loadDeck(deckPath, false); + } + }); + } + private void importFromClipboardWithAppend(ActionEvent evt) { final DeckImportClipboardDialog dialog = new DeckImportClipboardDialog(); - dialog.showDialog(); - - if (!dialog.getTmpPath().isEmpty()) { - StringBuilder errorMessages = new StringBuilder(); - - MageFrame.getDesktop().setCursor(new Cursor(Cursor.WAIT_CURSOR)); - try { - Deck deckToAppend = Deck.load(DeckImporter.importDeckFromFile(dialog.getTmpPath(), errorMessages, false), true, true); - processAndShowImportErrors(errorMessages); - this.deck = Deck.append(deckToAppend, this.deck); - refreshDeck(); - } catch (GameException e1) { - JOptionPane.showMessageDialog(MageFrame.getDesktop(), e1.getMessage(), "Error loading deck", JOptionPane.ERROR_MESSAGE); - } finally { - MageFrame.getDesktop().setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + dialog.showDialog(tempDeckPath -> { + if (!tempDeckPath.isEmpty()) { + StringBuilder errorMessages = new StringBuilder(); + MageFrame.getDesktop().setCursor(new Cursor(Cursor.WAIT_CURSOR)); + try { + Deck deckToAppend = Deck.load(DeckImporter.importDeckFromFile(tempDeckPath, errorMessages, false), true, true); + processAndShowImportErrors(errorMessages); + this.deck = Deck.append(deckToAppend, this.deck); + refreshDeck(); + } catch (GameException e1) { + JOptionPane.showMessageDialog(MageFrame.getDesktop(), e1.getMessage(), "Error loading deck", JOptionPane.ERROR_MESSAGE); + } finally { + MageFrame.getDesktop().setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + } } + }); + if (dialog.isModal()) { + // on modal - it's done here + dialog.dispose(); + } else { + // on non-modal - it's do nothing yet } } @@ -1462,9 +1486,8 @@ public class DeckEditorPanel extends javax.swing.JPanel { }//GEN-LAST:event_btnExitActionPerformed private void btnAddLandActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnAddLandActionPerformed - AddLandDialog addLand = new AddLandDialog(); - addLand.showDialog(deck, mode); - refreshDeck(); + AddLandDialog dialog = new AddLandDialog(); + dialog.showDialog(deck, mode, this::refreshDeck); }//GEN-LAST:event_btnAddLandActionPerformed private void btnGenDeckActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnGenDeckActionPerformed diff --git a/Mage.Client/src/main/java/mage/client/deckeditor/DeckExportClipboardDialog.java b/Mage.Client/src/main/java/mage/client/deckeditor/DeckExportClipboardDialog.java index 3a4fa5dff82..204ca982bbe 100644 --- a/Mage.Client/src/main/java/mage/client/deckeditor/DeckExportClipboardDialog.java +++ b/Mage.Client/src/main/java/mage/client/deckeditor/DeckExportClipboardDialog.java @@ -48,11 +48,7 @@ public class DeckExportClipboardDialog extends MageDialog { // windows settings MageFrame.getDesktop().remove(this); - if (this.isModal()) { - MageFrame.getDesktop().add(this, JLayeredPane.MODAL_LAYER); - } else { - MageFrame.getDesktop().add(this, JLayeredPane.PALETTE_LAYER); - } + MageFrame.getDesktop().add(this, this.isModal() ? JLayeredPane.MODAL_LAYER : JLayeredPane.PALETTE_LAYER); this.makeWindowCentered(); // Close on "ESC" diff --git a/Mage.Client/src/main/java/mage/client/deckeditor/DeckImportClipboardDialog.java b/Mage.Client/src/main/java/mage/client/deckeditor/DeckImportClipboardDialog.java index ccf56809cb9..f08bdbd4366 100644 --- a/Mage.Client/src/main/java/mage/client/deckeditor/DeckImportClipboardDialog.java +++ b/Mage.Client/src/main/java/mage/client/deckeditor/DeckImportClipboardDialog.java @@ -29,14 +29,18 @@ public class DeckImportClipboardDialog extends MageDialog { "// Your current clipboard:\n" + "\n"; - private String tmpPath; + private DeckImportClipboardCallback callback = null; public DeckImportClipboardDialog() { initComponents(); } - public void showDialog() { - this.tmpPath = ""; + public interface DeckImportClipboardCallback { + void onImportDone(String tempDeckPath); + } + + public void showDialog(DeckImportClipboardCallback callback) { + this.callback = callback; onRefreshClipboard(); this.setModal(true); @@ -45,11 +49,7 @@ public class DeckImportClipboardDialog extends MageDialog { // windows settings MageFrame.getDesktop().remove(this); - if (this.isModal()) { - MageFrame.getDesktop().add(this, JLayeredPane.MODAL_LAYER); - } else { - MageFrame.getDesktop().add(this, JLayeredPane.PALETTE_LAYER); - } + MageFrame.getDesktop().add(this, this.isModal() ? JLayeredPane.MODAL_LAYER : JLayeredPane.PALETTE_LAYER); this.makeWindowCentered(); // Close on "ESC" @@ -70,17 +70,24 @@ public class DeckImportClipboardDialog extends MageDialog { private void onOK() { String decklist = editData.getText(); decklist = decklist.replace(FORMAT_TEXT, ""); + + String tempDeckPath; // This dialog also accepts a paste in .mtga format if (decklist.startsWith("Deck\n")) { // An .mtga list always starts with the first line being "Deck". This kind of paste is processed as .mtga - tmpPath = DeckUtil.writeTextToTempFile("cbimportdeck", ".mtga", decklist); - } else { // If the paste is not .mtga format, it's processed as plaintext - tmpPath = DeckUtil.writeTextToTempFile(decklist); + tempDeckPath = DeckUtil.writeTextToTempFile("cbimportdeck", ".mtga", decklist); + } else { + // If the paste is not .mtga format, it's processed as plaintext + tempDeckPath = DeckUtil.writeTextToTempFile(decklist); } - this.removeDialog(); + if (this.callback != null) { + callback.onImportDone(tempDeckPath); + } + + onCancel(); } private void onCancel() { - this.removeDialog(); + this.removeDialog(); // TODO: combine hideDialog and removeDialog logic for all usages in all dialogs } private void onRefreshClipboard() { @@ -88,10 +95,6 @@ public class DeckImportClipboardDialog extends MageDialog { editData.setCaretPosition(FORMAT_TEXT.length()); } - public String getTmpPath() { - return tmpPath; - } - /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always diff --git a/Mage.Client/src/main/java/mage/client/dialog/AboutDialog.java b/Mage.Client/src/main/java/mage/client/dialog/AboutDialog.java index 4e1ac407315..b3ef0201f5d 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/AboutDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/AboutDialog.java @@ -20,7 +20,6 @@ public class AboutDialog extends MageDialog { public AboutDialog() { initComponents(); - this.modal = false; panelDevs.setText(devsList + " and hundreds of other developers from https://github.com/magefree/mage/graphs/contributors"); } @@ -30,11 +29,7 @@ public class AboutDialog extends MageDialog { // windows settings MageFrame.getDesktop().remove(this); - if (this.isModal()) { - MageFrame.getDesktop().add(this, JLayeredPane.MODAL_LAYER); - } else { - MageFrame.getDesktop().add(this, JLayeredPane.PALETTE_LAYER); - } + MageFrame.getDesktop().add(this, this.isModal() ? JLayeredPane.MODAL_LAYER : JLayeredPane.PALETTE_LAYER); this.makeWindowCentered(); // Close on "ESC" diff --git a/Mage.Client/src/main/java/mage/client/dialog/AddLandDialog.java b/Mage.Client/src/main/java/mage/client/dialog/AddLandDialog.java index 32f7e2f49e4..00ce3e7af75 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/AddLandDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/AddLandDialog.java @@ -23,15 +23,15 @@ import java.util.TreeSet; /** * App GUI: adding new lands to the deck, uses in deck editor and drafting * - * @author BetaSteward_at_googlemail.com + * @author BetaSteward_at_googlemail.com, JayDi85 */ public class AddLandDialog extends MageDialog { private static final Logger logger = Logger.getLogger(MageDialog.class); private Deck deck; - private DeckEditorMode mode; + private AddLandCallback callback = null; private static final int DEFAULT_SEALED_DECK_CARD_NUMBER = 40; @@ -40,9 +40,14 @@ public class AddLandDialog extends MageDialog { this.setModal(true); } - public void showDialog(Deck deck, DeckEditorMode mode) { + public interface AddLandCallback { + void onLandsAdded(); + } + + public void showDialog(Deck deck, DeckEditorMode mode, AddLandCallback callback) { this.deck = deck; this.mode = mode; + this.callback = callback; SortedSet landSetNames = new TreeSet<>(); String defaultSetName = null; if (mode != DeckEditorMode.FREE_BUILDING) { @@ -126,11 +131,7 @@ public class AddLandDialog extends MageDialog { // windows settings MageFrame.getDesktop().remove(this); - if (this.isModal()) { - MageFrame.getDesktop().add(this, JLayeredPane.MODAL_LAYER); - } else { - MageFrame.getDesktop().add(this, JLayeredPane.PALETTE_LAYER); - } + MageFrame.getDesktop().add(this, this.isModal() ? JLayeredPane.MODAL_LAYER : JLayeredPane.PALETTE_LAYER); this.makeWindowCentered(); // Close on "ESC" @@ -214,7 +215,11 @@ public class AddLandDialog extends MageDialog { addLands("Plains", nPlains, useFullArt); addLands("Swamp", nSwamp, useFullArt); - this.removeDialog(); + if (this.callback != null) { + callback.onLandsAdded(); + } + + onCancel(); } /** diff --git a/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.java b/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.java index dece061fa10..3d10a77241e 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.java @@ -14,6 +14,7 @@ import org.apache.log4j.Logger; import javax.swing.*; import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; import java.io.*; import java.net.*; import java.util.List; @@ -28,21 +29,20 @@ import static mage.client.dialog.PreferencesDialog.*; /** * App GUI: connection windows * - * @author BetaSteward_at_googlemail.com + * @author BetaSteward_at_googlemail.com, JayDi85 */ public class ConnectDialog extends MageDialog { private static final Logger logger = Logger.getLogger(ConnectDialog.class); + private Connection connection; private ConnectTask task; private final RegisterUserDialog registerUserDialog; private final ResetPasswordDialog resetPasswordDialog; + ConnectCallback callback = null; private final ActionListener connectAction = evt -> btnConnectActionPerformed(evt); - /** - * Creates new form ConnectDialog - */ public ConnectDialog() { initComponents(); @@ -51,14 +51,18 @@ public class ConnectDialog extends MageDialog { this.txtUserName.addActionListener(connectAction); this.txtPassword.addActionListener(connectAction); - registerUserDialog = new RegisterUserDialog(this); - MageFrame.getDesktop().add(registerUserDialog, JLayeredPane.MODAL_LAYER); + registerUserDialog = new RegisterUserDialog(); + MageFrame.getDesktop().add(registerUserDialog, registerUserDialog.isModal() ? JLayeredPane.MODAL_LAYER : JLayeredPane.PALETTE_LAYER); - resetPasswordDialog = new ResetPasswordDialog(this); - MageFrame.getDesktop().add(resetPasswordDialog, JLayeredPane.MODAL_LAYER); + resetPasswordDialog = new ResetPasswordDialog(); + MageFrame.getDesktop().add(resetPasswordDialog, resetPasswordDialog.isModal() ? JLayeredPane.MODAL_LAYER : JLayeredPane.PALETTE_LAYER); } - public void showDialog() { + public interface ConnectCallback { + void onConnectClosed(); + } + + public void showDialog(ConnectCallback callback) { this.lblStatus.setText(""); String serverAddress = MagePreferences.getServerAddressWithDefault(ClientDefaultSettings.serverName); this.txtServer.setText(serverAddress); @@ -77,10 +81,32 @@ public class ConnectDialog extends MageDialog { } } this.setModal(true); - this.setLocation(50, 50); + + // windows settings + MageFrame.getDesktop().remove(this); + MageFrame.getDesktop().add(this, this.isModal() ? JLayeredPane.MODAL_LAYER : JLayeredPane.PALETTE_LAYER); + //this.makeWindowCentered(); + this.setLocation(50, 50); // make sure it will be visible in any sizes + + // Close on "ESC" + registerKeyboardAction(e -> onCancel(), KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + this.setVisible(true); } + private void onCancel() { + MageFrame.getPreferences().put("autoConnect", Boolean.toString(chkAutoConnect.isSelected())); + MageFrame.getPreferences().put(KEY_CONNECT_FLAG, ((CountryItemEditor) cbFlag.getEditor()).getImageItem()); + if (task != null && !task.isDone()) { + task.cancel(true); + } else { + this.hideDialog(); + if (callback != null) { + callback.onConnectClosed(); + } + } + } + private void saveSettings() { String serverAddress = txtServer.getText().trim(); MagePreferences.setServerAddress(serverAddress); @@ -535,13 +561,7 @@ public class ConnectDialog extends MageDialog { }// //GEN-END:initComponents private void btnCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCancelActionPerformed - MageFrame.getPreferences().put("autoConnect", Boolean.toString(chkAutoConnect.isSelected())); - MageFrame.getPreferences().put(KEY_CONNECT_FLAG, ((CountryItemEditor) cbFlag.getEditor()).getImageItem()); - if (task != null && !task.isDone()) { - task.cancel(true); - } else { - this.hideDialog(); - } + onCancel(); }//GEN-LAST:event_btnCancelActionPerformed private void btnConnectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnConnectActionPerformed @@ -658,6 +678,9 @@ public class ConnectDialog extends MageDialog { private void doAfterConnected() { this.saveSettings(); this.hideDialog(); + if (this.callback != null) { + this.callback.onConnectClosed(); + } } private void keyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_keyTyped @@ -689,11 +712,11 @@ public class ConnectDialog extends MageDialog { }//GEN-LAST:event_txtPasswordActionPerformed private void btnRegisterActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRegisterActionPerformed - registerUserDialog.showDialog(); + registerUserDialog.showDialog(this.getServer(), this.getPort()); }//GEN-LAST:event_btnRegisterActionPerformed private void btnForgotPasswordActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnForgotPasswordActionPerformed - resetPasswordDialog.showDialog(); + resetPasswordDialog.showDialog(this.getServer(), this.getPort()); }//GEN-LAST:event_btnForgotPasswordActionPerformed private void connectXmageDe(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnFind1findPublicServerActionPerformed @@ -795,13 +818,14 @@ public class ConnectDialog extends MageDialog { // ask for new value PickChoiceDialog dlg = new PickChoiceDialog(); dlg.setWindowSize(300, 500); - dlg.showDialog(choice, needSelectValue); - if (choice.isChosen()) { - flagItem = new String[2]; - flagItem[0] = choice.getChoiceValue(); - flagItem[1] = choice.getChoiceKey(); - flagModel.setSelectedItem(flagItem); - } + dlg.showDialog(choice, needSelectValue, () -> { + if (choice.isChosen()) { + String[] flag = new String[2]; + flag[0] = choice.getChoiceValue(); + flag[1] = choice.getChoiceKey(); + flagModel.setSelectedItem(flag); + } + }); } public String getServer() { diff --git a/Mage.Client/src/main/java/mage/client/dialog/DownloadImagesDialog.java b/Mage.Client/src/main/java/mage/client/dialog/DownloadImagesDialog.java index a9cf41d1792..d0ca1c614bc 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/DownloadImagesDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/DownloadImagesDialog.java @@ -12,23 +12,17 @@ import java.util.HashMap; import java.util.Map; /** - * App GUI: download card images window + * App GUI: control dialog for card images downloader service * * @author JayDi85 */ public class DownloadImagesDialog extends MageDialog { - public static final int RET_CANCEL = 0; - public static final int RET_OK = 1; - private final Dimension sizeModeMessageOnly; private final Dimension sizeModeMessageAndControls; private final Map actionsControlStates = new HashMap<>(); + private DownloadImagesCallback callback = null; - - /** - * Creates new form DownloadImagesDialog - */ public DownloadImagesDialog() { initComponents(); this.setModal(true); @@ -51,7 +45,7 @@ public class DownloadImagesDialog extends MageDialog { ActionMap actionMap = getRootPane().getActionMap(); actionMap.put(cancelName, new AbstractAction() { public void actionPerformed(ActionEvent e) { - doClose(RET_CANCEL); + onCancel(); } }); } @@ -60,28 +54,27 @@ public class DownloadImagesDialog extends MageDialog { this.setSize(new Dimension(width, heigth)); } - public void showDialog() { - showDialog(null); + public interface DownloadImagesCallback { + void onDownloadDone(); } - public void showDialog(MageDialogState mageDialogState) { - + public void showDialog(DownloadImagesCallback callback) { // window settings + this.callback = callback; MageFrame.getDesktop().remove(this); - if (this.isModal()) { - MageFrame.getDesktop().add(this, JLayeredPane.MODAL_LAYER); - } else { - MageFrame.getDesktop().add(this, JLayeredPane.PALETTE_LAYER); - } - if (mageDialogState != null) mageDialogState.setStateToDialog(this); - else this.makeWindowCentered(); - - showDownloadControls(false); // call to change window size + MageFrame.getDesktop().add(this, this.isModal() ? JLayeredPane.MODAL_LAYER : JLayeredPane.PALETTE_LAYER); + showDownloadControls(false); // call to change window size and view mode this.setVisible(true); } public void setGlobalInfo(String info) { + // workaround to keep auto-sizeable and centered text + Dimension newSize = new Dimension(Integer.MAX_VALUE, this.labelGlobal.getPreferredSize().height); + this.labelGlobal.setPreferredSize(newSize); + this.labelGlobal.setMaximumSize(newSize); + this.labelGlobal.setHorizontalAlignment(SwingConstants.CENTER); + this.labelGlobal.setText(info); } @@ -188,13 +181,8 @@ public class DownloadImagesDialog extends MageDialog { // TODO: add manual mode as tab this.tabsList.getTabComponentAt(1).setEnabled(false); this.tabsList.setEnabledAt(1, false); - } - /** - * @return the return status of this dialog - one of RET_OK or RET_CANCEL - */ - public int getReturnStatus() { - return returnStatus; + this.invalidate(); } /** @@ -432,7 +420,7 @@ public class DownloadImagesDialog extends MageDialog { * Closes the dialog */ private void closeDialog(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_closeDialog - doClose(RET_CANCEL); + onCancel(); }//GEN-LAST:event_closeDialog private void buttonSearchSetActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonSearchSetActionPerformed @@ -440,14 +428,15 @@ public class DownloadImagesDialog extends MageDialog { }//GEN-LAST:event_buttonSearchSetActionPerformed private void buttonStopActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonStopActionPerformed - // TODO add your handling code here: + // TODO implement stop feature for cancel button }//GEN-LAST:event_buttonStopActionPerformed - private void doClose(int retStatus) { - - returnStatus = retStatus; - setVisible(false); - dispose(); + private void onCancel() { + // it's only control GUI, all works in download service + hideDialog(); + if (this.callback != null) { + this.callback.onDownloadDone(); + } } // Variables declaration - do not modify//GEN-BEGIN:variables @@ -493,6 +482,4 @@ public class DownloadImagesDialog extends MageDialog { private javax.swing.JPanel tabMain; private javax.swing.JTabbedPane tabsList; // End of variables declaration//GEN-END:variables - - private int returnStatus = RET_CANCEL; } diff --git a/Mage.Client/src/main/java/mage/client/dialog/ErrorDialog.java b/Mage.Client/src/main/java/mage/client/dialog/ErrorDialog.java index 80952993e75..f589ea9a890 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/ErrorDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/ErrorDialog.java @@ -7,6 +7,7 @@ import mage.util.CardUtil; /** * GUI: error dialog with copyable error message + * // TODO: add game logs and data for game errors (client side info from GameView) * * @author JayDi85 */ diff --git a/Mage.Client/src/main/java/mage/client/dialog/FeedbackDialog.java b/Mage.Client/src/main/java/mage/client/dialog/FeedbackDialog.java index d014e6d6fd2..88eb49e45a7 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/FeedbackDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/FeedbackDialog.java @@ -194,7 +194,6 @@ public class FeedbackDialog extends javax.swing.JDialog { }// //GEN-END:initComponents private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed - dialog.setVisible(false); dialog.dispose(); }//GEN-LAST:event_cancelButtonActionPerformed diff --git a/Mage.Client/src/main/java/mage/client/dialog/GameEndDialog.java b/Mage.Client/src/main/java/mage/client/dialog/GameEndDialog.java index b356879e123..30f8cdf5cc7 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/GameEndDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/GameEndDialog.java @@ -33,7 +33,7 @@ */ public GameEndDialog(GameEndView gameEndView) { initComponents(); - this.modal = true; + setModal(true); pnlText.setOpaque(true); pnlText.setBackground(new Color(240, 240, 240, 140)); diff --git a/Mage.Client/src/main/java/mage/client/dialog/JoinTableDialog.java b/Mage.Client/src/main/java/mage/client/dialog/JoinTableDialog.java index 1f305c233e4..f5725dc588a 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/JoinTableDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/JoinTableDialog.java @@ -11,7 +11,7 @@ import javax.swing.*; import java.util.UUID; /** - * App GUI: join to the new game window + * App GUI: join to table (client side dialog to choose deck and enter pass) * * @author BetaSteward_at_googlemail.com */ @@ -120,6 +120,7 @@ public class JoinTableDialog extends MageDialog { private void btnOKActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnOKActionPerformed Session session = SessionHandler.getSession(); try { + // remember pass for next joins PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_PASSWORD_JOIN, txtPassword.getText()); if (isTournament) { joined = session.joinTournamentTable(roomId, tableId, this.newPlayerPanel.getPlayerName(), PlayerType.HUMAN, 1, DeckImporter.importDeckFromFile(this.newPlayerPanel.getDeckFile(), true), this.txtPassword.getText()); diff --git a/Mage.Client/src/main/java/mage/client/dialog/MageDialog.java b/Mage.Client/src/main/java/mage/client/dialog/MageDialog.java index c5d9b9a5fb6..5ce46cc10a3 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/MageDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/MageDialog.java @@ -16,13 +16,22 @@ import java.beans.PropertyVetoException; import java.lang.reflect.InvocationTargetException; /** + * GUI: basic class for all dialogs + *

+ * WARNING, make sure you don't wait results after showXXX call -- use callback function instead + *

+ * TODO: research and make sure all dialogs can be called one time and clean on main form close + * bad example: deck editor can call multiple PickCheckBoxDialog instances (not critical) + * TODO: migrate all JInternalFrame and other dialogs to MageDialog and support non modal + * TODO: must add clean code on doClose for all dialogs? See PickPileDialog for example (cleanUp, removeDialog) + * * @author BetaSteward_at_googlemail.com, JayDi85 */ public class MageDialog extends javax.swing.JInternalFrame { private static final Logger LOGGER = Logger.getLogger(MageDialog.class); - protected boolean modal = false; + private boolean modal = false; // warning, app can work in non-modal mode, so make sure result processing on callback // GUI performance and bugs issues: // TODO: swing components should override paintComponent() instead paint() @@ -232,7 +241,7 @@ public class MageDialog extends javax.swing.JInternalFrame { } public void setModal(boolean modal) { - this.modal = modal; + this.modal = MageFrame.isGuiModalModeEnabled() && modal; } public boolean isModal() { diff --git a/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.java b/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.java index 2a6427c4882..614c785fd3c 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.java @@ -35,7 +35,7 @@ public class NewTableDialog extends MageDialog { private static final Logger logger = Logger.getLogger(NewTableDialog.class); - private CustomOptionsDialog customOptions; + private final CustomOptionsDialog customOptions; private TableView table; private UUID playerId; private UUID roomId; @@ -45,14 +45,11 @@ public class NewTableDialog extends MageDialog { private static final String LIMITED = "Limited"; - /** - * Creates new form NewTableDialog - */ public NewTableDialog() { lastSessionId = ""; initComponents(); this.customOptions = new CustomOptionsDialog(CustomOptionsDialog.SaveLoadKeys.TABLE, btnCustomOptions); - MageFrame.getDesktop().add(customOptions, JLayeredPane.MODAL_LAYER); + MageFrame.getDesktop().add(customOptions, customOptions.isModal() ? JLayeredPane.MODAL_LAYER : JLayeredPane.PALETTE_LAYER); player1Panel.showLevel(false); this.spnNumWins.setModel(new SpinnerNumberModel(1, 1, 5, 1)); this.spnQuitRatio.setModel(new SpinnerNumberModel(100, 0, 100, 5)); @@ -480,12 +477,19 @@ public class NewTableDialog extends MageDialog { private void btnCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCancelActionPerformed this.table = null; this.playerId = null; - this.hideDialog(); + doClose(); }//GEN-LAST:event_btnCancelActionPerformed private void btnPreviousConfigurationActionPerformed(java.awt.event.ActionEvent evt, int i) {//GEN-FIRST:event_btnPreviousConfigurationActionPerformed }//GEN-LAST:event_btnPreviousConfigurationActionPerformed + private void doClose() { + if (this.customOptions.isVisible()) { + this.customOptions.hideDialog(); + } + this.hideDialog(); + } + private void btnOKActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnOKActionPerformed MatchOptions options = getMatchOptions(); @@ -524,7 +528,7 @@ public class NewTableDialog extends MageDialog { DeckImporter.importDeckFromFile(this.player1Panel.getDeckFile(), true), this.txtPassword.getText())) { // all fine, can close create dialog (join dialog will be opened after feedback from server) - this.hideDialog(); + doClose(); return; } } catch (ClassNotFoundException | IOException ex) { diff --git a/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java b/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java index 394d92b6bdf..d45700ec42b 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java @@ -44,7 +44,7 @@ public class NewTournamentDialog extends MageDialog { private UUID roomId; private String lastSessionId; private RandomPacksSelectorDialog randomPackSelector; - private CustomOptionsDialog customOptions; + private final CustomOptionsDialog customOptions; private JTextArea txtRandomPacks; private final java.util.List players = new ArrayList<>(); private final java.util.List packPanels = new ArrayList<>(); @@ -60,7 +60,7 @@ public class NewTournamentDialog extends MageDialog { public NewTournamentDialog() { initComponents(); this.customOptions = new CustomOptionsDialog(CustomOptionsDialog.SaveLoadKeys.TOURNEY, btnCustomOptions); - MageFrame.getDesktop().add(customOptions, JLayeredPane.MODAL_LAYER); + MageFrame.getDesktop().add(customOptions, customOptions.isModal() ? JLayeredPane.MODAL_LAYER : JLayeredPane.PALETTE_LAYER); lastSessionId = ""; txtName.setText("Tournament"); this.spnNumWins.setModel(new SpinnerNumberModel(2, 1, 5, 1)); @@ -657,6 +657,13 @@ public class NewTournamentDialog extends MageDialog { }//GEN-LAST:event_cbTournamentTypeActionPerformed + private void doClose() { + if (this.customOptions.isVisible()) { + this.customOptions.hideDialog(); + } + this.hideDialog(); + } + private void btnOkActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnOkActionPerformed // get settings @@ -714,7 +721,7 @@ public class NewTournamentDialog extends MageDialog { DeckImporter.importDeckFromFile(this.player1Panel.getDeckFile(), true), tOptions.getPassword())) { // all fine, can close create dialog (join dialog will be opened after feedback from server) - this.hideDialog(); + doClose(); return; } @@ -726,7 +733,7 @@ public class NewTournamentDialog extends MageDialog { private void btnCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCancelActionPerformed this.table = null; // this.playerId = null; - this.hideDialog(); + doClose(); }//GEN-LAST:event_btnCancelActionPerformed private void updateNumSeats() { diff --git a/Mage.Client/src/main/java/mage/client/dialog/PickCheckBoxDialog.java b/Mage.Client/src/main/java/mage/client/dialog/PickCheckBoxDialog.java index 34e7dada7ad..c7b4074e5a5 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/PickCheckBoxDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/PickCheckBoxDialog.java @@ -28,41 +28,30 @@ public class PickCheckBoxDialog extends MageDialog { CheckBoxList tList; int[] startingCheckboxes; // restore to it on cancel + PickCheckBoxCallback callback = null; final private static String HTML_TEMPLATE = "

%s
"; - private void setFocus(CheckBoxList obj) { - - if (!(obj instanceof java.awt.Component)) { - throw new IllegalArgumentException("Must be a java.awt.Component!"); - } - this.scrollList.setViewportView(obj); + public interface PickCheckBoxCallback { + void onChoiceDone(); } - private javax.swing.JList get_a_Jlist_from_ScrollListView() { - return ((javax.swing.JList) this.scrollList.getViewport().getView()); + public void showDialog(Choice choice, PickCheckBoxCallback callback) { + showDialog(choice, null, null, null, callback); } - private void restoreData(Object dataFrom) { - this.allItems.forEach((item) -> { - ((CheckBoxList.CheckBoxListModel) dataFrom).addElement(item.getObjectValue()); - }); + public void showDialog(Choice choice, String startSelectionValue, PickCheckBoxCallback callback) { + showDialog(choice, null, null, startSelectionValue, callback); } - public void showDialog(Choice choice) { - showDialog(choice, null, null, null); + public void showDialog(Choice choice, UUID objectId, MageDialogState mageDialogState, PickCheckBoxCallback callback) { + showDialog(choice, objectId, mageDialogState, null, callback); } - public void showDialog(Choice choice, String startSelectionValue) { - showDialog(choice, null, null, startSelectionValue); - } - - public void showDialog(Choice choice, UUID objectId, MageDialogState mageDialogState) { - showDialog(choice, objectId, mageDialogState, null); - } - - public void showDialog(Choice choice, UUID objectId, MageDialogState mageDialogState, String startSelectionValue) { + public void showDialog(Choice choice, UUID objectId, MageDialogState mageDialogState, String startSelectionValue, PickCheckBoxCallback callback) { this.choice = choice; + this.callback = callback; + KeyValueItem tempKeyValue; int indexInTList; @@ -186,11 +175,7 @@ public class PickCheckBoxDialog extends MageDialog { // window settings MageFrame.getDesktop().remove(this); - if (this.isModal()) { - MageFrame.getDesktop().add(this, JLayeredPane.MODAL_LAYER); - } else { - MageFrame.getDesktop().add(this, JLayeredPane.PALETTE_LAYER); - } + MageFrame.getDesktop().add(this, this.isModal() ? JLayeredPane.MODAL_LAYER : JLayeredPane.PALETTE_LAYER); if (mageDialogState != null) mageDialogState.setStateToDialog(this); else this.makeWindowCentered(); @@ -223,6 +208,23 @@ public class PickCheckBoxDialog extends MageDialog { this.setVisible(true); } + private void setFocus(CheckBoxList obj) { + if (!(obj instanceof java.awt.Component)) { + throw new IllegalArgumentException("Must be a java.awt.Component!"); + } + this.scrollList.setViewportView(obj); + } + + private javax.swing.JList get_a_Jlist_from_ScrollListView() { + return ((javax.swing.JList) this.scrollList.getViewport().getView()); + } + + private void restoreData(Object dataFrom) { + this.allItems.forEach((item) -> { + ((CheckBoxList.CheckBoxListModel) dataFrom).addElement(item.getObjectValue()); + }); + } + public void setWindowSize(int width, int heigth) { this.setSize(new Dimension(width, heigth)); } @@ -276,7 +278,7 @@ public class PickCheckBoxDialog extends MageDialog { if ((tList != null) || (setChoice())) { this.m_dataModel.clear(); restoreData(this.m_dataModel); - this.hideDialog(); + doClose(); } } @@ -289,14 +291,16 @@ public class PickCheckBoxDialog extends MageDialog { this.listChoices.clearSelection(); this.choice.clearChoice(); - hideDialog(); + doClose(); + } + + private void doClose() { + this.hideDialog(); + if (this.callback != null) { + this.callback.onChoiceDone(); + } } - /** - * Creates new form PickChoiceDialog - * - * @param list - */ public PickCheckBoxDialog(CheckBoxList list) { initComponents(); tList = list; diff --git a/Mage.Client/src/main/java/mage/client/dialog/PickChoiceDialog.java b/Mage.Client/src/main/java/mage/client/dialog/PickChoiceDialog.java index 01b20e2c1f6..8090d65da04 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/PickChoiceDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/PickChoiceDialog.java @@ -40,6 +40,7 @@ public class PickChoiceDialog extends MageDialog { java.util.List allItems = new ArrayList<>(); KeyValueItem biggestItem = null; // for render optimization + PickChoiceCallback callback = null; final private static String HTML_HEADERS_TEMPLATE = "
%s
"; @@ -58,14 +59,19 @@ public class PickChoiceDialog extends MageDialog { this.setModal(true); } - public void showDialog(Choice choice, String startSelectionValue) { - showDialog(choice, startSelectionValue, null, null, null); + public interface PickChoiceCallback { + void onChoiceDone(); } - public void showDialog(Choice choice, String startSelectionValue, UUID objectId, MageDialogState mageDialogState, BigCard bigCard) { + public void showDialog(Choice choice, String startSelectionValue, PickChoiceCallback callback) { + showDialog(choice, startSelectionValue, null, null, null, callback); + } + + public void showDialog(Choice choice, String startSelectionValue, UUID objectId, MageDialogState mageDialogState, BigCard bigCard, PickChoiceCallback callback) { this.choice = choice; this.bigCard = bigCard; this.gameId = objectId; + this.callback = callback; changeGUISize(); @@ -244,11 +250,7 @@ public class PickChoiceDialog extends MageDialog { // window settings MageFrame.getDesktop().remove(this); - if (this.isModal()) { - MageFrame.getDesktop().add(this, JLayeredPane.MODAL_LAYER); - } else { - MageFrame.getDesktop().add(this, JLayeredPane.PALETTE_LAYER); - } + MageFrame.getDesktop().add(this, this.isModal() ? JLayeredPane.MODAL_LAYER : JLayeredPane.PALETTE_LAYER); if (mageDialogState != null) { mageDialogState.setStateToDialog(this); } else { @@ -421,14 +423,21 @@ public class PickChoiceDialog extends MageDialog { private void doChoose() { if (setChoice()) { - this.hideDialog(); + doClose(); } } private void doCancel() { this.listChoices.clearSelection(); this.choice.clearChoice(); - hideDialog(); + doClose(); + } + + private void doClose() { + this.hideDialog(); + if (this.callback != null) { + this.callback.onChoiceDone(); + } } public boolean setChoice() { diff --git a/Mage.Client/src/main/java/mage/client/dialog/PickMultiNumberDialog.java b/Mage.Client/src/main/java/mage/client/dialog/PickMultiNumberDialog.java index 27a0052a81a..eebdcf24d9c 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/PickMultiNumberDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/PickMultiNumberDialog.java @@ -14,12 +14,15 @@ import java.util.Map; import java.util.stream.Collectors; /** + * Game GUI: dialog to distribute values between multiple items + * (used for some cards and add lands in cheat menu, search by MultiAmountMessage) * * @author weirddan455 */ public class PickMultiNumberDialog extends MageDialog { private boolean cancel; + private PickMultiNumberCallback callback = null; private List labelList = null; private List spinnerList = null; @@ -29,7 +32,14 @@ public class PickMultiNumberDialog extends MageDialog { this.setModal(true); } - public void showDialog(List messages, int min, int max, Map options) { + public interface PickMultiNumberCallback { + void onChoiceDone(); + } + + public void showDialog(List messages, int min, int max, Map options, PickMultiNumberCallback callback) { + this.cancel = false; + this.callback = callback; + this.header.setText("" + ManaSymbols.replaceSymbolsWithHTML((String) options.get("header"), ManaSymbols.Type.DIALOG)); this.setTitle((String) options.get("title")); @@ -142,6 +152,13 @@ public class PickMultiNumberDialog extends MageDialog { return cancel; } + private void doClose() { + this.hideDialog(); + if (this.callback != null) { + this.callback.onChoiceDone(); + } + } + /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always @@ -231,12 +248,12 @@ public class PickMultiNumberDialog extends MageDialog { private void btnOkActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnOkActionPerformed this.cancel = false; - this.hideDialog(); + doClose(); }//GEN-LAST:event_btnOkActionPerformed private void btnCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCancelActionPerformed this.cancel = true; - this.hideDialog(); + doClose(); }//GEN-LAST:event_btnCancelActionPerformed diff --git a/Mage.Client/src/main/java/mage/client/dialog/PickNumberDialog.java b/Mage.Client/src/main/java/mage/client/dialog/PickNumberDialog.java index 0ee154c667d..cd3baf43746 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/PickNumberDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/PickNumberDialog.java @@ -9,13 +9,14 @@ import java.util.ArrayList; import java.util.List; /** - * Game GUI: choose number + * Game GUI: choose number dialog * * @author BetaSteward_at_googlemail.com, JayDi85 */ public class PickNumberDialog extends MageDialog { private boolean cancel; + private PickNumberCallback callback = null; public PickNumberDialog() { initComponents(); @@ -24,10 +25,15 @@ public class PickNumberDialog extends MageDialog { this.setModal(true); } - public void showDialog(int min, int max, String message) { + public interface PickNumberCallback { + void onChoiceDone(); + } + + public void showDialog(int min, int max, String message, PickNumberCallback callback) { this.editAmount.setModel(new SpinnerNumberModel(min, min, max, 1)); this.textMessage.setContentType("text/html"); this.textMessage.setText(message); + this.callback = callback; List limits = new ArrayList<>(); if (min != Integer.MIN_VALUE) { @@ -42,11 +48,7 @@ public class PickNumberDialog extends MageDialog { // window settings MageFrame.getDesktop().remove(this); - if (this.isModal()) { - MageFrame.getDesktop().add(this, JLayeredPane.MODAL_LAYER); - } else { - MageFrame.getDesktop().add(this, JLayeredPane.PALETTE_LAYER); - } + MageFrame.getDesktop().add(this, this.isModal() ? JLayeredPane.MODAL_LAYER : JLayeredPane.PALETTE_LAYER); this.getRootPane().setDefaultButton(this.buttonOk); // restore default button after root panel change (no need actually) @@ -73,7 +75,7 @@ public class PickNumberDialog extends MageDialog { this.makeWindowCentered(); - // TODO: need to fix focus restore on second popup (it's not focues, test on Manamorphose) + // TODO: need to fix focus restore on second popup (it's not get focus, test on Manamorphose) this.setVisible(true); } @@ -85,6 +87,13 @@ public class PickNumberDialog extends MageDialog { return cancel; } + private void doClose() { + this.hideDialog(); + if (this.callback != null) { + this.callback.onChoiceDone(); + } + } + /** * This method is called from within the constructor to * initialize the form. @@ -188,12 +197,12 @@ public class PickNumberDialog extends MageDialog { private void buttonOkActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonOkActionPerformed this.cancel = false; - this.hideDialog(); + doClose(); }//GEN-LAST:event_buttonOkActionPerformed private void buttonCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonCancelActionPerformed this.cancel = true; - this.hideDialog(); + doClose(); }//GEN-LAST:event_buttonCancelActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables diff --git a/Mage.Client/src/main/java/mage/client/dialog/PickPileDialog.java b/Mage.Client/src/main/java/mage/client/dialog/PickPileDialog.java index 4fc66f65e26..a4c822eb8d1 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/PickPileDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/PickPileDialog.java @@ -5,14 +5,13 @@ import mage.client.MageFrame; import mage.client.cards.BigCard; import mage.client.cards.CardArea; import mage.view.CardsView; -import org.mage.card.arcane.CardPanel; import javax.swing.*; import java.awt.*; import java.util.UUID; /** - * Game GUI: pile choosing (select a 1 pile from a 2 piles) + * Game GUI: pile choose dialog (one from two) * * @author BetaSteward_at_googlemail.com, JayDi85 */ @@ -23,10 +22,8 @@ public class PickPileDialog extends MageDialog { private boolean pickedPile1 = false; private boolean pickedOK = false; + private PickPileCallback callback = null; - /** - * Create the frame. - */ public PickPileDialog() { getContentPane().setLayout(new BorderLayout(0, 0)); @@ -53,6 +50,29 @@ public class PickPileDialog extends MageDialog { panel_1.add(btnChoosePile2, BorderLayout.NORTH); } + public interface PickPileCallback { + void onChoiceDone(); + } + + public void showDialog(String name, CardsView pile1, CardsView pile2, BigCard bigCard, UUID gameId, PickPileCallback callback) { + this.pickedOK = false; + this.pickedPile1 = false; + this.title = name; + this.pile1.loadCardsNarrow(pile1, bigCard, gameId); + this.pile2.loadCardsNarrow(pile2, bigCard, gameId); + this.callback = callback; + + this.setModal(true); + pack(); + + // windows settings + MageFrame.getDesktop().remove(this); + MageFrame.getDesktop().add(this, this.isModal() ? JLayeredPane.MODAL_LAYER : JLayeredPane.PALETTE_LAYER); + this.makeWindowCentered(); + + this.setVisible(true); + } + public void cleanUp() { for (Component comp : pile1.getComponents()) { if (comp instanceof MageCard) { @@ -68,38 +88,25 @@ public class PickPileDialog extends MageDialog { } } - public void loadCards(String name, CardsView pile1, CardsView pile2, BigCard bigCard, UUID gameId) { - this.pickedOK = false; - this.pickedPile1 = false; - this.title = name; - this.pile1.loadCardsNarrow(pile1, bigCard, gameId); - this.pile2.loadCardsNarrow(pile2, bigCard, gameId); - - this.setModal(true); - pack(); - - // windows settings - MageFrame.getDesktop().remove(this); - if (this.isModal()) { - MageFrame.getDesktop().add(this, JLayeredPane.MODAL_LAYER); - } else { - MageFrame.getDesktop().add(this, JLayeredPane.PALETTE_LAYER); + private void doClose() { + this.hideDialog(); + if (this.callback != null) { + this.callback.onChoiceDone(); } - this.makeWindowCentered(); - - this.setVisible(true); + this.cleanUp(); + this.removeDialog(); } private void btnPile1ActionPerformed(java.awt.event.ActionEvent evt) { pickedPile1 = true; pickedOK = true; - this.hideDialog(); + doClose(); } private void btnPile2ActionPerformed(java.awt.event.ActionEvent evt) { pickedPile1 = false; pickedOK = true; - this.hideDialog(); + doClose(); } public boolean isPickedPile1() { diff --git a/Mage.Client/src/main/java/mage/client/dialog/RegisterUserDialog.java b/Mage.Client/src/main/java/mage/client/dialog/RegisterUserDialog.java index 61277bf3e2c..cae7eb6addb 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/RegisterUserDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/RegisterUserDialog.java @@ -19,22 +19,17 @@ import java.util.concurrent.TimeoutException; */ public class RegisterUserDialog extends MageDialog { - private static final Logger logger = Logger.getLogger(ConnectDialog.class); - private final ConnectDialog connectDialog; + private static final Logger logger = Logger.getLogger(RegisterUserDialog.class); private Connection connection; private ConnectTask task; - /** - * Creates new form RegisterUserDialog - */ - public RegisterUserDialog(ConnectDialog connectDialog) { + public RegisterUserDialog() { initComponents(); - this.connectDialog = connectDialog; } - public void showDialog() { - this.txtServer.setText(this.connectDialog.getServer()); - this.txtPort.setText(this.connectDialog.getPort()); + public void showDialog(String server, String port) { + this.txtServer.setText(server); + this.txtPort.setText(port); this.lblStatus.setText(""); this.setModal(true); diff --git a/Mage.Client/src/main/java/mage/client/dialog/ResetPasswordDialog.java b/Mage.Client/src/main/java/mage/client/dialog/ResetPasswordDialog.java index b09633dd8a6..c0b30bc4525 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/ResetPasswordDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/ResetPasswordDialog.java @@ -20,24 +20,18 @@ import java.util.concurrent.TimeoutException; public class ResetPasswordDialog extends MageDialog { private static final Logger logger = Logger.getLogger(ResetPasswordDialog.class); - private final ConnectDialog connectDialog; private Connection connection; private GetAuthTokenTask getAuthTokenTask; private ResetPasswordTask resetPasswordTask; - /** - * Creates new form ResetPasswordDialog - */ - public ResetPasswordDialog(ConnectDialog connectDialog) { + public ResetPasswordDialog() { initComponents(); - this.connectDialog = connectDialog; } - public void showDialog() { - String serverAddress = this.connectDialog.getServer(); - this.txtServer.setText(serverAddress); - this.txtPort.setText(this.connectDialog.getPort()); - this.txtEmail.setText(MagePreferences.getEmail(serverAddress)); + public void showDialog(String server, String port) { + this.txtServer.setText(server); + this.txtPort.setText(port); + this.txtEmail.setText(MagePreferences.getEmail(server)); this.lblStatus.setText(""); this.setModal(true); diff --git a/Mage.Client/src/main/java/mage/client/dialog/ShowCardsDialog.java b/Mage.Client/src/main/java/mage/client/dialog/ShowCardsDialog.java index ad35a0a1dff..34090e0ff8c 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/ShowCardsDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/ShowCardsDialog.java @@ -21,17 +21,17 @@ /** * Game GUI: choose target card from the cards list (example: exile and choose card to cast, choose triggers order, etc) + *

+ * Used by feedback's connected dialog, send command on card clicks, so no need callback on close * * @author BetaSteward_at_googlemail.com, JayDi85 */ public class ShowCardsDialog extends MageDialog { // remember if this dialog was already auto positioned, so don't do it after the first time + // TODO: buggy, must remember by window title? Don't work with multiple triggers https://github.com/magefree/mage/issues/12281 private boolean positioned; - /** - * Creates new form ShowCardsDialog - */ public ShowCardsDialog() { this.positioned = false; @@ -91,7 +91,6 @@ }); } - public void loadCards(String name, CardsView showCards, BigCard bigCard, UUID gameId, boolean modal, Map options, JPopupMenu popupMenu, Listener eventListener) { @@ -127,11 +126,7 @@ // window settings MageFrame.getDesktop().remove(this); - if (this.isModal()) { - MageFrame.getDesktop().add(this, JLayeredPane.MODAL_LAYER); - } else { - MageFrame.getDesktop().add(this, JLayeredPane.PALETTE_LAYER); - } + MageFrame.getDesktop().add(this, this.isModal() ? JLayeredPane.MODAL_LAYER : JLayeredPane.PALETTE_LAYER); } private void initComponents() { diff --git a/Mage.Client/src/main/java/mage/client/dialog/TableWaitingDialog.java b/Mage.Client/src/main/java/mage/client/dialog/TableWaitingDialog.java index be803c879bf..2fff7e2ff18 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/TableWaitingDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/TableWaitingDialog.java @@ -34,6 +34,8 @@ import static mage.client.dialog.PreferencesDialog.KEY_TABLES_DIVIDER_LOCATION_4 /** * App GUI: waiting other players before join to a table + *

+ * Do not use modal/callback, send direct commands to server * * @author BetaSteward_at_googlemail.com */ @@ -101,7 +103,7 @@ public class TableWaitingDialog extends MageDialog { this.btnMoveUp.setEnabled(false); break; default: - closeDialog(); + doClose(); return; } int row = this.jTableSeats.getSelectedRow(); @@ -113,10 +115,10 @@ public class TableWaitingDialog extends MageDialog { this.jTableSeats.repaint(); this.jTableSeats.getSelectionModel().setSelectionInterval(row, row); } else { - closeDialog(); + doClose(); } } catch (Exception ex) { - closeDialog(); + doClose(); } } @@ -149,11 +151,11 @@ public class TableWaitingDialog extends MageDialog { GuiDisplayUtil.restoreDividerLocations(currentBounds, tournamentChatDivider, jSplitPane1); } else { - closeDialog(); + doClose(); } } - public void closeDialog() { + public void doClose() { if (updateTask != null) { updateTask.cancel(true); } @@ -249,10 +251,10 @@ public class TableWaitingDialog extends MageDialog { private void btnStartActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnStartActionPerformed if (!isTournament) { if (SessionHandler.startMatch(roomId, tableId)) { - closeDialog(); + doClose(); } } else if (SessionHandler.startTournament(roomId, tableId)) { - closeDialog(); + doClose(); } }//GEN-LAST:event_btnStartActionPerformed @@ -265,7 +267,7 @@ public class TableWaitingDialog extends MageDialog { //swallow exception LOGGER.error(e); } - closeDialog(); + doClose(); }//GEN-LAST:event_btnCancelActionPerformed private void btnMoveDownActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnMoveDownActionPerformed @@ -401,7 +403,7 @@ class UpdateSeatsTask extends SwingWorker { if (tableView.isPresent()) { tableView.ifPresent(this::publish); } else { - dialog.closeDialog(); + dialog.doClose(); } TimeUnit.SECONDS.sleep(1); } diff --git a/Mage.Client/src/main/java/mage/client/dialog/TestCardRenderDialog.java b/Mage.Client/src/main/java/mage/client/dialog/TestCardRenderDialog.java index a79316a1e46..e209b2b57a2 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/TestCardRenderDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/TestCardRenderDialog.java @@ -113,11 +113,7 @@ public class TestCardRenderDialog extends MageDialog { // windows settings MageFrame.getDesktop().remove(this); - if (this.isModal()) { - MageFrame.getDesktop().add(this, JLayeredPane.MODAL_LAYER); - } else { - MageFrame.getDesktop().add(this, JLayeredPane.PALETTE_LAYER); - } + MageFrame.getDesktop().add(this, this.isModal() ? JLayeredPane.MODAL_LAYER : JLayeredPane.PALETTE_LAYER); this.makeWindowCentered(); // Close on "ESC" diff --git a/Mage.Client/src/main/java/mage/client/dialog/TestModalDialog.java b/Mage.Client/src/main/java/mage/client/dialog/TestModalDialog.java index d59f029d59a..bd3d7a47763 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/TestModalDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/TestModalDialog.java @@ -41,11 +41,7 @@ public class TestModalDialog extends MageDialog { // windows settings MageFrame.getDesktop().remove(this); - if (this.isModal()) { - MageFrame.getDesktop().add(this, JLayeredPane.MODAL_LAYER); - } else { - MageFrame.getDesktop().add(this, JLayeredPane.PALETTE_LAYER); - } + MageFrame.getDesktop().add(this, this.isModal() ? JLayeredPane.MODAL_LAYER : JLayeredPane.PALETTE_LAYER); this.makeWindowCentered(); // Close on "ESC" diff --git a/Mage.Client/src/main/java/mage/client/dialog/TestModalSampleDialog.java b/Mage.Client/src/main/java/mage/client/dialog/TestModalSampleDialog.java index 1c0654445a5..1860a241c72 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/TestModalSampleDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/TestModalSampleDialog.java @@ -36,11 +36,7 @@ public class TestModalSampleDialog extends MageDialog { // windows settings MageFrame.getDesktop().remove(this); - if (this.isModal()) { - MageFrame.getDesktop().add(this, JLayeredPane.MODAL_LAYER); - } else { - MageFrame.getDesktop().add(this, JLayeredPane.PALETTE_LAYER); - } + MageFrame.getDesktop().add(this, this.isModal() ? JLayeredPane.MODAL_LAYER : JLayeredPane.PALETTE_LAYER); this.makeWindowCentered(); Point p = this.getLocation(); p.x = p.x + offsetX; diff --git a/Mage.Client/src/main/java/mage/client/dialog/UserRequestDialog.java b/Mage.Client/src/main/java/mage/client/dialog/UserRequestDialog.java index 11b4fc32b95..83f2333bfd5 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/UserRequestDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/UserRequestDialog.java @@ -10,7 +10,7 @@ import javax.swing.plaf.basic.BasicInternalFrameUI; import java.awt.*; /** - * GUI: global window message with additional action to choose (example: close the app) + * App GUI: global window message with additional action to choose (example: close the app) * Can be used in any places (in games, in app, etc) * * @author BetaSteward_at_googlemail.com @@ -19,9 +19,6 @@ public class UserRequestDialog extends MageDialog { private UserRequestMessage userRequestMessage; - /** - * Creates new form AskDialog - */ public UserRequestDialog() { initComponents(); setGUISize(); diff --git a/Mage.Client/src/main/java/mage/client/dialog/WhatsNewDialog.java b/Mage.Client/src/main/java/mage/client/dialog/WhatsNewDialog.java index ea8265924ff..dfab17f27fa 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/WhatsNewDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/WhatsNewDialog.java @@ -69,11 +69,7 @@ public class WhatsNewDialog extends MageDialog { // windows settings MageFrame.getDesktop().remove(this); - if (this.isModal()) { - MageFrame.getDesktop().add(this, JLayeredPane.MODAL_LAYER); - } else { - MageFrame.getDesktop().add(this, JLayeredPane.PALETTE_LAYER); - } + MageFrame.getDesktop().add(this, this.isModal() ? JLayeredPane.MODAL_LAYER : JLayeredPane.PALETTE_LAYER); this.makeWindowCentered(); // Close on "ESC" diff --git a/Mage.Client/src/main/java/mage/client/game/GamePanel.java b/Mage.Client/src/main/java/mage/client/game/GamePanel.java index cd9272addad..c22d72ce1c5 100644 --- a/Mage.Client/src/main/java/mage/client/game/GamePanel.java +++ b/Mage.Client/src/main/java/mage/client/game/GamePanel.java @@ -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 messages, Map 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 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 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 getPlayers() { diff --git a/Mage.Client/src/main/java/mage/client/table/TablesPanel.java b/Mage.Client/src/main/java/mage/client/table/TablesPanel.java index 06777f2680b..957fc9b991a 100644 --- a/Mage.Client/src/main/java/mage/client/table/TablesPanel.java +++ b/Mage.Client/src/main/java/mage/client/table/TablesPanel.java @@ -57,6 +57,8 @@ import java.util.concurrent.TimeUnit; import static mage.client.dialog.PreferencesDialog.*; /** + * GUI: lobby's main component + * * @author BetaSteward_at_googlemail.com */ public class TablesPanel extends javax.swing.JPanel { @@ -140,9 +142,12 @@ public class TablesPanel extends javax.swing.JPanel { private UpdateTablesTask updateTablesTask; private UpdatePlayersTask updatePlayersTask; private UpdateMatchesTask updateMatchesTask; + + // no needs in multiple create/join tables dialogs, it's a client side action private JoinTableDialog joinTableDialog; private NewTableDialog newTableDialog; private NewTournamentDialog newTournamentDialog; + private final GameChooser gameChooser; private java.util.List messages; private int currentMessage; @@ -439,14 +444,18 @@ public class TablesPanel extends javax.swing.JPanel { LOGGER.info("Joining tournament " + tableId); if (!gameType.startsWith("Constructed")) { if (TablesTableModel.PASSWORD_VALUE_YES.equals(pwdColumn)) { + // need enter password joinTableDialog.showDialog(roomId, tableId, true, !gameType.startsWith("Constructed")); } else { + // direct join (no pass, no deck) SessionHandler.joinTournamentTable(roomId, tableId, SessionHandler.getUserName(), PlayerType.HUMAN, 1, null, ""); } } else { + // need choose deck joinTableDialog.showDialog(roomId, tableId, true, !gameType.startsWith("Constructed")); } } else { + // need choose deck LOGGER.info("Joining table " + tableId); joinTableDialog.showDialog(roomId, tableId, false, false); } @@ -758,15 +767,15 @@ public class TablesPanel extends javax.swing.JPanel { } if (newTableDialog == null) { newTableDialog = new NewTableDialog(); - MageFrame.getDesktop().add(newTableDialog, JLayeredPane.MODAL_LAYER); + MageFrame.getDesktop().add(newTableDialog, newTableDialog.isModal() ? JLayeredPane.MODAL_LAYER : JLayeredPane.PALETTE_LAYER); } if (newTournamentDialog == null) { newTournamentDialog = new NewTournamentDialog(); - MageFrame.getDesktop().add(newTournamentDialog, JLayeredPane.MODAL_LAYER); + MageFrame.getDesktop().add(newTournamentDialog, newTournamentDialog.isModal() ? JLayeredPane.MODAL_LAYER : JLayeredPane.PALETTE_LAYER); } if (joinTableDialog == null) { joinTableDialog = new JoinTableDialog(); - MageFrame.getDesktop().add(joinTableDialog, JLayeredPane.MODAL_LAYER); + MageFrame.getDesktop().add(joinTableDialog, joinTableDialog.isModal() ? JLayeredPane.MODAL_LAYER : JLayeredPane.PALETTE_LAYER); } if (chatRoomId != null) { this.chatPanelMain.getUserChatPanel().connect(chatRoomId); @@ -810,7 +819,7 @@ public class TablesPanel extends javax.swing.JPanel { this.saveDividerLocations(); for (Component component : MageFrame.getDesktop().getComponents()) { if (component instanceof TableWaitingDialog) { - ((TableWaitingDialog) component).closeDialog(); + ((TableWaitingDialog) component).doClose(); } } stopTasks(); diff --git a/Mage.Client/src/main/java/mage/client/util/gui/FastSearchUtil.java b/Mage.Client/src/main/java/mage/client/util/gui/FastSearchUtil.java index 533b0c95cd0..1b226b90cf5 100644 --- a/Mage.Client/src/main/java/mage/client/util/gui/FastSearchUtil.java +++ b/Mage.Client/src/main/java/mage/client/util/gui/FastSearchUtil.java @@ -36,10 +36,9 @@ public class FastSearchUtil { DefaultComboBoxModel comboModel = (DefaultComboBoxModel) combo.getModel(); Map choiceItems = new HashMap<>(comboModel.getSize()); Map choiceSorting = new HashMap<>(comboModel.getSize()); - String item; for (int i = 0; i < comboModel.getSize(); i++) { - item = comboModel.getElementAt(i).toString(); + String item = comboModel.getElementAt(i).toString(); choiceItems.put(item, item); choiceSorting.put(item, i); // need so sorting } @@ -55,17 +54,18 @@ public class FastSearchUtil { // ask for new value PickChoiceDialog dlg = new PickChoiceDialog(); dlg.setWindowSize(windowWidth, windowHeight); - dlg.showDialog(choice, needSelectValue); - if (choice.isChosen()) { - item = choice.getChoiceKey(); + dlg.showDialog(choice, needSelectValue, () -> { + if (choice.isChosen()) { + String item = choice.getChoiceKey(); - // compatible select for object's models (use setSelectedIndex instead setSelectedObject) - for (int i = 0; i < comboModel.getSize(); i++) { - if (comboModel.getElementAt(i).toString().equals(item)) { - combo.setSelectedIndex(i); + // compatible select for object's models (use setSelectedIndex instead setSelectedObject) + for (int i = 0; i < comboModel.getSize(); i++) { + if (comboModel.getElementAt(i).toString().equals(item)) { + combo.setSelectedIndex(i); + } } } - } + }); } /** @@ -73,8 +73,9 @@ public class FastSearchUtil { * * @param combo CheckBoxList control with default data model * @param chooseMessage caption message for dialog + * @param additionalCallbackOnDone will be called after choice done */ - public static void showFastSearchForStringComboBox(CheckBoxList combo, String chooseMessage) { + public static void showFastSearchForStringComboBox(CheckBoxList combo, String chooseMessage, PickCheckBoxDialog.PickCheckBoxCallback additionalCallbackOnDone) { // fast search/choice dialog for string combobox mage.choices.Choice choice = new ChoiceImpl(false); @@ -83,10 +84,9 @@ public class FastSearchUtil { DefaultListModel comboModel = (DefaultListModel) combo.getModel(); Map choiceItems = new HashMap<>(comboModel.getSize()); Map choiceSorting = new HashMap<>(comboModel.getSize()); - String item; for (int i = 0; i < comboModel.size(); i++) { - item = comboModel.getElementAt(i).toString(); + String item = comboModel.getElementAt(i).toString(); choiceItems.put(item, item); choiceSorting.put(item, i); // need so sorting } @@ -105,16 +105,18 @@ public class FastSearchUtil { PickCheckBoxDialog dlg = new PickCheckBoxDialog(combo); dlg.setWindowSize(300, 500); - dlg.showDialog(choice, needSelectValue); - if (choice.isChosen()) { - item = choice.getChoiceKey(); + dlg.showDialog(choice, needSelectValue, () -> { + if (choice.isChosen()) { + String item = choice.getChoiceKey(); - // compatible select for object's models (use setSelectedIndex instead setSelectedObject) - for (int i = 0; i < comboModel.getSize(); i++) { - if (comboModel.getElementAt(i).toString().equals(item)) { - combo.setSelectedIndex(i); + // compatible select for object's models (use setSelectedIndex instead setSelectedObject) + for (int i = 0; i < comboModel.getSize(); i++) { + if (comboModel.getElementAt(i).toString().equals(item)) { + combo.setSelectedIndex(i); + } } } - } + additionalCallbackOnDone.onChoiceDone(); + }); } } diff --git a/Mage.Client/src/main/java/mage/client/util/gui/GuiDisplayUtil.java b/Mage.Client/src/main/java/mage/client/util/gui/GuiDisplayUtil.java index 94a1ffb5567..49d6b83feda 100644 --- a/Mage.Client/src/main/java/mage/client/util/gui/GuiDisplayUtil.java +++ b/Mage.Client/src/main/java/mage/client/util/gui/GuiDisplayUtil.java @@ -513,7 +513,7 @@ public final class GuiDisplayUtil { // re-render existing components with new style for (Frame frame : Frame.getFrames()) { - refreshLookAndFill(frame); + refreshLookAndFeel(frame); } // re-render hidden/shared components @@ -528,9 +528,9 @@ public final class GuiDisplayUtil { }); } - private static void refreshLookAndFill(Window window) { + private static void refreshLookAndFeel(Window window) { for (Window childWindow : window.getOwnedWindows()) { - refreshLookAndFill(childWindow); + refreshLookAndFeel(childWindow); } SwingUtilities.updateComponentTreeUI(window); } diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/DownloadServiceInfo.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/DownloadServiceInfo.java index 72c816d3908..abc8a313a04 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/DownloadServiceInfo.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/DownloadServiceInfo.java @@ -17,7 +17,5 @@ public interface DownloadServiceInfo { void updateProgressMessage(String text, int progressCurrent, int progressNeed); - void showDownloadControls(boolean needToShow); - Object getSync(); } diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CopyPasteImageSourceDialog.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CopyPasteImageSourceDialog.java index 91db9311eb2..68b7a7f20f1 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CopyPasteImageSourceDialog.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CopyPasteImageSourceDialog.java @@ -54,7 +54,7 @@ public class CopyPasteImageSourceDialog extends JDialog { StreamUtils.closeQuietly(bw); } - dispose(); + onCancel(); } private void onCancel() { diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSource.java index 4087f85051d..467bd4f13ec 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSource.java @@ -311,11 +311,14 @@ public class ScryfallImageSource implements CardImageSource { } // if up to date - if (isBulkDataPrepared()) { + if (isBulkDataPrepared(downloadServiceInfo)) { return true; } // NEED TO DOWNLOAD + if (downloadServiceInfo.isNeedCancel()) { + return false; + } // clean TFile bulkTempFile = prepareTempFileForBulkData(); @@ -424,16 +427,20 @@ public class ScryfallImageSource implements CardImageSource { } } - return isBulkDataPrepared(); + return isBulkDataPrepared(downloadServiceInfo); } - private boolean isBulkDataPrepared() { + private boolean isBulkDataPrepared(DownloadServiceInfo downloadServiceInfo) { // already loaded if (bulkCardsDatabaseAll.size() > 0) { return true; } + if (downloadServiceInfo.isNeedCancel()) { + return false; + } + // file not exists Path textBulkPath = Paths.get(getBulkStaticFileName()); if (!Files.exists(textBulkPath)) { @@ -462,6 +469,10 @@ public class ScryfallImageSource implements CardImageSource { jsonReader.beginArray(); while (jsonReader.hasNext()) { + if (downloadServiceInfo.isNeedCancel()) { + return false; + } + ScryfallApiCard card = gson.fromJson(jsonReader, ScryfallApiCard.class); // prepare data diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPicturesService.java b/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPicturesService.java index 5336d1784a9..f4aadb4917d 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPicturesService.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPicturesService.java @@ -45,13 +45,15 @@ import java.util.stream.Collectors; import static org.mage.plugins.card.utils.CardImageUtils.getImagesDir; /** - * Images downloader + * App GUI: card images downloader service (for GUI control see DownloadImagesDialog) * * @author JayDi85 */ public class DownloadPicturesService extends DefaultBoundedRangeModel implements DownloadServiceInfo, Runnable { - private static DownloadPicturesService instance; + private static DownloadPicturesService instance = null; + private static Thread loadMissingDataThread = null; + private static final Logger logger = Logger.getLogger(DownloadPicturesService.class); private static final String ALL_IMAGES = "- ALL images from selected source (can be slow)"; @@ -79,7 +81,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements private final List cardsDownloadQueue; private final List selectedSets = new ArrayList<>(); - private static CardImageSource selectedSource; + private CardImageSource selectedSource; private final Object sync = new Object(); @@ -114,31 +116,47 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements return instance; } - public static void main(String[] args) { - startDownload(); - } - public static void startDownload() { - // load images info in background task - instance = new DownloadPicturesService(MageFrame.getInstance()); - new Thread(new LoadMissingCardDataNew(instance)).start(); + // workaround to keep first db connection in main thread (not images thread) - so it will keep connection after close + // TODO: no needs? + CardRepository.instance.getNonLandAndNonCreatureNames(); - // show dialog + // load images info in background task + if (instance == null) { + instance = new DownloadPicturesService(); + } + + if (loadMissingDataThread != null) { + // stop old thread + //loadMissingDataThread.interrupt(); + } + + // refresh ui + instance.uiDialog.setGlobalInfo("Initializing image download..."); + instance.uiDialog.getProgressBar().setValue(0); + + // start new thread + loadMissingDataThread = new Thread(new LoadMissingCardDataNew(instance)); + loadMissingDataThread.setDaemon(true); + loadMissingDataThread.start(); + + // show control dialog instance.setNeedCancel(false); instance.resetErrorCount(); - instance.uiDialog.showDialog(); - instance.uiDialog.dispose(); - instance.setNeedCancel(true); + instance.uiDialog.showDialog(() -> { + // on finish/close/cancel + doStopAndClose(); + }); + } - // IMAGES CHECK (download process can broke some files, so fix it here too) - // code executes on cancel/close download dialog (but not executes on app's close -- it's ok) - logger.info("Images: search broken files..."); - CardImageUtils.checkAndFixImageFiles(); + static private void doStopAndClose() { + instance.setNeedCancel(true); + instance.uiDialog.hideDialog(); } @Override public boolean isNeedCancel() { - return this.needCancel || (this.errorCount > MAX_ERRORS_COUNT_BEFORE_CANCEL); + return this.needCancel || (this.errorCount > MAX_ERRORS_COUNT_BEFORE_CANCEL) || Thread.interrupted(); } private void setNeedCancel(boolean needCancel) { @@ -158,16 +176,13 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements this.errorCount = 0; } - public DownloadPicturesService(JFrame frame) { + public DownloadPicturesService() { // init service and dialog cardsAll = Collections.synchronizedList(new ArrayList<>()); cardsMissing = Collections.synchronizedList(new ArrayList<>()); cardsDownloadQueue = Collections.synchronizedList(new ArrayList<>()); uiDialog = new DownloadImagesDialog(); - // MESSAGE - uiDialog.setGlobalInfo("Initializing image download..."); - // SOURCES - scryfall is default source uiDialog.getSourcesCombo().setModel(new DefaultComboBoxModel(DownloadSources.values())); uiDialog.getSourcesCombo().setSelectedItem(DownloadSources.SCRYFALL_NORM); @@ -215,11 +230,8 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements }); // BUTTON CANCEL (dialog and loading) - uiDialog.getCancelButton().addActionListener(e -> uiDialog.setVisible(false)); - uiDialog.getStopButton().addActionListener(e -> uiDialog.setVisible(false)); - - // PROGRESS BAR - uiDialog.getProgressBar().setValue(0); + uiDialog.getCancelButton().addActionListener(e -> doStopAndClose()); + uiDialog.getStopButton().addActionListener(e -> doStopAndClose()); } public void findMissingCards() { @@ -228,21 +240,30 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements this.cardsMissing.clear(); this.cardsDownloadQueue.clear(); - updateGlobalMessage("Loading cards list..."); - this.cardsAll = Collections.synchronizedList(CardRepository.instance.findCards( - new CardCriteria().nightCard(null) // meld cards need to be in the target cards, so we allow for night cards - )); + try { + updateGlobalMessage("Loading cards list..."); + this.cardsAll.addAll(CardRepository.instance.findCards( + new CardCriteria().nightCard(null) // meld cards need to be in the target cards, so we allow for night cards + )); + if (isNeedCancel()) { + // fast stop on cancel + return; + } - updateGlobalMessage("Finding missing images..."); - this.cardsMissing = prepareMissingCards(this.cardsAll, uiDialog.getRedownloadCheckbox().isSelected()); + updateGlobalMessage("Finding missing images..."); + this.cardsMissing.addAll(prepareMissingCards(this.cardsAll, uiDialog.getRedownloadCheckbox().isSelected())); + if (isNeedCancel()) { + // fast stop on cancel + return; + } - updateGlobalMessage("Finding available sets from selected source..."); - this.uiDialog.getSetsCombo().setModel(new DefaultComboBoxModel<>(getSetsForCurrentImageSource())); - reloadCardsToDownload(this.uiDialog.getSetsCombo().getSelectedItem().toString()); - - this.uiDialog.showDownloadControls(true); - updateGlobalMessage(""); - showDownloadControls(true); + updateGlobalMessage("Finding available sets from selected source..."); + this.uiDialog.getSetsCombo().setModel(new DefaultComboBoxModel<>(getSetsForCurrentImageSource())); + reloadCardsToDownload(this.uiDialog.getSetsCombo().getSelectedItem().toString()); + } finally { + updateGlobalMessage(""); + this.uiDialog.showDownloadControls(true); + } } private void reloadLanguagesForSelectedSource() { @@ -286,12 +307,6 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements this.uiDialog.getProgressBar().setValue(progressCurrent); } - @Override - public void showDownloadControls(boolean needToShow) { - // auto-size form on show - this.uiDialog.showDownloadControls(needToShow); - } - private String getSetNameWithYear(ExpansionSet exp) { return exp.getName() + " (" + exp.getCode() + ", " + exp.getReleaseYear() + ")"; } @@ -419,7 +434,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements MageFrame.getDesktop().setCursor(new Cursor(Cursor.WAIT_CURSOR)); try { this.cardsMissing.clear(); - this.cardsMissing = prepareMissingCards(this.cardsAll, uiDialog.getRedownloadCheckbox().isSelected()); + this.cardsMissing.addAll(prepareMissingCards(this.cardsAll, uiDialog.getRedownloadCheckbox().isSelected())); reloadCardsToDownload(uiDialog.getSetsCombo().getSelectedItem().toString()); } finally { MageFrame.getDesktop().setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); @@ -577,7 +592,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements allCardsUrls.add(card); }); } catch (Exception e) { - logger.error(e); + logger.error("Error on prepare images list: " + e, e); } // find missing files @@ -691,12 +706,15 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements } executor.shutdown(); - while (!executor.isTerminated()) { - try { - TimeUnit.SECONDS.sleep(1); - } catch (InterruptedException ignore) { - } + try { + executor.awaitTermination(30, TimeUnit.SECONDS); + } catch (InterruptedException ignore) { } + + // IMAGES CHECK (download process can break some files, so fix it here too) + // code executes on finish/cancel download (but not executes on app's close -- it's ok) + logger.info("Images: search broken files..."); + CardImageUtils.checkAndFixImageFiles(); } } catch (Throwable e) { logger.error("Catch unknown error while downloading: " + e, e); @@ -998,8 +1016,4 @@ class LoadMissingCardDataNew implements Runnable { public void run() { downloadPicturesService.findMissingCards(); } - - public static void main() { - (new Thread(new LoadMissingCardDataNew(downloadPicturesService))).start(); - } } diff --git a/Mage.Common/src/main/java/mage/view/UserRequestMessage.java b/Mage.Common/src/main/java/mage/view/UserRequestMessage.java index 5e379eadfd4..c1f5d2ef923 100644 --- a/Mage.Common/src/main/java/mage/view/UserRequestMessage.java +++ b/Mage.Common/src/main/java/mage/view/UserRequestMessage.java @@ -6,7 +6,7 @@ import java.io.Serializable; import java.util.UUID; /** - * GUI: settings for message window that allows to choose additional action (can be used in game or outside) + * App GUI: settings for message window that allows to choose additional action (can be used in game or outside) * * @author LevelX2 */