mirror of
https://github.com/magefree/mage.git
synced 2025-12-20 10:40:06 -08:00
[card.plugin] Symbols support: download and display. Please try it, if you don't like it, will remove or make configurable. Thanks to SillyFreak (Laterna Magica) for GathererSymbols downloader code.
This commit is contained in:
parent
7d9d2bc744
commit
c650c43f94
35 changed files with 1758 additions and 25 deletions
|
|
@ -57,6 +57,11 @@
|
|||
<artifactId>swingx</artifactId>
|
||||
<version>1.6.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jetlang</groupId>
|
||||
<artifactId>jetlang</artifactId>
|
||||
<version>0.2.4</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
|
|||
|
|
@ -143,6 +143,21 @@ public class MageFrame extends javax.swing.JFrame {
|
|||
Separator separator = new javax.swing.JToolBar.Separator();
|
||||
mageToolbar.add(separator);
|
||||
|
||||
JButton btnDownloadSymbols = new JButton("Symbols");
|
||||
btnDownloadSymbols.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
|
||||
btnDownloadSymbols.setFocusable(false);
|
||||
btnDownloadSymbols.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
|
||||
btnDownloadSymbols.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
|
||||
btnDownloadSymbols.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
btnSymbolsActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
mageToolbar.add(btnDownloadSymbols);
|
||||
|
||||
separator = new javax.swing.JToolBar.Separator();
|
||||
mageToolbar.add(separator);
|
||||
|
||||
JButton btnDownload = new JButton("Images");
|
||||
btnDownload.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
|
||||
btnDownload.setFocusable(false);
|
||||
|
|
@ -174,6 +189,12 @@ public class MageFrame extends javax.swing.JFrame {
|
|||
Plugins.getInstance().downloadImage(allCards);
|
||||
}
|
||||
|
||||
private void btnSymbolsActionPerformed(java.awt.event.ActionEvent evt) {
|
||||
if (JOptionPane.showConfirmDialog(null, "Do you want to download mana symbols?") == JOptionPane.OK_OPTION) {
|
||||
Plugins.getInstance().downloadSymbols();
|
||||
}
|
||||
}
|
||||
|
||||
public void showGame(UUID gameId, UUID playerId) {
|
||||
this.tablesPane.hideTables();
|
||||
this.tablesPane.setVisible(false);
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ public interface MagePlugins {
|
|||
boolean isCounterPluginLoaded();
|
||||
void sortPermanents(Map<String, JComponent> ui, Collection<MagePermanent> permanents);
|
||||
void downloadImage(Set<Card> allCards);
|
||||
void downloadSymbols();
|
||||
int getGamesPlayed();
|
||||
void addGamesPlayed();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -113,6 +113,11 @@ public class Plugins implements MagePlugins {
|
|||
if (this.cardPlugin != null) this.cardPlugin.downloadImages(allCards);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void downloadSymbols() {
|
||||
if (this.cardPlugin != null) this.cardPlugin.downloadSymbols();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getGamesPlayed() {
|
||||
if (this.counterPlugin != null) {
|
||||
|
|
|
|||
|
|
@ -28,4 +28,5 @@ public interface CardPlugin extends Plugin {
|
|||
MagePermanent getMageCard(CardView permanent, CardDimensions dimension, UUID gameId, ActionCallback callback);
|
||||
void sortPermanents(Map<String, JComponent> ui, Collection<MagePermanent> cards);
|
||||
void downloadImages(Set<Card> allCards);
|
||||
void downloadSymbols();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,6 +45,12 @@
|
|||
<version>0.8.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jetlang</groupId>
|
||||
<artifactId>jetlang</artifactId>
|
||||
<version>0.2.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
|
|||
|
|
@ -314,10 +314,13 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti
|
|||
super.paintChildren(g);
|
||||
|
||||
if (showCastingCost && !isAnimationPanel && cardWidth < 200 && cardWidth > 60) {
|
||||
//TODO:uncomment
|
||||
/*int width = ManaSymbols.getWidth(gameCard.getManaCost());
|
||||
ManaSymbols.draw(g, gameCard.getManaCost(), cardXOffset + 8, cardHeight - 9);
|
||||
*/
|
||||
String manaCost = ManaSymbols.getStringManaCost(gameCard.getManaCost());
|
||||
int width = ManaSymbols.getWidth(manaCost);
|
||||
if (hasImage) {
|
||||
ManaSymbols.draw(g, manaCost, cardXOffset + cardWidth - width - 5, cardYOffset + 5);
|
||||
} else {
|
||||
ManaSymbols.draw(g, manaCost, cardXOffset + 8, cardHeight - 9);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,13 +2,19 @@ package org.mage.card.arcane;
|
|||
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Image;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.mage.plugins.card.constants.Constants;
|
||||
import org.mage.plugins.card.images.ImageCache;
|
||||
import org.mage.plugins.card.utils.BufferedImageBuilder;
|
||||
|
||||
public class ManaSymbols {
|
||||
private static final Logger log = Logger.getLogger(ManaSymbols.class);
|
||||
|
|
@ -18,9 +24,16 @@ public class ManaSymbols {
|
|||
static public void loadImages () {
|
||||
String[] symbols = new String[] {"0", "1", "10", "11", "12", "15", "16", "2", "3", "4", "5", "6", "7", "8", "9", "B", "BG",
|
||||
"BR", "G", "GU", "GW", "R", "RG", "RW", "S", "T", "U", "UB", "UR", "W", "WB", "WU", "X", "Y", "Z", "slash"};
|
||||
//TODO: replace by downloading
|
||||
for (String symbol : symbols)
|
||||
manaImages.put(symbol, UI.getImageIcon(Constants.RESOURCE_PATH_MANA + "/" + symbol + ".png").getImage());
|
||||
for (String symbol : symbols) {
|
||||
File file = new File(Constants.RESOURCE_PATH_MANA + "/" + symbol + ".jpg");
|
||||
BufferedImageBuilder builder = new BufferedImageBuilder();
|
||||
Rectangle r = new Rectangle(11, 11);
|
||||
try {
|
||||
Image image = UI.getImageIcon(file.getAbsolutePath()).getImage();
|
||||
BufferedImage resized = ImageCache.getResizedImage(builder.bufferImage(image, BufferedImage.TYPE_INT_ARGB), r);
|
||||
manaImages.put(symbol, resized);
|
||||
} catch (Exception e) {}
|
||||
}
|
||||
}
|
||||
|
||||
static public void draw (Graphics g, String manaCost, int x, int y) {
|
||||
|
|
@ -32,7 +45,7 @@ public class ManaSymbols {
|
|||
String symbol = tok.nextToken().substring(0);
|
||||
Image image = manaImages.get(symbol);
|
||||
if (image == null) {
|
||||
log.error("Symbol not recognized \"" + symbol + "\" in mana cost: " + manaCost);
|
||||
//log.error("Symbol not recognized \"" + symbol + "\" in mana cost: " + manaCost);
|
||||
continue;
|
||||
}
|
||||
g.drawImage(image, x, y, null);
|
||||
|
|
@ -40,7 +53,15 @@ public class ManaSymbols {
|
|||
}
|
||||
}
|
||||
|
||||
static public int getWidth (String manaCost) {
|
||||
static public String getStringManaCost(List<String> manaCost) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String s : manaCost) {
|
||||
sb.append(s);
|
||||
}
|
||||
return sb.toString().replace("{", "").replace("}", " ").trim();
|
||||
}
|
||||
|
||||
static public int getWidth(String manaCost) {
|
||||
int width = 0;
|
||||
manaCost = manaCost.replace("\\", "");
|
||||
StringTokenizer tok = new StringTokenizer(manaCost, " ");
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
package org.mage.plugins.card;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Frame;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
|
@ -9,6 +13,7 @@ import java.util.Set;
|
|||
import java.util.UUID;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JLayeredPane;
|
||||
import javax.swing.JScrollPane;
|
||||
|
||||
|
|
@ -27,7 +32,12 @@ import net.xeoh.plugins.base.annotations.meta.Author;
|
|||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.mage.card.arcane.CardPanel;
|
||||
import org.mage.card.arcane.ManaSymbols;
|
||||
import org.mage.plugins.card.constants.Constants;
|
||||
import org.mage.plugins.card.dl.DownloadGui;
|
||||
import org.mage.plugins.card.dl.DownloadJob;
|
||||
import org.mage.plugins.card.dl.Downloader;
|
||||
import org.mage.plugins.card.dl.sources.GathererSymbols;
|
||||
import org.mage.plugins.card.images.DownloadPictures;
|
||||
|
||||
/**
|
||||
|
|
@ -68,6 +78,7 @@ public class CardPluginImpl implements CardPlugin {
|
|||
|
||||
@PluginLoaded
|
||||
public void newPlugin(CardPlugin plugin) {
|
||||
ManaSymbols.loadImages();
|
||||
log.info(plugin.toString() + " has been loaded.");
|
||||
}
|
||||
|
||||
|
|
@ -80,6 +91,7 @@ public class CardPluginImpl implements CardPlugin {
|
|||
CardPanel cardPanel = new CardPanel(permanent, gameId, true, callback);
|
||||
cardPanel.setShowCastingCost(true);
|
||||
cardPanel.setCardBounds(0, 0, dimension.frameWidth, dimension.frameHeight);
|
||||
cardPanel.setShowCastingCost(true);
|
||||
return cardPanel;
|
||||
}
|
||||
|
||||
|
|
@ -88,6 +100,7 @@ public class CardPluginImpl implements CardPlugin {
|
|||
CardPanel cardPanel = new CardPanel(permanent, gameId, true, callback);
|
||||
cardPanel.setShowCastingCost(true);
|
||||
cardPanel.setCardBounds(0, 0, dimension.frameWidth, dimension.frameHeight);
|
||||
cardPanel.setShowCastingCost(true);
|
||||
return cardPanel;
|
||||
}
|
||||
|
||||
|
|
@ -390,4 +403,28 @@ public class CardPluginImpl implements CardPlugin {
|
|||
public void downloadImages(Set<Card> allCards) {
|
||||
DownloadPictures.startDownload(null, allCards);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void downloadSymbols() {
|
||||
final DownloadGui g = new DownloadGui(new Downloader());
|
||||
|
||||
Iterable<DownloadJob> it = new GathererSymbols();
|
||||
|
||||
for(DownloadJob job:it) {
|
||||
g.getDownloader().add(job);
|
||||
}
|
||||
|
||||
JDialog d = new JDialog((Frame) null, "Download pictures", false);
|
||||
d.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
|
||||
d.addWindowListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e) {
|
||||
g.getDownloader().dispose();
|
||||
}
|
||||
});
|
||||
d.setLayout(new BorderLayout());
|
||||
d.add(g);
|
||||
d.pack();
|
||||
d.setVisible(true);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,24 +4,14 @@ import java.awt.Rectangle;
|
|||
import java.io.File;
|
||||
|
||||
public class Constants {
|
||||
public static final String RESOURCE_PATH = "/images";
|
||||
public static final String RESOURCE_PATH_MANA = resourcePath("mana");
|
||||
public static final String RESOURCE_PATH_MANA = IO.imageBaseDir + "symbols" + File.separator + "large";
|
||||
|
||||
public static final Rectangle CARD_SIZE_FULL = new Rectangle(101, 149);
|
||||
|
||||
public interface IO {
|
||||
public static final String imageBaseDir = "." + File.separator + "plugins" + File.separator + "images" + File.separator;
|
||||
public static final String imageBaseDir = "plugins" + File.separator + "images" + File.separator;
|
||||
public static final String IMAGE_PROPERTIES_FILE = "image.url.properties";
|
||||
}
|
||||
|
||||
public static final String CARD_IMAGE_PATH_TEMPLATE = "." + File.separator + "plugins" + File.separator + "images/{set}/{name}.{collector}.full.jpg";
|
||||
|
||||
/**
|
||||
* Build resource path.
|
||||
*
|
||||
* @param folder
|
||||
* @return
|
||||
*/
|
||||
private static String resourcePath(String folder) {
|
||||
return RESOURCE_PATH + "/" + folder;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,195 @@
|
|||
/**
|
||||
* DownloadGui.java
|
||||
*
|
||||
* Created on 25.08.2010
|
||||
*/
|
||||
|
||||
package org.mage.plugins.card.dl;
|
||||
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.beans.IndexedPropertyChangeEvent;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.BoundedRangeModel;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.DefaultBoundedRangeModel;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JProgressBar;
|
||||
import javax.swing.JScrollPane;
|
||||
|
||||
import org.mage.plugins.card.dl.DownloadJob.State;
|
||||
|
||||
|
||||
/**
|
||||
* The class DownloadGui.
|
||||
*
|
||||
* @version V0.0 25.08.2010
|
||||
* @author Clemens Koza
|
||||
*/
|
||||
public class DownloadGui extends JPanel {
|
||||
private static final long serialVersionUID = -7346572382493844327L;
|
||||
|
||||
private final Downloader d;
|
||||
private final DownloadListener l = new DownloadListener();
|
||||
private final BoundedRangeModel model = new DefaultBoundedRangeModel(0, 0, 0, 0);
|
||||
private final JProgressBar progress = new JProgressBar(model);
|
||||
|
||||
private final Map<DownloadJob, DownloadPanel> progresses = new HashMap<DownloadJob, DownloadPanel>();
|
||||
private final JPanel panel = new JPanel();
|
||||
|
||||
public DownloadGui(Downloader d) {
|
||||
super(new BorderLayout());
|
||||
this.d = d;
|
||||
d.addPropertyChangeListener(l);
|
||||
|
||||
JPanel p = new JPanel(new BorderLayout());
|
||||
p.setBorder(BorderFactory.createTitledBorder("Progress:"));
|
||||
p.add(progress);
|
||||
JButton b = new JButton("X");
|
||||
b.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
getDownloader().dispose();
|
||||
}
|
||||
});
|
||||
p.add(b, BorderLayout.EAST);
|
||||
add(p, BorderLayout.NORTH);
|
||||
|
||||
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
|
||||
JScrollPane pane = new JScrollPane(panel);
|
||||
pane.setPreferredSize(new Dimension(500, 300));
|
||||
add(pane);
|
||||
for(int i = 0; i < d.getJobs().size(); i++)
|
||||
addJob(i, d.getJobs().get(i));
|
||||
}
|
||||
|
||||
public Downloader getDownloader() {
|
||||
return d;
|
||||
}
|
||||
|
||||
private class DownloadListener implements PropertyChangeListener {
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
String name = evt.getPropertyName();
|
||||
if(evt.getSource() instanceof DownloadJob) {
|
||||
DownloadPanel p = progresses.get(evt.getSource());
|
||||
if("state".equals(name)) {
|
||||
if(evt.getOldValue() == State.FINISHED || evt.getOldValue() == State.ABORTED) {
|
||||
changeProgress(-1, 0);
|
||||
}
|
||||
if(evt.getNewValue() == State.FINISHED || evt.getOldValue() == State.ABORTED) {
|
||||
changeProgress(+1, 0);
|
||||
}
|
||||
if(p != null) {
|
||||
p.setVisible(p.getJob().getState() != State.FINISHED);
|
||||
p.revalidate();
|
||||
}
|
||||
} else if("message".equals(name)) {
|
||||
if(p != null) {
|
||||
JProgressBar bar = p.getBar();
|
||||
String message = p.getJob().getMessage();
|
||||
bar.setStringPainted(message != null);
|
||||
bar.setString(message);
|
||||
}
|
||||
}
|
||||
} else if(evt.getSource() == d) {
|
||||
if("jobs".equals(name)) {
|
||||
IndexedPropertyChangeEvent ev = (IndexedPropertyChangeEvent) evt;
|
||||
int index = ev.getIndex();
|
||||
|
||||
DownloadJob oldValue = (DownloadJob) ev.getOldValue();
|
||||
if(oldValue != null) removeJob(index, oldValue);
|
||||
|
||||
DownloadJob newValue = (DownloadJob) ev.getNewValue();
|
||||
if(newValue != null) addJob(index, newValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void addJob(int index, DownloadJob job) {
|
||||
job.addPropertyChangeListener(l);
|
||||
changeProgress(0, +1);
|
||||
DownloadPanel p = new DownloadPanel(job);
|
||||
progresses.put(job, p);
|
||||
panel.add(p, index);
|
||||
panel.revalidate();
|
||||
}
|
||||
|
||||
private synchronized void removeJob(int index, DownloadJob job) {
|
||||
assert progresses.get(job) == panel.getComponent(index);
|
||||
job.removePropertyChangeListener(l);
|
||||
changeProgress(0, -1);
|
||||
progresses.remove(job);
|
||||
panel.remove(index);
|
||||
panel.revalidate();
|
||||
}
|
||||
|
||||
private synchronized void changeProgress(int progress, int total) {
|
||||
progress += model.getValue();
|
||||
total += model.getMaximum();
|
||||
model.setMaximum(total);
|
||||
model.setValue(progress);
|
||||
this.progress.setStringPainted(true);
|
||||
this.progress.setString(progress + "/" + total);
|
||||
}
|
||||
|
||||
private class DownloadPanel extends JPanel {
|
||||
private static final long serialVersionUID = 1187986738303477168L;
|
||||
|
||||
private DownloadJob job;
|
||||
private JProgressBar bar;
|
||||
|
||||
public DownloadPanel(DownloadJob job) {
|
||||
super(new BorderLayout());
|
||||
this.job = job;
|
||||
|
||||
setBorder(BorderFactory.createTitledBorder(job.getName()));
|
||||
add(bar = new JProgressBar(job.getProgress()));
|
||||
JButton b = new JButton("X");
|
||||
b.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
switch(getJob().getState()) {
|
||||
case NEW:
|
||||
case WORKING:
|
||||
getJob().setState(State.ABORTED);
|
||||
}
|
||||
}
|
||||
});
|
||||
add(b, BorderLayout.EAST);
|
||||
|
||||
if(job.getState() == State.FINISHED | job.getState() == State.ABORTED) {
|
||||
changeProgress(+1, 0);
|
||||
}
|
||||
setVisible(job.getState() != State.FINISHED);
|
||||
|
||||
String message = job.getMessage();
|
||||
bar.setStringPainted(message != null);
|
||||
bar.setString(message);
|
||||
|
||||
Dimension d = getPreferredSize();
|
||||
d.width = Integer.MAX_VALUE;
|
||||
setMaximumSize(d);
|
||||
// d.width = 500;
|
||||
// setMinimumSize(d);
|
||||
}
|
||||
|
||||
public DownloadJob getJob() {
|
||||
return job;
|
||||
}
|
||||
|
||||
public JProgressBar getBar() {
|
||||
return bar;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,213 @@
|
|||
/**
|
||||
* DownloadJob.java
|
||||
*
|
||||
* Created on 25.08.2010
|
||||
*/
|
||||
|
||||
package org.mage.plugins.card.dl;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Proxy;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
|
||||
import javax.swing.BoundedRangeModel;
|
||||
import javax.swing.DefaultBoundedRangeModel;
|
||||
|
||||
import org.mage.plugins.card.dl.beans.properties.Property;
|
||||
import org.mage.plugins.card.dl.lm.AbstractLaternaBean;
|
||||
|
||||
|
||||
/**
|
||||
* The class DownloadJob.
|
||||
*
|
||||
* @version V0.0 25.08.2010
|
||||
* @author Clemens Koza
|
||||
*/
|
||||
public class DownloadJob extends AbstractLaternaBean {
|
||||
public static enum State {
|
||||
NEW, WORKING, FINISHED, ABORTED;
|
||||
}
|
||||
|
||||
private final String name;
|
||||
private final Source source;
|
||||
private final Destination destination;
|
||||
private final Property<State> state = properties.property("state", State.NEW);
|
||||
private final Property<String> message = properties.property("message");
|
||||
private final Property<Exception> error = properties.property("error");
|
||||
private final BoundedRangeModel progress = new DefaultBoundedRangeModel();
|
||||
|
||||
public DownloadJob(String name, Source source, Destination destination) {
|
||||
this.name = name;
|
||||
this.source = source;
|
||||
this.destination = destination;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the job's state. If the state is {@link State#ABORTED}, it instead sets the error to "ABORTED"
|
||||
*/
|
||||
public void setState(State state) {
|
||||
if(state == State.ABORTED) setError("ABORTED");
|
||||
else this.state.setValue(state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the job's state to {@link State#ABORTED} and the error message to the given message. Logs a warning
|
||||
* with the given message.
|
||||
*/
|
||||
public void setError(String message) {
|
||||
setError(message, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the job's state to {@link State#ABORTED} and the error to the given exception. Logs a warning with the
|
||||
* given exception.
|
||||
*/
|
||||
public void setError(Exception error) {
|
||||
setError(null, error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the job's state to {@link State#ABORTED} and the error to the given exception. Logs a warning with the
|
||||
* given message and exception.
|
||||
*/
|
||||
public void setError(String message, Exception error) {
|
||||
if(message == null) message = error.toString();
|
||||
log.warn(message, error);
|
||||
this.state.setValue(State.ABORTED);
|
||||
this.error.setValue(error);
|
||||
this.message.setValue(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the job's message.
|
||||
*/
|
||||
public void setMessage(String message) {
|
||||
this.message.setValue(message);
|
||||
}
|
||||
|
||||
public BoundedRangeModel getProgress() {
|
||||
return progress;
|
||||
}
|
||||
|
||||
public State getState() {
|
||||
return state.getValue();
|
||||
}
|
||||
|
||||
public Exception getError() {
|
||||
return error.getValue();
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message.getValue();
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Source getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
public Destination getDestination() {
|
||||
return destination;
|
||||
}
|
||||
|
||||
public static Source fromURL(final String url) {
|
||||
return fromURL(null, url);
|
||||
}
|
||||
|
||||
public static Source fromURL(final URL url) {
|
||||
return fromURL(null, url);
|
||||
}
|
||||
|
||||
public static Source fromURL(final Proxy proxy, final String url) {
|
||||
return new Source() {
|
||||
private URLConnection c;
|
||||
|
||||
public URLConnection getConnection() throws IOException {
|
||||
if(c == null) c = proxy == null? new URL(url).openConnection():new URL(url).openConnection(proxy);
|
||||
return c;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream open() throws IOException {
|
||||
return getConnection().getInputStream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int length() throws IOException {
|
||||
return getConnection().getContentLength();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static Source fromURL(final Proxy proxy, final URL url) {
|
||||
return new Source() {
|
||||
private URLConnection c;
|
||||
|
||||
public URLConnection getConnection() throws IOException {
|
||||
if(c == null) c = proxy == null? url.openConnection():url.openConnection(proxy);
|
||||
return c;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream open() throws IOException {
|
||||
return getConnection().getInputStream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int length() throws IOException {
|
||||
return getConnection().getContentLength();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static Destination toFile(final String file) {
|
||||
return toFile(new File(file));
|
||||
}
|
||||
|
||||
public static Destination toFile(final File file) {
|
||||
return new Destination() {
|
||||
@Override
|
||||
public OutputStream open() throws IOException {
|
||||
File parent = file.getAbsoluteFile().getParentFile();
|
||||
//Trying to create the directory before checking it exists makes it threadsafe
|
||||
if(!parent.mkdirs() && !parent.exists()) throw new IOException(parent
|
||||
+ ": directory could not be created");
|
||||
return new FileOutputStream(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists() {
|
||||
return file.isFile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete() throws IOException {
|
||||
if(file.exists() && !file.delete()) throw new IOException(file + " couldn't be deleted");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static interface Source {
|
||||
public InputStream open() throws IOException;
|
||||
|
||||
public int length() throws IOException;
|
||||
}
|
||||
|
||||
public static interface Destination {
|
||||
public OutputStream open() throws IOException;
|
||||
|
||||
public boolean exists() throws IOException;
|
||||
|
||||
public void delete() throws IOException;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,157 @@
|
|||
/**
|
||||
* Downloader.java
|
||||
*
|
||||
* Created on 25.08.2010
|
||||
*/
|
||||
|
||||
package org.mage.plugins.card.dl;
|
||||
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import javax.swing.BoundedRangeModel;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.jetlang.channels.Channel;
|
||||
import org.jetlang.channels.MemoryChannel;
|
||||
import org.jetlang.core.Callback;
|
||||
import org.jetlang.core.Disposable;
|
||||
import org.jetlang.fibers.Fiber;
|
||||
import org.jetlang.fibers.PoolFiberFactory;
|
||||
import org.mage.plugins.card.dl.DownloadJob.Destination;
|
||||
import org.mage.plugins.card.dl.DownloadJob.Source;
|
||||
import org.mage.plugins.card.dl.DownloadJob.State;
|
||||
import org.mage.plugins.card.dl.lm.AbstractLaternaBean;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The class Downloader.
|
||||
*
|
||||
* @version V0.0 25.08.2010
|
||||
* @author Clemens Koza
|
||||
*/
|
||||
public class Downloader extends AbstractLaternaBean implements Disposable {
|
||||
|
||||
private static final Logger log = Logger.getLogger(Downloader.class);
|
||||
|
||||
private final List<DownloadJob> jobs = properties.list("jobs");
|
||||
private final Channel<DownloadJob> channel = new MemoryChannel<DownloadJob>();
|
||||
|
||||
private final ExecutorService pool = Executors.newCachedThreadPool();
|
||||
private final List<Fiber> fibers = new ArrayList<Fiber>();
|
||||
|
||||
public Downloader() {
|
||||
PoolFiberFactory f = new PoolFiberFactory(pool);
|
||||
//subscribe multiple fibers for parallel execution
|
||||
for(int i = 0, numThreads = 10; i < numThreads; i++) {
|
||||
Fiber fiber = f.create();
|
||||
fiber.start();
|
||||
fibers.add(fiber);
|
||||
channel.subscribe(fiber, new DownloadCallback());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
for(DownloadJob j:getJobs()) {
|
||||
switch(j.getState()) {
|
||||
case NEW:
|
||||
case WORKING:
|
||||
j.setState(State.ABORTED);
|
||||
}
|
||||
}
|
||||
|
||||
for(Fiber f:fibers)
|
||||
f.dispose();
|
||||
pool.shutdown();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
dispose();
|
||||
super.finalize();
|
||||
}
|
||||
|
||||
public void add(DownloadJob job) {
|
||||
if(job.getState() == State.WORKING) throw new IllegalArgumentException("Job already running");
|
||||
if(job.getState() == State.FINISHED) throw new IllegalArgumentException("Job already finished");
|
||||
job.setState(State.NEW);
|
||||
jobs.add(job);
|
||||
channel.publish(job);
|
||||
}
|
||||
|
||||
public List<DownloadJob> getJobs() {
|
||||
return jobs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the download job: Transfers data from {@link Source} to {@link Destination} and updates the
|
||||
* download job's state to reflect the progress.
|
||||
*/
|
||||
private class DownloadCallback implements Callback<DownloadJob> {
|
||||
@Override
|
||||
public void onMessage(DownloadJob job) {
|
||||
//the job won't be processed by multiple threads
|
||||
synchronized(job) {
|
||||
if(job.getState() != State.NEW) return;
|
||||
job.setState(State.WORKING);
|
||||
}
|
||||
try {
|
||||
Source src = job.getSource();
|
||||
Destination dst = job.getDestination();
|
||||
BoundedRangeModel progress = job.getProgress();
|
||||
|
||||
if(dst.exists()) {
|
||||
progress.setMaximum(1);
|
||||
progress.setValue(1);
|
||||
} else {
|
||||
progress.setMaximum(src.length());
|
||||
InputStream is = new BufferedInputStream(src.open());
|
||||
try {
|
||||
OutputStream os = new BufferedOutputStream(dst.open());
|
||||
try {
|
||||
byte[] buf = new byte[8 * 1024];
|
||||
int total = 0;
|
||||
for(int len; (len = is.read(buf)) != -1;) {
|
||||
if(job.getState() == State.ABORTED) throw new IOException("Job was aborted");
|
||||
progress.setValue(total += len);
|
||||
os.write(buf, 0, len);
|
||||
}
|
||||
} catch(IOException ex) {
|
||||
try {
|
||||
dst.delete();
|
||||
} catch(IOException ex1) {
|
||||
log.warn("While deleting", ex1);
|
||||
}
|
||||
throw ex;
|
||||
} finally {
|
||||
try {
|
||||
os.close();
|
||||
} catch(IOException ex) {
|
||||
log.warn("While closing", ex);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
try {
|
||||
is.close();
|
||||
} catch(IOException ex) {
|
||||
log.warn("While closing", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
job.setState(State.FINISHED);
|
||||
} catch(IOException ex) {
|
||||
job.setError(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
/**
|
||||
* AbstractBoundBean.java
|
||||
*
|
||||
* Created on 24.08.2010
|
||||
*/
|
||||
|
||||
package org.mage.plugins.card.dl.beans;
|
||||
|
||||
|
||||
import java.beans.PropertyChangeListener;
|
||||
|
||||
|
||||
/**
|
||||
* The class AbstractBoundBean.
|
||||
*
|
||||
* @version V0.0 24.08.2010
|
||||
* @author Clemens Koza
|
||||
*/
|
||||
public abstract class AbstractBoundBean implements BoundBean {
|
||||
protected PropertyChangeSupport s = new PropertyChangeSupport(this);
|
||||
|
||||
public void addPropertyChangeListener(PropertyChangeListener listener) {
|
||||
s.addPropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
|
||||
s.addPropertyChangeListener(propertyName, listener);
|
||||
}
|
||||
|
||||
public void removePropertyChangeListener(PropertyChangeListener listener) {
|
||||
s.removePropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
|
||||
s.removePropertyChangeListener(propertyName, listener);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* BoundBean.java
|
||||
*
|
||||
* Created on 24.08.2010
|
||||
*/
|
||||
|
||||
package org.mage.plugins.card.dl.beans;
|
||||
|
||||
|
||||
import java.beans.PropertyChangeListener;
|
||||
|
||||
|
||||
/**
|
||||
* The class BoundBean.
|
||||
*
|
||||
* @version V0.0 24.08.2010
|
||||
* @author Clemens Koza
|
||||
*/
|
||||
public interface BoundBean {
|
||||
public void addPropertyChangeListener(PropertyChangeListener listener);
|
||||
|
||||
public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener);
|
||||
|
||||
public void removePropertyChangeListener(PropertyChangeListener listener);
|
||||
|
||||
public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener);
|
||||
}
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
/**
|
||||
* EventListenerList.java
|
||||
*
|
||||
* Created on 08.04.2010
|
||||
*/
|
||||
|
||||
package org.mage.plugins.card.dl.beans;
|
||||
|
||||
|
||||
import static java.util.Arrays.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EventListener;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.AbstractIterator;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
|
||||
/**
|
||||
* The class EventListenerList.
|
||||
*
|
||||
* @version V0.0 08.04.2010
|
||||
* @author Clemens Koza
|
||||
*/
|
||||
public class EventListenerList extends javax.swing.event.EventListenerList {
|
||||
private static final long serialVersionUID = -7545754245081842909L;
|
||||
|
||||
/**
|
||||
* Returns an iterable over all listeners for the specified classes. the listener classes are in the specified
|
||||
* order. for every class, listeners are in the reverse order of registering. A listener contained multiple
|
||||
* times (for a single or multiple classes) is only returned the first time it occurs.
|
||||
*/
|
||||
public <T extends EventListener> Iterable<T> getIterable(final Class<? extends T>... listenerClass) {
|
||||
//transform class -> iterable
|
||||
List<Iterable<T>> l = Lists.transform(asList(listenerClass), new ClassToIterableFunction<T>());
|
||||
|
||||
//compose iterable (use an arraylist to memoize the function's results)
|
||||
final Iterable<T> it = Iterables.concat(new ArrayList<Iterable<T>>(l));
|
||||
|
||||
//transform to singleton iterators
|
||||
return new Iterable<T>() {
|
||||
public Iterator<T> iterator() {
|
||||
return new SingletonIterator<T>(it.iterator());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator over all listeners for the specified classes. the listener classes are in the specified
|
||||
* order. for every class, listeners are in the reverse order of registering. A listener contained multiple
|
||||
* times (for a single or multiple classes) is only returned the first time it occurs.
|
||||
*/
|
||||
public <T extends EventListener> Iterator<T> getIterator(Class<? extends T>... listenerClass) {
|
||||
return getIterable(listenerClass).iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates backwards over the listeners registered for a class by using the original array. The Listener runs
|
||||
* backwards, just as listener notification usually works.
|
||||
*/
|
||||
private class ListenerIterator<T> extends AbstractIterator<T> {
|
||||
private final Class<? extends T> listenerClass;
|
||||
private Object[] listeners = listenerList;
|
||||
private int index = listeners.length;
|
||||
|
||||
private ListenerIterator(Class<? extends T> listenerClass) {
|
||||
this.listenerClass = listenerClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected T computeNext() {
|
||||
for(index -= 2; index >= 0; index -= 2) {
|
||||
if(listenerClass == listeners[index]) return (T) listeners[index + 1];
|
||||
}
|
||||
return endOfData();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a class to the associated listener iterator
|
||||
*/
|
||||
private class ClassToIterableFunction<T> implements Function<Class<? extends T>, Iterable<T>> {
|
||||
|
||||
public Iterable<T> apply(final Class<? extends T> from) {
|
||||
return new Iterable<T>() {
|
||||
|
||||
public Iterator<T> iterator() {
|
||||
return new ListenerIterator<T>(from);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the delegate iterator so that every but the first occurrence of every element is ignored.
|
||||
*/
|
||||
private static class SingletonIterator<T> extends AbstractIterator<T> {
|
||||
private Iterator<T> it;
|
||||
private HashSet<T> previous = new HashSet<T>();
|
||||
|
||||
public SingletonIterator(Iterator<T> it) {
|
||||
this.it = it;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected T computeNext() {
|
||||
while(it.hasNext()) {
|
||||
T next = it.next();
|
||||
if(previous.add(next)) return next;
|
||||
}
|
||||
return endOfData();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/**
|
||||
* PropertyChangeSupport.java
|
||||
*
|
||||
* Created on 16.07.2010
|
||||
*/
|
||||
|
||||
package org.mage.plugins.card.dl.beans;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The class PropertyChangeSupport.
|
||||
*
|
||||
* @version V0.0 16.07.2010
|
||||
* @author Clemens Koza
|
||||
*/
|
||||
public class PropertyChangeSupport extends java.beans.PropertyChangeSupport {
|
||||
private static final long serialVersionUID = -4241465377828790076L;
|
||||
|
||||
private Object sourceBean;
|
||||
|
||||
public PropertyChangeSupport(Object sourceBean) {
|
||||
super(sourceBean);
|
||||
this.sourceBean = sourceBean;
|
||||
}
|
||||
|
||||
public Object getSourceBean() {
|
||||
return sourceBean;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
/**
|
||||
* This package contains bean-related utilities, most importantly
|
||||
* <ul>
|
||||
* <li>{@link net.slightlymagic.beans.BoundBean} and {@link net.slightlymagic.beans.AbstractBoundBean}, an interface and an
|
||||
* abstract class for easier property change support for bean classes</li>
|
||||
* <li>{@link net.slightlymagic.beans.properties.Properties} and its implementations. These make it easy for beans
|
||||
* to use delegates, by providing a centralized configuration for bean properties. For example, a {@link
|
||||
* net.slightlymagic.beans.properties.bound.BoundProperties} object creates properties that do automatic property
|
||||
* change notifications. What exact configuration is used is thus hidden from the delegate.</li>
|
||||
* <li>The {@link net.slightlymagic.beans.relational.Relations} class provides relational properties that model
|
||||
* bidirectional 1:1, 1:n and m:n relationships.</li>
|
||||
* </ul>
|
||||
*/
|
||||
|
||||
package org.mage.plugins.card.dl.beans;
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
/**
|
||||
* AbstractProperties.java
|
||||
*
|
||||
* Created on 24.08.2010
|
||||
*/
|
||||
|
||||
package org.mage.plugins.card.dl.beans.properties;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.mage.plugins.card.dl.beans.properties.basic.BasicProperty;
|
||||
|
||||
|
||||
/**
|
||||
* The class AbstractProperties.
|
||||
*
|
||||
* @version V0.0 24.08.2010
|
||||
* @author Clemens Koza
|
||||
*/
|
||||
public abstract class AbstractProperties implements Properties {
|
||||
public <T> Property<T> property(String name, T value) {
|
||||
return property(name, new BasicProperty<T>(value));
|
||||
}
|
||||
|
||||
public <T> Property<T> property(String name) {
|
||||
return property(name, new BasicProperty<T>());
|
||||
}
|
||||
|
||||
public <E> List<E> list(String name) {
|
||||
return list(name, new ArrayList<E>());
|
||||
}
|
||||
|
||||
public <E> Set<E> set(String name) {
|
||||
return set(name, new HashSet<E>());
|
||||
}
|
||||
|
||||
public <K, V> Map<K, V> map(String name) {
|
||||
return map(name, new HashMap<K, V>());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* AbstractProperty.java
|
||||
*
|
||||
* Created on 24.08.2010
|
||||
*/
|
||||
|
||||
package org.mage.plugins.card.dl.beans.properties;
|
||||
|
||||
|
||||
import static java.lang.String.*;
|
||||
|
||||
|
||||
/**
|
||||
* The class AbstractProperty.
|
||||
*
|
||||
* @version V0.0 24.08.2010
|
||||
* @author Clemens Koza
|
||||
*/
|
||||
public abstract class AbstractProperty<T> implements Property<T> {
|
||||
@Override
|
||||
public int hashCode() {
|
||||
T value = getValue();
|
||||
return value == null? 0:value.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if(!(obj instanceof Property<?>)) return false;
|
||||
Object value = getValue();
|
||||
Object other = ((Property<?>) obj).getValue();
|
||||
return value == other || (value != null && value.equals(other));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return valueOf(getValue());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
* CompoundProperties.java
|
||||
*
|
||||
* Created on 24.08.2010
|
||||
*/
|
||||
|
||||
package org.mage.plugins.card.dl.beans.properties;
|
||||
|
||||
|
||||
import static java.util.Arrays.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
/**
|
||||
* The class CompoundProperties.
|
||||
*
|
||||
* @version V0.0 24.08.2010
|
||||
* @author Clemens Koza
|
||||
*/
|
||||
public class CompoundProperties extends AbstractProperties {
|
||||
private List<Properties> delegates;
|
||||
|
||||
public CompoundProperties(Properties... delegates) {
|
||||
this.delegates = asList(delegates);
|
||||
Collections.reverse(this.delegates);
|
||||
}
|
||||
|
||||
public CompoundProperties(List<Properties> delegates) {
|
||||
this.delegates = new ArrayList<Properties>(delegates);
|
||||
Collections.reverse(this.delegates);
|
||||
}
|
||||
|
||||
public <T> Property<T> property(String name, Property<T> property) {
|
||||
for(Properties p:delegates)
|
||||
property = p.property(name, property);
|
||||
return property;
|
||||
}
|
||||
|
||||
public <E> List<E> list(String name, List<E> list) {
|
||||
for(Properties p:delegates)
|
||||
list = p.list(name, list);
|
||||
return list;
|
||||
}
|
||||
|
||||
public <E> Set<E> set(String name, Set<E> set) {
|
||||
for(Properties p:delegates)
|
||||
set = p.set(name, set);
|
||||
return set;
|
||||
}
|
||||
|
||||
public <K, V> Map<K, V> map(String name, Map<K, V> map) {
|
||||
for(Properties p:delegates)
|
||||
map = p.map(name, map);
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
/**
|
||||
* Properties.java
|
||||
*
|
||||
* Created on 24.08.2010
|
||||
*/
|
||||
|
||||
package org.mage.plugins.card.dl.beans.properties;
|
||||
|
||||
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.mage.plugins.card.dl.beans.properties.bound.BoundProperties;
|
||||
|
||||
|
||||
/**
|
||||
* The class Properties. A Properties object is a factory for bean properties. For example, the
|
||||
* {@link BoundProperties} class produces properties that can be observed using {@link PropertyChangeListener}s.
|
||||
*
|
||||
* @version V0.0 24.08.2010
|
||||
* @author Clemens Koza
|
||||
*/
|
||||
public interface Properties {
|
||||
public <T> Property<T> property(String name, Property<T> property);
|
||||
|
||||
public <E> List<E> list(String name, List<E> list);
|
||||
|
||||
public <E> Set<E> set(String name, Set<E> set);
|
||||
|
||||
public <K, V> Map<K, V> map(String name, Map<K, V> map);
|
||||
|
||||
|
||||
public <T> Property<T> property(String name, T value);
|
||||
|
||||
public <T> Property<T> property(String name);
|
||||
|
||||
public <E> List<E> list(String name);
|
||||
|
||||
public <E> Set<E> set(String name);
|
||||
|
||||
public <K, V> Map<K, V> map(String name);
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* Property.java
|
||||
*
|
||||
* Created on 24.08.2010
|
||||
*/
|
||||
|
||||
package org.mage.plugins.card.dl.beans.properties;
|
||||
|
||||
|
||||
/**
|
||||
* The class Property.
|
||||
*
|
||||
* @version V0.0 24.08.2010
|
||||
* @author Clemens Koza
|
||||
*/
|
||||
public interface Property<T> {
|
||||
public void setValue(T value);
|
||||
|
||||
public T getValue();
|
||||
|
||||
/**
|
||||
* A property's hash code is its value's hashCode, or {@code null} if the value is null.
|
||||
*/
|
||||
@Override
|
||||
public int hashCode();
|
||||
|
||||
/**
|
||||
* Two properties are equal if their values are equal.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj);
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/**
|
||||
* BoundProperties.java
|
||||
*
|
||||
* Created on 24.08.2010
|
||||
*/
|
||||
|
||||
package org.mage.plugins.card.dl.beans.properties.basic;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.mage.plugins.card.dl.beans.properties.AbstractProperties;
|
||||
import org.mage.plugins.card.dl.beans.properties.Property;
|
||||
|
||||
|
||||
/**
|
||||
* The class BoundProperties.
|
||||
*
|
||||
* @version V0.0 24.08.2010
|
||||
* @author Clemens Koza
|
||||
*/
|
||||
public class BasicProperties extends AbstractProperties {
|
||||
public <T> Property<T> property(String name, Property<T> value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
public <E> List<E> list(String name, List<E> list) {
|
||||
return list;
|
||||
}
|
||||
|
||||
public <E> Set<E> set(String name, Set<E> set) {
|
||||
return set;
|
||||
}
|
||||
|
||||
public <K, V> Map<K, V> map(String name, Map<K, V> map) {
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
/**
|
||||
* BasicProperty.java
|
||||
*
|
||||
* Created on 16.07.2010
|
||||
*/
|
||||
|
||||
package org.mage.plugins.card.dl.beans.properties.basic;
|
||||
|
||||
|
||||
import org.mage.plugins.card.dl.beans.properties.AbstractProperty;
|
||||
|
||||
|
||||
/**
|
||||
* The class BasicProperty.
|
||||
*
|
||||
* @version V0.0 16.07.2010
|
||||
* @author Clemens Koza
|
||||
*/
|
||||
public class BasicProperty<T> extends AbstractProperty<T> {
|
||||
private T value;
|
||||
|
||||
public BasicProperty() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public BasicProperty(T initialValue) {
|
||||
value = initialValue;
|
||||
}
|
||||
|
||||
public void setValue(T value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public T getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/**
|
||||
* BoundProperties.java
|
||||
*
|
||||
* Created on 24.08.2010
|
||||
*/
|
||||
|
||||
package org.mage.plugins.card.dl.beans.properties.bound;
|
||||
|
||||
|
||||
import static org.mage.plugins.card.dl.beans.collections.ListenableCollections.listenableList;
|
||||
import static org.mage.plugins.card.dl.beans.collections.ListenableCollections.listenableMap;
|
||||
import static org.mage.plugins.card.dl.beans.collections.ListenableCollections.listenableSet;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.mage.plugins.card.dl.beans.PropertyChangeSupport;
|
||||
import org.mage.plugins.card.dl.beans.properties.AbstractProperties;
|
||||
import org.mage.plugins.card.dl.beans.properties.Property;
|
||||
|
||||
|
||||
/**
|
||||
* The class BoundProperties.
|
||||
*
|
||||
* @version V0.0 24.08.2010
|
||||
* @author Clemens Koza
|
||||
*/
|
||||
public class BoundProperties extends AbstractProperties {
|
||||
public final PropertyChangeSupport s;
|
||||
|
||||
public BoundProperties(Object sourceBean) {
|
||||
this(new PropertyChangeSupport(sourceBean));
|
||||
}
|
||||
|
||||
public BoundProperties(PropertyChangeSupport s) {
|
||||
if(s == null) throw new IllegalArgumentException("s == null");
|
||||
this.s = s;
|
||||
}
|
||||
|
||||
public <T> Property<T> property(String name, Property<T> property) {
|
||||
return new BoundProperty<T>(s, name, property);
|
||||
}
|
||||
|
||||
public <E> List<E> list(String name, List<E> list) {
|
||||
return listenableList(list, new PropertyChangeListListener<E>(s, name));
|
||||
}
|
||||
|
||||
public <E> Set<E> set(String name, Set<E> set) {
|
||||
return listenableSet(set, new PropertyChangeSetListener<E>(s, set, name));
|
||||
}
|
||||
|
||||
public <K, V> Map<K, V> map(String name, Map<K, V> map) {
|
||||
return listenableMap(map, new PropertyChangeMapListener<K, V>(s, map, name));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
/**
|
||||
* BasicProperty.java
|
||||
*
|
||||
* Created on 16.07.2010
|
||||
*/
|
||||
|
||||
package org.mage.plugins.card.dl.beans.properties.bound;
|
||||
|
||||
|
||||
import java.beans.PropertyChangeSupport;
|
||||
|
||||
import org.mage.plugins.card.dl.beans.properties.AbstractProperty;
|
||||
import org.mage.plugins.card.dl.beans.properties.Property;
|
||||
|
||||
|
||||
/**
|
||||
* The class BasicProperty.
|
||||
*
|
||||
* @version V0.0 16.07.2010
|
||||
* @author Clemens Koza
|
||||
*/
|
||||
public class BoundProperty<T> extends AbstractProperty<T> {
|
||||
private PropertyChangeSupport s;
|
||||
private String name;
|
||||
private Property<T> property;
|
||||
|
||||
public BoundProperty(PropertyChangeSupport s, String name, Property<T> property) {
|
||||
if(property == null) throw new IllegalArgumentException();
|
||||
this.s = s;
|
||||
this.name = name;
|
||||
this.property = property;
|
||||
|
||||
}
|
||||
|
||||
public void setValue(T value) {
|
||||
T old = getValue();
|
||||
property.setValue(value);
|
||||
s.firePropertyChange(name, old, getValue());
|
||||
}
|
||||
|
||||
public T getValue() {
|
||||
return property.getValue();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* PropertyChangeListListener.java
|
||||
*
|
||||
* Created on 16.07.2010
|
||||
*/
|
||||
|
||||
package org.mage.plugins.card.dl.beans.properties.bound;
|
||||
|
||||
import org.mage.plugins.card.dl.beans.PropertyChangeSupport;
|
||||
import org.mage.plugins.card.dl.beans.collections.ListenableCollections.ListListener;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The class PropertyChangeListListener.
|
||||
*
|
||||
* @version V0.0 16.07.2010
|
||||
* @author Clemens Koza
|
||||
*/
|
||||
public class PropertyChangeListListener<E> implements ListListener<E> {
|
||||
private static final long serialVersionUID = 625853864429729560L;
|
||||
|
||||
private PropertyChangeSupport s;
|
||||
private String propertyName;
|
||||
|
||||
public PropertyChangeListListener(PropertyChangeSupport s, String propertyName) {
|
||||
this.s = s;
|
||||
this.propertyName = propertyName;
|
||||
}
|
||||
|
||||
public void add(int index, E newValue) {
|
||||
s.fireIndexedPropertyChange(propertyName, index, null, newValue);
|
||||
}
|
||||
|
||||
public void set(int index, E oldValue, E newValue) {
|
||||
s.fireIndexedPropertyChange(propertyName, index, oldValue, newValue);
|
||||
}
|
||||
|
||||
public void remove(int index, E oldValue) {
|
||||
s.fireIndexedPropertyChange(propertyName, index, oldValue, null);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
/**
|
||||
* PropertyChangeMapListener.java
|
||||
*
|
||||
* Created on 16.07.2010
|
||||
*/
|
||||
|
||||
package org.mage.plugins.card.dl.beans.properties.bound;
|
||||
|
||||
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.util.Map;
|
||||
|
||||
import org.mage.plugins.card.dl.beans.PropertyChangeSupport;
|
||||
import org.mage.plugins.card.dl.beans.collections.ListenableCollections.MapListener;
|
||||
|
||||
|
||||
/**
|
||||
* The class PropertyChangeMapListener. This listener alway fires events with {@link Map} -> {@link Map} as the
|
||||
* value parameters, as nonindexed collection properties. The events will be {@link MapEvent} instances.
|
||||
*
|
||||
* @version V0.0 16.07.2010
|
||||
* @author Clemens Koza
|
||||
*/
|
||||
public class PropertyChangeMapListener<K, V> implements MapListener<K, V> {
|
||||
private static final long serialVersionUID = 625853864429729560L;
|
||||
|
||||
private PropertyChangeSupport s;
|
||||
private Map<K, V> map;
|
||||
private String propertyName;
|
||||
|
||||
public PropertyChangeMapListener(PropertyChangeSupport s, Map<K, V> map, String propertyName) {
|
||||
this.s = s;
|
||||
this.map = map;
|
||||
this.propertyName = propertyName;
|
||||
}
|
||||
|
||||
public void put(K key, V newValue) {
|
||||
s.firePropertyChange(new MapPutEvent<K, V>(s.getSourceBean(), propertyName, map, key, newValue));
|
||||
}
|
||||
|
||||
public void set(K key, V oldValue, V newValue) {
|
||||
s.firePropertyChange(new MapSetEvent<K, V>(s.getSourceBean(), propertyName, map, key, oldValue, newValue));
|
||||
}
|
||||
|
||||
public void remove(K key, V oldValue) {
|
||||
s.firePropertyChange(new MapRemoveEvent<K, V>(s.getSourceBean(), propertyName, map, key, oldValue));
|
||||
}
|
||||
|
||||
public static abstract class MapEvent<K, V> extends PropertyChangeEvent {
|
||||
private static final long serialVersionUID = -651568020675693544L;
|
||||
|
||||
private Map<K, V> map;
|
||||
private K key;
|
||||
|
||||
public MapEvent(Object source, String propertyName, Map<K, V> map, K key) {
|
||||
super(source, propertyName, null, null);
|
||||
this.map = map;
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<K, V> getOldValue() {
|
||||
//old and new value must not be equal
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<K, V> getNewValue() {
|
||||
return map;
|
||||
}
|
||||
|
||||
public K getKey() {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
public static class MapPutEvent<K, V> extends MapEvent<K, V> {
|
||||
private static final long serialVersionUID = 6006291474676939650L;
|
||||
|
||||
private V newElement;
|
||||
|
||||
public MapPutEvent(Object source, String propertyName, Map<K, V> map, K key, V newElement) {
|
||||
super(source, propertyName, map, key);
|
||||
this.newElement = newElement;
|
||||
}
|
||||
|
||||
public V getNewElement() {
|
||||
return newElement;
|
||||
}
|
||||
}
|
||||
|
||||
public static class MapSetEvent<K, V> extends MapEvent<K, V> {
|
||||
private static final long serialVersionUID = -2419438379909500079L;
|
||||
|
||||
private V oldElement, newElement;
|
||||
|
||||
public MapSetEvent(Object source, String propertyName, Map<K, V> map, K key, V oldElement, V newElement) {
|
||||
super(source, propertyName, map, key);
|
||||
this.oldElement = oldElement;
|
||||
this.newElement = newElement;
|
||||
}
|
||||
|
||||
public V getOldElement() {
|
||||
return oldElement;
|
||||
}
|
||||
|
||||
public V getNewElement() {
|
||||
return newElement;
|
||||
}
|
||||
}
|
||||
|
||||
public static class MapRemoveEvent<K, V> extends MapEvent<K, V> {
|
||||
private static final long serialVersionUID = -2644879706878221895L;
|
||||
|
||||
private V oldElement;
|
||||
|
||||
public MapRemoveEvent(Object source, String propertyName, Map<K, V> map, K key, V oldElement) {
|
||||
super(source, propertyName, map, key);
|
||||
this.oldElement = oldElement;
|
||||
}
|
||||
|
||||
public V getOldElement() {
|
||||
return oldElement;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
/**
|
||||
* PropertyChangeSetListener.java
|
||||
*
|
||||
* Created on 16.07.2010
|
||||
*/
|
||||
|
||||
package org.mage.plugins.card.dl.beans.properties.bound;
|
||||
|
||||
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.util.Set;
|
||||
|
||||
import org.mage.plugins.card.dl.beans.PropertyChangeSupport;
|
||||
import org.mage.plugins.card.dl.beans.collections.ListenableCollections.SetListener;
|
||||
|
||||
|
||||
/**
|
||||
* The class PropertyChangeSetListener. This listener always fires events with {@link Set} -> {@link Set} as the
|
||||
* value parameters, as nonindexed collection properties. The events will be {@link SetEvent} instances.
|
||||
*
|
||||
* @version V0.0 16.07.2010
|
||||
* @author Clemens Koza
|
||||
*/
|
||||
public class PropertyChangeSetListener<E> implements SetListener<E> {
|
||||
private static final long serialVersionUID = 625853864429729560L;
|
||||
|
||||
private PropertyChangeSupport s;
|
||||
private Set<E> set;
|
||||
private String propertyName;
|
||||
|
||||
public PropertyChangeSetListener(PropertyChangeSupport s, Set<E> set, String propertyName) {
|
||||
this.s = s;
|
||||
this.set = set;
|
||||
this.propertyName = propertyName;
|
||||
}
|
||||
|
||||
public void add(E newValue) {
|
||||
s.firePropertyChange(new SetAddEvent<E>(s.getSourceBean(), propertyName, set, newValue));
|
||||
}
|
||||
|
||||
public void remove(E oldValue) {
|
||||
s.firePropertyChange(new SetRemoveEvent<E>(s.getSourceBean(), propertyName, set, oldValue));
|
||||
}
|
||||
|
||||
public static abstract class SetEvent<E> extends PropertyChangeEvent {
|
||||
private static final long serialVersionUID = -651568020675693544L;
|
||||
|
||||
private Set<E> set;
|
||||
|
||||
public SetEvent(Object source, String propertyName, Set<E> set) {
|
||||
super(source, propertyName, null, null);
|
||||
this.set = set;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<E> getOldValue() {
|
||||
//old and new value must not be equal
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<E> getNewValue() {
|
||||
return set;
|
||||
}
|
||||
}
|
||||
|
||||
public static class SetAddEvent<E> extends SetEvent<E> {
|
||||
private static final long serialVersionUID = 9041766866796759871L;
|
||||
|
||||
private E newElement;
|
||||
|
||||
public SetAddEvent(Object source, String propertyName, Set<E> set, E newElement) {
|
||||
super(source, propertyName, set);
|
||||
this.newElement = newElement;
|
||||
}
|
||||
|
||||
public E getNewElement() {
|
||||
return newElement;
|
||||
}
|
||||
}
|
||||
|
||||
public static class SetRemoveEvent<E> extends SetEvent<E> {
|
||||
private static final long serialVersionUID = -1315342339926392385L;
|
||||
|
||||
private E oldElement;
|
||||
|
||||
public SetRemoveEvent(Object source, String propertyName, Set<E> set, E oldElement) {
|
||||
super(source, propertyName, set);
|
||||
this.oldElement = oldElement;
|
||||
}
|
||||
|
||||
public E getOldElement() {
|
||||
return oldElement;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* AbstractLaternaBean.java
|
||||
*
|
||||
* Created on 25.08.2010
|
||||
*/
|
||||
|
||||
package org.mage.plugins.card.dl.lm;
|
||||
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.mage.plugins.card.dl.beans.AbstractBoundBean;
|
||||
import org.mage.plugins.card.dl.beans.EventListenerList;
|
||||
import org.mage.plugins.card.dl.beans.properties.Properties;
|
||||
import org.mage.plugins.card.dl.beans.properties.bound.BoundProperties;
|
||||
|
||||
|
||||
/**
|
||||
* The class AbstractLaternaBean.
|
||||
*
|
||||
* @version V0.0 25.08.2010
|
||||
* @author Clemens Koza
|
||||
*/
|
||||
public class AbstractLaternaBean extends AbstractBoundBean {
|
||||
protected static final Logger log = Logger.getLogger(AbstractLaternaBean.class);
|
||||
protected Properties properties = new BoundProperties(s);
|
||||
protected EventListenerList listeners = new EventListenerList();
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
/**
|
||||
* GathererSymbols.java
|
||||
*
|
||||
* Created on 25.08.2010
|
||||
*/
|
||||
|
||||
package org.mage.plugins.card.dl.sources;
|
||||
|
||||
|
||||
import static java.lang.String.format;
|
||||
import static org.mage.plugins.card.dl.DownloadJob.fromURL;
|
||||
import static org.mage.plugins.card.dl.DownloadJob.toFile;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.mage.plugins.card.dl.DownloadJob;
|
||||
|
||||
import com.google.common.collect.AbstractIterator;
|
||||
|
||||
|
||||
/**
|
||||
* The class GathererSymbols.
|
||||
*
|
||||
* @version V0.0 25.08.2010
|
||||
* @author Clemens Koza
|
||||
*/
|
||||
public class GathererSymbols implements Iterable<DownloadJob> {
|
||||
//TODO chaos and planeswalker symbol
|
||||
//chaos: http://gatherer.wizards.com/Images/Symbols/chaos.gif
|
||||
|
||||
private static final File outDir = new File("plugins/images/symbols");
|
||||
private static final String urlFmt = "http://gatherer.wizards.com/handlers/image.ashx?size=%1$s&name=%2$s&type=symbol";
|
||||
|
||||
private static final String[] sizes = {"small", "medium", "large"};
|
||||
|
||||
private static final String[] symbols = {"W", "U", "B", "R", "G",
|
||||
|
||||
"W/U", "U/B", "B/R", "R/G", "G/W", "W/B", "U/R", "B/G", "R/W", "G/U",
|
||||
|
||||
"2/W", "2/U", "2/B", "2/R", "2/G",
|
||||
|
||||
"X", "S", "T", "Q"};
|
||||
private static final int minNumeric = 0, maxNumeric = 16;
|
||||
|
||||
@Override
|
||||
public Iterator<DownloadJob> iterator() {
|
||||
return new AbstractIterator<DownloadJob>() {
|
||||
private int sizeIndex, symIndex, numeric = minNumeric;
|
||||
private File dir = new File(outDir, sizes[sizeIndex]);
|
||||
|
||||
@Override
|
||||
protected DownloadJob computeNext() {
|
||||
String sym;
|
||||
if(symIndex < symbols.length) {
|
||||
sym = symbols[symIndex++];
|
||||
} else if(numeric <= maxNumeric) {
|
||||
sym = "" + (numeric++);
|
||||
} else {
|
||||
sizeIndex++;
|
||||
if(sizeIndex == sizes.length) return endOfData();
|
||||
|
||||
symIndex = 0;
|
||||
numeric = 0;
|
||||
dir = new File(outDir, sizes[sizeIndex]);
|
||||
return computeNext();
|
||||
}
|
||||
String symbol = sym.replaceAll("/", "");
|
||||
File dst = new File(dir, symbol + ".jpg");
|
||||
|
||||
if(symbol.equals("T")) symbol = "tap";
|
||||
else if(symbol.equals("Q")) symbol = "untap";
|
||||
else if(symbol.equals("S")) symbol = "snow";
|
||||
|
||||
String url = format(urlFmt, sizes[sizeIndex], symbol);
|
||||
|
||||
return new DownloadJob(sym, fromURL(url), toFile(dst));
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +1,14 @@
|
|||
package org.mage.plugins.card.images;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.Frame;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
|
|
@ -42,6 +46,10 @@ import mage.cards.Card;
|
|||
import org.apache.log4j.Logger;
|
||||
import org.mage.plugins.card.CardUrl;
|
||||
import org.mage.plugins.card.constants.Constants;
|
||||
import org.mage.plugins.card.dl.DownloadGui;
|
||||
import org.mage.plugins.card.dl.DownloadJob;
|
||||
import org.mage.plugins.card.dl.Downloader;
|
||||
import org.mage.plugins.card.dl.sources.GathererSymbols;
|
||||
import org.mage.plugins.card.properties.SettingsManager;
|
||||
import org.mage.plugins.card.utils.CardImageUtils;
|
||||
|
||||
|
|
@ -60,6 +68,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
|||
private JLabel jLabel1;
|
||||
private static boolean offlineMode = false;
|
||||
private JCheckBox checkBox;
|
||||
private JButton downloadSymbols;
|
||||
|
||||
public static final Proxy.Type[] types = Proxy.Type.values();
|
||||
|
||||
|
|
@ -70,10 +79,10 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
|||
public static void startDownload(JFrame frame, Set<Card> allCards) {
|
||||
ArrayList<CardUrl> cards = getNeededCards(allCards);
|
||||
|
||||
if (cards == null || cards.size() == 0) {
|
||||
/*if (cards == null || cards.size() == 0) {
|
||||
JOptionPane.showMessageDialog(null, "All card pictures have been downloaded.");
|
||||
return;
|
||||
}
|
||||
}*/
|
||||
|
||||
DownloadPictures download = new DownloadPictures(cards);
|
||||
JDialog dlg = download.getDlg(frame);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,59 @@
|
|||
package org.mage.plugins.card.utils;
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Image;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.ImageObserver;
|
||||
|
||||
public class BufferedImageBuilder {
|
||||
|
||||
private static final int DEFAULT_IMAGE_TYPE = BufferedImage.TYPE_INT_RGB;
|
||||
|
||||
public BufferedImage bufferImage(Image image) {
|
||||
return bufferImage(image, DEFAULT_IMAGE_TYPE);
|
||||
}
|
||||
|
||||
public BufferedImage bufferImage(Image image, int type) {
|
||||
BufferedImage bufferedImage = new BufferedImage(image.getWidth(null), image.getHeight(null), type);
|
||||
Graphics2D g = bufferedImage.createGraphics();
|
||||
g.drawImage(image, null, null);
|
||||
//waitForImage(bufferedImage);
|
||||
return bufferedImage;
|
||||
}
|
||||
|
||||
private void waitForImage(BufferedImage bufferedImage) {
|
||||
final ImageLoadStatus imageLoadStatus = new ImageLoadStatus();
|
||||
bufferedImage.getHeight(new ImageObserver() {
|
||||
public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) {
|
||||
if (infoflags == ALLBITS) {
|
||||
imageLoadStatus.heightDone = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
bufferedImage.getWidth(new ImageObserver() {
|
||||
public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) {
|
||||
if (infoflags == ALLBITS) {
|
||||
imageLoadStatus.widthDone = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
while (!imageLoadStatus.widthDone && !imageLoadStatus.heightDone) {
|
||||
try {
|
||||
Thread.sleep(300);
|
||||
} catch (InterruptedException e) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ImageLoadStatus {
|
||||
|
||||
public boolean widthDone = false;
|
||||
public boolean heightDone = false;
|
||||
}
|
||||
|
||||
}
|
||||
5
pom.xml
5
pom.xml
|
|
@ -36,6 +36,11 @@
|
|||
<name>Java Image Scaling Repository Released</name>
|
||||
<url>svn:https://java-image-scaling.googlecode.com/svn/repo/released</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>jetlang.googlecode.com</id>
|
||||
<name>Jetlang Repository for Maven</name>
|
||||
<url>http://jetlang.googlecode.com/svn/repo/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<properties>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue