package mekhq.gui.model;
import java.awt.Color;
import java.awt.Component;
import java.awt.Image;
import java.awt.Toolkit;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.UUID;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import megamek.common.Entity;
import megamek.common.Jumpship;
import megamek.common.SmallCraft;
import megamek.common.Tank;
import megamek.common.UnitType;
import megamek.common.options.PilotOptions;
import mekhq.IconPackage;
import mekhq.campaign.Campaign;
import mekhq.campaign.force.Force;
import mekhq.campaign.market.PersonnelMarket;
import mekhq.campaign.personnel.Person;
import mekhq.campaign.personnel.SkillType;
import mekhq.campaign.unit.Unit;
import mekhq.gui.BasicInfo;
/**
* A table Model for displaying information about personnel
* @author Jay lawson
*/
public class PersonnelTableModel extends DataTableModel {
private static final long serialVersionUID = -5207167419079014157L;
private Campaign campaign;
private PersonnelMarket personnelMarket;
private boolean loadAssignmentFromMarket;
public final static int COL_RANK = 0;
public final static int COL_NAME = 1;
public final static int COL_CALL = 2;
public final static int COL_AGE = 3;
public final static int COL_GENDER = 4;
public final static int COL_SKILL = 5;
public final static int COL_TYPE = 6;
public final static int COL_ASSIGN = 7;
public final static int COL_FORCE = 8;
public final static int COL_DEPLOY = 9;
public final static int COL_MECH = 10;
public final static int COL_AERO = 11;
public final static int COL_JET = 12;
public final static int COL_VEE = 13;
public final static int COL_VTOL = 14;
public final static int COL_NVEE = 15;
public final static int COL_SPACE = 16;
public final static int COL_ARTY = 17;
public final static int COL_GUN_BA = 18;
public final static int COL_SMALL_ARMS = 19;
public final static int COL_ANTI_MECH = 20;
public final static int COL_TACTICS = 21;
public final static int COL_STRATEGY = 22;
public final static int COL_TECH_MECH = 23;
public final static int COL_TECH_AERO = 24;
public final static int COL_TECH_VEE = 25;
public final static int COL_TECH_BA = 26;
public final static int COL_MEDICAL = 27;
public final static int COL_ADMIN = 28;
public final static int COL_NEG = 29;
public final static int COL_SCROUNGE = 30;
public final static int COL_TOUGH = 31;
public final static int COL_EDGE = 32;
public final static int COL_NABIL = 33;
public final static int COL_NIMP = 34;
public final static int COL_HITS = 35;
public final static int COL_KILLS = 36;
public final static int COL_SALARY = 37;
public final static int COL_XP = 38;
public final static int N_COL = 39;
public PersonnelTableModel(Campaign c) {
data = new ArrayList<Person>();
campaign = c;
}
@Override
public int getColumnCount() {
return N_COL;
}
@Override
public String getColumnName(int column) {
switch(column) {
case COL_RANK:
return "Rank";
case COL_NAME:
return "Name";
case COL_CALL:
return "Callsign";
case COL_AGE:
return "Age";
case COL_GENDER:
return "Gender";
case COL_TYPE:
return "Role";
case COL_MECH:
return "Mech";
case COL_AERO:
return "Aero";
case COL_JET:
return "Aircraft";
case COL_VEE:
return "Vehicle";
case COL_VTOL:
return "VTOL";
case COL_NVEE:
return "Naval";
case COL_SPACE:
return "Spacecraft";
case COL_ARTY:
return "Artillery";
case COL_GUN_BA:
return "G/Battlesuit";
case COL_SMALL_ARMS:
return "Small Arms";
case COL_ANTI_MECH:
return "Anti-Mech";
case COL_TACTICS:
return "Tactics";
case COL_STRATEGY:
return "Strategy";
case COL_TECH_MECH:
return "Tech/Mech";
case COL_TECH_AERO:
return "Tech/Aero";
case COL_TECH_VEE:
return "Mechanic";
case COL_TECH_BA:
return "Tech/BA";
case COL_MEDICAL:
return "Medical";
case COL_ADMIN:
return "Admin";
case COL_NEG:
return "Negotiation";
case COL_SCROUNGE:
return "Scrounge";
case COL_TOUGH:
return "Toughness";
case COL_SKILL:
return "Skill Level";
case COL_ASSIGN:
return "Unit Assignment";
case COL_EDGE:
return "Edge";
case COL_NABIL:
return "# Abilities";
case COL_NIMP:
return "# Implants";
case COL_HITS:
return "Hits";
case COL_XP:
return "XP";
case COL_DEPLOY:
return "Deployed";
case COL_FORCE:
return "Force";
case COL_SALARY:
return "Salary";
case COL_KILLS:
return "Kills";
default:
return "?";
}
}
public int getColumnWidth(int c) {
switch(c) {
case COL_RANK:
case COL_DEPLOY:
return 70;
case COL_CALL:
case COL_SALARY:
case COL_SKILL:
return 50;
case COL_TYPE:
case COL_FORCE:
return 100;
case COL_NAME:
case COL_ASSIGN:
return 125;
default:
return 20;
}
}
public int getAlignment(int col) {
switch(col) {
case COL_SALARY:
return SwingConstants.RIGHT;
case COL_RANK:
case COL_NAME:
case COL_GENDER:
case COL_TYPE:
case COL_DEPLOY:
case COL_FORCE:
case COL_ASSIGN:
case COL_SKILL:
return SwingConstants.LEFT;
default:
return SwingConstants.CENTER;
}
}
public String getTooltip(int row, int col) {
Person p = getPerson(row);
switch(col) {
case COL_NABIL:
return p.getAbilityList(PilotOptions.LVL3_ADVANTAGES);
case COL_NIMP:
return p.getAbilityList(PilotOptions.MD_ADVANTAGES);
case COL_ASSIGN:
if((p.getTechUnitIDs().size() > 1) && !loadAssignmentFromMarket) {
String toReturn = "<html>";
for(UUID id : p.getTechUnitIDs()) {
Unit u = getCampaign().getUnit(id);
if(null != u) {
toReturn += u.getName() + "<br>";
}
}
toReturn += "</html>";
return toReturn;
} else {
return null;
}
default:
return null;
}
}
@Override
public Class<?> getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
@Override
public boolean isCellEditable(int row, int col) {
return false;
}
public Person getPerson(int i) {
if( i >= data.size()) {
return null;
}
return (Person)data.get(i);
}
public boolean isDeployed(int row) {
return getPerson(row).isDeployed();
}
@Override
public Object getValueAt(int row, int col) {
Person p;
DecimalFormat formatter = new DecimalFormat();
if(data.isEmpty()) {
return "";
} else {
p = getPerson(row);
}
if(col == COL_RANK) {
return p.makeHTMLRank();
}
if(col == COL_NAME) {
return p.getName();
}
if(col == COL_CALL) {
return p.getCallsign();
}
if(col == COL_GENDER) {
return p.getGenderName();
}
if(col == COL_AGE) {
return Integer.toString(p.getAge(getCampaign().getCalendar()));
}
if(col == COL_TYPE) {
return p.getRoleDesc();
}
if(col == COL_MECH) {
String toReturn = "";
if(p.hasSkill(SkillType.S_GUN_MECH)) {
toReturn += Integer.toString(p.getSkill(SkillType.S_GUN_MECH).getFinalSkillValue());
} else {
toReturn += "-";
}
toReturn += "/";
if(p.hasSkill(SkillType.S_PILOT_MECH)) {
toReturn += Integer.toString(p.getSkill(SkillType.S_PILOT_MECH).getFinalSkillValue());
} else {
toReturn += "-";
}
return toReturn;
}
if(col == COL_AERO) {
String toReturn = "";
if(p.hasSkill(SkillType.S_GUN_AERO)) {
toReturn += Integer.toString(p.getSkill(SkillType.S_GUN_AERO).getFinalSkillValue());
} else {
toReturn += "-";
}
toReturn += "/";
if(p.hasSkill(SkillType.S_PILOT_AERO)) {
toReturn += Integer.toString(p.getSkill(SkillType.S_PILOT_AERO).getFinalSkillValue());
} else {
toReturn += "-";
}
return toReturn;
}
if(col == COL_JET) {
String toReturn = "";
if(p.hasSkill(SkillType.S_GUN_JET)) {
toReturn += Integer.toString(p.getSkill(SkillType.S_GUN_JET).getFinalSkillValue());
} else {
toReturn += "-";
}
toReturn += "/";
if(p.hasSkill(SkillType.S_PILOT_JET)) {
toReturn += Integer.toString(p.getSkill(SkillType.S_PILOT_JET).getFinalSkillValue());
} else {
toReturn += "-";
}
return toReturn;
}
if(col == COL_SPACE) {
String toReturn = "";
if(p.hasSkill(SkillType.S_GUN_SPACE)) {
toReturn += Integer.toString(p.getSkill(SkillType.S_GUN_SPACE).getFinalSkillValue());
} else {
toReturn += "-";
}
toReturn += "/";
if(p.hasSkill(SkillType.S_PILOT_SPACE)) {
toReturn += Integer.toString(p.getSkill(SkillType.S_PILOT_SPACE).getFinalSkillValue());
} else {
toReturn += "-";
}
return toReturn;
}
if(col == COL_VEE) {
String toReturn = "";
if(p.hasSkill(SkillType.S_GUN_VEE)) {
toReturn += Integer.toString(p.getSkill(SkillType.S_GUN_VEE).getFinalSkillValue());
} else {
toReturn += "-";
}
toReturn += "/";
if(p.hasSkill(SkillType.S_PILOT_GVEE)) {
toReturn += Integer.toString(p.getSkill(SkillType.S_PILOT_GVEE).getFinalSkillValue());
} else {
toReturn += "-";
}
return toReturn;
}
if(col == COL_NVEE) {
String toReturn = "";
if(p.hasSkill(SkillType.S_GUN_VEE)) {
toReturn += Integer.toString(p.getSkill(SkillType.S_GUN_VEE).getFinalSkillValue());
} else {
toReturn += "-";
}
toReturn += "/";
if(p.hasSkill(SkillType.S_PILOT_NVEE)) {
toReturn += Integer.toString(p.getSkill(SkillType.S_PILOT_NVEE).getFinalSkillValue());
} else {
toReturn += "-";
}
return toReturn;
}
if(col == COL_VTOL) {
String toReturn = "";
if(p.hasSkill(SkillType.S_GUN_VEE)) {
toReturn += Integer.toString(p.getSkill(SkillType.S_GUN_VEE).getFinalSkillValue());
} else {
toReturn += "-";
}
toReturn += "/";
if(p.hasSkill(SkillType.S_PILOT_VTOL)) {
toReturn += Integer.toString(p.getSkill(SkillType.S_PILOT_VTOL).getFinalSkillValue());
} else {
toReturn += "-";
}
return toReturn;
}
if(col == COL_GUN_BA) {
if(p.hasSkill(SkillType.S_GUN_BA)) {
return Integer.toString(p.getSkill(SkillType.S_GUN_BA).getFinalSkillValue());
} else {
return "-";
}
}
if(col == COL_ANTI_MECH) {
if(p.hasSkill(SkillType.S_ANTI_MECH)) {
return Integer.toString(p.getSkill(SkillType.S_ANTI_MECH).getFinalSkillValue());
} else {
return "-";
}
}
if(col == COL_SMALL_ARMS) {
if(p.hasSkill(SkillType.S_SMALL_ARMS)) {
return Integer.toString(p.getSkill(SkillType.S_SMALL_ARMS).getFinalSkillValue());
} else {
return "-";
}
}
if(col == COL_ARTY) {
if(p.hasSkill(SkillType.S_ARTILLERY)) {
return Integer.toString(p.getSkill(SkillType.S_ARTILLERY).getFinalSkillValue());
} else {
return "-";
}
}
if(col == COL_TACTICS) {
if(p.hasSkill(SkillType.S_TACTICS)) {
return Integer.toString(p.getSkill(SkillType.S_TACTICS).getFinalSkillValue());
} else {
return "-";
}
}
if(col == COL_STRATEGY) {
if(p.hasSkill(SkillType.S_STRATEGY)) {
return Integer.toString(p.getSkill(SkillType.S_STRATEGY).getFinalSkillValue());
} else {
return "-";
}
}
if(col == COL_TECH_MECH) {
if(p.hasSkill(SkillType.S_TECH_MECH)) {
return Integer.toString(p.getSkill(SkillType.S_TECH_MECH).getFinalSkillValue());
} else {
return "-";
}
}
if(col == COL_TECH_AERO) {
if(p.hasSkill(SkillType.S_TECH_AERO)) {
return Integer.toString(p.getSkill(SkillType.S_TECH_AERO).getFinalSkillValue());
} else {
return "-";
}
}
if(col == COL_TECH_VEE) {
if(p.hasSkill(SkillType.S_TECH_MECHANIC)) {
return Integer.toString(p.getSkill(SkillType.S_TECH_MECHANIC).getFinalSkillValue());
} else {
return "-";
}
}
if(col == COL_TECH_BA) {
if(p.hasSkill(SkillType.S_TECH_BA)) {
return Integer.toString(p.getSkill(SkillType.S_TECH_BA).getFinalSkillValue());
} else {
return "-";
}
}
if(col == COL_MEDICAL) {
if(p.hasSkill(SkillType.S_DOCTOR)) {
return Integer.toString(p.getSkill(SkillType.S_DOCTOR).getFinalSkillValue());
} else {
return "-";
}
}
if(col == COL_ADMIN) {
if(p.hasSkill(SkillType.S_ADMIN)) {
return Integer.toString(p.getSkill(SkillType.S_ADMIN).getFinalSkillValue());
} else {
return "-";
}
}
if(col == COL_NEG) {
if(p.hasSkill(SkillType.S_NEG)) {
return Integer.toString(p.getSkill(SkillType.S_NEG).getFinalSkillValue());
} else {
return "-";
}
}
if(col == COL_SCROUNGE) {
if(p.hasSkill(SkillType.S_SCROUNGE)) {
return Integer.toString(p.getSkill(SkillType.S_SCROUNGE).getFinalSkillValue());
} else {
return "-";
}
}
if(col == COL_TOUGH) {
return "?";
}
if(col == COL_EDGE) {
return Integer.toString(p.getEdge());
}
if(col == COL_NABIL) {
return Integer.toString(p.countOptions(PilotOptions.LVL3_ADVANTAGES));
}
if(col == COL_NIMP) {
return Integer.toString(p.countOptions(PilotOptions.MD_ADVANTAGES));
}
if(col == COL_HITS) {
return Integer.toString(p.getHits());
}
if(col == COL_SKILL) {
return p.getSkillSummary();
}
if(col == COL_ASSIGN) {
if (loadAssignmentFromMarket) {
Entity en = personnelMarket.getAttachedEntity(p);
if (null == en) {
return "-";
}
return en.getDisplayName();
} else {
Unit u = getCampaign().getUnit(p.getUnitId());
if(null != u) {
String name = u.getName();
if(u.getEntity() instanceof Tank) {
if(u.isDriver(p)) {
name = name + " [Driver]";
} else {
name = name + " [Gunner]";
}
}
if(u.getEntity() instanceof SmallCraft || u.getEntity() instanceof Jumpship) {
if(u.isNavigator(p)) {
name = name + " [Navigator]";
}
else if(u.isDriver(p)) {
name = name + " [Pilot]";
}
else if(u.isGunner(p)) {
name = name + " [Gunner]";
} else {
name = name + " [Crew]";
}
}
return name;
}
//check for tech
if(!p.getTechUnitIDs().isEmpty()) {
if(p.getTechUnitIDs().size() == 1) {
u = getCampaign().getUnit(p.getTechUnitIDs().get(0));
if(null != u) {
return u.getName() + " (" + p.getMaintenanceTimeUsing() + "m)";
}
} else {
return "" + p.getTechUnitIDs().size() + " units (" + p.getMaintenanceTimeUsing() + "m)";
}
}
return "-";
}
}
if(col == COL_XP) {
return Integer.toString(p.getXp());
}
if(col == COL_DEPLOY) {
Unit u = getCampaign().getUnit(p.getUnitId());
if(null != u && u.isDeployed()) {
return getCampaign().getScenario(u.getScenarioId()).getName();
} else {
return "-";
}
}
if(col == COL_FORCE) {
Force force = getCampaign().getForceFor(p);
if(null != force) {
return force.getName();
} else {
return "None";
}
}
if(col == COL_SALARY) {
return formatter.format(p.getSalary());
}
if(col == COL_KILLS) {
return Integer.toString(getCampaign().getKillsFor(p.getId()).size());
}
return "?";
}
private Campaign getCampaign() {
return campaign;
}
public void refreshData() {
setData(getCampaign().getPersonnel());
}
public TableCellRenderer getRenderer(boolean graphic, IconPackage icons) {
if(graphic) {
return new PersonnelTableModel.VisualRenderer(icons);
}
return new PersonnelTableModel.Renderer();
}
public class Renderer extends DefaultTableCellRenderer {
private static final long serialVersionUID = 9054581142945717303L;
@Override
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus,
int row, int column) {
super.getTableCellRendererComponent(table, value, isSelected,
hasFocus, row, column);
setOpaque(true);
int actualCol = table.convertColumnIndexToModel(column);
int actualRow = table.convertRowIndexToModel(row);
setHorizontalAlignment(getAlignment(actualCol));
setToolTipText(getTooltip(actualRow, actualCol));
setForeground(Color.BLACK);
if (isSelected) {
setBackground(Color.DARK_GRAY);
setForeground(Color.WHITE);
} else {
// tiger stripes
if (isDeployed(actualRow)) {
setBackground(Color.LIGHT_GRAY);
} else if(Integer.parseInt((String) getValueAt(actualRow,COL_HITS)) > 0 || getPerson(actualRow).hasInjuries(true)) {
setBackground(Color.RED);
} else if (getPerson(actualRow).hasOnlyHealedPermanentInjuries()) {
setBackground(new Color(0xee9a00));
} else {
setBackground(Color.WHITE);
}
}
return this;
}
}
public class VisualRenderer extends BasicInfo implements TableCellRenderer {
private static final long serialVersionUID = -9154596036677641620L;
public VisualRenderer(IconPackage icons) {
super(icons);
}
@Override
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus,
int row, int column) {
Component c = this;
int actualCol = table.convertColumnIndexToModel(column);
int actualRow = table.convertRowIndexToModel(row);
Person p = getPerson(actualRow);
String color = "black";
if(isSelected) {
color = "white";
}
setText(getValueAt(actualRow, actualCol).toString(), color);
if (actualCol == COL_RANK) {
setPortrait(p);
setText(p.getFullDesc(), color);
}
if(actualCol == COL_ASSIGN) {
if (loadAssignmentFromMarket) {
Entity en = personnelMarket.getAttachedEntity(p);
if (null == en) {
setText("-", color);
}
setText(en.getDisplayName(), color);
} else {
Unit u = getCampaign().getUnit(p.getUnitId());
if(!p.getTechUnitIDs().isEmpty()) {
u = getCampaign().getUnit(p.getTechUnitIDs().get(0));
}
if(null != u) {
String desc = "<b>" + u.getName() + "</b><br>";
desc += u.getEntity().getWeightClassName();
if(!(u.getEntity() instanceof SmallCraft || u.getEntity() instanceof Jumpship)) {
desc += " " + UnitType.getTypeDisplayableName(UnitType.determineUnitTypeCode(u.getEntity()));
}
desc += "<br>" + u.getStatus() + "";
setText(desc, color);
Image mekImage = getImageFor(u);
if(null != mekImage) {
setImage(mekImage);
} else {
clearImage();
}
} else {
clearImage();
}
}
}
if(actualCol == COL_FORCE) {
Force force = getCampaign().getForceFor(p);
if(null != force) {
String desc = "<html><b>" + force.getName() + "</b>";
Force parent = force.getParentForce();
//cut off after three lines and don't include the top level
int lines = 1;
while(parent != null && null != parent.getParentForce() && lines < 4) {
desc += "<br>" + parent.getName();
lines++;
parent = parent.getParentForce();
}
desc += "</html>";
setText(desc, color);
Image forceImage = getImageFor(force);
if(null != forceImage) {
setImage(forceImage);
} else {
clearImage();
}
} else {
clearImage();
}
}
if(actualCol == COL_HITS) {
Image hitImage = getHitsImage(p.getHits());
if(null != hitImage) {
setImage(hitImage);
setText("", color);
} else {
clearImage();
setText("", color);
}
}
if (isSelected) {
c.setBackground(Color.DARK_GRAY);
} else {
// tiger stripes
if ((row % 2) == 0) {
c.setBackground(new Color(220, 220, 220));
} else {
c.setBackground(Color.WHITE);
}
}
return c;
}
private Image getHitsImage(int hits) {
switch(hits) {
case 1:
return Toolkit.getDefaultToolkit().getImage("data/images/misc/hits/onehit.png");
case 2:
return Toolkit.getDefaultToolkit().getImage("data/images/misc/hits/twohits.png");
case 3:
return Toolkit.getDefaultToolkit().getImage("data/images/misc/hits/threehits.png");
case 4:
return Toolkit.getDefaultToolkit().getImage("data/images/misc/hits/fourhits.png");
case 5:
return Toolkit.getDefaultToolkit().getImage("data/images/misc/hits/fivehits.png");
case 6:
return Toolkit.getDefaultToolkit().getImage("data/images/misc/hits/sixhits.png");
}
return null;
}
}
public void loadAssignmentFromMarket(PersonnelMarket personnelMarket) {
this.personnelMarket = personnelMarket;
this.loadAssignmentFromMarket = (null != personnelMarket);
}
}