Update card image downloading (see #1039).
parent
4a93805b00
commit
f48e2c9740
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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() {}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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() { }
|
||||
}
|
||||
|
|
|
@ -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. <b>Not 100% coverage</b>, 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 = "<b>Not 100% coverage</b>. 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("<b>%s</b><br>%s<br><br><b>%s</b><br>%s<br><br>%s",
|
||||
return String.format("<b>%s</b><br>%s<br><br><b>%s</b><br>%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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<Void, Integer> 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<MagicCardDefinition> getCards(Collection<MagicCardDefinition> 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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<Void, Integer> {
|
||||
|
||||
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<Void, Integer> {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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<Void, Integer> {
|
|||
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<Void, Integer> {
|
|||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
|
|
|
@ -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<CardTextLanguage> cboCardText = new JComboBox<>();
|
||||
private final JComboBox<CardImageDisplayMode> cboDisplayMode = new JComboBox<>();
|
||||
private final DirectoryChooser imagesFolderChooser;
|
||||
private final JComboBox<Boolean> cboOnDemand = new JComboBox<>();
|
||||
private final JComboBox<ImageSizePresets> 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("<b>%s</b><br>%s<br><br><b>%s</b>",
|
||||
MText.get(_S4), MText.get(_S5), MText.get(_S11)
|
||||
));
|
||||
hintPanel.addHintSource(cboOnDemand, String.format("<b>%s</b><br>%s",
|
||||
MText.get(_S6), MText.get(_S7)
|
||||
));
|
||||
hintPanel.addHintSource(cboDisplaySize, String.format("<b>%s</b><br>%s<br><br><b>%s</b>",
|
||||
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("<b>%s</b><br>%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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue