diff --git a/src/magic/data/DownloadableFile.java b/src/magic/data/DownloadableFile.java index cbfdee93e1..4d3d9b35e6 100644 --- a/src/magic/data/DownloadableFile.java +++ b/src/magic/data/DownloadableFile.java @@ -14,6 +14,11 @@ import org.apache.commons.io.FileUtils; public class DownloadableFile { + private static final GeneralConfig CONFIG = GeneralConfig.getInstance(); + + private static String proxySettings = ""; + private static Proxy proxy = Proxy.NO_PROXY; + private final File localFile; private final URL remoteFile; @@ -34,24 +39,24 @@ public class DownloadableFile { return localFile.getName(); } - public void doDownload(final Proxy proxy) throws IOException { + public void doDownload() throws IOException { final File tempFile = new File(localFile.getParent(), "~" + localFile.getName()); - downloadToFile(proxy, remoteFile, tempFile); + downloadToFile(remoteFile, tempFile); Files.move(tempFile.toPath(), localFile.toPath(), StandardCopyOption.REPLACE_EXISTING); } - public static void downloadToFile(final Proxy proxy, final URL url, final File file) throws IOException { - if (proxy != Proxy.NO_PROXY && proxy.type() != Proxy.Type.DIRECT) { - downloadUsingProxy(proxy, url, file); - } else { - FileUtils.copyURLToFile(url, file, 10000, 5000); + private static Proxy getProxy() { + if (!proxySettings.equals(CONFIG.getProxySettings())) { + proxySettings = CONFIG.getProxySettings(); + proxy = CONFIG.getProxy(); } + return proxy; } - private static void downloadUsingProxy(final Proxy proxy, final URL url, final File file) throws IOException { + private static void downloadUsingProxy(URL url, File file) throws IOException { try ( final OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(file)); - final InputStream inputStream = url.openConnection(proxy).getInputStream()) { + final InputStream inputStream = url.openConnection(getProxy()).getInputStream()) { final byte[] buffer = new byte[65536]; while (true) { final int len = inputStream.read(buffer); @@ -66,4 +71,12 @@ public class DownloadableFile { } } + public static void downloadToFile(URL url, File file) throws IOException { + if (getProxy() != Proxy.NO_PROXY && getProxy().type() != Proxy.Type.DIRECT) { + downloadUsingProxy(url, file); + } else { + FileUtils.copyURLToFile(url, file, 10000, 5000); + } + } + } diff --git a/src/magic/data/GeneralConfig.java b/src/magic/data/GeneralConfig.java index c6c4032670..38dcf9c4ce 100644 --- a/src/magic/data/GeneralConfig.java +++ b/src/magic/data/GeneralConfig.java @@ -190,15 +190,13 @@ public class GeneralConfig { public Proxy getProxy() { final String DELIM = "\\|"; - final String proxyString = proxySettings.trim(); - if (proxyString.isEmpty() || proxyString.split(DELIM).length != 3) { - return Proxy.NO_PROXY; - } else { - final Proxy.Type proxyType = Proxy.Type.valueOf(proxyString.split(DELIM)[0]); - final int port = Integer.parseInt(proxyString.split(DELIM)[1]); - final String urlAddress = proxyString.split(DELIM)[2]; + if (!proxySettings.isEmpty() && proxySettings.split(DELIM).length == 3) { + Proxy.Type proxyType = Proxy.Type.valueOf(proxySettings.split(DELIM)[0]); + int port = Integer.parseInt(proxySettings.split(DELIM)[1]); + String urlAddress = proxySettings.split(DELIM)[2]; return new Proxy(proxyType, new InetSocketAddress(urlAddress, port)); } + return Proxy.NO_PROXY; } public void setProxy(final Proxy proxy) { @@ -214,6 +212,10 @@ public class GeneralConfig { } } + public String getProxySettings() { + return proxySettings; + } + public int getDeckFileMaxLines() { return deckFileMaxLines; } @@ -559,7 +561,7 @@ public class GeneralConfig { cardImagesPath = properties.getProperty(CARD_IMAGES_PATH, cardImagesPath); animateGameplay = Boolean.parseBoolean(properties.getProperty(ANIMATE_GAMEPLAY, "" + animateGameplay)); deckFileMaxLines = Integer.parseInt(properties.getProperty(DECK_FILE_MAX_LINES, ""+ deckFileMaxLines)); - proxySettings = properties.getProperty(PROXY_SETTINGS, proxySettings); + proxySettings = properties.getProperty(PROXY_SETTINGS, proxySettings).trim(); firemindAccessToken = properties.getProperty(FIREMIND_ACCESS_TOKEN, firemindAccessToken); newTurnAlertDuration = Integer.parseInt(properties.getProperty(NEWTURN_ALERT_DURATION,"" + newTurnAlertDuration)); landPreviewDuration = Integer.parseInt(properties.getProperty(LAND_PREVIEW_DURATION,"" + landPreviewDuration)); diff --git a/src/magic/data/json/NewVersionJsonParser.java b/src/magic/data/json/NewVersionJsonParser.java index b57bb7c19a..7ff785cebb 100644 --- a/src/magic/data/json/NewVersionJsonParser.java +++ b/src/magic/data/json/NewVersionJsonParser.java @@ -2,7 +2,6 @@ package magic.data.json; import java.io.File; import java.io.IOException; -import magic.data.GeneralConfig; import magic.utility.MagicFileSystem; import magic.utility.MagicFileSystem.DataPath; import magic.utility.MagicSystem; @@ -23,7 +22,7 @@ public final class NewVersionJsonParser { private static boolean downloadJsonToFile(final File jsonFile) { try { final DownloadableJsonFile downloadFile = new DownloadableJsonFile("https://magarena.github.io/current.json", jsonFile); - downloadFile.doDownload(GeneralConfig.getInstance().getProxy()); + downloadFile.doDownload(); if (jsonFile.length() == 0) { System.err.println("new version json file is empty!"); return false; diff --git a/src/magic/exception/DownloadException.java b/src/magic/exception/DownloadException.java new file mode 100644 index 0000000000..022747b1ea --- /dev/null +++ b/src/magic/exception/DownloadException.java @@ -0,0 +1,23 @@ +package magic.exception; + +import magic.data.DownloadableFile; + +@SuppressWarnings("serial") +public class DownloadException extends Exception { + + private final DownloadableFile dfile; + + public DownloadException(String message, Throwable cause, final DownloadableFile dfile) { + super(message, cause); + this.dfile = dfile; + } + + public DownloadException(String message, Throwable cause) { + super(message, cause); + this.dfile = null; + } + + public boolean hasFile() { + return dfile != null; + } +} diff --git a/src/magic/firemind/FiremindJsonReader.java b/src/magic/firemind/FiremindJsonReader.java index 3bd6d45eea..25a53ad890 100644 --- a/src/magic/firemind/FiremindJsonReader.java +++ b/src/magic/firemind/FiremindJsonReader.java @@ -6,7 +6,6 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.Calendar; import java.util.List; -import magic.data.GeneralConfig; import magic.data.json.DownloadableJsonFile; import magic.model.MagicDeck; import magic.utility.DeckUtils; @@ -30,7 +29,7 @@ public final class FiremindJsonReader { try { final DownloadableJsonFile downloadFile = new DownloadableJsonFile("https://www.firemind.ch/decks/top.json", jsonFile); - downloadFile.doDownload(GeneralConfig.getInstance().getProxy()); + downloadFile.doDownload(); } catch (IOException ex) { System.err.println("Download of json file failed : " + ex.getMessage()); } diff --git a/src/magic/ui/MagicCardImages.java b/src/magic/ui/MagicCardImages.java index d378035241..862b4fd582 100644 --- a/src/magic/ui/MagicCardImages.java +++ b/src/magic/ui/MagicCardImages.java @@ -2,13 +2,12 @@ package magic.ui; import java.awt.image.BufferedImage; import java.io.File; -import java.io.IOException; -import java.net.Proxy; import java.nio.file.Path; import java.util.Arrays; -import magic.cardBuilder.renderers.CardBuilder; -import magic.data.CardImageFile; +import java.util.logging.Level; +import java.util.logging.Logger; import magic.data.GeneralConfig; +import magic.exception.DownloadException; import magic.model.IRenderableCard; import magic.model.MagicCardDefinition; import magic.ui.screen.images.download.CardImageDisplayMode; @@ -26,17 +25,18 @@ public final class MagicCardImages { PRINTED } + private static final Logger LOGGER = Logger.getLogger(MagicCardImages.class.getName()); + private static final String[] CUSTOM_IMAGE_ENDINGS = new String[]{".jpg", ".full.jpg"}; private static final GeneralConfig CONFIG = GeneralConfig.getInstance(); - private static Proxy proxy; private static File getCustomCardImageFile(IRenderableCard face, String ending) { Path imagesFolder = MagicFileSystem.getImagesPath(MagicFileSystem.ImagesPath.CUSTOM); return new File(imagesFolder.toFile(), face.getImageName() + ending); } - private static boolean customCardImageExists(IRenderableCard face) { + public static boolean isCustomCardImageFound(IRenderableCard face) { return Arrays.stream(CUSTOM_IMAGE_ENDINGS) .anyMatch(ending -> getCustomCardImageFile(face, ending).exists()); } @@ -50,21 +50,26 @@ public final class MagicCardImages { .orElse(MagicImages.MISSING_CARD); } + private static boolean printedImageExists(IRenderableCard face) { + return MagicFileSystem.getPrintedCardImage(face).exists(); + } + private static ImageType getImageType(IRenderableCard face) { if (face.isUnknown()) { return ImageType.UNKNOWN; } - if (customCardImageExists(face)) { + if (isCustomCardImageFound(face)) { return ImageType.CUSTOM; } - if (CONFIG.getCardImageDisplayMode() == CardImageDisplayMode.PROXY) { + if (CONFIG.getCardImageDisplayMode() == CardImageDisplayMode.PROXY + && !face.isPlaneswalker() && !face.isFlipCard() && !face.isToken()) { return ImageType.PROXY; } - if (MagicFileSystem.getPrintedCardImage(face).exists() || CONFIG.getImagesOnDemand()) { + if (printedImageExists(face) || CONFIG.getImagesOnDemand()) { return ImageType.PRINTED; } @@ -72,53 +77,60 @@ public final class MagicCardImages { return ImageType.PROXY; } - private static void tryDownloadingPrintedImage(IRenderableCard face) { - if (proxy == null) { - proxy = CONFIG.getProxy(); - } + private static BufferedImage getPrintedCardImage(IRenderableCard face) { try { - CardImageFile cif = new CardImageFile(face); - cif.doDownload(proxy); - } catch (IOException ex) { - System.err.println(face.getCardDefinition().getDistinctName() + " : " + ex); + return PrintedCardImage.get(face); + } catch (DownloadException ex) { + LOGGER.log(Level.SEVERE, null, ex); + return MagicImages.MISSING_CARD; + } + } + + private static BufferedImage getProxyCardImage(IRenderableCard face) { + try { + return ProxyCardImage.get(face); + } catch (DownloadException ex) { + LOGGER.log(Level.SEVERE, null, ex); + return MagicImages.MISSING_CARD; } } public static BufferedImage createImage(IRenderableCard face) { final ImageType type = getImageType(face); switch (type) { - case UNKNOWN: - return MagicImages.MISSING_CARD; - case CUSTOM: - return getCustomCardImage(face); - case PROXY: - return CardBuilder.getCardBuilderImage(face); - case PRINTED: - if (!MagicFileSystem.getPrintedCardImage(face).exists()) { - // on-demand image download. - tryDownloadingPrintedImage(face); - } - if (MagicFileSystem.getPrintedCardImage(face).exists()) { - if (CONFIG.getCardImageDisplayMode() == CardImageDisplayMode.PRINTED || CONFIG.getCardTextLanguage() != CardTextLanguage.ENGLISH) { - return ImageFileIO.getOptimizedImage(MagicFileSystem.getPrintedCardImage(face)); - } else { - return face.isPlaneswalker() || face.isFlipCard() || face.isToken() - ? ImageFileIO.getOptimizedImage(MagicFileSystem.getPrintedCardImage(face)) - : CardBuilder.getCardBuilderImage(face); - } - } + case UNKNOWN: return MagicImages.MISSING_CARD; + case CUSTOM: return getCustomCardImage(face); + case PROXY: return getProxyCardImage(face); + case PRINTED: return getPrintedCardImage(face); } - return CardBuilder.getCardBuilderImage(face); + throw new RuntimeException("Unsupported image type: " + type); } public static boolean isProxyImage(IRenderableCard face) { return getImageType(face) == ImageType.PROXY; } + public static boolean isPrintedCardImageMissing(MagicCardDefinition card) { + return !MagicFileSystem.getPrintedCardImage(card).exists(); + } + + private static boolean customCardImageMissing(MagicCardDefinition card) { + return !isCustomCardImageFound(card); + } + + public static boolean isCroppedCardImageMissing(MagicCardDefinition card) { + return !MagicFileSystem.getCroppedCardImage(card).exists(); + } + public static boolean isCardImageMissing(MagicCardDefinition aCard) { - return !customCardImageExists(aCard) - && !MagicFileSystem.getCroppedCardImage(aCard).exists() - && !MagicFileSystem.getPrintedCardImage(aCard).exists(); + if (CONFIG.getCardImageDisplayMode() == CardImageDisplayMode.PRINTED) { + return customCardImageMissing(aCard) + && isPrintedCardImageMissing(aCard); + } else { // PROXY + return customCardImageMissing(aCard) + && isCroppedCardImageMissing(aCard) + && isPrintedCardImageMissing(aCard); + } } private MagicCardImages() {} diff --git a/src/magic/ui/PrintedCardImage.java b/src/magic/ui/PrintedCardImage.java new file mode 100644 index 0000000000..dafb705d93 --- /dev/null +++ b/src/magic/ui/PrintedCardImage.java @@ -0,0 +1,73 @@ +package magic.ui; + +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import magic.cardBuilder.renderers.CardBuilder; +import magic.data.CardImageFile; +import magic.data.DownloadableFile; +import magic.data.GeneralConfig; +import magic.exception.DownloadException; +import magic.model.IRenderableCard; +import magic.ui.helpers.UrlHelper; +import magic.utility.MagicFileSystem; + +public abstract class PrintedCardImage { + + private static final GeneralConfig CONFIG = GeneralConfig.getInstance(); + + public static boolean imageExists(IRenderableCard face) { + return MagicFileSystem.getPrintedCardImage(face).exists(); + } + + private static void downloadEnglishImage(CardImageFile aFile) throws DownloadException { + try { + aFile.doDownload(); + } catch (IOException ex) { + throw new DownloadException(String.format("%s [%s]", ex.toString(), aFile.getFilename()), ex, aFile); + } + } + + private static boolean downloadNonEnglishImage(CardImageFile aFile, CardTextLanguage aLang) throws DownloadException, MalformedURLException { + URL url = UrlHelper.getAltMagicCardsInfoUrl(aFile, aLang); + if (UrlHelper.isUrlValid(url)) { + DownloadableFile df = new DownloadableFile(aFile.getLocalFile(), url); + try { + df.doDownload(); + return true; + } catch (IOException ex) { + throw new DownloadException(String.format("%s [%s (%s)]", ex.toString(), aFile.getFilename(), aLang), ex, aFile); + } + } + return false; + } + + public static void tryDownloadingPrintedImage(CardImageFile imageFile) throws DownloadException { + try { + CardTextLanguage textLang = GeneralConfig.getInstance().getCardTextLanguage(); + if (textLang.isEnglish() || !downloadNonEnglishImage(imageFile, textLang)) { + downloadEnglishImage(imageFile); + } + } catch (MalformedURLException ex) { + throw new DownloadException(String.format("%s [%s]", ex.toString(), imageFile.getUrl()), ex, imageFile); + } + } + + private static void tryDownloadingPrintedImage(IRenderableCard face) throws DownloadException { + if (CONFIG.getImagesOnDemand() && !imageExists(face)) { + try { + tryDownloadingPrintedImage(new CardImageFile(face)); + } catch (MalformedURLException ex) { + throw new DownloadException(String.format("%s [%s]", ex.toString(), face.getImageName()), ex); + } + } + } + + static BufferedImage get(IRenderableCard face) throws DownloadException { + tryDownloadingPrintedImage(face); + return imageExists(face) + ? ImageFileIO.getOptimizedImage(MagicFileSystem.getPrintedCardImage(face)) + : CardBuilder.getCardBuilderImage(face); + } +} diff --git a/src/magic/ui/ProxyCardImage.java b/src/magic/ui/ProxyCardImage.java new file mode 100644 index 0000000000..c89ffe462e --- /dev/null +++ b/src/magic/ui/ProxyCardImage.java @@ -0,0 +1,68 @@ +package magic.ui; + +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import magic.cardBuilder.renderers.CardBuilder; +import magic.data.CardImageFile; +import magic.data.DownloadableFile; +import magic.data.GeneralConfig; +import magic.exception.DownloadException; +import magic.model.IRenderableCard; +import magic.model.MagicCardDefinition; +import magic.ui.helpers.UrlHelper; +import magic.utility.MagicFileSystem; + +public abstract class ProxyCardImage { + + private static final GeneralConfig CONFIG = GeneralConfig.getInstance(); + + private static boolean croppedImageExists(IRenderableCard face) { + return MagicFileSystem.getCroppedCardImage(face).exists(); + } + + private static boolean tryDownloadingFile(DownloadableFile aFile) { + try { + aFile.doDownload(); + return true; + } catch (IOException ex) { + return false; + } + } + + public static boolean tryDownloadingCroppedImage(CardImageFile imageFile) throws MalformedURLException, DownloadException { + MagicCardDefinition card = imageFile.getCard(); + if (card.getImageURL().contains("magiccards.info/scans/")) { + URL remote = new URL(card.getImageURL().replace("/scans/", "/crop/")); + if (UrlHelper.isUrlValid(remote)) { + File local = MagicFileSystem.getCroppedCardImage(imageFile.getCard()); + return tryDownloadingFile(new DownloadableFile(local, remote)); + } + } + return false; + } + + private static void tryDownloadingCroppedImage(IRenderableCard face) throws DownloadException { + try { + tryDownloadingCroppedImage(new CardImageFile(face)); + } catch (MalformedURLException ex) { + throw new DownloadException(String.format("%s [%s]", ex.toString(), face.getImageName()), ex); + } + } + + static BufferedImage get(IRenderableCard face) throws DownloadException { + if (CONFIG.getImagesOnDemand()) { + if (!croppedImageExists(face) && !PrintedCardImage.imageExists(face)) { + tryDownloadingCroppedImage(face); + } + if (!croppedImageExists(face) && !PrintedCardImage.imageExists(face)) { + // CB can extract crop from printed image as a last resort. + PrintedCardImage.get(face); + } + } + return CardBuilder.getCardBuilderImage(face); + } + +} diff --git a/src/magic/ui/helpers/UrlHelper.java b/src/magic/ui/helpers/UrlHelper.java index 25d776afd5..c0a705b885 100644 --- a/src/magic/ui/helpers/UrlHelper.java +++ b/src/magic/ui/helpers/UrlHelper.java @@ -7,6 +7,7 @@ import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; +import magic.data.DownloadableFile; import magic.ui.CardTextLanguage; public final class UrlHelper { @@ -43,10 +44,10 @@ public final class UrlHelper { /** * Returns a {@code magiccards.info} image url for a given non-English language code. */ - public static URL getAlternateMagicCardsImageUrl(URL defaultUrl, CardTextLanguage lang) throws MalformedURLException { + public static URL getAltMagicCardsInfoUrl(DownloadableFile aFile, CardTextLanguage lang) throws MalformedURLException { final String BASE = "/magiccards.info/scans/"; final String TARGET = BASE + "en/"; - final String s = defaultUrl.toExternalForm(); + final String s = aFile.getUrl().toExternalForm(); return s.contains(TARGET) ? new URL(s.replaceAll(TARGET, BASE + lang.getMagicCardsCode() + "/")) : null; @@ -71,6 +72,6 @@ public final class UrlHelper { return false; } } - + private UrlHelper() { } } diff --git a/src/magic/ui/screen/images/download/DialogMainPanel.java b/src/magic/ui/screen/images/download/DialogMainPanel.java index bb7074d449..3b7dabef8b 100644 --- a/src/magic/ui/screen/images/download/DialogMainPanel.java +++ b/src/magic/ui/screen/images/download/DialogMainPanel.java @@ -13,10 +13,9 @@ import javax.swing.JPanel; import javax.swing.SwingUtilities; import magic.data.MagicIcon; import magic.translate.MText; -import magic.ui.CardTextLanguage; import magic.ui.MagicImages; -import magic.ui.helpers.UrlHelper; import magic.ui.dialog.button.CloseButton; +import magic.ui.helpers.UrlHelper; import net.miginfocom.swing.MigLayout; @SuppressWarnings("serial") @@ -31,8 +30,7 @@ class DialogMainPanel extends JPanel implements PropertyChangeListener { private static final String _S3 = "Run in background..."; private static final String _S4 = "Opens a page containing more information on this screen in your internet browser."; private static final String _S6 = "Downloads card images that are missing or out-of-date in the 'cards' and 'tokens' folders."; - private static final String _S7 = "Downloads cropped images that are missing or out-of-date in the 'crops' folder. Not 100% coverage, currently there is not a downloadable cropped image for every card."; - private static final String _S8 = "Magarena will display the first image it finds using the folder order:- 'custom', 'crops', 'cards' or 'tokens'. If a cropped image is found or the image is missing then a proxy card image will be generated."; + private static final String _S7 = "Not 100% coverage. Please note there may be a bit of a delay the first time a proxy image is requested while the rendering sub-system is loaded and intialized."; private final JButton backgroundButton; private final OptionsPanel optionsPanel; @@ -46,13 +44,6 @@ class DialogMainPanel extends JPanel implements PropertyChangeListener { hintPanel = new HintPanel(getDefaultHint()); - optionsPanel = new OptionsPanel(); - optionsPanel.addHintSources(hintPanel); - optionsPanel.setEnabled(false); - optionsPanel.addPropertyChangeListener(OptionsPanel.CP_OPTIONS_CHANGED, - (e) -> { refreshDownloadList(); } - ); - backgroundButton = new JButton(MText.get(_S3)); backgroundButton.setFocusable(false); backgroundButton.addActionListener((a) -> { doRunInBackground(); }); @@ -63,17 +54,20 @@ class DialogMainPanel extends JPanel implements PropertyChangeListener { buttonsPanel = new ButtonsPanel(); + optionsPanel = new OptionsPanel(this); + optionsPanel.addHintSources(hintPanel); + setDownloadPanels(); setLookAndFeel(); refreshLayout(); + updateComponentState(); } private String getDefaultHint() { - return String.format("%s
%s

%s
%s

%s", + return String.format("%s
%s

%s
%s", CardImageDisplayMode.PRINTED.toString(), MText.get(_S6), - CardImageDisplayMode.PROXY.toString(), MText.get(_S7), - MText.get(_S8) + CardImageDisplayMode.PROXY.toString(), MText.get(_S7) ); } @@ -82,18 +76,18 @@ class DialogMainPanel extends JPanel implements PropertyChangeListener { } private void refreshDownloadList() { - final CardImageDisplayMode mode = optionsPanel.getDisplayMode(); - final CardTextLanguage lang = optionsPanel.getCardTextLanguage(); + CardImageDisplayMode mode = optionsPanel.getCardImageDisplayMode(); for (DownloadPanel panel : downloadPanels) { - panel.refreshDownloadList(mode, lang); + panel.doCancel(); + panel.refreshDownloadList(mode); } } private void setDownloadPanels() { downloadPanels.add(getPlayableDownloaderPanel()); downloadPanels.add(getUnimplementedDownloaderPanel()); - downloadPanel.setLayout(new MigLayout("flowy, insets 6 0 6 0, gapy 0")); - downloadPanel.setBorder(BorderFactory.createMatteBorder(1, 0, 1, 0, Color.GRAY)); + downloadPanel.setLayout(new MigLayout("flowy, insets 0 0 6 0, gapy 0")); + downloadPanel.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.GRAY)); for (DownloadPanel panel : downloadPanels) { downloadPanel.add(panel, "w 100%"); } @@ -116,8 +110,7 @@ class DialogMainPanel extends JPanel implements PropertyChangeListener { private DownloadPanel getPlayableDownloaderPanel() { final DownloadPanel playableDownloaderPanel = new PlayablePanel( - optionsPanel.getDisplayMode(), - optionsPanel.getCardTextLanguage(), + optionsPanel.getCardImageDisplayMode(), this ); playableDownloaderPanel.addPropertyChangeListener(DownloadPanel.CP_STATE_CHANGED, this); @@ -126,8 +119,7 @@ class DialogMainPanel extends JPanel implements PropertyChangeListener { private DownloadPanel getUnimplementedDownloaderPanel() { final DownloadPanel unimplementedDownloaderPanel = new UnimplementedPanel( - optionsPanel.getDisplayMode(), - optionsPanel.getCardTextLanguage(), + optionsPanel.getCardImageDisplayMode(), this ); unimplementedDownloaderPanel.addPropertyChangeListener(DownloadPanel.CP_STATE_CHANGED, this); @@ -146,12 +138,17 @@ class DialogMainPanel extends JPanel implements PropertyChangeListener { activePanel = panel; } } + if (optionsPanel != null) { + optionsPanel.setEnabled(!isDownloading); + } + for (DownloadPanel panel : downloadPanels) { + panel.setEnabled(!optionsPanel.isOnDemand()); + } if (activePanel != null) { for (DownloadPanel panel : downloadPanels) { panel.setLocked(panel != activePanel); } } - optionsPanel.setEnabled(!isScanning && !isDownloading); buttonsPanel.setIsDownloading(isDownloading); } @@ -165,6 +162,20 @@ class DialogMainPanel extends JPanel implements PropertyChangeListener { return false; } + void doOnImageFolderChanged() { + refreshDownloadList(); + updateComponentState(); + } + + void doOnDisplayModeChanged() { + refreshDownloadList(); + updateComponentState(); + } + + void doOnDemandChanged() { + updateComponentState(); + } + private class ButtonsPanel extends JPanel { private final JButton closeButton; @@ -204,6 +215,7 @@ class DialogMainPanel extends JPanel implements PropertyChangeListener { for (DownloadPanel panel : downloadPanels) { panel.doCancel(); } + optionsPanel.saveSettings(); firePropertyChange(CP_CLOSE, true, false); } diff --git a/src/magic/ui/screen/images/download/DirectoryChooser.java b/src/magic/ui/screen/images/download/DirectoryChooser.java index 6f7464ba5d..42bd817572 100644 --- a/src/magic/ui/screen/images/download/DirectoryChooser.java +++ b/src/magic/ui/screen/images/download/DirectoryChooser.java @@ -3,6 +3,7 @@ package magic.ui.screen.images.download; import java.awt.Color; import java.awt.Component; import java.awt.Container; +import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.MouseListener; import java.io.File; @@ -14,8 +15,8 @@ import javax.swing.JFileChooser; import javax.swing.JPanel; import javax.swing.JTextField; import magic.translate.MText; -import magic.ui.ScreenController; import magic.ui.FontsAndBorders; +import magic.ui.ScreenController; import magic.ui.widget.M.MFileLink; import magic.utility.MagicFileSystem; import magic.utility.MagicFileSystem.DataPath; @@ -82,7 +83,7 @@ public class DirectoryChooser extends JPanel { imagesFolder.setFile(defaultPath); imagesFolder.setToolTipText(MText.get(_S6)); imagesFolder.setBorder(BorderFactory.createCompoundBorder( - BorderFactory.createMatteBorder(1, 1, 1, 1, Color.GRAY), + BorderFactory.createMatteBorder(1, 1, 1, 1, Color.GRAY), BorderFactory.createEmptyBorder(0, 4, 0, 0)) ); } @@ -99,6 +100,10 @@ public class DirectoryChooser extends JPanel { )); } + void setBold(boolean b) { + imagesFolder.setFont(imagesFolder.getFont().deriveFont(b ? Font.BOLD : Font.PLAIN)); + } + private static class ImagesDirectoryChooser extends JFileChooser { public ImagesDirectoryChooser(String currentDirectoryPath) { super(currentDirectoryPath); diff --git a/src/magic/ui/screen/images/download/DownloadPanel.java b/src/magic/ui/screen/images/download/DownloadPanel.java index ba550908b6..cff9443fde 100644 --- a/src/magic/ui/screen/images/download/DownloadPanel.java +++ b/src/magic/ui/screen/images/download/DownloadPanel.java @@ -2,9 +2,10 @@ package magic.ui.screen.images.download; import java.awt.Font; import java.io.IOException; -import java.net.Proxy; import java.util.Collection; import java.util.Date; +import java.util.logging.Level; +import java.util.logging.Logger; import java.util.stream.Stream; import javax.swing.ImageIcon; import javax.swing.JButton; @@ -21,9 +22,8 @@ import magic.data.ImagesDownloadList; import magic.data.MagicIcon; import magic.model.MagicCardDefinition; import magic.translate.MText; -import magic.ui.CardTextLanguage; +import magic.ui.MagicCardImages; import magic.ui.MagicImages; -import magic.utility.MagicFileSystem; import net.miginfocom.swing.MigLayout; @SuppressWarnings("serial") @@ -34,7 +34,9 @@ abstract class DownloadPanel extends JPanel implements IScanListener, IDownloadL // translatable strings private static final String _S1 = "Cancel"; - protected final GeneralConfig CONFIG = GeneralConfig.getInstance(); + private static final Logger LOGGER = Logger.getLogger(DownloadPanel.class.getName()); + + protected static final GeneralConfig CONFIG = GeneralConfig.getInstance(); private final MigLayout migLayout = new MigLayout(); protected final JLabel captionLabel = getCaptionLabel(getProgressCaption()); @@ -43,20 +45,17 @@ abstract class DownloadPanel extends JPanel implements IScanListener, IDownloadL protected final JProgressBar progressBar = new JProgressBar(); private ImagesDownloadList files; - private boolean isCancelled = false; private SwingWorker imagesDownloader; private ScanWorker imagesScanner; private DownloadState downloaderState = DownloadState.STOPPED; private CardImageDisplayMode displayMode = CardImageDisplayMode.PRINTED; - private CardTextLanguage textLanguage = CardTextLanguage.ENGLISH; private final DialogMainPanel mainPanel; protected abstract String getProgressCaption(); protected abstract String getDownloadButtonCaption(); - DownloadPanel(CardImageDisplayMode aMode, CardTextLanguage aLang, DialogMainPanel aPanel) { + DownloadPanel(CardImageDisplayMode aMode, DialogMainPanel aPanel) { this.displayMode = aMode; - this.textLanguage = aLang; this.mainPanel = aPanel; setLookAndFeel(); refreshLayout(); @@ -70,7 +69,7 @@ abstract class DownloadPanel extends JPanel implements IScanListener, IDownloadL private void doRunImageDownloadWorker() { setDownloadingState(); - imagesDownloader = new DownloadWorker(this, textLanguage, displayMode); + imagesDownloader = new DownloadWorker(this, displayMode); imagesDownloader.execute(); notifyStatusChanged(DownloadState.DOWNLOADING); } @@ -85,7 +84,6 @@ abstract class DownloadPanel extends JPanel implements IScanListener, IDownloadL } void doCancel() { - isCancelled = true; doCancelImageDownloadWorker(); doCancelImagesScanner(); } @@ -108,14 +106,16 @@ abstract class DownloadPanel extends JPanel implements IScanListener, IDownloadL if (imagesScanner != null && !imagesScanner.isDone()) { imagesScanner.cancel(true); } - if (!isCancelled) { - captionLabel.setIcon(MagicImages.getIcon(MagicIcon.BUSY16)); - captionLabel.setText(getProgressCaption()); - imagesScanner = new ScanWorker(this, displayMode); - imagesScanner.execute(); - downloadButton.setEnabled(false); - notifyStatusChanged(DownloadState.SCANNING); + if (imagesScanner != null && !imagesScanner.isDone()) { + LOGGER.log(Level.WARNING, "Scanner still running!"); + return; } + captionLabel.setIcon(MagicImages.getIcon(MagicIcon.BUSY16)); + captionLabel.setText(getProgressCaption()); + imagesScanner = new ScanWorker(this, displayMode); + imagesScanner.execute(); + downloadButton.setEnabled(false); + notifyStatusChanged(DownloadState.SCANNING); } private void resetProgressBar() { @@ -186,9 +186,9 @@ abstract class DownloadPanel extends JPanel implements IScanListener, IDownloadL ); } - void refreshDownloadList(CardImageDisplayMode aMode, CardTextLanguage aLang) { + void refreshDownloadList(CardImageDisplayMode aMode) { + doCancel(); this.displayMode = aMode; - this.textLanguage = aLang; buildDownloadImagesList(); } @@ -212,8 +212,8 @@ abstract class DownloadPanel extends JPanel implements IScanListener, IDownloadL progressBar.setString(null); } - protected String doFileDownloadAndGetName(final DownloadableFile file, final Proxy proxy) throws IOException { - file.doDownload(proxy); + protected String doFileDownloadAndGetName(final DownloadableFile file) throws IOException { + file.doDownload(); if (file instanceof CardImageFile) { return ((CardImageFile) file).getCardName(); } else { @@ -225,23 +225,38 @@ abstract class DownloadPanel extends JPanel implements IScanListener, IDownloadL return countInteger; } - private static boolean isImageFileMissing(MagicCardDefinition card, CardImageDisplayMode mode) { - if (mode == CardImageDisplayMode.PRINTED) { - return !MagicFileSystem.getPrintedCardImage(card).exists(); - } else { - return !MagicFileSystem.getCroppedCardImage(card).exists() - && !MagicFileSystem.getPrintedCardImage(card).exists(); + private static boolean requiresNewImageDownload(MagicCardDefinition card, Date lastDownloadDate) { + if (!card.hasImageUrl()) { + return false; + } + if (MagicCardImages.isCustomCardImageFound(card)) { + return false; + } + if (card.isImageUpdatedAfter(lastDownloadDate)) { + return true; + } + if (CONFIG.getCardImageDisplayMode() == CardImageDisplayMode.PRINTED) { + return MagicCardImages.isPrintedCardImageMissing(card); + } else { // PROXY + return MagicCardImages.isCroppedCardImageMissing(card) + && MagicCardImages.isPrintedCardImageMissing(card); } } protected static Stream getCards(Collection cards, Date aDate, CardImageDisplayMode mode) { - return cards.stream() - .filter(MagicCardDefinition::hasImageUrl) - .filter(card -> card.isImageUpdatedAfter(aDate) || isImageFileMissing(card, mode)); + return cards.stream().filter(card -> requiresNewImageDownload(card, aDate)); } void setLocked(boolean b) { downloadButton.setEnabled(!b && files != null && !files.isEmpty()); } + @Override + public void setEnabled(boolean b) { + super.setEnabled(b); + downloadButton.setEnabled(b); + progressBar.setEnabled(b); + captionLabel.setEnabled(b); + } + } diff --git a/src/magic/ui/screen/images/download/DownloadWorker.java b/src/magic/ui/screen/images/download/DownloadWorker.java index 7f95032f5b..25bebe5ed7 100644 --- a/src/magic/ui/screen/images/download/DownloadWorker.java +++ b/src/magic/ui/screen/images/download/DownloadWorker.java @@ -3,7 +3,6 @@ package magic.ui.screen.images.download; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; -import java.net.Proxy; import java.net.URL; import java.nio.file.Files; import java.time.LocalDateTime; @@ -14,40 +13,35 @@ import javax.swing.SwingUtilities; import javax.swing.SwingWorker; import magic.data.CardImageFile; import magic.data.DownloadableFile; -import magic.data.GeneralConfig; import magic.data.ImagesDownloadList; -import magic.model.MagicCardDefinition; +import magic.exception.DownloadException; import magic.ui.CardTextLanguage; import magic.ui.MagicImages; import magic.ui.MagicLogFile; -import magic.ui.helpers.UrlHelper; -import magic.utility.MagicFileSystem; +import magic.ui.PrintedCardImage; +import magic.ui.ProxyCardImage; import magic.utility.MagicSystem; class DownloadWorker extends SwingWorker { private static final MagicLogFile missingLog = new MagicLogFile("downloaded-images"); - private final Proxy proxy; private ImagesDownloadList downloadList; private final IDownloadListener listener; - private final CardTextLanguage textLanguage; private final CardImageDisplayMode displayMode; private boolean updateDownloadDate = true; private boolean isLogging = true; private int serverBusyCooldown = 1; // in millisecs - DownloadWorker(IDownloadListener aListener, CardTextLanguage aLanguage, CardImageDisplayMode aMode) { + DownloadWorker(IDownloadListener aListener, CardImageDisplayMode aMode) { this.listener = aListener; - this.textLanguage = aLanguage; this.displayMode = aMode; - this.proxy = GeneralConfig.getInstance().getProxy(); } @Override protected Void doInBackground() throws MalformedURLException { this.downloadList = ScanWorker.getImagesDownloadList((IScanListener)listener, displayMode); - doDownloadImages(textLanguage); + doDownloadImages(); return null; } @@ -113,51 +107,12 @@ class DownloadWorker extends SwingWorker { } } - /** - * Gets alternate magiccards.info image url for given card text language. - * If it fails then displays reason in error log panel and returns null url. - */ - private URL getAlternateUrl(DownloadableFile aFile, CardTextLanguage textLang) { - try { - return UrlHelper.getAlternateMagicCardsImageUrl(aFile.getUrl(), textLang); - } catch (MalformedURLException ex) { - listener.setMessage(String.format("%s [%s]", ex.toString(), aFile.getUrl())); - return null; - } - } - private void setServerBusyCooldown(String errmsg) { if (errmsg.contains("HTTP response code: 503")) { serverBusyCooldown += 100; } } - /** - * Attempts to download alternate card image. - * If it fails displays reason in error log panel. - */ - private boolean tryAlternateDownload(final DownloadableFile aFile, CardTextLanguage aLang) { - try { - aFile.doDownload(proxy); - } catch (IOException ex) { - listener.setMessage(String.format("%s [%s (%s)]", ex.toString(), aFile.getFilename(), aLang)); - setServerBusyCooldown(ex.toString()); - return false; - } - return true; - } - - private boolean downloadAlternateCardImage(final CardImageFile aFile, CardTextLanguage aLang) { - final URL altUrl = getAlternateUrl(aFile, aLang); - if (UrlHelper.isUrlValid(altUrl)) { - if (tryAlternateDownload(new DownloadableFile(aFile.getLocalFile(), altUrl), aLang)) { - doLog(aFile.getCardName(), aLang, altUrl); - return true; - } - } - return false; - } - private boolean doDeleteLocalImageFile(File aFile) { try { Files.deleteIfExists(aFile.toPath()); @@ -168,50 +123,30 @@ class DownloadWorker extends SwingWorker { return true; } - /** - * Attempts to download default card image. - * If it fails displays reason in error log panel. - */ - private boolean tryDefaultDownload(final DownloadableFile aFile) { + private void downloadPrintedImage(CardImageFile imageFile) { try { - aFile.doDownload(proxy); - } catch (IOException ex) { - // if local file exists then download was triggered by the - // 'image_updated' script property. But download failed so - // remove local image so it becomes 'missing' instead. - updateDownloadDate = displayMode != CardImageDisplayMode.PROXY && doDeleteLocalImageFile(aFile.getLocalFile()); - listener.setMessage(String.format("%s [%s]", ex.toString(), aFile.getFilename())); + PrintedCardImage.tryDownloadingPrintedImage(imageFile); + } catch (DownloadException ex) { + listener.setMessage(ex.getMessage()); setServerBusyCooldown(ex.toString()); - return false; - } - return true; - } - - private void downloadDefaultCardImage(final CardImageFile aFile) { - if (tryDefaultDownload(aFile)) { - doLog(aFile.getCardName(), CardTextLanguage.ENGLISH, null); - } - } - - private boolean doDownloadCroppedImage(CardImageFile imageFile) throws MalformedURLException { - final MagicCardDefinition card = imageFile.getCard(); - final File local = MagicFileSystem.getCroppedCardImage(imageFile.getCard()); - if (card.getImageURL().contains("magiccards.info/scans/")) { - final URL remote = new URL(card.getImageURL().replace("/scans/", "/crop/")); - if (UrlHelper.isUrlValid(remote)) { - if (tryDefaultDownload(new DownloadableFile(local, remote))) { - doLog(card.getCardTextName(), CardTextLanguage.ENGLISH, remote); - return true; - } + if (ex.getCause() instanceof IOException) { + // if local image file already existed before download then + // download was triggered by the 'image_updated' script property. + // As download failed remove local image so it gets picked up + // by the missing image trigger instead. If unable to remove + // local image then don't update 'imageDownloaderRunDate'. + updateDownloadDate = doDeleteLocalImageFile(imageFile.getLocalFile()); } } - return false; } - private void doDownloadPrintedImage(CardImageFile imageFile, CardTextLanguage textLang) throws MalformedURLException { - if (textLang.isEnglish() || !downloadAlternateCardImage(imageFile, textLang)) { - downloadDefaultCardImage(imageFile); + private boolean tryDownloadingCroppedImage(CardImageFile imageFile) { + try { + return ProxyCardImage.tryDownloadingCroppedImage(imageFile); + } catch (DownloadException | MalformedURLException ex) { + System.err.println(String.format("%s [%s]", ex.toString(), imageFile.getFilename())); } + return false; } private void doPause(int millisecs) { @@ -222,24 +157,23 @@ class DownloadWorker extends SwingWorker { } } - private void doDownloadImages(CardTextLanguage textLang) throws MalformedURLException { + private void doDownloadImages() throws MalformedURLException { assert !SwingUtilities.isEventDispatchThread(); initializeLogFiles(); int fileCount = 0; - updateDownloadDate = displayMode != CardImageDisplayMode.PROXY; for (DownloadableFile dFile : downloadList) { final CardImageFile imageFile = (CardImageFile) dFile; if (displayMode == CardImageDisplayMode.PROXY) { - if (!doDownloadCroppedImage(imageFile)) { - doDownloadPrintedImage(imageFile, textLang); + if (!tryDownloadingCroppedImage(imageFile)) { + downloadPrintedImage(imageFile); } } else { - doDownloadPrintedImage(imageFile, textLang); + downloadPrintedImage(imageFile); } doPause(serverBusyCooldown); diff --git a/src/magic/ui/screen/images/download/OptionsPanel.java b/src/magic/ui/screen/images/download/OptionsPanel.java index a7bfe8b536..323f5b29e8 100644 --- a/src/magic/ui/screen/images/download/OptionsPanel.java +++ b/src/magic/ui/screen/images/download/OptionsPanel.java @@ -1,51 +1,69 @@ package magic.ui.screen.images.download; +import java.awt.Color; import java.awt.Component; import java.awt.Font; import java.awt.event.ItemEvent; import javax.swing.DefaultComboBoxModel; +import javax.swing.DefaultListCellRenderer; import javax.swing.JComboBox; import javax.swing.JLabel; +import javax.swing.JList; import javax.swing.JPanel; import magic.data.GeneralConfig; import magic.translate.MText; import magic.ui.CardTextLanguage; +import magic.ui.dialog.prefs.ImageSizePresets; import net.miginfocom.swing.MigLayout; @SuppressWarnings("serial") class OptionsPanel extends JPanel { - private static final String _S1 = "Images folder:"; - private static final String _S2 = "Card text:"; - private static final String _S3 = "Display:"; + private static final String _S2 = "Preferred card text:"; + private static final String _S3 = "Display card image as:"; private static final String _S4 = "Preferred card text language"; - private static final String _S5 = "If a language other than English is selected then Magarena will try to find and download a card image for the given language. If no image is found then it will download the default English edition instead."; - - static final String CP_OPTIONS_CHANGED = "fc9a1955-7e59-47d5-83b4-14db558c731e"; + private static final String _S5 = "If a language other than English is selected then Magarena will first try to download a card image with text in that language. If no image is found then it will download the default English card image instead."; + private static final String _S11 = "Not applicable to rendered proxy images."; + private static final String _S6 = "Download on demand:"; + private static final String _S7 = "Only downloads card images as needed. Switch off if you want to download all images in one go, use proxy frames with cropped images or download non-English card images."; + private static final String _S8 = "Preferred display size:"; + private static final String _S9 = "Sets the size of the card image displayed in card explorer and deck editor as well as popup images during a game. Select 'Default' to display the card image at its native size. Otherwise it will be scaled up or down to the selected preset."; + private static final String _S10 = "** This has no affect on the size of an image that is downloaded **"; private final GeneralConfig CONFIG = GeneralConfig.getInstance(); private final JComboBox cboCardText = new JComboBox<>(); private final JComboBox cboDisplayMode = new JComboBox<>(); private final DirectoryChooser imagesFolderChooser; + private final JComboBox cboOnDemand = new JComboBox<>(); + private final JComboBox cboDisplaySize = new JComboBox<>(); + private final DialogMainPanel listener; - OptionsPanel() { + OptionsPanel(DialogMainPanel listener) { + + this.listener = listener; imagesFolderChooser = getImagesFolderChooser(); - setCardTextCombo(); + imagesFolderChooser.setBold(true); + setDisplayModeCombo(); + setDisplaySizeCombo(); + setCardTextCombo(); + setOnDemandCombo(); - setLayout(new MigLayout("wrap 2, insets 0", "[right][]")); + setLayout(new MigLayout("wrap 2, insets 0", "[right, 40%][60%]")); - // image folder - add(new JLabel(MText.get(_S1))); - add(imagesFolderChooser, "w 100%"); - // card text language - add(new JLabel(MText.get(_S2))); - add(cboCardText); - // download mode + add(imagesFolderChooser, "w 100%, spanx 2"); add(getBoldLabel(MText.get(_S3))); add(cboDisplayMode); + add(getBoldLabel(MText.get(_S2))); + add(cboCardText); + add(getBoldLabel(MText.get(_S8))); + add(cboDisplaySize); + add(getBoldLabel(MText.get(_S6))); + add(cboOnDemand); + + setOptionsState(); } private JLabel getBoldLabel(String text) { @@ -54,50 +72,77 @@ class OptionsPanel extends JPanel { return lbl; } - private void saveSettings() { - CONFIG.setCardTextLanguage(getCardTextLanguage()); - CONFIG.setCardImagesPath(imagesFolderChooser.getPath()); - CONFIG.save(); - } - - private void doImageFolderChanged() { - setEnabled(false); - saveSettings(); - firePropertyChange(CP_OPTIONS_CHANGED, true, false); + void saveSettings() { + CONFIG.setCardImageDisplayMode(getCardImageDisplayMode()); + CONFIG.setPreferredImageSize(getPreferredImageSize()); + CONFIG.setImagesOnDemand(isOnDemand()); + if (getCardImageDisplayMode() == CardImageDisplayMode.PRINTED) { + CONFIG.setCardTextLanguage(getCardTextLanguage()); + } } private DirectoryChooser getImagesFolderChooser() { final DirectoryChooser chooser = new DirectoryChooser(CONFIG.getCardImagesPath()); chooser.setFocusable(false); chooser.addPropertyChangeListener(DirectoryChooser.CP_FOLDER_CHANGED, (e) -> { - doImageFolderChanged(); + CONFIG.setCardImagesPath(chooser.getPath()); + listener.doOnImageFolderChanged(); }); return chooser; } - private void doTextLanguageChanged() { - saveSettings(); - firePropertyChange(CP_OPTIONS_CHANGED, true, false); - } - private void setCardTextCombo() { cboCardText.setModel(new DefaultComboBoxModel<>(CardTextLanguage.values())); cboCardText.setSelectedItem(CONFIG.getCardTextLanguage()); - cboCardText.addItemListener((ItemEvent ev) -> { - if (ev.getStateChange() == ItemEvent.SELECTED) { - doTextLanguageChanged(); + cboCardText.addItemListener((final ItemEvent e) -> { + if (e.getStateChange() == ItemEvent.SELECTED) { + if (getCardImageDisplayMode() == CardImageDisplayMode.PRINTED) { + CONFIG.setCardTextLanguage(getCardTextLanguage()); + } } }); } + private void setOptionsState() { + if (getCardImageDisplayMode() == CardImageDisplayMode.PROXY) { + cboCardText.setSelectedItem(CardTextLanguage.ENGLISH); + cboCardText.setEnabled(false); + } else { + cboCardText.setSelectedItem(CONFIG.getCardTextLanguage()); + cboCardText.setEnabled(true); + } + } + private void doDisplayModeChanged() { - setEnabled(false); - firePropertyChange(CP_OPTIONS_CHANGED, true, false); - CONFIG.setCardImageDisplayMode((CardImageDisplayMode) cboDisplayMode.getSelectedItem()); + setOptionsState(); + listener.doOnDisplayModeChanged(); + } + + private void doOnDemandChanged() { + CONFIG.setImagesOnDemand(isOnDemand()); + listener.doOnDemandChanged(); + } + + private void setOnDemandCombo() { + cboOnDemand.setModel(new DefaultComboBoxModel<>(new Boolean[]{true, false})); + cboOnDemand.getModel().setSelectedItem(CONFIG.getImagesOnDemand()); + cboOnDemand.setRenderer(new DefaultListCellRenderer() { + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + setText((Boolean) value == true ? "Yes" : "No"); + setForeground(cboOnDemand.isEnabled() ? getForeground() : Color.GRAY); + return this; + } + }); + cboOnDemand.addItemListener((final ItemEvent e) -> { + if (e.getStateChange() == ItemEvent.SELECTED) { + doOnDemandChanged(); + } + }); } private void setDisplayModeCombo() { - cboDisplayMode.setFont(cboDisplayMode.getFont().deriveFont(Font.BOLD)); cboDisplayMode.setModel(new DefaultComboBoxModel<>(CardImageDisplayMode.values())); cboDisplayMode.getModel().setSelectedItem(CONFIG.getCardImageDisplayMode()); cboDisplayMode.addItemListener((final ItemEvent e) -> { @@ -107,27 +152,48 @@ class OptionsPanel extends JPanel { }); } - @Override - public void setEnabled(boolean b) { - super.setEnabled(b); - for (Component c : getComponents()) { - c.setEnabled(b); - } + private void setDisplaySizeCombo() { + cboDisplaySize.setModel(new DefaultComboBoxModel<>(ImageSizePresets.values())); + cboDisplaySize.getModel().setSelectedItem(CONFIG.getPreferredImageSize()); } - CardImageDisplayMode getDisplayMode() { - return (CardImageDisplayMode) cboDisplayMode.getSelectedItem(); + void addHintSources(HintPanel hintPanel) { + imagesFolderChooser.addHintSources(hintPanel); + hintPanel.addHintSource(cboCardText, String.format("%s
%s

%s", + MText.get(_S4), MText.get(_S5), MText.get(_S11) + )); + hintPanel.addHintSource(cboOnDemand, String.format("%s
%s", + MText.get(_S6), MText.get(_S7) + )); + hintPanel.addHintSource(cboDisplaySize, String.format("%s
%s

%s", + MText.get(_S8), MText.get(_S9), MText.get(_S10) + )); + } + + boolean isOnDemand() { + return (Boolean) cboOnDemand.getSelectedItem(); } CardTextLanguage getCardTextLanguage() { return (CardTextLanguage) cboCardText.getSelectedItem(); } - void addHintSources(HintPanel hintPanel) { - imagesFolderChooser.addHintSources(hintPanel); - hintPanel.addHintSource(cboCardText, String.format("%s
%s", - MText.get(_S4), MText.get(_S5) - )); + CardImageDisplayMode getCardImageDisplayMode() { + return (CardImageDisplayMode) cboDisplayMode.getSelectedItem(); + } + + private ImageSizePresets getPreferredImageSize() { + return (ImageSizePresets) cboDisplaySize.getSelectedItem(); + } + + @Override + public void setEnabled(boolean b) { + super.setEnabled(b); + imagesFolderChooser.setEnabled(b); + cboDisplayMode.setEnabled(b); + cboCardText.setEnabled(b && getCardImageDisplayMode() == CardImageDisplayMode.PRINTED); + cboDisplaySize.setEnabled(b); + cboOnDemand.setEnabled(b); } } diff --git a/src/magic/ui/screen/images/download/PlayablePanel.java b/src/magic/ui/screen/images/download/PlayablePanel.java index 7c32a28a29..0e604dcd4d 100644 --- a/src/magic/ui/screen/images/download/PlayablePanel.java +++ b/src/magic/ui/screen/images/download/PlayablePanel.java @@ -6,17 +6,16 @@ import magic.data.CardDefinitions; import magic.data.GeneralConfig; import magic.model.MagicCardDefinition; import magic.translate.MText; -import magic.ui.CardTextLanguage; @SuppressWarnings("serial") class PlayablePanel extends DownloadPanel { // translatable strings - private static final String _S1 = "Playable"; + private static final String _S1 = "Missing images for playable cards"; private static final String _S2 = "Download"; - PlayablePanel(CardImageDisplayMode aMode, CardTextLanguage aLang, DialogMainPanel aPanel) { - super(aMode, aLang, aPanel); + PlayablePanel(CardImageDisplayMode aMode, DialogMainPanel aPanel) { + super(aMode, aPanel); } @Override diff --git a/src/magic/ui/screen/images/download/UnimplementedPanel.java b/src/magic/ui/screen/images/download/UnimplementedPanel.java index 35793f8326..f4e20d483b 100644 --- a/src/magic/ui/screen/images/download/UnimplementedPanel.java +++ b/src/magic/ui/screen/images/download/UnimplementedPanel.java @@ -6,17 +6,16 @@ import magic.data.CardDefinitions; import magic.data.GeneralConfig; import magic.model.MagicCardDefinition; import magic.translate.MText; -import magic.ui.CardTextLanguage; @SuppressWarnings("serial") class UnimplementedPanel extends DownloadPanel { // translatable strings - private static final String _S1 = "Unimplemented"; + private static final String _S1 = "Missing images for unimplemented cards"; private static final String _S2 = "Download"; - UnimplementedPanel(CardImageDisplayMode aMode, CardTextLanguage aLang, DialogMainPanel aPanel) { - super(aMode, aLang, aPanel); + UnimplementedPanel(CardImageDisplayMode aMode, DialogMainPanel aPanel) { + super(aMode, aPanel); } @Override diff --git a/src/magic/ui/widget/M/MFileLink.java b/src/magic/ui/widget/M/MFileLink.java index 5567cafd92..82be1ba8f1 100644 --- a/src/magic/ui/widget/M/MFileLink.java +++ b/src/magic/ui/widget/M/MFileLink.java @@ -148,6 +148,10 @@ public class MFileLink extends MWidget { label.setFont(aFont); } + public Font getFont() { + return label.getFont(); + } + public void setVisible(boolean b) { label.setVisible(b); }