diff --git a/Mage.Client/src/main/java/mage/client/components/ColorPane.java b/Mage.Client/src/main/java/mage/client/components/ColorPane.java index 370459a2664..aa6d5be1aac 100644 --- a/Mage.Client/src/main/java/mage/client/components/ColorPane.java +++ b/Mage.Client/src/main/java/mage/client/components/ColorPane.java @@ -2,13 +2,28 @@ package mage.client.components; import java.awt.BorderLayout; import java.awt.Color; +import java.awt.Component; import java.awt.Graphics; +import java.awt.Point; + import javax.swing.JEditorPane; import javax.swing.JPanel; import javax.swing.JTextPane; +import javax.swing.SwingUtilities; +import javax.swing.event.HyperlinkEvent; +import javax.swing.event.HyperlinkEvent.EventType; +import javax.swing.event.HyperlinkListener; import javax.swing.text.html.HTMLDocument; import javax.swing.text.html.HTMLEditorKit; +import mage.cards.repository.CardInfo; +import mage.cards.repository.CardRepository; +import mage.client.MageFrame; +import mage.client.dialog.PreferencesDialog; +import mage.client.util.gui.GuiDisplayUtil; +import mage.components.CardInfoPane; +import mage.view.CardView; + /** * Enhanced {@link JTextPane} with text highlighting support. * @@ -18,10 +33,52 @@ public class ColorPane extends JEditorPane { HTMLEditorKit kit = new HTMLEditorKit(); HTMLDocument doc = new HTMLDocument(); + private int tooltipDelay; public ColorPane() { this.setEditorKit(kit); this.setDocument(doc); + addHyperlinkListener(new HyperlinkListener() { + + @Override + public void hyperlinkUpdate(final HyperlinkEvent e) { + tooltipDelay = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_SHOW_TOOLTIPS_DELAY, 300); + if (tooltipDelay == 0) { + return; + } + String name = e.getDescription().substring(1); + CardInfo card = CardRepository.instance.findCard(name); + try { + final Component container = MageFrame.getUI().getComponent(MageComponents.POPUP_CONTAINER); + if (e.getEventType() == EventType.EXITED) { + setPopupVisibility(container, false); + } else { + CardInfoPane cardInfoPane = (CardInfoPane) MageFrame.getUI().getComponent(MageComponents.CARD_INFO_PANE); + cardInfoPane.setCard(new CardView(card.getMockCard()), container); + Point location = new Point(getLocationOnScreen().x - container.getWidth(), (int) MageFrame.getDesktop() + .getMousePosition().getY()); + Component parentComponent = MageFrame.getInstance(); + location = GuiDisplayUtil.keepComponentInsideParent(location, parentComponent.getLocationOnScreen(), container, + parentComponent); + container.setLocation(location); + setPopupVisibility(container, true); + } + } catch (InterruptedException e1) { + e1.printStackTrace(); + } + } + + private void setPopupVisibility(final Component container, final boolean show) throws InterruptedException { + final Component c = MageFrame.getUI().getComponent(MageComponents.DESKTOP_PANE); + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + container.setVisible(show); + c.repaint(); + } + }); + } + }); } /** @@ -45,6 +102,7 @@ public class ColorPane extends JEditorPane { public void append(String text) { try { + text = text.replaceAll("(]*>([^<]*)) (\\[[0-9a-fA-F]*\\])", "$1 $3"); setEditable(true); kit.insertHTML(doc, doc.getLength(), text, 0, 0, null); setEditable(false); diff --git a/Mage.Client/src/main/java/mage/client/components/ability/AbilityPicker.java b/Mage.Client/src/main/java/mage/client/components/ability/AbilityPicker.java index efed293521b..5d46d46db97 100644 --- a/Mage.Client/src/main/java/mage/client/components/ability/AbilityPicker.java +++ b/Mage.Client/src/main/java/mage/client/components/ability/AbilityPicker.java @@ -14,6 +14,7 @@ import org.apache.log4j.Logger; import org.jdesktop.layout.GroupLayout; import org.jdesktop.layout.LayoutStyle; import org.jdesktop.swingx.JXPanel; +import org.jsoup.Jsoup; import org.mage.card.arcane.ManaSymbols; import org.mage.card.arcane.UI; @@ -434,6 +435,7 @@ public class AbilityPicker extends JXPanel implements MouseWheelListener { if (choice == null || choice.isEmpty()) { return choice; } + choice = Jsoup.parse(choice).text(); // decode HTML entities and strip tags return choice.substring(0, 1).toUpperCase() + choice.substring(1); } diff --git a/Mage.Client/src/main/java/mage/client/deck/generator/DeckGenerator.java b/Mage.Client/src/main/java/mage/client/deck/generator/DeckGenerator.java index 67429dd5e8c..cb63a4d543a 100644 --- a/Mage.Client/src/main/java/mage/client/deck/generator/DeckGenerator.java +++ b/Mage.Client/src/main/java/mage/client/deck/generator/DeckGenerator.java @@ -54,6 +54,14 @@ import mage.util.TournamentUtil; */ public class DeckGenerator { + public static class DeckGeneratorException extends RuntimeException { + + public DeckGeneratorException(String message) { + super(message); + } + + } + private static final int MAX_TRIES = 8196; private static DeckGeneratorDialog genDialog; private static DeckGeneratorPool genPool; @@ -82,6 +90,9 @@ public class DeckGenerator { String format = genDialog.getSelectedFormat(); List setsToUse = ConstructedFormats.getSetsByFormat(format); + if (setsToUse == null) { + throw new DeckGeneratorException("Deck sets aren't initialized; please connect to a server to update the database."); + } if (setsToUse.isEmpty()) { // Default to using all sets setsToUse = ExpansionRepository.instance.getSetCodes(); diff --git a/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.form b/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.form index 30eac766e46..f0db80d7055 100644 --- a/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.form +++ b/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.form @@ -83,6 +83,8 @@ + + @@ -110,6 +112,7 @@ + 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 377b69adda8..d9be9c4e207 100644 --- a/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java +++ b/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java @@ -60,9 +60,9 @@ import mage.client.MageFrame; import mage.client.cards.BigCard; import mage.client.cards.ICardGrid; import mage.client.constants.Constants.DeckEditorMode; -import static mage.client.constants.Constants.DeckEditorMode.FREE_BUILDING; -import static mage.client.constants.Constants.DeckEditorMode.LIMITED_BUILDING; -import static mage.client.constants.Constants.DeckEditorMode.SIDEBOARDING; +import mage.client.deck.generator.DeckGenerator; +import mage.client.deck.generator.DeckGenerator.DeckGeneratorException; + import mage.client.dialog.AddLandDialog; import mage.client.plugins.impl.Plugins; import mage.client.util.Event; @@ -173,6 +173,7 @@ public class DeckEditorPanel extends javax.swing.JPanel { this.cardSelector.switchToGrid(); this.btnExit.setVisible(false); this.btnImport.setVisible(false); + this.btnGenDeck.setVisible(false); if (!MageFrame.getSession().isTestMode()) { this.btnLoad.setVisible(false); } @@ -195,6 +196,7 @@ public class DeckEditorPanel extends javax.swing.JPanel { //this.cardTableSelector.loadCards(this.bigCard); this.btnExit.setVisible(true); this.btnImport.setVisible(true); + this.btnGenDeck.setVisible(true); if (!MageFrame.getSession().isTestMode()) { this.btnLoad.setVisible(true); } @@ -504,6 +506,7 @@ public class DeckEditorPanel extends javax.swing.JPanel { btnImport = new javax.swing.JButton(); btnSubmit = new javax.swing.JButton(); btnAddLand = new javax.swing.JButton(); + btnGenDeck = new javax.swing.JButton(); txtTimeRemaining = new javax.swing.JTextField(); jSplitPane1.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT); @@ -591,6 +594,15 @@ public class DeckEditorPanel extends javax.swing.JPanel { btnAddLandActionPerformed(evt); } }); + + btnGenDeck.setText("Generate"); + btnGenDeck.setName("btnGenDeck"); + btnGenDeck.addActionListener(new java.awt.event.ActionListener() { + @Override + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnGenDeckActionPerformed(evt); + } + }); txtTimeRemaining.setEditable(false); txtTimeRemaining.setForeground(java.awt.Color.red); @@ -626,6 +638,8 @@ public class DeckEditorPanel extends javax.swing.JPanel { .addContainerGap() .addComponent(btnImport) .addContainerGap() + .addComponent(btnGenDeck) + .addContainerGap() .addComponent(btnAddLand) .addContainerGap() .addComponent(btnSubmit)) @@ -650,6 +664,7 @@ public class DeckEditorPanel extends javax.swing.JPanel { .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(btnImport) + .addComponent(btnGenDeck) .addComponent(btnAddLand) .addComponent(btnSubmit)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) @@ -801,6 +816,21 @@ public class DeckEditorPanel extends javax.swing.JPanel { refreshDeck(); }//GEN-LAST:event_btnAddLandActionPerformed + private void btnGenDeckActionPerformed(ActionEvent evt) { + try { + setCursor(new Cursor(Cursor.WAIT_CURSOR)); + String path = DeckGenerator.generateDeck(); + deck = Deck.load(DeckImporterUtil.importDeck(path), true, true); + } catch (GameException ex) { + JOptionPane.showMessageDialog(MageFrame.getDesktop(), ex.getMessage(), "Error loading generated deck", JOptionPane.ERROR_MESSAGE); + }catch (DeckGeneratorException ex) { + JOptionPane.showMessageDialog(MageFrame.getDesktop(), ex.getMessage(), "Generator error", JOptionPane.ERROR_MESSAGE); + } finally { + setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + } + refreshDeck(); + } + // Variables declaration - do not modify//GEN-BEGIN:variables private mage.client.cards.BigCard bigCard; private javax.swing.JButton btnExit; @@ -816,6 +846,7 @@ public class DeckEditorPanel extends javax.swing.JPanel { private javax.swing.JTextField txtDeckName; private javax.swing.JButton btnSubmit; private javax.swing.JButton btnAddLand; + private javax.swing.JButton btnGenDeck; private JComponent cardInfoPane; private javax.swing.JTextField txtTimeRemaining; // End of variables declaration//GEN-END:variables diff --git a/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.java b/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.java index 9a59abd1730..6436e0172bd 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.java @@ -66,6 +66,7 @@ import static mage.client.dialog.PreferencesDialog.KEY_CONNECT_FLAG; import mage.client.preference.MagePreferences; import mage.client.util.Config; import mage.client.util.gui.countryBox.CountryItemEditor; +import mage.client.util.sets.ConstructedFormats; import mage.remote.Connection; import org.apache.log4j.Logger; @@ -442,6 +443,7 @@ public class ConnectDialog extends MageDialog { private void connected() { this.saveSettings(); this.hideDialog(); + ConstructedFormats.ensureLists(); } private void keyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_keyTyped diff --git a/Mage.Client/src/main/java/mage/client/util/sets/ConstructedFormats.java b/Mage.Client/src/main/java/mage/client/util/sets/ConstructedFormats.java index 81bc28210b6..f76efc4af01 100644 --- a/Mage.Client/src/main/java/mage/client/util/sets/ConstructedFormats.java +++ b/Mage.Client/src/main/java/mage/client/util/sets/ConstructedFormats.java @@ -50,6 +50,12 @@ public class ConstructedFormats { } + public static void ensureLists() { + if (getSetsByFormat(ConstructedFormats.STANDARD) == null) { + buildLists(); + } + } + private static void buildLists() { GregorianCalendar cutoff; // month is zero based so January = 0 @@ -60,6 +66,7 @@ public class ConstructedFormats { cutoff = new GregorianCalendar(calendar.get(Calendar.YEAR) - 2, Calendar.SEPTEMBER, 1); } final Map expansionInfo = new HashMap<>(); + formats.clear(); // prevent NPE on sorting if this is not the first try for (ExpansionInfo set : ExpansionRepository.instance.getAll()) { expansionInfo.put(set.getName(), set); formats.add(set.getName()); @@ -207,10 +214,11 @@ public class ConstructedFormats { } }); - - formats.add(0, MODERN); - formats.add(0, EXTENDED); - formats.add(0, STANDARD); + if (!formats.isEmpty()) { + formats.add(0, MODERN); + formats.add(0, EXTENDED); + formats.add(0, STANDARD); + } formats.add(0, ALL); } diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/CardPluginImpl.java b/Mage.Client/src/main/java/org/mage/plugins/card/CardPluginImpl.java index 7e76349d6ad..0df1894a878 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/CardPluginImpl.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/CardPluginImpl.java @@ -31,6 +31,7 @@ import net.xeoh.plugins.base.annotations.meta.Author; import org.apache.log4j.Logger; import org.mage.card.arcane.Animation; import org.mage.card.arcane.CardPanel; +import org.mage.card.arcane.ManaSymbols; import org.mage.plugins.card.dl.DownloadGui; import org.mage.plugins.card.dl.DownloadJob; import org.mage.plugins.card.dl.Downloader; @@ -540,6 +541,7 @@ public class CardPluginImpl implements CardPlugin { @Override public void windowClosing(WindowEvent e) { g.getDownloader().dispose(); + ManaSymbols.loadImages(); } }); d.setLayout(new BorderLayout());