Add new DownloadImagesScreen with related components and updates, pre-implementation.

master
lodici 2015-12-12 09:26:22 +00:00
parent aaf7fa131b
commit 64040dec28
27 changed files with 1414 additions and 94 deletions

View File

@ -1,51 +1,24 @@
package magic.data;
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.nio.file.StandardCopyOption;
import magic.model.MagicCardDefinition;
import magic.utility.MagicFileSystem;
public class CardImageFile extends DownloadableFile {
private final File file;
private final URL url;
private final String cardName;
public CardImageFile(final MagicCardDefinition cdef) throws MalformedURLException {
file = MagicFileSystem.getCardImageFile(cdef);
url = new URL(cdef.getImageURL());
cardName = cdef.getName();
}
@Override
public String getFilename() {
return file.getName();
}
@Override
public File getLocalFile() {
return file;
}
@Override
public void download(final Proxy proxy) throws IOException {
final File tempFile = new File(file.getParent(), "~" + file.getName());
DownloadableFile.downloadToFile(proxy, url, tempFile);
Files.move(tempFile.toPath(), file.toPath(), StandardCopyOption.REPLACE_EXISTING);
super(
MagicFileSystem.getCardImageFile(cdef),
new URL(cdef.getImageURL())
);
cardName = cdef.getDistinctName();
}
public String getCardName() {
return cardName;
}
@Override
public URL getDownloadUrl() {
return url;
}
}

View File

@ -8,18 +8,37 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.net.Proxy;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import org.apache.commons.io.FileUtils;
public abstract class DownloadableFile {
public abstract void download(final Proxy proxy) throws IOException;
public class DownloadableFile {
public abstract String getFilename();
private final File localFile;
private final URL remoteFile;
public abstract File getLocalFile();
public DownloadableFile(File aFile, URL aUrl) {
this.localFile = aFile;
this.remoteFile = aUrl;
}
public abstract URL getDownloadUrl();
public File getLocalFile() {
return localFile;
}
protected String filenamePrefix = "";
public URL getUrl() {
return remoteFile;
}
public String getFilename() {
return localFile.getName();
}
public void doDownload(final Proxy proxy) throws IOException {
final File tempFile = new File(localFile.getParent(), "~" + localFile.getName());
downloadToFile(proxy, 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) {
@ -33,22 +52,18 @@ public abstract class DownloadableFile {
try (
final OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(file));
final InputStream inputStream = url.openConnection(proxy).getInputStream()) {
final byte[] buffer=new byte[65536];
while (true) {
final int len=inputStream.read(buffer);
if (len<0) {
break;
}
outputStream.write(buffer,0,len);
final byte[] buffer = new byte[65536];
while (true) {
final int len = inputStream.read(buffer);
if (len < 0) {
break;
}
outputStream.write(buffer, 0, len);
}
} catch (final Exception ex) {
file.delete();
throw ex;
}
}
public void setFilenamePrefix(final String prefix) {
filenamePrefix = prefix;
}
}

View File

@ -12,6 +12,7 @@ import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;
import magic.ui.CardTextLanguage;
import magic.ui.duel.animation.AnimationFx;
import magic.ui.message.MessageStyle;
import magic.utility.MagicFileSystem;
@ -73,6 +74,7 @@ public class GeneralConfig {
private static final String LOG_MESSAGE_STYLE = "logMessageStyle";
private static final String ANIMATION_FLAGS = "animationFlags";
private static final String PREF_IMAGE_SIZE = "preferredImageSize";
private static final String CARD_TEXT_LANG = "cardTextLanguage";
private static final int DEFAULT_LEFT=-1;
private static final int DEFAULT_TOP=0;
@ -160,6 +162,7 @@ public class GeneralConfig {
private String translation = DEFAULT_TRANSLATION;
private MessageStyle logMessageStyle = MessageStyle.PLAIN;
private String preferredImageSize = DEFAULT_PREF_IMAGE_SIZE;
private CardTextLanguage cardTextLanguage = CardTextLanguage.ENGLISH;
private GeneralConfig() { }
@ -630,6 +633,7 @@ public class GeneralConfig {
logMessageStyle = MessageStyle.valueOf(properties.getProperty(LOG_MESSAGE_STYLE, MessageStyle.PLAIN.name()));
AnimationFx.setFlags(Integer.parseInt(properties.getProperty(ANIMATION_FLAGS, "" + AnimationFx.getFlags())));
preferredImageSize = properties.getProperty(PREF_IMAGE_SIZE, DEFAULT_PREF_IMAGE_SIZE);
cardTextLanguage = CardTextLanguage.valueOf(properties.getProperty(CARD_TEXT_LANG, CardTextLanguage.ENGLISH.name()));
}
public void load() {
@ -682,6 +686,7 @@ public class GeneralConfig {
properties.setProperty(LOG_MESSAGE_STYLE, logMessageStyle.name());
properties.setProperty(ANIMATION_FLAGS, String.valueOf(AnimationFx.getFlags()));
properties.setProperty(PREF_IMAGE_SIZE, preferredImageSize);
properties.setProperty(CARD_TEXT_LANG, cardTextLanguage.name());
}
public void save() {
@ -714,4 +719,12 @@ public class GeneralConfig {
this.preferredImageSize = s;
}
public CardTextLanguage getCardTextLanguage() {
return cardTextLanguage;
}
public void setCardTextLanguage(CardTextLanguage aLang) {
this.cardTextLanguage = aLang;
}
}

View File

@ -5,42 +5,13 @@ import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.Proxy;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import magic.data.DownloadableFile;
public class DownloadableJsonFile extends DownloadableFile {
private final URL url;
private final File file;
public DownloadableJsonFile(final String url, final File jsonFile) throws MalformedURLException {
this.url = new URL(url);
file = jsonFile;
}
@Override
public void download(Proxy proxy) throws IOException {
final File tempFile = new File(file.getParent(), "~" + file.getName());
DownloadableFile.downloadToFile(proxy, url, tempFile);
Files.move(tempFile.toPath(), file.toPath(), StandardCopyOption.REPLACE_EXISTING);
}
@Override
public String getFilename() {
return file.getName();
}
@Override
public File getLocalFile() {
return file;
}
@Override
public URL getDownloadUrl() {
return url;
super(jsonFile, new URL(url));
}
public static String getJsonString(final File jsonFile) throws IOException {
@ -56,5 +27,4 @@ public class DownloadableJsonFile extends DownloadableFile {
}
}
}

View File

@ -22,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.download(GeneralConfig.getInstance().getProxy());
downloadFile.doDownload(GeneralConfig.getInstance().getProxy());
if (jsonFile.length() == 0) {
System.err.println("new version json file is empty!");
return false;

View File

@ -30,7 +30,7 @@ public final class FiremindJsonReader {
try {
final DownloadableJsonFile downloadFile =
new DownloadableJsonFile("https://www.firemind.ch/decks/top.json", jsonFile);
downloadFile.download(GeneralConfig.getInstance().getProxy());
downloadFile.doDownload(GeneralConfig.getInstance().getProxy());
} catch (IOException ex) {
System.err.println("Download of json file failed : " + ex.getMessage());
}

View File

@ -0,0 +1,39 @@
package magic.ui;
public enum CardTextLanguage {
ENGLISH("English", "en"),
// Magarena translations
PORTUGUESE("Português", "pt"),
RUSSIAN("Русский", "ru"),
// other languages offered by magiccards.info.
GERMAN("Deutsch", "de"),
SPANISH("Español", "es"),
FRENCH("Français", "fr"),
ITALIAN("Italiano", "it"),
CHINESE("简体中文", "cn"),
JAPANESE("日本語", "jp"),
TAIWANESE("繁體中文", "tw")
;
private final String caption;
private final String mcardsLangCode; // language code used by magiccards.info in image urls.
private CardTextLanguage(String aCaption, String aLangCode) {
this.caption = aCaption;
this.mcardsLangCode = aLangCode;
}
@Override
public String toString() {
return caption;
}
public String getMagicCardsCode() {
return mcardsLangCode;
}
public boolean isEnglish() {
return this == ENGLISH;
}
}

View File

@ -0,0 +1,49 @@
package magic.ui;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import magic.utility.MagicFileSystem;
public class MagicLogFile {
private boolean isError = false;
private final File logFile;
public MagicLogFile(String aLogName) {
final Path logsPath = MagicFileSystem.getDataPath(MagicFileSystem.DataPath.LOGS);
logFile = logsPath.resolve(aLogName + ".log").toFile();
}
public void deleteLogFileIfExists() throws IOException {
if (!isError) {
Files.deleteIfExists(logFile.toPath());
}
}
public void log(String msg) throws IOException {
if (!isError) {
try (
FileWriter fw = new FileWriter(logFile, true);
BufferedWriter bw = new BufferedWriter(fw);
PrintWriter out = new PrintWriter(bw)) {
out.println(msg);
} catch (IOException ex) {
isError = true;
throw new IOException("Logging switched off (restart Magarena to enable) : " + ex.getMessage(), ex);
}
}
}
public void log(String msg, CardTextLanguage lang, URL cardUrl) throws IOException {
log(String.format("%s %s %s",
lang != CardTextLanguage.ENGLISH ? lang.getMagicCardsCode() : " ",
msg,
cardUrl != null ? "(" + cardUrl.toExternalForm() + ")" : ""));
}
}

View File

@ -29,6 +29,7 @@ import magic.ui.screen.DeckEditorScreen;
import magic.ui.screen.DeckTiledCardsScreen;
import magic.ui.screen.DeckViewScreen;
import magic.ui.screen.DecksScreen;
import magic.ui.screen.DownloadImagesScreen;
import magic.ui.screen.DuelDecksScreen;
import magic.ui.screen.DuelGameScreen;
import magic.ui.screen.GameLogScreen;
@ -55,6 +56,7 @@ public final class ScreenController {
private static MagicFrame mainFrame = null;
private static final Stack<AbstractScreen> screens = new Stack<>();
private static AbstractScreen hiddenScreen;
public static MagicFrame getMainFrame() {
if (mainFrame == null && java.awt.GraphicsEnvironment.isHeadless() == false) {
@ -190,6 +192,10 @@ public final class ScreenController {
new AboutDialog(getMainFrame());
}
public static void showDownloadImagesScreen() {
showScreen(new DownloadImagesScreen());
}
public static void showPreferencesDialog() {
final PreferencesDialog dialog = new PreferencesDialog(getMainFrame(), isDuelActive());
if (dialog.isRestartRequired()) {
@ -225,9 +231,14 @@ public final class ScreenController {
}
}
private static void showScreen(final AbstractScreen screen) {
private static void showScreen(AbstractScreen screen) {
if (hiddenScreen != null && hiddenScreen.getClass().getName().equals(screen.getClass().getName())) {
screen = hiddenScreen;
hiddenScreen = null;
}
setMainFrameScreen(screen);
screens.push(screen);
screen.setVisible(true);
screen.requestFocus();
}
@ -274,4 +285,14 @@ public final class ScreenController {
return false;
}
public static void hideActiveScreen() {
if (hiddenScreen == null) {
hiddenScreen = screens.pop();
hiddenScreen.setVisible(false);
showScreen(screens.pop());
} else {
throw new RuntimeException("A screen is already hidden - only one allowed at a time!");
}
}
}

View File

@ -2,8 +2,11 @@ package magic.ui;
import java.awt.Desktop;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
public class URLUtils {
@ -35,4 +38,37 @@ public class URLUtils {
use.printStackTrace();
}
}
/**
* Returns a {@code magiccards.info} image url for a given non-English language code.
*/
public static URL getAlternateMagicCardsImageUrl(URL defaultUrl, CardTextLanguage lang) throws MalformedURLException {
final String BASE = "/magiccards.info/scans/";
final String TARGET = BASE + "en/";
final String s = defaultUrl.toExternalForm();
return s.contains(TARGET)
? new URL(s.replaceAll(TARGET, BASE + lang.getMagicCardsCode() + "/"))
: null;
}
/**
* Quickly checks to see whether URL is reachable.
*/
public static boolean isUrlValid(final URL url) {
if (url == null)
return false;
try {
final HttpURLConnection huc = (HttpURLConnection) url.openConnection();
huc.setRequestMethod("HEAD");
huc.setConnectTimeout(2000);
final int responseCode = huc.getResponseCode();
return responseCode == HttpURLConnection.HTTP_OK;
} catch (IOException ex) {
return false;
}
}
}

View File

@ -0,0 +1,18 @@
package magic.ui.dialog.button;
import magic.data.MagicIcon;
import magic.ui.MagicImages;
import magic.translate.UiString;
@SuppressWarnings("serial")
public class CloseButton extends MagicDialogButton {
// translatable strings
private static final String _S1 = "Close";
public CloseButton() {
super(UiString.get(_S1));
setIcon(MagicImages.getIcon(MagicIcon.BANNED_ICON));
}
}

View File

@ -0,0 +1,198 @@
package magic.ui.image.download;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import magic.data.MagicIcon;
import magic.translate.UiString;
import magic.ui.MagicImages;
import magic.ui.URLUtils;
import magic.ui.dialog.button.CloseButton;
import net.miginfocom.swing.MigLayout;
@SuppressWarnings("serial")
class DialogMainPanel extends JPanel implements PropertyChangeListener {
static final String CP_CLOSE = "b0fbb0a7";
static final String CP_RUN_BACKGROUND = "a88997e6";
// translatable strings
private static final String _S3 = "Run in background...";
private final JButton backgroundButton;
private final OptionsPanel optionsPanel;
private final List<DownloadPanel> downloadPanels = new ArrayList<>();
private final ErrorPanel errorPanel = new ErrorPanel();
private final ButtonsPanel buttonsPanel;
DialogMainPanel() {
optionsPanel = new OptionsPanel();
optionsPanel.setEnabled(false);
optionsPanel.addPropertyChangeListener(OptionsPanel.CP_OPTIONS_CHANGED,
(e) -> { refreshDownloadList(); }
);
backgroundButton = new JButton(UiString.get(_S3));
backgroundButton.setFocusable(false);
backgroundButton.addActionListener((a) -> { doRunInBackground(); });
buttonsPanel = new ButtonsPanel();
setDownloadPanels();
setLookAndFeel();
refreshLayout();
}
private void doRunInBackground() {
firePropertyChange(CP_RUN_BACKGROUND, true, false);
}
private void refreshDownloadList() {
final DownloadMode mode = optionsPanel.getDownloadMode();
for (DownloadPanel panel : downloadPanels) {
panel.refreshDownloadList(mode);
}
}
private void setDownloadPanels() {
downloadPanels.add(getPlayableDownloaderPanel());
downloadPanels.add(getUnimplementedDownloaderPanel());
}
private void refreshLayout() {
setLayout(new MigLayout("flowy, gap 0, insets 2 6 6 6"));
add(optionsPanel, "w 100%, gapbottom 6");
add(getDownloadPanel(), "w 100%");
add(errorPanel, "w 100%, h 100%");
add(buttonsPanel, "w 100%, h 30!, pushy, aligny bottom");
}
private void setLookAndFeel() {
backgroundButton.setEnabled(false);
}
private JPanel getDownloadPanel() {
final JPanel panel = new JPanel(new MigLayout("flowy, insets 6 0 6 0, gapy 0"));
panel.setBorder(BorderFactory.createMatteBorder(1, 0, 1, 0, Color.GRAY));
for (DownloadPanel downloadPanel : downloadPanels) {
panel.add(downloadPanel, "w 100%");
}
return panel;
}
private DownloadPanel getPlayableDownloaderPanel() {
final DownloadPanel playableDownloaderPanel = new PlayablePanel(
optionsPanel.getDownloadMode(),
optionsPanel.getCardTextLanguage(),
this
);
playableDownloaderPanel.addPropertyChangeListener(DownloadPanel.CP_STATE_CHANGED, this);
return playableDownloaderPanel;
}
private DownloadPanel getUnimplementedDownloaderPanel() {
final DownloadPanel unimplementedDownloaderPanel = new UnimplementedPanel(
optionsPanel.getDownloadMode(),
optionsPanel.getCardTextLanguage(),
this
);
unimplementedDownloaderPanel.addPropertyChangeListener(DownloadPanel.CP_STATE_CHANGED, this);
return unimplementedDownloaderPanel;
}
private void updateComponentState() {
boolean isScanning = false;
boolean isDownloading = false;
for (DownloadPanel panel : downloadPanels) {
isScanning |= panel.getState() == DownloadState.SCANNING;
isDownloading |= panel.getState() == DownloadState.DOWNLOADING;
}
optionsPanel.setEnabled(!isScanning && !isDownloading);
buttonsPanel.setIsDownloading(isDownloading);
}
boolean isBusy() {
for (DownloadPanel panel : downloadPanels) {
if (panel.getState() == DownloadState.SCANNING ||
panel.getState() == DownloadState.DOWNLOADING) {
return true;
}
}
return false;
}
private class ButtonsPanel extends JPanel {
private final JButton closeButton;
ButtonsPanel() {
closeButton = new CloseButton();
closeButton.setFocusable(false);
closeButton.addActionListener(getCancelAction());
final JButton helpButton = new JButton();
helpButton.setIcon(MagicImages.getIcon(MagicIcon.MISSING_ICON));
helpButton.setFocusable(false);
helpButton.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
URLUtils.openURL(URLUtils.URL_WIKI + "UIDownloadImages");
}
});
setLayout(new MigLayout("insets 0, alignx right, aligny bottom"));
add(helpButton);
add(backgroundButton, "w 100%");
add(closeButton);
}
void setIsDownloading(boolean b) {
closeButton.setEnabled(b == false);
backgroundButton.setEnabled(b);
}
}
private void doCancelAndClose() {
for (DownloadPanel panel : downloadPanels) {
panel.doCancel();
}
firePropertyChange(CP_CLOSE, true, false);
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(DownloadPanel.CP_STATE_CHANGED)) {
updateComponentState();
}
}
synchronized void setMessage(final String message) {
SwingUtilities.invokeLater(() -> {
errorPanel.setErrorText(message + "\n");
if (!errorPanel.isVisible()) {
errorPanel.setVisible(true);
}
});
}
AbstractAction getCancelAction() {
return new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
if (!backgroundButton.isEnabled()) {
doCancelAndClose();
}
}
};
}
}

View File

@ -0,0 +1,79 @@
package magic.ui.image.download;
import java.awt.Color;
import java.awt.Dimension;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import magic.ui.ScreenController;
import magic.ui.theme.Theme;
import magic.ui.utility.MagicStyle;
import magic.ui.widget.FontsAndBorders;
import net.miginfocom.swing.MigLayout;
@SuppressWarnings("serial")
public class DownloadDialogPanel extends JPanel implements PropertyChangeListener {
private final DialogMainPanel mainPanel;
public DownloadDialogPanel() {
setPreferredSize(new Dimension(440, 460));
setBorder(
BorderFactory.createCompoundBorder(
BorderFactory.createLineBorder(Color.DARK_GRAY),
BorderFactory.createMatteBorder(0, 8, 8, 8, MagicStyle.getTheme().getColor(Theme.COLOR_TITLE_BACKGROUND)))
);
mainPanel = getMainPanel();
setLayout(new MigLayout("flowy, insets 0"));
add(getDialogCaptionLabel(), "w 100%, h 26!");
add(mainPanel, "w 100%, h 100%");
}
private DialogMainPanel getMainPanel() {
final DialogMainPanel panel = new DialogMainPanel();
panel.addPropertyChangeListener(DialogMainPanel.CP_CLOSE, this);
panel.addPropertyChangeListener(DialogMainPanel.CP_RUN_BACKGROUND, this);
return panel;
}
private JLabel getDialogCaptionLabel() {
final JLabel lbl = new JLabel("Download card images");
lbl.setOpaque(true);
lbl.setBackground(MagicStyle.getTheme().getColor(Theme.COLOR_TITLE_BACKGROUND));
lbl.setForeground(MagicStyle.getTheme().getColor(Theme.COLOR_TITLE_FOREGROUND));
lbl.setFont(FontsAndBorders.FONT1.deriveFont(14f));
lbl.setHorizontalAlignment(SwingConstants.CENTER);
return lbl;
}
private void doCloseScreen() {
ScreenController.closeActiveScreen(false);
}
private void doHideScreen() {
ScreenController.hideActiveScreen();
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
switch (evt.getPropertyName()) {
case DialogMainPanel.CP_CLOSE:
doCloseScreen();
break;
case DialogMainPanel.CP_RUN_BACKGROUND:
doHideScreen();
break;
}
}
public boolean isBusy() {
return mainPanel.isBusy();
}
}

View File

@ -0,0 +1,18 @@
package magic.ui.image.download;
enum DownloadMode {
MISSING("Missing images"),
ALL("All images");
private final String desc;
private DownloadMode(String aDesc) {
this.desc = aDesc;
}
@Override
public String toString() {
return desc;
}
}

View File

@ -0,0 +1,229 @@
package magic.ui.image.download;
import java.awt.Font;
import java.io.IOException;
import java.net.Proxy;
import java.util.Collection;
import java.util.Date;
import java.util.stream.Stream;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import magic.data.CardImageFile;
import magic.data.DownloadableFile;
import magic.data.ImagesDownloadList;
import magic.data.GeneralConfig;
import magic.data.MagicIcon;
import magic.model.MagicCardDefinition;
import magic.ui.MagicImages;
import magic.translate.UiString;
import magic.ui.CardTextLanguage;
import net.miginfocom.swing.MigLayout;
@SuppressWarnings("serial")
abstract class DownloadPanel extends JPanel implements IScanListener, IDownloadListener {
static final String CP_STATE_CHANGED = "7b40b0dd";
// translatable strings
private static final String _S1 = "Cancel";
protected final GeneralConfig CONFIG = GeneralConfig.getInstance();
private final MigLayout migLayout = new MigLayout();
protected final JLabel captionLabel = getCaptionLabel(getProgressCaption());
protected final JButton downloadButton = new JButton();
private final JButton cancelButton = new JButton(UiString.get(_S1));
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 DownloadMode downloadMode = DownloadMode.MISSING;
private CardTextLanguage textLanguage = CardTextLanguage.ENGLISH;
private final DialogMainPanel mainPanel;
protected abstract String getProgressCaption();
protected abstract String getDownloadButtonCaption();
DownloadPanel(DownloadMode aMode, CardTextLanguage aLang, DialogMainPanel aPanel) {
this.downloadMode = aMode;
this.textLanguage = aLang;
this.mainPanel = aPanel;
setLookAndFeel();
refreshLayout();
setActions();
buildDownloadImagesList();
}
DownloadState getState() {
return downloaderState;
}
private void doRunImageDownloadWorker() {
setDownloadingState();
imagesDownloader = new DownloadWorker(this, files, textLanguage, downloadMode);
imagesDownloader.execute();
notifyStatusChanged(DownloadState.DOWNLOADING);
}
private void setActions() {
downloadButton.addActionListener(action -> { doRunImageDownloadWorker(); });
cancelButton.addActionListener(action -> { doCancelImageDownloadWorker(); });
}
void doCancel() {
isCancelled = true;
doCancelImageDownloadWorker();
doCancelImagesScanner();
}
private void doCancelImageDownloadWorker() {
if (imagesDownloader != null && !imagesDownloader.isCancelled() && !imagesDownloader.isDone()) {
imagesDownloader.cancel(true);
setButtonState(false);
}
}
private void doCancelImagesScanner() {
if (imagesScanner != null && !imagesScanner.isCancelled() && !imagesScanner.isDone()) {
imagesScanner.cancel(true);
}
}
@Override
public final void buildDownloadImagesList() {
if (imagesScanner != null && !imagesScanner.isDone()) {
System.out.println("cancelling images scanner");
imagesScanner.cancel(true);
}
if (!isCancelled) {
captionLabel.setIcon(MagicImages.getIcon(MagicIcon.BUSY16));
captionLabel.setText(getProgressCaption());
imagesScanner = new ScanWorker(this, downloadMode);
imagesScanner.execute();
downloadButton.setEnabled(false);
notifyStatusChanged(DownloadState.SCANNING);
}
}
private void resetProgressBar() {
progressBar.setMinimum(0);
progressBar.setMaximum(files.size());
progressBar.setValue(0);
}
@Override
public void setButtonState(final boolean isDownloading) {
downloadButton.setVisible(!isDownloading);
cancelButton.setVisible(isDownloading);
refreshLayout();
}
private void setDownloadingState() {
setButtonState(true);
resetProgressBar();
captionLabel.setIcon(MagicImages.getIcon(MagicIcon.BUSY16));
}
private void refreshLayout() {
removeAll();
migLayout.setLayoutConstraints("flowx, insets 0, gap 0");
add(progressBar, "w 100%, h 26!");
add(downloadButton.isVisible() ? downloadButton : cancelButton, "w 100!");
}
private void setLookAndFeel() {
// Layout manager.
setLayout(migLayout);
// download button
downloadButton.setEnabled(false);
downloadButton.setText(getDownloadButtonCaption());
// progress bar
progressBar.setLayout(new MigLayout("insets 0 8 0 0, aligny center"));
progressBar.add(captionLabel, "w 100%, h 100%");
progressBar.setStringPainted(false);
}
private JLabel getCaptionLabel(final String text) {
final ImageIcon ii = MagicImages.getIcon(MagicIcon.BUSY16);
final JLabel lbl = new JLabel(ii);
lbl.setText(text);
lbl.setHorizontalAlignment(SwingConstants.LEFT);
lbl.setHorizontalTextPosition(SwingConstants.LEADING);
lbl.setOpaque(false);
lbl.setFont(lbl.getFont().deriveFont(Font.BOLD));
return lbl;
}
@Override
public void notifyStatusChanged(final DownloadState newState) {
assert SwingUtilities.isEventDispatchThread();
final DownloadState oldState = downloaderState;
downloaderState = newState;
firePropertyChange(CP_STATE_CHANGED, oldState, newState);
}
@Override
public void doScannerFinished(final ImagesDownloadList aList) {
files = aList;
downloadButton.setEnabled(files != null && files.size() > 0);
captionLabel.setIcon(null);
captionLabel.setText(String.format("%s = %d",
getProgressCaption(),
files == null ? 0 : files.size())
);
}
void refreshDownloadList(DownloadMode aType) {
this.downloadMode = aType;
buildDownloadImagesList();
}
@Override
public void setMessage(final String message) {
mainPanel.setMessage(message);
}
@Override
public void showProgress(int count, int total) {
progressBar.setValue(count);
captionLabel.setText(String.format("%s = %d",
getProgressCaption(),
total - getCustomCount(count))
);
}
@Override
public void resetProgress() {
progressBar.setValue(0);
progressBar.setString(null);
}
protected String doFileDownloadAndGetName(final DownloadableFile file, final Proxy proxy) throws IOException {
file.doDownload(proxy);
if (file instanceof CardImageFile) {
return ((CardImageFile) file).getCardName();
} else {
return "";
}
}
protected int getCustomCount(int countInteger) {
return countInteger;
}
protected static Stream<MagicCardDefinition> getCards(Collection<MagicCardDefinition> cards, Date aDate) {
return cards.stream()
.filter(MagicCardDefinition::hasImageUrl)
.filter(card -> card.isImageUpdatedAfter(aDate) || card.isImageFileMissing());
}
}

View File

@ -0,0 +1,7 @@
package magic.ui.image.download;
enum DownloadState {
STOPPED,
SCANNING,
DOWNLOADING;
}

View File

@ -0,0 +1,228 @@
package magic.ui.image.download;
import magic.ui.CardTextLanguage;
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;
import java.util.List;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
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.ui.URLUtils;
import magic.ui.MagicLogFile;
import magic.utility.MagicSystem;
class DownloadWorker extends SwingWorker<Void, Integer> {
private static final MagicLogFile missingLog = new MagicLogFile("downloaded-images");
private final Proxy proxy;
private final ImagesDownloadList downloadList;
private final IDownloadListener listener;
private final CardTextLanguage textLanguage;
private final DownloadMode downloadMode;
private boolean updateDownloadDate = true;
private boolean isLogging = true;
DownloadWorker(
IDownloadListener aListener,
ImagesDownloadList downloadList,
CardTextLanguage aLanguage,
DownloadMode aDownloadMode) {
this.listener = aListener;
this.downloadList = downloadList;
this.textLanguage = aLanguage;
this.downloadMode = aDownloadMode;
this.proxy = GeneralConfig.getInstance().getProxy();
}
@Override
protected Void doInBackground() {
doDownloadImages(textLanguage);
return null;
}
@Override
protected void done() {
try {
get();
} catch (ExecutionException | InterruptedException ex) {
throw new RuntimeException(ex);
} catch (CancellationException ex) {
System.err.println("ImageDownloadWorker cancelled.");
}
listener.setButtonState(false);
resetProgressBar();
magic.ui.CachedImagesProvider.getInstance().clearCache();
listener.buildDownloadImagesList();
}
@Override
protected void process(List<Integer> chunks) {
final int countInteger = chunks.get(chunks.size() - 1);
if (!isCancelled()) {
listener.showProgress(countInteger, downloadList.size());
}
}
private boolean isLoggingOn() {
return isLogging && MagicSystem.isDevMode() && downloadMode == DownloadMode.MISSING;
}
/**
* Experimental, currently only available in devMode and missing mode.
*/
private void doLog(String cardName, CardTextLanguage aLang, URL cardUrl) {
if (isLoggingOn()) {
synchronized (missingLog) {
try {
missingLog.log(cardName, aLang, cardUrl);
} catch (IOException ex) {
System.err.println("doLog: " + ex);
isLogging = false;
}
}
}
}
/**
* Initializes log files for capturing useful info (DEVMODE ONLY!).
*/
private void initializeLogFiles() {
if (isLoggingOn()) {
synchronized (missingLog) {
try {
missingLog.deleteLogFileIfExists();
missingLog.log("# " + LocalDateTime.now());
missingLog.log("#");
} catch (IOException ex) {
System.err.println("initializeLogFiles: " + ex);
isLogging = false;
}
}
}
}
/**
* 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 URLUtils.getAlternateMagicCardsImageUrl(aFile.getUrl(), textLang);
} catch (MalformedURLException ex) {
listener.setMessage(String.format("%s [%s]", ex.toString(), aFile.getUrl()));
return null;
}
}
/**
* 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));
return false;
}
return true;
}
private boolean downloadAlternateCardImage(final CardImageFile aFile, CardTextLanguage aLang) {
final URL altUrl = getAlternateUrl(aFile, aLang);
if (URLUtils.isUrlValid(altUrl)) {
if (tryAlternateDownload(new DownloadableFile(aFile.getLocalFile(), altUrl), aLang)) {
doLog(aFile.getCardName(), aLang, altUrl);
return true;
}
}
return false;
}
/**
* Attempts to download default card image.
* If it fails displays reason in error log panel.
*/
private boolean tryDefaultDownload(final DownloadableFile aFile) {
try {
aFile.doDownload(proxy);
} catch (IOException ex) {
listener.setMessage(String.format("%s [%s]", ex.toString(), aFile.getFilename()));
return false;
}
return true;
}
private void downloadDefaultCardImage(final CardImageFile aFile) {
if (tryDefaultDownload(aFile)) {
doLog(aFile.getCardName(), CardTextLanguage.ENGLISH, null);
}
}
private void doDownloadImages(CardTextLanguage textLang) {
initializeLogFiles();
int fileCount = 0;
for (DownloadableFile dFile : downloadList) {
final CardImageFile imageFile = (CardImageFile) dFile;
if (deleteLocalImageFileIfMissing(imageFile) == false)
continue; // with next DownloadableFile.
if (textLang.isEnglish() || !downloadAlternateCardImage(imageFile, textLang)) {
downloadDefaultCardImage(imageFile);
}
fileCount++;
if (isCancelled()) {
break;
} else {
publish(new Integer(fileCount));
}
}
if (updateDownloadDate) {
listener.doCustomActionAfterDownload();
}
}
/**
* If downloading missing images but local image file already exists then download was
* triggered by 'image_updated'. If unable to delete image file so that it becomes
* "missing" do not update 'imageDownloaderRunDate' so that image update remains pending.
*/
private boolean deleteLocalImageFileIfMissing(DownloadableFile dFile) {
if (downloadMode == DownloadMode.MISSING) {
try {
Files.deleteIfExists(dFile.getLocalFile().toPath());
} catch (IOException ex) {
updateDownloadDate = false;
listener.setMessage(String.format("%s [%s]", ex.toString(), dFile.getFilename()));
return false;
}
}
return true;
}
private void resetProgressBar() {
assert SwingUtilities.isEventDispatchThread();
listener.resetProgress();
}
}

View File

@ -0,0 +1,83 @@
package magic.ui.image.download;
import java.awt.Color;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import magic.translate.UiString;
import magic.ui.ScreenController;
import magic.ui.widget.FontsAndBorders;
import net.miginfocom.swing.MigLayout;
@SuppressWarnings("serial")
class ErrorPanel extends JPanel {
private static final String _S4 = "Copy to clipboard";
private static final String _S5 = "Error details have been copied to the clipboard.";
private final JTextArea textArea;
ErrorPanel() {
final JButton copyButton = new JButton(UiString.get(_S4));
copyButton.setEnabled(false);
textArea = new JTextArea();
textArea.setEditable(false);
textArea.setForeground(Color.red);
textArea.setFont(FontsAndBorders.FONT_README.deriveFont(11.0f));
textArea.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent e) {
copyButton.setEnabled(!isEmpty());
}
@Override
public void removeUpdate(DocumentEvent e) {
copyButton.setEnabled(!isEmpty());
}
@Override
public void changedUpdate(DocumentEvent e) {
copyButton.setEnabled(!isEmpty());
}
private boolean isEmpty() {
return textArea.getText().trim().isEmpty();
}
});
final JScrollPane scrollPane = new JScrollPane(textArea);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scrollPane.setBorder(FontsAndBorders.BLACK_BORDER);
copyButton.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
final Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
final StringSelection textSelection = new StringSelection(textArea.getText());
clip.setContents(textSelection, null);
ScreenController.showInfoMessage(UiString.get(_S5));
}
});
setVisible(false);
setLayout(new MigLayout("flowy, gap 0, insets 10 0 10 0"));
add(scrollPane, "w 100%, h 100%");
add(copyButton, "w 100%");
}
void setErrorText(String text) {
textArea.append(text);
}
}

View File

@ -0,0 +1,10 @@
package magic.ui.image.download;
interface IDownloadListener {
void setMessage(final String message);
void setButtonState(final boolean isDownloading);
void doCustomActionAfterDownload();
void buildDownloadImagesList();
void showProgress(int count, int total);
void resetProgress();
}

View File

@ -0,0 +1,11 @@
package magic.ui.image.download;
import java.util.stream.Stream;
import magic.data.ImagesDownloadList;
import magic.model.MagicCardDefinition;
interface IScanListener {
Stream<MagicCardDefinition> getCards(final DownloadMode aType);
void doScannerFinished(final ImagesDownloadList aList);
void notifyStatusChanged(final DownloadState newState);
}

View File

@ -0,0 +1,123 @@
package magic.ui.image.download;
import java.awt.Component;
import java.awt.Font;
import java.awt.event.ItemEvent;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import magic.data.GeneralConfig;
import magic.translate.UiString;
import magic.ui.CardTextLanguage;
import magic.ui.widget.DirectoryChooser;
import net.miginfocom.swing.MigLayout;
@SuppressWarnings("serial")
class OptionsPanel extends JPanel {
static final String CP_OPTIONS_CHANGED = "1b7206a7";
private final GeneralConfig CONFIG = GeneralConfig.getInstance();
private final JComboBox<CardTextLanguage> cboCardText = new JComboBox<>();
private final JComboBox<DownloadMode> cboDownloadMode = new JComboBox<>();
private final DirectoryChooser imagesFolderChooser;
OptionsPanel() {
imagesFolderChooser = getImagesFolderChooser();
setDownloadModeCombo();
setLayout(new MigLayout("wrap 2, insets 0", "[right][]"));
add(new JLabel(UiString.get("Images folder:")));
add(imagesFolderChooser, "w 100%");
add(new JLabel(UiString.get("Card text:")));
add(getCardTextCombo());
add(getBoldLabel(UiString.get("Download mode:")));
add(cboDownloadMode);
}
private JLabel getBoldLabel(String text) {
final JLabel lbl = new JLabel(text);
lbl.setFont(lbl.getFont().deriveFont(Font.BOLD));
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);
}
private DirectoryChooser getImagesFolderChooser() {
final DirectoryChooser chooser = new DirectoryChooser(CONFIG.getCardImagesPath());
chooser.setFocusable(false);
chooser.addPropertyChangeListener(DirectoryChooser.CP_FOLDER_CHANGED, (e) -> {
doImageFolderChanged();
});
return chooser;
}
private void doTextLanguageChanged() {
cboCardText.setToolTipText(getCardTextLanguage().isEnglish()
? ""
: "<html><b>Preferred Language</b><br>Downloads selected translation of card if available.</html>"
);
saveSettings();
}
private JComboBox<CardTextLanguage> getCardTextCombo() {
cboCardText.setModel(new DefaultComboBoxModel<>(CardTextLanguage.values()));
cboCardText.setSelectedItem(CONFIG.getCardTextLanguage());
cboCardText.addItemListener((ItemEvent ev) -> {
if (ev.getStateChange() == ItemEvent.SELECTED) {
doTextLanguageChanged();
}
});
return cboCardText;
}
private void doDownloadModeChanged() {
setEnabled(false);
firePropertyChange(CP_OPTIONS_CHANGED, true, false);
}
private void setDownloadModeCombo() {
cboDownloadMode.setFont(cboDownloadMode.getFont().deriveFont(Font.BOLD));
cboDownloadMode.setModel(new DefaultComboBoxModel<>(DownloadMode.values()));
cboDownloadMode.getModel().setSelectedItem(cboDownloadMode.getItemAt(0));
cboDownloadMode.addItemListener((final ItemEvent e) -> {
if (e.getStateChange() == ItemEvent.SELECTED) {
doDownloadModeChanged();
}
});
}
@Override
public void setEnabled(boolean b) {
super.setEnabled(b);
for (Component c : getComponents()) {
c.setEnabled(b);
}
}
JComboBox<DownloadMode> getDownloadTypeCombo() {
return cboDownloadMode;
}
DownloadMode getDownloadMode() {
return (DownloadMode) cboDownloadMode.getSelectedItem();
}
CardTextLanguage getCardTextLanguage() {
return (CardTextLanguage) cboCardText.getSelectedItem();
}
}

View File

@ -0,0 +1,48 @@
package magic.ui.image.download;
import java.util.Date;
import java.util.stream.Stream;
import magic.data.CardDefinitions;
import magic.data.GeneralConfig;
import magic.model.MagicCardDefinition;
import magic.translate.UiString;
import magic.ui.CardTextLanguage;
@SuppressWarnings("serial")
class PlayablePanel extends DownloadPanel {
// translatable strings
private static final String _S1 = "Playable";
private static final String _S2 = "Download";
PlayablePanel(DownloadMode aMode, CardTextLanguage aLang, DialogMainPanel aPanel) {
super(aMode, aLang, aPanel);
}
@Override
protected String getProgressCaption() {
return UiString.get(_S1);
}
@Override
public Stream<MagicCardDefinition> getCards(final DownloadMode aType) {
return aType == DownloadMode.ALL
? CardDefinitions.getAllPlayableCardDefs().stream()
: getCards(
CardDefinitions.getAllPlayableCardDefs(),
GeneralConfig.getInstance().getPlayableImagesDownloadDate()
);
}
@Override
protected String getDownloadButtonCaption() {
return UiString.get(_S2);
}
@Override
public void doCustomActionAfterDownload() {
GeneralConfig.getInstance().setPlayableImagesDownloadDate(new Date());
GeneralConfig.getInstance().save();
}
}

View File

@ -0,0 +1,42 @@
package magic.ui.image.download;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import javax.swing.SwingWorker;
import magic.data.ImagesDownloadList;
class ScanWorker extends SwingWorker<ImagesDownloadList, Void> {
private final IScanListener listener;
private final DownloadMode downloadType;
private ImagesDownloadList downloadList;
ScanWorker(final IScanListener aListener, final DownloadMode aType) {
this.listener = aListener;
this.downloadType = aType;
}
@Override
protected ImagesDownloadList doInBackground() throws Exception {
// Speeds up scanning by preventing multiple scanners
// accessing filesystem at the same time.
synchronized (ScanWorker.class) {
return new ImagesDownloadList(listener.getCards(downloadType));
}
}
@Override
protected void done() {
try {
downloadList = get();
} catch (InterruptedException | ExecutionException ex) {
throw new RuntimeException(ex);
} catch (CancellationException ex) {
System.out.println("ImagesScanner cancelled by user!");
}
if (!isCancelled()) {
listener.doScannerFinished(downloadList);
}
listener.notifyStatusChanged(DownloadState.STOPPED);
}
}

View File

@ -0,0 +1,48 @@
package magic.ui.image.download;
import java.util.Date;
import java.util.stream.Stream;
import magic.data.CardDefinitions;
import magic.data.GeneralConfig;
import magic.model.MagicCardDefinition;
import magic.translate.UiString;
import magic.ui.CardTextLanguage;
@SuppressWarnings("serial")
class UnimplementedPanel extends DownloadPanel {
// translatable strings
private static final String _S1 = "Unimplemented";
private static final String _S2 = "Download";
UnimplementedPanel(DownloadMode aMode, CardTextLanguage aLang, DialogMainPanel aPanel) {
super(aMode, aLang, aPanel);
}
@Override
protected String getProgressCaption() {
return UiString.get(_S1);
}
@Override
public Stream<MagicCardDefinition> getCards(final DownloadMode aType) {
return aType == DownloadMode.ALL
? CardDefinitions.getMissingCards().stream()
: getCards(
CardDefinitions.getMissingCards(),
GeneralConfig.getInstance().getMissingImagesDownloadDate()
);
}
@Override
protected String getDownloadButtonCaption() {
return UiString.get(_S2);
}
@Override
public void doCustomActionAfterDownload() {
GeneralConfig.getInstance().setMissingImagesDownloadDate(new Date());
GeneralConfig.getInstance().save();
}
}

View File

@ -0,0 +1,29 @@
package magic.ui.screen;
import javax.swing.JPanel;
import magic.ui.image.download.DownloadDialogPanel;
import net.miginfocom.swing.MigLayout;
@SuppressWarnings("serial")
public class DownloadImagesScreen extends AbstractScreen {
private final DownloadDialogPanel dialogPanel;
public DownloadImagesScreen() {
dialogPanel = new DownloadDialogPanel();
setContent(getContentPanel());
}
private JPanel getContentPanel() {
final JPanel panel = new JPanel(new MigLayout("alignx center, aligny center"));
panel.setOpaque(false);
panel.add(dialogPanel);
return panel;
}
@Override
public boolean isScreenReadyToClose(final AbstractScreen nextScreen) {
return dialogPanel.isBusy() == false;
}
}

View File

@ -1,5 +1,7 @@
package magic.ui.widget;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
@ -23,6 +25,8 @@ import net.miginfocom.swing.MigLayout;
@SuppressWarnings("serial")
public class DirectoryChooser extends JPanel implements MouseListener {
public static final String CP_FOLDER_CHANGED = "imageFolderUChanged";
// translatable strings
private static final String _S1 = "Choose directory...";
private static final String _S3 = "Not enough free space!";
@ -34,7 +38,7 @@ public class DirectoryChooser extends JPanel implements MouseListener {
private final MigLayout layout = new MigLayout();
private final JTextField textField = new JTextField();
private final JButton selectButton = new JButton();
private final Path defaultPath;
private Path defaultPath;
public DirectoryChooser(final Path defaultPath) {
@ -46,19 +50,29 @@ public class DirectoryChooser extends JPanel implements MouseListener {
selectButton.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
final JFileChooser fileChooser = new ImagesDirectoryChooser(defaultPath.toString());
final JFileChooser fileChooser = new ImagesDirectoryChooser(getDefaultPath().toString());
final int action = fileChooser.showOpenDialog(ScreenController.getMainFrame());
if (action == JFileChooser.APPROVE_OPTION) {
final File f = fileChooser.getSelectedFile();
if (MagicFileSystem.directoryContains(MagicFileSystem.INSTALL_PATH, f.toPath())) {
textField.setText(MagicFileSystem.getDataPath(DataPath.IMAGES).toString());
} else {
textField.setText(f.toString());
}
setImagesPath(fileChooser.getSelectedFile());
}
}
});
}
private File getDefaultPath() {
return defaultPath.toFile();
}
private void setImagesPath(final File f) {
if (!f.equals(getDefaultPath())) {
if (MagicFileSystem.directoryContains(MagicFileSystem.INSTALL_PATH, f.toPath())) {
textField.setText(MagicFileSystem.getDataPath(DataPath.IMAGES).toString());
} else {
textField.setText(f.toString());
}
firePropertyChange(CP_FOLDER_CHANGED, defaultPath.toFile(), f);
defaultPath = f.toPath();
}
}
private void setLookAndFeel() {
@ -67,6 +81,7 @@ public class DirectoryChooser extends JPanel implements MouseListener {
textField.setText(defaultPath.toString());
textField.setEditable(false);
textField.addMouseListener(this);
textField.setToolTipText("<html><b>Images folder</b><br>Double-click to open in the default file manager.");
// JButton
selectButton.setText("...");
selectButton.setFont(FontsAndBorders.FONT1);
@ -122,20 +137,24 @@ public class DirectoryChooser extends JPanel implements MouseListener {
public void mousePressed(MouseEvent e) { }
@Override
public void mouseReleased(MouseEvent e) {
if (e.getSource() == textField && e.getButton() == MouseEvent.BUTTON3) {
if (e.getSource() == textField && e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 2) {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
try {
DesktopUtils.openDirectory(textField.getText());
} catch (IOException | IllegalArgumentException e1) {
} catch (IOException | IllegalArgumentException e1) {
ScreenController.showWarningMessage(e1.getMessage());
}
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
}
@Override
public void mouseEntered(MouseEvent e) {
setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
dispatchEvent(e);
}
@Override
public void mouseExited(MouseEvent e) {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
dispatchEvent(e);
}
@ -147,4 +166,18 @@ public class DirectoryChooser extends JPanel implements MouseListener {
}
}
@Override
public void setFocusable(boolean b) {
super.setFocusable(b);
textField.setFocusable(b);
}
@Override
public void setEnabled(boolean b) {
super.setEnabled(b);
for (Component c : getComponents()) {
c.setEnabled(b);
}
}
}

View File

@ -19,7 +19,7 @@ public abstract class MissingImagesDownloadPanel extends ImageDownloadPanel {
@Override
protected String doFileDownloadAndGetName(final DownloadableFile file, final Proxy proxy) throws IOException {
file.download(proxy);
file.doDownload(proxy);
if (file instanceof CardImageFile) {
return ((CardImageFile) file).getCardName();
} else {