/*
* $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.
*/
/*
* Created by IntelliJ IDEA.
* User: unknown
* Date: Dec 30, 2002
* Time: 12:42:01 PM
* To change template for new class use
* Code Style | Class Templates options (Tools | IDE Options).
*/
package VASSAL.counters;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.util.ArrayList;
import java.util.List;
import javax.swing.Box;
import javax.swing.Icon;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import VASSAL.build.module.GlobalOptions;
import VASSAL.build.module.Map;
import VASSAL.build.module.documentation.HelpFile;
import VASSAL.command.ChangeTracker;
import VASSAL.command.Command;
import VASSAL.configure.IconConfigurer;
import VASSAL.configure.IntConfigurer;
import VASSAL.configure.NamedHotKeyConfigurer;
import VASSAL.configure.StringConfigurer;
import VASSAL.i18n.PieceI18nData;
import VASSAL.i18n.TranslatablePiece;
import VASSAL.tools.NamedKeyStroke;
import VASSAL.tools.SequenceEncoder;
/**
* A GamePiece with this trait will automatically be marked whenever it is moved. A marked piece is
* indicated by drawing a specified image at a specified location
*/
public class MovementMarkable extends Decorator implements TranslatablePiece {
public static final String ID = "markmoved;";
private int xOffset = 0;
private int yOffset = 0;
private String command;
private NamedKeyStroke key;
private IconConfigurer movedIcon = new IconConfigurer(null, "Marker Image: ", "/images/moved.gif");
private boolean hasMoved = false;
public MovementMarkable() {
this(ID + "moved.gif;0;0", null);
}
public MovementMarkable(String type, GamePiece p) {
mySetType(type);
setInner(p);
}
public boolean isMoved() {
return hasMoved;
}
public void setMoved(boolean b) {
hasMoved = b;
}
public void mySetType(String type) {
SequenceEncoder.Decoder st = new SequenceEncoder.Decoder(type, ';');
st.nextToken();
movedIcon.setValue(st.nextToken());
xOffset = st.nextInt(0);
yOffset = st.nextInt(0);
command = st.nextToken("Mark Moved");
key = st.nextNamedKeyStroke('M');
}
public void mySetState(String newState) {
hasMoved = "true".equals(newState);
}
public String myGetState() {
return String.valueOf(hasMoved);
}
public String myGetType() {
SequenceEncoder se = new SequenceEncoder(';');
se.append(movedIcon.getValueString()).append(xOffset).append(yOffset).append(command).append(key);
return ID + se.getValue();
}
protected KeyCommand[] myGetKeyCommands() {
return new KeyCommand[]{new KeyCommand(command, key, Decorator.getOutermost(this), this)};
}
public Command myKeyEvent(javax.swing.KeyStroke stroke) {
if (stroke != null && key.equals(stroke)) {
ChangeTracker c = new ChangeTracker(this);
// Set the property on the entire piece so all traits can respond
Decorator.getOutermost(this)
.setProperty(Properties.MOVED, Boolean.valueOf(!hasMoved));
return c.getChangeCommand();
}
else {
return null;
}
}
public Shape getShape() {
return piece.getShape();
}
public Rectangle boundingBox() {
final Rectangle r = piece.boundingBox();
r.add(piece.boundingBox());
final Dimension d = getImageSize();
r.add(new Rectangle(xOffset, yOffset, d.width, d.height));
return r;
}
public String getName() {
return piece.getName();
}
public void draw(Graphics g, int x, int y, Component obs, double zoom) {
piece.draw(g, x, y, obs, zoom);
if (hasMoved
&& movedIcon.getIconValue() != null) {
Graphics2D g2d = (Graphics2D) g;
AffineTransform transform = g2d.getTransform();
g2d.scale(zoom, zoom);
movedIcon.getIconValue().paintIcon(obs, g,
(int) Math.round(x / zoom) + xOffset,
(int) Math.round(y / zoom) + yOffset);
g2d.setTransform(transform);
}
}
private Dimension getImageSize() {
Icon icon = movedIcon.getIconValue();
return icon != null ? new Dimension(icon.getIconWidth(), icon.getIconHeight()) : new Dimension();
}
public String getDescription() {
return "Mark When Moved";
}
public VASSAL.build.module.documentation.HelpFile getHelpFile() {
return HelpFile.getReferenceManualPage("MarkMoved.htm");
}
@Override
public Object getLocalizedProperty(Object key) {
if (Properties.MOVED.equals(key)) {
return isMoved() ? Boolean.TRUE : Boolean.FALSE;
}
else {
return super.getLocalizedProperty(key);
}
}
public Object getProperty(Object key) {
if (Properties.MOVED.equals(key)) {
return isMoved() ? Boolean.TRUE : Boolean.FALSE;
}
else {
return super.getProperty(key);
}
}
public void setProperty(Object key, Object val) {
if (Properties.MOVED.equals(key)) {
setMoved(Boolean.TRUE.equals(val));
piece.setProperty(key, val); // So other traits can respond to the property change
}
else {
super.setProperty(key, val);
}
}
public PieceEditor getEditor() {
return new Ed(this);
}
public PieceI18nData getI18nData() {
return getI18nData(command, "Mark Moved command");
}
private static class Ed implements PieceEditor {
private IconConfigurer iconConfig;
private IntConfigurer xOff;
private IntConfigurer yOff;
private StringConfigurer command;
private NamedHotKeyConfigurer key;
private Box box;
private Ed(MovementMarkable p) {
iconConfig = p.movedIcon;
box = Box.createVerticalBox();
command = new StringConfigurer(null,"Command: ",p.command);
box.add(command.getControls());
key = new NamedHotKeyConfigurer(null,"Keyboard command: ",p.key);
box.add(key.getControls());
box.add(iconConfig.getControls());
xOff = new IntConfigurer(null, "Horizontal Offset: ", p.xOffset);
yOff = new IntConfigurer(null, "Vertical Offset: ", p.yOffset);
box.add(xOff.getControls());
box.add(yOff.getControls());
}
public Component getControls() {
boolean enabled = false;
for (Map m : Map.getMapList()) {
String value = m.getAttributeValueString(Map.MARK_MOVED);
enabled = enabled
|| GlobalOptions.ALWAYS.equals(value)
|| GlobalOptions.PROMPT.equals(value);
}
if (!enabled) {
Runnable runnable = new Runnable() {
public void run() {
JOptionPane.showMessageDialog(box, "You must enable the \"Mark Pieces that Move\" option in one or more Map Windows", "Option not enabled", JOptionPane.WARNING_MESSAGE);
}
};
SwingUtilities.invokeLater(runnable);
}
return box;
}
public String getType() {
SequenceEncoder se = new SequenceEncoder(';');
se.append(iconConfig.getValueString())
.append(xOff.getValueString())
.append(yOff.getValueString())
.append(command.getValueString())
.append(key.getValueString());
return ID + se.getValue();
}
public String getState() {
return "false";
}
}
/**
* Return Property names exposed by this trait
*/
public List<String> getPropertyNames() {
ArrayList<String> l = new ArrayList<String>();
l.add(Properties.MOVED);
return l;
}
}