Game log hyperlink to tooltip can create client error
Got this error while testing the hyperlink to tooltip window from the game log.

```
FATAL 2016-03-01 22:12:46,766 MAGE Client UI error                                                                       =>[AWT-EventQueue-0] EDTExceptionHandler.handle 
java.lang.IllegalArgumentException: Width (-60) and height (-60) cannot be <= 0
    at java.awt.image.DirectColorModel.createCompatibleWritableRaster(DirectColorModel.java:1016)
    at java.awt.GraphicsConfiguration.createCompatibleImage(GraphicsConfiguration.java:186)
    at org.jdesktop.swingx.graphics.GraphicsUtilities.createCompatibleTranslucentImage(GraphicsUtilities.java:237)
    at mage.client.components.MageRoundPane.setBounds(MageRoundPane.java:87)
    at java.awt.Component.move(Component.java:2111)
    at java.awt.Component.setLocation(Component.java:2100)
    at java.awt.Component.setLocation(Component.java:2132)
    at mage.client.components.ColorPane$1.hyperlinkUpdate(ColorPane.java:63)
    at javax.swing.JEditorPane.fireHyperlinkUpdate(JEditorPane.java:345)
    at javax.swing.text.html.HTMLEditorKit$LinkController.fireEvents(HTMLEditorKit.java:957)
    at javax.swing.text.html.HTMLEditorKit$LinkController.mouseMoved(HTMLEditorKit.java:731)
    at java.awt.AWTEventMulticaster.mouseMoved(AWTEventMulticaster.java:330)
    at java.awt.Component.processMouseMotionEvent(Component.java:6580)
    at javax.swing.JComponent.processMouseMotionEvent(JComponent.java:3342)
    at java.awt.Component.processEvent(Component.java:6304)
    at java.awt.Container.processEvent(Container.java:2236)
    at java.awt.Component.dispatchEventImpl(Component.java:4891)
    at java.awt.Container.dispatchEventImpl(Container.java:2294)
    at java.awt.Component.dispatchEvent(Component.java:4713)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4888)
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4538)
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4466)
    at java.awt.Container.dispatchEventImpl(Container.java:2280)
    at java.awt.Window.dispatchEventImpl(Window.java:2750)
    at java.awt.Component.dispatchEvent(Component.java:4713)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
    at java.awt.EventQueue.access$500(EventQueue.java:97)
    at java.awt.EventQueue$3.run(EventQueue.java:709)
    at java.awt.EventQueue$3.run(EventQueue.java:703)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
    at java.awt.EventQueue$4.run(EventQueue.java:731)
    at java.awt.EventQueue$4.run(EventQueue.java:729)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
```

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 370459a266..aa6d5be1aa 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("(<font color=[^>]*>([^<]*)) (\\[[0-9a-fA-F]*\\])</font>", "<a href='#$2'>$1</a> $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 efed293521..5d46d46db9 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 67429dd5e8..cb63a4d543 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<String> 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 30eac766e4..f0db80d705 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 @@
                           <EmptySpace max="-2" attributes="0"/>
                           <Component id="btnImport" min="-2" max="-2" attributes="0"/>
                           <EmptySpace max="-2" attributes="0"/>
+                          <Component id="btnGenDeck" min="-2" max="-2" attributes="0"/>
+                          <EmptySpace max="-2" attributes="0"/>
                           <Component id="btnAddLand" min="-2" max="-2" attributes="0"/>   
                           <EmptySpace max="-2" attributes="0"/>
                           <Component id="btnSubmit" min="-2" max="-2" attributes="0"/>                                                    
@@ -110,6 +112,7 @@
                   <EmptySpace max="-2" attributes="0"/>
                   <Group type="103" groupAlignment="3" attributes="0">
                       <Component id="btnImport" alignment="3" min="-2" max="-2" attributes="0"/>
+                      <Component id="btnGenDeck" alignment="3" min="-2" max="-2" attributes="0"/>
                       <Component id="btnAddLand" alignment="3" min="-2" max="-2" attributes="0"/>
                       <Component id="btnSubmit" alignment="3" min="-2" max="-2" attributes="0"/>                      
                   </Group>
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 377b69adda..d9be9c4e20 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 9a59abd173..6436e0172b 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 81bc28210b..f76efc4af0 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<String, ExpansionInfo> 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 7e76349d6a..0df1894a87 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());

['Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.java', 'Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java', 'Mage.Client/src/main/java/mage/client/components/ColorPane.java', 'Mage.Client/src/main/java/mage/client/components/ability/AbilityPicker.java', 'Mage.Client/src/main/java/mage/client/deck/generator/DeckGenerator.java', 'Mage.Client/src/main/java/org/mage/plugins/card/CardPluginImpl.java', 'Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.form', 'Mage.Client/src/main/java/mage/client/util/sets/ConstructedFormats.java']