diff --git a/Mage.Client/pom.xml b/Mage.Client/pom.xml
index aa5782dc7bc..6da7a3174ca 100644
--- a/Mage.Client/pom.xml
+++ b/Mage.Client/pom.xml
@@ -57,6 +57,11 @@
swingx
1.6.1
+
+ org.jetlang
+ jetlang
+ 0.2.4
+
diff --git a/Mage.Client/src/main/java/mage/client/MageFrame.java b/Mage.Client/src/main/java/mage/client/MageFrame.java
index 346a95e7b42..cb54fd0c846 100644
--- a/Mage.Client/src/main/java/mage/client/MageFrame.java
+++ b/Mage.Client/src/main/java/mage/client/MageFrame.java
@@ -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);
@@ -173,6 +188,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();
diff --git a/Mage.Client/src/main/java/mage/client/plugins/MagePlugins.java b/Mage.Client/src/main/java/mage/client/plugins/MagePlugins.java
index ca033451877..ff274153e4e 100644
--- a/Mage.Client/src/main/java/mage/client/plugins/MagePlugins.java
+++ b/Mage.Client/src/main/java/mage/client/plugins/MagePlugins.java
@@ -27,6 +27,7 @@ public interface MagePlugins {
boolean isCounterPluginLoaded();
void sortPermanents(Map ui, Collection permanents);
void downloadImage(Set allCards);
+ void downloadSymbols();
int getGamesPlayed();
void addGamesPlayed();
}
diff --git a/Mage.Client/src/main/java/mage/client/plugins/impl/Plugins.java b/Mage.Client/src/main/java/mage/client/plugins/impl/Plugins.java
index 0b328227cfa..7b913e05acf 100644
--- a/Mage.Client/src/main/java/mage/client/plugins/impl/Plugins.java
+++ b/Mage.Client/src/main/java/mage/client/plugins/impl/Plugins.java
@@ -112,6 +112,11 @@ public class Plugins implements MagePlugins {
public void downloadImage(Set allCards) {
if (this.cardPlugin != null) this.cardPlugin.downloadImages(allCards);
}
+
+ @Override
+ public void downloadSymbols() {
+ if (this.cardPlugin != null) this.cardPlugin.downloadSymbols();
+ }
@Override
public int getGamesPlayed() {
diff --git a/Mage.Common/src/mage/interfaces/plugin/CardPlugin.java b/Mage.Common/src/mage/interfaces/plugin/CardPlugin.java
index e181f9065ac..dd1fba9d9b9 100644
--- a/Mage.Common/src/mage/interfaces/plugin/CardPlugin.java
+++ b/Mage.Common/src/mage/interfaces/plugin/CardPlugin.java
@@ -28,4 +28,5 @@ public interface CardPlugin extends Plugin {
MagePermanent getMageCard(CardView permanent, CardDimensions dimension, UUID gameId, ActionCallback callback);
void sortPermanents(Map ui, Collection cards);
void downloadImages(Set allCards);
+ void downloadSymbols();
}
diff --git a/Mage.Plugins/Mage.Card.Plugin/pom.xml b/Mage.Plugins/Mage.Card.Plugin/pom.xml
index f8ca19ceb0c..c1307599b06 100644
--- a/Mage.Plugins/Mage.Card.Plugin/pom.xml
+++ b/Mage.Plugins/Mage.Card.Plugin/pom.xml
@@ -45,6 +45,12 @@
0.8.4
provided
+
+ org.jetlang
+ jetlang
+ 0.2.4
+ provided
+
diff --git a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/card/arcane/CardPanel.java b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/card/arcane/CardPanel.java
index d72c9581a6f..d61515020ef 100644
--- a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/card/arcane/CardPanel.java
+++ b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/card/arcane/CardPanel.java
@@ -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);
+ }
}
}
diff --git a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/card/arcane/ManaSymbols.java b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/card/arcane/ManaSymbols.java
index 8427bc63380..39e0e27b6bc 100644
--- a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/card/arcane/ManaSymbols.java
+++ b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/card/arcane/ManaSymbols.java
@@ -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 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, " ");
diff --git a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/CardPluginImpl.java b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/CardPluginImpl.java
index f0d9188022c..abff2f7ecfe 100644
--- a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/CardPluginImpl.java
+++ b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/CardPluginImpl.java
@@ -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 allCards) {
DownloadPictures.startDownload(null, allCards);
}
+
+ @Override
+ public void downloadSymbols() {
+ final DownloadGui g = new DownloadGui(new Downloader());
+
+ Iterable 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);
+ }
}
diff --git a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/constants/Constants.java b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/constants/Constants.java
index 0713b66a342..2fdade1ba80 100644
--- a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/constants/Constants.java
+++ b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/constants/Constants.java
@@ -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;
- }
}
diff --git a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/DownloadGui.java b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/DownloadGui.java
new file mode 100644
index 00000000000..5e971cae91f
--- /dev/null
+++ b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/DownloadGui.java
@@ -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 progresses = new HashMap();
+ 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;
+ }
+ }
+}
diff --git a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/DownloadJob.java b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/DownloadJob.java
new file mode 100644
index 00000000000..bdd95bd4c4e
--- /dev/null
+++ b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/DownloadJob.java
@@ -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 = properties.property("state", State.NEW);
+ private final Property message = properties.property("message");
+ private final Property 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;
+ }
+}
diff --git a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/Downloader.java b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/Downloader.java
new file mode 100644
index 00000000000..e00ccf2f840
--- /dev/null
+++ b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/Downloader.java
@@ -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 jobs = properties.list("jobs");
+ private final Channel channel = new MemoryChannel();
+
+ private final ExecutorService pool = Executors.newCachedThreadPool();
+ private final List fibers = new ArrayList();
+
+ 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 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 {
+ @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);
+ }
+ }
+ }
+}
diff --git a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/AbstractBoundBean.java b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/AbstractBoundBean.java
new file mode 100644
index 00000000000..82f551c6fc7
--- /dev/null
+++ b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/AbstractBoundBean.java
@@ -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);
+ }
+}
diff --git a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/BoundBean.java b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/BoundBean.java
new file mode 100644
index 00000000000..a0a87ba9455
--- /dev/null
+++ b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/BoundBean.java
@@ -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);
+}
diff --git a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/EventListenerList.java b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/EventListenerList.java
new file mode 100644
index 00000000000..2814e8dbbb1
--- /dev/null
+++ b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/EventListenerList.java
@@ -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 Iterable getIterable(final Class extends T>... listenerClass) {
+ //transform class -> iterable
+ List> l = Lists.transform(asList(listenerClass), new ClassToIterableFunction());
+
+ //compose iterable (use an arraylist to memoize the function's results)
+ final Iterable it = Iterables.concat(new ArrayList>(l));
+
+ //transform to singleton iterators
+ return new Iterable() {
+ public Iterator iterator() {
+ return new SingletonIterator(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 Iterator 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 extends AbstractIterator {
+ 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 implements Function, Iterable> {
+
+ public Iterable apply(final Class extends T> from) {
+ return new Iterable() {
+
+ public Iterator iterator() {
+ return new ListenerIterator(from);
+ }
+ };
+ }
+ }
+
+ /**
+ * Filters the delegate iterator so that every but the first occurrence of every element is ignored.
+ */
+ private static class SingletonIterator extends AbstractIterator {
+ private Iterator it;
+ private HashSet previous = new HashSet();
+
+ public SingletonIterator(Iterator it) {
+ this.it = it;
+ }
+
+
+ @Override
+ protected T computeNext() {
+ while(it.hasNext()) {
+ T next = it.next();
+ if(previous.add(next)) return next;
+ }
+ return endOfData();
+ }
+ }
+}
diff --git a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/PropertyChangeSupport.java b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/PropertyChangeSupport.java
new file mode 100644
index 00000000000..961f408ba61
--- /dev/null
+++ b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/PropertyChangeSupport.java
@@ -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;
+ }
+}
diff --git a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/package-info.java b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/package-info.java
new file mode 100644
index 00000000000..f1cf99d2b69
--- /dev/null
+++ b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/package-info.java
@@ -0,0 +1,17 @@
+/**
+ * This package contains bean-related utilities, most importantly
+ *
+ * - {@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
+ * - {@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.
+ * - The {@link net.slightlymagic.beans.relational.Relations} class provides relational properties that model
+ * bidirectional 1:1, 1:n and m:n relationships.
+ *
+ */
+
+package org.mage.plugins.card.dl.beans;
+
+
diff --git a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/properties/AbstractProperties.java b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/properties/AbstractProperties.java
new file mode 100644
index 00000000000..3f992d255c1
--- /dev/null
+++ b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/properties/AbstractProperties.java
@@ -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 Property property(String name, T value) {
+ return property(name, new BasicProperty(value));
+ }
+
+ public Property property(String name) {
+ return property(name, new BasicProperty());
+ }
+
+ public List list(String name) {
+ return list(name, new ArrayList());
+ }
+
+ public Set set(String name) {
+ return set(name, new HashSet());
+ }
+
+ public Map map(String name) {
+ return map(name, new HashMap());
+ }
+
+}
diff --git a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/properties/AbstractProperty.java b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/properties/AbstractProperty.java
new file mode 100644
index 00000000000..13f105ebb23
--- /dev/null
+++ b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/properties/AbstractProperty.java
@@ -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 implements Property {
+ @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());
+ }
+}
diff --git a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/properties/CompoundProperties.java b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/properties/CompoundProperties.java
new file mode 100644
index 00000000000..cd751cb7fd5
--- /dev/null
+++ b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/properties/CompoundProperties.java
@@ -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 delegates;
+
+ public CompoundProperties(Properties... delegates) {
+ this.delegates = asList(delegates);
+ Collections.reverse(this.delegates);
+ }
+
+ public CompoundProperties(List delegates) {
+ this.delegates = new ArrayList(delegates);
+ Collections.reverse(this.delegates);
+ }
+
+ public Property property(String name, Property property) {
+ for(Properties p:delegates)
+ property = p.property(name, property);
+ return property;
+ }
+
+ public List list(String name, List list) {
+ for(Properties p:delegates)
+ list = p.list(name, list);
+ return list;
+ }
+
+ public Set set(String name, Set set) {
+ for(Properties p:delegates)
+ set = p.set(name, set);
+ return set;
+ }
+
+ public Map map(String name, Map map) {
+ for(Properties p:delegates)
+ map = p.map(name, map);
+ return map;
+ }
+}
diff --git a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/properties/Properties.java b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/properties/Properties.java
new file mode 100644
index 00000000000..80d45f7494c
--- /dev/null
+++ b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/properties/Properties.java
@@ -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 Property property(String name, Property property);
+
+ public List list(String name, List list);
+
+ public Set set(String name, Set set);
+
+ public Map map(String name, Map map);
+
+
+ public Property property(String name, T value);
+
+ public Property property(String name);
+
+ public List list(String name);
+
+ public Set set(String name);
+
+ public Map map(String name);
+}
diff --git a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/properties/Property.java b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/properties/Property.java
new file mode 100644
index 00000000000..47668e4d372
--- /dev/null
+++ b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/properties/Property.java
@@ -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 {
+ 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);
+}
diff --git a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/properties/basic/BasicProperties.java b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/properties/basic/BasicProperties.java
new file mode 100644
index 00000000000..a7bb00d54de
--- /dev/null
+++ b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/properties/basic/BasicProperties.java
@@ -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 Property property(String name, Property value) {
+ return value;
+ }
+
+ public List list(String name, List list) {
+ return list;
+ }
+
+ public Set set(String name, Set set) {
+ return set;
+ }
+
+ public Map map(String name, Map map) {
+ return map;
+ }
+}
diff --git a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/properties/basic/BasicProperty.java b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/properties/basic/BasicProperty.java
new file mode 100644
index 00000000000..388d2c25734
--- /dev/null
+++ b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/properties/basic/BasicProperty.java
@@ -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 extends AbstractProperty {
+ 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;
+ }
+}
diff --git a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/properties/bound/BoundProperties.java b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/properties/bound/BoundProperties.java
new file mode 100644
index 00000000000..4ed79704eb5
--- /dev/null
+++ b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/properties/bound/BoundProperties.java
@@ -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 Property property(String name, Property property) {
+ return new BoundProperty(s, name, property);
+ }
+
+ public List list(String name, List list) {
+ return listenableList(list, new PropertyChangeListListener(s, name));
+ }
+
+ public Set set(String name, Set set) {
+ return listenableSet(set, new PropertyChangeSetListener(s, set, name));
+ }
+
+ public Map map(String name, Map map) {
+ return listenableMap(map, new PropertyChangeMapListener(s, map, name));
+ }
+}
diff --git a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/properties/bound/BoundProperty.java b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/properties/bound/BoundProperty.java
new file mode 100644
index 00000000000..4f85a026efb
--- /dev/null
+++ b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/properties/bound/BoundProperty.java
@@ -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 extends AbstractProperty {
+ private PropertyChangeSupport s;
+ private String name;
+ private Property property;
+
+ public BoundProperty(PropertyChangeSupport s, String name, Property 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();
+ }
+}
diff --git a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/properties/bound/PropertyChangeListListener.java b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/properties/bound/PropertyChangeListListener.java
new file mode 100644
index 00000000000..54b34c6a3fa
--- /dev/null
+++ b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/properties/bound/PropertyChangeListListener.java
@@ -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 implements ListListener {
+ 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);
+ }
+}
diff --git a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/properties/bound/PropertyChangeMapListener.java b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/properties/bound/PropertyChangeMapListener.java
new file mode 100644
index 00000000000..c43a78944d4
--- /dev/null
+++ b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/properties/bound/PropertyChangeMapListener.java
@@ -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 implements MapListener {
+ private static final long serialVersionUID = 625853864429729560L;
+
+ private PropertyChangeSupport s;
+ private Map map;
+ private String propertyName;
+
+ public PropertyChangeMapListener(PropertyChangeSupport s, Map map, String propertyName) {
+ this.s = s;
+ this.map = map;
+ this.propertyName = propertyName;
+ }
+
+ public void put(K key, V newValue) {
+ s.firePropertyChange(new MapPutEvent(s.getSourceBean(), propertyName, map, key, newValue));
+ }
+
+ public void set(K key, V oldValue, V newValue) {
+ s.firePropertyChange(new MapSetEvent(s.getSourceBean(), propertyName, map, key, oldValue, newValue));
+ }
+
+ public void remove(K key, V oldValue) {
+ s.firePropertyChange(new MapRemoveEvent(s.getSourceBean(), propertyName, map, key, oldValue));
+ }
+
+ public static abstract class MapEvent extends PropertyChangeEvent {
+ private static final long serialVersionUID = -651568020675693544L;
+
+ private Map map;
+ private K key;
+
+ public MapEvent(Object source, String propertyName, Map map, K key) {
+ super(source, propertyName, null, null);
+ this.map = map;
+ this.key = key;
+ }
+
+ @Override
+ public Map getOldValue() {
+ //old and new value must not be equal
+ return null;
+ }
+
+ @Override
+ public Map getNewValue() {
+ return map;
+ }
+
+ public K getKey() {
+ return key;
+ }
+ }
+
+ public static class MapPutEvent extends MapEvent {
+ private static final long serialVersionUID = 6006291474676939650L;
+
+ private V newElement;
+
+ public MapPutEvent(Object source, String propertyName, Map map, K key, V newElement) {
+ super(source, propertyName, map, key);
+ this.newElement = newElement;
+ }
+
+ public V getNewElement() {
+ return newElement;
+ }
+ }
+
+ public static class MapSetEvent extends MapEvent {
+ private static final long serialVersionUID = -2419438379909500079L;
+
+ private V oldElement, newElement;
+
+ public MapSetEvent(Object source, String propertyName, Map 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 extends MapEvent {
+ private static final long serialVersionUID = -2644879706878221895L;
+
+ private V oldElement;
+
+ public MapRemoveEvent(Object source, String propertyName, Map map, K key, V oldElement) {
+ super(source, propertyName, map, key);
+ this.oldElement = oldElement;
+ }
+
+ public V getOldElement() {
+ return oldElement;
+ }
+ }
+}
diff --git a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/properties/bound/PropertyChangeSetListener.java b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/properties/bound/PropertyChangeSetListener.java
new file mode 100644
index 00000000000..328962e29d2
--- /dev/null
+++ b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/beans/properties/bound/PropertyChangeSetListener.java
@@ -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 implements SetListener {
+ private static final long serialVersionUID = 625853864429729560L;
+
+ private PropertyChangeSupport s;
+ private Set set;
+ private String propertyName;
+
+ public PropertyChangeSetListener(PropertyChangeSupport s, Set set, String propertyName) {
+ this.s = s;
+ this.set = set;
+ this.propertyName = propertyName;
+ }
+
+ public void add(E newValue) {
+ s.firePropertyChange(new SetAddEvent(s.getSourceBean(), propertyName, set, newValue));
+ }
+
+ public void remove(E oldValue) {
+ s.firePropertyChange(new SetRemoveEvent(s.getSourceBean(), propertyName, set, oldValue));
+ }
+
+ public static abstract class SetEvent extends PropertyChangeEvent {
+ private static final long serialVersionUID = -651568020675693544L;
+
+ private Set set;
+
+ public SetEvent(Object source, String propertyName, Set set) {
+ super(source, propertyName, null, null);
+ this.set = set;
+ }
+
+ @Override
+ public Set getOldValue() {
+ //old and new value must not be equal
+ return null;
+ }
+
+ @Override
+ public Set getNewValue() {
+ return set;
+ }
+ }
+
+ public static class SetAddEvent extends SetEvent {
+ private static final long serialVersionUID = 9041766866796759871L;
+
+ private E newElement;
+
+ public SetAddEvent(Object source, String propertyName, Set set, E newElement) {
+ super(source, propertyName, set);
+ this.newElement = newElement;
+ }
+
+ public E getNewElement() {
+ return newElement;
+ }
+ }
+
+ public static class SetRemoveEvent extends SetEvent {
+ private static final long serialVersionUID = -1315342339926392385L;
+
+ private E oldElement;
+
+ public SetRemoveEvent(Object source, String propertyName, Set set, E oldElement) {
+ super(source, propertyName, set);
+ this.oldElement = oldElement;
+ }
+
+ public E getOldElement() {
+ return oldElement;
+ }
+ }
+}
diff --git a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/lm/AbstractLaternaBean.java b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/lm/AbstractLaternaBean.java
new file mode 100644
index 00000000000..b44019add22
--- /dev/null
+++ b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/lm/AbstractLaternaBean.java
@@ -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();
+}
diff --git a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/sources/GathererSymbols.java b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/sources/GathererSymbols.java
new file mode 100644
index 00000000000..4b2c988c47c
--- /dev/null
+++ b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/dl/sources/GathererSymbols.java
@@ -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 {
+ //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 iterator() {
+ return new AbstractIterator() {
+ 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));
+ }
+ };
+ }
+}
diff --git a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/images/DownloadPictures.java b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/images/DownloadPictures.java
index 8a448fe06ae..d4021df9207 100644
--- a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/images/DownloadPictures.java
+++ b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/images/DownloadPictures.java
@@ -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 allCards) {
ArrayList 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);
@@ -147,7 +156,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
jComboBox1.setAlignmentX(Component.LEFT_ALIGNMENT);
p0.add(jComboBox1);
p0.add(Box.createVerticalStrut(5));
-
+
// Start
final JButton b = new JButton("Start download");
b.addActionListener(new ActionListener() {
diff --git a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/utils/BufferedImageBuilder.java b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/utils/BufferedImageBuilder.java
new file mode 100644
index 00000000000..cc0890cdc56
--- /dev/null
+++ b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/utils/BufferedImageBuilder.java
@@ -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;
+ }
+
+}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index a9869b1dbea..787c8ed7836 100644
--- a/pom.xml
+++ b/pom.xml
@@ -36,6 +36,11 @@
Java Image Scaling Repository Released
svn:https://java-image-scaling.googlecode.com/svn/repo/released
+
+ jetlang.googlecode.com
+ Jetlang Repository for Maven
+ http://jetlang.googlecode.com/svn/repo/
+