package mekhq.gui.model; import java.awt.Component; import java.awt.Image; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.swing.JTable; import javax.swing.table.TableCellRenderer; import megamek.common.TargetRoll; import mekhq.IconPackage; import mekhq.campaign.parts.MissingPart; import mekhq.campaign.parts.Part; import mekhq.campaign.parts.PodSpace; import mekhq.campaign.personnel.Person; import mekhq.campaign.personnel.Skill; import mekhq.campaign.work.IPartWork; import mekhq.gui.CampaignGUI; import mekhq.gui.ITechWorkPanel; import mekhq.gui.RepairTaskInfo; /** * A table model for displaying work items */ public class TaskTableModel extends DataTableModel { private static final long serialVersionUID = -6256038046416893994L; private static Map<String, Person> techCache = new HashMap<String, Person>(); private CampaignGUI gui; private ITechWorkPanel panel; private interface REPAIR_STATE { public static final int AVAILABLE = 0; public static final int NOT_AVAILABLE = 1; public static final int IN_TRANSIT = 2; public static final int BLOCKED = 3; public static final int SCHEDULED = 4; } public TaskTableModel(CampaignGUI gui, ITechWorkPanel panel) { columnNames = new String[] { "Tasks" }; data = new ArrayList<IPartWork>(); this.gui = gui; this.panel = panel; } public Object getValueAt(int row, int col) { return ((IPartWork) data.get(row)).getDesc(); } public IPartWork getTaskAt(int row) { return (IPartWork) data.get(row); } public IPartWork[] getTasksAt(int[] rows) { IPartWork[] tasks = new IPartWork[rows.length]; for (int i = 0; i < rows.length; i++) { int row = rows[i]; tasks[i] = (IPartWork) data.get(row); } return tasks; } public TaskTableModel.Renderer getRenderer(IconPackage icons) { return new TaskTableModel.Renderer(icons); } public class Renderer extends RepairTaskInfo implements TableCellRenderer { public Renderer(IconPackage icons) { super(icons); } private static final long serialVersionUID = -3052618135259621130L; 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); setOpaque(true); setText("<html>" + getValueAt(actualRow, actualCol).toString() + "</html>", "black"); if (isSelected) { highlightBorder(); } else { unhighlightBorder(); } IPartWork part = getTaskAt(actualRow); int availableLevel = REPAIR_STATE.AVAILABLE; if (null != part.getTeamId()) { availableLevel = REPAIR_STATE.SCHEDULED; } else { if (part instanceof MissingPart) { if (!((MissingPart)part).isReplacementAvailable()) { String[] inventories = gui.getCampaign().getPartInventory(((MissingPart) part).getNewPart()); //int inStock = processInventoryString(inventories[0]); int inTransit = processInventoryString(inventories[1]); int onOrder = processInventoryString(inventories[2]); if ((inTransit > 0) || (onOrder > 0)) { availableLevel = REPAIR_STATE.IN_TRANSIT; } else { availableLevel = REPAIR_STATE.NOT_AVAILABLE; } } } else if (part instanceof PodSpace && !part.isSalvaging()) { Matcher m = Pattern.compile(".*(\\d+)/(\\d+).*(\\d+) in transit, (\\d+) on order.*").matcher(part.getDetails()); if (m.matches()) { //Show available if at least one replacement can be made if (m.group(2).equals("0")) { availableLevel = REPAIR_STATE.BLOCKED; } else if (!m.group(1).equals("0")) { availableLevel = REPAIR_STATE.AVAILABLE; } else if (m.group(3).equals("0") && m.group(4).equals("0")) { availableLevel = REPAIR_STATE.NOT_AVAILABLE; } else { availableLevel = REPAIR_STATE.IN_TRANSIT; } } } if (availableLevel == REPAIR_STATE.AVAILABLE) { Person tech = panel.getSelectedTech(); if (null == tech) { //Find a valid tech that we can copy their skill from ArrayList<Person> techs = gui.getCampaign().getTechs(false); for (int i = techs.size() - 1; i >= 0; i--) { Person techTemp = techs.get(i); if (techTemp.canTech(part.getUnit().getEntity())) { tech = techTemp; break; } } if (null != tech) { Skill partSkill = tech.getSkillForWorkingOn(part); String skillName = partSkill.getType().getName(); //Find a tech in our placeholder cache tech = techCache.get(skillName); if (null == tech) { //Create a dummy elite tech with the proper skill and 1 minute and put it in our cache for later use tech = new Person(String.format("Temp Tech (%s)", skillName), gui.getCampaign()); tech.addSkill(skillName, partSkill.getType().getEliteLevel(), 1); tech.setMinutesLeft(1); techCache.put(skillName, tech); } } } if (null != tech) { TargetRoll roll = gui.getCampaign().getTargetFor(part, tech); if ((roll.getValue() == TargetRoll.IMPOSSIBLE) || (roll.getValue() == TargetRoll.AUTOMATIC_FAIL) || (roll.getValue() == TargetRoll.CHECK_FALSE)) { availableLevel = REPAIR_STATE.BLOCKED; } } } } String imgMod = ""; boolean setSecondary = false; switch (availableLevel) { case REPAIR_STATE.BLOCKED: imgMod = "_impossible"; break; case REPAIR_STATE.IN_TRANSIT: imgMod = "_transit"; break; case REPAIR_STATE.NOT_AVAILABLE: imgMod = "_na"; break; case REPAIR_STATE.SCHEDULED: setSecondary = true; break; } String[] imgData = Part.findPartImage(part); String imgPath = imgData[0] + imgData[1] + imgMod + ".png"; Image imgTool = getToolkit().getImage(imgPath); //$NON-NLS-1$ this.setImage(imgTool); if (setSecondary) { this.setSecondaryImage(getToolkit().getImage("data/images/misc/repair/working.png")); } else { this.setSecondaryImage(null); } return c; } //This is a hack to compensate for the sub-optimal return values private int processInventoryString(String str) { if (str.indexOf(" ") > -1) { return Integer.parseInt(str.substring(0, str.indexOf(" "))); } return Integer.parseInt(str); } } }