/*
* Copyright (c) 2014 tabletoptool.com team.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v3.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html
*
* Contributors:
* rptools.com team - initial implementation
* tabletoptool.com team - further development
*/
package com.t3.model;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import com.t3.guid.GUID;
import com.t3.model.grid.Grid;
import com.t3.xstreamversioned.version.SerializationVersion;
/**
* This class represents the set of cells a token occupies based on its size. Each token is assumed to take up at least
* one cell, additional cells are indicated by cell offsets assuming the occupied cell is at 0, 0
*/
@SerializationVersion(0)
public class TokenFootprint {
private final Set<Point> cellSet = new HashSet<Point>();
private String name;
private GUID id;
private boolean isDefault;
private double scale = 1;
private transient List<OffsetTranslator> translatorList = new LinkedList<OffsetTranslator>();
public TokenFootprint(String name, GUID id, boolean isDefault, double scale, Point... points) {
this.name=name;
this.id=id;
this.isDefault=isDefault;
this.scale=scale;
for (Point p : points)
cellSet.add(p);
}
public TokenFootprint(String name, boolean isDefault, double scale, Point... points) {
this.name = name;
id = new GUID();
this.isDefault = isDefault;
this.scale = scale;
for (Point p : points) {
cellSet.add(p);
}
}
@Override
public String toString() {
return name;
}
public void addOffsetTranslator(OffsetTranslator translator) {
translatorList.add(translator);
}
public Set<CellPoint> getOccupiedCells(CellPoint centerPoint) {
Set<CellPoint> occupiedSet = new HashSet<CellPoint>();
// Implied
occupiedSet.add(centerPoint);
// Relative
for (Point offset : cellSet) {
CellPoint cp = new CellPoint(centerPoint.x + offset.x, centerPoint.y + offset.y);
for (OffsetTranslator translator : translatorList) {
translator.translate(centerPoint, cp);
}
occupiedSet.add(cp);
}
return occupiedSet;
}
public TokenFootprint(String name, Point... points) {
this(name, false, 1, points);
}
public void setDefault(boolean isDefault) {
this.isDefault = isDefault;
}
public boolean isDefault() {
return isDefault;
}
public GUID getId() {
return id;
}
public String getName() {
return name;
}
public Rectangle getBounds(Grid grid) {
return getBounds(grid, null);
}
public double getScale() {
return scale;
}
/**
* Return a rectangle that exactly bounds the footprint, values are in {@link ZonePoint} space.
*
* @param grid
* the {@link Grid} that the footprint corresponds to
* @param cell
* origin cell of this footprint; <code>null</code> means that <code>(0,0)</code> will be used
*/
public Rectangle getBounds(Grid grid, CellPoint cell) {
cell = cell != null ? cell : new CellPoint(0, 0);
Rectangle bounds = new Rectangle(grid.getBounds(cell));
for (CellPoint cp : getOccupiedCells(cell)) {
bounds.add(grid.getBounds(cp));
}
bounds.x += grid.getOffsetX();
bounds.y += grid.getOffsetY();
return bounds;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof TokenFootprint)) {
return false;
}
return ((TokenFootprint) obj).id.equals(id);
}
private Object readResolve() {
translatorList = new LinkedList<OffsetTranslator>();
return this;
}
public static interface OffsetTranslator {
public void translate(CellPoint originPoint, CellPoint offsetPoint);
}
}