mirror of https://github.com/FreeCol/freecol.git
1550 lines
59 KiB
Java
1550 lines
59 KiB
Java
/**
|
|
* Copyright (C) 2002-2007 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.awt.Color;
|
|
import java.awt.Component;
|
|
import java.awt.Container;
|
|
import java.awt.Dimension;
|
|
import java.awt.FlowLayout;
|
|
import java.awt.Graphics;
|
|
import java.awt.Graphics2D;
|
|
import java.awt.GridLayout;
|
|
import java.awt.Insets;
|
|
import java.awt.Point;
|
|
import java.awt.Rectangle;
|
|
import java.awt.dnd.Autoscroll;
|
|
import java.awt.event.ActionEvent;
|
|
import java.awt.event.ActionListener;
|
|
import java.awt.event.KeyEvent;
|
|
import java.awt.event.MouseAdapter;
|
|
import java.awt.event.MouseEvent;
|
|
import java.awt.event.MouseListener;
|
|
import java.beans.PropertyChangeEvent;
|
|
import java.beans.PropertyChangeListener;
|
|
import java.util.ArrayList;
|
|
import java.util.Collections;
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
import java.util.logging.Logger;
|
|
|
|
import javax.swing.BorderFactory;
|
|
import javax.swing.ComponentInputMap;
|
|
import javax.swing.ImageIcon;
|
|
import javax.swing.InputMap;
|
|
import javax.swing.JButton;
|
|
import javax.swing.JComboBox;
|
|
import javax.swing.JComponent;
|
|
import javax.swing.JLabel;
|
|
import javax.swing.JPanel;
|
|
import javax.swing.JScrollPane;
|
|
import javax.swing.JToolTip;
|
|
import javax.swing.JViewport;
|
|
import javax.swing.KeyStroke;
|
|
import javax.swing.ScrollPaneConstants;
|
|
import javax.swing.SwingUtilities;
|
|
import javax.swing.border.BevelBorder;
|
|
|
|
import net.miginfocom.swing.MigLayout;
|
|
import net.sf.freecol.client.ClientOptions;
|
|
import net.sf.freecol.client.gui.Canvas;
|
|
import net.sf.freecol.client.gui.GUI;
|
|
import net.sf.freecol.client.gui.i18n.Messages;
|
|
import net.sf.freecol.common.model.AbstractGoods;
|
|
import net.sf.freecol.common.model.BuildableType;
|
|
import net.sf.freecol.common.model.Building;
|
|
import net.sf.freecol.common.model.Colony;
|
|
import net.sf.freecol.common.model.ColonyTile;
|
|
import net.sf.freecol.common.model.Game;
|
|
import net.sf.freecol.common.model.Goods;
|
|
import net.sf.freecol.common.model.GoodsType;
|
|
import net.sf.freecol.common.model.IndianSettlement;
|
|
import net.sf.freecol.common.model.ModelMessage;
|
|
import net.sf.freecol.common.model.Player;
|
|
import net.sf.freecol.common.model.Settlement;
|
|
import net.sf.freecol.common.model.Specification;
|
|
import net.sf.freecol.common.model.StringTemplate;
|
|
import net.sf.freecol.common.model.Tile;
|
|
import net.sf.freecol.common.model.TileType;
|
|
import net.sf.freecol.common.model.TradeRoute;
|
|
import net.sf.freecol.common.model.Unit;
|
|
import net.sf.freecol.common.model.Colony.ColonyChangeEvent;
|
|
import net.sf.freecol.common.resources.ResourceManager;
|
|
|
|
/**
|
|
* This is a panel for the Colony display. It shows the units that are working
|
|
* in the colony, the buildings and much more.
|
|
*/
|
|
public final class ColonyPanel extends FreeColPanel implements ActionListener,PropertyChangeListener {
|
|
|
|
|
|
private static Logger logger = Logger.getLogger(ColonyPanel.class.getName());
|
|
|
|
/**
|
|
* The height of the area in which autoscrolling should happen.
|
|
*/
|
|
public static final int SCROLL_AREA_HEIGHT = 40;
|
|
|
|
/**
|
|
* The speed of the scrolling.
|
|
*/
|
|
public static final int SCROLL_SPEED = 40;
|
|
|
|
private static final int EXIT = 0, BUILDQUEUE = 1, UNLOAD = 2, WAREHOUSE = 4, FILL = 5;
|
|
|
|
private final JLabel rebelShield = new JLabel();
|
|
private final JLabel rebelLabel = new JLabel();
|
|
private final JLabel bonusLabel = new JLabel();
|
|
private final JLabel royalistLabel = new JLabel();
|
|
private final JLabel royalistShield = new JLabel();
|
|
private final JLabel rebelMemberLabel = new JLabel();
|
|
private final JLabel popLabel = new JLabel();
|
|
private final JLabel royalistMemberLabel = new JLabel();
|
|
|
|
private final JPanel rightProductionPanel = new JPanel();
|
|
private final JPanel populationPanel = new JPanel() {
|
|
public JToolTip createToolTip() {
|
|
return new RebelToolTip(colony, getCanvas());
|
|
}
|
|
};
|
|
|
|
private final JComboBox nameBox;
|
|
|
|
private final OutsideColonyPanel outsideColonyPanel;
|
|
|
|
private final InPortPanel inPortPanel;
|
|
|
|
private final ColonyCargoPanel cargoPanel;
|
|
|
|
private final WarehousePanel warehousePanel;
|
|
|
|
private final TilePanel tilePanel;
|
|
|
|
private final BuildingsPanel buildingsPanel;
|
|
|
|
private final ConstructionPanel constructionPanel;
|
|
|
|
private final DefaultTransferHandler defaultTransferHandler;
|
|
|
|
private final MouseListener pressListener;
|
|
|
|
private final MouseListener releaseListener;
|
|
|
|
private Colony colony;
|
|
|
|
private UnitLabel selectedUnit;
|
|
|
|
private JButton exitButton = new JButton(Messages.message("close"));
|
|
|
|
private JButton unloadButton = new JButton(Messages.message("unload"));
|
|
|
|
private JButton fillButton = new JButton(Messages.message("fill"));
|
|
|
|
private JButton warehouseButton = new JButton(Messages.message("warehouseDialog.name"));
|
|
|
|
private JButton buildQueueButton = new JButton(Messages.message("colonyPanel.buildQueue"));
|
|
|
|
/**
|
|
* The saved size of this panel.
|
|
*/
|
|
private static Dimension savedSize = null;
|
|
|
|
|
|
/**
|
|
* The constructor for the panel.
|
|
*
|
|
* @param parent The parent of this panel
|
|
*/
|
|
public ColonyPanel(final Canvas parent, Colony colony) {
|
|
super(parent);
|
|
|
|
setFocusCycleRoot(true);
|
|
|
|
// Use ESCAPE for closing the ColonyPanel:
|
|
InputMap closeInputMap = new ComponentInputMap(exitButton);
|
|
closeInputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false), "pressed");
|
|
closeInputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, true), "released");
|
|
SwingUtilities.replaceUIInputMap(exitButton, JComponent.WHEN_IN_FOCUSED_WINDOW, closeInputMap);
|
|
|
|
InputMap unloadInputMap = new ComponentInputMap(unloadButton);
|
|
unloadInputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_U, 0, false), "pressed");
|
|
unloadInputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_U, 0, true), "released");
|
|
SwingUtilities.replaceUIInputMap(unloadButton, JComponent.WHEN_IN_FOCUSED_WINDOW, unloadInputMap);
|
|
|
|
InputMap fillInputMap = new ComponentInputMap(fillButton);
|
|
fillInputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_L, 0, false), "pressed");
|
|
fillInputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_L, 0, true), "released");
|
|
SwingUtilities.replaceUIInputMap(fillButton, JComponent.WHEN_IN_FOCUSED_WINDOW, fillInputMap);
|
|
|
|
rightProductionPanel.setOpaque(false);
|
|
|
|
populationPanel.setOpaque(false);
|
|
populationPanel.setToolTipText(" ");
|
|
populationPanel.setLayout(new MigLayout("wrap 5, fill, insets 0",
|
|
"[][]:push[center]:push[right][]", ""));
|
|
populationPanel.add(rebelShield, "bottom");
|
|
populationPanel.add(rebelLabel, "split 2, flowy");
|
|
populationPanel.add(rebelMemberLabel);
|
|
populationPanel.add(popLabel, "split 2, flowy");
|
|
populationPanel.add(bonusLabel);
|
|
populationPanel.add(royalistLabel, "split 2, flowy");
|
|
populationPanel.add(royalistMemberLabel);
|
|
populationPanel.add(royalistShield, "bottom");
|
|
|
|
constructionPanel = new ConstructionPanel(parent, colony);
|
|
constructionPanel.setOpaque(false);
|
|
|
|
outsideColonyPanel = new OutsideColonyPanel();
|
|
outsideColonyPanel.setLayout(new GridLayout(0, 8));
|
|
|
|
inPortPanel = new InPortPanel();
|
|
inPortPanel.setLayout(new GridLayout(0, 2));
|
|
|
|
warehousePanel = new WarehousePanel(this);
|
|
warehousePanel.setLayout(new GridLayout(1, 0));
|
|
|
|
tilePanel = new TilePanel(this);
|
|
|
|
buildingsPanel = new BuildingsPanel(this);
|
|
|
|
cargoPanel = new ColonyCargoPanel(parent);
|
|
cargoPanel.setParentPanel(this);
|
|
cargoPanel.setLayout(new GridLayout(1, 0));
|
|
|
|
defaultTransferHandler = new DefaultTransferHandler(parent, this);
|
|
pressListener = new DragListener(this);
|
|
releaseListener = new DropListener();
|
|
|
|
JScrollPane outsideColonyScroll = new JScrollPane(outsideColonyPanel,
|
|
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
|
|
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
|
outsideColonyScroll.getVerticalScrollBar().setUnitIncrement( 16 );
|
|
JScrollPane inPortScroll = new JScrollPane(inPortPanel,
|
|
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
|
|
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
|
inPortScroll.getVerticalScrollBar().setUnitIncrement( 16 );
|
|
JScrollPane cargoScroll = new JScrollPane(cargoPanel,
|
|
ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER,
|
|
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
|
|
JScrollPane warehouseScroll = new JScrollPane(warehousePanel,
|
|
ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER,
|
|
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
|
|
JScrollPane tilesScroll = new JScrollPane(tilePanel,
|
|
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
|
|
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
|
|
JScrollPane buildingsScroll = new JScrollPane(buildingsPanel,
|
|
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
|
|
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
|
buildingsScroll.getVerticalScrollBar().setUnitIncrement( 16 );
|
|
|
|
// Make the colony label
|
|
nameBox = new JComboBox();
|
|
nameBox.setFont(smallHeaderFont);
|
|
List<Colony> settlements = colony.getOwner().getColonies();
|
|
sortColonies(settlements);
|
|
for (Colony aColony : settlements) {
|
|
nameBox.addItem(aColony);
|
|
}
|
|
nameBox.setSelectedItem(colony);
|
|
nameBox.addActionListener(new ActionListener() {
|
|
public void actionPerformed(ActionEvent event) {
|
|
initialize((Colony) nameBox.getSelectedItem());
|
|
}
|
|
});
|
|
|
|
buildingsScroll.setAutoscrolls(true);
|
|
buildingsScroll.getViewport().setOpaque(false);
|
|
buildingsPanel.setOpaque(false);
|
|
|
|
/** Borders */
|
|
tilesScroll.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
|
|
buildingsScroll.setBorder(BorderFactory.createEtchedBorder());
|
|
warehouseScroll.setBorder(BorderFactory.createEtchedBorder());
|
|
cargoScroll.setBorder(BorderFactory.createEtchedBorder());
|
|
inPortScroll.setBorder(BorderFactory.createEtchedBorder());
|
|
outsideColonyScroll.setBorder(BorderFactory.createEtchedBorder());
|
|
|
|
exitButton.setActionCommand(String.valueOf(EXIT));
|
|
enterPressesWhenFocused(exitButton);
|
|
exitButton.addActionListener(this);
|
|
|
|
unloadButton.setActionCommand(String.valueOf(UNLOAD));
|
|
enterPressesWhenFocused(unloadButton);
|
|
unloadButton.addActionListener(this);
|
|
|
|
fillButton.setActionCommand(String.valueOf(FILL));
|
|
enterPressesWhenFocused(fillButton);
|
|
fillButton.addActionListener(this);
|
|
|
|
warehouseButton.setActionCommand(String.valueOf(WAREHOUSE));
|
|
enterPressesWhenFocused(warehouseButton);
|
|
warehouseButton.addActionListener(this);
|
|
|
|
buildQueueButton.setActionCommand(String.valueOf(BUILDQUEUE));
|
|
enterPressesWhenFocused(buildQueueButton);
|
|
buildQueueButton.addActionListener(this);
|
|
|
|
selectedUnit = null;
|
|
|
|
// See the message of Ulf Onnen for more information about the presence
|
|
// of this fake mouse listener.
|
|
addMouseListener(new MouseAdapter() {
|
|
});
|
|
|
|
setLayout(new MigLayout("fill, wrap 2, insets 2", "[390!][fill]", "[][][][][growprio 200,shrinkprio 10][growprio 150,shrinkprio 50]"));
|
|
|
|
add(nameBox, "height 48:, grow");
|
|
add(rightProductionPanel);
|
|
add(tilesScroll, "width 390!, height 200!, top");
|
|
add(buildingsScroll, "span 1 3, grow");
|
|
add(populationPanel, "grow");
|
|
add(constructionPanel, "growx, top");
|
|
add(inPortScroll, "split 2, grow, height 60:121:");
|
|
add(cargoScroll, "grow, height 60:121:");
|
|
add(outsideColonyScroll, "grow, height 60:121:");
|
|
add(warehouseScroll, "span, height 40:60:80, growx");
|
|
add(unloadButton, "span, split 5, align center");
|
|
add(fillButton);
|
|
add(warehouseButton);
|
|
add(buildQueueButton);
|
|
add(exitButton);
|
|
|
|
initialize(colony);
|
|
if (savedSize != null) {
|
|
setPreferredSize(savedSize);
|
|
}
|
|
|
|
}
|
|
|
|
@Override
|
|
public void requestFocus() {
|
|
exitButton.requestFocus();
|
|
}
|
|
|
|
/**
|
|
* Get the <code>SavedSize</code> value.
|
|
*
|
|
* @return a <code>Dimension</code> value
|
|
*/
|
|
public final Dimension getSavedSize() {
|
|
return savedSize;
|
|
}
|
|
|
|
/**
|
|
* Set the <code>SavedSize</code> value.
|
|
*
|
|
* @param newSavedSize The new SavedSize value.
|
|
*/
|
|
public final void setSavedSize(final Dimension newSavedSize) {
|
|
ColonyPanel.savedSize = newSavedSize;
|
|
}
|
|
|
|
/**
|
|
* Initialize the data on the window. This is the same as calling:
|
|
* <code>initialize(colony, game, null)</code>.
|
|
*
|
|
* @param colony The <code>Colony</code> to be displayed.
|
|
*/
|
|
public void initialize(Colony colony) {
|
|
initialize(colony, null);
|
|
}
|
|
|
|
/**
|
|
* Initialize the data on the window.
|
|
*
|
|
* @param colony The <code>Colony</code> to be displayed.
|
|
* @param preSelectedUnit This <code>Unit</code> will be selected if it is
|
|
* not <code>null</code> and it is a carrier located in the
|
|
* given <code>Colony</code>.
|
|
*/
|
|
public void initialize(final Colony colony, Unit preSelectedUnit) {
|
|
setColony(colony);
|
|
|
|
rebelShield.setIcon(new ImageIcon(ResourceManager.getImage(colony.getOwner().getNation().getId()
|
|
+ ".coat-of-arms.image", 0.5)));
|
|
royalistShield.setIcon(new ImageIcon(ResourceManager.getImage(colony.getOwner().getNation().getRefNation().getId()
|
|
+ ".coat-of-arms.image", 0.5)));
|
|
// Set listeners and transfer handlers
|
|
outsideColonyPanel.removeMouseListener(releaseListener);
|
|
inPortPanel.removeMouseListener(releaseListener);
|
|
cargoPanel.removeMouseListener(releaseListener);
|
|
warehousePanel.removeMouseListener(releaseListener);
|
|
if (isEditable()) {
|
|
outsideColonyPanel.setTransferHandler(defaultTransferHandler);
|
|
inPortPanel.setTransferHandler(defaultTransferHandler);
|
|
cargoPanel.setTransferHandler(defaultTransferHandler);
|
|
warehousePanel.setTransferHandler(defaultTransferHandler);
|
|
|
|
outsideColonyPanel.addMouseListener(releaseListener);
|
|
inPortPanel.addMouseListener(releaseListener);
|
|
cargoPanel.addMouseListener(releaseListener);
|
|
warehousePanel.addMouseListener(releaseListener);
|
|
} else {
|
|
outsideColonyPanel.setTransferHandler(null);
|
|
inPortPanel.setTransferHandler(null);
|
|
cargoPanel.setTransferHandler(null);
|
|
warehousePanel.setTransferHandler(null);
|
|
}
|
|
|
|
// Enable/disable widgets
|
|
unloadButton.setEnabled(isEditable());
|
|
fillButton.setEnabled(isEditable());
|
|
warehouseButton.setEnabled(isEditable());
|
|
nameBox.setEnabled(isEditable());
|
|
|
|
// update all the subpanels
|
|
cargoPanel.removeAll();
|
|
warehousePanel.removeAll();
|
|
tilePanel.removeAll();
|
|
|
|
inPortPanel.initialize(preSelectedUnit);
|
|
warehousePanel.initialize();
|
|
buildingsPanel.initialize();
|
|
tilePanel.initialize();
|
|
|
|
updateProductionPanel();
|
|
updateSoLLabel();
|
|
|
|
constructionPanel.setColony(colony);
|
|
outsideColonyPanel.setColony(colony);
|
|
}
|
|
|
|
/**
|
|
* Enables the unload and fill buttons if the currently selected unit is a
|
|
* carrier with some cargo.
|
|
*/
|
|
private void updateCarrierButtons() {
|
|
unloadButton.setEnabled(false);
|
|
fillButton.setEnabled(false);
|
|
if (isEditable() && selectedUnit != null) {
|
|
Unit unit = selectedUnit.getUnit();
|
|
if (unit != null && unit.isCarrier() && unit.getSpaceLeft() < unit.getType().getSpace()) {
|
|
unloadButton.setEnabled(true);
|
|
for (Goods goods : unit.getGoodsList()) {
|
|
if (getColony().getGoodsCount(goods.getType()) > 0) {
|
|
fillButton.setEnabled(true);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Updates the SoL membership label.
|
|
*/
|
|
private void updateSoLLabel() {
|
|
int population = colony.getUnitCount();
|
|
int members = getColony().getMembers();
|
|
int rebels = getColony().getSoL();
|
|
String rebelNumber = Messages.message("colonyPanel.rebelLabel", "%number%",
|
|
Integer.toString(members));
|
|
String royalistNumber = Messages.message("colonyPanel.royalistLabel", "%number%",
|
|
Integer.toString(population - members));
|
|
/*
|
|
* TODO : remove compatibility code sometime after 0.9.1
|
|
*
|
|
* The string templates were changed from percentages to
|
|
* absolute numbers shortly before 0.9.0, so that translators
|
|
* had no chance to catch up.
|
|
*/
|
|
if (rebelNumber.endsWith("%")) {
|
|
rebelNumber = rebelNumber.substring(0, rebelNumber.length() - 1);
|
|
}
|
|
if (royalistNumber.endsWith("%")) {
|
|
royalistNumber = royalistNumber.substring(0, royalistNumber.length() - 1);
|
|
}
|
|
// end TODO
|
|
|
|
popLabel.setText(Messages.message("colonyPanel.populationLabel", "%number%",
|
|
Integer.toString(population)));
|
|
rebelLabel.setText(rebelNumber);
|
|
rebelMemberLabel.setText(Integer.toString(rebels) + "%");
|
|
bonusLabel.setText(Messages.message("colonyPanel.bonusLabel", "%number%",
|
|
Integer.toString(getColony().getProductionBonus())));
|
|
royalistLabel.setText(royalistNumber);
|
|
royalistMemberLabel.setText(Integer.toString(getColony().getTory()) + "%");
|
|
}
|
|
|
|
public void updateInPortPanel() {
|
|
inPortPanel.initialize(null);
|
|
}
|
|
|
|
public void updateWarehousePanel() {
|
|
warehousePanel.update();
|
|
}
|
|
|
|
public void updateTilePanel() {
|
|
tilePanel.initialize();
|
|
}
|
|
|
|
private void sortBuildings(List<Building> buildings) {
|
|
Collections.sort(buildings);
|
|
}
|
|
|
|
private void sortColonies(List<Colony> colonies) {
|
|
Collections.sort(colonies, getClient().getClientOptions().getColonyComparator());
|
|
}
|
|
|
|
public void updateProductionPanel() {
|
|
rightProductionPanel.removeAll();
|
|
|
|
GoodsType grain = getSpecification().getGoodsType("model.goods.food");
|
|
int food = 0;
|
|
|
|
List<AbstractGoods> foodProduction = new ArrayList<AbstractGoods>();
|
|
for (GoodsType goodsType : getSpecification().getGoodsTypeList()) {
|
|
int production = colony.getProductionOf(goodsType);
|
|
if (production != 0) {
|
|
if (goodsType.isFoodType()) {
|
|
foodProduction.add(new AbstractGoods(goodsType, production));
|
|
food += production;
|
|
} else if (goodsType.isBreedable()) {
|
|
ProductionLabel horseLabel = new ProductionLabel(goodsType, production, getCanvas());
|
|
horseLabel.setMaxGoodsIcons(1);
|
|
rightProductionPanel.add(horseLabel);
|
|
} else if (goodsType.isImmigrationType() || goodsType.isLibertyType()) {
|
|
int consumption = colony.getConsumption(goodsType);
|
|
ProductionLabel bellsLabel = new ProductionLabel(goodsType, production, getCanvas());
|
|
bellsLabel.setToolTipPrefix(Messages.message("totalProduction"));
|
|
if (consumption != 0) {
|
|
int surplus = production - consumption;
|
|
ProductionLabel surplusLabel = new ProductionLabel(goodsType, surplus, getCanvas());
|
|
surplusLabel.setToolTipPrefix(Messages.message("surplusProduction"));
|
|
rightProductionPanel.add(surplusLabel, 0);
|
|
}
|
|
rightProductionPanel.add(bellsLabel, 0);
|
|
} else {
|
|
production = colony.getProductionNetOf(goodsType);
|
|
rightProductionPanel.add(new ProductionLabel(goodsType, production, getCanvas()));
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
ProductionMultiplesLabel surplusLabel =
|
|
new ProductionMultiplesLabel(surplusProduction, getCanvas());
|
|
surplusLabel.setDrawPlus(true);
|
|
surplusLabel.setToolTipPrefix(Messages.message("surplusProduction"));
|
|
rightProductionPanel.add(surplusLabel, 0);
|
|
*/
|
|
rightProductionPanel.add(new ProductionLabel(grain, food - colony.getFoodConsumption(), getCanvas()), 0);
|
|
|
|
ProductionMultiplesLabel label = new ProductionMultiplesLabel(foodProduction, getCanvas());
|
|
label.setToolTipPrefix(Messages.message("totalProduction"));
|
|
rightProductionPanel.add(label, 0);
|
|
|
|
rightProductionPanel.revalidate();
|
|
}
|
|
|
|
/**
|
|
* Returns the currently select unit.
|
|
*
|
|
* @return The currently select unit.
|
|
*/
|
|
public Unit getSelectedUnit() {
|
|
if (selectedUnit == null)
|
|
return null;
|
|
else
|
|
return selectedUnit.getUnit();
|
|
}
|
|
|
|
/**
|
|
* Returns the currently select unit.
|
|
*
|
|
* @return The currently select unit.
|
|
*/
|
|
public UnitLabel getSelectedUnitLabel() {
|
|
return selectedUnit;
|
|
}
|
|
|
|
/**
|
|
* Analyzes an event and calls the right external methods to take care of
|
|
* the user's request.
|
|
*
|
|
* @param event The incoming action event
|
|
*/
|
|
public void actionPerformed(ActionEvent event) {
|
|
String command = event.getActionCommand();
|
|
try {
|
|
switch (Integer.valueOf(command).intValue()) {
|
|
case EXIT:
|
|
closeColonyPanel();
|
|
break;
|
|
case UNLOAD:
|
|
unload();
|
|
break;
|
|
case WAREHOUSE:
|
|
if (getCanvas().showFreeColDialog(new WarehouseDialog(getCanvas(), colony))) {
|
|
warehousePanel.update();
|
|
}
|
|
break;
|
|
case BUILDQUEUE:
|
|
getCanvas().showSubPanel(new BuildQueuePanel(colony, getCanvas()));
|
|
break;
|
|
case FILL:
|
|
fill();
|
|
break;
|
|
default:
|
|
logger.warning("Invalid action");
|
|
}
|
|
} catch (NumberFormatException e) {
|
|
logger.warning("Invalid action number: " + command);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Unloads all goods and units from the carrier currently selected.
|
|
*/
|
|
private void unload() {
|
|
Unit unit = getSelectedUnit();
|
|
if (unit != null && unit.isCarrier()) {
|
|
Iterator<Goods> goodsIterator = unit.getGoodsIterator();
|
|
while (goodsIterator.hasNext()) {
|
|
Goods goods = goodsIterator.next();
|
|
getController().unloadCargo(goods, false);
|
|
}
|
|
Iterator<Unit> unitIterator = unit.getUnitIterator();
|
|
while (unitIterator.hasNext()) {
|
|
Unit newUnit = unitIterator.next();
|
|
getController().leaveShip(newUnit);
|
|
}
|
|
cargoPanel.initialize();
|
|
outsideColonyPanel.initialize();
|
|
}
|
|
unloadButton.setEnabled(false);
|
|
fillButton.setEnabled(false);
|
|
}
|
|
|
|
/**
|
|
* Fill goods from the carrier currently selected until 100 units.
|
|
*/
|
|
private void fill() {
|
|
Unit unit = getSelectedUnit();
|
|
if (unit != null && unit.isCarrier()) {
|
|
Iterator<Goods> goodsIterator = unit.getGoodsIterator();
|
|
while (goodsIterator.hasNext()) {
|
|
Goods goods = goodsIterator.next();
|
|
if (goods.getAmount() < 100 && colony.getGoodsCount(goods.getType()) > 0) {
|
|
int amount = Math.min(100 - goods.getAmount(), colony.getGoodsCount(goods.getType()));
|
|
getController().loadCargo(new Goods(goods.getGame(), colony, goods.getType(), amount), unit);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Closes the <code>ColonyPanel</code>.
|
|
*/
|
|
public void closeColonyPanel() {
|
|
Canvas canvas = getCanvas();
|
|
if (getColony().getUnitCount() == 0) {
|
|
if (canvas.showConfirmDialog("abandonColony.text",
|
|
"abandonColony.yes",
|
|
"abandonColony.no")) {
|
|
canvas.remove(this);
|
|
getController().abandonColony(getColony());
|
|
}
|
|
} else {
|
|
BuildableType buildable = colony.getCurrentlyBuilding();
|
|
if (buildable != null
|
|
&& buildable.getPopulationRequired() > colony.getUnitCount()
|
|
&& !canvas.showConfirmDialog(null, StringTemplate.template("colonyPanel.reducePopulation")
|
|
.addName("%colony%", colony.getName())
|
|
.addAmount("%number%", buildable.getPopulationRequired())
|
|
.add("%buildable%", buildable.getNameKey()),
|
|
"ok", "cancel")) {
|
|
return;
|
|
}
|
|
canvas.remove(this);
|
|
// remove property listeners
|
|
if (colony != null) {
|
|
colony.removePropertyChangeListener(this);
|
|
colony.getTile().removePropertyChangeListener(Tile.UNIT_CHANGE, outsideColonyPanel);
|
|
colony.getGoodsContainer().removePropertyChangeListener(warehousePanel);
|
|
}
|
|
if (getSelectedUnit() != null) {
|
|
getSelectedUnit().removePropertyChangeListener(this);
|
|
}
|
|
buildingsPanel.removePropertyChangeListeners();
|
|
tilePanel.removePropertyChangeListeners();
|
|
|
|
if (getGame().getCurrentPlayer() == getMyPlayer()) {
|
|
getController().nextModelMessage();
|
|
Unit activeUnit = canvas.getGUI().getActiveUnit();
|
|
if (activeUnit == null || activeUnit.getTile() == null || activeUnit.getMovesLeft() <= 0
|
|
|| (!(activeUnit.getLocation() instanceof Tile) && !(activeUnit.isOnCarrier()))) {
|
|
canvas.getGUI().setActiveUnit(null);
|
|
getController().nextActiveUnit();
|
|
}
|
|
}
|
|
getClient().getGUI().restartBlinking();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Selects a unit that is located somewhere on this panel.
|
|
*
|
|
* @param unit The unit that is being selected.
|
|
*/
|
|
public void setSelectedUnit(Unit unit) {
|
|
Component[] components = inPortPanel.getComponents();
|
|
for (int i = 0; i < components.length; i++) {
|
|
if (components[i] instanceof UnitLabel && ((UnitLabel) components[i]).getUnit() == unit) {
|
|
setSelectedUnitLabel((UnitLabel) components[i]);
|
|
break;
|
|
}
|
|
}
|
|
updateCarrierButtons();
|
|
}
|
|
|
|
/**
|
|
* Selects a unit that is located somewhere on this panel.
|
|
*
|
|
* @param unitLabel The unit that is being selected.
|
|
*/
|
|
public void setSelectedUnitLabel(UnitLabel unitLabel) {
|
|
if (selectedUnit != unitLabel) {
|
|
if (selectedUnit != null) {
|
|
selectedUnit.setSelected(false);
|
|
selectedUnit.getUnit().removePropertyChangeListener(this);
|
|
}
|
|
selectedUnit = unitLabel;
|
|
if (unitLabel == null) {
|
|
cargoPanel.setCarrier(null);
|
|
} else {
|
|
cargoPanel.setCarrier(unitLabel.getUnit());
|
|
unitLabel.setSelected(true);
|
|
unitLabel.getUnit().addPropertyChangeListener(this);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns a pointer to the <code>CargoPanel</code>-object in use.
|
|
*
|
|
* @return The <code>CargoPanel</code>.
|
|
*/
|
|
public final CargoPanel getCargoPanel() {
|
|
return cargoPanel;
|
|
}
|
|
|
|
/**
|
|
* Returns a pointer to the <code>WarehousePanel</code>-object in use.
|
|
*
|
|
* @return The <code>WarehousePanel</code>.
|
|
*/
|
|
public final WarehousePanel getWarehousePanel() {
|
|
return warehousePanel;
|
|
}
|
|
|
|
/**
|
|
* Returns a pointer to the <code>TilePanel</code>-object in use.
|
|
*
|
|
* @return The <code>TilePanel</code>.
|
|
*/
|
|
public final TilePanel getTilePanel() {
|
|
return tilePanel;
|
|
}
|
|
|
|
/**
|
|
* Returns a pointer to the <code>Colony</code>-pointer in use.
|
|
*
|
|
* @return The <code>Colony</code>.
|
|
*/
|
|
public synchronized final Colony getColony() {
|
|
return colony;
|
|
}
|
|
|
|
/**
|
|
* Set the current colony.
|
|
*
|
|
* @param colony The new colony value.
|
|
*/
|
|
private synchronized void setColony(Colony colony) {
|
|
if (this.colony != null){
|
|
this.colony.removePropertyChangeListener(this);
|
|
}
|
|
this.colony = colony;
|
|
if (this.colony != null){
|
|
this.colony.addPropertyChangeListener(this);
|
|
}
|
|
editable = (colony.getOwner() == getMyPlayer());
|
|
}
|
|
|
|
/**
|
|
* This panel shows the content of a carrier in the colony
|
|
*/
|
|
public final class ColonyCargoPanel extends CargoPanel {
|
|
|
|
public ColonyCargoPanel(Canvas canvas) {
|
|
super(canvas, true);
|
|
}
|
|
|
|
@Override
|
|
public String getUIClassID() {
|
|
return "CargoPanelUI";
|
|
}
|
|
}
|
|
|
|
/**
|
|
* This panel is a list of the colony's buildings.
|
|
*/
|
|
public final class BuildingsPanel extends JPanel {
|
|
|
|
private final ColonyPanel colonyPanel;
|
|
|
|
|
|
/**
|
|
* Creates this BuildingsPanel.
|
|
*
|
|
* @param colonyPanel The panel that holds this BuildingsPanel.
|
|
*/
|
|
public BuildingsPanel(ColonyPanel colonyPanel) {
|
|
setLayout(new MigLayout("wrap 4, gap 0"));
|
|
this.colonyPanel = colonyPanel;
|
|
}
|
|
|
|
@Override
|
|
public String getUIClassID() {
|
|
return "BuildingsPanelUI";
|
|
}
|
|
|
|
/**
|
|
* Initializes the <code>BuildingsPanel</code> by loading/displaying
|
|
* the buildings of the colony.
|
|
*/
|
|
public void initialize() {
|
|
removeAll();
|
|
|
|
MouseAdapter mouseAdapter = new MouseAdapter() {
|
|
public void mousePressed(MouseEvent e) {
|
|
getCanvas().showSubPanel(new BuildQueuePanel(colony, getCanvas()));
|
|
}
|
|
};
|
|
ASingleBuildingPanel aSingleBuildingPanel;
|
|
|
|
List<Building> buildings = getColony().getBuildings();
|
|
sortBuildings(buildings);
|
|
for (Building building : buildings) {
|
|
aSingleBuildingPanel = new ASingleBuildingPanel(building);
|
|
if (colonyPanel.isEditable()) {
|
|
aSingleBuildingPanel.addMouseListener(releaseListener);
|
|
aSingleBuildingPanel.setTransferHandler(defaultTransferHandler);
|
|
}
|
|
aSingleBuildingPanel.setOpaque(false);
|
|
aSingleBuildingPanel.addMouseListener(mouseAdapter);
|
|
add(aSingleBuildingPanel);
|
|
}
|
|
}
|
|
|
|
public void update(){
|
|
initialize();
|
|
}
|
|
|
|
public void removePropertyChangeListeners() {
|
|
for (Component component : getComponents()) {
|
|
if (component instanceof ASingleBuildingPanel) {
|
|
((ASingleBuildingPanel) component).removePropertyChangeListeners();
|
|
} else if (component instanceof BuildingSitePanel) {
|
|
((BuildingSitePanel) component).removePropertyChangeListeners();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* This panel is a single line (one building) in the
|
|
* <code>BuildingsPanel</code>.
|
|
*/
|
|
public final class ASingleBuildingPanel extends BuildingPanel implements Autoscroll {
|
|
|
|
/**
|
|
* Creates this ASingleBuildingPanel.
|
|
*
|
|
* @param building The building to display information from.
|
|
*/
|
|
public ASingleBuildingPanel(Building building) {
|
|
super(building, getCanvas());
|
|
}
|
|
|
|
public void initialize() {
|
|
super.initialize();
|
|
if (colonyPanel.isEditable()) {
|
|
for (UnitLabel unitLabel : getUnitLabels()) {
|
|
unitLabel.setTransferHandler(defaultTransferHandler);
|
|
unitLabel.addMouseListener(pressListener);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void autoscroll(Point p) {
|
|
JViewport vp = (JViewport) colonyPanel.buildingsPanel.getParent();
|
|
if (getLocation().y + p.y - vp.getViewPosition().y < SCROLL_AREA_HEIGHT) {
|
|
vp.setViewPosition(new Point(vp.getViewPosition().x,
|
|
Math.max(vp.getViewPosition().y - SCROLL_SPEED, 0)));
|
|
} else if (getLocation().y + p.y - vp.getViewPosition().y >= vp.getHeight() - SCROLL_AREA_HEIGHT) {
|
|
vp.setViewPosition(new Point(vp.getViewPosition().x,
|
|
Math.min(vp.getViewPosition().y + SCROLL_SPEED,
|
|
colonyPanel.buildingsPanel.getHeight()
|
|
- vp.getHeight())));
|
|
}
|
|
}
|
|
|
|
public Insets getAutoscrollInsets() {
|
|
Rectangle r = getBounds();
|
|
return new Insets(r.x, r.y, r.width, r.height);
|
|
}
|
|
|
|
|
|
/**
|
|
* Adds a component to this ASingleBuildingPanel and makes sure that
|
|
* the unit that the component represents gets modified so that it
|
|
* will be located in the colony.
|
|
*
|
|
* @param comp The component to add to this ColonistsPanel.
|
|
* @param editState Must be set to 'true' if the state of the
|
|
* component that is added (which should be a dropped
|
|
* component representing a Unit) should be changed so
|
|
* that the underlying unit will be located in the
|
|
* colony.
|
|
* @return The component argument.
|
|
*/
|
|
public Component add(Component comp, boolean editState) {
|
|
Container oldParent = comp.getParent();
|
|
|
|
if (editState) {
|
|
if (comp instanceof UnitLabel) {
|
|
Unit unit = ((UnitLabel) comp).getUnit();
|
|
|
|
if (getBuilding().canAdd(unit)) {
|
|
oldParent.remove(comp);
|
|
getController().work(unit, getBuilding());
|
|
} else {
|
|
return null;
|
|
}
|
|
} else {
|
|
logger.warning("An invalid component got dropped on this BuildingsPanel.");
|
|
return null;
|
|
}
|
|
}
|
|
initialize();
|
|
return null;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
/**
|
|
* A panel that holds UnitLabels that represent Units that are standing in
|
|
* front of a colony.
|
|
*/
|
|
public final class OutsideColonyPanel extends JPanel implements PropertyChangeListener {
|
|
|
|
private Colony colony;
|
|
|
|
public OutsideColonyPanel() {
|
|
super();
|
|
setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(),
|
|
Messages.message("outsideColony")));
|
|
}
|
|
|
|
public void setColony(Colony newColony) {
|
|
if (colony != null) {
|
|
colony.getTile().removePropertyChangeListener(Tile.UNIT_CHANGE, this);
|
|
}
|
|
this.colony = newColony;
|
|
if (colony != null) {
|
|
colony.getTile().addPropertyChangeListener(Tile.UNIT_CHANGE, this);
|
|
}
|
|
initialize();
|
|
}
|
|
|
|
public void initialize() {
|
|
|
|
removeAll();
|
|
if (colony == null) {
|
|
return;
|
|
}
|
|
|
|
Tile colonyTile = colony.getTile();
|
|
for (Unit unit : colonyTile.getUnitList()) {
|
|
// we only deal with land, non-carrier units here
|
|
if(unit.isNaval() || unit.isCarrier()){
|
|
continue;
|
|
}
|
|
|
|
UnitLabel unitLabel = new UnitLabel(unit, getCanvas());
|
|
if (isEditable()) {
|
|
unitLabel.setTransferHandler(defaultTransferHandler);
|
|
unitLabel.addMouseListener(pressListener);
|
|
}
|
|
add(unitLabel, false);
|
|
}
|
|
revalidate();
|
|
repaint();
|
|
}
|
|
|
|
public Colony getColony() {
|
|
return colony;
|
|
}
|
|
|
|
@Override
|
|
public String getUIClassID() {
|
|
return "OutsideColonyPanelUI";
|
|
}
|
|
|
|
/**
|
|
* Adds a component to this OutsideColonyPanel and makes sure that the
|
|
* unit that the component represents gets modified so that it will be
|
|
* located in the colony.
|
|
*
|
|
* @param comp The component to add to this ColonistsPanel.
|
|
* @param editState Must be set to 'true' if the state of the component
|
|
* that is added (which should be a dropped component
|
|
* representing a Unit) should be changed so that the
|
|
* underlying unit will be located in the colony.
|
|
* @return The component argument.
|
|
*/
|
|
public Component add(Component comp, boolean editState) {
|
|
Container oldParent = comp.getParent();
|
|
if (editState) {
|
|
if (comp instanceof UnitLabel) {
|
|
UnitLabel unitLabel = ((UnitLabel) comp);
|
|
Unit unit = unitLabel.getUnit();
|
|
|
|
if (!unit.isOnCarrier()) {
|
|
getController().putOutsideColony(unit);
|
|
}
|
|
|
|
if (unit.getColony() == null) {
|
|
closeColonyPanel();
|
|
return null;
|
|
} else if (!(unit.getLocation() instanceof Tile) && !unit.isOnCarrier()) {
|
|
return null;
|
|
}
|
|
|
|
oldParent.remove(comp);
|
|
initialize();
|
|
return comp;
|
|
} else {
|
|
logger.warning("An invalid component got dropped on this ColonistsPanel.");
|
|
return null;
|
|
}
|
|
} else {
|
|
((UnitLabel) comp).setSmall(false);
|
|
Component c = add(comp);
|
|
return c;
|
|
}
|
|
}
|
|
|
|
public void propertyChange(PropertyChangeEvent event) {
|
|
initialize();
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* A panel that holds UnitsLabels that represent naval Units that are
|
|
* waiting in the port of the colony.
|
|
*/
|
|
public final class InPortPanel extends JPanel {
|
|
|
|
public InPortPanel() {
|
|
super();
|
|
setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(),
|
|
Messages.message("inPort")));
|
|
}
|
|
|
|
@Override
|
|
public String getUIClassID() {
|
|
return "InPortPanelUI";
|
|
}
|
|
|
|
public void initialize(Unit selectedUnit) {
|
|
// This is required
|
|
UnitLabel oldSelectedUnitLabel = ColonyPanel.this.getSelectedUnitLabel();
|
|
if(oldSelectedUnitLabel != null){
|
|
if(selectedUnit == null){
|
|
selectedUnit = oldSelectedUnitLabel.getUnit();
|
|
}
|
|
ColonyPanel.this.setSelectedUnit(null);
|
|
}
|
|
|
|
removeAll();
|
|
if (colony == null) {
|
|
return;
|
|
}
|
|
|
|
Tile colonyTile = colony.getTile();
|
|
Unit lastCarrier = null;
|
|
for (Unit unit : colonyTile.getUnitList()) {
|
|
if(!unit.isCarrier()){
|
|
continue;
|
|
}
|
|
|
|
lastCarrier = unit;
|
|
UnitLabel unitLabel = new UnitLabel(unit, getCanvas());
|
|
TradeRoute tradeRoute = unit.getTradeRoute();
|
|
if (tradeRoute != null) {
|
|
unitLabel.setDescriptionLabel(Messages.message(Messages.getLabel(unit))
|
|
+ " (" + tradeRoute.getName() + ")");
|
|
}
|
|
if (isEditable()) {
|
|
unitLabel.setTransferHandler(defaultTransferHandler);
|
|
unitLabel.addMouseListener(pressListener);
|
|
}
|
|
add(unitLabel, false);
|
|
}
|
|
revalidate();
|
|
repaint();
|
|
|
|
// last carrier is selected by default, if no other should be
|
|
if(selectedUnit == null && lastCarrier != null){
|
|
selectedUnit = lastCarrier;
|
|
}
|
|
// select the unit
|
|
if(selectedUnit != null){
|
|
ColonyPanel.this.setSelectedUnit(selectedUnit);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* A panel that holds goods that represent cargo that is inside the Colony.
|
|
*/
|
|
public final class WarehousePanel extends JPanel implements PropertyChangeListener {
|
|
|
|
private final ColonyPanel colonyPanel;
|
|
|
|
/**
|
|
* Creates this WarehousePanel.
|
|
*
|
|
* @param colonyPanel The panel that holds this WarehousePanel.
|
|
*/
|
|
public WarehousePanel(ColonyPanel colonyPanel) {
|
|
this.colonyPanel = colonyPanel;
|
|
}
|
|
|
|
public void initialize() {
|
|
// get notified of warehouse changes
|
|
colony.getGoodsContainer().addPropertyChangeListener(this);
|
|
update();
|
|
revalidate();
|
|
repaint();
|
|
}
|
|
|
|
private void update() {
|
|
removeAll();
|
|
for (GoodsType goodsType : getSpecification().getGoodsTypeList()) {
|
|
if (goodsType.isStorable()) {
|
|
Goods goods = colony.getGoodsContainer().getGoods(goodsType);
|
|
if (goods.getAmount() >= getClient().getClientOptions()
|
|
.getInteger(ClientOptions.MIN_NUMBER_FOR_DISPLAYING_GOODS)) {
|
|
GoodsLabel goodsLabel = new GoodsLabel(goods, getCanvas());
|
|
if (colonyPanel.isEditable()) {
|
|
goodsLabel.setTransferHandler(defaultTransferHandler);
|
|
goodsLabel.addMouseListener(pressListener);
|
|
}
|
|
add(goodsLabel, false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public String getUIClassID() {
|
|
return "WarehousePanelUI";
|
|
}
|
|
|
|
|
|
/**
|
|
* Adds a component to this WarehousePanel and makes sure that the unit or
|
|
* good that the component represents gets modified so that it is on
|
|
* board the currently selected ship.
|
|
*
|
|
* @param comp The component to add to this WarehousePanel.
|
|
* @param editState Must be set to 'true' if the state of the component
|
|
* that is added (which should be a dropped component
|
|
* representing a Unit or good) should be changed so that the
|
|
* underlying unit or goods are on board the currently
|
|
* selected ship.
|
|
* @return The component argument.
|
|
*/
|
|
public Component add(Component comp, boolean editState) {
|
|
if (editState) {
|
|
if (comp instanceof GoodsLabel) {
|
|
comp.getParent().remove(comp);
|
|
((GoodsLabel) comp).setSmall(false);
|
|
return comp;
|
|
}
|
|
logger.warning("An invalid component got dropped on this WarehousePanel.");
|
|
return null;
|
|
}
|
|
|
|
Component c = add(comp);
|
|
|
|
return c;
|
|
}
|
|
|
|
public void propertyChange(PropertyChangeEvent event) {
|
|
update();
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
* A panel that displays the tiles in the immediate area around the colony.
|
|
*/
|
|
public final class TilePanel extends FreeColPanel {
|
|
|
|
private final ColonyPanel colonyPanel;
|
|
|
|
/**
|
|
* Creates this TilePanel.
|
|
*
|
|
* @param colonyPanel The panel that holds this TilePanel.
|
|
*/
|
|
public TilePanel(ColonyPanel colonyPanel) {
|
|
super(colonyPanel.getCanvas());
|
|
this.colonyPanel = colonyPanel;
|
|
setBackground(Color.BLACK);
|
|
setBorder(null);
|
|
setLayout(null);
|
|
}
|
|
|
|
public void initialize() {
|
|
int layer = 2;
|
|
|
|
for (int x = 0; x < 3; x++) {
|
|
for (int y = 0; y < 3; y++) {
|
|
ColonyTile tile = getColony().getColonyTile(x, y);
|
|
if (tile==null)
|
|
continue;
|
|
ASingleTilePanel p = new ASingleTilePanel(tile, x, y);
|
|
add(p, new Integer(layer));
|
|
layer++;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
public void removePropertyChangeListeners() {
|
|
for (Component component : getComponents()) {
|
|
if (component instanceof ASingleTilePanel) {
|
|
((ASingleTilePanel) component).removePropertyChangeListeners();
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void paintComponent(Graphics g) {
|
|
GUI colonyTileGUI = getCanvas().getColonyTileGUI();
|
|
Game game = colony.getGame();
|
|
|
|
g.setColor(Color.black);
|
|
g.fillRect(0, 0, getWidth(), getHeight());
|
|
|
|
if (getColony() != null) {
|
|
for (int x = 0; x < 3; x++) {
|
|
for (int y = 0; y < 3; y++) {
|
|
TileType tileType = getColony().getTile().getType();
|
|
Tile tile = getColony().getTile(x, y);
|
|
if (tile != null) {
|
|
int xx = ((2 - x) + y) * getLibrary().getTerrainImageWidth(tileType) / 2;
|
|
int yy = (x + y) * getLibrary().getTerrainImageHeight(tileType) / 2;
|
|
g.translate(xx, yy);
|
|
colonyTileGUI.displayColonyTile((Graphics2D) g, game.getMap(), tile, getColony());
|
|
g.translate(-xx, -yy);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Panel for visualizing a <code>ColonyTile</code>. The component
|
|
* itself is not visible, however the content of the component is (i.e.
|
|
* the people working and the production)
|
|
*/
|
|
public final class ASingleTilePanel extends JPanel implements PropertyChangeListener {
|
|
|
|
private ColonyTile colonyTile;
|
|
|
|
public ASingleTilePanel(ColonyTile colonyTile, int x, int y) {
|
|
setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
|
|
this.colonyTile = colonyTile;
|
|
|
|
colonyTile.addPropertyChangeListener(this);
|
|
|
|
setOpaque(false);
|
|
TileType tileType = colonyTile.getTile().getType();
|
|
// Size and position:
|
|
setSize(getLibrary().getTerrainImageWidth(tileType), getLibrary().getTerrainImageHeight(tileType));
|
|
setLocation(((2 - x) + y) * getLibrary().getTerrainImageWidth(tileType) / 2,
|
|
(x + y) * getLibrary().getTerrainImage(tileType, 0, 0).getHeight(null) / 2);
|
|
initialize();
|
|
}
|
|
|
|
private void initialize() {
|
|
|
|
removeAll();
|
|
UnitLabel unitLabel = null;
|
|
if (colonyTile.getUnit() != null) {
|
|
Unit unit = colonyTile.getUnit();
|
|
unitLabel = new UnitLabel(unit, getCanvas());
|
|
if (colonyPanel.isEditable()) {
|
|
unitLabel.setTransferHandler(defaultTransferHandler);
|
|
unitLabel.addMouseListener(pressListener);
|
|
}
|
|
super.add(unitLabel);
|
|
|
|
}
|
|
updateDescriptionLabel(unitLabel, true);
|
|
|
|
if (colonyTile.isColonyCenterTile()) {
|
|
initializeAsCenterTile();
|
|
}
|
|
|
|
if (colonyPanel.isEditable()) {
|
|
setTransferHandler(defaultTransferHandler);
|
|
addMouseListener(releaseListener);
|
|
}
|
|
|
|
revalidate();
|
|
repaint();
|
|
}
|
|
|
|
/**
|
|
* Initialized the center of the colony panel tile. The one
|
|
* containing the city.
|
|
*
|
|
*/
|
|
private void initializeAsCenterTile() {
|
|
|
|
setLayout(new GridLayout(2, 1));
|
|
|
|
TileType tileType = colonyTile.getTile().getType();
|
|
|
|
AbstractGoods primaryGoods = tileType.getPrimaryGoods();
|
|
if (primaryGoods != null) {
|
|
GoodsType goodsType = primaryGoods.getType();
|
|
ImageIcon goodsIcon = getLibrary().getGoodsImageIcon(goodsType);
|
|
ProductionLabel pl =
|
|
new ProductionLabel(goodsType, colonyTile.getProductionOf(goodsType),
|
|
getCanvas());
|
|
pl.setSize(getLibrary().getTerrainImageWidth(tileType), goodsIcon.getIconHeight());
|
|
add(pl);
|
|
}
|
|
|
|
AbstractGoods secondaryGoods = tileType.getSecondaryGoods();
|
|
if (secondaryGoods != null) {
|
|
GoodsType goodsType = secondaryGoods.getType();
|
|
ImageIcon goodsIcon = getLibrary().getGoodsImageIcon(goodsType);
|
|
ProductionLabel pl =
|
|
new ProductionLabel(goodsType, colonyTile.getProductionOf(goodsType),
|
|
getCanvas());
|
|
pl.setSize(getLibrary().getTerrainImageWidth(tileType), goodsIcon.getIconHeight());
|
|
add(pl);
|
|
}
|
|
}
|
|
|
|
public void removePropertyChangeListeners() {
|
|
colonyTile.removePropertyChangeListener(this);
|
|
}
|
|
|
|
/**
|
|
* Updates the description label The description label is a tooltip
|
|
* with the terrain type, road and plow indicator if any
|
|
*
|
|
* If a unit is on it update the tooltip of it instead
|
|
*/
|
|
private void updateDescriptionLabel(UnitLabel unit, boolean toAdd) {
|
|
String tileDescription = Messages.message(this.colonyTile.getLabel());
|
|
|
|
if (unit == null) {
|
|
setToolTipText(tileDescription);
|
|
} else {
|
|
String unitDescription = Messages.message(Messages.getLabel(unit.getUnit()));
|
|
if (toAdd) {
|
|
unitDescription = tileDescription + " [" + unitDescription + "]";
|
|
}
|
|
unit.setDescriptionLabel(unitDescription);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Adds a component to this CargoPanel and makes sure that the unit
|
|
* or good that the component represents gets modified so that it is
|
|
* on board the currently selected ship.
|
|
*
|
|
* @param comp The component to add to this CargoPanel.
|
|
* @param editState Must be set to 'true' if the state of the
|
|
* component that is added (which should be a dropped
|
|
* component representing a Unit or good) should be
|
|
* changed so that the underlying unit or goods are on
|
|
* board the currently selected ship.
|
|
* @return The component argument.
|
|
*/
|
|
public Component add(Component comp, boolean editState) {
|
|
Container oldParent = comp.getParent();
|
|
if (editState) {
|
|
if (comp instanceof UnitLabel) {
|
|
Unit unit = ((UnitLabel) comp).getUnit();
|
|
Tile tile = colonyTile.getWorkTile();
|
|
Player player = unit.getOwner();
|
|
|
|
logger.info("Colony " + colony.getName()
|
|
+ " claims tile " + tile.toString()
|
|
+ " with unit " + unit.getId());
|
|
if ((tile.getOwner() != player
|
|
|| tile.getOwningSettlement() != colony)
|
|
&& !getController().claimLand(tile, colony, 0)) {
|
|
logger.warning("Colony " + colony.getName()
|
|
+ " could not claim tile " + tile.toString()
|
|
+ " with unit " + unit.getId());
|
|
return null;
|
|
}
|
|
|
|
if (colonyTile.canAdd(unit)) {
|
|
oldParent.remove(comp);
|
|
|
|
GoodsType workType = colonyTile.getWorkType(unit);
|
|
|
|
getController().work(unit, colonyTile);
|
|
// check whether worktype is suitable
|
|
if (workType != unit.getWorkType()) {
|
|
getController().changeWorkType(unit, workType);
|
|
}
|
|
|
|
((UnitLabel) comp).setSmall(false);
|
|
|
|
if (getClient().getClientOptions().getBoolean(ClientOptions.SHOW_NOT_BEST_TILE)) {
|
|
ColonyTile bestTile = colony.getVacantColonyTileFor(unit, false, workType);
|
|
if (colonyTile != bestTile
|
|
&& (colonyTile.getProductionOf(unit, workType)
|
|
< bestTile.getProductionOf(unit, workType))) {
|
|
StringTemplate template = StringTemplate.template("colonyPanel.notBestTile")
|
|
.addStringTemplate("%unit%", Messages.getLabel(unit))
|
|
.add("%goods%", workType.getNameKey())
|
|
.addStringTemplate("%tile%", bestTile.getLabel());
|
|
getCanvas().showInformationMessage(template);
|
|
}
|
|
}
|
|
} else {
|
|
// could not add the unit on the tile
|
|
Canvas canvas = getCanvas();
|
|
Tile workTile = colonyTile.getWorkTile();
|
|
Settlement s = workTile.getOwningSettlement();
|
|
|
|
if (s != null && s != getColony()) {
|
|
if (s.getOwner() == player) {
|
|
// Its one of ours
|
|
canvas.errorMessage("tileTakenSelf");
|
|
} else if (s.getOwner().isEuropean()) {
|
|
// occupied by a foreign european colony
|
|
canvas.errorMessage("tileTakenEuro");
|
|
} else if (s instanceof IndianSettlement) {
|
|
// occupied by an indian settlement
|
|
canvas.errorMessage("tileTakenInd");
|
|
}
|
|
} else {
|
|
if(colonyTile.getUnitCount() > 0) { // Tile is already occupied
|
|
;
|
|
} else if (!workTile.isLand()) { // no docks
|
|
canvas.errorMessage("tileNeedsDocks");
|
|
} else if (workTile.hasLostCityRumour()) {
|
|
canvas.errorMessage("tileHasRumour");
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
} else {
|
|
logger.warning("An invalid component got dropped on this CargoPanel.");
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* At this point, the panel has already been updated
|
|
* via the property change listener.
|
|
*
|
|
removeAll();
|
|
Component c = super.add(comp);
|
|
refresh();
|
|
*/
|
|
return comp;
|
|
}
|
|
|
|
public void propertyChange(PropertyChangeEvent event) {
|
|
initialize();
|
|
}
|
|
|
|
/**
|
|
* Checks if this <code>JComponent</code> contains the given
|
|
* coordinate.
|
|
*/
|
|
@Override
|
|
public boolean contains(int px, int py) {
|
|
int w = getWidth();
|
|
int h = getHeight();
|
|
int dx = Math.abs(w/2 - px);
|
|
int dy = Math.abs(h/2 - py);
|
|
return (dx + w * dy / h) <= w/2;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void propertyChange(PropertyChangeEvent e) {
|
|
if (!isShowing() || getColony() == null) {
|
|
return;
|
|
}
|
|
String property = e.getPropertyName();
|
|
|
|
if (Unit.CARGO_CHANGE.equals(property)) {
|
|
updateInPortPanel();
|
|
} else if (ColonyChangeEvent.POPULATION_CHANGE.toString().equals(property)) {
|
|
updateSoLLabel();
|
|
} else if (ColonyChangeEvent.BONUS_CHANGE.toString().equals(property)) {
|
|
ModelMessage msg = getColony().checkForGovMgtChangeMessage();
|
|
if (msg != null) {
|
|
getCanvas().showInformationMessage(msg);
|
|
}
|
|
updateSoLLabel();
|
|
} else if (ColonyTile.UNIT_CHANGE.toString().equals(property)) {
|
|
updateTilePanel();
|
|
updateProductionPanel();
|
|
} else if (property.startsWith("model.goods.")) {
|
|
// changes to warehouse goods count may affect building production
|
|
//which requires a view update
|
|
updateProductionPanel();
|
|
updateWarehousePanel();
|
|
buildingsPanel.update();
|
|
} else if (Building.UNIT_CHANGE.equals(property)) {
|
|
// already processed by BuildingPanel
|
|
} else {
|
|
logger.warning("Unknown property change event: " + e.getPropertyName());
|
|
}
|
|
}
|
|
|
|
}
|