/*
* ForceViewPanel
*
* Created on May 2, 2011
*/
package mekhq.gui.view;
import java.awt.Color;
import java.awt.Component;
import java.awt.Image;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.ResourceBundle;
import java.util.UUID;
import java.util.Vector;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import megamek.client.ui.Messages;
import megamek.client.ui.swing.util.PlayerColors;
import megamek.common.Crew;
import megamek.common.Entity;
import megamek.common.UnitType;
import megamek.common.util.EncodeControl;
import mekhq.IconPackage;
import mekhq.campaign.Campaign;
import mekhq.campaign.force.Force;
import mekhq.campaign.personnel.Person;
import mekhq.campaign.unit.Unit;
import mekhq.gui.EntityImage;
/**
* A custom panel that gets filled in with goodies from a Force record
* @author Jay Lawson <jaylawson39 at yahoo.com>
*/
public class ForceViewPanel extends javax.swing.JPanel {
/**
*
*/
private static final long serialVersionUID = 7004741688464105277L;
private Force force;
private Campaign campaign;
private IconPackage icons;
private javax.swing.JLabel lblIcon;
private javax.swing.JPanel pnlStats;
private javax.swing.JPanel pnlSubUnits;
private javax.swing.JTextArea txtDesc;
private javax.swing.JLabel lblType;
private javax.swing.JLabel lblAssign1;
private javax.swing.JLabel lblAssign2;
private javax.swing.JLabel lblCommander1;
private javax.swing.JLabel lblCommander2;
private javax.swing.JLabel lblBV1;
private javax.swing.JLabel lblBV2;
private javax.swing.JLabel lblTonnage1;
private javax.swing.JLabel lblTonnage2;
private javax.swing.JLabel lblCost1;
private javax.swing.JLabel lblCost2;
private javax.swing.JLabel lblTech1;
private javax.swing.JLabel lblTech2;
public ForceViewPanel(Force f, Campaign c, IconPackage icons) {
this.force = f;
this.campaign = c;
this.icons = icons;
initComponents();
}
private void initComponents() {
java.awt.GridBagConstraints gridBagConstraints;
lblIcon = new javax.swing.JLabel();
pnlStats = new javax.swing.JPanel();
pnlSubUnits = new javax.swing.JPanel();
txtDesc = new javax.swing.JTextArea();
setLayout(new java.awt.GridBagLayout());
setBackground(Color.WHITE);
lblIcon.setName("lblPortait"); // NOI18N
lblIcon.setBackground(Color.WHITE);
setIcon(force, lblIcon, 150);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.fill = java.awt.GridBagConstraints.NONE;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new java.awt.Insets(10,10,0,0);
add(lblIcon, gridBagConstraints);
pnlStats.setName("pnlStats");
pnlStats.setBorder(BorderFactory.createTitledBorder(force.getName()));
pnlStats.setBackground(Color.WHITE);
fillStats();
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 0;
gridBagConstraints.gridheight = 1;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 20);
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
add(pnlStats, gridBagConstraints);
pnlSubUnits.setName("pnlSubUnits");
pnlSubUnits.setBackground(Color.WHITE);
fillSubUnits();
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 1;
gridBagConstraints.gridwidth = 2;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 20);
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
add(pnlSubUnits, gridBagConstraints);
txtDesc.setName("txtDesc");
txtDesc.setText(force.getDescription());
txtDesc.setEditable(false);
txtDesc.setLineWrap(true);
txtDesc.setWrapStyleWord(true);
txtDesc.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createTitledBorder("Description"),
BorderFactory.createEmptyBorder(5,5,5,5)));
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 2;
gridBagConstraints.gridwidth = 2;
gridBagConstraints.weighty = 1.0;
gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 20);
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
add(txtDesc, gridBagConstraints);
}
private void setIcon(Force force, JLabel lbl, int scale) {
String category = force.getIconCategory();
String filename = force.getIconFileName();
LinkedHashMap<String, Vector<String>> iconMap = force.getIconMap();
if(Crew.ROOT_PORTRAIT.equals(category)) {
category = "";
}
// Return a null if the player has selected no portrait file.
if ((null == category) || (null == filename) || (Crew.PORTRAIT_NONE.equals(filename) && !Force.ROOT_LAYERED.equals(category))) {
filename = "empty.png";
}
// Try to get the player's portrait file.
Image portrait = null;
try {
portrait = IconPackage.buildForceIcon(category, filename, icons.getForceIcons(), iconMap);
if(null != portrait) {
portrait = portrait.getScaledInstance(scale, -1, Image.SCALE_SMOOTH);
} else {
portrait = (Image) icons.getForceIcons().getItem("", "empty.png");
}
portrait = portrait.getScaledInstance(scale, -1, Image.SCALE_SMOOTH);
ImageIcon icon = new ImageIcon(portrait);
lbl.setIcon(icon);
} catch (Exception err) {
err.printStackTrace();
}
}
private void fillStats() {
ResourceBundle resourceMap = ResourceBundle.getBundle("mekhq.resources.ForceViewPanel", new EncodeControl()); //$NON-NLS-1$
lblType = new javax.swing.JLabel();
lblAssign1 = new javax.swing.JLabel();
lblAssign2 = new javax.swing.JLabel();
lblCommander1 = new javax.swing.JLabel();
lblCommander2 = new javax.swing.JLabel();
lblBV1 = new javax.swing.JLabel();
lblBV2 = new javax.swing.JLabel();
lblCost1 = new javax.swing.JLabel();
lblCost2 = new javax.swing.JLabel();
lblTonnage1 = new javax.swing.JLabel();
lblTonnage2 = new javax.swing.JLabel();
lblTech1 = new javax.swing.JLabel();
lblTech2 = new javax.swing.JLabel();
java.awt.GridBagConstraints gridBagConstraints;
pnlStats.setLayout(new java.awt.GridBagLayout());
long bv = 0;
long cost = 0;
double ton = 0;
String commander = "";
String LanceTech = "";
String assigned = "";
String type = null;
ArrayList<Person> people = new ArrayList<Person>();
for(UUID uid : force.getAllUnits()) {
Unit u = campaign.getUnit(uid);
if(null != u) {
Person p = u.getCommander();
bv += u.getEntity().calculateBattleValue(true, !u.hasPilot());
cost += u.getEntity().getCost(true);
ton += u.getEntity().getWeight();
String utype = UnitType.getTypeDisplayableName(UnitType.determineUnitTypeCode(u.getEntity()));
if(null == type) {
type = utype;
} else if(!utype.equals(type)) {
type = resourceMap.getString("mixed");
}
if(null != p) {
people.add(p);
}
}
}
//sort person vector by rank
Collections.sort(people, new Comparator<Person>(){
public int compare(final Person p1, final Person p2) {
return ((Comparable<Integer>)p2.getRankNumeric()).compareTo(p1.getRankNumeric());
}
});
if(people.size() > 0) {
commander = people.get(0).getFullTitle();
}
if (null != force.getTechID()) {
Person p = campaign.getPerson(force.getTechID());
LanceTech = p.getName();
}
if(null != force.getParentForce()) {
assigned = force.getParentForce().getName();
}
DecimalFormat format = new DecimalFormat();
int nexty = 0;
if(null != type) {
lblType.setName("lblCommander2"); // NOI18N
lblType.setText("<html><i>" + type + " " + resourceMap.getString("unit")+ "</i></html>");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = nexty;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.gridwidth = 2;
gridBagConstraints.fill = java.awt.GridBagConstraints.NONE;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
pnlStats.add(lblType, gridBagConstraints);
nexty++;
}
if(!commander.equals("")) {
lblCommander1.setName("lblCommander1"); // NOI18N
lblCommander1.setText(resourceMap.getString("lblCommander1.text"));
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = nexty;
gridBagConstraints.fill = java.awt.GridBagConstraints.NONE;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
pnlStats.add(lblCommander1, gridBagConstraints);
lblCommander2.setName("lblCommander2"); // NOI18N
lblCommander2.setText(commander);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = nexty;
gridBagConstraints.weightx = 0.5;
gridBagConstraints.insets = new java.awt.Insets(0, 10, 0, 0);
gridBagConstraints.fill = java.awt.GridBagConstraints.NONE;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
pnlStats.add(lblCommander2, gridBagConstraints);
nexty++;
}
if (null != force.getTechID()) {
if (!LanceTech.equals("")) {
lblTech1.setName("lblTech1"); // NOI18N
lblTech1.setText(resourceMap.getString("lblTech1.text"));
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = nexty;
gridBagConstraints.fill = java.awt.GridBagConstraints.NONE;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
pnlStats.add(lblTech1, gridBagConstraints);
lblTech2.setName("lblTech2"); // NOI18N
lblTech2.setText(LanceTech);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = nexty;
gridBagConstraints.weightx = 0.5;
gridBagConstraints.insets = new java.awt.Insets(0, 10, 0, 0);
gridBagConstraints.fill = java.awt.GridBagConstraints.NONE;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
pnlStats.add(lblTech2, gridBagConstraints);
nexty++;
}
}
if(!assigned.equals("")) {
lblAssign1.setName("lblAssign1"); // NOI18N
lblAssign1.setText(resourceMap.getString("lblAssign1.text"));
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = nexty;
gridBagConstraints.fill = java.awt.GridBagConstraints.NONE;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
pnlStats.add(lblAssign1, gridBagConstraints);
lblAssign2.setName("lblAssign2"); // NOI18N
lblAssign2.setText(assigned);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = nexty;
gridBagConstraints.weightx = 0.5;
gridBagConstraints.insets = new java.awt.Insets(0, 10, 0, 0);
gridBagConstraints.fill = java.awt.GridBagConstraints.NONE;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
pnlStats.add(lblAssign2, gridBagConstraints);
nexty++;
}
lblBV1.setName("lblBV1"); // NOI18N
lblBV1.setText(resourceMap.getString("lblBV1.text"));
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = nexty;
gridBagConstraints.fill = java.awt.GridBagConstraints.NONE;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
pnlStats.add(lblBV1, gridBagConstraints);
lblBV2.setName("lblBV2"); // NOI18N
lblBV2.setText(format.format(bv));
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = nexty;
gridBagConstraints.weightx = 0.5;
gridBagConstraints.insets = new java.awt.Insets(0, 10, 0, 0);
gridBagConstraints.fill = java.awt.GridBagConstraints.NONE;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
pnlStats.add(lblBV2, gridBagConstraints);
nexty++;
lblTonnage1.setName("lblTonnage1"); // NOI18N
lblTonnage1.setText(resourceMap.getString("lblTonnage1.text"));
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = nexty;
gridBagConstraints.fill = java.awt.GridBagConstraints.NONE;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
pnlStats.add(lblTonnage1, gridBagConstraints);
lblTonnage2.setName("lblTonnage2"); // NOI18N
lblTonnage2.setText(format.format(ton));
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = nexty;
gridBagConstraints.weightx = 0.5;
gridBagConstraints.insets = new java.awt.Insets(0, 10, 0, 0);
gridBagConstraints.fill = java.awt.GridBagConstraints.NONE;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
pnlStats.add(lblTonnage2, gridBagConstraints);
nexty++;
lblCost1.setName("lblCost1"); // NOI18N
lblCost1.setText(resourceMap.getString("lblCost1.text"));
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = nexty;
gridBagConstraints.fill = java.awt.GridBagConstraints.NONE;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
pnlStats.add(lblCost1, gridBagConstraints);
lblCost2.setName("lblCost2"); // NOI18N
lblCost2.setText(format.format(cost) + " C-bills");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = nexty;
gridBagConstraints.weightx = 0.5;
gridBagConstraints.insets = new java.awt.Insets(0, 10, 0, 0);
gridBagConstraints.fill = java.awt.GridBagConstraints.NONE;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
pnlStats.add(lblCost2, gridBagConstraints);
nexty++;
//BV
//Tonnage?
//Cost?
//Number of units?
//Assigned to
}
private void fillSubUnits() {
java.awt.GridBagConstraints gridBagConstraints;
pnlSubUnits.setLayout(new java.awt.GridBagLayout());
JLabel lblForce;
int nexty = 0;
for(Force subForce : force.getSubForces()) {
lblForce = new JLabel();
lblForce.setText(getSummaryFor(subForce));
setIcon(subForce, lblForce, 72);
nexty++;
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = nexty;
gridBagConstraints.gridwidth = 2;
gridBagConstraints.weighty = 1.0;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
pnlSubUnits.add(lblForce, gridBagConstraints);
}
JLabel lblPerson;
JLabel lblUnit;
ArrayList<Unit> units = new ArrayList<Unit>();
ArrayList<Unit> unmannedUnits = new ArrayList<Unit>();
for(UUID uid : force.getUnits()) {
Unit u = campaign.getUnit(uid);
if(null == u) {
continue;
}
if(null == u.getCommander()) {
unmannedUnits.add(u);
} else {
units.add(u);
}
}
//sort person vector by rank
Collections.sort(units, new Comparator<Unit>(){
public int compare(final Unit u1, final Unit u2) {
return ((Comparable<Integer>)u2.getCommander().getRankNumeric()).compareTo(u1.getCommander().getRankNumeric());
}
});
for(Unit unit : unmannedUnits) {
units.add(unit);
}
for(Unit unit : units) {
Person p = unit.getCommander();
lblPerson = new JLabel();
lblUnit = new JLabel();
if(null != p) {
lblPerson.setText(getSummaryFor(p, unit));
setPortrait(p, lblPerson);
}
nexty++;
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = nexty;
gridBagConstraints.gridwidth = 1;
gridBagConstraints.weighty = 1.0;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
pnlSubUnits.add(lblPerson, gridBagConstraints);
if(null != unit) {
lblUnit.setText(getSummaryFor(unit));
lblUnit.setIcon(new ImageIcon(getImageFor(unit, lblUnit)));
}
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = nexty;
gridBagConstraints.gridwidth = 1;
gridBagConstraints.weighty = 1.0;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
pnlSubUnits.add(lblUnit, gridBagConstraints);
}
}
/**
* set the portrait for the given person.
*
* @return The <code>Image</code> of the pilot's portrait. This value
* will be <code>null</code> if no portrait was selected
* or if there was an error loading it.
*/
public void setPortrait(Person p, JLabel lbl) {
String category = p.getPortraitCategory();
String filename = p.getPortraitFileName();
if(Crew.ROOT_PORTRAIT.equals(category)) {
category = "";
}
// Return a null if the player has selected no portrait file.
if ((null == category) || (null == filename) || Crew.PORTRAIT_NONE.equals(filename)) {
filename = "default.gif";
}
// Try to get the player's portrait file.
Image portrait = null;
try {
portrait = (Image) icons.getPortraits().getItem(category, filename);
if(null != portrait) {
portrait = portrait.getScaledInstance(72, -1, Image.SCALE_DEFAULT);
} else {
portrait = (Image) icons.getPortraits().getItem("", "default.gif");
if(null != portrait) {
portrait = portrait.getScaledInstance(72, -1, Image.SCALE_DEFAULT);
}
}
lbl.setIcon(new ImageIcon(portrait));
} catch (Exception err) {
err.printStackTrace();
}
}
private Image getImageFor(Unit u, Component c) {
if(null == icons.getMechTiles()) {
return null;
}
Image base = icons.getMechTiles().imageFor(u.getEntity(), c, -1);
int tint = PlayerColors.getColorRGB(u.campaign.getColorIndex());
EntityImage entityImage = new EntityImage(base, tint, getCamo(u), c);
return entityImage.loadPreviewImage();
}
private Image getCamo(Unit unit) {
// Try to get the player's camo file.
Image camo = null;
try {
camo = (Image) icons.getCamos().getItem(unit.getCamoCategory(), unit.getCamoFileName());
} catch (Exception err) {
err.printStackTrace();
}
return camo;
}
public String getSummaryFor(Person person, Unit unit) {
String toReturn = "<html><font size='2'><b>" + person.getFullTitle() + "</b><br/>";
toReturn += person.getSkillSummary() + " " + person.getRoleDesc();
if(null != unit && null != unit.getEntity()
&& null != unit.getEntity().getCrew() && unit.getEntity().getCrew().getHits() > 0) {
toReturn += "<br><font color='red' size='2'>" + unit.getEntity().getCrew().getHits() + " hit(s)";
}
toReturn += "</font></html>";
return toReturn;
}
public String getSummaryFor(Unit unit) {
String toReturn = "<html><font size='2'><b>" + unit.getName() + "</b><br/>";
toReturn += "<b>BV:</b> " + unit.getEntity().calculateBattleValue(true, null == unit.getEntity().getCrew()) + "<br/>";
toReturn += unit.getStatus();
Entity entity = unit.getEntity();
if (entity.hasC3i()) {
toReturn += "<br><i>";
if (entity.calculateFreeC3Nodes() >= 5) {
toReturn += Messages.getString("ChatLounge.C3iNone");
} else {
toReturn += Messages
.getString("ChatLounge.C3iNetwork")
+ entity.getC3NetId();
if (entity.calculateFreeC3Nodes() > 0) {
toReturn += Messages.getString("ChatLounge.C3Nodes",
new Object[] { entity.calculateFreeC3Nodes() });
}
}
toReturn += "</i>";
}
toReturn += "</font></html>";
return toReturn;
}
public String getSummaryFor(Force f) {
//we are not going to use the campaign methods here because we can be more efficient
//by only traversing once
int bv = 0;
int cost = 0;
double ton = 0;
int number = 0;
String commander = "No personnel found";
ArrayList<Person> people = new ArrayList<Person>();
for(UUID uid : f.getAllUnits()) {
Unit u = campaign.getUnit(uid);
if(null != u) {
Person p = u.getCommander();
number++;
if (p != null) {
bv += u.getEntity().calculateBattleValue(true, false);
} else {
bv += u.getEntity().calculateBattleValue(true, true);
}
cost += u.getEntity().getCost(true);
ton += u.getEntity().getWeight();
if(null != p) {
people.add(p);
}
}
}
//sort person vector by rank
Collections.sort(people, new Comparator<Person>(){
public int compare(final Person p1, final Person p2) {
return ((Comparable<Integer>)p2.getRankNumeric()).compareTo(p1.getRankNumeric());
}
});
if(people.size() > 0) {
commander = people.get(0).getFullTitle();
}
DecimalFormat format = new DecimalFormat();
String toReturn = "<html><font size='2'><b>" + f.getName() + "</b> (" + commander + ")<br/>";
toReturn += "<b>Number of Units:</b> " + number + "<br/>";
toReturn += bv + " BV, ";
toReturn += format.format(ton) + " tons, ";
toReturn += format.format(cost) + " C-bills";
toReturn += "</font></html>";
return toReturn;
}
}