/*
* $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.awt.Component;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.InputEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.Box;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.KeyStroke;
import VASSAL.build.module.documentation.HelpFile;
import VASSAL.command.Command;
import VASSAL.tools.SequenceEncoder;
/**
* Decorator that filters events to prevent a GamePiece from
* being selected and/or moved.
*
* Note: The Alt selection filter was originally implemented
* as a ctl-shift filter, but this conflicts with the standard counter
* selection interface and has not worked since v3.0.
*
*/
public class Immobilized extends Decorator implements EditablePiece {
public static final String ID = "immob;";
protected boolean shiftToSelect = false;
protected boolean altToSelect = false;
protected boolean ignoreGrid = false;
protected boolean neverSelect = false;
protected boolean neverMove = false;
protected boolean moveIfSelected = false;
protected EventFilter selectFilter;
protected EventFilter moveFilter;
protected static final char MOVE_SELECTED = 'I';
protected static final char MOVE_NORMAL = 'N';
protected static final char NEVER_MOVE = 'V';
protected static final char IGNORE_GRID = 'g';
protected static final char SHIFT_SELECT = 'i';
protected static final char ALT_SELECT = 'c'; //NB. Using 'c' to maintain compatibility with old ctl-shift version
protected static final char NEVER_SELECT = 'n';
public class UseShift implements EventFilter {
public boolean rejectEvent(InputEvent evt) {
return !evt.isShiftDown() && !Boolean.TRUE.equals(getProperty(Properties.SELECTED));
}
};
public class UseAlt implements EventFilter {
public boolean rejectEvent(InputEvent evt) {
return !evt.isAltDown() && !Boolean.TRUE.equals(getProperty(Properties.SELECTED));
}
};
protected class MoveIfSelected implements EventFilter {
public boolean rejectEvent(InputEvent evt) {
return !Boolean.TRUE.equals(getProperty(Properties.SELECTED));
}
}
protected static EventFilter NEVER = new EventFilter() {
public boolean rejectEvent(InputEvent evt) {
return true;
}
};
public Immobilized() {
this(null, Immobilized.ID);
}
public Immobilized(GamePiece p, String type) {
setInner(p);
mySetType(type);
}
public void mySetType(String type) {
shiftToSelect = false;
altToSelect = false;
neverSelect = false;
ignoreGrid = false;
neverMove = false;
moveIfSelected = false;
SequenceEncoder.Decoder st = new SequenceEncoder.Decoder(type, ';');
st.nextToken();
String selectionOptions = st.nextToken("");
String movementOptions = st.nextToken("");
if (selectionOptions.indexOf(SHIFT_SELECT) >= 0) {
shiftToSelect = true;
moveIfSelected = true;
}
if (selectionOptions.indexOf(ALT_SELECT) >= 0) {
altToSelect = true;
moveIfSelected = true;
}
if (selectionOptions.indexOf(NEVER_SELECT) >= 0) {
neverSelect = true;
neverMove = true;
}
if (selectionOptions.indexOf(IGNORE_GRID) >= 0) {
ignoreGrid = true;
}
if (movementOptions.length() > 0) {
switch (movementOptions.charAt(0)) {
case NEVER_MOVE:
neverMove = true;
moveIfSelected = false;
break;
case MOVE_SELECTED:
neverMove = false;
moveIfSelected = true;
break;
default :
neverMove = false;
moveIfSelected = false;
}
}
if (neverSelect) {
selectFilter = NEVER;
}
else if (shiftToSelect) {
selectFilter = new UseShift();
}
else if (altToSelect) {
selectFilter = new UseAlt();
}
else {
selectFilter = null;
}
if (neverMove) {
moveFilter = NEVER;
}
else if (moveIfSelected) {
moveFilter = new MoveIfSelected();
}
else {
moveFilter = null;
}
}
public String getName() {
return piece.getName();
}
public KeyCommand[] myGetKeyCommands() {
return new KeyCommand[0];
}
public Command myKeyEvent(KeyStroke e) {
return null;
}
@Override
public Object getLocalizedProperty(Object key) {
if (Properties.NO_STACK.equals(key)) {
return Boolean.TRUE;
}
else if (Properties.TERRAIN.equals(key)) {
return Boolean.valueOf(moveIfSelected || neverMove);
}
else if (Properties.IGNORE_GRID.equals(key)) {
return Boolean.valueOf(ignoreGrid);
}
else if (Properties.SELECT_EVENT_FILTER.equals(key)) {
return selectFilter;
}
else if (Properties.MOVE_EVENT_FILTER.equals(key)) {
return moveFilter;
}
else if (Properties.NON_MOVABLE.equals(key)) {
return neverMove;
}
else {
return super.getLocalizedProperty(key);
}
}
public Object getProperty(Object key) {
if (Properties.NO_STACK.equals(key)) {
return Boolean.TRUE;
}
else if (Properties.TERRAIN.equals(key)) {
return Boolean.valueOf(moveIfSelected || neverMove);
}
else if (Properties.IGNORE_GRID.equals(key)) {
return Boolean.valueOf(ignoreGrid);
}
else if (Properties.SELECT_EVENT_FILTER.equals(key)) {
return selectFilter;
}
else if (Properties.MOVE_EVENT_FILTER.equals(key)) {
return moveFilter;
}
else if (Properties.NON_MOVABLE.equals(key)) {
return neverMove;
}
else {
return super.getProperty(key);
}
}
public void draw(Graphics g, int x, int y, Component obs, double zoom) {
piece.draw(g, x, y, obs, zoom);
}
public Rectangle boundingBox() {
return piece.boundingBox();
}
public Shape getShape() {
return piece.getShape();
}
public String myGetType() {
final StringBuilder buffer = new StringBuilder(ID);
if (neverSelect) {
buffer.append(NEVER_SELECT);
}
else if (shiftToSelect) {
buffer.append(SHIFT_SELECT);
}
else if (altToSelect) {
buffer.append(ALT_SELECT);
}
if (ignoreGrid) {
buffer.append(IGNORE_GRID);
}
buffer.append(';');
if (neverMove) {
buffer.append(NEVER_MOVE);
}
else if (moveIfSelected) {
buffer.append(MOVE_SELECTED);
}
else {
buffer.append(MOVE_NORMAL);
}
return buffer.toString();
}
public String myGetState() {
return "";
}
public void mySetState(String s) {
}
public String getDescription() {
return "Does not stack";
}
public HelpFile getHelpFile() {
return HelpFile.getReferenceManualPage("NonStacking.htm");
}
public PieceEditor getEditor() {
return new Ed(this);
}
/**
* Return Property names exposed by this trait
*/
public List<String> getPropertyNames() {
ArrayList<String> l = new ArrayList<String>();
l.add(Properties.TERRAIN);
l.add(Properties.IGNORE_GRID);
l.add(Properties.NON_MOVABLE);
return l;
}
private static class Ed implements PieceEditor {
private JComboBox selectionOption;
private JComboBox movementOption;
private JCheckBox ignoreGridBox;
private Box controls;
public Ed(Immobilized p) {
selectionOption = new JComboBox();
selectionOption.addItem("normally");
selectionOption.addItem("when shift-key down");
selectionOption.addItem("when alt-key down");
selectionOption.addItem("never");
if (p.neverSelect) {
selectionOption.setSelectedIndex(3);
}
else if (p.altToSelect) {
selectionOption.setSelectedIndex(2);
}
else if (p.shiftToSelect) {
selectionOption.setSelectedIndex(1);
}
else {
selectionOption.setSelectedIndex(0);
}
ignoreGridBox = new JCheckBox("Ignore map grid when moving?");
ignoreGridBox.setSelected(p.ignoreGrid);
controls = Box.createVerticalBox();
Box b = Box.createHorizontalBox();
b.add(new JLabel("Select piece: "));
b.add(selectionOption);
controls.add(b);
movementOption = new JComboBox();
movementOption.addItem("normally");
movementOption.addItem("only if selected");
movementOption.addItem("never");
if (p.neverMove) {
movementOption.setSelectedIndex(2);
}
else if (p.moveIfSelected) {
movementOption.setSelectedIndex(1);
}
else {
movementOption.setSelectedIndex(0);
}
b = Box.createHorizontalBox();
b.add(new JLabel("Move piece: "));
b.add(movementOption);
controls.add(b);
controls.add(ignoreGridBox);
}
public String getState() {
return "";
}
public String getType() {
String s = ID;
switch (selectionOption.getSelectedIndex()) {
case 1:
s += SHIFT_SELECT;
break;
case 2:
s += ALT_SELECT;
break;
case 3:
s += NEVER_SELECT;
}
if (ignoreGridBox.isSelected()) {
s += IGNORE_GRID;
}
s += ';';
switch (movementOption.getSelectedIndex()) {
case 0:
s += MOVE_NORMAL;
break;
case 1:
s += MOVE_SELECTED;
break;
case 2:
s += NEVER_MOVE;
break;
}
return s;
}
public Component getControls() {
return controls;
}
}
}