gt:         if (wasBusy) return;
context: package org.arcanist.client;
  
  import java.awt.Point;
  import java.awt.Rectangle;
  import java.awt.event.ActionEvent;
  import java.awt.event.ActionListener;
  import java.awt.event.MouseEvent;
  import java.awt.event.MouseMotionListener;
  import java.awt.image.BufferedImage;
  import javax.swing.ButtonGroup;
  import javax.swing.JCheckBoxMenuItem;
  import javax.swing.JComponent;
  import javax.swing.JFileChooser;
  import javax.swing.JMenu;
  import javax.swing.JMenuItem;
  import javax.swing.JOptionPane;
  import javax.swing.JPopupMenu;
  import javax.swing.JRadioButtonMenuItem;
  import javax.swing.SwingUtilities;
  import javax.swing.event.EventListenerList;
  import javax.swing.event.ListDataEvent;
  import javax.swing.event.ListDataListener;
  import java.io.BufferedWriter;
  import java.io.File;
  import java.io.FileWriter;
  import java.io.FileNotFoundException;
  import java.io.IOException;
  import java.util.ArrayList;
  import java.util.List;
  import java.util.Random;
  
  import org.arcanist.client.*;
  import org.arcanist.util.*;
  
  
  /**
   * An array of cards.
   * A deck uses the image of one of its
   * members to represent itself on the table.
   */
  public class Deck implements ActionListener, GuiInterruptListener, CardListContainer {
    private ArcanistCCGFrame frame = null;
  
    private Deck pronoun = this;
  
    /** Deck image. */
    private DeckComponent deckComp;
  
    private List<Card> deckList;
  
  
    private boolean faceUp = true;
    private boolean locked = false;
    private boolean autoface = true;
    private boolean bottom = false;
    private char drawOffset = 'D';
    private int newCardOffsetH = Prefs.defaultNewCardOffsetH;
    private int newCardOffsetV = Prefs.defaultNewCardOffsetV;
  
  
    /** Should this be inert. */
    private boolean inUse = false;
  
    /** An array of Dependent objects. */
    private List<Dependent> dependentArray = new ArrayList<Dependent>();
  
    protected EventListenerList listenerList = new EventListenerList();
  
    /** Context menu. */
    private JPopupMenu popup = null;
  
    private JCheckBoxMenuItem lockMenuItem = new JCheckBoxMenuItem("Position Lock");
    private JCheckBoxMenuItem autofaceMenuItem = new JCheckBoxMenuItem("AutoFace");
    private JCheckBoxMenuItem facingMenuItem = new JCheckBoxMenuItem("FaceUp");
    private JCheckBoxMenuItem addBottomMenuItem = new JCheckBoxMenuItem("Add to Bottom");
    private JRadioButtonMenuItem settingsDirUMenuItem = new JRadioButtonMenuItem("Up");
    private JRadioButtonMenuItem settingsDirDMenuItem = new JRadioButtonMenuItem("Down");
    private JRadioButtonMenuItem settingsDirLMenuItem = new JRadioButtonMenuItem("Left");
    private JRadioButtonMenuItem settingsDirRMenuItem = new JRadioButtonMenuItem("Right");
  
    private JMenuItem shuffleMenuItem = new JMenuItem("Shuffle");
    private JMenuItem drawXMenuItem = new JMenuItem("Draw X Cards...");
    private JMenuItem randomMenuItem = new JMenuItem("Grab a Random Card");
    private JMenuItem searchMenuItem = new JMenuItem("Search...");
    private JMenuItem listMenuItem = new JMenuItem("List Contents...");
    private JMenuItem dupMenuItem = new JMenuItem("Duplicate");
    private JMenuItem saveMenuItem = new JMenuItem("Save...");
    private JMenuItem reverseMenuItem = new JMenuItem("Reverse");
    private JMenuItem removeMenuItem = new JMenuItem("Remove");
  
    private GuiInterruptMouseAdapter deckListener = null;
  
  
    public Deck(ArcanistCCGFrame f, List<Card> newDeckList, int positionX, int positionY, boolean facing) {
      frame = f;
  
      deckList = newDeckList;
  
      BufferedImage image = Prefs.Cache.getImg(Prefs.defaultEmptyDeckPath);
      deckComp = new DeckComponent(frame, image);
  
      faceUp = facing;
      deckComp.setBounds(positionX, positionY, image.getWidth()+4, image.getHeight()+4);
      deckComp.setToolTipText("Deck/Discard ("+ deckList.size() +" cards)");
  
      ButtonGroup radioDirGroup = new ButtonGroup();
        radioDirGroup.add(settingsDirUMenuItem);
        radioDirGroup.add(settingsDirDMenuItem);
        radioDirGroup.add(settingsDirLMenuItem);
        radioDirGroup.add(settingsDirRMenuItem);
  
      //Setup Popup menu
      popup = new JPopupMenu();
        // See top: shuffleMenuItem
        // See top: drawXMenuItem
        // See top: randomMenuItem
        // See top: searchMenuItem
        // See top: listMenuItem
        JMenu popupSettingsSubMenu = new JMenu("Settings");
          // See top: lockMenuItem (setLocked accesses it)
          // See top: autofaceMenuItem (setAutoFace accesses it)
            autofaceMenuItem.setSelected(autoface);
          // See top: facingMenuItem (setFacing accesses it)
            facingMenuItem.setSelected(facing);
          // See top: addBottomMenuItem (setToBottom accesses it)
          JMenu popupSettingsDirSubMenu = new JMenu("Card Offset");
            // See top: settingsDirUMenuItem
            // See top: settingsDirDMenuItem
              settingsDirDMenuItem.setSelected(true);
            // See top: settingsDirLMenuItem
            // See top: settingsDirRMenuItem
        // See top: dupMenuItem
        // See top: saveMenuItem
        // See top: reverseMenuItem
        // See top: removeMenuItem
      popup.add(shuffleMenuItem);
      popup.add(drawXMenuItem);
      popup.add(randomMenuItem);
      popup.add(searchMenuItem);
      popup.add(listMenuItem);
      popup.add(popupSettingsSubMenu);
        popupSettingsSubMenu.add(lockMenuItem);
        popupSettingsSubMenu.add(autofaceMenuItem);
        popupSettingsSubMenu.add(facingMenuItem);
        popupSettingsSubMenu.add(addBottomMenuItem);
        popupSettingsSubMenu.add(popupSettingsDirSubMenu);
          popupSettingsDirSubMenu.add(settingsDirUMenuItem);
          popupSettingsDirSubMenu.add(settingsDirDMenuItem);
          popupSettingsDirSubMenu.add(settingsDirLMenuItem);
          popupSettingsDirSubMenu.add(settingsDirRMenuItem);
      popup.add(dupMenuItem);
      popup.add(saveMenuItem);
      popup.add(reverseMenuItem);
      popup.add(removeMenuItem);
  
  
      shuffleMenuItem.addActionListener(this);
      drawXMenuItem.addActionListener(this);
      randomMenuItem.addActionListener(this);
      searchMenuItem.addActionListener(this);
      listMenuItem.addActionListener(this);
      lockMenuItem.addActionListener(this);
      autofaceMenuItem.addActionListener(this);
      facingMenuItem.addActionListener(this);
      addBottomMenuItem.addActionListener(this);
      settingsDirUMenuItem.addActionListener(this);
      settingsDirDMenuItem.addActionListener(this);
      settingsDirLMenuItem.addActionListener(this);
      settingsDirRMenuItem.addActionListener(this);
      dupMenuItem.addActionListener(this);
      saveMenuItem.addActionListener(this);
      reverseMenuItem.addActionListener(this);
      removeMenuItem.addActionListener(this);
  
      deckListener = new GuiInterruptMouseAdapter() {
        boolean wasBusy = true;                                // Remembers not to unlock on release
        MouseMotionListener dragability;
        int xdist=0, ydist=0;
        JComponent dragObj = deckComp;
  
        public void mouseEntered(MouseEvent e) {               // Update JumboView
          JumboView jumboFrame = frame.getJumboFrame();
          if (jumboFrame != null && jumboFrame.isJumboActive()) {
            if (!frame.isDragging() && deckList.size() > 0) {
              Card topCard = getCard(deckList.size()-1);
              if ( getFacing() == true || topCard.getBackName().length() > 0 ) {
                boolean preferText = jumboFrame.getPreferText();
                if (e.isShiftDown()) preferText = !preferText;
  
                if (topCard.isText() == true || preferText) {
                  if (getFacing() == true)
                    frame.getJumboFrame().updateJumboText(new CardTextPanel(topCard.getFrontName(), topCard.getSetAbbrev(), false));
                  else if (topCard.getBackName().length() > 0)
                    frame.getJumboFrame().updateJumboText(new CardTextPanel(topCard.getBackName(), topCard.getSetAbbrev(), false));
                }
                else {
                  if (getFacing() == true)
                    frame.getJumboFrame().updateJumboImage(topCard.getFrontPath());
                  else if (topCard.getBackName().length()>0)
                    frame.getJumboFrame().updateJumboImage(topCard.getBackPath());
                }
              }
            }
          }
        }
  
        public void mousePressed(MouseEvent e) {
          wasBusy = false;                                     //Reset the var
          if (pronoun.isInUse()) {wasBusy = true; return;}
  
          deckComp.grabFocus();
  
          if (e.getButton() == 1) {
            if (getLocked() == false) {
              xdist = e.getX();
              ydist = e.getY();
              ArcanistCCG.NetManager.deckUse(arrayID());
              frame.setDragging(true);
  
              DragGhost dragGhost = frame.getDragGhost();
              dragGhost.setOffset(xdist, ydist);
              dragGhost.setSourceObject(dragObj);
              dragGhost.setSnap(true);
              frame.addDragGhost();
              frame.getTablePane().revalidate();
              frame.getTablePane().repaint();
            }
          }
          //Right-Click Popup menu
          //  Technically This should be in both pressed and released
          //  Mac checks the trigger on press, Win on release
          //  But only macs have 1-button mice, which need the trigger check ;)
          if (e.getButton() == 3 || e.isPopupTrigger()) {popup.show(e.getComponent(), e.getX(), e.getY());}
        }
  
        public void mouseReleased(MouseEvent e) {
          if (wasBusy == true) return;
                                                               //A Click triggers all 3: P,R,C
                                                               //So clicking briefly adds the listener
          DragGhost dragGhost = frame.getDragGhost();
          boolean moved = dragGhost.hasMoved();
          dragGhost.setSourceObject(null);
          frame.removeDragGhost();
          frame.setDragging(false);
          frame.getTablePane().revalidate();
          frame.getTablePane().repaint();
  
          ArcanistCCG.NetManager.deckUnuse(arrayID());
  
          boolean dropped = false;
          if (moved && !dropped) {
            Hand tmpHand = null;
            int handsCount = frame.getHandCount();
            // Add this deck to a hand if dragged onto one
            for (int i = 0; i < handsCount; i++) {
              tmpHand = frame.getHand(i);
              Point handSpace = SwingUtilities.convertPoint(dragObj, e.getPoint(), tmpHand);
              if ( tmpHand.contains(handSpace.x, handSpace.y) && tmpHand.isInUse() == false ) {
                ArcanistCCG.NetManager.deckHand(arrayID(), i);
  
                dropped = true;
                break;
              }
            }
          }
          if (moved && !dropped) {
            Deck tmpDeck = null;
            int decksCount = frame.getDeckCount();
            // Add this deck to another if dragged onto one
            for (int i = 0; i < decksCount; i++) {
              tmpDeck = frame.getDeck(i);
              Point deckSpace = SwingUtilities.convertPoint(dragObj, e.getPoint(), tmpDeck.getComponent());
              if ( tmpDeck.getComponent().contains(deckSpace.x, deckSpace.y) && tmpDeck.isInUse() == false ) {
                if (tmpDeck.equals(pronoun)) continue;
  
                boolean prevToBottom = tmpDeck.getToBottom();
                // Set AddToBottom if shift is held
                if (e.isShiftDown()) {
                  if (prevToBottom == false) {
                    ArcanistCCG.NetManager.deckSetToBottom(i, true);
                  }
                }
                if (JOptionPane.showInternalConfirmDialog(frame.getDesktop(), "Are You SURE You Want To Combine Decks?", "Combine Decks?", JOptionPane.YES_NO_OPTION) != JOptionPane.YES_OPTION) break;
  
                ArcanistCCG.NetManager.deckDeck(arrayID(), i);
                // //pronoun.removeFromTable();
                // //tmpDeck.addDeck(pronoun);
                // //tmpDeck.refresh();
  
                // Revert AddToBottom if necessary
                if (e.isShiftDown()) {
                  if (prevToBottom == false) {
                    ArcanistCCG.NetManager.deckSetToBottom(i, false);
                  }
                  String chatAlias = ArcanistCCG.NetManager.getPlayerAlias();
                  ArcanistCCG.NetManager.chatNotice(ChatPanel.STYLE_NOTICE1, "--"+ chatAlias +" added a deck under a deck--");
                }
  
                dropped = true;
                break;
              }
            }
          }
          if (moved && !dropped) {
            e = SwingUtilities.convertMouseEvent(dragObj, e, deckComp.getParent());  //Convert deck coords to table coords
            Point snapPoint = frame.getTablePane().getNearestGridPoint( new Point(e.getX()-xdist, e.getY()-ydist) );
  
            ArcanistCCG.NetManager.deckMove(arrayID(), (int)snapPoint.getX(), (int)snapPoint.getY());
            moved = false;
          }
  
          frame.getTablePane().repaint();
        }
  
        public void mouseClicked(MouseEvent e) {
  