/*
* $Id$
*
* Copyright (c) 2007 by 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.tools.imageop;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import VASSAL.counters.GamePiece;
import VASSAL.counters.Properties;
import VASSAL.tools.image.ImageUtils;
import VASSAL.tools.opcache.Op;
import VASSAL.tools.opcache.OpObserver;
/**
* An {@link ImageOp} which uses a {@link GamePiece} as its source.
*
* @since 3.1.0
* @author Joel Uckelman
*/
public class GamePieceOpImpl extends AbstractTileOpImpl implements GamePieceOp {
/** The image source for this <code>ImageOp</code>. */
private final GamePiece piece;
private final String state;
private final int hash;
/**
* Constructs an <code>ImageOp</code> which will produce an image
* from the given <code>GamePiece</code>.
*
* @param gp the source
* @throws IllegalArgumentException if <code>gp == null</code>.
*/
public GamePieceOpImpl(GamePiece gp) {
if (gp == null) throw new IllegalArgumentException();
piece = gp;
state = String.valueOf(piece.getProperty(Properties.VISIBLE_STATE));
hash = piece.hashCode();
}
@Override
public BufferedImage get(OpObserver<BufferedImage> obs)
throws CancellationException, InterruptedException, ExecutionException
{
// GamePieceOpImpl CANNOT be called asynchronously becuase it cannot
// reliably report on its dependencies.
if (obs != null) throw new UnsupportedOperationException();
return super.get(obs);
}
@Override
public Future<BufferedImage> getFuture(OpObserver<BufferedImage> obs)
throws ExecutionException {
// GamePieceOpImpl CANNOT be called asynchronously becuase it cannot
// reliably report on its dependencies.
if (obs != null) throw new UnsupportedOperationException();
return super.getFuture(obs);
}
public List<Op<?>> getSources() {
return Collections.emptyList();
}
/** {@inheritDoc} */
public BufferedImage eval() {
final Rectangle b = piece.boundingBox();
final BufferedImage im = ImageUtils.createCompatibleTranslucentImage(
Math.max(b.width, 1),
Math.max(b.height, 1)
);
final Graphics2D g = im.createGraphics();
piece.draw(g, -b.x, -b.y, null, 1.0);
g.dispose();
return im;
}
/** {@inheritDoc} */
protected void fixSize() {
size = piece.boundingBox().getSize();
if (size.width < 1) size.width = 1;
if (size.height < 1) size.height = 1;
}
/**
* Returns the source <code>GamePiece</code>.
*
* @return the source
*/
public GamePiece getPiece() {
return piece;
}
public String getState() {
return state;
}
/**
* Returns <code>true</code> iff the source <code>GamePiece</code>
* has changed state.
*
* @return <code>true</code> iff the source has changed.
*/
public boolean isChanged() {
return !state.equals(piece.getProperty(Properties.VISIBLE_STATE));
}
/** {@inheritDoc} */
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || o.getClass() != this.getClass()) return false;
GamePieceOp op = (GamePieceOp) o;
return piece.equals(op.getPiece()) &&
state.equals(op.getState());
}
/** {@inheritDoc} */
@Override
public int hashCode() {
return hash;
}
}