/* * $Id$ * * Copyright (c) 2000-2003 by Rodney Kinney * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License (LGPL) as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, copies are available * at http://www.opensource.org. */ package VASSAL.counters; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Enumeration; import java.util.Iterator; import java.util.List; import VASSAL.command.Command; import VASSAL.command.NullCommand; public class KeyBuffer { private static KeyBuffer theBuffer; private List<GamePiece> pieces; private BoundsTracker bounds; private Comparator<GamePiece> pieceSorter = new PieceSorter(); private KeyBuffer() { pieces = new ArrayList<GamePiece>(); bounds = new BoundsTracker(); } public static void init(KeyBuffer kb) { if (theBuffer == null) theBuffer = kb; } public static KeyBuffer getBuffer() { if (theBuffer == null) { theBuffer = new KeyBuffer(); } return theBuffer; } public void add(GamePiece p) { // FIXME: should we use a HashSet or LinkedHashSet instead to make contains() // checks faster? Is insertion order important? if (p != null && !pieces.contains(p)) { pieces.add(p); p.setProperty(Properties.SELECTED, Boolean.TRUE); } } public void clear() { for (GamePiece p : pieces) { p.setProperty(Properties.SELECTED, null); } pieces.clear(); } public void remove(GamePiece p) { if (p != null) { p.setProperty(Properties.SELECTED, null); pieces.remove(p); } } public boolean contains(GamePiece p) { if (p instanceof Stack) { for (Iterator<GamePiece> i = ((Stack) p).getPiecesIterator(); i.hasNext();) { if (!pieces.contains(i.next())) { return false; } } return true; } else { return pieces.contains(p); } } public boolean isEmpty() { return pieces.isEmpty(); } public Command keyCommand(javax.swing.KeyStroke stroke) { sort(pieceSorter); Command comm = new NullCommand(); bounds.clear(); // Copy contents into new list, because contents may change // as a result of key commands ArrayList<GamePiece> targets = new ArrayList<GamePiece>(pieces); // Reverse the order if this is a "Move Up" or "Move to Bottom" keystroke if (targets.size() > 0) { GamePiece top = targets.get(0); if (top.getMap() != null) { if (stroke.equals(top.getMap().getStackMetrics().getMoveBottomKey()) || stroke.equals(top.getMap().getStackMetrics().getMoveUpKey())) { Collections.reverse(targets); } } } for (GamePiece p : targets) { bounds.addPiece(p); p.setProperty(Properties.SNAPSHOT, PieceCloner.getInstance().clonePiece(p)); // save state prior to command Command c2 = p.keyEvent(stroke); comm = comm.append(c2); bounds.addPiece(p); } bounds.repaint(); return comm; } public Iterator<GamePiece> getPiecesIterator() { return pieces.iterator(); } /** @deprecated Use {@link #getPiecesIterator()} instead. */ @Deprecated public Enumeration<GamePiece> getPieces() { return Collections.enumeration(pieces); } public void sort(Comparator<GamePiece> comp) { Collections.sort(pieces, comp); } /** * * @param stack * @return true if a child of the specified Stack is selected */ public boolean containsChild(Stack stack) { for (Iterator<GamePiece> i = stack.getPiecesIterator(); i.hasNext();) { if (contains(i.next())) { return true; } } return false; } }