Refactor gui downloaders to be reusable by mobile app

This commit is contained in:
drdev
2014-05-27 05:57:03 +00:00
parent 25305fd6d6
commit df0e320a5f
22 changed files with 443 additions and 321 deletions

View File

@@ -448,4 +448,9 @@ public class GuiDesktop implements IGuiBase {
public void startAltSoundSystem(String filename, boolean isSynchronized) {
new AltSoundSystem(filename, isSynchronized).start();
}
@Override
public void clearImageCache() {
ImageCache.clear();
}
}

View File

@@ -1,92 +0,0 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.download;
import forge.assets.ImageUtil;
import forge.card.CardRules;
import forge.item.PaperCard;
import forge.model.FModel;
import forge.properties.ForgeConstants;
import org.apache.commons.lang3.StringUtils;
import java.io.File;
import java.util.Map;
import java.util.TreeMap;
@SuppressWarnings("serial")
public class GuiDownloadPicturesLQ extends GuiDownloader {
public GuiDownloadPicturesLQ() {
super();
}
@Override
protected final Map<String, String> getNeededImages() {
Map<String, String> downloads = new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER);
for (PaperCard c : FModel.getMagicDb().getCommonCards().getAllCards()) {
addDLObject(c, downloads, false);
if (ImageUtil.hasBackFacePicture(c)) {
addDLObject(c, downloads, true);
}
}
for (PaperCard c : FModel.getMagicDb().getVariantCards().getAllCards()) {
addDLObject(c, downloads, false);
}
// Add missing tokens to the list of things to download.
addMissingItems(downloads, ForgeConstants.IMAGE_LIST_TOKENS_FILE, ForgeConstants.CACHE_TOKEN_PICS_DIR);
return downloads;
}
private void addDLObject(PaperCard c, Map<String, String> downloads, boolean backFace) {
CardRules cardRules = c.getRules();
String urls = cardRules.getPictureUrl(backFace);
if (StringUtils.isEmpty(urls)) {
return;
}
String filename = ImageUtil.getImageKey(c, backFace, false);
File destFile = new File(ForgeConstants.CACHE_CARD_PICS_DIR, filename + ".jpg");
if (destFile.exists())
return;
filename = destFile.getAbsolutePath();
if (downloads.containsKey(filename)) {
return;
}
final String urlToDownload;
int urlIndex = 0;
int allUrlsLen = 1;
if (urls.indexOf("\\") < 0)
urlToDownload = urls;
else {
String[] allUrls = urls.split("\\\\");
allUrlsLen = allUrls.length;
urlIndex = (c.getArtIndex()-1) % allUrlsLen;
urlToDownload = allUrls[urlIndex];
}
//System.out.println(c.getName() + "|" + c.getEdition() + " - " + c.getArtIndex() + " -> " + urlIndex + "/" + allUrlsLen + " === " + filename + " <<< " + urlToDownload);
downloads.put(destFile.getAbsolutePath(), urlToDownload);
}
}

View File

@@ -1,37 +0,0 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.download;
import forge.properties.ForgeConstants;
import java.util.HashMap;
import java.util.Map;
@SuppressWarnings("serial")
public class GuiDownloadPrices extends GuiDownloader {
public GuiDownloadPrices() {
super();
}
@Override
protected Map<String, String> getNeededImages() {
Map<String, String> result = new HashMap<String, String>();
result.put(ForgeConstants.QUEST_CARD_PRICE_FILE, ForgeConstants.URL_PRICE_DOWNLOAD);
return result;
}
}

View File

@@ -1,60 +0,0 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.download;
import forge.properties.ForgeConstants;
import java.util.Map;
import java.util.TreeMap;
/** */
@SuppressWarnings("serial")
public class GuiDownloadQuestImages extends GuiDownloader {
/**
* <p>
* Constructor for GuiDownloadQuestImages.
* </p>
*/
public GuiDownloadQuestImages() {
super();
}
/**
* <p>
* getNeededCards.
* </p>
*
* @return an array of {@link forge.download.GuiDownloadSetPicturesLQ} objects.
*/
@Override
protected final Map<String, String> getNeededImages() {
// read all card names and urls
final Map<String, String> urls = new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER);
addMissingItems(urls, ForgeConstants.IMAGE_LIST_QUEST_OPPONENT_ICONS_FILE, ForgeConstants.CACHE_ICON_PICS_DIR);
addMissingItems(urls, ForgeConstants.IMAGE_LIST_QUEST_PET_SHOP_ICONS_FILE, ForgeConstants.CACHE_ICON_PICS_DIR);
addMissingItems(urls, ForgeConstants.IMAGE_LIST_QUEST_BOOSTERS_FILE, ForgeConstants.CACHE_BOOSTER_PICS_DIR);
addMissingItems(urls, ForgeConstants.IMAGE_LIST_QUEST_FATPACKS_FILE, ForgeConstants.CACHE_FATPACK_PICS_DIR);
addMissingItems(urls, ForgeConstants.IMAGE_LIST_QUEST_BOOSTERBOXES_FILE, ForgeConstants.CACHE_BOOSTERBOX_PICS_DIR);
addMissingItems(urls, ForgeConstants.IMAGE_LIST_QUEST_PRECONS_FILE, ForgeConstants.CACHE_PRECON_PICS_DIR);
addMissingItems(urls, ForgeConstants.IMAGE_LIST_QUEST_TOURNAMENTPACKS_FILE, ForgeConstants.CACHE_TOURNAMENTPACK_PICS_DIR);
addMissingItems(urls, ForgeConstants.IMAGE_LIST_QUEST_TOKENS_FILE, ForgeConstants.CACHE_TOKEN_PICS_DIR);
return urls;
}
}

View File

@@ -1,70 +0,0 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.download;
import com.google.common.collect.Iterables;
import forge.assets.ImageUtil;
import forge.card.CardEdition;
import forge.item.PaperCard;
import forge.model.FModel;
import forge.properties.ForgeConstants;
import org.apache.commons.lang3.StringUtils;
import java.io.File;
import java.util.Map;
import java.util.TreeMap;
@SuppressWarnings("serial")
public class GuiDownloadSetPicturesLQ extends GuiDownloader {
public GuiDownloadSetPicturesLQ() {
super();
}
@Override
protected final Map<String, String> getNeededImages() {
Map<String, String> downloads = new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER);
for (final PaperCard c : Iterables.concat(FModel.getMagicDb().getCommonCards().getAllCards(), FModel.getMagicDb().getVariantCards().getAllCards())) {
final String setCode3 = c.getEdition();
if (StringUtils.isBlank(setCode3) || CardEdition.UNKNOWN.getCode().equals(setCode3)) {
// we don't want cards from unknown sets
continue;
}
addDLObject(ImageUtil.getDownloadUrl(c, false), ImageUtil.getImageKey(c, false, true), downloads);
if (ImageUtil.hasBackFacePicture(c)) {
addDLObject(ImageUtil.getDownloadUrl(c, true), ImageUtil.getImageKey(c, true, true), downloads);
}
}
// Add missing tokens to the list of things to download.
addMissingItems(downloads, ForgeConstants.IMAGE_LIST_TOKENS_FILE, ForgeConstants.CACHE_TOKEN_PICS_DIR);
return downloads;
}
private void addDLObject(String urlPath, String filename, Map<String, String> downloads) {
File destFile = new File(ForgeConstants.CACHE_CARD_PICS_DIR, filename + ".jpg");
// System.out.println(filename);
if (!destFile.exists()) {
downloads.put(destFile.getAbsolutePath(), ForgeConstants.URL_PIC_DOWNLOAD + urlPath);
}
}
}

View File

@@ -17,89 +17,51 @@
*/
package forge.download;
import com.esotericsoftware.minlog.Log;
import forge.UiCommand;
import forge.ImageCache;
import forge.assets.FSkinProp;
import forge.error.BugReporter;
import forge.gui.SOverlayUtils;
import forge.toolbox.*;
import forge.util.FileUtil;
import forge.util.MyRandom;
import net.miginfocom.swing.MigLayout;
import org.apache.commons.lang3.tuple.Pair;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.*;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
@SuppressWarnings("serial")
public abstract class GuiDownloader extends DefaultBoundedRangeModel implements Runnable {
public class GuiDownloader extends DefaultBoundedRangeModel {
public static final Proxy.Type[] TYPES = Proxy.Type.values();
// Actions and commands
private final ActionListener actStartDownload = new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
// invalidate image cache so newly downloaded images will be loaded
ImageCache.clear();
new Thread(GuiDownloader.this).start();
btnStart.setEnabled(false);
}
};
private final ActionListener actOK = new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
close();
}
};
private final UiCommand cmdClose = new UiCommand() { @Override
public void run() { close(); } };
// Swing components
private final FPanel pnlDialog = new FPanel(new MigLayout("insets 0, gap 0, wrap, ax center, ay center"));
private final FProgressBar barProgress = new FProgressBar();
private final FButton btnStart = new FButton("Start");
private final JTextField txfAddr = new JTextField("Proxy Address");
private final JTextField txfPort = new JTextField("Proxy Port");
private final FTextField txtAddress = new FTextField.Builder().ghostText("Proxy Address").build();
private final FTextField txtPort = new FTextField.Builder().ghostText("Proxy Port").build();
private final UiCommand cmdClose = new UiCommand() {
@Override
public void run() {
service.setCancel(true);
// Kill overlay
SOverlayUtils.hideOverlay();
}
};
private final FLabel btnClose = new FLabel.Builder().text("X")
.hoverable(true).fontAlign(SwingConstants.CENTER).cmdClick(cmdClose).build();
private final JRadioButton radProxyNone = new FRadioButton("No Proxy");
private final JRadioButton radProxySocks = new FRadioButton("SOCKS Proxy");
private final JRadioButton radProxyHTTP = new FRadioButton("HTTP Proxy");
private final FRadioButton radProxyNone = new FRadioButton("No Proxy");
private final FRadioButton radProxySocks = new FRadioButton("SOCKS Proxy");
private final FRadioButton radProxyHTTP = new FRadioButton("HTTP Proxy");
// Proxy info
private int type;
private final GuiDownloadService service;
// Progress variables
private Map<String, String> cards; // local path -> url
private boolean cancel;
private final long[] times = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
private int tptr = 0;
private int skipped = 0;
private long lTime = System.currentTimeMillis();
public GuiDownloader(GuiDownloadService service0) {
service = service0;
protected GuiDownloader() {
String radConstraints = "w 100%!, h 30px!, gap 2% 0 0 10px";
JXButtonPanel grpPanel = new JXButtonPanel();
grpPanel.add(radProxyNone, radConstraints);
@@ -121,8 +83,8 @@ public abstract class GuiDownloader extends DefaultBoundedRangeModel implements
// Layout
pnlDialog.add(grpPanel, "w 50%!");
pnlDialog.add(txfAddr, "w 95%!, h 30px!, gap 2% 0 0 10px");
pnlDialog.add(txfPort, "w 95%!, h 30px!, gap 2% 0 0 10px");
pnlDialog.add(txtAddress, "w 95%!, h 30px!, gap 2% 0 0 10px");
pnlDialog.add(txtPort, "w 95%!, h 30px!, gap 2% 0 0 10px");
pnlDialog.add(barProgress, "w 95%!, h 40px!, gap 2% 0 20px 0");
pnlDialog.add(btnStart, "w 200px!, h 40px!, gap 0 0 20px 0, ax center");
pnlDialog.add(btnClose, "w 20px!, h 20px!, pos 370px 10px");
@@ -133,218 +95,15 @@ public abstract class GuiDownloader extends DefaultBoundedRangeModel implements
pnl.add(pnlDialog, "w 400px!, h 350px!, ax center, ay center");
SOverlayUtils.showOverlay();
// Free up the EDT by assembling card list in the background
SwingWorker<Void, Void> thrGetImages = new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws Exception {
try {
GuiDownloader.this.cards = GuiDownloader.this.getNeededImages();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
protected void done() {
GuiDownloader.this.readyToStart();
}
};
thrGetImages.execute();
}
private void readyToStart() {
if (this.cards.isEmpty()) {
barProgress.setString("All items have been downloaded.");
btnStart.setText("OK");
btnStart.addActionListener(actOK);
} else {
barProgress.setMaximum(this.cards.size());
barProgress.setString(this.cards.size() == 1 ? "1 item found." : this.cards.size() + " items found.");
//for(Entry<String, String> kv : cards.entrySet()) System.out.printf("Will get %s from %s%n", kv.getKey(), kv.getValue());
btnStart.addActionListener(actStartDownload);
}
btnStart.setVisible(true);
SwingUtilities.invokeLater(new Runnable() {
service.initialize(txtAddress, txtPort, barProgress, btnStart, cmdClose, new Runnable() {
@Override
public void run() {
btnStart.requestFocusInWindow();
fireStateChanged();
}
});
}
private void setCancel(final boolean cancel) {
this.cancel = cancel;
}
private void close() {
setCancel(true);
// Kill overlay
SOverlayUtils.hideOverlay();
}
protected final int getAverageTimePerObject() {
int numNonzero = 10;
if (this.tptr > 9) {
this.tptr = 0;
}
this.times[this.tptr] = System.currentTimeMillis() - this.lTime;
this.lTime = System.currentTimeMillis();
int tTime = 0;
for (int i = 0; i < 10; i++) {
tTime += this.times[i];
if (this.times[i] == 0) {
numNonzero--;
}
}
this.tptr++;
return tTime / Math.max(1, numNonzero);
}
private void update(final int card, final File dest) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
GuiDownloader.this.fireStateChanged();
final StringBuilder sb = new StringBuilder();
final int a = GuiDownloader.this.getAverageTimePerObject();
if (card != GuiDownloader.this.cards.size()) {
sb.append(card + "/" + GuiDownloader.this.cards.size() + " - ");
long t2Go = (GuiDownloader.this.cards.size() - card) * a;
if (t2Go > 3600000) {
sb.append(String.format("%02d:", t2Go / 3600000));
t2Go = t2Go % 3600000;
}
if (t2Go > 60000) {
sb.append(String.format("%02d:", t2Go / 60000));
t2Go = t2Go % 60000;
} else {
sb.append("00:");
}
sb.append(String.format("%02d remaining.", t2Go / 1000));
} else {
sb.append(String.format("%d of %d items finished! Skipped " + skipped + " items. Please close!",
card, GuiDownloader.this.cards.size()));
btnStart.setText("OK");
btnStart.addActionListener(actOK);
btnStart.setEnabled(true);
btnStart.requestFocusInWindow();
}
GuiDownloader.this.barProgress.setString(sb.toString());
System.out.println(card + "/" + GuiDownloader.this.cards.size() + " - " + dest);
}
});
}
@Override
public final void run() {
final Random r = MyRandom.getRandom();
Proxy p = null;
if (this.type == 0) {
p = Proxy.NO_PROXY;
} else {
try {
p = new Proxy(GuiDownloader.TYPES[this.type], new InetSocketAddress(this.txfAddr.getText(),
Integer.parseInt(this.txfPort.getText())));
} catch (final Exception ex) {
BugReporter.reportException(ex,
"Proxy connection could not be established!\nProxy address: %s\nProxy port: %s",
this.txfAddr.getText(), this.txfPort.getText());
return;
}
}
int iCard = 0;
for(Entry<String, String> kv : cards.entrySet()) {
if( cancel )
break;
String url = kv.getValue();
final File fileDest = new File(kv.getKey());
final File base = fileDest.getParentFile();
ReadableByteChannel rbc = null;
FileOutputStream fos = null;
try {
// test for folder existence
if (!base.exists() && !base.mkdir()) { // create folder if not found
System.out.println("Can't create folder" + base.getAbsolutePath());
}
URL imageUrl = new URL(url);
HttpURLConnection conn = (HttpURLConnection) imageUrl.openConnection(p);
// don't allow redirections here -- they indicate 'file not found' on the server
conn.setInstanceFollowRedirects(false);
conn.connect();
if (conn.getResponseCode() != 200) {
conn.disconnect();
System.out.println("Skipped Download for: " + fileDest.getPath());
update(++iCard, fileDest);
skipped++;
continue;
}
rbc = Channels.newChannel(conn.getInputStream());
fos = new FileOutputStream(fileDest);
fos.getChannel().transferFrom(rbc, 0, 1 << 24);
} catch (final ConnectException ce) {
System.out.println("Connection refused for url: " + url);
} catch (final MalformedURLException mURLe) {
System.out.println("Error - possibly missing URL for: " + fileDest.getName());
} catch (final FileNotFoundException fnfe) {
String formatStr = "Error - the LQ picture %s could not be found on the server. [%s] - %s";
System.out.println(String.format(formatStr, fileDest.getName(), url, fnfe.getMessage()));
} catch (final Exception ex) {
Log.error("LQ Pictures", "Error downloading pictures", ex);
} finally {
if (null != rbc) {
try { rbc.close(); } catch (IOException e) { System.out.println("error closing input stream"); }
}
if (null != fos) {
try { fos.close(); } catch (IOException e) { System.out.println("error closing output stream"); }
}
}
update(++iCard, fileDest);
// throttle to reduce load on the server
try {
Thread.sleep(r.nextInt(50) + 50);
} catch (final InterruptedException e) {
Log.error("GuiDownloader", "Sleep Error", e);
}
} // for
}
protected abstract Map<String, String> getNeededImages();
protected static void addMissingItems(Map<String, String> list, String nameUrlFile, String dir) {
for (Pair<String, String> nameUrlPair : FileUtil.readNameUrlFile(nameUrlFile)) {
File f = new File(dir, nameUrlPair.getLeft());
//System.out.println(f.getAbsolutePath());
if (!f.exists()) {
list.put(f.getAbsolutePath(), nameUrlPair.getRight());
}
}
}
protected class ProxyHandler implements ChangeListener {
private class ProxyHandler implements ChangeListener {
private final int type;
public ProxyHandler(final int type) {
@@ -354,9 +113,9 @@ public abstract class GuiDownloader extends DefaultBoundedRangeModel implements
@Override
public final void stateChanged(final ChangeEvent e) {
if (((AbstractButton) e.getSource()).isSelected()) {
GuiDownloader.this.type = this.type;
GuiDownloader.this.txfAddr.setEnabled(this.type != 0);
GuiDownloader.this.txfPort.setEnabled(this.type != 0);
service.setType(this.type);
txtAddress.setEnabled(this.type != 0);
txtPort.setEnabled(this.type != 0);
}
}
}

View File

@@ -5,6 +5,7 @@ import forge.download.GuiDownloadPicturesLQ;
import forge.download.GuiDownloadPrices;
import forge.download.GuiDownloadQuestImages;
import forge.download.GuiDownloadSetPicturesLQ;
import forge.download.GuiDownloader;
import forge.error.BugReporter;
import forge.gui.ImportDialog;
import forge.gui.framework.ICDoc;
@@ -24,13 +25,13 @@ public enum CSubmenuDownloaders implements ICDoc {
private final UiCommand cmdLicensing = new UiCommand() { @Override
public void run() { VSubmenuDownloaders.SINGLETON_INSTANCE.showLicensing(); } };
private final UiCommand cmdPicDownload = new UiCommand() { @Override
public void run() { new GuiDownloadPicturesLQ(); } };
public void run() { new GuiDownloader(new GuiDownloadPicturesLQ()); } };
private final UiCommand cmdSetDownload = new UiCommand() { @Override
public void run() { new GuiDownloadSetPicturesLQ(); } };
public void run() { new GuiDownloader(new GuiDownloadSetPicturesLQ()); } };
private final UiCommand cmdQuestImages = new UiCommand() { @Override
public void run() { new GuiDownloadQuestImages(); } };
public void run() { new GuiDownloader(new GuiDownloadQuestImages()); } };
private final UiCommand cmdDownloadPrices = new UiCommand() { @Override
public void run() { new GuiDownloadPrices(); } };
public void run() { new GuiDownloader(new GuiDownloadPrices()); } };
private final UiCommand cmdHowToPlay = new UiCommand() { @Override
public void run() { VSubmenuDownloaders.SINGLETON_INSTANCE.showHowToPlay(); } };
private final UiCommand cmdImportPictures = new UiCommand() { @Override

View File

@@ -17,6 +17,7 @@
*/
package forge.toolbox;
import forge.UiCommand;
import forge.assets.FSkinProp;
import forge.gui.framework.ILocalRepaint;
import forge.interfaces.IButton;
@@ -237,4 +238,14 @@ public class FButton extends SkinnedButton implements ILocalRepaint, IButton {
super.paintComponent(g);
}
@Override
public void setCommand(final UiCommand command) {
addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
command.run();
}
});
}
}

View File

@@ -627,4 +627,9 @@ public class FLabel extends SkinnedLabel implements ILocalRepaint, IButton {
super.setIcon(new ImageIcon(img.getScaledInstance(w, h, Image.SCALE_SMOOTH)));
}
}
@Override
public void setCommand(UiCommand command0) {
cmdClick = command0;
}
}

View File

@@ -1,6 +1,7 @@
package forge.toolbox;
import forge.gui.MouseUtil;
import forge.interfaces.ITextField;
import forge.toolbox.FSkin.SkinnedTextField;
import javax.swing.*;
@@ -19,7 +20,7 @@ import java.awt.event.FocusEvent;
*
*/
@SuppressWarnings("serial")
public class FTextField extends SkinnedTextField {
public class FTextField extends SkinnedTextField implements ITextField {
/**
* Uses the Builder pattern to facilitate/encourage inline styling.
* Credit to Effective Java 2 (Joshua Bloch).

View File

@@ -1,6 +1,7 @@
package forge;
import forge.download.GuiDownloadPicturesLQ;
import forge.download.GuiDownloader;
import org.testng.annotations.Test;
@@ -15,6 +16,6 @@ public class GuiDownloadPicturesLQTest {
*/
@Test(enabled = false, timeOut = 1000)
public void guiDownloadPicturesTest1() {
new GuiDownloadPicturesLQ();
new GuiDownloader(new GuiDownloadPicturesLQ());
}
}

View File

@@ -1,6 +1,7 @@
package forge;
import forge.download.GuiDownloadSetPicturesLQ;
import forge.download.GuiDownloader;
import org.testng.annotations.Test;
@@ -15,6 +16,6 @@ public class GuiDownloadSetPicturesLQTest {
*/
@Test(enabled = false, timeOut = 1000)
public void g() {
new GuiDownloadSetPicturesLQ();
new GuiDownloader(new GuiDownloadSetPicturesLQ());
}
}