/**
* 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.LinkedHashSet;
import java.util.Set;
import org.freecolandroid.repackaged.java.awt.Color;
import org.freecolandroid.repackaged.java.awt.Insets;
import org.freecolandroid.repackaged.java.awt.event.ActionEvent;
import org.freecolandroid.repackaged.java.awt.event.ActionListener;
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 org.freecolandroid.repackaged.javax.swing.SwingConstants;
import org.freecolandroid.repackaged.javax.swing.border.Border;
import org.freecolandroid.repackaged.javax.swing.border.EmptyBorder;
import net.miginfocom.swing.MigLayout;
import net.sf.freecol.client.FreeColClient;
import net.sf.freecol.client.gui.GUI;
import net.sf.freecol.client.gui.i18n.Messages;
import net.sf.freecol.common.model.Ability;
import net.sf.freecol.common.model.Building;
import net.sf.freecol.common.model.Colony;
import net.sf.freecol.common.model.GoodsType;
import net.sf.freecol.common.model.StringTemplate;
import net.sf.freecol.common.model.Unit;
import net.sf.freecol.common.model.UnitType;
/**
* This panel displays the Labour Report.
*/
public final class CompactLabourReport extends ReportPanel {
private int COLONY_COLUMN = 0;
private int UNIT_TYPE_COLUMN = 1;
private int WORKING_COLUMN = 2;
private int BUILDING_COLUMN = 3;
private int COLONIST_COLUMN = 4;
private int COLONIST_SUMMARY_COLUMN = 5;
private int PRODUCTION_SYMBOL_COLUMN = 6;
private int PRODUCTION_COLUMN = 7;
private int PRODUCTION_SUMMARY_COLUMN = 8;
private int NETPRODUCTION_SUMMARY_COLUMN = 9;
private static final int COLUMNS = 10;
private LabourData labourData;
private LabourData.UnitData unitData;
private boolean showProduction;
private boolean showNetProduction;
private boolean showProductionSymbols;
private boolean showBuildings;
private final JPanel headerRow = new JPanel() {
@Override
public String getUIClassID() {
return "ReportPanelUI";
}
};
/**
* The constructor that will add the items to this panel.
* @param freeColClient
*
* @param parent The parent of this panel.
*/
public CompactLabourReport(FreeColClient freeColClient, GUI gui) {
this(freeColClient, gui, null);
labourData = new LabourData(getFreeColClient());
initialize();
}
/**
* The constructor that will add the items to this panel.
* @param freeColClient
*
* @param parent The parent of this panel.
*/
public CompactLabourReport(FreeColClient freeColClient, GUI gui, LabourData.UnitData data) {
super(freeColClient, gui, data == null ? Messages.message("reportLabourAction.name")
: Messages.message("report.labour.details"));
this.unitData = data;
headerRow.setBorder(new EmptyBorder(20, 20, 0, 20));
headerRow.setOpaque(true);
scrollPane.setColumnHeaderView(headerRow);
}
public JButton createColonyButton(final Colony colony) {
String text = colony.getName();
if (!unitData.isSummary()) {
// int unitIndex = unitData.getUnitType().getIndex();
//
// int skillLevel = Unit.getSkillLevel(unitIndex);
// if (skillLevel <= 0 && skillLevel > -2) {
// //settlers and servants can be trained anywwhere a farmer can
// unitIndex = Unit.EXPERT_FARMER;
// }
if (colony.canTrain(unitData.getUnitType())) {
text = text + "*";
}
}
return createButton(text, new ActionListener() {
public void actionPerformed(ActionEvent e) {
getGUI().showColonyPanel(colony);
}
});
}
@Override
public void initialize() {
if (isOverview()) {
showProduction = true;
showNetProduction = true;
showProductionSymbols = true;
showBuildings = false;
} else {
showProduction = unitData.showProduction();
showNetProduction = unitData.showNetProduction();
showProductionSymbols = false;
GoodsType expertProduction = getGoodsType();
showBuildings = (expertProduction != null && !expertProduction.isFarmed()) || unitData.getTotal().isTraining();
}
String layoutConstraints = "fill, insets 0, gap 0 0";
StringBuilder widths = new StringBuilder();
widths.append("[175, fill]");
widths.append(isOverview() || !unitData.isSummary() ? "[150, fill]" : "[0!]");
widths.append("[150, fill]");
widths.append(showBuildings ? "[130, fill]" : "[0!]");
widths.append("[26, fill][33, fill]");
widths.append(showProductionSymbols ? "[50, fill]" : "[0!]");
widths.append(showProduction ? "[30, fill][40, fill]" : "[0!][0!]");
widths.append(showNetProduction ? "[40, fill]" : "[0!]");
String columnConstraints = widths.toString();
String rowConstraints = "[fill]";
headerRow.setLayout(new MigLayout(layoutConstraints, columnConstraints, rowConstraints));
reportPanel.setLayout(new MigLayout(layoutConstraints, columnConstraints, rowConstraints));
addHeader();
if (isOverview()) {
addUnitTypes();
} else {
addLocations();
}
}
@Override
protected Border createBorder() {
return new EmptyBorder(0, 20, 20, 20);
}
/**
* adds the header rows
*/
private void addHeader() {
int row = 1;
JLabel empty = new JLabel("");
empty.setBorder(TOPLEFTCELLBORDER);
headerRow.add(empty, "cell " + COLONY_COLUMN + " 1");
if (isOverview() || !unitData.isSummary()) {
JLabel unitType = new JLabel(Messages.message("model.unit.type"));
unitType.setBorder(TOPCELLBORDER);
headerRow.add(unitType, "cell " + UNIT_TYPE_COLUMN + " 1");
}
JLabel workingAs = new JLabel(Messages.message("model.unit.workingAs"));
workingAs.setBorder(TOPCELLBORDER);
headerRow.add(workingAs, "cell " + WORKING_COLUMN + " 1");
if (showBuildings) {
JLabel building = new JLabel(Messages.message("building"));
building.setBorder(TOPCELLBORDER);
headerRow.add(building, "cell " + BUILDING_COLUMN + " 1");
}
JLabel colonists = new JLabel(Messages.message("colonists"));
colonists.setBorder(TOPCELLBORDER);
headerRow.add(colonists, "cell " + COLONIST_COLUMN + " 1 2 1");
if (isOverview()) {
JLabel production = new JLabel(Messages.message("report.production"));
production.setBorder(TOPCELLBORDER);
headerRow.add(production, "cell " + PRODUCTION_SYMBOL_COLUMN + " 1 " + (COLUMNS - PRODUCTION_SYMBOL_COLUMN) + " 1");
} else if (showProduction) {
LabourData.UnitData unit = unitData;
GoodsType goods = unit.getExpertProduction();
JLabel production = new JLabel(getLibrary().getGoodsImageIcon(goods));
production.setBorder(TOPCELLBORDER);
headerRow.add(production, "cell " + PRODUCTION_SYMBOL_COLUMN + " 1 " + (COLUMNS - PRODUCTION_SYMBOL_COLUMN + (showNetProduction && goods.isStoredAs() ? 1 : 0)) + " 1");
if (showNetProduction && goods.isStoredAs()) {
JLabel netProduction = new JLabel(getLibrary().getGoodsImageIcon(goods.getStoredAs()));
netProduction.setBorder(TOPCELLBORDER);
headerRow.add(netProduction, "cell " + NETPRODUCTION_SUMMARY_COLUMN + " 1");
}
}
if (!isSummary()) {
ImageIcon icon = getUnitIcon(unitData.getUnitType());
header.setIcon(icon);
header.setIconTextGap(20);
}
}
/**
* add unit data for a given location
*
* @param data
* @param row starting row
* @return next row to use
*/
private int addLocationData(LabourData.LocationData data, Colony colony, int row) {
boolean allColonists = data.getUnitData().isSummary();
LabourData.UnitData unit = data.getUnitData();
UnitType unitType = unit.getUnitType();
String unitName = unit.getUnitName();
String workingAs = null;
Building productionBuilding = null;
if (!allColonists) {
workingAs = Messages.message(unitType.getWorkingAsKey());
if (colony != null) {
GoodsType expert = unitType.getExpertProduction();
if (expert != null) {
productionBuilding = colony.getBuildingForProducing(expert);
}
}
}
addLocationSummary(data, row);
int buildingStartRow = row;
//details
int otherAmateurs = data.getOtherWorkingAmateurs().getColonists();
if (!allColonists && otherAmateurs > 0) {
addRow(data,
Messages.message("report.labour.otherUnitType"),
workingAs,
createNonCountedLabel(otherAmateurs),
data.getOtherWorkingAmateurs().getProduction(),
row);
row++;
}
row = addRow(data,
unitName,
allColonists ? Messages.message("report.labour.expertsWorking") : workingAs,
data.getWorkingProfessionals().getColonists(),
data.getWorkingProfessionals().getProduction(),
row);
int notProducingStartRow = row;
if (showBuildings) {
if (productionBuilding != null && row > buildingStartRow) {
JLabel buildingLabel = localizedLabel(productionBuilding.getNameKey());
buildingLabel.setBorder(CELLBORDER);
reportPanel.add(buildingLabel, "cell " + BUILDING_COLUMN + " " + buildingStartRow + " 1 " + (row - buildingStartRow));
buildingStartRow = row;
} else {
reportPanel.add(createEmptyLabel(), "cell " + BUILDING_COLUMN + " " + buildingStartRow + " 1 " + (row - buildingStartRow));
}
}
row = addRow(data,
unitName,
Messages.message(allColonists ?
"report.labour.amateursWorking" :
"report.labour.workingAsOther"),
data.getWorkingAmateurs(),
0, row);
if (data.getNotWorking() > 0) {
addRow(data,
unitName,
Messages.message("report.labour.notWorking"),
createNumberLabel(data.getNotWorking(), "report.labour.notWorking.tooltip"),
0, row);
row++;
}
Building schoolhouse = colony != null && data.isTraining() ?
colony.getBuildingWithAbility(Ability.CAN_TEACH) : null;
if (showBuildings && schoolhouse != null && row > buildingStartRow) {
reportPanel.add(createEmptyLabel(), "cell " + BUILDING_COLUMN + " " + buildingStartRow + " 1 " + (row - buildingStartRow));
buildingStartRow = row;
}
row = addRow(data,
unitName,
Messages.message("report.labour.teacher"),
data.getTeachers(),
0, row);
if (!allColonists) {
row = addRow(data,
data.getOtherStudentsName(),
Messages.message(StringTemplate.template("report.labour.learning")
.addName("%unit%", data.getUnitData().getUnitName())),
data.getOtherStudents(),
0, row);
}
int studentCount = data.getStudents();
if (studentCount > 0) {
if (allColonists) {
addRow(data, null, Messages.message("report.labour.sutdent"), createNonCountedLabel(studentCount), 0, row);
} else {
Set<UnitType> resultOfTraining = new LinkedHashSet<UnitType>();
if (colony != null) {
for (Unit teacher : colony.getTeachers()) {
Unit student = teacher.getStudent();
if (student != null && student.getType() == unitType) {
resultOfTraining.add(Unit.getUnitTypeTeaching(teacher.getType(), student.getType()));
}
}
}
String student = resultOfTraining.size() == 1 ?
Messages.message(StringTemplate.template("report.labour.learning")
.addName("%unit%", resultOfTraining.iterator().next())) :
Messages.message("report.labour.learningOther");
addRow(data,
data.getUnitData().getUnitName(),
student,
createNumberLabel(-studentCount, "report.labour.subtracted.tooltip"),
0, row);
}
row++;
}
if (showBuildings && row > buildingStartRow) {
JLabel buildingLabel = new JLabel(schoolhouse != null ?
Messages.message(schoolhouse.getNameKey()) : "");
buildingLabel.setBorder(CELLBORDER);
reportPanel.add(buildingLabel, "cell " + BUILDING_COLUMN + " " + buildingStartRow + " 1 " + (row - buildingStartRow));
}
if (data.getUnitData().showProduction() && row > notProducingStartRow) {
reportPanel.add(createEmptyLabel(), "cell " + PRODUCTION_COLUMN + " " + notProducingStartRow + " 1 " + (row - notProducingStartRow));
}
return row;
}
private void addLocations() {
LabourData.LocationData unitTotal = unitData.getTotal();
int row = 1;
JLabel summaryLabel = new JLabel(Messages.message("report.labour.summary"));
summaryLabel.setBorder(LEFTCELLBORDER);
reportPanel.add(summaryLabel, "cell " + COLONY_COLUMN + " " + row + " 1 " + unitTotal.getRowCount());
row = addLocationData(unitTotal, null, row);
for (Colony colony : getSortedColonies()) {
LabourData.LocationData colonyData = unitData.getDetails().get(colony);
if (colonyData != null) {
reportPanel.add(createColonyButton(colony), "cell " + COLONY_COLUMN + " "
+ row + " 1 " + colonyData.getRowCount());
row = addLocationData(colonyData, colony, row);
}
}
LabourData.LocationData europe = unitData.getUnitsInEurope();
if (europe.getRowCount() > 0) {
JButton button = createButton(Messages.message(getMyPlayer().getEurope().getNameKey()),
new ActionListener() {
public void actionPerformed(ActionEvent e) {
getGUI().showEuropePanel();
}
});
reportPanel.add(button, "cell " + COLONY_COLUMN + " " + row + " 1 " + europe.getRowCount());
row = addLocationData(europe, null, row);
}
row = addNonLinkedLocation(unitData.getUnitsOnLand(), "report.onLand", row);
row = addNonLinkedLocation(unitData.getUnitsAtSea(), "report.atSea", row);
reportPanel.add(new JLabel(Messages.message("report.labour.canTrain")), "cell 1 " + row + " " + COLUMNS + " 1");
}
/*
* distributes {@code value}, amount the number of {@code pocketCount}
*
* @param value
* @param pocketCount
* @return distribution of {@code value}
*/
/*
private int[] distribute(int value, int pocketCount) {
int[] pockets = new int[pocketCount];
int pocketIndex = 0;
for (int i = value; i > 0; i--) {
pockets[pocketIndex]++;
pocketIndex++;
pocketIndex = pocketIndex % pocketCount;
}
return pockets;
}
*/
private void addLocationSummary(LabourData.LocationData data, int row) {
int rows = data.getRowCount();
JLabel colonistsLabel = createNumberLabel(data.getTotalColonists(), null);
if (data.getUnitData().isSummary()) {
if (isOverview()) {
reportPanel.add(createEmptyLabel(), "cell " + UNIT_TYPE_COLUMN + " " + row + " 1 " + rows);
}
} else {
colonistsLabel.setToolTipText(Messages.message(StringTemplate.template("report.labour.unitTotal.tooltip")
.addName("%unit%", data.getUnitData().getUnitName())));
}
reportPanel.add(colonistsLabel, "cell " + COLONIST_SUMMARY_COLUMN + " " + row + " 1 " + data.getRowCount());
if (showProduction && !data.getUnitData().showProduction()) {
reportPanel.add(createEmptyLabel(), "cell " + PRODUCTION_SYMBOL_COLUMN + " " + row + " 4 " + rows);
return;
}
if (showProduction) {
JLabel productionLabel = createNumberLabel(data.getTotalProduction(), "report.labour.potentialProduction.tooltip");
if (!data.isTotal() && data.getTotalProduction() == 0) {
productionLabel.setText("");
}
reportPanel.add(productionLabel, "cell " + PRODUCTION_SUMMARY_COLUMN + " " + row + " 1 " + rows);
}
if (showNetProduction) {
int net = data.getNetProduction();
JLabel netProductionLabel = createNumberLabel(net, "report.labour.netProduction.tooltip");
if (!data.getUnitData().showNetProduction() || (!data.isTotal() && net == 0)) {
netProductionLabel.setText("");
netProductionLabel.setToolTipText("");
} else if (net >= 0) {
netProductionLabel.setText("+" + net);
} else {
netProductionLabel.setForeground(Color.RED);
}
reportPanel.add(netProductionLabel, "cell " + NETPRODUCTION_SUMMARY_COLUMN + " " + row + " 1 " + rows);
}
if (showProductionSymbols) {
JLabel icon = new JLabel();
icon.setBorder(CELLBORDER);
GoodsType goods = data.getUnitData().getExpertProduction();
if (goods != null) {
icon.setIcon(getLibrary().getGoodsImageIcon(goods));
}
reportPanel.add(icon, "cell " + PRODUCTION_SYMBOL_COLUMN + " " + row + " 1 " + rows);
}
}
private int addNonLinkedLocation(LabourData.LocationData data, String messageKey, int row) {
int rows = data.getRowCount();
if (rows > 0) {
JLabel label = new JLabel(Messages.message(messageKey));
label.setBorder(LEFTCELLBORDER);
label.setForeground(Color.GRAY);
reportPanel.add(label, "cell " + COLONY_COLUMN + " " + row + " 1 " + rows);
return addLocationData(data, null, row);
}
return row;
}
private int addRow(LabourData.LocationData data, String typeName, String activity, int colonists, int production, int row) {
if (colonists > 0) {
addRow(data, typeName, activity, createNumberLabel(colonists, null), production, row);
row++;
}
return row;
}
private void addRow(LabourData.LocationData data, String typeName, String activity, JLabel colonistLabel, int production, int row) {
if (!data.getUnitData().isSummary()) {
JLabel typeLabel = new JLabel(typeName);
typeLabel.setBorder(CELLBORDER);
reportPanel.add(typeLabel, "cell " + UNIT_TYPE_COLUMN + " " + row);
}
JLabel activityLabel = new JLabel(activity);
activityLabel.setBorder(CELLBORDER);
reportPanel.add(activityLabel, "cell " + WORKING_COLUMN + " " + row);
reportPanel.add(colonistLabel, "cell " + COLONIST_COLUMN + " " + row);
if (data.getUnitData().showProduction() && production > 0) {
reportPanel.add(createNumberLabel(production, "report.labour.potentialProduction.tooltip"), "cell " + PRODUCTION_COLUMN + " " + row);
}
}
private void addUnitTypes() {
int row = 1;
JButton allColonistsButton = createUnitNameButton(Messages.message("report.labour.allColonists"), labourData.getSummary());
reportPanel.add(allColonistsButton, "cell " + COLONY_COLUMN + " " + row + " 1 " + labourData.getSummary().getUnitSummaryRowCount());
row = addLocationData(labourData.getSummary().getTotal(), null, row);
for (UnitType unitType : LabourData.getLabourTypes(getMyPlayer())) {
LabourData.UnitData unitData = labourData.getUnitData(unitType);
JButton unitButton = createUnitNameButton(unitData.getUnitName(), unitData);
int rows = unitData.getUnitSummaryRowCount();
reportPanel.add(unitButton, "cell " + COLONY_COLUMN + " " + row + " 1 " + rows);
if (unitData.hasDetails()) {
row = addLocationData(unitData.getTotal(), null, row);
} else {
unitButton.setEnabled(false);
unitButton.setDisabledIcon(unitButton.getIcon());
unitButton.setForeground(Color.GRAY);
reportPanel.add(createEmptyLabel(), "cell " + UNIT_TYPE_COLUMN + " " + row + " " + (COLUMNS - 1) + " 1");
row++;
}
}
}
private JButton createButton(String name, ActionListener listener) {
JButton button = new JButton(name);
button.setMargin(new Insets(0, 0, 0, 0));
button.setOpaque(false);
button.setHorizontalAlignment(SwingConstants.LEADING);
button.setForeground(LINK_COLOR);
button.setBorder(LEFTCELLBORDER);
button.addActionListener(listener);
return button;
}
private JLabel createEmptyLabel() {
JLabel empty = new JLabel("");
empty.setBorder(CELLBORDER);
return empty;
}
private JLabel createNonCountedLabel(int otherAmateurs) {
JLabel label = createNumberLabel(otherAmateurs, "report.labour.notCounted.tooltip");
label.setForeground(Color.GRAY);
return label;
}
private JLabel createNumberLabel(int number, String toolTipKey) {
JLabel label = new JLabel(String.valueOf(number));
label.setHorizontalAlignment(SwingConstants.TRAILING);
label.setBorder(CELLBORDER);
if (toolTipKey != null) {
label.setToolTipText(Messages.message(toolTipKey));
}
return label;
}
private JButton createUnitNameButton(String name, final LabourData.UnitData unitData) {
JButton button = createButton(name, new ActionListener() {
public void actionPerformed(ActionEvent e) {
getGUI().showCompactLabourReport(unitData);
}
});
if (!unitData.isSummary()) {
button.setIcon(getUnitIcon(unitData.getUnitType()));
}
return button;
}
private GoodsType getGoodsType() {
return isSummary() ? null : unitData.getUnitType().getExpertProduction();
}
private ImageIcon getUnitIcon(UnitType unit) {
Unit.Role role = Unit.Role.DEFAULT;
if (unit.hasAbility(Ability.EXPERT_PIONEER)) {
role = Unit.Role.PIONEER;
} else if (unit.hasAbility(Ability.EXPERT_MISSIONARY)) {
role = Unit.Role.MISSIONARY;
}
return getLibrary().getUnitImageIcon(unit, role);
}
/**
* @return if this is the location summary, grouped by unit type
*/
private boolean isOverview() {
return unitData == null;
}
/**
* @return if we are any summary
*/
private boolean isSummary() {
return isOverview() || unitData.isSummary();
}
}