diff --git a/Mage.Client/plugins/mage-card-plugin.jar b/Mage.Client/plugins/mage-card-plugin.jar
index 45bf0f62ec8..1ad58bba6e9 100644
Binary files a/Mage.Client/plugins/mage-card-plugin.jar and b/Mage.Client/plugins/mage-card-plugin.jar differ
diff --git a/Mage.Client/src/main/java/mage/client/MageFrame.java b/Mage.Client/src/main/java/mage/client/MageFrame.java
index a31bcc88b8a..95f83f64d15 100644
--- a/Mage.Client/src/main/java/mage/client/MageFrame.java
+++ b/Mage.Client/src/main/java/mage/client/MageFrame.java
@@ -137,7 +137,7 @@ public class MageFrame extends javax.swing.JFrame {
initComponents();
setSize(1024,768);
- this.setExtendedState(JFrame.MAXIMIZED_BOTH);
+ //this.setExtendedState(JFrame.MAXIMIZED_BOTH);
session = new Session(this);
connectDialog = new ConnectDialog();
diff --git a/Mage.Client/src/main/java/mage/client/cards/BigCard.java b/Mage.Client/src/main/java/mage/client/cards/BigCard.java
index 6d13f4a0b16..5c7d1adab0e 100644
--- a/Mage.Client/src/main/java/mage/client/cards/BigCard.java
+++ b/Mage.Client/src/main/java/mage/client/cards/BigCard.java
@@ -51,6 +51,7 @@ import java.util.UUID;
import javax.swing.text.BadLocationException;
import javax.swing.text.StyledDocument;
+import mage.client.components.CardInfoPane;
import mage.client.plugins.impl.Plugins;
import org.jdesktop.swingx.JXPanel;
@@ -66,6 +67,8 @@ public class BigCard extends javax.swing.JPanel {
protected JXPanel panel;
protected boolean initState;
+ protected CardInfoPane cardInfoPane;
+
public BigCard() {
initComponents();
if (!Plugins.getInstance().isCardPluginLoaded()) {
diff --git a/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java b/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java
index 74c9e2b6210..6ed8cc69e05 100644
--- a/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java
+++ b/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java
@@ -34,7 +34,20 @@
package mage.client.deckeditor;
-import java.awt.Cursor;
+import mage.cards.Card;
+import mage.cards.decks.Deck;
+import mage.cards.decks.DeckCardLists;
+import mage.client.MageFrame;
+import mage.client.plugins.impl.Plugins;
+import mage.client.util.Event;
+import mage.client.util.Listener;
+import mage.components.CardInfoPane;
+import mage.game.GameException;
+import mage.view.CardsView;
+
+import javax.swing.*;
+import javax.swing.filechooser.FileFilter;
+import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Constructor;
@@ -42,19 +55,6 @@ import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
-import javax.swing.JFileChooser;
-import javax.swing.JOptionPane;
-import javax.swing.filechooser.FileFilter;
-
-import mage.cards.Card;
-import mage.cards.decks.Deck;
-import mage.cards.decks.DeckCardLists;
-import mage.client.MageFrame;
-import mage.client.util.Event;
-import mage.client.util.Listener;
-import mage.game.GameException;
-import mage.view.CardsView;
-
/**
*
* @author BetaSteward_at_googlemail.com
@@ -64,6 +64,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
private JFileChooser fcSelectDeck;
private JFileChooser fcImportDeck;
private Deck deck = new Deck();
+ private boolean isShowCardInfo = false;
/** Creates new form DeckEditorPanel */
public DeckEditorPanel() {
@@ -96,6 +97,9 @@ public class DeckEditorPanel extends javax.swing.JPanel {
if (System.getProperty("draft") != null) {
cardSelector.getCardsList().removeCard(card.getId());
}
+ if (cardInfoPane instanceof CardInfoPane) {
+ ((CardInfoPane)cardInfoPane).setCard(card);
+ }
break;
}
}
@@ -150,13 +154,6 @@ public class DeckEditorPanel extends javax.swing.JPanel {
}
}
- /** This method is called from within the constructor to
- * initialize the form.
- * WARNING: Do NOT modify this code. The content of this method is
- * always regenerated by the Form Editor.
- */
- @SuppressWarnings("unchecked")
- // //GEN-BEGIN:initComponents
private void initComponents() {
jSplitPane1 = new javax.swing.JSplitPane();
@@ -179,6 +176,16 @@ public class DeckEditorPanel extends javax.swing.JPanel {
bigCard.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
+ cardInfoPane = Plugins.getInstance().getCardInfoPane();
+ if (cardInfoPane != null && System.getProperty("testCardInfo") != null) {
+ cardInfoPane.setPreferredSize(new Dimension(170,230));
+ cardInfoPane.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
+ isShowCardInfo = true;
+ } else {
+ cardInfoPane = new JLabel();
+ cardInfoPane.setVisible(false);
+ }
+
lblDeckName.setLabelFor(txtDeckName);
lblDeckName.setText("Deck Name:");
@@ -225,10 +232,11 @@ public class DeckEditorPanel extends javax.swing.JPanel {
.addGroup(jPanel1Layout.createSequentialGroup()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
- .addGap(6, 6, 6)
- .addComponent(lblDeckName)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(txtDeckName, javax.swing.GroupLayout.DEFAULT_SIZE, 189, Short.MAX_VALUE))
+ .addGap(6, 6, 6)
+ .addComponent(lblDeckName)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(txtDeckName, javax.swing.GroupLayout.DEFAULT_SIZE, 189, Short.MAX_VALUE))
+ .addComponent(cardInfoPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(bigCard, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
@@ -249,17 +257,18 @@ public class DeckEditorPanel extends javax.swing.JPanel {
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
- .addComponent(txtDeckName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addComponent(lblDeckName))
+ .addComponent(txtDeckName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(lblDeckName))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
- .addComponent(btnSave)
- .addComponent(btnLoad)
- .addComponent(btnNew)
- .addComponent(btnExit))
+ .addComponent(btnSave)
+ .addComponent(btnLoad)
+ .addComponent(btnNew)
+ .addComponent(btnExit))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnImport)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 159, Short.MAX_VALUE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, isShowCardInfo ? 30 : 159, Short.MAX_VALUE)
+ .addComponent(cardInfoPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(bigCard, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
);
@@ -277,7 +286,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jSplitPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 615, Short.MAX_VALUE)
);
- }// //GEN-END:initComponents
+ }
private void btnLoadActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnLoadActionPerformed
String lastFolder = MageFrame.getPreferences().get("lastDeckFolder", "");
@@ -396,6 +405,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
private javax.swing.JTextField txtDeckName;
// End of variables declaration//GEN-END:variables
+ private JComponent cardInfoPane;
}
class DeckFilter extends FileFilter {
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 000b2727fef..61807e13ed9 100644
--- a/Mage.Client/src/main/java/mage/client/plugins/MagePlugins.java
+++ b/Mage.Client/src/main/java/mage/client/plugins/MagePlugins.java
@@ -34,4 +34,5 @@ public interface MagePlugins {
Image getManaSymbolImage(String symbol);
void onAddCard(MagePermanent card);
void onRemoveCard(MagePermanent card);
+ JComponent getCardInfoPane();
}
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 88c645203bd..eef3fa4139e 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
@@ -181,4 +181,14 @@ public class Plugins implements MagePlugins {
this.cardPlugin.onRemoveCard(card);
}
}
+
+ @Override
+ public JComponent getCardInfoPane() {
+ if (this.cardPlugin != null) {
+ return this.cardPlugin.getCardInfoPane();
+ }
+ return null;
+ }
+
+
}
diff --git a/Mage.Common/src/mage/components/CardInfoPane.java b/Mage.Common/src/mage/components/CardInfoPane.java
new file mode 100644
index 00000000000..19b1047ca23
--- /dev/null
+++ b/Mage.Common/src/mage/components/CardInfoPane.java
@@ -0,0 +1,14 @@
+package mage.components;
+
+import mage.cards.Card;
+
+/**
+ * Card info pane for displaying card rules.
+ * Supports drawing mana symbols.
+ *
+ * @author nantuko
+ */
+public interface CardInfoPane {
+ public void setCard (final Card card);
+ public boolean isCurrentCard (Card card);
+}
diff --git a/Mage.Common/src/mage/interfaces/plugin/CardPlugin.java b/Mage.Common/src/mage/interfaces/plugin/CardPlugin.java
index 72cdd0346d4..4ba61be4d29 100644
--- a/Mage.Common/src/mage/interfaces/plugin/CardPlugin.java
+++ b/Mage.Common/src/mage/interfaces/plugin/CardPlugin.java
@@ -33,4 +33,5 @@ public interface CardPlugin extends Plugin {
Image getManaSymbolImage(String symbol);
void onAddCard(MagePermanent card);
void onRemoveCard(MagePermanent card);
+ JComponent getCardInfoPane();
}
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 6cdc968b436..932e57bd155 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
@@ -84,10 +84,10 @@ public class ManaSymbols {
static public synchronized String replaceSymbolsWithHTML (String value, boolean small) {
if (small)
- return replaceSymbolsPattern.matcher(value).replaceAll("
");
+ return replaceSymbolsPattern.matcher(value).replaceAll("
");
else {
- value = value.replace("{slash}", "
");
- return replaceSymbolsPattern.matcher(value).replaceAll("
");
+ value = value.replace("{slash}", "
");
+ return replaceSymbolsPattern.matcher(value).replaceAll("
");
}
}
}
diff --git a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/card/arcane/ThreadUtils.java b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/card/arcane/ThreadUtils.java
new file mode 100644
index 00000000000..4df8c5a0d20
--- /dev/null
+++ b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/card/arcane/ThreadUtils.java
@@ -0,0 +1,44 @@
+package org.mage.card.arcane;
+
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Util method to work with threads.
+ *
+ * @author ayrat
+ */
+public class ThreadUtils {
+
+ static public ThreadPoolExecutor threadPool;
+ static private int threadCount;
+ static {
+ threadPool = new ThreadPoolExecutor(4, 4, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), new ThreadFactory() {
+ public Thread newThread (Runnable runnable) {
+ threadCount++;
+ Thread thread = new Thread(runnable, "Util" + threadCount);
+ thread.setDaemon(true);
+ return thread;
+ }
+ });
+ threadPool.prestartAllCoreThreads();
+ }
+
+ static public void sleep (int millis) {
+ try {
+ Thread.sleep(millis);
+ } catch (InterruptedException ignored) {
+ }
+ }
+
+ static public void wait (Object lock) {
+ synchronized (lock) {
+ try {
+ lock.wait();
+ } catch (InterruptedException ex) {
+ }
+ }
+ }
+}
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 dd70c1aba95..7afd87da181 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
@@ -22,6 +22,7 @@ import mage.cards.Card;
import mage.cards.CardDimensions;
import mage.cards.MagePermanent;
import mage.cards.action.ActionCallback;
+import mage.components.CardInfoPane;
import mage.interfaces.plugin.CardPlugin;
import mage.utils.CardUtil;
import mage.view.CardView;
@@ -41,6 +42,7 @@ 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;
+import org.mage.plugins.card.info.CardInfoPaneImpl;
/**
* {@link CardPlugin} implementation.
@@ -462,4 +464,9 @@ public class CardPluginImpl implements CardPlugin {
}
}
}
+
+ @Override
+ public JComponent getCardInfoPane() {
+ return new CardInfoPaneImpl();
+ }
}
diff --git a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/info/CardInfoPaneImpl.java b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/info/CardInfoPaneImpl.java
new file mode 100644
index 00000000000..e13fd59aa91
--- /dev/null
+++ b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/info/CardInfoPaneImpl.java
@@ -0,0 +1,162 @@
+package org.mage.plugins.card.info;
+
+import mage.Constants;
+import mage.cards.Card;
+import mage.components.CardInfoPane;
+import mage.utils.CardUtil;
+import org.mage.card.arcane.ManaSymbols;
+import org.mage.card.arcane.ThreadUtils;
+import org.mage.card.arcane.UI;
+
+import javax.swing.*;
+import java.awt.*;
+import java.util.List;
+
+/**
+ * Card info pane for displaying card rules.
+ * Supports drawing mana symbols.
+ *
+ * @author nantuko
+ */
+public class CardInfoPaneImpl extends JEditorPane implements CardInfoPane {
+
+ private Card currentCard;
+
+ public CardInfoPaneImpl() {
+ UI.setHTMLEditorKit(this);
+ setEditable(false);
+ setBackground(Color.white);
+ }
+
+ public void setCard (final Card card) {
+ if (card == null) return;
+ if (isCurrentCard(card)) return;
+ currentCard = card;
+
+ ThreadUtils.threadPool.submit(new Runnable() {
+ public void run () {
+ if (!card.equals(currentCard)) return;
+
+ String castingCost = UI.getDisplayManaCost(card.getManaCost().getText());
+ castingCost = ManaSymbols.replaceSymbolsWithHTML(castingCost, false);
+
+ int symbolCount = 0;
+ int offset = 0;
+ while ((offset = castingCost.indexOf("
rulings = card.getRules();
+
+ boolean smallImages = true;
+ int fontSize = 11;
+
+ String fontFamily = "tahoma";
+ /*if (prefs.fontFamily == CardFontFamily.arial)
+ fontFamily = "arial";
+ else if (prefs.fontFamily == CardFontFamily.verdana) {
+ fontFamily = "verdana";
+ }*/
+
+ final StringBuffer buffer = new StringBuffer(512);
+ buffer.append("
");
+ buffer.append("");
+ buffer.append("| ");
+ buffer.append(card.getName());
+ buffer.append(" | ");
+ buffer.append(castingCost);
+ buffer.append(" |
");
+ buffer.append("| ");
+ buffer.append(getTypes(card));
+ buffer.append(" | ");
+ switch (card.getRarity()) {
+ case RARE:
+ buffer.append("");
+ break;
+ case UNCOMMON:
+ buffer.append("");
+ break;
+ case COMMON:
+ buffer.append("");
+ break;
+ case MYTHIC:
+ buffer.append("");
+ break;
+ }
+ buffer.append(card.getExpansionSetCode().toUpperCase());
+ buffer.append(" |
");
+
+ String legal = "";
+ if (rulings.size() > 0) {
+ legal = legal.replaceAll("#([^#]+)#", "$1");
+ legal = legal.replaceAll("\\s*//\\s*", "
");
+ legal = legal.replace("\r\n", "");
+ legal += "
";
+ for (String ruling : rulings) {
+ legal += ruling;
+ legal += "
";
+ }
+ }
+
+ if (legal.length() > 0) {
+ buffer.append("
");
+ legal = legal.replaceAll("\\{this\\}", card.getName());
+ legal = legal.replaceAll("\\{source\\}", card.getName());
+ buffer.append(ManaSymbols.replaceSymbolsWithHTML(legal, smallImages));
+ }
+
+ String pt = "";
+ if (card.getCardType().contains(Constants.CardType.CREATURE)) {
+ pt = card.getPower() + "/" + card.getToughness();
+ } else if (card.getCardType().contains(Constants.CardType.PLANESWALKER)) {
+ pt = card.getLoyalty().toString();
+ }
+ if (pt.length() > 0) {
+ buffer.append("| ");
+ buffer.append(" | ");
+ buffer.append("");
+ buffer.append(pt);
+ buffer.append("");
+ buffer.append(" |
");
+ }
+
+ buffer.append("
");
+
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run () {
+ if (!card.equals(currentCard)) return;
+ setText(buffer.toString());
+ System.out.println(buffer.toString());
+ setCaretPosition(0);
+ }
+ });
+ }
+ });
+ }
+
+ private String getTypes(Card card) {
+ String types = "";
+ for (String superType : card.getSupertype()) {
+ types += superType + " ";
+ }
+ for (Constants.CardType cardType : card.getCardType()) {
+ types += cardType.toString() + " ";
+ }
+ if (card.getSubtype().size() > 0) {
+ types += "- ";
+ }
+ for (String subType : card.getSubtype()) {
+ types += subType + " ";
+ }
+ return types.trim();
+ }
+
+ public boolean isCurrentCard (Card card) {
+ return currentCard != null && card.equals(currentCard);
+ }
+}