/*
* $Id$
*
* Copyright (c) 2006-2007 by Brent Easton, Joel Uckelman
*
* 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.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.AffineTransform;
import VASSAL.build.AbstractConfigurable;
import VASSAL.build.AutoConfigurable;
import VASSAL.build.Buildable;
import VASSAL.build.IllegalBuildException;
import VASSAL.build.module.documentation.HelpFile;
import VASSAL.configure.ColorConfigurer;
import VASSAL.configure.Configurer;
import VASSAL.configure.ConfigurerFactory;
import VASSAL.configure.IconConfigurer;
import VASSAL.configure.PropertyExpression;
import VASSAL.configure.VisibilityCondition;
import VASSAL.counters.GamePiece;
import VASSAL.counters.Highlighter;
import VASSAL.i18n.Resources;
import VASSAL.tools.image.ImageUtils;
import VASSAL.tools.imageop.ScaledImagePainter;
public class SelectionHighlighter extends AbstractConfigurable implements Highlighter {
public static final String NAME = "name";
public static final String MATCH = "match";
public static final String COLOR = "color";
public static final String THICKNESS = "thickness";
public static final String USE_IMAGE = "useImage";
public static final String IMAGE = "image";
public static final String X_OFFSET = "xoffset";
public static final String Y_OFFSET = "yoffset";
protected PropertyExpression matchProperties = new PropertyExpression();
protected Color color = Color.RED;
protected int thickness = 3;
protected boolean useImage = false;
protected String imageName = "";
protected int x = 0;
protected int y = 0;
protected VisibilityCondition visibilityCondition;
@Deprecated
protected Image image;
protected ScaledImagePainter imagePainter = new ScaledImagePainter();
public void draw(GamePiece p, Graphics g, int x, int y, Component obs, double zoom) {
final Graphics2D g2d = (Graphics2D) g;
if (accept(p)) {
if (useImage) {
final int x1 = x - (int) (imagePainter.getImageSize().width * zoom / 2);
final int y1 = y - (int) (imagePainter.getImageSize().height * zoom / 2);
imagePainter.draw(g, x1, y1, zoom, obs);
}
else {
if (color == null || thickness <= 0) {
return;
}
final Shape s = p.getShape();
final Stroke str = g2d.getStroke();
g2d.setStroke(new BasicStroke(Math.max(1, Math.round(zoom * thickness))));
g2d.setColor(color);
final AffineTransform t = AffineTransform.getScaleInstance(zoom, zoom);
t.translate(x / zoom, y / zoom);
g2d.draw(t.createTransformedShape(s));
g2d.setStroke(str);
}
}
}
public Rectangle boundingBox(GamePiece p) {
final Rectangle r = p.getShape().getBounds();
if (accept(p)) {
if (useImage) {
r.add(ImageUtils.getBounds(imagePainter.getImageSize()));
}
else {
r.translate(-thickness, -thickness);
r.setSize(r.width + 2 * thickness, r.height + 2 * thickness);
}
}
return r;
}
protected boolean accept(GamePiece p) {
return matchProperties.isNull() ? true : matchProperties.accept(p);
}
public static String getConfigureTypeName() {
return Resources.getString("Editor.SelectionHighlight.component_type"); //$NON-NLS-1$
}
public String[] getAttributeDescriptions() {
return new String[]{
Resources.getString(Resources.NAME_LABEL),
Resources.getString("Editor.SelectionHighlight.active_property"), //$NON-NLS-1$
Resources.getString("Editor.SelectionHighlight.use_image"), //$NON-NLS-1$
Resources.getString("Editor.SelectionHighlight.border_color"), //$NON-NLS-1$
Resources.getString("Editor.SelectionHighlight.border_thickness"), //$NON-NLS-1$
Resources.getString("Editor.SelectionHighlight.image"), //$NON-NLS-1$
Resources.getString("Editor.SelectionHighlight.offset_x"), //$NON-NLS-1$
Resources.getString("Editor.SelectionHighlight.offset_y"),//$NON-NLS-1$
};
}
public Class<?>[] getAttributeTypes() {
return new Class<?>[]{String.class, PropertyExpression.class, Boolean.class, Color.class, Integer.class, IconConfig.class, Integer.class, Integer.class};
}
public static class IconConfig implements ConfigurerFactory {
public Configurer getConfigurer(AutoConfigurable c, String key, String name) {
return new IconConfigurer(key, name, ((SelectionHighlighter) c).imageName);
}
}
public String[] getAttributeNames() {
return new String[]{NAME, MATCH, USE_IMAGE, COLOR, THICKNESS, IMAGE, X_OFFSET, Y_OFFSET};
}
public VisibilityCondition getAttributeVisibility(String name) {
if (COLOR.equals(name) || THICKNESS.equals(name)) {
return new VisibilityCondition() {
public boolean shouldBeVisible() {
return !useImage;
}
};
}
else if (IMAGE.equals(name) || X_OFFSET.equals(name) || Y_OFFSET.equals(name)) {
return new VisibilityCondition() {
public boolean shouldBeVisible() {
return useImage;
}
};
}
else {
return super.getAttributeVisibility(name);
}
}
public void setAttribute(String key, Object value) {
if (key.equals(NAME)) {
setConfigureName((String) value);
}
else if (key.equals(MATCH)) {
matchProperties.setExpression((String) value);
}
else if (key.equals(USE_IMAGE)) {
if (value instanceof String) {
value = Boolean.valueOf((String) value);
}
useImage = ((Boolean) value).booleanValue();
}
else if (key.equals(COLOR)) {
if (value instanceof String) {
value = ColorConfigurer.stringToColor((String) value);
}
if (value != null) {
color = ((Color) value);
}
}
else if (key.equals(THICKNESS)) {
if (value instanceof String) {
value = Integer.valueOf((String) value);
}
thickness = ((Integer) value).intValue();
}
else if (key.equals(IMAGE)) {
imageName = (String) value;
imagePainter.setImageName(imageName);
}
else if (key.equals(X_OFFSET)) {
if (value instanceof String) {
value = Integer.valueOf((String) value);
}
try {
x = ((Integer) value).intValue();
}
catch (NumberFormatException ex) {
throw new IllegalBuildException(ex);
}
}
else if (key.equals(Y_OFFSET)) {
if (value instanceof String) {
value = Integer.valueOf((String) value);
}
try {
y = ((Integer) value).intValue();
}
catch (NumberFormatException ex) {
throw new IllegalBuildException(ex);
}
}
}
public String getAttributeValueString(String key) {
if (key.equals(NAME)) {
return getConfigureName();
}
else if (key.equals(MATCH)) {
return matchProperties.getExpression();
}
else if (key.equals(USE_IMAGE)) {
return String.valueOf(useImage);
}
else if (key.equals(COLOR)) {
return ColorConfigurer.colorToString(color);
}
else if (key.equals(THICKNESS)) {
return String.valueOf(thickness);
}
else if (key.equals(IMAGE)) {
return imageName;
}
else if (key.equals(X_OFFSET)) {
return String.valueOf(x);
}
else if (key.equals(Y_OFFSET)) {
return String.valueOf(y);
}
return null;
}
public void removeFrom(Buildable parent) {
((SelectionHighlighters) parent).removeHighlighter(this);
}
public HelpFile getHelpFile() {
return HelpFile.getReferenceManualPage("Map.htm", "SelectionHighlighter");
}
public Class<?>[] getAllowableConfigureComponents() {
return new Class<?>[0];
}
public void addTo(Buildable parent) {
((SelectionHighlighters) parent).addHighlighter(this);
}
}