/*
* $Id$
*
* Copyright (c) 2004 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.build.module.map;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import VASSAL.build.AbstractConfigurable;
import VASSAL.build.AutoConfigurable;
import VASSAL.build.Buildable;
import VASSAL.build.GameModule;
import VASSAL.build.module.Map;
import VASSAL.build.module.documentation.HelpFile;
import VASSAL.command.ChangeTracker;
import VASSAL.command.Command;
import VASSAL.command.NullCommand;
import VASSAL.configure.Configurer;
import VASSAL.configure.ConfigurerFactory;
import VASSAL.configure.IconConfigurer;
import VASSAL.counters.Deck;
import VASSAL.counters.DeckVisitor;
import VASSAL.counters.DeckVisitorDispatcher;
import VASSAL.counters.GamePiece;
import VASSAL.counters.Stack;
import VASSAL.i18n.Resources;
import VASSAL.tools.LaunchButton;
import VASSAL.tools.NamedKeyStroke;
/** Adds a button to a Maps toolbar that adjusts the positions of all pieces
* so that their centroid is at the center of the map
*/
public class PieceRecenterer extends AbstractConfigurable implements DeckVisitor {
public static final String BUTTON_TEXT="text";
public static final String ICON="icon";
public static final String HOTKEY="hotkey";
public static final String TOOLTIP = "tooltip";
protected LaunchButton launch;
protected Map map;
protected DeckVisitorDispatcher dispatcher;
public PieceRecenterer() {
ActionListener al = new ActionListener() {
public void actionPerformed(ActionEvent e) {
GameModule.getGameModule().sendAndLog(recenter(map));
}
};
launch = new LaunchButton("Recenter",TOOLTIP,BUTTON_TEXT,HOTKEY,ICON,al);
dispatcher = new DeckVisitorDispatcher(this);
}
/**
* Returns a Command that moves all pieces so that their centroid is
* centered on the map.
*/
public Command recenter(Map map) {
final Command c = new NullCommand();
final GamePiece[] pieces = map.getPieces();
final Rectangle r = new Rectangle(0,0,-1,-1);
for (GamePiece p : pieces) {
if (Boolean.TRUE.equals(dispatcher.accept(p))) {
final Point pt = p.getPosition();
final Rectangle pRect = p.getShape().getBounds();
pRect.translate(pt.x,pt.y);
r.add(pRect);
}
}
if (r.height >= 0 && r.width >= 0) {
final int dx = map.mapSize().width/2-(r.x+r.width/2);
final int dy = map.mapSize().height/2-(r.y+r.height/2);
for (GamePiece p : pieces) {
if (Boolean.TRUE.equals(dispatcher.accept(p))) {
final ChangeTracker tracker = new ChangeTracker(p);
final Point pt = p.getPosition();
pt.translate(dx,dy);
p.setPosition(pt);
c.append(tracker.getChangeCommand());
}
}
}
map.repaint();
return c;
}
/** Implements {@link DeckVisitor}. Returns Boolean.TRUE if the piece should be moved */
public Object visitDeck(Deck d) {
return Boolean.TRUE;
}
/** Implements {@link DeckVisitor}. Returns Boolean.TRUE if the piece should be moved */
public Object visitDefault(GamePiece p) {
return Boolean.TRUE;
}
/** Implements {@link DeckVisitor}. Returns Boolean.TRUE if the piece should be moved */
public Object visitStack(Stack s) {
return s.getPieceCount() > 0 ? Boolean.TRUE : Boolean.FALSE;
}
public static String getConfigureTypeName() {
return Resources.getString("Editor.PieceRecenter.component_type"); //$NON-NLS-1$
}
public void addTo(Buildable parent) {
map = (Map)parent;
map.getToolBar().add(launch);
}
public Class<?>[] getAllowableConfigureComponents() {
return new Class<?>[0];
}
public String[] getAttributeDescriptions() {
return new String[]{
Resources.getString(Resources.BUTTON_TEXT),
Resources.getString(Resources.TOOLTIP_TEXT),
Resources.getString(Resources.BUTTON_ICON),
Resources.getString(Resources.HOTKEY_LABEL),
};
}
public String[] getAttributeNames() {
return new String[]{
BUTTON_TEXT,
TOOLTIP,
ICON,HOTKEY
};
}
public Class<?>[] getAttributeTypes() {
return new Class<?>[]{
String.class,
String.class,
IconConfig.class,
NamedKeyStroke.class
};
}
public static class IconConfig implements ConfigurerFactory {
public Configurer getConfigurer(AutoConfigurable c, String key, String name) {
return new IconConfigurer(key, name, "/images/recenter.gif");
}
}
public String getAttributeValueString(String key) {
return launch.getAttributeValueString(key);
}
public HelpFile getHelpFile() {
return HelpFile.getReferenceManualPage("Map.htm", "PieceRecenterer");
}
public void removeFrom(Buildable parent) {
map.getToolBar().remove(launch);
}
public void setAttribute(String key, Object value) {
launch.setAttribute(key,value);
}
}