package magic.ui; import java.awt.dnd.DropTarget; import java.awt.event.KeyEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.File; import java.io.IOException; import java.nio.file.Path; import java.util.Locale; import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.ToolTipManager; import magic.data.CardDefinitions; import magic.data.DuelConfig; import magic.data.OSXAdapter; import magic.exception.DesktopNotSupportedException; import magic.game.state.GameLoader; import magic.model.MagicDeck; import magic.model.MagicDeckConstructionRule; import magic.model.MagicDuel; import magic.model.MagicGameLog; import magic.translate.MText; import magic.ui.helpers.DesktopHelper; import magic.ui.helpers.ImageHelper; import magic.ui.screen.MScreen; import magic.ui.screen.ScreenHelper; import magic.ui.theme.ThemeFactory; import magic.utility.MagicFileSystem; import magic.utility.MagicFileSystem.DataPath; import magic.utility.MagicSystem; import org.apache.commons.io.FileUtils; @SuppressWarnings("serial") public class MagicFrame extends MagicStickyFrame implements IDragDropListener { // translatable strings private static final String _S1 = "F11 : full screen"; private static final String _S2 = "No saved duel found."; private static final String _S3 = "%s's deck is illegal."; private static final String _S4 = "Are you sure you want to quit Magarena?"; private static final String _S5 = "Confirm Quit to Desktop"; private static final String _S6 = "Invalid action!"; private boolean confirmQuitToDesktop = true; // Check if we are on Mac OS X. This is crucial to loading and using the OSXAdapter class. public static final boolean MAC_OS_X = System.getProperty("os.name").toLowerCase(Locale.ENGLISH).startsWith("mac os x"); private final MagicFramePanel contentPanel; private MagicDuel duel; public MagicFrame(final String frameTitle) { ToolTipManager.sharedInstance().setInitialDelay(400); // Setup frame. this.setTitle(String.format("%s [%s]", frameTitle, MText.get(_S1))); this.setIconImage(MagicImages.APP_LOGO); setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); addWindowListeners(); registerForMacOSXEvents(); // Setup content container with a painted background based on theme. contentPanel = new MagicFramePanel(); contentPanel.setOpaque(true); setContentPane(contentPanel); setKeyboardEventActions(); // Enable drag and drop of background image file. new DropTarget(this, new FileDropTargetListener(this)); setVisible(true); } private void setKeyboardEventActions() { ScreenHelper.setKeyEvent(contentPanel, KeyEvent.VK_F10, this::doScreenshot); ScreenHelper.setKeyEvent(contentPanel, KeyEvent.VK_F11, this::toggleFullScreenMode); ScreenHelper.setKeyEvent(contentPanel, KeyEvent.VK_F12, this::toggleUI); } private void addWindowListeners() { addWindowListener(new WindowAdapter() { @Override public void windowClosing(final WindowEvent event) { onClose(); } }); } public void showDuel() { if (duel!=null) { ScreenController.showDuelDecksScreen(duel); if (MagicSystem.isAiVersusAi()) { if (!duel.isFinished()) { nextGame(); } else { newDuel(DuelConfig.getInstance()); } } } } public void newDuel(final DuelConfig configuration) { duel = new MagicDuel(configuration); duel.initialize(); showDuel(); } public void loadDuel() { final File duelFile=MagicDuel.getLatestDuelFile(); if (duelFile.exists()) { duel=new MagicDuel(DuelConfig.getInstance()); duel.load(duelFile); showDuel(); } else { ScreenController.showWarningMessage(MText.get(_S2)); } } public void restartDuel() { if (duel!=null) { duel.restart(); showDuel(); } } public boolean isLegalDeckAndShowErrors(final MagicDeck deck, final String playerName) { final String brokenRulesText = MagicDeckConstructionRule.getRulesText(MagicDeckConstructionRule.checkDeck(deck)); if (brokenRulesText.length() > 0) { ScreenController.showWarningMessage(String.format("%s\n\n%s", MText.get(_S3, playerName), brokenRulesText)); return false; } return true; } public void nextGame() { ScreenController.showDuelGameScreen(duel); } /** * Set up our application to respond to the Mac OS X application menu */ private void registerForMacOSXEvents() { if (MAC_OS_X) { try { // Generate and register the OSXAdapter, passing it a hash of all the methods we wish to // use as delegates for various com.apple.eawt.ApplicationListener methods OSXAdapter.setQuitHandler(this, getClass().getDeclaredMethod("onClose")); //OSXAdapter.setAboutHandler(this, getClass().getDeclaredMethod("about", (Class[])null)); //OSXAdapter.setPreferencesHandler(this, getClass().getDeclaredMethod("preferences", (Class[])null)); //OSXAdapter.setFileHandler(this, getClass().getDeclaredMethod("loadImageFile", new Class[] { String.class })); } catch (Exception e) { System.err.println("Error while loading the OSXAdapter:"); e.printStackTrace(); } } } public boolean onClose() { if (!confirmQuitToDesktop) { doShutdownMagarena(); } else { final String message = String.format("%s\n", MText.get(_S4)); final Object[] params = {message}; final int n = JOptionPane.showConfirmDialog(contentPanel, params, MText.get(_S5), JOptionPane.YES_NO_OPTION); if (n == JOptionPane.YES_OPTION) { doShutdownMagarena(); } } // set the ApplicationEvent as handled (for OS X) return false; } private void doShutdownMagarena() { saveSizeAndPosition(); MagicGameLog.close(); MagicSound.shutdown(); /* if (gamePanel != null) { gamePanel.getController().haltGame(); } */ System.exit(0); } public void quitToDesktop(final boolean confirmQuit) { this.confirmQuitToDesktop = confirmQuit; processWindowEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING)); } /** * */ public void closeDuelScreen() { ScreenController.closeActiveScreen(false); showDuel(); } private void doScreenshot() { try { final Path filePath = MagicFileSystem.getDataPath(DataPath.LOGS).resolve("screenshot.png"); final File imageFile = ImageHelper.doScreenshotToFile(this.getContentPane(), filePath); DesktopHelper.openFileInDefaultOsEditor(imageFile); } catch (IOException | DesktopNotSupportedException e) { e.printStackTrace(); ScreenController.showWarningMessage(e.toString()); } } private void refreshBackground() { contentPanel.refreshBackground(); } public void refreshLookAndFeel() { ScreenController.refreshStyle(); refreshBackground(); } public void refreshUI() { config.setIsMissingFiles(false); CardDefinitions.checkForMissingFiles(); ThemeFactory.getInstance().loadThemes(); refreshLookAndFeel(); } public void setScreen(MScreen s) { contentPanel.setScreen(s); } private boolean replaceBackgroundImage(File newImage) { try { FileUtils.copyFile(newImage, MagicFileSystem.getBackgroundImageFile()); return true; } catch (IOException ex) { ScreenController.showWarningMessage(String.format("%s\n\n%s", MText.get(_S6), ex.getMessage()) ); } return false; } private void doSetCustomBackgroundImage(File imageFile) { if (!ImageHelper.isValidImageFile(imageFile)) { ScreenController.showWarningMessage("Invalid image file."); return; } final String message = String.format("%s\n", MText.get("Replace background image?")); final Object[] params = {message}; final int response = JOptionPane.showConfirmDialog(contentPanel, params, MText.get("Confirmation required..."), JOptionPane.YES_NO_OPTION); if (response == JOptionPane.YES_OPTION) { if (replaceBackgroundImage(imageFile)) { config.setCustomBackground(true); config.save(); refreshLookAndFeel(); } } } @Override public void onImageFileDropped(File imageFile) { doSetCustomBackgroundImage(imageFile); } @Override public void onZipFileDropped(File zipFile) { System.out.println("[TODO] onZipFileDropped : " + zipFile); } private void toggleUI() { final MScreen screen = ScreenController.getActiveScreen(); screen.setVisible(!screen.isVisible()); } @Override public void onGameSnapshotDropped(File aFile) { MagicSystem.setIsTestGame(true); ScreenController.showDuelGameScreen(GameLoader.loadSavedGame(aFile)); } }