/*
* $Id$
*
* Copyright (c) 2005 by Rodney Kinney, Brent Easton
*
* 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.gamepieceimage;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import VASSAL.build.AbstractConfigurable;
import VASSAL.build.AutoConfigurable;
import VASSAL.build.Buildable;
import VASSAL.build.module.documentation.HelpFile;
import VASSAL.configure.Configurer;
import VASSAL.configure.ConfigurerFactory;
import VASSAL.configure.StringEnum;
import VASSAL.tools.SequenceEncoder;
import VASSAL.tools.image.ImageUtils;
public class GamePieceLayout extends AbstractConfigurable implements Visualizable {
protected static final String NAME = "name"; //$NON-NLS-1$
protected static final String WIDTH = "width"; //$NON-NLS-1$
protected static final String HEIGHT = "height"; //$NON-NLS-1$
protected static final String BORDER = "border"; //$NON-NLS-1$
protected static final String ITEMS = "layout"; //$NON-NLS-1$
protected static final String N = "Top";
protected static final String S = "Bottom";
protected static final String E = "Right";
protected static final String W = "Left";
protected static final String NE = "Top Right";
protected static final String NW = "Top Left";
protected static final String SE = "Bottom Right";
protected static final String SW = "Bottom Left";
protected static final String CENTER = "Center";
protected static final int POS_L = 15;
protected static final int POS_R = 85;
protected static final int POS_T = 15;
protected static final int POS_B = 85;
protected static final int POS_C = 50;
protected static final String BORDER_PLAIN = "Plain";
protected static final String BORDER_FANCY = "Fancy";
protected static final String BORDER_3D = "3D";
protected static final String BORDER_NONE = "None";
public static final String[] LOCATIONS = new String[]{CENTER, N, S, E, W, NE, NW, SE, SW};
public static final int[] X_POS = new int[]{POS_C, POS_C, POS_C, POS_R, POS_L, POS_R, POS_L, POS_R, POS_L};
public static final int[] Y_POS = new int[]{POS_C, POS_T, POS_B, POS_C, POS_C, POS_T, POS_T, POS_B, POS_B};
protected static Map<String,String> compass = new HashMap<String,String>();
static {
compass.put(N,"N");
compass.put(S,"S");
compass.put(E,"E");
compass.put(W,"W");
compass.put(NE,"NE");
compass.put(NW,"NW");
compass.put(SE,"SE");
compass.put(SW,"SW");
compass.put(CENTER,"CENTER");
}
public static String getCompassPoint(String location) {
return compass.get(location);
}
public Point getPosition(Item item) {
final String s = getCompassPoint(item.getLocation());
int x,y;
final Dimension d = item.getSize();
switch (s.charAt(s.length() - 1)) {
case 'E':
x = getLayoutWidth() - d.width;
break;
case 'W':
x = 0;
break;
default:
x = getLayoutWidth() / 2 - d.width / 2;
}
switch (s.charAt(0)) {
case 'N':
y = 0;
break;
case 'S':
y = getLayoutHeight() - d.height;
break;
default:
y = getLayoutHeight() / 2 - d.height / 2;
}
return new Point(x + item.getXoffset(), y + item.getYoffset());
}
protected int width = 54;
protected int height = 54;
protected String border = BORDER_3D;
protected GamePieceImage imageDefn;
protected Image visImage;
protected List<Item> items = new ArrayList<Item>();
public GamePieceLayout() {
super();
name = ""; //$NON-NLS-1$
imageDefn = new GamePieceImage(this);
}
public String[] getAttributeDescriptions() {
return new String[]{
"Name: ",
"Counter Width: ",
"Counter Height: ",
"Border Style: ",
"" //$NON-NLS-1$
};
}
public Class<?>[] getAttributeTypes() {
return new Class<?>[]{
String.class,
Integer.class,
Integer.class,
BorderConfig.class,
LayoutConfig.class
};
}
public static class LayoutConfig implements ConfigurerFactory {
protected static LayoutConfigurer configurer;
public Configurer getConfigurer(AutoConfigurable c,
String key, String name) {
configurer = new LayoutConfigurer(key, name, (GamePieceLayout) c);
return configurer;
}
public static void refresh() {
if (configurer != null) {
configurer.repack();
}
}
}
public static class BorderConfig extends StringEnum {
public String[] getValidValues(AutoConfigurable target) {
return new String[]{BORDER_PLAIN, BORDER_FANCY, BORDER_3D, BORDER_NONE};
}
}
public boolean isColoredBorder() {
return border.equals(BORDER_PLAIN) || border.equals(BORDER_FANCY);
}
public String[] getAttributeNames() {
return new String[]{NAME, WIDTH, HEIGHT, BORDER, ITEMS};
}
public void setAttribute(String key, Object value) {
if (NAME.equals(key)) {
setConfigureName((String) value);
}
else if (WIDTH.equals(key)) {
if (value instanceof String) {
value = Integer.valueOf((String) value);
}
setWidth(((Integer) value).intValue());
}
else if (HEIGHT.equals(key)) {
if (value instanceof String) {
value = Integer.valueOf((String) value);
}
setHeight(((Integer) value).intValue());
}
else if (BORDER.equals(key)) {
border = (String) value;
}
else if (ITEMS.equals(key)) {
decodeItemList((String) value);
}
invalidate();
LayoutConfig.refresh();
}
public String getAttributeValueString(String key) {
if (NAME.equals(key)) {
return getConfigureName();
}
else if (WIDTH.equals(key)) {
return getLayoutWidth() + ""; //$NON-NLS-1$
}
else if (HEIGHT.equals(key)) {
return getLayoutHeight() + ""; //$NON-NLS-1$
}
else if (BORDER.equals(key)) {
return border + ""; //$NON-NLS-1$
}
else if (ITEMS.equals(key)) {
return encodeItemList();
}
else
return null;
}
public void removeFrom(Buildable parent) {
}
public HelpFile getHelpFile() {
return HelpFile.getReferenceManualPage("GamePieceLayouts.htm"); //$NON-NLS-1$
}
public Class<?>[] getAllowableConfigureComponents() {
return new Class<?>[]{GamePieceImage.class};
}
public void addTo(Buildable parent) {
setAllAttributesUntranslatable();
}
public static String getConfigureTypeName() {
return "Game Piece Layout"; //$NON-NLS-1$
}
public void setWidth(int width) {
this.width = width;
}
public int getLayoutWidth() {
return width;
}
public void setHeight(int height) {
this.height = height;
}
public int getLayoutHeight() {
return height;
}
public String getBorder() {
return border;
}
public List<Item> getItems() {
return items;
}
protected int getItemCount() {
return items.size();
}
protected Item getItem(int n) {
return items.get(n);
}
protected Item getItem(String name) {
for (Item item : items) {
if (item.getConfigureName().equals(name)) {
return item;
}
}
return null;
}
protected void removeItem(int n) {
items.remove(n);
}
public void addItem(Item i) {
items.add(i);
}
public void moveItem(int from, int to) {
Item temp = items.get(to);
items.set(to, items.get(from));
items.set(from, temp);
}
public void add(Buildable b) {
super.add(b);
}
public void remove(Buildable b) {
super.remove(b);
}
public Image getVisualizerImage() {
if (visImage == null) {
rebuildVisualizerImage();
}
return visImage;
}
public Image buildImage(GamePieceImage defn) {
// Create our base image
final BufferedImage image = ImageUtils.createCompatibleTranslucentImage(
Math.max(width,1),
Math.max(height,1)
);
final Graphics2D g = image.createGraphics();
// Fill in the sample Background color
Color bgColor = defn.getBgColor().getColor();
g.setColor(bgColor);
if (getBorder().equals(BORDER_3D)) {
if (bgColor != null) g.fill3DRect(0, 0, width, height, true);
}
else {
if (bgColor != null) g.fillRect(0, 0, width, height);
// Add Border
if (getBorder().equals(BORDER_PLAIN) || getBorder().equals(BORDER_FANCY)) {
Color bg = bgColor == null ? Color.WHITE : bgColor;
g.setColor(defn.getBorderColor().getColor());
g.setStroke(new BasicStroke(1.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
g.drawRect(0, 0, width - 1, height - 1);
if (getBorder().equals(BORDER_FANCY)) {
Color lt = new Color(bg.getRed() / 2,
bg.getGreen() / 2,
bg.getBlue() / 2);
Color dk = new Color(bg.getRed() + (255 - bg.getRed()) / 2,
bg.getGreen() + (255 - bg.getGreen()) / 2,
bg.getBlue() + (255 - bg.getBlue()) / 2);
g.setColor(dk);
g.drawLine(1, 1, width - 3, 1);
g.drawLine(1, 2, 1, height - 3);
g.setColor(lt);
g.drawLine(width - 2, 2, width - 2, height - 2);
g.drawLine(2, height - 2, width - 3, height - 2);
}
}
}
// layer each item over the top
for (Item item : items) {
if (item != null) {
item.draw(g, defn);
}
}
g.dispose();
return image;
}
public void refresh() {
invalidate();
LayoutConfig.refresh();
}
protected void invalidate() {
for (GamePieceImage i : getComponentsOf(GamePieceImage.class)) {
i.rebuildVisualizerImage();
}
}
protected void decodeItemList(String string) {
items.clear();
if (string.length() > 0) {
SequenceEncoder.Decoder sd = new SequenceEncoder.Decoder(string, ',');
while (sd.hasMoreTokens()) {
Item item = Item.decode(this, sd.nextToken());
addItem(item);
}
}
}
protected String encodeItemList() {
String[] list = new String[getItemCount()];
int i = 0;
for (Item item : items) {
list[i++] = item.encode();
}
SequenceEncoder se = new SequenceEncoder('#');
se.append(list);
return se.getValue();
}
public int getVisualizerHeight() {
return getLayoutHeight();
}
public int getVisualizerWidth() {
return getLayoutWidth();
}
public void rebuildVisualizerImage() {
visImage = buildImage(imageDefn);
}
public void setImageDefn(GamePieceImage d) {
imageDefn = d;
}
public GamePieceImage getGenericDefn(String defnName) {
for (Buildable b : getBuildables()) {
if (b instanceof GamePieceImage) {
GamePieceImage gpi = (GamePieceImage) b;
if (gpi.getConfigureName().equals(defnName)) {
return gpi;
}
}
}
return null;
}
}