/**
* 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.panel;
import java.util.List;
import java.util.logging.Logger;
import org.freecolandroid.repackaged.java.awt.BorderLayout;
import org.freecolandroid.repackaged.java.awt.Dimension;
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.Image;
import org.freecolandroid.repackaged.java.awt.event.MouseAdapter;
import org.freecolandroid.repackaged.java.awt.event.MouseEvent;
import org.freecolandroid.repackaged.java.awt.image.BufferedImage;
import org.freecolandroid.repackaged.javax.swing.ImageIcon;
import org.freecolandroid.repackaged.javax.swing.JButton;
import org.freecolandroid.repackaged.javax.swing.JLabel;
import org.freecolandroid.repackaged.javax.swing.JPanel;
import net.miginfocom.swing.MigLayout;
import net.sf.freecol.client.FreeColClient;
import net.sf.freecol.client.gui.GUI;
import net.sf.freecol.client.gui.ViewMode;
import net.sf.freecol.client.gui.action.EndTurnAction;
import net.sf.freecol.client.gui.i18n.Messages;
import net.sf.freecol.client.gui.panel.MapEditorTransformPanel.MapTransform;
import net.sf.freecol.common.model.AbstractGoods;
import net.sf.freecol.common.model.EquipmentType;
import net.sf.freecol.common.model.Goods;
import net.sf.freecol.common.model.Modifier;
import net.sf.freecol.common.model.StringTemplate;
import net.sf.freecol.common.model.Tile;
import net.sf.freecol.common.model.TileImprovement;
import net.sf.freecol.common.model.Unit;
import net.sf.freecol.common.resources.ResourceManager;
/**
* This is the panel that shows more details about the currently selected unit
* and the tile it stands on. It also shows the amount of gold the player has
* left and stuff like that.
*/
public final class InfoPanel extends FreeColPanel {
@SuppressWarnings("unused")
private static final Logger logger = Logger.getLogger(InfoPanel.class.getName());
private static final int PANEL_WIDTH = 256;
public static final int PANEL_HEIGHT = 128;
private final EndTurnPanel endTurnPanel;
private final UnitInfoPanel unitInfoPanel;
private final TileInfoPanel tileInfoPanel = new TileInfoPanel();
private final JPanel mapEditorPanel;
private Image skin = ResourceManager.getImage("InfoPanel.skin");
private boolean useSkin = true;
/**
* The constructor that will add the items to this panel.
*
* @param freeColClient The main controller object for the client.
* @param gui a <code>GUI</code> value
*/
public InfoPanel(final FreeColClient freeColClient, final GUI gui) {
this(freeColClient, gui, true);
}
/**
* The constructor that will add the items to this panel.
*
* @param freeColClient The main controller object for the client.
* @param gui a <code>GUI</code> value
* @param useSkin a <code>boolean</code> value
*/
public InfoPanel(final FreeColClient freeColClient, final GUI gui, boolean useSkin) {
super(freeColClient, gui);
this.useSkin = useSkin;
this.endTurnPanel = new EndTurnPanel(gui);
unitInfoPanel = new UnitInfoPanel();
setLayout(null);
int internalPanelTop = 0;
int internalPanelHeight = 128;
if (useSkin && skin != null) {
setBorder(null);
setSize(skin.getWidth(null), skin.getHeight(null));
setOpaque(false);
internalPanelTop = 75;
internalPanelHeight = 128;
} else {
setSize(PANEL_WIDTH, PANEL_HEIGHT);
}
mapEditorPanel = new JPanel(null);
mapEditorPanel.setSize(130, 100);
mapEditorPanel.setOpaque(false);
add(unitInfoPanel, internalPanelTop, internalPanelHeight);
add(endTurnPanel, internalPanelTop, internalPanelHeight);
add(tileInfoPanel, internalPanelTop, internalPanelHeight);
add(mapEditorPanel, internalPanelTop, internalPanelHeight);
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
Unit activeUnit = gui.getActiveUnit();
if (activeUnit != null && activeUnit.getTile() != null) {
gui.setFocus(activeUnit.getTile());
}
}
});
}
/**
* Adds a panel to show information
*/
private void add(JPanel panel, int internalPanelTop, int internalPanelHeight) {
panel.setVisible(false);
panel.setLocation((getWidth() - panel.getWidth()) / 2, internalPanelTop
+ (internalPanelHeight - panel.getHeight()) / 2);
add(panel);
}
/**
* Updates this <code>InfoPanel</code>.
*
* @param unit The displayed unit (or null if none)
*/
public void update(Unit unit) {
unitInfoPanel.update(unit);
}
/**
* Updates this <code>InfoPanel</code>.
*
* @param mapTransform The current MapTransform.
*/
public void update(MapTransform mapTransform) {
if (mapTransform != null) {
final JPanel p = mapTransform.getDescriptionPanel();
if (p != null) {
p.setOpaque(false);
final Dimension d = p.getPreferredSize();
p.setBounds(0, (mapEditorPanel.getHeight() - d.height)/2, mapEditorPanel.getWidth(), d.height);
mapEditorPanel.removeAll();
mapEditorPanel.add(p, BorderLayout.CENTER);
mapEditorPanel.validate();
mapEditorPanel.revalidate();
mapEditorPanel.repaint();
}
}
}
/**
* Updates this <code>InfoPanel</code>.
*
* @param tile The displayed tile (or null if none)
*/
public void update(Tile tile) {
tileInfoPanel.update(tile);
}
/**
* Gets the <code>Unit</code> in which this <code>InfoPanel</code> is
* displaying information about.
*
* @return The <code>Unit</code> or <i>null</i> if no <code>Unit</code>
* applies.
*/
public Unit getUnit() {
return unitInfoPanel.getUnit();
}
/**
* Gets the <code>Tile</code> in which this <code>InfoPanel</code> is
* displaying information about.
*
* @return The <code>Tile</code> or <i>null</i> if no <code>Tile</code>
* applies.
*/
public Tile getTile() {
return tileInfoPanel.getTile();
}
/**
* Paints this component.
*
* @param graphics The Graphics context in which to draw this component.
*/
@Override
public void paintComponent(Graphics graphics) {
int viewMode = getGUI().getCurrentViewMode();
mapEditorPanel.setVisible(false);
unitInfoPanel.setVisible(false);
endTurnPanel.setVisible(false);
tileInfoPanel.setVisible(false);
if (getFreeColClient().isMapEditor()) {
mapEditorPanel.setVisible(true);
} else if (viewMode == ViewMode.VIEW_TERRAIN_MODE) {
tileInfoPanel.setVisible(true);
} else if (unitInfoPanel.getUnit() != null) {
unitInfoPanel.setVisible(true);
} else if (getMyPlayer() != null
&& !getMyPlayer().hasNextActiveUnit()) {
endTurnPanel.setVisible(true);
}
if (useSkin && skin != null) {
graphics.drawImage(skin, 0, 0, null);
}
super.paintComponent(graphics);
}
/**
* Panel for displaying <code>Tile</code>-information.
*/
public class TileInfoPanel extends JPanel {
private Tile tile;
private Font font = new JLabel().getFont().deriveFont(9f);
public TileInfoPanel() {
super(null);
setSize(226, 128);
setOpaque(false);
setLayout(new MigLayout("fill, wrap 5, gap 2 2"));
}
/**
* Updates this <code>InfoPanel</code>.
*
* @param tile The displayed tile (or null if none)
*/
public void update(Tile tile) {
this.tile = tile;
removeAll();
if (tile != null) {
int width = getLibrary().getTerrainImageWidth(tile.getType());
int height = getLibrary().getTerrainImageHeight(tile.getType());
int compoundHeight = getLibrary().getCompoundTerrainImageHeight(tile.getType());
BufferedImage image = new BufferedImage(width, compoundHeight, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = image.createGraphics();
g.translate(0, compoundHeight - height);
getGUI().getMapViewer().displayTerrain(g, tile);
if (tile.isExplored()) {
StringTemplate items = StringTemplate.label(", ");
items.add(tile.getNameKey());
for (TileImprovement tileImprovement : tile.getCompletedTileImprovements()) {
items.add(tileImprovement.getType().getDescriptionKey());
}
add(new JLabel(Messages.message(items)), "span, align center");
add(new JLabel(new ImageIcon(image)), "spany");
if (tile.getOwner() != null) {
JLabel ownerLabel = localizedLabel(tile.getOwner().getNationName());
ownerLabel.setFont(font);
add(ownerLabel, "span 4");
}
int defenceBonus = (int) tile.getType().getFeatureContainer()
.applyModifier(100, Modifier.DEFENCE) - 100;
JLabel defenceLabel = new JLabel(Messages.message("colopedia.terrain.defenseBonus") +
" " + defenceBonus + "%");
defenceLabel.setFont(font);
add(defenceLabel, "span 4");
JLabel moveLabel = new JLabel(Messages.message("colopedia.terrain.movementCost") +
" " + String.valueOf(tile.getType().getBasicMoveCost()/3));
moveLabel.setFont(font);
add(moveLabel, "span 4");
List<AbstractGoods> production = tile.getType().getProduction();
for (AbstractGoods goods : production) {
JLabel goodsLabel = new JLabel(String.valueOf(tile.potential(goods.getType(), null)),
getLibrary().getScaledGoodsImageIcon(goods.getType(), 0.50f),
JLabel.RIGHT);
goodsLabel.setToolTipText(Messages.message(goods.getType().getNameKey()));
goodsLabel.setFont(font);
add(goodsLabel);
}
} else {
add(new JLabel(Messages.message("unexplored")), "span, align center");
add(new JLabel(new ImageIcon(image)), "spany");
}
revalidate();
repaint();
}
}
/**
* Gets the <code>Tile</code> in which this <code>InfoPanel</code>
* is displaying information about.
*
* @return The <code>Tile</code> or <i>null</i> if no
* <code>Tile</code> applies.
*/
public Tile getTile() {
return tile;
}
}
/**
* Panel for displaying <code>Unit</code>-information.
*/
public class UnitInfoPanel extends JPanel {
private Unit unit;
public UnitInfoPanel() {
super(new MigLayout("wrap 6, fill, gap 0 0", "", ""));
setSize(226, 100);
setOpaque(false);
}
/**
* Updates this <code>InfoPanel</code>.
*
* @param unit The displayed unit (or null if none)
*/
public void update(Unit unit) {
this.unit = unit;
removeAll();
if (unit != null) {
add(new JLabel(getLibrary().getUnitImageIcon(unit)), "spany, gapafter 5px");
String name = Messages.message(Messages.getLabel(unit));
// TODO: this is too brittle!
int index = name.indexOf(" (");
if (index < 0) {
add(new JLabel(name), "span");
} else {
add(new JLabel(name.substring(0, index)), "span");
add(new JLabel(name.substring(index + 1)), "span");
}
add(new JLabel(Messages.message("moves") + " " + unit.getMovesAsString()), "span");
// Handle the special cases. TODO: make this more generic
if (unit.canCarryTreasure()) {
add(new JLabel(unit.getTreasureAmount() + " " + Messages.message("gold")), "span");
} else if (unit.isCarrier()) {
for (Goods goods : unit.getGoodsList()) {
JLabel goodsLabel = new JLabel(getLibrary().getScaledGoodsImageIcon(goods.getType(), 0.66f));
goodsLabel.setToolTipText(Messages.message(StringTemplate.template("model.goods.goodsAmount")
.addAmount("%amount%", goods.getAmount())
.add("%goods%", goods.getNameKey())));
add(goodsLabel);
}
for (Unit carriedUnit : unit.getUnitList()) {
ImageIcon unitIcon = getLibrary().getUnitImageIcon(carriedUnit, 0.5);
JLabel unitLabel = new JLabel(unitIcon);
unitLabel.setToolTipText(Messages.message(carriedUnit.getLabel()));
add(unitLabel);
}
} else {
for (EquipmentType equipment : unit.getEquipment().keySet()) {
for (AbstractGoods goods : equipment.getGoodsRequired()) {
int amount = goods.getAmount() * unit.getEquipment().getCount(equipment);
JLabel equipmentLabel =
new JLabel(Integer.toString(amount),
getLibrary().getScaledGoodsImageIcon(goods.getType(), 0.66f),
JLabel.CENTER);
equipmentLabel
.setToolTipText(Messages.message(StringTemplate.template("model.goods.goodsAmount")
.addAmount("%amount%", amount)
.add("%goods%", goods.getNameKey())));
add(equipmentLabel);
}
}
}
}
revalidate();
repaint();
}
/**
* Gets the <code>Unit</code> in which this <code>InfoPanel</code>
* is displaying information about.
*
* @return The <code>Unit</code> or <i>null</i> if no
* <code>Unit</code> applies.
*/
public Unit getUnit() {
return unit;
}
}
/**
* Panel for ending the turn.
*/
public class EndTurnPanel extends JPanel {
public EndTurnPanel(GUI gui) {
super(new MigLayout("wrap 1, center", "[center]", ""));
String labelString = Messages.message("infoPanel.endTurnPanel.text");
int width = getFontMetrics(getFont()).stringWidth(labelString);
if (width > 150 ) {
int index = Messages.getBreakingPoint(labelString);
if (index > 0) {
add(new JLabel(labelString.substring(0, index)));
add(new JLabel(labelString.substring(index + 1)));
} else {
add(new JLabel(labelString));
}
} else {
add(new JLabel(labelString));
}
add(new JButton(getFreeColClient().getActionManager()
.getFreeColAction(EndTurnAction.id)));
setOpaque(false);
setSize(getPreferredSize());
}
}
}