/**
* Copyright (C) 2002-2012 The FreeCol Team
*
* This file is part of FreeCol.
*
* FreeCol is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* FreeCol 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with FreeCol. If not, see <http://www.gnu.org/licenses/>.
*/
package net.sf.freecol.client.gui;
import java.util.Map.Entry;
import java.util.logging.Logger;
import org.freecolandroid.repackaged.java.awt.Color;
import org.freecolandroid.repackaged.java.awt.Font;
import org.freecolandroid.repackaged.java.awt.Graphics;
import org.freecolandroid.repackaged.java.awt.Graphics2D;
import org.freecolandroid.repackaged.java.awt.GraphicsConfiguration;
import org.freecolandroid.repackaged.java.awt.GraphicsEnvironment;
import org.freecolandroid.repackaged.java.awt.Image;
import org.freecolandroid.repackaged.java.awt.Insets;
import org.freecolandroid.repackaged.java.awt.Transparency;
import org.freecolandroid.repackaged.java.awt.font.TextLayout;
import org.freecolandroid.repackaged.java.awt.image.BufferedImage;
import org.freecolandroid.repackaged.javax.swing.ImageIcon;
import org.freecolandroid.repackaged.javax.swing.JComponent;
import net.sf.freecol.common.FreeColException;
import net.sf.freecol.common.model.FoundingFather;
import net.sf.freecol.common.model.FreeColGameObjectType;
import net.sf.freecol.common.model.GoodsType;
import net.sf.freecol.common.model.Map.Direction;
import net.sf.freecol.common.model.LostCityRumour;
import net.sf.freecol.common.model.Nation;
import net.sf.freecol.common.model.Ownable;
import net.sf.freecol.common.model.Player;
import net.sf.freecol.common.model.ResourceType;
import net.sf.freecol.common.model.Settlement;
import net.sf.freecol.common.model.SettlementType;
import net.sf.freecol.common.model.Tension;
import net.sf.freecol.common.model.Tile;
import net.sf.freecol.common.model.TileType;
import net.sf.freecol.common.model.Unit;
import net.sf.freecol.common.model.Unit.Role;
import net.sf.freecol.common.model.UnitType;
import net.sf.freecol.common.resources.ResourceManager;
/**
* Holds various images that can be called upon by others in order to display
* certain things.
*/
public final class ImageLibrary {
private static final Logger logger = Logger.getLogger(ImageLibrary.class.getName());
public static final String UNIT_SELECT = "unitSelect.image",
DELETE = "delete.image",
PLOWED = "model.improvement.plow.image",
TILE_TAKEN = "tileTaken.image",
TILE_OWNED_BY_INDIANS = "nativeLand.image",
LOST_CITY_RUMOUR = "lostCityRumour.image",
DARKNESS = "halo.dark.image";
/**
* Draw a (usually small) background image into a (usually larger)
* space specified by a component, tiling the image to fill up the
* space. If the image is not available, just fill with the background
* colour.
*
* @param resource The name of the <code>ImageResource</code> to tile with.
* @param g The <code>Graphics</code> to draw to.
* @param c The <code>JComponent</code> that defines the space.
* @param insets Optional <code>Insets</code> to apply.
*/
public static void drawTiledImage(String resource, Graphics g,
JComponent c, Insets insets) {
int width = c.getWidth();
int height = c.getHeight();
Image image = ResourceManager.getImage(resource);
int dx, dy, xmin, ymin;
if (insets == null) {
xmin = 0;
ymin = 0;
} else {
xmin = insets.left;
ymin = insets.top;
width -= insets.left + insets.right;
height -= insets.top + insets.bottom;
}
if (image != null && (dx = image.getWidth(null)) > 0
&& (dy = image.getHeight(null)) > 0) {
int xmax, ymax;
xmax = xmin + width;
ymax = ymin + height;
for (int x = xmin; x < xmax; x += dx) {
for (int y = ymin; y < ymax; y += dy) {
g.drawImage(image, x, y, null);
}
}
} else {
g.setColor(c.getBackground());
g.fillRect(xmin, ymin, width, height);
}
}
/**
* The scaling factor used when creating this
* <code>ImageLibrary</code>. The value
* <code>1</code> is used if this object is not
* a result of a scaling operation.
*/
private final float scalingFactor;
/**
* The constructor to use.
*
*/
public ImageLibrary() {
this(1);
}
public ImageLibrary(float scalingFactor) {
this.scalingFactor = scalingFactor;
}
/**
* Returns the alarm chip with the given color.
*
* @param alarm The alarm level.
* @param visited a <code>boolean</code> value
* @param scale a <code>double</code> value
* @return The alarm chip.
*/
public Image getAlarmChip(Tension.Level alarm, final boolean visited, double scale) {
if (visited) {
return ResourceManager.getChip("alarmChip.visited."
+ alarm.toString().toLowerCase(), scale);
} else {
return ResourceManager.getChip("alarmChip." + alarm.toString().toLowerCase(), scale);
}
}
/**
* Returns the beach corner image at the given index.
*
* @param index The index of the image to return.
* @param x an <code>int</code> value
* @param y an <code>int</code> value
* @return The image at the given index.
*/
public Image getBeachCornerImage(int index, int x, int y) {
return ResourceManager.getImage("model.tile.beach.corner" + index
+ (isEven(x, y) ? "_even" : "_odd"), scalingFactor);
}
/**
* Returns the beach edge image at the given index.
*
* @param index The index of the image to return.
* @param x an <code>int</code> value
* @param y an <code>int</code> value
* @return The image at the given index.
*/
public Image getBeachEdgeImage(int index, int x, int y) {
return ResourceManager.getImage("model.tile.beach.edge" + index
+ (isEven(x, y) ? "_even" : "_odd"), scalingFactor);
}
public Image getBonusImage(ResourceType type) {
return getBonusImage(type, scalingFactor);
}
public Image getBonusImage(ResourceType type, double scale) {
return ResourceManager.getImage(type.getId() + ".image", scale);
}
/**
* Returns the bonus-image for the given tile.
*
* @param tile
* @return the bonus-image for the given tile.
*/
public Image getBonusImage(Tile tile) {
if (tile.hasResource()) {
return getBonusImage(tile.getTileItemContainer().getResource().getType());
} else {
return null;
}
}
/**
* Returns the bonus-ImageIcon at the given index.
*
* @param type The type of the bonus-ImageIcon to return.
* @return <code>ImageIcon</code>
*/
public ImageIcon getBonusImageIcon(ResourceType type) {
return new ImageIcon(getBonusImage(type));
}
/**
* Returns the border terrain-image for the given type.
*
* @param type The type of the terrain-image to return.
* @param direction a <code>Direction</code> value
* @param x The x-coordinate of the location of the tile that is being
* drawn.
* @param y The x-coordinate of the location of the tile that is being
* drawn.
* @return The terrain-image at the given index.
*/
public Image getBorderImage(TileType type, Direction direction, int x, int y) {
String key = (type == null) ? "model.tile.unexplored" : type.getId();
return ResourceManager.getImage(key + ".border_" + direction
+ (isEven(x, y) ? "_even" : "_odd")
+ ".image", scalingFactor);
}
/**
* Returns true if the tile with the given coordinates is to be
* considered "even". This is useful to select different images
* for the same tile type in order to prevent big stripes or
* a checker-board effect.
*
* @param x an <code>int</code> value
* @param y an <code>int</code> value
* @return a <code>boolean</code> value
*/
private boolean isEven(int x, int y) {
return ((y % 8 <= 2) || ((x + y) % 2 == 0 ));
}
/**
* Returns the coat-of-arms image for the given Nation.
*
* @param nation The nation.
* @return the coat-of-arms of this nation
*/
public Image getCoatOfArmsImage(Nation nation) {
return getCoatOfArmsImage(nation, scalingFactor);
}
public Image getCoatOfArmsImage(Nation nation, double scale) {
return ResourceManager.getImage(nation.getId() + ".image", scale);
}
/**
* Returns the coat-of-arms image for the given Nation.
*
* @param nation The nation.
* @return the coat-of-arms of this nation
*/
public ImageIcon getCoatOfArmsImageIcon(Nation nation) {
return ResourceManager.getImageIcon(nation.getId() + ".image");
}
/**
* Returns the color of the given player.
*
* @param player a <code>Player</code> value
* @return The color of the given player.
*/
public Color getColor(Player player) {
return ResourceManager.getColor(player.getNationID() + ".color");
}
/**
* Returns the color chip with the given color.
*
* @param ownable an <code>Ownable</code> value
* @param scale a <code>double</code> value
* @return The color chip with the given color.
*/
public Image getColorChip(Ownable ownable, double scale) {
return ResourceManager.getChip(ownable.getOwner().getNationID() + ".chip", scale);
}
/**
* Returns the scaled terrain-image for a terrain type (and position 0, 0).
*
* @param type The type of the terrain-image to return.
* @param scale The scale of the terrain image to return.
* @return The terrain-image
*/
public Image getCompoundTerrainImage(TileType type, double scale) {
// Currently used for hills and mountains
Image terrainImage = getTerrainImage(type, 0, 0, scale);
Image overlayImage = getOverlayImage(type, 0, 0, scale);
Image forestImage = type.isForested() ? getForestImage(type, scale) : null;
if (overlayImage == null && forestImage == null) {
return terrainImage;
} else {
GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment()
.getDefaultScreenDevice().getDefaultConfiguration();
int width = terrainImage.getWidth(null);
int height = terrainImage.getHeight(null);
if (overlayImage != null) {
height = Math.max(height, overlayImage.getHeight(null));
}
if (forestImage != null) {
height = Math.max(height, forestImage.getHeight(null));
}
BufferedImage compositeImage = gc.createCompatibleImage(width, height, Transparency.TRANSLUCENT);
Graphics2D g = compositeImage.createGraphics();
g.drawImage(terrainImage, 0, height - terrainImage.getHeight(null), null);
if (overlayImage != null) {
g.drawImage(overlayImage, 0, height - overlayImage.getHeight(null), null);
}
if (forestImage != null) {
g.drawImage(forestImage, 0, height - forestImage.getHeight(null), null);
}
g.dispose();
return compositeImage;
}
}
/**
* Converts an image to grayscale
*
* @param image Source image to convert
* @return The image in grayscale
*/
/*
private ImageIcon convertToGrayscale(Image image) {
int width = image.getWidth(null);
int height = image.getHeight(null);
ColorConvertOp filter = new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null);
BufferedImage srcImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
srcImage.createGraphics().drawImage(image, 0, 0, null);
return new ImageIcon(filter.filter(srcImage, null));
}
*/
/**
* Returns the height of the terrain-image including overlays and
* forests for the given terrain type.
*
* @param type The type of the terrain-image.
* @return The height of the terrain-image at the given index.
*/
public int getCompoundTerrainImageHeight(TileType type) {
int height = getTerrainImageHeight(type);
if (type != null) {
Image overlayImage = getOverlayImage(type, 0, 0);
if (overlayImage != null) {
height = Math.max(height, overlayImage.getHeight(null));
}
if (type.isForested()) {
height = Math.max(height, getForestImage(type).getHeight(null));
}
}
return height;
}
/**
* Returns the forest image for a terrain type.
*
* @param type The type of the terrain-image to return.
* @return The image at the given index.
*/
public Image getForestImage(TileType type) {
return getForestImage(type, scalingFactor);
}
public Image getForestImage(TileType type, double scale) {
return ResourceManager.getImage(type.getId() + ".forest", scale);
}
/**
* Returns the portrait of this Founding Father.
*
* @param father a <code>FoundingFather</code> value
* @return an <code>Image</code> value
*/
public Image getFoundingFatherImage(FoundingFather father) {
return ResourceManager.getImage(father.getId() + ".image");
}
/**
* Returns the goods-image at the given index.
*
* @param goodsType The type of the goods-image to return.
* @return The goods-image at the given index.
*/
public Image getGoodsImage(GoodsType goodsType) {
return getGoodsImage(goodsType, scalingFactor);
}
public Image getGoodsImage(GoodsType goodsType, double scale) {
return ResourceManager.getImage(goodsType.getId() + ".image", scale);
}
/**
* Returns the goods-image for a goods type.
*
* @param goodsType The type of the goods-image to return.
* @return The goods-image at the given index.
*/
public ImageIcon getGoodsImageIcon(GoodsType goodsType) {
return ResourceManager.getImageIcon(goodsType.getId() + ".image");
}
public Image getImage(FreeColGameObjectType type) {
return ResourceManager.getImage(type.getId() + ".image", scalingFactor);
}
public Image getImage(FreeColGameObjectType type, double scale) {
return ResourceManager.getImage(type.getId() + ".image", scale);
}
/**
* Returns the appropriate ImageIcon for Object.
*
* @param display The Object to display.
* @return The appropriate ImageIcon.
*/
public ImageIcon getImageIcon(Object display, boolean small) {
Image image = null;
if (display == null) {
return new ImageIcon();
} else if (display instanceof GoodsType) {
GoodsType goodsType = (GoodsType) display;
try {
image = this.getGoodsImage(goodsType);
} catch (Exception e) {
logger.warning("could not find image for goods " + goodsType);
}
} else if (display instanceof Unit) {
Unit unit = (Unit) display;
try {
image = this.getUnitImageIcon(unit).getImage();
} catch (Exception e) {
logger.warning("could not find image for unit " + unit.toString());
}
} else if (display instanceof UnitType) {
UnitType unitType = (UnitType) display;
try {
image = this.getUnitImageIcon(unitType).getImage();
} catch (Exception e) {
logger.warning("could not find image for unit " + unitType);
}
} else if (display instanceof Settlement) {
Settlement settlement = (Settlement) display;
try {
image = this.getSettlementImage(settlement);
} catch (Exception e) {
logger.warning("could not find image for settlement " + settlement);
}
} else if (display instanceof LostCityRumour) {
try {
image = this.getMiscImage(ImageLibrary.LOST_CITY_RUMOUR);
} catch (Exception e) {
logger.warning("could not find image for lost city rumour");
}
} else if (display instanceof Player) {
image = this.getCoatOfArmsImage(((Player) display).getNation());
}
if (image != null && small) {
return new ImageIcon(image.getScaledInstance((image.getWidth(null) / 3) * 2,
(image.getHeight(null) / 3) *2,
Image.SCALE_SMOOTH));
} else {
return (image != null) ? new ImageIcon(image) : null;
}
}
/**
* Returns the image with the given id.
*
* @param id The id of the image to return.
* @return The image.
*/
public Image getMiscImage(String id) {
return getMiscImage(id, scalingFactor);
}
public Image getMiscImage(String id, double scale) {
return ResourceManager.getImage(id, scale);
}
/**
* Returns the image with the given id.
*
* @param id The id of the image to return.
* @return The image.
*/
public ImageIcon getMiscImageIcon(String id) {
return new ImageIcon(getMiscImage(id));
}
/**
* Returns the mission chip with the given color.
*
* @param ownable an <code>Ownable</code> value
* @param expertMission Indicates whether or not the missionary is an
* expert.
* @param scale a <code>double</code> value
* @return The color chip with the given color.
*/
public Image getMissionChip(Ownable ownable, boolean expertMission, double scale) {
if (expertMission) {
return ResourceManager.getChip(ownable.getOwner().getNationID()
+ ".mission.expert.chip", scale);
} else {
return ResourceManager.getChip(ownable.getOwner().getNationID()
+ ".mission.chip", scale);
}
}
/**
* Returns the monarch-image for the given tile.
*
* @param nation The nation this monarch rules.
* @return the monarch-image for the given nation.
*/
public Image getMonarchImage(Nation nation) {
return ResourceManager.getImage(nation.getId() + ".monarch.image");
}
/**
* Returns the monarch-image icon for the given Nation.
*
* @param nation The nation this monarch rules.
* @return the monarch-image for the given nation.
*/
public ImageIcon getMonarchImageIcon(Nation nation) {
return ResourceManager.getImageIcon(nation.getId() + ".monarch.image");
}
/**
* Returns the overlay-image for the given type.
*
* @param type The type of the terrain-image to return.
* @param x The x-coordinate of the location of the tile that is being
* drawn.
* @param y The x-coordinate of the location of the tile that is being
* drawn.
* @return The terrain-image at the given index.
*/
public Image getOverlayImage(TileType type, int x, int y) {
return getOverlayImage(type, x, y, scalingFactor);
}
public Image getOverlayImage(TileType type, int x, int y, double scale) {
String key = type.getId() + ".overlay" + ((x + y) % 2) + ".image";
if (ResourceManager.hasResource(key)) {
return ResourceManager.getImage(key, scale);
} else {
return null;
}
}
/**
* Gets an image to represent the path of the given <code>Unit</code>.
*
* @param u The <code>Unit</code>
* @return The <code>Image</code>.
*/
public Image getPathImage(Unit u) {
if (u == null) {
return null;
} else {
return ResourceManager.getImage("path." + getPathType(u) + ".image");
}
}
/**
* Gets an image to represent the path of the given <code>Unit</code>.
*
* @param u The <code>Unit</code>
* @return The <code>Image</code>.
*/
public Image getPathNextTurnImage(Unit u) {
if (u == null) {
return null;
} else {
return ResourceManager.getImage("path." + getPathType(u) + ".nextTurn.image");
}
}
/**
* Returns the river image at the given index.
*
* @param index The index of the image to return.
* @return The image at the given index.
*/
public Image getRiverImage(int index) {
return getRiverImage(index, scalingFactor);
}
public Image getRiverImage(int index, double scale) {
return ResourceManager.getImage("model.tile.river" + index, scale);
}
/**
* Returns the river mouth terrain-image for the direction and magnitude.
*
* @param direction a <code>Direction</code> value
* @param magnitude an <code>int</code> value
* @param x The x-coordinate of the location of the tile that is being
* drawn (ignored).
* @param y The x-coordinate of the location of the tile that is being
* drawn (ignored).
* @return The terrain-image at the given index.
*/
public Image getRiverMouthImage(Direction direction, int magnitude, int x, int y) {
String key = "model.tile.delta_" + direction + (magnitude == 1 ? "_small" : "_large");
return ResourceManager.getImage(key, scalingFactor);
}
public ImageIcon getScaledBonusImageIcon(ResourceType type, float scale) {
return new ImageIcon(getBonusImage(type, scale));
}
/**
* Returns the scaled goods-ImageIcon for a goods type.
*
* @param type The type of the goods-ImageIcon to return.
* @param scale The scale of the goods-ImageIcon to return.
* @return The goods-ImageIcon at the given index.
*/
public ImageIcon getScaledGoodsImageIcon(GoodsType type, double scale) {
return new ImageIcon(getGoodsImage(type, scale));
}
/**
* Gets a scaled version of this <code>ImageLibrary</code>.
* @param scalingFactor The factor used when scaling. 2 is twice
* the size of the original images and 0.5 is half.
* @return A new <code>ImageLibrary</code>.
* @throws FreeColException
*/
public ImageLibrary getScaledImageLibrary(float scalingFactor) throws FreeColException {
return new ImageLibrary(scalingFactor);
}
/**
* Returns the scaling factor used when creating this ImageLibrary.
* @return 1 unless {@link #getScaledImageLibrary} was used to create
* this object.
*/
public float getScalingFactor() {
return scalingFactor;
}
/**
* Returns the graphics that will represent the given settlement.
*
* @param settlement The settlement whose graphics type is needed.
* @return The graphics that will represent the given settlement.
*/
public Image getSettlementImage(Settlement settlement) {
return getSettlementImage(settlement, scalingFactor);
}
/**
* Returns the graphics that will represent the given settlement.
*
* @param settlement The settlement whose graphics type is needed.
* @param scale a <code>double</code> value
* @return The graphics that will represent the given settlement.
*/
public Image getSettlementImage(Settlement settlement, double scale) {
return ResourceManager.getImage(settlement.getImageKey(), scale);
}
/**
* Returns the graphics that will represent the given settlement.
*
* @param settlementType The type of settlement whose graphics type is needed.
* @return The graphics that will represent the given settlement.
*/
public Image getSettlementImage(SettlementType settlementType) {
return getSettlementImage(settlementType, scalingFactor);
}
public Image getSettlementImage(SettlementType settlementType, double scale) {
return ResourceManager.getImage(settlementType.getId() + ".image", scale);
}
/**
* Returns the terrain-image for the given type.
*
* @param type The type of the terrain-image to return.
* @param x The x-coordinate of the location of the tile that is being
* drawn.
* @param y The x-coordinate of the location of the tile that is being
* drawn.
* @return The terrain-image at the given index.
*/
public Image getTerrainImage(TileType type, int x, int y) {
return getTerrainImage(type, x, y, scalingFactor);
}
public Image getTerrainImage(TileType type, int x, int y, double scale) {
String key = (type == null) ? "model.tile.unexplored" : type.getId();
return ResourceManager.getImage(key + ".center" + (isEven(x, y) ? "0" : "1")
+ ".image", scale);
}
/**
* Returns the height of the terrain-image for a terrain type.
*
* @param type The type of the terrain-image.
* @return The height of the terrain-image at the given index.
*/
public int getTerrainImageHeight(TileType type) {
return getTerrainImage(type, 0, 0).getHeight(null);
}
/**
* Returns the width of the terrain-image for a terrain type.
*
* @param type The type of the terrain-image.
* @return The width of the terrain-image at the given index.
*/
public int getTerrainImageWidth(TileType type) {
return getTerrainImage(type, 0, 0).getWidth(null);
}
/**
* Returns the ImageIcon that will represent the given unit.
*
* @param unit The unit whose graphics type is needed.
* @return an <code>ImageIcon</code> value
*/
public ImageIcon getUnitImageIcon(Unit unit) {
return getUnitImageIcon(unit.getType(), unit.getRole(), unit.hasNativeEthnicity(), false, scalingFactor);
}
public ImageIcon getUnitImageIcon(Unit unit, boolean grayscale) {
return getUnitImageIcon(unit.getType(), unit.getRole(), unit.hasNativeEthnicity(), grayscale, scalingFactor);
}
public ImageIcon getUnitImageIcon(Unit unit, boolean grayscale, double scale) {
return getUnitImageIcon(unit.getType(), unit.getRole(), unit.hasNativeEthnicity(), grayscale, scale);
}
public ImageIcon getUnitImageIcon(Unit unit, double scale) {
return getUnitImageIcon(unit.getType(), unit.getRole(), unit.hasNativeEthnicity(), false, scale);
}
/**
* Returns the ImageIcon that will represent a unit of the given type.
*
* @param unitType an <code>UnitType</code> value
* @return an <code>ImageIcon</code> value
*/
public ImageIcon getUnitImageIcon(UnitType unitType) {
return getUnitImageIcon(unitType, Role.DEFAULT, false, false, scalingFactor);
}
public ImageIcon getUnitImageIcon(UnitType unitType, boolean grayscale) {
return getUnitImageIcon(unitType, Role.DEFAULT, false, grayscale, scalingFactor);
}
public ImageIcon getUnitImageIcon(UnitType unitType, boolean grayscale, double scale) {
return getUnitImageIcon(unitType, Role.DEFAULT, false, grayscale, scale);
}
public ImageIcon getUnitImageIcon(UnitType unitType, double scale) {
return getUnitImageIcon(unitType, Role.DEFAULT, false, false, scale);
}
public ImageIcon getUnitImageIcon(UnitType unitType, Role role) {
return getUnitImageIcon(unitType, role, false, false, scalingFactor);
}
public ImageIcon getUnitImageIcon(UnitType unitType, Role role, boolean grayscale) {
return getUnitImageIcon(unitType, role, false, grayscale, scalingFactor);
}
/**
* Returns the ImageIcon that will represent a unit with the given specifics.
*
* @param unitType the type of unit to be represented
* @param role unit has equipment that affects its abilities/appearance
* @param nativeEthnicity draws the unit with native skin tones
* @param grayscale draws the icon in an inactive/disabled-looking state
* @return an <code>ImageIcon</code> value
*/
public ImageIcon getUnitImageIcon(UnitType unitType, Role role, boolean nativeEthnicity, boolean grayscale, double scale) {
// units that can only be native don't need the .native key part
if (unitType.getId().equals("model.unit.indianConvert")
|| unitType.getId().equals("model.unit.brave")) {
nativeEthnicity = false;
}
else for (Entry<String, Boolean> entry : unitType.getAbilitiesRequired().entrySet()) {
if (entry.getKey().equals("model.ability.native") && entry.getValue() == true) {
nativeEthnicity = false;
}
}
// try to get an image matching the key
final String key = unitType.getId()
+ (role == Role.DEFAULT ? "" : "." + role.getId())
+ (nativeEthnicity ? ".native" : "")
+ ".image";
Image image = null;
if (grayscale) {
image = ResourceManager.getGrayscaleImage(key, scale);
} else {
image = ResourceManager.getImage(key, scale);
}
if (image == null) {
// log and attempt fallback
logger.finest("No image found for image for " + key);
if (nativeEthnicity == true) {
// try non-native variant
return getUnitImageIcon(unitType, role, false, grayscale, scale);
// FIXME: these require the game specification, which ImageLibrary doesn't yet have access to
/* } else if (role != Role.DEFAULT && !unitType.getId().equals("model.unit.freeColonist")) {
// try a free colonist with the same role
unitType = getGame().getSpecification().getUnitType("model.unit.freeColonist");
return getUnitImageIcon(unitType, role, false, grayscale, scale);
} else {
// give up, draw a standard unit icon
unitType = getGame().getSpecification().getUnitType("model.unit.freeColonist");
return getUnitImageIcon(unitType, Role.DEFAULT, false, grayscale, scale);
*/ }
logger.warning("Failed to retrieve image for " + key);
return null;
}
return new ImageIcon(image);
}
public ImageIcon getUnitImageIcon(UnitType unitType, Role role, boolean grayscale, double scale) {
return getUnitImageIcon(unitType, role, false, grayscale, scale);
}
/**
* Gets an image to represent the path of the given <code>Unit</code>.
*
* @param u The <code>Unit</code>
* @return The <code>Image</code>.
*
private Image getPathIllegalImage(Unit u) {
if (u == null || u.isNaval()) {
return (Image) UIManager.get("path.naval.illegal.image");
} else if (u.isMounted()) {
return (Image) UIManager.get("path.horse.illegal.image");
} else if (u.getType() == Unit.WAGON_TRAIN || u.getType() == Unit.TREASURE_TRAIN || u.getType() == Unit.ARTILLERY || u.getType() == Unit.DAMAGED_ARTILLERY) {
return (Image) UIManager.get("path.wagon.illegal.image");
} else {
return (Image) UIManager.get("path.foot.illegal.image");
}
}
*/
public ImageIcon getUnitImageIcon(UnitType unitType, Role role, double scale) {
return getUnitImageIcon(unitType, role, false, false, scale);
}
private String getPathType(Unit unit) {
if (unit.isNaval()) {
return "naval";
} else if (unit.isMounted()) {
return "horse";
} else if (unit.getType().hasSkill() || unit.isUndead()) {
return "foot";
} else {
return "wagon";
}
}
/**
* Create a "chip" with the given text and colors.
*
* @param text a <code>String</code> value
* @param border a <code>Color</code> value
* @param background a <code>Color</code> value
* @param foreground a <code>Color</code> value
* @return an <code>Image</code> value
*/
public Image createChip(String text, Color border, Color background, Color foreground) {
// Draw it and put it in the cache
Font font = ResourceManager.getFont("SimpleFont", Font.BOLD,
(float) Math.rint(12 * getScalingFactor()));
// hopefully, this is big enough
BufferedImage bi = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = bi.createGraphics();
TextLayout label = new TextLayout(text, font, g2.getFontRenderContext());
float padding = 6 * getScalingFactor();
int width = (int) (label.getBounds().getWidth() + padding);
int height = (int) (label.getAscent() + label.getDescent() + padding);
g2.setColor(border);
g2.fillRect(0, 0, width, height);
g2.setColor(background);
g2.fillRect(1, 1, width - 2, height - 2);
g2.setColor(foreground);
label.draw(g2, (float) (padding/2 - label.getBounds().getX()), label.getAscent() + padding/2);
g2.dispose();
return bi.getSubimage(0, 0, width, height);
}
}