/*
* Copyright (c) 2017 The MegaMek Team. All rights reserved.
*
* This file is part of MekHQ.
*
* MekHQ 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 3 of the License, or
* (at your option) any later version.
*
* MekHQ 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 MekHQ. If not, see <http://www.gnu.org/licenses/>.
*/
package mekhq.gui;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.ResourceBundle;
import java.util.UUID;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextPane;
import javax.swing.JToggleButton;
import javax.swing.ListSelectionModel;
import javax.swing.RowFilter;
import javax.swing.RowSorter;
import javax.swing.SortOrder;
import javax.swing.table.TableColumn;
import javax.swing.table.TableRowSorter;
import megamek.common.MechView;
import megamek.common.TargetRoll;
import megamek.common.event.Subscribe;
import megamek.common.util.EncodeControl;
import mekhq.MekHQ;
import mekhq.campaign.event.AcquisitionEvent;
import mekhq.campaign.event.AstechPoolChangedEvent;
import mekhq.campaign.event.DeploymentChangedEvent;
import mekhq.campaign.event.OvertimeModeEvent;
import mekhq.campaign.event.PartEvent;
import mekhq.campaign.event.PartWorkEvent;
import mekhq.campaign.event.PersonEvent;
import mekhq.campaign.event.ProcurementEvent;
import mekhq.campaign.event.RepairStatusChangedEvent;
import mekhq.campaign.event.ScenarioResolvedEvent;
import mekhq.campaign.event.UnitEvent;
import mekhq.campaign.parts.MekLocation;
import mekhq.campaign.parts.Part;
import mekhq.campaign.parts.PodSpace;
import mekhq.campaign.personnel.Person;
import mekhq.campaign.personnel.Skill;
import mekhq.campaign.personnel.SkillType;
import mekhq.campaign.unit.Unit;
import mekhq.campaign.work.IPartWork;
import mekhq.gui.adapter.ServicedUnitsTableMouseAdapter;
import mekhq.gui.adapter.TaskTableMouseAdapter;
import mekhq.gui.dialog.AcquisitionsDialog;
import mekhq.gui.dialog.MassRepairSalvageDialog;
import mekhq.gui.model.TaskTableModel;
import mekhq.gui.model.TechTableModel;
import mekhq.gui.model.UnitTableModel;
import mekhq.gui.model.XTableColumnModel;
import mekhq.gui.sorter.TaskSorter;
import mekhq.gui.sorter.TechSorter;
import mekhq.gui.sorter.UnitStatusSorter;
import mekhq.gui.sorter.UnitTypeSorter;
import mekhq.service.PartsAcquisitionService;
/**
* Shows damaged units and controls for repair.
*
*/
public final class RepairTab extends CampaignGuiTab implements ITechWorkPanel {
private static final long serialVersionUID = 6757065427956450309L;
private JPanel panDoTask;
private JSplitPane splitServicedUnits;
private JTable servicedUnitTable;
private JTable taskTable;
private JTable techTable;
private JButton btnDoTask;
private JToggleButton btnShowAllTechs;
private JScrollPane scrTextTarget;
private JLabel lblTargetNum;
private JTextPane txtServicedUnitView;
private JTextArea textTarget;
private JLabel astechPoolLabel;
private JComboBox<String> choiceLocation;
private JButton btnAcquisitions;
private UnitTableModel servicedUnitModel;
private TaskTableModel taskModel;
private TechTableModel techsModel;
private TableRowSorter<UnitTableModel> servicedUnitSorter;
private TableRowSorter<TaskTableModel> taskSorter;
private TableRowSorter<TechTableModel> techSorter;
//Maintain selections after refresh
private int selectedRow = -1;
private int selectedLocation = -1;
private Unit selectedUnit = null;
private Person selectedTech = getSelectedTech();
RepairTab(CampaignGUI gui, String name) {
super(gui, name);
MekHQ.registerHandler(this);
}
/*
* (non-Javadoc)
*
* @see mekhq.gui.CampaignGuiTab#initTab()
*/
@Override
public void initTab() {
ResourceBundle resourceMap = ResourceBundle.getBundle("mekhq.resources.CampaignGUI", //$NON-NLS-1$ ;
new EncodeControl());
GridBagConstraints gridBagConstraints;
setLayout(new GridBagLayout());
JPanel panServicedUnits = new JPanel(new GridBagLayout());
// Add panel for action buttons
JPanel actionButtons = new JPanel(new GridBagLayout());
JButton btnMRMSDialog = new JButton();
btnMRMSDialog.setText("Mass Repair/Salvage"); // NOI18N
btnMRMSDialog.setToolTipText("Start Mass Repair/Salvage from dialog");
btnMRMSDialog.setName("btnMRMSDialog"); // NOI18N
btnMRMSDialog.addActionListener(ev -> {
MassRepairSalvageDialog dlg = new MassRepairSalvageDialog(getFrame(), true, getCampaignGui(), null,
MassRepairSalvageDialog.MODE.UNITS);
dlg.setVisible(true);
});
JButton btnMRMSInstantAll = new JButton();
btnMRMSInstantAll.setText("Instant Mass Repair/Salvage All"); // NOI18N
btnMRMSInstantAll
.setToolTipText("Perform Mass Repair/Salvage immediately on all units using active configuration");
btnMRMSInstantAll.setName("btnMRMSInstantAll"); // NOI18N
btnMRMSInstantAll.addActionListener(ev -> {
MassRepairSalvageDialog.massRepairSalvageAllUnits(getCampaignGui());
});
btnAcquisitions = new JButton();
btnAcquisitions.setText("Parts"); // NOI18N
btnAcquisitions.setToolTipText("Show missing/in transit/on order parts");
btnAcquisitions.setName("btnAcquisitions"); // NOI18N
btnAcquisitions.addActionListener(ev -> {
AcquisitionsDialog dlg = new AcquisitionsDialog(getFrame(), true, getCampaignGui());
dlg.setVisible(true);
});
btnAcquisitions.addPropertyChangeListener("counts", new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
String txt = "Parts Acquisition";
if (PartsAcquisitionService.getMissingCount() > 0) {
if (PartsAcquisitionService.getUnavailableCount() > 0) {
txt += String.format(" (%s missing, %s unavailable)", PartsAcquisitionService.getMissingCount(), PartsAcquisitionService.getUnavailableCount());
} else {
txt += String.format(" (%s missing)", PartsAcquisitionService.getMissingCount());
}
}
btnAcquisitions.setText(txt);
btnAcquisitions.repaint();
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.weightx = 0.5;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
actionButtons.add(btnMRMSDialog, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 0;
gridBagConstraints.weightx = 0.5;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
actionButtons.add(btnMRMSInstantAll, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 1;
gridBagConstraints.weightx = 1;
gridBagConstraints.weighty = 1;
gridBagConstraints.gridwidth = 2;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
actionButtons.add(btnAcquisitions, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.insets = new Insets(5, 0, 5, 0);
panServicedUnits.add(actionButtons, gridBagConstraints);
servicedUnitModel = new UnitTableModel(getCampaign());
servicedUnitTable = new JTable(servicedUnitModel);
servicedUnitTable.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
servicedUnitTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
servicedUnitTable.setColumnModel(new XTableColumnModel());
servicedUnitTable.createDefaultColumnsFromModel();
servicedUnitSorter = new TableRowSorter<UnitTableModel>(servicedUnitModel);
servicedUnitSorter.setComparator(UnitTableModel.COL_STATUS, new UnitStatusSorter());
servicedUnitSorter.setComparator(UnitTableModel.COL_TYPE, new UnitTypeSorter());
servicedUnitTable.setRowSorter(servicedUnitSorter);
ArrayList<RowSorter.SortKey> sortKeys = new ArrayList<RowSorter.SortKey>();
sortKeys.add(new RowSorter.SortKey(UnitTableModel.COL_TYPE, SortOrder.DESCENDING));
servicedUnitSorter.setSortKeys(sortKeys);
TableColumn column = null;
for (int i = 0; i < UnitTableModel.N_COL; i++) {
column = ((XTableColumnModel) servicedUnitTable.getColumnModel()).getColumnByModelIndex(i);
column.setPreferredWidth(servicedUnitModel.getColumnWidth(i));
column.setCellRenderer(servicedUnitModel.getRenderer(false, getIconPackage()));
if (i != UnitTableModel.COL_NAME && i != UnitTableModel.COL_STATUS && i != UnitTableModel.COL_REPAIR
&& i != UnitTableModel.COL_SITE && i != UnitTableModel.COL_TYPE) {
((XTableColumnModel) servicedUnitTable.getColumnModel()).setColumnVisible(column, false);
}
}
servicedUnitTable.setIntercellSpacing(new Dimension(0, 0));
servicedUnitTable.setShowGrid(false);
servicedUnitTable.getSelectionModel().addListSelectionListener(ev -> servicedUnitTableValueChanged(ev));
servicedUnitTable.addMouseListener(new ServicedUnitsTableMouseAdapter(getCampaignGui(),
servicedUnitTable, servicedUnitModel));
JScrollPane scrollServicedUnitTable = new JScrollPane(servicedUnitTable);
scrollServicedUnitTable.setMinimumSize(new java.awt.Dimension(350, 200));
scrollServicedUnitTable.setPreferredSize(new java.awt.Dimension(350, 200));
txtServicedUnitView = new JTextPane();
txtServicedUnitView.setEditable(false);
txtServicedUnitView.setContentType("text/html");
JScrollPane scrollServicedUnitView = new JScrollPane(txtServicedUnitView);
scrollServicedUnitView.setMinimumSize(new java.awt.Dimension(350, 400));
scrollServicedUnitView.setPreferredSize(new java.awt.Dimension(350, 400));
splitServicedUnits = new JSplitPane(JSplitPane.VERTICAL_SPLIT, scrollServicedUnitTable, scrollServicedUnitView);
splitServicedUnits.setOneTouchExpandable(true);
splitServicedUnits.setResizeWeight(0.0);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 1;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
panServicedUnits.add(splitServicedUnits, gridBagConstraints);
JPanel panTasks = new JPanel(new GridBagLayout());
techsModel = new TechTableModel(getCampaignGui(), this);
techTable = new JTable(techsModel);
techTable.setRowHeight(60);
techTable.getColumnModel().getColumn(0).setCellRenderer(techsModel.getRenderer(getIconPackage()));
techTable.getSelectionModel().addListSelectionListener(ev -> techTableValueChanged(ev));
techSorter = new TableRowSorter<TechTableModel>(techsModel);
techSorter.setComparator(0, new TechSorter());
techTable.setRowSorter(techSorter);
sortKeys = new ArrayList<RowSorter.SortKey>();
sortKeys.add(new RowSorter.SortKey(0, SortOrder.ASCENDING));
techSorter.setSortKeys(sortKeys);
JScrollPane scrollTechTable = new JScrollPane(techTable);
scrollTechTable.setMinimumSize(new java.awt.Dimension(200, 200));
scrollTechTable.setPreferredSize(new java.awt.Dimension(300, 300));
panDoTask = new JPanel(new GridBagLayout());
panDoTask.setMinimumSize(new java.awt.Dimension(300, 100));
panDoTask.setName("panelDoTask"); // NOI18N
panDoTask.setPreferredSize(new java.awt.Dimension(300, 100));
btnDoTask = new JButton(resourceMap.getString("btnDoTask.text")); // NOI18N
btnDoTask.setToolTipText(resourceMap.getString("btnDoTask.toolTipText")); // NOI18N
btnDoTask.setEnabled(false);
btnDoTask.addActionListener(ev -> doTask());
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
panDoTask.add(btnDoTask, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 1;
gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTH;
panDoTask.add(new JLabel(resourceMap.getString("lblTarget.text")), gridBagConstraints);
lblTargetNum = new JLabel(resourceMap.getString("lblTargetNum.text")); // NOI18N
lblTargetNum.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
lblTargetNum.setName("lblTargetNum"); // NOI18N
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 2;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
panDoTask.add(lblTargetNum, gridBagConstraints);
textTarget = new JTextArea();
textTarget.setColumns(20);
textTarget.setEditable(false);
textTarget.setLineWrap(true);
textTarget.setRows(5);
textTarget.setText(resourceMap.getString("textTarget.text")); // NOI18N
textTarget.setWrapStyleWord(true);
textTarget.setBorder(null);
textTarget.setName("textTarget"); // NOI18N
scrTextTarget = new JScrollPane(textTarget);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 0;
gridBagConstraints.gridheight = 4;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 2);
panDoTask.add(scrTextTarget, gridBagConstraints);
choiceLocation = new JComboBox<String>();
choiceLocation.removeAllItems();
choiceLocation.addItem("All");
choiceLocation.setEnabled(false);
choiceLocation.addActionListener(ev -> filterTasks());
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 3;
gridBagConstraints.gridwidth = 1;
gridBagConstraints.gridheight = 1;
panDoTask.add(choiceLocation, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.weightx = 1.0;
panTasks.add(panDoTask, gridBagConstraints);
taskModel = new TaskTableModel(getCampaignGui(), this);
taskTable = new JTable(taskModel);
taskTable.setRowHeight(70);
taskTable.getColumnModel().getColumn(0).setCellRenderer(taskModel.getRenderer(getIconPackage()));
taskTable.getSelectionModel().addListSelectionListener(ev -> taskTableValueChanged());
taskSorter = new TableRowSorter<TaskTableModel>(taskModel);
taskSorter.setComparator(0, new TaskSorter());
taskTable.setRowSorter(taskSorter);
sortKeys = new ArrayList<RowSorter.SortKey>();
sortKeys.add(new RowSorter.SortKey(0, SortOrder.ASCENDING));
taskSorter.setSortKeys(sortKeys);
taskTable.addMouseListener(new TaskTableMouseAdapter(getCampaignGui(),
taskTable, taskModel));
JScrollPane scrollTaskTable = new JScrollPane(taskTable);
scrollTaskTable.setMinimumSize(new java.awt.Dimension(200, 200));
scrollTaskTable.setPreferredSize(new java.awt.Dimension(300, 300));
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 1;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
panTasks.add(scrollTaskTable, gridBagConstraints);
JPanel panTechs = new JPanel(new GridBagLayout());
btnShowAllTechs = new JToggleButton(resourceMap.getString("btnShowAllTechs.text")); // NOI18N
btnShowAllTechs.setToolTipText(resourceMap.getString("btnShowAllTechs.toolTipText")); // NOI18N
btnShowAllTechs.setName("btnShowAllTechs"); // NOI18N
btnShowAllTechs.addActionListener(ev -> filterTechs());
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
panTechs.add(btnShowAllTechs, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 1;
gridBagConstraints.gridwidth = 2;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
panTechs.add(scrollTechTable, gridBagConstraints);
astechPoolLabel = new JLabel("<html><b>Astech Pool Minutes:</> " + getCampaign().getAstechPoolMinutes() + " ("
+ getCampaign().getNumberAstechs() + " Astechs)</html>"); // NOI18N
astechPoolLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
astechPoolLabel.setName("astechPoolLabel"); // NOI18N
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 2;
gridBagConstraints.gridwidth = 2;
gridBagConstraints.insets = new java.awt.Insets(0, 10, 0, 0);
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
panTechs.add(astechPoolLabel, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
add(panServicedUnits, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 0;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
add(panTasks, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 0;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
add(panTechs, gridBagConstraints);
filterTechs();
}
protected void updateTechTarget() {
TargetRoll target = null;
IPartWork part = getSelectedTask();
if (null != part) {
Unit u = part.getUnit();
Person tech = getSelectedTech();
if (null != u && u.isSelfCrewed()) {
tech = u.getEngineer();
if (null == tech) {
target = new TargetRoll(TargetRoll.IMPOSSIBLE,
"You must have a crew assigned to large vessels to attempt repairs.");
}
}
if (null != tech) {
boolean wasNull = false;
// Temporarily set the Team ID if it isn't already.
// This is needed for the Clan Tech flag
if (part.getTeamId() == null) {
part.setTeamId(tech.getId());
wasNull = true;
}
target = getCampaign().getTargetFor(part, tech);
if (wasNull) { // If it was null, make it null again
part.setTeamId(null);
}
}
}
((TechSorter) techSorter.getComparator(0)).clearPart();
if (null != target) {
btnDoTask.setEnabled(target.getValue() != TargetRoll.IMPOSSIBLE);
textTarget.setText(target.getDesc());
lblTargetNum.setText(target.getValueAsString());
} else {
btnDoTask.setEnabled(false);
textTarget.setText("");
lblTargetNum.setText("-");
}
}
/*
* (non-Javadoc)
*
* @see mekhq.gui.CampaignGuiTab#refreshAll()
*/
@Override
public void refreshAll() {
refreshServicedUnitList();
refreshTaskList();
refreshPartsAcquisition();
refreshTechsList();
}
/*
* (non-Javadoc)
*
* @see mekhq.gui.CampaignGuiTab#tabType()
*/
@Override
public GuiTabType tabType() {
return GuiTabType.REPAIR;
}
@Override
public Person getSelectedTech() {
int row = techTable.getSelectedRow();
if (row < 0) {
return null;
}
return techsModel.getTechAt(techTable.convertRowIndexToModel(row));
}
@Override
public IPartWork getSelectedTask() {
int row = taskTable.getSelectedRow();
if (row < 0) {
return null;
}
return taskModel.getTaskAt(taskTable.convertRowIndexToModel(row));
}
private Unit getSelectedServicedUnit() {
int row = servicedUnitTable.getSelectedRow();
if (row < 0) {
return null;
}
return servicedUnitModel.getUnit(servicedUnitTable.convertRowIndexToModel(row));
}
private void taskTableValueChanged() {
filterTechs();
updateTechTarget();
}
private void servicedUnitTableValueChanged(javax.swing.event.ListSelectionEvent evt) {
refreshTaskList();
refreshPartsAcquisition();
int selected = servicedUnitTable.getSelectedRow();
txtServicedUnitView.setText("");
if (selected > -1) {
Unit unit = servicedUnitModel.getUnit(servicedUnitTable.convertRowIndexToModel(selected));
if (null != unit) {
MechView mv = new MechView(unit.getEntity(), true, true);
txtServicedUnitView.setText("<div style='font: 12pt monospaced'>" + mv.getMechReadoutBasic() + "<br>"
+ mv.getMechReadoutLoadout() + "</div>");
}
}
}
private void techTableValueChanged(javax.swing.event.ListSelectionEvent evt) {
updateTechTarget();
taskTable.repaint();
}
private void doTask() {
selectedRow = taskTable.getSelectedRow();
selectedLocation = choiceLocation.getSelectedIndex();
selectedUnit = getSelectedServicedUnit();
selectedTech = getSelectedTech();
IPartWork part = (IPartWork)getSelectedTask();
if (null == part) {
return;
}
Unit u = part.getUnit();
if (null != u && u.isSelfCrewed()) {
selectedTech = u.getEngineer();
}
if (null == selectedTech) {
return;
}
if (part instanceof Part && ((Part)part).onBadHipOrShoulder() && !part.isSalvaging()) {
if (part instanceof MekLocation && ((MekLocation) part).isBreached()
&& 0 != JOptionPane.showConfirmDialog(getFrame(),
"You are sealing a limb with a bad shoulder or hip.\n"
+ "You may continue, but this limb cannot be repaired and you will have to\n"
+ "scrap it in order to repair the internal structure and fix the shoulder/hip.\n"
+ "Do you wish to continue?",
"Busted Hip/Shoulder", JOptionPane.YES_NO_OPTION)) {
return;
} else if (part instanceof MekLocation && ((MekLocation) part).isBlownOff()
&& 0 != JOptionPane.showConfirmDialog(getFrame(),
"You are re-attaching a limb with a bad shoulder or hip.\n"
+ "You may continue, but this limb cannot be repaired and you will have to\n"
+ "scrap it in order to repair the internal structure and fix the shoulder/hip.\n"
+ "Do you wish to continue?",
"Busted Hip/Shoulder", JOptionPane.YES_NO_OPTION)) {
return;
} else if (0 != JOptionPane.showConfirmDialog(getFrame(),
"You are repairing/replacing a part on a limb with a bad shoulder or hip.\n"
+ "You may continue, but this limb cannot be repaired and you will have to\n"
+ "remove this equipment if you wish to scrap and then replace the limb.\n"
+ "Do you wish to continue?",
"Busted Hip/Shoulder", JOptionPane.YES_NO_OPTION)) {
return;
}
}
getCampaign().fixPart(part, selectedTech);
if (null != u) {
if (!u.isRepairable() && u.getSalvageableParts().size() == 0) {
selectedRow = -1;
getCampaign().removeUnit(u.getId());
}
if (!getCampaign().getServiceableUnits().contains(u)) {
selectedRow = -1;
}
u.refreshPodSpace();
}
MekHQ.triggerEvent(new PartWorkEvent(selectedTech, part));
// get the selected row back for tasks
if (selectedRow != -1) {
if (taskTable.getRowCount() > 0) {
if (taskTable.getRowCount() <= selectedRow) {
selectedRow = taskTable.getRowCount() - 1;
}
taskTable.setRowSelectionInterval(selectedRow, selectedRow);
}
// If requested, switch to top entry
if (getCampaign().getCampaignOptions().useResetToFirstTech() && techTable.getRowCount() > 0) {
techTable.setRowSelectionInterval(0, 0);
} else {
// Or get the selected tech back
for (int i = 0; i < techTable.getRowCount(); i++) {
Person p = techsModel.getTechAt(techTable.convertRowIndexToModel(i));
if (selectedTech.getId().equals(p.getId())) {
techTable.setRowSelectionInterval(i, i);
break;
}
}
}
}
if (selectedLocation != -1) {
if (selectedUnit == null || getSelectedServicedUnit() == null
|| !selectedUnit.equals(getSelectedServicedUnit())
|| selectedLocation >= choiceLocation.getItemCount()) {
selectedLocation = 0;
}
choiceLocation.setSelectedIndex(selectedLocation);
}
}
public void filterTasks() {
RowFilter<TaskTableModel, Integer> taskLocationFilter = null;
final String loc = (String) choiceLocation.getSelectedItem();
taskLocationFilter = new RowFilter<TaskTableModel, Integer>() {
@Override
public boolean include(Entry<? extends TaskTableModel, ? extends Integer> entry) {
TaskTableModel taskModel = entry.getModel();
IPartWork part = (IPartWork)taskModel.getTaskAt(entry.getIdentifier());
if (part == null) {
return false;
}
if (loc != null && !loc.isEmpty()) {
if (loc.equals("All")) {
return true;
} else if (loc.equals("OmniPod")) {
return part instanceof PodSpace;
} else if (part instanceof PodSpace) {
return ((PodSpace)part).getLocation() == part.getUnit().getEntity().getLocationFromAbbr(loc);
} else {
return ((Part)part).isInLocation(loc);
}
}
return false;
}
};
taskSorter.setRowFilter(taskLocationFilter);
}
public void filterTechs() {
RowFilter<TechTableModel, Integer> techTypeFilter = null;
final IPartWork part = getSelectedTask();
final Unit unit = getSelectedServicedUnit();
techTypeFilter = new RowFilter<TechTableModel, Integer>() {
@Override
public boolean include(Entry<? extends TechTableModel, ? extends Integer> entry) {
if (null == part) {
return false;
}
if (!part.needsFixing() && !part.isSalvaging()) {
return false;
}
TechTableModel techModel = entry.getModel();
Person tech = techModel.getTechAt(entry.getIdentifier());
if (null != unit && unit.isSelfCrewed()) {
if (tech.getPrimaryRole() != Person.T_SPACE_CREW) {
return false;
}
// check whether the engineer is assigned to the correct
// unit
return unit.getId().equals(tech.getUnitId());
}
if (tech.getPrimaryRole() == Person.T_SPACE_CREW && (null != unit) && !unit.isSelfCrewed()) {
return false;
}
if (!tech.isRightTechTypeFor(part) && !btnShowAllTechs.isSelected()) {
return false;
}
Skill skill = tech.getSkillForWorkingOn(part);
int modePenalty = part.getMode().expReduction;
if (skill == null) {
return false;
}
if (part.getSkillMin() > SkillType.EXP_ELITE) {
return false;
}
if (tech.getMinutesLeft() <= 0) {
return false;
}
return (getCampaign().getCampaignOptions().isDestroyByMargin()
|| part.getSkillMin() <= (skill.getExperienceLevel() - modePenalty));
}
};
if (getCampaign().getCampaignOptions().useAssignedTechFirst()) {
((TechSorter) techSorter.getComparator(0)).setPart(part);
}
techSorter.setRowFilter(techTypeFilter);
}
public void focusOnUnit(UUID id) {
int row = -1;
for (int i = 0; i < servicedUnitTable.getRowCount(); i++) {
if (servicedUnitModel.getUnit(servicedUnitTable.convertRowIndexToModel(i)).getId().equals(id)) {
row = i;
break;
}
}
if (row != -1) {
servicedUnitTable.setRowSelectionInterval(row, row);
servicedUnitTable.scrollRectToVisible(servicedUnitTable.getCellRect(row, 0, true));
}
}
public void refreshServicedUnitList() {
int selected = servicedUnitTable.getSelectedRow();
servicedUnitModel.setData(getCampaign().getServiceableUnits());
if (selected == servicedUnitTable.getRowCount()) {
selected--;
}
if ((selected > -1) && (selected < servicedUnitTable.getRowCount())) {
servicedUnitTable.setRowSelectionInterval(selected, selected);
}
refreshPartsAcquisition();
}
public void refreshTaskList() {
UUID uuid = null;
if (null != getSelectedServicedUnit()) {
uuid = getSelectedServicedUnit().getId();
}
taskModel.setData(getCampaign().getPartsNeedingServiceFor(uuid));
if (getSelectedServicedUnit() != null && getSelectedServicedUnit().getEntity() != null) {
choiceLocation.removeAllItems();
choiceLocation.addItem("All");
for (String s : getSelectedServicedUnit().getEntity().getLocationAbbrs()) {
if (s.equals("WNG")) {
choiceLocation.addItem("FSLG");
} else {
choiceLocation.addItem(s);
}
}
if (getSelectedServicedUnit().getEntity().isOmni()) {
choiceLocation.addItem("OmniPod");
}
if (selectedLocation > -1 && choiceLocation.getModel().getSize() > selectedLocation) {
choiceLocation.setSelectedIndex(selectedLocation);
} else {
choiceLocation.setSelectedIndex(0);
}
choiceLocation.setEnabled(true);
} else {
choiceLocation.removeAllItems();
choiceLocation.setEnabled(false);
}
filterTasks();
if (selectedRow != -1 && taskTable.getRowCount() > 0) {
if (taskTable.getRowCount() <= selectedRow) {
selectedRow = taskTable.getRowCount() - 1;
}
taskTable.setRowSelectionInterval(selectedRow,
selectedRow);
}
if (selectedLocation != -1 && choiceLocation.getItemCount() > 0) {
if (selectedUnit == null || getSelectedServicedUnit() == null
|| !selectedUnit.equals(getSelectedServicedUnit())
|| selectedLocation >= choiceLocation.getItemCount()) {
selectedLocation = 0;
}
choiceLocation.setSelectedIndex(selectedLocation);
}
}
public void refreshTechsList() {
int selected = techTable.getSelectedRow();
ArrayList<Person> techs = getCampaign().getTechs(true, null);
techsModel.setData(techs);
if ((selected > -1) && (selected < techs.size())) {
techTable.setRowSelectionInterval(selected, selected);
}
String astechString = "<html><b>Astech Pool Minutes:</> " + getCampaign().getAstechPoolMinutes();
if (getCampaign().isOvertimeAllowed()) {
astechString += " [" + getCampaign().getAstechPoolOvertime() + " overtime]";
}
astechString += " (" + getCampaign().getNumberAstechs() + " Astechs)</html>";
astechPoolLabel.setText(astechString); // NOI18N
// If requested, switch to top entry
if(getCampaign().getCampaignOptions().useResetToFirstTech() && techTable.getRowCount() > 0) {
techTable.setRowSelectionInterval(0, 0);
} else {
// Or get the selected tech back
for (int i = 0; i < techTable.getRowCount(); i++) {
Person p = techsModel
.getTechAt(techTable.convertRowIndexToModel(i));
if (selectedTech.getId().equals(p.getId())) {
techTable.setRowSelectionInterval(i, i);
break;
}
}
}
}
public void refreshPartsAcquisition() {
refreshPartsAcquisitionService(true);
}
public void refreshPartsAcquisitionService(boolean rebuildPartsList) {
if (rebuildPartsList) {
PartsAcquisitionService.buildPartsList(getCampaign());
}
btnAcquisitions.firePropertyChange("counts", -1, 0);
}
private ActionScheduler servicedUnitListScheduler = new ActionScheduler(this::refreshServicedUnitList);
private ActionScheduler techsScheduler = new ActionScheduler(this::refreshTechsList);
private ActionScheduler taskScheduler = new ActionScheduler(this::refreshTaskList);
private ActionScheduler acquireScheduler = new ActionScheduler(this::refreshPartsAcquisition);
@Subscribe
public void handle(DeploymentChangedEvent ev) {
servicedUnitListScheduler.schedule();
}
@Subscribe
public void handle(ScenarioResolvedEvent ev) {
servicedUnitListScheduler.schedule();
}
@Subscribe
public void handle(UnitEvent ev) {
servicedUnitListScheduler.schedule();
}
@Subscribe
public void handle(RepairStatusChangedEvent ev) {
servicedUnitListScheduler.schedule();
}
@Subscribe
public void handle(PersonEvent ev) {
techsScheduler.schedule();
}
@Subscribe
public void handle(PartEvent ev) {
if (ev.getPart().getUnit() == null) {
acquireScheduler.schedule();
taskScheduler.schedule();
} else {
servicedUnitListScheduler.schedule();
}
}
@Subscribe
public void handle(AcquisitionEvent ev) {
acquireScheduler.schedule();
taskScheduler.schedule();
}
@Subscribe
public void handle(ProcurementEvent ev) {
filterTasks();
acquireScheduler.schedule();
}
@Subscribe
public void handle(PartWorkEvent ev) {
if (ev.getPartWork().getUnit() == null) {
acquireScheduler.schedule();
taskScheduler.schedule();
} else {
servicedUnitListScheduler.schedule();
}
techsScheduler.schedule();
}
@Subscribe
public void handle(OvertimeModeEvent ev) {
filterTechs();
}
@Subscribe
public void handle(AstechPoolChangedEvent ev) {
filterTechs();
}
}