From dda33f86a400a4a5155101d1c58860e46dba811c Mon Sep 17 00:00:00 2001
From: LevelX2 <ludwig.hirth@online.de>
Date: Sat, 1 Feb 2014 18:15:42 +0100
Subject: [PATCH] Removed more memory leaks in game and editor panes and panels
 of client.

---
 .../src/main/java/mage/client/MagePane.java   |  4 +
 .../java/mage/client/cards/DraftGrid.java     |  4 +
 .../components/ability/AbilityPicker.java     | 16 +++-
 .../components/ext/dlg/DialogManager.java     | 55 ++++++++---
 .../client/deckeditor/DeckEditorPanel.java    | 18 ++--
 .../java/mage/client/game/AbilityPicker.java  | 12 ++-
 .../main/java/mage/client/game/GamePane.java  | 35 ++-----
 .../main/java/mage/client/game/GamePanel.java | 96 +++++++++++++------
 .../java/mage/client/game/HelperPanel.java    |  1 -
 .../java/mage/client/game/PlayAreaPanel.java  | 45 +++++----
 .../java/mage/client/game/PlayerPanelExt.java |  4 +
 .../src/mage/utils/timer/PriorityTimer.java   |  4 +-
 12 files changed, 199 insertions(+), 95 deletions(-)

diff --git a/Mage.Client/src/main/java/mage/client/MagePane.java b/Mage.Client/src/main/java/mage/client/MagePane.java
index 3a57fd1dc2..066051a149 100644
--- a/Mage.Client/src/main/java/mage/client/MagePane.java
+++ b/Mage.Client/src/main/java/mage/client/MagePane.java
@@ -68,6 +68,10 @@ public abstract class MagePane extends javax.swing.JInternalFrame {
     }
 
     public void hideFrame() {
+        MageFrame.deactivate(this);
+    }
+
+    public void removeFrame() {
         KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
         try {
             this.setClosed(true);
diff --git a/Mage.Client/src/main/java/mage/client/cards/DraftGrid.java b/Mage.Client/src/main/java/mage/client/cards/DraftGrid.java
index 3a57c2ee7b..6366b6d154 100644
--- a/Mage.Client/src/main/java/mage/client/cards/DraftGrid.java
+++ b/Mage.Client/src/main/java/mage/client/cards/DraftGrid.java
@@ -142,6 +142,9 @@ public class DraftGrid extends javax.swing.JPanel implements MouseListener {
         cardEventSource.clearListeners();
     }
 
+    private void hidePopup() {
+        Plugins.getInstance().getActionCallback().mouseExited(null, null);
+    }
 
     /** This method is called from within the constructor to
      * initialize the form.
@@ -173,6 +176,7 @@ public class DraftGrid extends javax.swing.JPanel implements MouseListener {
         Object obj = e.getSource();
         if (obj instanceof MageCard) {
             this.cardEventSource.doubleClick(((MageCard)obj).getOriginal(), "pick-a-card");
+            this.hidePopup();
         }
     }
 
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 1526232b9a..3ddafd1e96 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
@@ -83,6 +83,12 @@ public class AbilityPicker extends JXPanel implements MouseWheelListener {
         this.gameId = gameId;
     }
 
+    public void cleanUp() {
+        for(MouseListener ml: this.getMouseListeners()) {
+            this.removeMouseListener(ml);
+        }
+    }
+
     public void show(AbilityPickerView choices, Point p) {
         this.choices = new ArrayList<Object>();
         this.selected = true; // to stop previous modal
@@ -111,7 +117,7 @@ public class AbilityPicker extends JXPanel implements MouseWheelListener {
         //startModal();
     }
 
-    public void initComponents() {
+    private void initComponents() {
         JLabel jLabel1;
         JLabel jLabel3;
 
@@ -156,7 +162,9 @@ public class AbilityPicker extends JXPanel implements MouseWheelListener {
         rows.setMaximumSize(new Dimension(32767, 32767));
         rows.setMinimumSize(new Dimension(67, 16));
         rows.setOpaque(false);
+
         rows.addMouseListener(new MouseAdapter() {
+            @Override
             public void mousePressed(MouseEvent evt) {
                 if (evt.getButton() == MouseEvent.BUTTON1) {
                     objectMouseClicked(evt);
@@ -230,6 +238,7 @@ public class AbilityPicker extends JXPanel implements MouseWheelListener {
 
         public final Map<String, String> cache = new HashMap<String, String>();
         
+        @Override
         public Component getListCellRendererComponent(
                 javax.swing.JList list,
                 Object value,
@@ -302,6 +311,7 @@ public class AbilityPicker extends JXPanel implements MouseWheelListener {
 
     class ImageRenderer extends DefaultListCellRenderer {
 
+        @Override
         public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
             Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
 
@@ -310,7 +320,9 @@ public class AbilityPicker extends JXPanel implements MouseWheelListener {
             label.setOpaque(false);
             label.setForeground(Color.white);
 
-            if (choices.size() <= index) return label;
+            if (choices.size() <= index) {
+                return label;
+            }
 
             Object object = choices.get(index);
             String name = object.toString();
diff --git a/Mage.Client/src/main/java/mage/client/components/ext/dlg/DialogManager.java b/Mage.Client/src/main/java/mage/client/components/ext/dlg/DialogManager.java
index b89a6e62dd..cfd3f4da35 100644
--- a/Mage.Client/src/main/java/mage/client/components/ext/dlg/DialogManager.java
+++ b/Mage.Client/src/main/java/mage/client/components/ext/dlg/DialogManager.java
@@ -1,11 +1,7 @@
 package mage.client.components.ext.dlg;
 
-import mage.client.cards.BigCard;
-import mage.client.game.FeedbackPanel;
-import mage.view.CardsView;
-
-import javax.swing.*;
-import java.awt.*;
+import java.awt.Component;
+import java.awt.Rectangle;
 import java.awt.event.MouseEvent;
 import java.awt.event.MouseListener;
 import java.awt.event.MouseMotionListener;
@@ -13,6 +9,10 @@ import java.awt.event.MouseWheelEvent;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.UUID;
+import javax.swing.JComponent;
+import mage.client.cards.BigCard;
+import mage.client.game.FeedbackPanel;
+import mage.view.CardsView;
 
 /**
  * @author mw, noxx
@@ -20,8 +20,7 @@ import java.util.UUID;
 public class DialogManager extends JComponent implements MouseListener,
         MouseMotionListener {
 
-    private static Map<UUID, DialogManager> dialogManagers = new HashMap<UUID, DialogManager>();
-    //private static final Logger log = Logger.getLogger(DialogManager.class);
+    private final static Map<UUID, DialogManager> dialogManagers = new HashMap<UUID, DialogManager>();
 
     public static DialogManager getManager(UUID gameId) {
         if (!dialogManagers.containsKey(gameId)) {
@@ -44,6 +43,21 @@ public class DialogManager extends JComponent implements MouseListener,
         ChooseDeckDialog, ChooseCommonDialog, RevealDialog
     }
 
+    /**
+     * Remove the DialogManager of the gameId
+     * 
+     * @param gameId 
+     */
+    public static void removeGame(UUID gameId) {
+        if (!dialogManagers.containsKey(gameId)) {
+            synchronized (dialogManagers) {
+                DialogManager dialogManager = dialogManagers.get(gameId);
+                dialogManager.cleanUp();
+                dialogManagers.remove(gameId);
+            }
+        }
+    }
+
     private MTGDialogs currentDialog = MTGDialogs.none;
 
     private DialogContainer dialogContainer = null;
@@ -62,7 +76,14 @@ public class DialogManager extends JComponent implements MouseListener,
     public DialogManager() {
         addMouseListener(this);
         addMouseMotionListener(this);
-        //addMouseWheelListener(this);
+    }
+
+    public void cleanUp() {
+        this.currentDialog = null;
+        this.dialogContainer = null;
+        this.removeMouseListener(this);
+        this.removeMouseMotionListener(this);
+
     }
 
     public void setScreenWidth(int screen_width) {
@@ -224,6 +245,7 @@ public class DialogManager extends JComponent implements MouseListener,
         validate();
     }
 
+    @Override
     public void mouseDragged(MouseEvent e) {
         if (bDragged == true) {
             dx = e.getX() - mx;
@@ -244,18 +266,23 @@ public class DialogManager extends JComponent implements MouseListener,
         }
     }
 
+    @Override
     public void mouseMoved(MouseEvent e) {
     }
 
+    @Override
     public void mouseClicked(MouseEvent e) {
     }
 
+    @Override
     public void mouseEntered(MouseEvent e) {
     }
 
+    @Override
     public void mouseExited(MouseEvent e) {
     }
 
+    @Override
     public void mousePressed(MouseEvent e) {
         if (e.getButton() == MouseEvent.BUTTON1) {
             j = (JComponent) getComponentAt(e.getX(), e.getY());
@@ -269,6 +296,7 @@ public class DialogManager extends JComponent implements MouseListener,
         }
     }
 
+    @Override
     public void mouseReleased(MouseEvent e) {
         bDragged = false;
         if (j instanceof DialogManager) {
@@ -279,17 +307,20 @@ public class DialogManager extends JComponent implements MouseListener,
             j.setBounds(rec);
         }
         oldRec = null;
-        if (rec == null)
+        if (rec == null) {
             return;
+        }
         if (rec.x < 0) {
             rec.x = 0;
-            if (j != null)
+            if (j != null) {
                 j.setBounds(rec);
+            }
         }
         if (rec.y < 0) {
             rec.y = 0;
-            if (j != null)
+            if (j != null) {
                 j.setBounds(rec);
+            }
         }
         j = null;
     }
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 0c2fb93e24..1d8392254f 100644
--- a/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java
+++ b/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java
@@ -116,7 +116,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
                     }
                     setTimeout(0);
                     countdown.stop();
-                    hideDeckEditor();
+                    removeDeckEditor();
                 }
             }
         });
@@ -130,6 +130,9 @@ public class DeckEditorPanel extends javax.swing.JPanel {
             updateDeckTask.cancel(true);
         }
         if (countdown != null) {
+            if (countdown.isRunning()) {
+                countdown.stop();
+            }
             for (ActionListener al : countdown.getActionListeners()) {
                 countdown.removeActionListener(al);
             }
@@ -153,7 +156,9 @@ public class DeckEditorPanel extends javax.swing.JPanel {
                 this.txtTimeRemaining.setVisible(true);
             case Sideboard:
                 this.btnSubmit.setVisible(true);
-                this.cardSelector.loadSideboard(new ArrayList<Card>(deck.getSideboard()), this.bigCard);
+                if (deck != null) {
+                    this.cardSelector.loadSideboard(new ArrayList<Card>(deck.getSideboard()), this.bigCard);
+                }
                 // TODO: take from preferences
                 this.cardSelector.switchToGrid();
 
@@ -312,7 +317,8 @@ public class DeckEditorPanel extends javax.swing.JPanel {
         Plugins.getInstance().getActionCallback().mouseExited(null, null);
     }
 
-    public void hideDeckEditor() {
+    public void removeDeckEditor() {
+        hidePopup();
         this.clear();
 
         Component c = this.getParent();
@@ -320,7 +326,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
             c = c.getParent();
         }
         if (c != null) {
-            ((DeckEditorPane) c).hideFrame();
+            ((DeckEditorPane) c).removeFrame();
         }
     }
 
@@ -610,7 +616,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
     }//GEN-LAST:event_btnNewActionPerformed
 
     private void btnExitActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnExitActionPerformed
-        hideDeckEditor();
+        removeDeckEditor();
     }//GEN-LAST:event_btnExitActionPerformed
 
     private void btnImportActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnImportActionPerformed
@@ -655,7 +661,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
         }
 
         if (MageFrame.getSession().submitDeck(tableId, deck.getDeckCardLists())) {
-            hideDeckEditor();
+            removeDeckEditor();
         }
     }
 
diff --git a/Mage.Client/src/main/java/mage/client/game/AbilityPicker.java b/Mage.Client/src/main/java/mage/client/game/AbilityPicker.java
index c07d6046a1..d8937a35b1 100644
--- a/Mage.Client/src/main/java/mage/client/game/AbilityPicker.java
+++ b/Mage.Client/src/main/java/mage/client/game/AbilityPicker.java
@@ -42,6 +42,8 @@ import java.util.Map.Entry;
 import java.util.UUID;
 
 /**
+ * ************************  U N U S E D   *********************************
+ *
  *
  * @author BetaSteward_at_googlemail.com
  */
@@ -50,7 +52,7 @@ public class AbilityPicker extends JPopupMenu implements PopupMenuListener {
     private Session session;
     private UUID gameId;
 
-    public AbilityPicker() {
+    public AbilityPicker(String ThisIsnotUsedAnymore) {
         this.addPopupMenuListener(this);
     }
 
@@ -59,8 +61,14 @@ public class AbilityPicker extends JPopupMenu implements PopupMenuListener {
         this.gameId = gameId;
     }
 
+    public void cleanUp() {
+        this.removePopupMenuListener(this);
+    }
+
     public void show(AbilityPickerView choices, Point p) {
-        if (p == null) return;
+        if (p == null) {
+            return;
+        }
         this.removeAll();
         for (Entry<UUID, String> choice: choices.getChoices().entrySet()) {
             this.add(new AbilityPickerAction(choice.getKey(), choice.getValue()));
diff --git a/Mage.Client/src/main/java/mage/client/game/GamePane.java b/Mage.Client/src/main/java/mage/client/game/GamePane.java
index 98d0872f43..9bb117251d 100644
--- a/Mage.Client/src/main/java/mage/client/game/GamePane.java
+++ b/Mage.Client/src/main/java/mage/client/game/GamePane.java
@@ -34,12 +34,9 @@
 
 package mage.client.game;
 
-import java.awt.Component;
 import java.awt.KeyboardFocusManager;
-import java.beans.PropertyVetoException;
 import java.util.UUID;
 import javax.swing.SwingUtilities;
-import mage.client.MageFrame;
 import mage.client.MagePane;
 import mage.client.dialog.MageDialog;
 import org.apache.log4j.Logger;
@@ -72,32 +69,16 @@ public class GamePane extends MagePane {
         gamePanel.showGame(gameId, playerId);
     }
 
-    public void hideGame() {
-        KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner(); 
+    public void cleanUp() {
         gamePanel.cleanUp();
+        this.getInputMap().clear();
+        this.getActionMap().clear();
+    }
 
-        try {
-            this.setClosed(true);
-        } catch (PropertyVetoException ex) {
-            logger.fatal("Closing Game: setClosed - ", ex);
-        }
-        MageFrame.deactivate(this);
-        MageFrame.getDesktop().remove(this);
-        
-        logger.warn("Remove Dialog " + this.getClass().getName() + " Components left: "+ this.getComponentCount());
-        
-        for (Component comp: this.getComponents()) {
-            logger.warn("Existing Component: " + comp.getClass().getName()); 
-        }
-
-//        this.getUI().uninstallUI(this);
-//        this.removeAll();
-//        this.dispose();
-//            this.setClosed(true);
-//        } catch (PropertyVetoException ex) {
-//            Logger.getLogger(GamePane.class.getName()).log(Level.SEVERE, "GamePane could not be closed", ex);
-//            this.dispose();
-//        }
+    public void hideGame() {
+        KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();       
+        this.cleanUp();
+        this.removeFrame();
     }
 
     public void watchGame(UUID gameId) {
diff --git a/Mage.Client/src/main/java/mage/client/game/GamePanel.java b/Mage.Client/src/main/java/mage/client/game/GamePanel.java
index 4a45db60b2..0574c215aa 100644
--- a/Mage.Client/src/main/java/mage/client/game/GamePanel.java
+++ b/Mage.Client/src/main/java/mage/client/game/GamePanel.java
@@ -39,6 +39,7 @@ import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.awt.event.ComponentAdapter;
 import java.awt.event.ComponentEvent;
+import java.awt.event.ComponentListener;
 import java.awt.event.InputEvent;
 import java.awt.event.KeyEvent;
 import java.awt.event.MouseAdapter;
@@ -199,39 +200,28 @@ public final class GamePanel extends javax.swing.JPanel {
         MageFrame.removeGame(gameId);
         saveDividerLocations();
         this.gameChatPanel.disconnect();
+        this.userChatPanel.disconnect();
 
-        for (MouseListener ml :this.getMouseListeners()) {
-            this.removeMouseListener(ml);
-        }
-        for (MouseListener ml :this.btnConcede.getMouseListeners()) {
-            this.btnConcede.removeMouseListener(ml);
-        }
-        for (MouseListener ml :this.btnEndTurn.getMouseListeners()) {
-            this.btnEndTurn.removeMouseListener(ml);
-        }
-        for (MouseListener ml :this.btnSwitchHands.getMouseListeners()) {
-            this.btnSwitchHands.removeMouseListener(ml);
-        }
+        this.removeListener();
 
-        for (ActionListener al :this.btnStopWatching.getActionListeners()) {
-            this.btnStopWatching.removeActionListener(al);
-        }
-        for (ActionListener al :this.btnNextPlay.getActionListeners()) {
-            this.btnNextPlay.removeActionListener(al);
-        }
         for(Map.Entry<UUID, PlayAreaPanel>  playAreaPanelEntry: players.entrySet()) {            
             playAreaPanelEntry.getValue().CleanUp();
-            // playAreaPanelEntry.getValue().getUI().uninstallUI(playAreaPanelEntry.getValue());
-            // playAreaPanelEntry.getValue().removeAll();
         }
         this.players.clear();
         
-        this.pnlBattlefield.removeAll();
+        jLayeredPane.remove(abilityPicker);
+        this.abilityPicker.cleanUp();
 
-        this.getUI().uninstallUI(this);
+        jLayeredPane.remove(DialogManager.getManager(gameId));
+        DialogManager.removeGame(gameId);
+        
+        this.getInputMap().clear();
+        this.getActionMap().clear();
+
+        // this.pnlBattlefield.removeAll();
+        // this.getUI().uninstallUI(this);
 
         if (pickNumber != null) {
-            MageFrame.getDesktop().remove(pickNumber);
             pickNumber.removeDialog();
         }
         for (ExileZoneDialog exile: exiles.values()) {
@@ -240,16 +230,13 @@ public final class GamePanel extends javax.swing.JPanel {
         for (ShowCardsDialog reveal: revealed.values()) {
             reveal.hideDialog();
         }
-        this.jSplitPane0.getUI().uninstallUI(jSplitPane0);
-        this.jSplitPane0.removeAll();
-        
+
         try {
             Component popupContainer = MageFrame.getUI().getComponent(MageComponents.POPUP_CONTAINER);
             popupContainer.setVisible(false);
         } catch (InterruptedException ex) {
             logger.fatal("popupContainer error:", ex);
         }
-//        this.removeAll();
     }
 
     private void saveDividerLocations() {
@@ -877,8 +864,8 @@ public final class GamePanel extends javax.swing.JPanel {
         });
 
         int c = JComponent.WHEN_IN_FOCUSED_WINDOW;
-        KeyStroke ks = KeyStroke.getKeyStroke(KeyEvent.VK_F4, 0);
 
+        KeyStroke ks = KeyStroke.getKeyStroke(KeyEvent.VK_F4, 0);
         this.getInputMap(c).put(ks, "F4_PRESS");
         this.getActionMap().put("F4_PRESS", new AbstractAction() {
             @Override
@@ -1028,6 +1015,7 @@ public final class GamePanel extends javax.swing.JPanel {
             }
         });
 
+        // Replay panel to control replay of games
         javax.swing.GroupLayout gl_pnlReplay = new javax.swing.GroupLayout(pnlReplay);
         pnlReplay.setLayout(gl_pnlReplay);
         gl_pnlReplay.setHorizontalGroup(
@@ -1052,6 +1040,7 @@ public final class GamePanel extends javax.swing.JPanel {
             .addComponent(btnPreviousPlay, javax.swing.GroupLayout.PREFERRED_SIZE, 31, Short.MAX_VALUE)
         );
 
+        // Game info panel (buttons on the right panel)
         javax.swing.GroupLayout gl_pnlGameInfo = new javax.swing.GroupLayout(pnlGameInfo);
         pnlGameInfo.setLayout(gl_pnlGameInfo);
         gl_pnlGameInfo.setHorizontalGroup(
@@ -1222,6 +1211,57 @@ public final class GamePanel extends javax.swing.JPanel {
         );
     }
 
+    private void removeListener() {
+        for (MouseListener ml :this.getMouseListeners()) {
+            this.removeMouseListener(ml);
+        }
+        for (MouseListener ml :this.btnConcede.getMouseListeners()) {
+            this.btnConcede.removeMouseListener(ml);
+        }
+        for (MouseListener ml :this.btnEndTurn.getMouseListeners()) {
+            this.btnEndTurn.removeMouseListener(ml);
+        }
+        for (MouseListener ml :this.btnSwitchHands.getMouseListeners()) {
+            this.btnSwitchHands.removeMouseListener(ml);
+        }
+        for (ActionListener al :this.btnPlay.getActionListeners()) {
+            this.btnPlay.removeActionListener(al);
+        }
+        for (ActionListener al :this.btnStopWatching.getActionListeners()) {
+            this.btnStopWatching.removeActionListener(al);
+        }
+        for (ActionListener al :this.btnStopReplay.getActionListeners()) {
+            this.btnStopReplay.removeActionListener(al);
+        }
+        for (ActionListener al :this.btnNextPlay.getActionListeners()) {
+            this.btnNextPlay.removeActionListener(al);
+        }
+        for (ActionListener al :this.btnNextPlay.getActionListeners()) {
+            this.btnNextPlay.removeActionListener(al);
+        }
+        for (ActionListener al :this.btnPreviousPlay.getActionListeners()) {
+            this.btnPreviousPlay.removeActionListener(al);
+        }
+        for (ActionListener al :this.btnSkipForward.getActionListeners()) {
+            this.btnSkipForward.removeActionListener(al);
+        }
+
+        final BasicSplitPaneUI myUi = (BasicSplitPaneUI) jSplitPane0.getUI();
+        final BasicSplitPaneDivider divider = myUi.getDivider();
+        final JButton upArrowButton = (JButton) divider.getComponent(0);
+        for (ActionListener al: upArrowButton.getActionListeners()) {
+            upArrowButton.removeActionListener(al);
+        }
+        final JButton downArrowButton = (JButton) divider.getComponent(1);
+        for (ActionListener al: downArrowButton.getActionListeners()) {
+            downArrowButton.removeActionListener(al);
+        }
+
+        for (ComponentListener cl : this.getComponentListeners()) {
+            this.removeComponentListener(cl);
+        }
+    }
+
     private void btnConcedeActionPerformed(java.awt.event.ActionEvent evt) {
         if (modalQuestion("Are you sure you want to concede?", "Confirm concede") == JOptionPane.YES_OPTION) {
             session.concedeGame(gameId);
diff --git a/Mage.Client/src/main/java/mage/client/game/HelperPanel.java b/Mage.Client/src/main/java/mage/client/game/HelperPanel.java
index 8aa258a234..5330b2c28c 100644
--- a/Mage.Client/src/main/java/mage/client/game/HelperPanel.java
+++ b/Mage.Client/src/main/java/mage/client/game/HelperPanel.java
@@ -49,7 +49,6 @@ public class HelperPanel extends JPanel {
     //private javax.swing.JButton btnStopTimer;
 
     private MageTextArea textArea;
-    private javax.swing.JScrollPane jScrollPane1;
 
     private javax.swing.JButton linkLeft;
     private javax.swing.JButton linkRight;
diff --git a/Mage.Client/src/main/java/mage/client/game/PlayAreaPanel.java b/Mage.Client/src/main/java/mage/client/game/PlayAreaPanel.java
index 0d738c0098..648035972e 100644
--- a/Mage.Client/src/main/java/mage/client/game/PlayAreaPanel.java
+++ b/Mage.Client/src/main/java/mage/client/game/PlayAreaPanel.java
@@ -38,10 +38,13 @@ import javax.swing.LayoutStyle.ComponentPlacement;
 import java.awt.*;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
+import java.awt.event.KeyListener;
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
 import java.awt.event.MouseListener;
 import java.util.UUID;
+import javax.swing.event.MenuKeyListener;
+import javax.swing.plaf.basic.BasicPopupMenuUI;
 
 /**
  *
@@ -49,6 +52,7 @@ import java.util.UUID;
  */
 public class PlayAreaPanel extends javax.swing.JPanel {
 
+    private final JPopupMenu popupMenu;
     private UUID playerId;
     private UUID gameId;
     private boolean smallMode = false;
@@ -63,8 +67,9 @@ public class PlayAreaPanel extends javax.swing.JPanel {
         initComponents();
         setOpaque(false);
         battlefieldPanel.setOpaque(false);
+        popupMenu = new JPopupMenu();
         if (isPlayer) {
-            addPopupMenu();
+            addPopupMenuPlayer();
         } else {
             addPopupMenuWatcher();
         }
@@ -80,16 +85,32 @@ public class PlayAreaPanel extends javax.swing.JPanel {
     public void CleanUp() {
         for (MouseListener ml :battlefieldPanel.getMainPanel().getMouseListeners()) {
             battlefieldPanel.getMainPanel().removeMouseListener(ml);
-        }        
-        this.removeAll();
-        this.getUI().uninstallUI(this);
+        }
+        playerPanel.cleanUp();
+        for (KeyListener kl: popupMenu.getKeyListeners()) {
+            popupMenu.removeKeyListener(kl);
+        }
+        for (MenuKeyListener mkl: popupMenu.getMenuKeyListeners()) {
+            popupMenu.removeMenuKeyListener(mkl);
+        }
+
+        for (Component child : popupMenu.getComponents()) {
+            if (child instanceof JMenuItem) {
+                JMenuItem menuItem = (JMenuItem) child;
+                for (ActionListener al: menuItem.getActionListeners()) {
+                    menuItem.removeActionListener(al);
+                }
+            }
+        }
+        for (MouseListener ml :battlefieldPanel.getMainPanel().getMouseListeners()) {
+            battlefieldPanel.getMainPanel().removeMouseListener(ml);
+        }
+
     }
 
-    private void addPopupMenu() {
-        final JPopupMenu popupMenu;
-        JMenuItem menuItem;
+    private void addPopupMenuPlayer() {
 
-        popupMenu = new JPopupMenu();
+        JMenuItem menuItem;
 
         menuItem = new JMenuItem("F2 - Confirm");
         popupMenu.add(menuItem);
@@ -170,11 +191,6 @@ public class PlayAreaPanel extends javax.swing.JPanel {
             }
         });
 
-//        Pmenu.addSeparator();
-//
-//        menuItem = new JMenuItem("Cancel");
-//        Pmenu.add(menuItem);
-
         battlefieldPanel.getMainPanel().addMouseListener(new MouseAdapter() {
             @Override
             public void mouseReleased(MouseEvent Me) {
@@ -186,11 +202,8 @@ public class PlayAreaPanel extends javax.swing.JPanel {
     }
 
     private void addPopupMenuWatcher() {
-        final JPopupMenu popupMenu;
         JMenuItem menuItem;
 
-        popupMenu = new JPopupMenu();
-
         menuItem = new JMenuItem("Stop watching");
         popupMenu.add(menuItem);
 
diff --git a/Mage.Client/src/main/java/mage/client/game/PlayerPanelExt.java b/Mage.Client/src/main/java/mage/client/game/PlayerPanelExt.java
index 2d0f63afed..1a8370a18f 100644
--- a/Mage.Client/src/main/java/mage/client/game/PlayerPanelExt.java
+++ b/Mage.Client/src/main/java/mage/client/game/PlayerPanelExt.java
@@ -152,6 +152,10 @@ public class PlayerPanelExt extends javax.swing.JPanel {
         }
     }
 
+    public void cleanUp() {
+        this.timer.cancel();
+    }
+
     public void update(PlayerView player) {
         this.player = player;
         int playerLife = player.getLife();
diff --git a/Mage.Common/src/mage/utils/timer/PriorityTimer.java b/Mage.Common/src/mage/utils/timer/PriorityTimer.java
index 90911c8ddd..73c0d9ff72 100644
--- a/Mage.Common/src/mage/utils/timer/PriorityTimer.java
+++ b/Mage.Common/src/mage/utils/timer/PriorityTimer.java
@@ -95,7 +95,9 @@ public class PriorityTimer extends TimerTask {
                 }
             }
         }
-        if (logger.isDebugEnabled()) logger.debug("Count is: " + count);
+        if (logger.isDebugEnabled()) {
+            logger.debug("Count is: " + count);
+        }
         //System.out.println("Count is: " + count);
         if (count <= 0) {
             cancel();