/*
* CampaignGUI.java
*
* Copyright (c) 2009 Jay Lawson <jaylawson39 at yahoo.com>. 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.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.text.NumberFormat;
import java.util.Calendar;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.List;
import java.util.ResourceBundle;
import java.util.UUID;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JToggleButton;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.filechooser.FileFilter;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import chat.ChatClient;
import megamek.client.RandomNameGenerator;
import megamek.client.RandomUnitGenerator;
import megamek.client.ui.swing.GameOptionsDialog;
import megamek.common.Crew;
import megamek.common.Dropship;
import megamek.common.Entity;
import megamek.common.Jumpship;
import megamek.common.MULParser;
import megamek.common.TechConstants;
import megamek.common.event.Subscribe;
import megamek.common.loaders.EntityLoadingException;
import megamek.common.options.PilotOptions;
import megamek.common.util.EncodeControl;
import mekhq.IconPackage;
import mekhq.MekHQ;
import mekhq.Utilities;
import mekhq.Version;
import mekhq.campaign.Campaign;
import mekhq.campaign.CampaignOptions;
import mekhq.campaign.RandomSkillPreferences;
import mekhq.campaign.event.AssetEvent;
import mekhq.campaign.event.AstechPoolChangedEvent;
import mekhq.campaign.event.DeploymentChangedEvent;
import mekhq.campaign.event.LoanEvent;
import mekhq.campaign.event.MedicPoolChangedEvent;
import mekhq.campaign.event.MissionEvent;
import mekhq.campaign.event.OptionsChangedEvent;
import mekhq.campaign.event.OrganizationChangedEvent;
import mekhq.campaign.event.PersonEvent;
import mekhq.campaign.event.ReportEvent;
import mekhq.campaign.event.TransactionEvent;
import mekhq.campaign.event.UnitEvent;
import mekhq.campaign.force.Force;
import mekhq.campaign.mission.AtBContract;
import mekhq.campaign.mission.AtBScenario;
import mekhq.campaign.mission.Mission;
import mekhq.campaign.mission.Scenario;
import mekhq.campaign.parts.Part;
import mekhq.campaign.parts.Refit;
import mekhq.campaign.personnel.Person;
import mekhq.campaign.personnel.SkillType;
import mekhq.campaign.personnel.SpecialAbility;
import mekhq.campaign.report.CargoReport;
import mekhq.campaign.report.HangarReport;
import mekhq.campaign.report.PersonnelReport;
import mekhq.campaign.report.RatingReport;
import mekhq.campaign.report.Report;
import mekhq.campaign.report.TransportReport;
import mekhq.campaign.unit.Unit;
import mekhq.campaign.universe.NewsItem;
import mekhq.campaign.universe.RandomFactionGenerator;
import mekhq.gui.dialog.AdvanceDaysDialog;
import mekhq.gui.dialog.BatchXPDialog;
import mekhq.gui.dialog.BloodnameDialog;
import mekhq.gui.dialog.CampaignOptionsDialog;
import mekhq.gui.dialog.ContractMarketDialog;
import mekhq.gui.dialog.DailyReportLogDialog;
import mekhq.gui.dialog.DataLoadingDialog;
import mekhq.gui.dialog.GMToolsDialog;
import mekhq.gui.dialog.HireBulkPersonnelDialog;
import mekhq.gui.dialog.MaintenanceReportDialog;
import mekhq.gui.dialog.MekHQAboutBox;
import mekhq.gui.dialog.MercRosterDialog;
import mekhq.gui.dialog.NewRecruitDialog;
import mekhq.gui.dialog.NewsReportDialog;
import mekhq.gui.dialog.PartsStoreDialog;
import mekhq.gui.dialog.PersonnelMarketDialog;
import mekhq.gui.dialog.PopupValueChoiceDialog;
import mekhq.gui.dialog.RefitNameDialog;
import mekhq.gui.dialog.ReportDialog;
import mekhq.gui.dialog.RetirementDefectionDialog;
import mekhq.gui.dialog.ShipSearchDialog;
import mekhq.gui.dialog.UnitMarketDialog;
import mekhq.gui.dialog.UnitSelectorDialog;
import mekhq.gui.model.PartsTableModel;
/**
* The application's main frame.
*/
public class CampaignGUI extends JPanel {
private static final long serialVersionUID = -687162569841072579L;
public static final int MAX_START_WIDTH = 1400;
public static final int MAX_START_HEIGHT = 900;
private JFrame frame;
private MekHQ app;
private ResourceBundle resourceMap;
/* for the main panel */
private JSplitPane mainPanel;
private JTabbedPane tabMain;
private DailyReportLogPanel panLog;
/* For the menu bar */
private JMenuBar menuBar;
private JMenu menuThemes;
private JMenuItem miDetachLog;
private JMenuItem miAttachLog;
private JMenuItem miContractMarket;
private JMenuItem miUnitMarket;
private JMenuItem miShipSearch;
private JMenuItem miRetirementDefectionDialog;
private JCheckBoxMenuItem miShowOverview;
private EnumMap<GuiTabType,CampaignGuiTab> standardTabs;
/* Components for the status panel */
private JPanel statusPanel;
private JLabel lblLocation;
private JLabel lblRating;
private JLabel lblFunds;
private JLabel lblTempAstechs;
private JLabel lblTempMedics;
@SuppressWarnings("unused")
private JLabel lblCargo; // FIXME: Re-add this in an optionized form
/* for the top button panel */
private JPanel btnPanel;
private JToggleButton btnGMMode;
private JToggleButton btnOvertime;
private JButton btnAdvanceDay;
ReportHyperlinkListener reportHLL;
private DailyReportLogDialog logDialog;
private AdvanceDaysDialog advanceDaysDialog;
private BloodnameDialog bloodnameDialog;
public CampaignGUI(MekHQ app) {
this.app = app;
reportHLL = new ReportHyperlinkListener(this);
standardTabs = new EnumMap<>(GuiTabType.class);
initComponents();
MekHQ.registerHandler(this);
}
public void showAboutBox() {
MekHQAboutBox aboutBox = new MekHQAboutBox(getFrame());
aboutBox.setLocationRelativeTo(getFrame());
aboutBox.setVisible(true);
}
private void showDailyReportDialog() {
mainPanel.remove(panLog);
miDetachLog.setEnabled(false);
miAttachLog.setEnabled(true);
mainPanel.setOneTouchExpandable(false);
logDialog.setVisible(true);
refreshReport();
this.revalidate();
this.repaint();
}
public void hideDailyReportDialog() {
logDialog.setVisible(false);
mainPanel.setRightComponent(panLog);
mainPanel.setOneTouchExpandable(true);
miDetachLog.setEnabled(true);
miAttachLog.setEnabled(false);
this.revalidate();
this.repaint();
}
public void showRetirementDefectionDialog() {
/*
* if there are unresolved personnel, show the results view; otherwise,
* present the retirement view to give the player a chance to follow a
* custom schedule
*/
RetirementDefectionDialog rdd = new RetirementDefectionDialog(this,
null, getCampaign().getRetirementDefectionTracker()
.getRetirees().size() == 0);
rdd.setVisible(true);
if (!rdd.wasAborted()) {
getCampaign().applyRetirement(rdd.totalPayout(),
rdd.getUnitAssignments());
}
}
public void toggleOverviewTab() {
boolean show = !hasTab(GuiTabType.OVERVIEW);
miShowOverview.setSelected(show);
showOverviewTab(show);
}
public void showOverviewTab(boolean show) {
if (show) {
addStandardTab(GuiTabType.OVERVIEW);
} else {
removeStandardTab(GuiTabType.OVERVIEW);
}
}
public void showGMToolsDialog() {
GMToolsDialog gmTools = new GMToolsDialog(getFrame(), this);
gmTools.setVisible(true);
}
public void showAdvanceDaysDialog() {
advanceDaysDialog = new AdvanceDaysDialog(getFrame(), this, reportHLL);
advanceDaysDialog.setVisible(true);
advanceDaysDialog.dispose();
}
public void randomizeAllBloodnames() {
for (Person p : getCampaign().getPersonnel()) {
if (!p.isClanner()) {
continue;
}
getCampaign().checkBloodnameAdd(p, p.getPrimaryRole());
getCampaign().personUpdated(p);
}
}
public void spendBatchXP() {
BatchXPDialog batchXPDialog = new BatchXPDialog(getFrame(), getCampaign());
batchXPDialog.setVisible(true);
if(batchXPDialog.hasDataChanged()) {
refreshReport();
}
}
public void showBloodnameDialog() {
bloodnameDialog.setFaction(getCampaign().getFactionCode());
bloodnameDialog.setYear(getCampaign().getCalendar().get(
java.util.Calendar.YEAR));
bloodnameDialog.setVisible(true);
}
private void initComponents() {
resourceMap = ResourceBundle.getBundle("mekhq.resources.CampaignGUI", new EncodeControl()); //$NON-NLS-1$
frame = new JFrame("MekHQ"); //$NON-NLS-1$
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
tabMain = new JTabbedPane();
tabMain.setToolTipText(resourceMap.getString("tabMain.toolTipText")); // NOI18N
tabMain.setMinimumSize(new java.awt.Dimension(600, 200));
tabMain.setPreferredSize(new java.awt.Dimension(900, 300));
addStandardTab(GuiTabType.TOE);
addStandardTab(GuiTabType.BRIEFING);
addStandardTab(GuiTabType.MAP);
addStandardTab(GuiTabType.PERSONNEL);
addStandardTab(GuiTabType.HANGAR);
addStandardTab(GuiTabType.WAREHOUSE);
addStandardTab(GuiTabType.REPAIR);
addStandardTab(GuiTabType.INFIRMARY);
addStandardTab(GuiTabType.MEKLAB);
addStandardTab(GuiTabType.FINANCES);
addStandardTab(GuiTabType.OVERVIEW);
initMain();
initTopButtons();
initStatusBar();
setLayout(new BorderLayout());
add(mainPanel, BorderLayout.CENTER);
add(btnPanel, BorderLayout.PAGE_START);
add(statusPanel, BorderLayout.PAGE_END);
standardTabs.values().forEach(t -> t.refreshAll());
refreshCalendar();
initReport();
refreshFunds();
refreshRating();
refreshLocation();
refreshTempAstechs();
refreshTempMedics();
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
frame.setSize(Math.min(MAX_START_WIDTH, dim.width),
Math.min(MAX_START_HEIGHT, dim.height));
// Determine the new location of the window
int w = frame.getSize().width;
int h = frame.getSize().height;
int x = (dim.width - w) / 2;
int y = (dim.height - h) / 2;
// Move the window
frame.setLocation(x, y);
initMenu();
frame.setJMenuBar(menuBar);
frame.getContentPane().setLayout(new BorderLayout());
frame.getContentPane().add(this, BorderLayout.CENTER);
frame.validate();
if (isMacOSX()) {
enableFullScreenMode(frame);
}
frame.setVisible(true);
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
getApplication().exit();
}
});
mainPanel.setDividerLocation(0.75);
}
public CampaignGuiTab getTab(GuiTabType tabType) {
return standardTabs.get(tabType);
}
public boolean hasTab(GuiTabType tabType) {
return standardTabs.containsKey(tabType);
}
/**
* Adds one of the built-in tabs to the gui, if it is not already present.
*
* @param tab The type of tab to add
*/
public void addStandardTab(GuiTabType tab) {
if (tab.equals(GuiTabType.CUSTOM)) {
throw new IllegalArgumentException("Attempted to add custom tab as standard");
}
if (!standardTabs.containsKey(tab)) {
CampaignGuiTab t = tab.createTab(this);
standardTabs.put(tab, t);
int index = tabMain.getTabCount();
for (int i = 0; i < tabMain.getTabCount(); i++) {
if (((CampaignGuiTab)tabMain.getComponentAt(i)).tabType().getDefaultPos() > tab.getDefaultPos()) {
index = i;
break;
}
}
tabMain.insertTab(t.getTabName(), null, t, null, index);
}
}
/**
* Adds a custom tab to the gui at the end
*
* @param tab The tab to add
*/
public void addCustomTab(CampaignGuiTab tab) {
if (tabMain.indexOfComponent(tab) >= 0) {
return;
}
if (tab.tabType().equals(GuiTabType.CUSTOM)) {
tabMain.addTab(tab.getTabName(), tab);
} else {
addStandardTab(tab.tabType());
}
}
/**
* Adds a custom tab to the gui in the specified position. If <code>tab</code> is a built-in
* type it will be placed in its normal position if it does not already exist.
*
* @param tab The tab to add
* @param index The position to place the tab
*/
public void insertCustomTab(CampaignGuiTab tab, int index) {
if (tabMain.indexOfComponent(tab) >= 0) {
return;
}
if (tab.tabType().equals(GuiTabType.CUSTOM)) {
tabMain.insertTab(tab.getTabName(), null, tab, null, Math.min(index, tabMain.getTabCount()));
} else {
addStandardTab(tab.tabType());
}
}
/**
* Adds a custom tab to the gui positioned after one of the built-in tabs
*
* @param tab The tab to add
* @param stdTab The build-in tab after which to place the new one
*/
public void insertCustomTabAfter(CampaignGuiTab tab, GuiTabType stdTab) {
if (tabMain.indexOfComponent(tab) >= 0) {
return;
}
if (tab.tabType().equals(GuiTabType.CUSTOM)) {
int index = tabMain.indexOfTab(stdTab.getTabName());
if (index < 0) {
if (stdTab.getDefaultPos() == 0) {
index = tabMain.getTabCount();
} else {
for (int i = stdTab.getDefaultPos() - 1; i >= 0; i--) {
index = tabMain.indexOfTab(GuiTabType.values()[i].getTabName());
if (index >= 0) {
break;
}
}
}
}
insertCustomTab(tab, index);
} else {
addStandardTab(tab.tabType());
}
}
/**
* Adds a custom tab to the gui positioned before one of the built-in tabs
*
* @param tab The tab to add
* @param stdTab The build-in tab before which to place the new one
*/
public void insertCustomTabBefore(CampaignGuiTab tab, GuiTabType stdTab) {
if (tabMain.indexOfComponent(tab) >= 0) {
return;
}
if (tab.tabType().equals(GuiTabType.CUSTOM)) {
int index = tabMain.indexOfTab(stdTab.getTabName());
if (index < 0) {
if (stdTab.getDefaultPos() == GuiTabType.values().length - 1) {
index = tabMain.getTabCount();
} else {
for (int i = stdTab.getDefaultPos() + 1; i >= GuiTabType.values().length; i++) {
index = tabMain.indexOfTab(GuiTabType.values()[i].getTabName());
if (index >= 0) {
break;
}
}
}
}
insertCustomTab(tab, Math.max(0, index - 1));
} else {
addStandardTab(tab.tabType());
}
}
/**
* Removes one of the built-in tabs from the gui.
*
* @param tabType The tab to remove
*/
public void removeStandardTab(GuiTabType tabType) {
CampaignGuiTab tab = standardTabs.get(tabType);
if (tab != null) {
MekHQ.unregisterHandler(tab);
removeTab(tab);
}
}
/**
* Removes a tab from the gui.
*
* @param tab The tab to remove
*/
public void removeTab(CampaignGuiTab tab) {
tab.disposeTab();
removeTab(tab.getTabName());
}
/**
* Removes a tab from the gui.
*
* @param tabName The name of the tab to remove
*/
public void removeTab(String tabName) {
int index = tabMain.indexOfTab(tabName);
if (index >= 0) {
CampaignGuiTab tab = (CampaignGuiTab)tabMain.getComponentAt(index);
if (standardTabs.containsKey(tab.tabType())) {
standardTabs.remove(tab.tabType());
}
tabMain.removeTabAt(index);
}
}
private void initMenu() {
menuBar = new JMenuBar();
/* File Menu */
JMenu menuFile = new JMenu(resourceMap.getString("fileMenu.text")); // NOI18N
JMenuItem menuLoad = new JMenuItem(
resourceMap.getString("menuLoad.text")); // NOI18N
menuLoad.addActionListener(new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
menuLoadXmlActionPerformed(evt);
}
});
menuFile.add(menuLoad);
JMenuItem menuSave = new JMenuItem(
resourceMap.getString("menuSave.text")); // NOI18N
menuSave.addActionListener(new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
menuSaveXmlActionPerformed(evt);
}
});
menuFile.add(menuSave);
JMenu menuImport = new JMenu(resourceMap.getString("menuImport.text")); // NOI18N
JMenu menuExport = new JMenu(resourceMap.getString("menuExport.text")); // NOI18N
/*
* TODO: Implement these as "Export All" versions
*
* miExportPerson.setText(resourceMap.getString("miExportPerson.text"));
* // NOI18N miExportPerson.addActionListener(new ActionListener() {
* public void actionPerformed(java.awt.event.ActionEvent evt) {
* miExportPersonActionPerformed(evt); } });
* menuExport.add(miExportPerson);
*
* miExportParts.setText(resourceMap.getString("miExportParts.text"));
* // NOI18N miExportParts.addActionListener(new ActionListener() {
* public void actionPerformed(java.awt.event.ActionEvent evt) {
* miExportPartsActionPerformed(evt); } });
* menuExport.add(miExportParts);
*/
JMenuItem miExportOptions = new JMenuItem(
resourceMap.getString("miExportOptions.text")); // NOI18N
miExportOptions.addActionListener(new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
miExportOptionsActionPerformed(evt);
}
});
menuExport.add(miExportOptions);
JMenuItem miExportPersonCSV = new JMenuItem(
resourceMap.getString("miExportPersonCSV.text")); // NOI18N
miExportPersonCSV.addActionListener(ev -> {
if (getTab(GuiTabType.PERSONNEL) != null) {
exportTable(((PersonnelTab)getTab(GuiTabType.PERSONNEL)).getPersonnelTable(),
getCampaign().getName()
+ getCampaign().getShortDateAsString()
+ "_ExportedPersonnel" + ".csv");
}
});
menuExport.add(miExportPersonCSV);
JMenuItem miExportUnitCSV = new JMenuItem(
resourceMap.getString("miExportUnitCSV.text")); // NOI18N
miExportUnitCSV.addActionListener(ev -> {
if (getTab(GuiTabType.HANGAR) != null) {
exportTable(((HangarTab)getTab(GuiTabType.HANGAR)).getUnitTable(),
getCampaign().getName()
+ getCampaign().getShortDateAsString()
+ "_ExportedUnit" + ".csv");
}
});
menuExport.add(miExportUnitCSV);
JMenuItem miImportOptions = new JMenuItem(
resourceMap.getString("miImportOptions.text")); // NOI18N
miImportOptions.addActionListener(new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
miImportOptionsActionPerformed(evt);
}
});
menuImport.add(miImportOptions);
JMenuItem miImportPerson = new JMenuItem(
resourceMap.getString("miImportPerson.text")); // NOI18N
miImportPerson.addActionListener(new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
miImportPersonActionPerformed(evt);
}
});
menuImport.add(miImportPerson);
JMenuItem miImportParts = new JMenuItem(
resourceMap.getString("miImportParts.text")); // NOI18N
miImportParts.addActionListener(new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
miImportPartsActionPerformed(evt);
}
});
menuImport.add(miImportParts);
JMenuItem miLoadForces = new JMenuItem(
resourceMap.getString("miLoadForces.text")); // NOI18N
miLoadForces.addActionListener(new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
miLoadForcesActionPerformed(evt);
}
});
// miLoadForces.setEnabled(false);
menuImport.add(miLoadForces);
menuFile.add(menuImport);
menuFile.add(menuExport);
JMenuItem miMercRoster = new JMenuItem(
resourceMap.getString("miMercRoster.text")); // NOI18N
miMercRoster.addActionListener(new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
showMercRosterDialog();
}
});
menuFile.add(miMercRoster);
JMenuItem menuOptions = new JMenuItem(
resourceMap.getString("menuOptions.text")); // NOI18N
menuOptions.addActionListener(new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
menuOptionsActionPerformed(evt);
}
});
menuFile.add(menuOptions);
JMenuItem menuOptionsMM = new JMenuItem(
resourceMap.getString("menuOptionsMM.text")); // NOI18N
menuOptionsMM.addActionListener(new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
menuOptionsMMActionPerformed(evt);
}
});
menuFile.add(menuOptionsMM);
menuThemes = new JMenu("Themes");
refreshThemeChoices();
menuFile.add(menuThemes);
JMenuItem menuExitItem = new JMenuItem("Exit");
menuExitItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
getApplication().exit();
}
});
menuFile.add(menuExitItem);
menuBar.add(menuFile);
JMenu menuMarket = new JMenu(resourceMap.getString("menuMarket.text")); // NOI18N
// Personnel Market
JMenuItem miPersonnelMarket = new JMenuItem("Personnel Market");
miPersonnelMarket.addActionListener(new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
hirePersonMarket();
}
});
menuMarket.add(miPersonnelMarket);
// Contract Market
miContractMarket = new JMenuItem("Contract Market...");
miContractMarket.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
showContractMarket();
}
});
menuMarket.add(miContractMarket);
miContractMarket.setVisible(getCampaign().getCampaignOptions()
.getUseAtB());
miUnitMarket = new JMenuItem("Unit Market...");
miUnitMarket.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
showUnitMarket();
}
});
menuMarket.add(miUnitMarket);
miUnitMarket.setVisible(getCampaign().getCampaignOptions().getUseAtB());
miShipSearch = new JMenuItem("Ship Search...");
miShipSearch.addActionListener(ev -> showShipSearch());
menuMarket.add(miShipSearch);
miShipSearch.setVisible(getCampaign().getCampaignOptions().getUseAtB());
JMenuItem miPurchaseUnit = new JMenuItem(
resourceMap.getString("miPurchaseUnit.text")); // NOI18N
miPurchaseUnit.addActionListener(new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
miPurchaseUnitActionPerformed(evt);
}
});
menuMarket.add(miPurchaseUnit);
JMenuItem miBuyParts = new JMenuItem(
resourceMap.getString("miBuyParts.text")); // NOI18N
miBuyParts.addActionListener(new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
buyParts();
}
});
menuMarket.add(miBuyParts);
JMenuItem miHireBulk = new JMenuItem("Hire Personnel in Bulk");
miHireBulk.addActionListener(new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
hireBulkPersonnel();
}
});
menuMarket.add(miHireBulk);
JMenu menuHire = new JMenu(resourceMap.getString("menuHire.text")); // NOI18N
JMenuItem miHire;
for (int i = Person.T_MECHWARRIOR; i < Person.T_NUM; i++) {
miHire = new JMenuItem(Person.getRoleDesc(i, getCampaign()
.getFaction().isClan())); // NOI18N
miHire.setActionCommand(Integer.toString(i));
miHire.addActionListener(new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
hirePerson(evt);
}
});
menuHire.add(miHire);
}
menuMarket.add(menuHire);
JMenu menuAstechPool = new JMenu("Astech Pool");
JMenuItem miHireAstechs = new JMenuItem("Hire Astechs");
miHireAstechs.addActionListener(new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
PopupValueChoiceDialog pvcd = new PopupValueChoiceDialog(
getFrame(), true, "Hire How Many Astechs?", 1, 0, 100);
pvcd.setVisible(true);
if (pvcd.getValue() < 0) {
return;
}
getCampaign().increaseAstechPool(pvcd.getValue());
}
});
menuAstechPool.add(miHireAstechs);
JMenuItem miFireAstechs = new JMenuItem("Release Astechs");
miFireAstechs.addActionListener(new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
PopupValueChoiceDialog pvcd = new PopupValueChoiceDialog(
getFrame(), true, "Release How Many Astechs?", 1, 0,
getCampaign().getAstechPool());
pvcd.setVisible(true);
if (pvcd.getValue() < 0) {
return;
}
getCampaign().decreaseAstechPool(pvcd.getValue());
}
});
menuAstechPool.add(miFireAstechs);
JMenuItem miFullStrengthAstechs = new JMenuItem(
"Bring All Tech Teams to Full Strength");
miFullStrengthAstechs.addActionListener(new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
int need = (getCampaign().getTechs().size() * 6)
- getCampaign().getNumberAstechs();
if (need > 0) {
getCampaign().increaseAstechPool(need);
}
}
});
menuAstechPool.add(miFullStrengthAstechs);
JMenuItem miFireAllAstechs = new JMenuItem(
"Release All Astechs from Pool");
miFireAllAstechs.addActionListener(new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
getCampaign().decreaseAstechPool(getCampaign().getAstechPool());
}
});
menuAstechPool.add(miFireAllAstechs);
menuMarket.add(menuAstechPool);
JMenu menuMedicPool = new JMenu("Medic Pool");
JMenuItem miHireMedics = new JMenuItem("Hire Medics");
miHireMedics.addActionListener(new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
PopupValueChoiceDialog pvcd = new PopupValueChoiceDialog(
getFrame(), true, "Hire How Many Medics?", 1, 0, 100);
pvcd.setVisible(true);
if (pvcd.getValue() < 0) {
return;
}
getCampaign().increaseMedicPool(pvcd.getValue());
}
});
menuMedicPool.add(miHireMedics);
JMenuItem miFireMedics = new JMenuItem("Release Medics");
miFireMedics.addActionListener(new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
PopupValueChoiceDialog pvcd = new PopupValueChoiceDialog(
getFrame(), true, "Release How Many Medics?", 1, 0,
getCampaign().getMedicPool());
pvcd.setVisible(true);
if (pvcd.getValue() < 0) {
return;
}
getCampaign().decreaseMedicPool(pvcd.getValue());
}
});
menuMedicPool.add(miFireMedics);
JMenuItem miFullStrengthMedics = new JMenuItem(
"Bring All Medical Teams to Full Strength");
miFullStrengthMedics.addActionListener(new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
int need = (getCampaign().getDoctors().size() * 4)
- getCampaign().getNumberMedics();
if (need > 0) {
getCampaign().increaseMedicPool(need);
}
}
});
menuMedicPool.add(miFullStrengthMedics);
JMenuItem miFireAllMedics = new JMenuItem(
"Release All Medics from Pool");
miFireAllMedics.addActionListener(new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
getCampaign().decreaseMedicPool(getCampaign().getMedicPool());
}
});
menuMedicPool.add(miFireAllMedics);
menuMarket.add(menuMedicPool);
menuBar.add(menuMarket);
JMenu menuReports = new JMenu(resourceMap.getString("menuReports.text")); // NOI18N
JMenuItem miDragoonsRating = new JMenuItem(
resourceMap.getString("miDragoonsRating.text")); // NOI18N
miDragoonsRating.addActionListener(new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
showReport(new RatingReport(getCampaign()));
}
});
menuReports.add(miDragoonsRating);
JMenuItem miPersonnelReport = new JMenuItem(
resourceMap.getString("miPersonnelReport.text")); // NOI18N
miPersonnelReport.addActionListener(new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
showReport(new PersonnelReport(getCampaign()));
}
});
menuReports.add(miPersonnelReport);
JMenuItem miHangarBreakdown = new JMenuItem(
resourceMap.getString("miHangarBreakdown.text")); // NOI18N
miHangarBreakdown.addActionListener(new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
showReport(new HangarReport(getCampaign()));
}
});
menuReports.add(miHangarBreakdown);
JMenuItem miTransportReport = new JMenuItem(
resourceMap.getString("miTransportReport.text")); // NOI18N
miTransportReport.addActionListener(new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
showReport(new TransportReport(getCampaign()));
}
});
menuReports.add(miTransportReport);
JMenuItem miCargoReport = new JMenuItem(
resourceMap.getString("miCargoReport.text")); // NOI18N
miCargoReport.addActionListener(new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
showReport(new CargoReport(getCampaign()));
}
});
menuReports.add(miCargoReport);
menuBar.add(menuReports);
JMenu menuCommunity = new JMenu(
resourceMap.getString("menuCommunity.text")); // NOI18N
JMenuItem miChat = new JMenuItem(resourceMap.getString("miChat.text")); // NOI18N
miChat.addActionListener(new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
miChatActionPerformed(evt);
}
});
menuCommunity.add(miChat);
// menuBar.add(menuCommunity);
JMenu menuView = new JMenu("View"); // NOI18N
miDetachLog = new JMenuItem("Detach Daily Report Log"); // NOI18N
miDetachLog.addActionListener(new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
showDailyReportDialog();
}
});
menuView.add(miDetachLog);
miAttachLog = new JMenuItem("Attach Daily Report Log"); // NOI18N
miAttachLog.setEnabled(false);
miAttachLog.addActionListener(new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
hideDailyReportDialog();
}
});
menuView.add(miAttachLog);
JMenuItem miBloodnameDialog = new JMenuItem("Show Bloodname Dialog...");
miBloodnameDialog.setEnabled(true);
miBloodnameDialog.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
showBloodnameDialog();
}
});
menuView.add(miBloodnameDialog);
miRetirementDefectionDialog = new JMenuItem(
"Show Retirement/Defection Dialog...");
miRetirementDefectionDialog.setEnabled(true);
miRetirementDefectionDialog.setVisible(getCampaign()
.getCampaignOptions().getUseAtB());
miRetirementDefectionDialog.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
showRetirementDefectionDialog();
}
});
menuView.add(miRetirementDefectionDialog);
miShowOverview = new JCheckBoxMenuItem("Show Overview Tab");
miShowOverview.setSelected(hasTab(GuiTabType.OVERVIEW));
miShowOverview.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
toggleOverviewTab();
}
});
menuView.add(miShowOverview);
menuBar.add(menuView);
JMenu menuManage = new JMenu("Manage Campaign");
menuManage.setName("manageMenu");
JMenuItem miGMToolsDialog = new JMenuItem("Show GM Tools Dialog");
miGMToolsDialog.setEnabled(true);
miGMToolsDialog.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
showGMToolsDialog();
}
});
menuManage.add(miGMToolsDialog);
JMenuItem miAdvanceMultipleDays = new JMenuItem("Advance Multiple Days");
miAdvanceMultipleDays.setEnabled(true);
miAdvanceMultipleDays.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
showAdvanceDaysDialog();
}
});
menuManage.add(miAdvanceMultipleDays);
JMenuItem miBloodnames = new JMenuItem("Randomize Bloodnames All Personnel");
miBloodnames.setEnabled(true);
miBloodnames.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
randomizeAllBloodnames();
}
});
menuManage.add(miBloodnames);
JMenuItem miBatchXP = new JMenuItem("Mass training");
miBatchXP.setEnabled(true);
miBatchXP.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
spendBatchXP();
}
});
menuManage.add(miBatchXP);
menuBar.add(menuManage);
JMenu menuHelp = new JMenu(resourceMap.getString("helpMenu.text")); // NOI18N
menuHelp.setName("helpMenu"); // NOI18N
JMenuItem menuAboutItem = new JMenuItem("aboutMenuItem"); // NOI18N
menuAboutItem.setText("About");
menuAboutItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
showAboutBox();
}
});
menuHelp.add(menuAboutItem);
menuBar.add(menuHelp);
}
private void initMain() {
panLog = new DailyReportLogPanel(reportHLL);
panLog.setMinimumSize(new java.awt.Dimension(150, 100));
logDialog = new DailyReportLogDialog(getFrame(), this, reportHLL);
bloodnameDialog = new BloodnameDialog(getFrame());
mainPanel = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, tabMain, panLog);
mainPanel.setOneTouchExpandable(true);
mainPanel.setResizeWeight(1.0);
}
private void initStatusBar() {
statusPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 20, 4));
lblRating = new JLabel();
lblFunds = new JLabel();
lblTempAstechs = new JLabel();
lblTempMedics = new JLabel();
statusPanel.add(lblRating);
statusPanel.add(lblFunds);
statusPanel.add(lblTempAstechs);
statusPanel.add(lblTempMedics);
}
private void initTopButtons() {
GridBagConstraints gridBagConstraints;
lblLocation = new JLabel(getCampaign().getLocation().getReport(
getCampaign().getCalendar().getTime())); // NOI18N
btnPanel = new JPanel(new GridBagLayout());
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.fill = java.awt.GridBagConstraints.NONE;
gridBagConstraints.weightx = 0.0;
gridBagConstraints.weighty = 0.0;
gridBagConstraints.gridheight = 2;
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
gridBagConstraints.insets = new java.awt.Insets(3, 10, 3, 3);
btnPanel.add(lblLocation, gridBagConstraints);
btnGMMode = new JToggleButton(resourceMap.getString("btnGMMode.text")); // NOI18N
btnGMMode
.setToolTipText(resourceMap.getString("btnGMMode.toolTipText")); // NOI18N
btnGMMode.setSelected(getCampaign().isGM());
btnGMMode.addActionListener(new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnGMModeActionPerformed(evt);
}
});
btnGMMode.setMinimumSize(new Dimension(150, 25));
btnGMMode.setPreferredSize(new Dimension(150, 25));
btnGMMode.setMaximumSize(new Dimension(150, 25));
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 0;
gridBagConstraints.fill = java.awt.GridBagConstraints.NONE;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 0.0;
gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
btnPanel.add(btnGMMode, gridBagConstraints);
btnOvertime = new JToggleButton(
resourceMap.getString("btnOvertime.text")); // NOI18N
btnOvertime.setToolTipText(resourceMap
.getString("btnOvertime.toolTipText")); // NOI18N
btnOvertime.addActionListener(new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnOvertimeActionPerformed(evt);
}
});
btnOvertime.setMinimumSize(new Dimension(150, 25));
btnOvertime.setPreferredSize(new Dimension(150, 25));
btnOvertime.setMaximumSize(new Dimension(150, 25));
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 1;
gridBagConstraints.fill = java.awt.GridBagConstraints.NONE;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 0.0;
gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
btnPanel.add(btnOvertime, gridBagConstraints);
btnAdvanceDay = new JButton(resourceMap.getString("btnAdvanceDay.text")); // NOI18N
btnAdvanceDay.setToolTipText(resourceMap
.getString("btnAdvanceDay.toolTipText")); // NOI18N
btnAdvanceDay.addActionListener(new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
advanceDay();
}
});
btnAdvanceDay.setPreferredSize(new Dimension(250, 50));
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 0;
gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL;
gridBagConstraints.weightx = 0.0;
gridBagConstraints.weighty = 0.0;
gridBagConstraints.gridheight = 2;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST;
gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 15);
btnPanel.add(btnAdvanceDay, gridBagConstraints);
}
private static void enableFullScreenMode(Window window) {
String className = "com.apple.eawt.FullScreenUtilities";
String methodName = "setWindowCanFullScreen";
try {
Class<?> clazz = Class.forName(className);
Method method = clazz.getMethod(methodName, new Class<?>[] {
Window.class, boolean.class });
method.invoke(null, window, true);
} catch (Throwable t) {
System.err.println("Full screen mode is not supported");
t.printStackTrace();
}
}
private static boolean isMacOSX() {
return System.getProperty("os.name").indexOf("Mac OS X") >= 0;
}
private void miChatActionPerformed(ActionEvent evt) {
JDialog chatDialog = new JDialog(getFrame(), "MekHQ Chat", false); //$NON-NLS-1$
ChatClient client = new ChatClient("test", "localhost");
client.listen();
// chatDialog.add(client);
chatDialog.add(new JLabel("Testing"));
chatDialog.setResizable(true);
chatDialog.setVisible(true);
}
private void changeTheme(java.awt.event.ActionEvent evt) {
final String lafClassName = evt.getActionCommand();
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(lafClassName);
SwingUtilities.updateComponentTreeUI(frame);
refreshThemeChoices();
} catch (Exception exception) {
JOptionPane.showMessageDialog(frame,
"Can't change look and feel", "Invalid PLAF",
JOptionPane.ERROR_MESSAGE);
}
}
};
SwingUtilities.invokeLater(runnable);
}
private void refreshThemeChoices() {
menuThemes.removeAll();
JCheckBoxMenuItem miPlaf;
for (LookAndFeelInfo plaf : UIManager.getInstalledLookAndFeels()) {
miPlaf = new JCheckBoxMenuItem(plaf.getName());
if (plaf.getName().equalsIgnoreCase(
UIManager.getLookAndFeel().getName())) {
miPlaf.setSelected(true);
}
menuThemes.add(miPlaf);
miPlaf.setActionCommand(plaf.getClassName());
miPlaf.addActionListener(new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
changeTheme(evt);
}
});
}
}
//TODO: trigger from event
public void filterTasks() {
if (getTab(GuiTabType.REPAIR) != null) {
((RepairTab)getTab(GuiTabType.REPAIR)).filterTasks();
}
}
public void focusOnUnit(UUID id) {
HangarTab ht = (HangarTab)getTab(GuiTabType.HANGAR);
if (null == id || null == ht) {
return;
}
if (mainPanel.getDividerLocation() < 700) {
if (mainPanel.getLastDividerLocation() > 700) {
mainPanel
.setDividerLocation(mainPanel.getLastDividerLocation());
} else {
mainPanel.resetToPreferredSizes();
}
}
ht.focusOnUnit(id);
tabMain.setSelectedIndex(getTabIndexByName(resourceMap
.getString("panHangar.TabConstraints.tabTitle")));
}
public void focusOnUnitInRepairBay(UUID id) {
if (null == id) {
return;
}
if (getTab(GuiTabType.REPAIR) != null) {
if (mainPanel.getDividerLocation() < 700) {
if (mainPanel.getLastDividerLocation() > 700) {
mainPanel
.setDividerLocation(mainPanel.getLastDividerLocation());
} else {
mainPanel.resetToPreferredSizes();
}
}
((RepairTab)getTab(GuiTabType.REPAIR)).focusOnUnit(id);
tabMain.setSelectedComponent(getTab(GuiTabType.REPAIR));
}
}
public void focusOnPerson(UUID id) {
if (null == id) {
return;
}
PersonnelTab pt = (PersonnelTab)getTab(GuiTabType.PERSONNEL);
if (pt == null) {
return;
}
if (mainPanel.getDividerLocation() < 700) {
if (mainPanel.getLastDividerLocation() > 700) {
mainPanel
.setDividerLocation(mainPanel.getLastDividerLocation());
} else {
mainPanel.resetToPreferredSizes();
}
}
pt.focusOnPerson(id);
tabMain.setSelectedComponent(pt);
}
public void showNews(int id) {
NewsItem news = getCampaign().getNews().getNewsItem(id);
if (null != news) {
NewsReportDialog nrd = new NewsReportDialog(frame, news);
nrd.setVisible(true);
}
}
private void advanceDay() {
// first check for overdue loan payments - dont allow advancement until
// these are addressed
if (getCampaign().checkOverDueLoans()) {
refreshFunds();
refreshReport();
return;
}
if (getCampaign().checkRetirementDefections()) {
showRetirementDefectionDialog();
return;
}
if (getCampaign().checkYearlyRetirements()) {
showRetirementDefectionDialog();
return;
}
if (nagShortMaintenance()) {
return;
}
if (getCampaign().getCampaignOptions().getUseAtB()) {
if (nagShortDeployments()) {
return;
}
if (nagOutstandingScenarios()) {
return;
}
}
if(!getCampaign().newDay()) {
return;
}
refreshCalendar();
refreshLocation();
initReport();
refreshFunds();
refreshAllTabs();
}// GEN-LAST:event_btnAdvanceDayActionPerformed
public boolean nagShortMaintenance() {
if (!getCampaign().getCampaignOptions().checkMaintenance()) {
return false;
}
Vector<Unit> notMaintained = new Vector<Unit>();
int totalAstechMinutesNeeded = 0;
for (Unit u : getCampaign().getUnits()) {
if (u.requiresMaintenance() && null == u.getTech()) {
notMaintained.add(u);
} else {
// only add astech minutes for non-crewed units
if (null == u.getEngineer()) {
totalAstechMinutesNeeded += (u.getMaintenanceTime() * 6);
}
}
}
if (notMaintained.size() > 0) {
if (JOptionPane.YES_OPTION != JOptionPane
.showConfirmDialog(
null,
"You have unmaintained units. Do you really wish to advance the day?",
"Unmaintained Units", JOptionPane.YES_NO_OPTION)) {
return true;
}
}
int minutesAvail = getCampaign().getPossibleAstechPoolMinutes();
if (getCampaign().isOvertimeAllowed()) {
minutesAvail += getCampaign().getPossibleAstechPoolOvertime();
}
if (minutesAvail < totalAstechMinutesNeeded) {
int needed = (int) Math
.ceil((totalAstechMinutesNeeded - minutesAvail) / 480D);
if (JOptionPane.YES_OPTION != JOptionPane.showConfirmDialog(null,
"You do not have enough astechs to provide for full maintenance. You need "
+ needed
+ " more astech(s). Do you wish to proceed?",
"Astech shortage", JOptionPane.YES_NO_OPTION)) {
return true;
}
}
return false;
}
public boolean nagShortDeployments() {
if (getCampaign().getCalendar().get(Calendar.DAY_OF_WEEK) != Calendar.SUNDAY) {
return false;
}
for (Mission m : getCampaign().getMissions()) {
if (!m.isActive() || !(m instanceof AtBContract)
|| !getCampaign().getLocation().isOnPlanet()) {
continue;
}
if (getCampaign().getDeploymentDeficit((AtBContract) m) > 0) {
return 0 != JOptionPane
.showConfirmDialog(
null,
"You have not met the deployment levels required by contract. Do your really wish to advance the day?",
"Unmet deployment requirements",
JOptionPane.YES_NO_OPTION);
}
}
return false;
}
public boolean nagOutstandingScenarios() {
for (Mission m : getCampaign().getMissions()) {
if (!m.isActive() || !(m instanceof AtBContract)) {
continue;
}
for (Scenario s : m.getScenarios()) {
if (!s.isCurrent() || !(s instanceof AtBScenario)) {
continue;
}
if (getCampaign().getDate().equals(s.getDate())) {
return 0 != JOptionPane
.showConfirmDialog(
null,
"You have a pending battle. Failure to deploy will result in a defeat and a minor contract breach. Do your really wish to advance the day?",
"Pending battle", JOptionPane.YES_NO_OPTION);
}
}
}
return false;
}
private void hirePerson(java.awt.event.ActionEvent evt) {
int type = Integer.parseInt(evt.getActionCommand());
NewRecruitDialog npd = new NewRecruitDialog(this, true,
getCampaign().newPerson(type));
npd.setVisible(true);
}
public void hirePersonMarket() {
PersonnelMarketDialog pmd = new PersonnelMarketDialog(getFrame(), this,
getCampaign(), getIconPackage().getPortraits());
pmd.setVisible(true);
}
private void hireBulkPersonnel() {
HireBulkPersonnelDialog hbpd = new HireBulkPersonnelDialog(getFrame(),
true, getCampaign());
hbpd.setVisible(true);
}
public void showContractMarket() {
ContractMarketDialog cmd = new ContractMarketDialog(getFrame(), getCampaign());
cmd.setVisible(true);
}
public void showUnitMarket() {
UnitMarketDialog umd = new UnitMarketDialog(getFrame(), getCampaign());
umd.setVisible(true);
}
public void showShipSearch() {
ShipSearchDialog ssd = new ShipSearchDialog(getFrame(), this);
ssd.setVisible(true);
}
private void menuSaveXmlActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_menuSaveActionPerformed
MekHQ.logMessage("Saving campaign...");
// Choose a file...
File file = selectSaveCampaignFile();
if (file == null) {
// I want a file, y'know!
return;
}
String path = file.getPath();
if (!path.endsWith(".cpnx")) {
path += ".cpnx";
file = new File(path);
}
// check for existing file and make a back-up if found
String path2 = path + "_backup";
File backupFile = new File(path2);
if (file.exists()) {
Utilities.copyfile(file, backupFile);
}
// Then save it out to that file.
FileOutputStream fos = null;
PrintWriter pw = null;
try {
fos = new FileOutputStream(file);
pw = new PrintWriter(new OutputStreamWriter(fos, "UTF-8"));
getCampaign().writeToXml(pw);
pw.flush();
pw.close();
fos.close();
// delete the backup file because we didn't need it
if (backupFile.exists()) {
backupFile.delete();
}
MekHQ.logMessage("Campaign saved to " + file);
} catch (Exception ex) {
MekHQ.logError(ex);
JOptionPane
.showMessageDialog(
getFrame(),
"Oh no! The program was unable to correctly save your game. We know this\n"
+ "is annoying and apologize. Please help us out and submit a bug with the\n"
+ "mekhqlog.txt file from this game so we can prevent this from happening in\n"
+ "the future.", "Could not save game",
JOptionPane.ERROR_MESSAGE);
// restore the backup file
file.delete();
if (backupFile.exists()) {
Utilities.copyfile(backupFile, file);
backupFile.delete();
}
}
}
private File selectSaveCampaignFile() {
JFileChooser saveCpgn = new JFileChooser("./campaigns/");
saveCpgn.setDialogTitle("Save Campaign");
saveCpgn.setFileFilter(new CampaignFileFilter());
saveCpgn.setSelectedFile(new File(getCampaign().getName()
+ getCampaign().getShortDateAsString() + ".cpnx")); //$NON-NLS-1$
int returnVal = saveCpgn.showSaveDialog(mainPanel);
if ((returnVal != JFileChooser.APPROVE_OPTION)
|| (saveCpgn.getSelectedFile() == null)) {
// I want a file, y'know!
return null;
}
File file = saveCpgn.getSelectedFile();
return file;
}
private void menuLoadXmlActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_menuLoadActionPerformed
File f = selectLoadCampaignFile();
if (null == f) {
return;
}
boolean hadAtB = getCampaign().getCampaignOptions().getUseAtB();
DataLoadingDialog dataLoadingDialog = new DataLoadingDialog(
getApplication(), getFrame(), f);
// TODO: does this effectively deal with memory management issues?
dataLoadingDialog.setVisible(true);
if (hadAtB && !getCampaign().getCampaignOptions().getUseAtB()) {
RandomFactionGenerator.getInstance().dispose();
RandomUnitGenerator.getInstance().dispose();
RandomNameGenerator.getInstance().dispose();
}
//Unregister event handlers for CampaignGUI and tabs
for (int i = 0; i < tabMain.getTabCount(); i++) {
if (tabMain.getComponentAt(i) instanceof CampaignGuiTab) {
((CampaignGuiTab)tabMain.getComponentAt(i)).disposeTab();
}
}
MekHQ.unregisterHandler(this);
}
private File selectLoadCampaignFile() {
JFileChooser loadCpgn = new JFileChooser("./campaigns/");
loadCpgn.setDialogTitle("Load Campaign");
loadCpgn.setFileFilter(new CampaignFileFilter());
int returnVal = loadCpgn.showOpenDialog(mainPanel);
if ((returnVal != JFileChooser.APPROVE_OPTION)
|| (loadCpgn.getSelectedFile() == null)) {
// I want a file, y'know!
return null;
}
File file = loadCpgn.getSelectedFile();
return file;
}
private void btnOvertimeActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_btnOvertimeActionPerformed
getCampaign().setOvertime(btnOvertime.isSelected());
}// GEN-LAST:event_btnOvertimeActionPerformed
private void btnGMModeActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_btnGMModeActionPerformed
getCampaign().setGMMode(btnGMMode.isSelected());
}// GEN-LAST:event_btnGMModeActionPerformed
private void menuOptionsActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_menuOptionsActionPerformed
boolean atb = getCampaign().getCampaignOptions().getUseAtB();
boolean staticRATs = getCampaign().getCampaignOptions().useStaticRATs();
CampaignOptionsDialog cod = new CampaignOptionsDialog(getFrame(), true,
getCampaign(), getIconPackage().getCamos());
cod.setVisible(true);
if (atb != getCampaign().getCampaignOptions().getUseAtB()) {
if (getCampaign().getCampaignOptions().getUseAtB()) {
getCampaign().initAtB();
//refresh lance assignment table
MekHQ.triggerEvent(new OrganizationChangedEvent(getCampaign().getForces()));
}
miContractMarket.setVisible(getCampaign().getCampaignOptions()
.getUseAtB());
miUnitMarket.setVisible(getCampaign().getCampaignOptions()
.getUseAtB());
miShipSearch.setVisible(getCampaign().getCampaignOptions()
.getUseAtB());
miRetirementDefectionDialog.setVisible(getCampaign()
.getCampaignOptions().getUseAtB());
if (getCampaign().getCampaignOptions().getUseAtB()) {
while (!RandomFactionGenerator.getInstance().isInitialized()) {
//Sleep for up to one second.
try {
Thread.sleep(50);
} catch (InterruptedException ignore) {
}
}
while (!RandomUnitGenerator.getInstance().isInitialized()) {
//Sleep for up to one second.
try {
Thread.sleep(50);
} catch (InterruptedException ignore) {
}
}
RandomNameGenerator.getInstance();
RandomFactionGenerator.getInstance().updateTables(getCampaign().getDate(),
getCampaign().getCurrentPlanet(), getCampaign().getCampaignOptions());
} else {
RandomFactionGenerator.getInstance().dispose();
RandomUnitGenerator.getInstance().dispose();
RandomNameGenerator.getInstance().dispose();
}
}
if (staticRATs != getCampaign().getCampaignOptions().useStaticRATs()) {
getCampaign().initUnitGenerator();
}
refreshCalendar();
getCampaign().reloadNews();
}// GEN-LAST:event_menuOptionsActionPerformed
private void menuOptionsMMActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_menuOptionsActionPerformed
GameOptionsDialog god = new GameOptionsDialog(getFrame(), getCampaign().getGameOptions(), false);
god.refreshOptions();
god.setEditable(true);
god.setVisible(true);
if (!god.wasCancelled()) {
getCampaign().setGameOptions(god.getOptions());
setCampaignOptionsFromGameOptions();
refreshCalendar();
}
}// GEN-LAST:event_menuOptionsActionPerformed
private void miLoadForcesActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_miLoadForcesActionPerformed
try {
loadListFile(true);
} catch (IOException ex) {
Logger.getLogger(CampaignGUI.class.getName()).log(Level.SEVERE,
null, ex);
}
}// GEN-LAST:event_miLoadForcesActionPerformed
private void miImportPersonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_miImportPersonActionPerformed
try {
loadPersonFile();
} catch (IOException ex) {
Logger.getLogger(CampaignGUI.class.getName()).log(Level.SEVERE,
null, ex);
}
}// GEN-LAST:event_miImportPersonActionPerformed
public void miExportPersonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_miExportPersonActionPerformed
try {
savePersonFile();
} catch (IOException ex) {
Logger.getLogger(CampaignGUI.class.getName()).log(Level.SEVERE,
null, ex);
}
}// GEN-LAST:event_miExportPersonActionPerformed
private void miExportOptionsActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_miExportPersonActionPerformed
try {
saveOptionsFile();
} catch (IOException ex) {
Logger.getLogger(CampaignGUI.class.getName()).log(Level.SEVERE,
null, ex);
}
}// GEN-LAST:event_miExportPersonActionPerformed
private void miImportOptionsActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_miExportPersonActionPerformed
try {
loadOptionsFile();
} catch (IOException ex) {
Logger.getLogger(CampaignGUI.class.getName()).log(Level.SEVERE,
null, ex);
}
}// GEN-LAST:event_miExportPersonActionPerformed
private void miImportPartsActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_miImportPersonActionPerformed
try {
loadPartsFile();
} catch (IOException ex) {
Logger.getLogger(CampaignGUI.class.getName()).log(Level.SEVERE,
null, ex);
}
}// GEN-LAST:event_miImportPersonActionPerformed
public void miExportPartsActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_miExportPersonActionPerformed
try {
savePartsFile();
} catch (IOException ex) {
Logger.getLogger(CampaignGUI.class.getName()).log(Level.SEVERE,
null, ex);
}
}// GEN-LAST:event_miExportPersonActionPerformed
private void miPurchaseUnitActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_miPurchaseUnitActionPerformed
UnitSelectorDialog usd = new UnitSelectorDialog(getFrame(),
getCampaign(), true);
usd.setVisible(true);
}// GEN-LAST:event_miPurchaseUnitActionPerformed
private void buyParts() {
PartsStoreDialog psd = new PartsStoreDialog(true, this);
psd.setVisible(true);
}
private void showMercRosterDialog() {
MercRosterDialog mrd = new MercRosterDialog(getFrame(), true,
getCampaign());
mrd.setVisible(true);
}
public void refitUnit(Refit r, boolean selectModelName) {
if (r.getOriginalEntity() instanceof Dropship
|| r.getOriginalEntity() instanceof Jumpship) {
Person engineer = r.getOriginalUnit().getEngineer();
if (engineer == null) {
JOptionPane
.showMessageDialog(
frame,
"You cannot refit a ship that does not have an engineer. Assign a qualified vessel crew to this unit.",
"No Engineer", JOptionPane.WARNING_MESSAGE);
return;
}
r.setTeamId(engineer.getId());
} else if (getCampaign().getTechs().size() > 0) {
String name;
HashMap<String, Person> techHash = new HashMap<String, Person>();
String skillLvl = "Unknown";
int TimePerDay = 0;
for (Person tech : getCampaign().getTechs()) {
if (getCampaign().isWorkingOnRefit(tech) || tech.isEngineer()) {
continue;
}
if (tech.getSecondaryRole() == Person.T_MECH_TECH || tech.getSecondaryRole() == Person.T_MECHANIC || tech.getSecondaryRole() == Person.T_AERO_TECH) {
TimePerDay = 240 - tech.getMaintenanceTimeUsing();
} else {
TimePerDay = 480 - tech.getMaintenanceTimeUsing();
}
skillLvl = SkillType.getExperienceLevelName(tech.getExperienceLevel(false));
name = tech.getFullName()
+ ", "
+ skillLvl
+ " "
+ tech.getPrimaryRoleDesc()
+ " ("
+ getCampaign().getTargetFor(r, tech).getValueAsString()
+ "+)"
+ ", "
+ tech.getMinutesLeft() + "/" + TimePerDay
+ " minutes";
techHash.put(name, tech);
}
String[] techNames = new String[techHash.keySet().size()];
int i = 0;
for (String n : techHash.keySet()) {
techNames[i] = n;
i++;
}
String s = (String) JOptionPane.showInputDialog(frame,
"Which tech should work on the refit?", "Select Tech",
JOptionPane.PLAIN_MESSAGE, null, techNames, techNames[0]);
if (null == s) {
return;
}
r.setTeamId(techHash.get(s).getId());
} else {
JOptionPane.showMessageDialog(frame,
"You have no techs available to work on this refit.",
"No Techs", JOptionPane.WARNING_MESSAGE);
return;
}
if (selectModelName) {
// select a model name
RefitNameDialog rnd = new RefitNameDialog(frame, true, r);
rnd.setVisible(true);
if (rnd.wasCancelled()) {
// Set the tech team to null since we may want to change it when we re-do the refit
r.setTeamId(null);
return;
}
}
// TODO: allow overtime work?
// check to see if user really wants to do it - give some info on what
// will be done
// TODO: better information
String RefitRefurbish;
if (r.isBeingRefurbished()) {
RefitRefurbish = "Refurbishment is a " + r.getRefitClassName() + " refit and must be done at a factory and costs 10% of the purchase price"
+ ".\n Are you sure you want to refurbish ";
} else {
RefitRefurbish = "This is a " + r.getRefitClassName() + " refit. Are you sure you want to refit ";
}
if (0 != JOptionPane
.showConfirmDialog(null, RefitRefurbish
+ r.getUnit().getName() + "?", "Proceed?",
JOptionPane.YES_NO_OPTION)) {
return;
}
try {
r.begin();
} catch (EntityLoadingException ex) {
JOptionPane
.showMessageDialog(
null,
"For some reason, the unit you are trying to customize cannot be loaded\n and so the customization was cancelled. Please report the bug with a description\nof the unit being customized.",
"Could not customize unit",
JOptionPane.ERROR_MESSAGE);
return;
} catch (IOException e) {
JOptionPane.showMessageDialog(null, e.getMessage(), "IO Exception",
JOptionPane.ERROR_MESSAGE);
return;
}
getCampaign().refit(r);
if (hasTab(GuiTabType.MEKLAB)) {
((MekLabTab)getTab(GuiTabType.MEKLAB)).clearUnit();
}
}
private void showReport(Report report) {
ReportDialog rd = new ReportDialog(getFrame(), report);
rd.setVisible(true);
}
public void showMaintenanceReport(UUID id) {
if (null == id) {
return;
}
Unit u = getCampaign().getUnit(id);
if (null == u) {
return;
}
MaintenanceReportDialog mrd = new MaintenanceReportDialog(getFrame(), u);
mrd.setVisible(true);
}
public UUID selectTech(Unit u, String desc) {
String name;
HashMap<String, Person> techHash = new HashMap<String, Person>();
for (Person tech : getCampaign().getTechs()) {
if (tech.canTech(u.getEntity()) && !tech.isMothballing()) {
name = tech.getFullName()
+ ", "
+ SkillType.getExperienceLevelName(tech
.getSkillForWorkingOn(u).getExperienceLevel())
+ " (" + Math.max(0, (tech.getMinutesLeft() - tech.getMaintenanceTimeUsing()))
+ "min)";
techHash.put(name, tech);
}
}
if (techHash.isEmpty()) {
JOptionPane.showMessageDialog(frame,
"You have no techs available.", "No Techs",
JOptionPane.WARNING_MESSAGE);
return null;
}
String[] techNames = new String[techHash.keySet().size()];
int i = 0;
for (String n : techHash.keySet()) {
techNames[i] = n;
i++;
}
String s = (String) JOptionPane.showInputDialog(frame,
"Which tech should work on " + desc + "?", "Select Tech",
JOptionPane.PLAIN_MESSAGE, null, techNames, techNames[0]);
if (null == s) {
return null;
}
return techHash.get(s).getId();
}
public Part getPartByNameAndDetails(String pnd) {
return getCampaign().getPartsStore().getByNameAndDetails(pnd);
}
protected void loadListFile(boolean allowNewPilots) throws IOException {
JFileChooser loadList = new JFileChooser(".");
loadList.setDialogTitle("Load Units");
loadList.setFileFilter(new FileFilter() {
@Override
public boolean accept(File dir) {
if (dir.isDirectory()) {
return true;
}
return dir.getName().endsWith(".mul");
}
@Override
public String getDescription() {
return "MUL file";
}
});
int returnVal = loadList.showOpenDialog(mainPanel);
if ((returnVal != JFileChooser.APPROVE_OPTION)
|| (loadList.getSelectedFile() == null)) {
// I want a file, y'know!
return;
}
File unitFile = loadList.getSelectedFile();
if (unitFile != null) {
// I need to get the parser myself, because I want to pull both
// entities and pilots from it
// Create an empty parser.
MULParser parser = new MULParser();
// Open up the file.
InputStream listStream = new FileInputStream(unitFile);
// Read a Vector from the file.
try {
parser.parse(listStream);
listStream.close();
} catch (Exception excep) {
excep.printStackTrace(System.err);
// throw new IOException("Unable to read from: " +
// unitFile.getName());
}
// Was there any error in parsing?
if (parser.hasWarningMessage()) {
MekHQ.logMessage(parser.getWarningMessage());
}
// Add the units from the file.
for (Entity entity : parser.getEntities()) {
getCampaign().addUnit(entity, allowNewPilots, 0);
}
// add any ejected pilots
for (Crew pilot : parser.getPilots()) {
if (pilot.isEjected()) {
// getCampaign().addPilot(pilot, PilotPerson.T_MECHWARRIOR,
// false);
}
}
}
}
protected void loadPersonFile() throws IOException {
JFileChooser loadList = new JFileChooser(".");
loadList.setDialogTitle("Load Personnel");
loadList.setFileFilter(new FileFilter() {
@Override
public boolean accept(File dir) {
if (dir.isDirectory()) {
return true;
}
return dir.getName().endsWith(".prsx");
}
@Override
public String getDescription() {
return "Personnel file";
}
});
int returnVal = loadList.showOpenDialog(mainPanel);
if ((returnVal != JFileChooser.APPROVE_OPTION)
|| (loadList.getSelectedFile() == null)) {
// I want a file, y'know!
return;
}
File personnelFile = loadList.getSelectedFile();
if (personnelFile != null) {
// Open up the file.
InputStream fis = new FileInputStream(personnelFile);
MekHQ.logMessage("Starting load of personnel file from XML...");
// Initialize variables.
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
Document xmlDoc = null;
try {
// Using factory get an instance of document builder
DocumentBuilder db = dbf.newDocumentBuilder();
// Parse using builder to get DOM representation of the XML file
xmlDoc = db.parse(fis);
} catch (Exception ex) {
MekHQ.logError(ex);
}
Element personnelEle = xmlDoc.getDocumentElement();
NodeList nl = personnelEle.getChildNodes();
// Get rid of empty text nodes and adjacent text nodes...
// Stupid weird parsing of XML. At least this cleans it up.
personnelEle.normalize();
Version version = new Version(personnelEle.getAttribute("version"));
// we need to iterate through three times, the first time to collect
// any custom units that might not be written yet
for (int x = 0; x < nl.getLength(); x++) {
Node wn2 = nl.item(x);
// If it's not an element node, we ignore it.
if (wn2.getNodeType() != Node.ELEMENT_NODE) {
continue;
}
if (!wn2.getNodeName().equalsIgnoreCase("person")) {
// Error condition of sorts!
// Errr, what should we do here?
MekHQ.logMessage("Unknown node type not loaded in Personnel nodes: "
+ wn2.getNodeName());
continue;
}
Person p = Person.generateInstanceFromXML(wn2, getCampaign(),
version);
if (getCampaign().getPerson(p.getId()) != null
&& getCampaign().getPerson(p.getId()).getFullName()
.equals(p.getFullName())) {
MekHQ.logMessage("ERROR: Cannot load person who exists, ignoring. (Name: "
+ p.getFullName() + ")");
p = null;
}
if (p != null) {
getCampaign().addPersonWithoutId(p, true);
}
// Clear some values we no longer should have set in case this
// has transferred campaigns or things in the campaign have
// changed...
p.setUnitId(null);
p.clearTechUnitIDs();
}
MekHQ.logMessage("Finished load of personnel file");
}
}
//TODO: disable if not using personnel tab
private void savePersonFile() throws IOException {
JFileChooser savePersonnel = new JFileChooser(".");
savePersonnel.setDialogTitle("Save Personnel");
savePersonnel.setFileFilter(new FileFilter() {
@Override
public boolean accept(File dir) {
if (dir.isDirectory()) {
return true;
}
return dir.getName().endsWith(".prsx");
}
@Override
public String getDescription() {
return "Personnel file";
}
});
savePersonnel.setSelectedFile(new File(getCampaign().getName()
+ getCampaign().getShortDateAsString()
+ "_ExportedPersonnel" + ".prsx")); //$NON-NLS-1$
int returnVal = savePersonnel.showSaveDialog(mainPanel);
if ((returnVal != JFileChooser.APPROVE_OPTION)
|| (savePersonnel.getSelectedFile() == null)) {
// I want a file, y'know!
return;
}
File file = savePersonnel.getSelectedFile();
if (file == null) {
// I want a file, y'know!
return;
}
String path = file.getPath();
if (!path.endsWith(".prsx")) {
path += ".prsx";
file = new File(path);
}
// check for existing file and make a back-up if found
String path2 = path + "_backup";
File backupFile = new File(path2);
if (file.exists()) {
Utilities.copyfile(file, backupFile);
}
// Then save it out to that file.
FileOutputStream fos = null;
PrintWriter pw = null;
try {
PersonnelTab pt = (PersonnelTab)getTab(GuiTabType.PERSONNEL);
int row = pt.getPersonnelTable().getSelectedRow();
if (row < 0) {
MekHQ.logMessage("ERROR: Cannot export person if no one is selected! Ignoring.");
return;
}
Person selectedPerson = pt.getPersonModel().getPerson(pt.getPersonnelTable()
.convertRowIndexToModel(row));
int[] rows = pt.getPersonnelTable().getSelectedRows();
Person[] people = new Person[rows.length];
for (int i = 0; i < rows.length; i++) {
people[i] = pt.getPersonModel().getPerson(pt.getPersonnelTable()
.convertRowIndexToModel(rows[i]));
}
fos = new FileOutputStream(file);
pw = new PrintWriter(new OutputStreamWriter(fos, "UTF-8"));
// File header
pw.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
ResourceBundle resourceMap = ResourceBundle
.getBundle("mekhq.resources.MekHQ");
// Start the XML root.
pw.println("<personnel version=\""
+ resourceMap.getString("Application.version") + "\">");
if (rows.length > 1) {
for (int i = 0; i < rows.length; i++) {
people[i].writeToXml(pw, 1);
}
} else {
selectedPerson.writeToXml(pw, 1);
}
// Okay, we're done.
// Close everything out and be done with it.
pw.println("</personnel>");
pw.flush();
pw.close();
fos.close();
// delete the backup file because we didn't need it
if (backupFile.exists()) {
backupFile.delete();
}
MekHQ.logMessage("Personnel saved to " + file);
} catch (Exception ex) {
MekHQ.logError(ex);
JOptionPane
.showMessageDialog(
getFrame(),
"Oh no! The program was unable to correctly export your personnel. We know this\n"
+ "is annoying and apologize. Please help us out and submit a bug with the\n"
+ "mekhqlog.txt file from this game so we can prevent this from happening in\n"
+ "the future.",
"Could not export personnel",
JOptionPane.ERROR_MESSAGE);
// restore the backup file
file.delete();
if (backupFile.exists()) {
Utilities.copyfile(backupFile, file);
backupFile.delete();
}
}
}
private void saveOptionsFile() throws IOException {
JFileChooser saveOptions = new JFileChooser(".");
saveOptions.setDialogTitle("Save Campaign Options");
saveOptions.setFileFilter(new FileFilter() {
@Override
public boolean accept(File dir) {
if (dir.isDirectory()) {
return true;
}
return dir.getName().endsWith(".xml");
}
@Override
public String getDescription() {
return "Campaign options file";
}
});
saveOptions.setSelectedFile(new File("campaignOptions.xml")); //$NON-NLS-1$
int returnVal = saveOptions.showSaveDialog(mainPanel);
if ((returnVal != JFileChooser.APPROVE_OPTION)
|| (saveOptions.getSelectedFile() == null)) {
// I want a file, y'know!
return;
}
File file = saveOptions.getSelectedFile();
if (file == null) {
// I want a file, y'know!
return;
}
String path = file.getPath();
if (!path.endsWith(".xml")) {
path += ".xml";
file = new File(path);
}
// check for existing file and make a back-up if found
String path2 = path + "_backup";
File backupFile = new File(path2);
if (file.exists()) {
Utilities.copyfile(file, backupFile);
}
// Then save it out to that file.
FileOutputStream fos = null;
PrintWriter pw = null;
try {
fos = new FileOutputStream(file);
pw = new PrintWriter(new OutputStreamWriter(fos, "UTF-8"));
ResourceBundle resourceMap = ResourceBundle
.getBundle("mekhq.resources.MekHQ");
// File header
pw.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
pw.println("<options version=\""
+ resourceMap.getString("Application.version") + "\">");
// Start the XML root.
getCampaign().getCampaignOptions().writeToXml(pw, 1);
pw.println("\t<skillTypes>");
for (String name : SkillType.skillList) {
SkillType type = SkillType.getType(name);
if (null != type) {
type.writeToXml(pw, 2);
}
}
pw.println("\t</skillTypes>");
pw.println("\t<specialAbilities>");
for (String key : SpecialAbility.getAllSpecialAbilities().keySet()) {
SpecialAbility.getAbility(key).writeToXml(pw, 2);
}
pw.println("\t</specialAbilities>");
getCampaign().getRandomSkillPreferences().writeToXml(pw, 1);
pw.println("</options>");
// Okay, we're done.
// Close everything out and be done with it.
pw.flush();
pw.close();
fos.close();
// delete the backup file because we didn't need it
if (backupFile.exists()) {
backupFile.delete();
}
MekHQ.logMessage("Campaign Options saved saved to " + file);
} catch (Exception ex) {
MekHQ.logError(ex);
JOptionPane
.showMessageDialog(
getFrame(),
"Oh no! The program was unable to correctly export your campaign options. We know this\n"
+ "is annoying and apologize. Please help us out and submit a bug with the\n"
+ "mekhqlog.txt file from this game so we can prevent this from happening in\n"
+ "the future.",
"Could not export campaign options",
JOptionPane.ERROR_MESSAGE);
// restore the backup file
file.delete();
if (backupFile.exists()) {
Utilities.copyfile(backupFile, file);
backupFile.delete();
}
}
}
protected void loadPartsFile() throws IOException {
JFileChooser loadList = new JFileChooser(".");
loadList.setDialogTitle("Load Parts");
loadList.setFileFilter(new FileFilter() {
@Override
public boolean accept(File dir) {
if (dir.isDirectory()) {
return true;
}
return dir.getName().endsWith(".parts");
}
@Override
public String getDescription() {
return "Parts file";
}
});
int returnVal = loadList.showOpenDialog(mainPanel);
if ((returnVal != JFileChooser.APPROVE_OPTION)
|| (loadList.getSelectedFile() == null)) {
// I want a file, y'know!
return;
}
File partsFile = loadList.getSelectedFile();
if (partsFile != null) {
// Open up the file.
InputStream fis = new FileInputStream(partsFile);
MekHQ.logMessage("Starting load of parts file from XML...");
// Initialize variables.
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
Document xmlDoc = null;
try {
// Using factory get an instance of document builder
DocumentBuilder db = dbf.newDocumentBuilder();
// Parse using builder to get DOM representation of the XML file
xmlDoc = db.parse(fis);
} catch (Exception ex) {
MekHQ.logError(ex);
}
Element partsEle = xmlDoc.getDocumentElement();
NodeList nl = partsEle.getChildNodes();
// Get rid of empty text nodes and adjacent text nodes...
// Stupid weird parsing of XML. At least this cleans it up.
partsEle.normalize();
Version version = new Version(partsEle.getAttribute("version"));
// we need to iterate through three times, the first time to collect
// any custom units that might not be written yet
for (int x = 0; x < nl.getLength(); x++) {
Node wn2 = nl.item(x);
// If it's not an element node, we ignore it.
if (wn2.getNodeType() != Node.ELEMENT_NODE) {
continue;
}
if (!wn2.getNodeName().equalsIgnoreCase("part")) {
// Error condition of sorts!
// Errr, what should we do here?
MekHQ.logMessage("Unknown node type not loaded in Parts nodes: "
+ wn2.getNodeName());
continue;
}
Part p = Part.generateInstanceFromXML(wn2, version);
if (p != null) {
p.setCampaign(getCampaign());
getCampaign().addPartWithoutId(p);
}
}
MekHQ.logMessage("Finished load of parts file");
}
}
protected void loadOptionsFile() throws IOException {
JFileChooser loadList = new JFileChooser(".");
loadList.setDialogTitle("Load Campaign Options");
loadList.setFileFilter(new FileFilter() {
@Override
public boolean accept(File dir) {
if (dir.isDirectory()) {
return true;
}
return dir.getName().endsWith(".xml");
}
@Override
public String getDescription() {
return "Campaign options file";
}
});
int returnVal = loadList.showOpenDialog(mainPanel);
if ((returnVal != JFileChooser.APPROVE_OPTION)
|| (loadList.getSelectedFile() == null)) {
// I want a file, y'know!
return;
}
File optionsFile = loadList.getSelectedFile();
if (optionsFile != null) {
// Open up the file.
InputStream fis = new FileInputStream(optionsFile);
MekHQ.logMessage("Starting load of options file from XML...");
// Initialize variables.
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
Document xmlDoc = null;
try {
// Using factory get an instance of document builder
DocumentBuilder db = dbf.newDocumentBuilder();
// Parse using builder to get DOM representation of the XML file
xmlDoc = db.parse(fis);
} catch (Exception ex) {
MekHQ.logError(ex);
}
Element partsEle = xmlDoc.getDocumentElement();
NodeList nl = partsEle.getChildNodes();
// Get rid of empty text nodes and adjacent text nodes...
// Stupid weird parsing of XML. At least this cleans it up.
partsEle.normalize();
Version version = new Version(partsEle.getAttribute("version"));
CampaignOptions options = null;
RandomSkillPreferences rsp = null;
// we need to iterate through three times, the first time to collect
// any custom units that might not be written yet
for (int x = 0; x < nl.getLength(); x++) {
Node wn = nl.item(x);
// If it's not an element node, we ignore it.
if (wn.getNodeType() != Node.ELEMENT_NODE) {
continue;
}
String xn = wn.getNodeName();
if (xn.equalsIgnoreCase("campaignOptions")) {
options = CampaignOptions
.generateCampaignOptionsFromXml(wn);
} else if (xn.equalsIgnoreCase("randomSkillPreferences")) {
rsp = RandomSkillPreferences
.generateRandomSkillPreferencesFromXml(wn);
} else if (xn.equalsIgnoreCase("skillTypes")) {
NodeList wList = wn.getChildNodes();
// Okay, lets iterate through the children, eh?
for (int x2 = 0; x2 < wList.getLength(); x2++) {
Node wn2 = wList.item(x2);
// If it's not an element node, we ignore it.
if (wn2.getNodeType() != Node.ELEMENT_NODE) {
continue;
}
if (wn2.getNodeName().startsWith("ability-")) {
continue;
} else if (!wn2.getNodeName().equalsIgnoreCase(
"skillType")) {
// Error condition of sorts!
// Errr, what should we do here?
MekHQ.logMessage("Unknown node type not loaded in Skill Type nodes: "
+ wn2.getNodeName());
continue;
}
SkillType.generateInstanceFromXML(wn2, version);
}
} else if (xn.equalsIgnoreCase("specialAbilities")) {
PilotOptions poptions = new PilotOptions();
SpecialAbility.clearSPA();
NodeList wList = wn.getChildNodes();
// Okay, lets iterate through the children, eh?
for (int x2 = 0; x2 < wList.getLength(); x2++) {
Node wn2 = wList.item(x2);
// If it's not an element node, we ignore it.
if (wn2.getNodeType() != Node.ELEMENT_NODE) {
continue;
}
if (!wn2.getNodeName().equalsIgnoreCase("ability")) {
// Error condition of sorts!
// Errr, what should we do here?
MekHQ.logMessage("Unknown node type not loaded in Special Ability nodes: "
+ wn2.getNodeName());
continue;
}
SpecialAbility.generateInstanceFromXML(wn2, poptions,
null);
}
}
}
if (null != options) {
this.getCampaign().setCampaignOptions(options);
}
if (null != rsp) {
this.getCampaign().setRandomSkillPreferences(rsp);
}
MekHQ.logMessage("Finished load of campaign options file");
MekHQ.triggerEvent(new OptionsChangedEvent(getCampaign(), options));
}
refreshCalendar();
getCampaign().reloadNews();
}
private void savePartsFile() throws IOException {
JFileChooser saveParts = new JFileChooser(".");
saveParts.setDialogTitle("Save Parts");
saveParts.setFileFilter(new FileFilter() {
@Override
public boolean accept(File dir) {
if (dir.isDirectory()) {
return true;
}
return dir.getName().endsWith(".parts");
}
@Override
public String getDescription() {
return "Parts file";
}
});
saveParts.setSelectedFile(new File(getCampaign().getName()
+ getCampaign().getShortDateAsString()
+ "_ExportedParts" + ".parts")); //$NON-NLS-1$
int returnVal = saveParts.showSaveDialog(mainPanel);
if ((returnVal != JFileChooser.APPROVE_OPTION)
|| (saveParts.getSelectedFile() == null)) {
// I want a file, y'know!
return;
}
File file = saveParts.getSelectedFile();
if (file == null) {
// I want a file, y'know!
return;
}
String path = file.getPath();
if (!path.endsWith(".parts")) {
path += ".parts";
file = new File(path);
}
// check for existing file and make a back-up if found
String path2 = path + "_backup";
File backupFile = new File(path2);
if (file.exists()) {
Utilities.copyfile(file, backupFile);
}
// Then save it out to that file.
FileOutputStream fos = null;
PrintWriter pw = null;
if (getTab(GuiTabType.WAREHOUSE) != null) {
try {
JTable partsTable = ((WarehouseTab)getTab(GuiTabType.WAREHOUSE)).getPartsTable();
PartsTableModel partsModel = ((WarehouseTab)getTab(GuiTabType.WAREHOUSE)).getPartsModel();
int row = partsTable.getSelectedRow();
if (row < 0) {
MekHQ.logMessage("ERROR: Cannot export parts if none are selected! Ignoring.");
return;
}
Part selectedPart = partsModel.getPartAt(partsTable
.convertRowIndexToModel(row));
int[] rows = partsTable.getSelectedRows();
Part[] parts = new Part[rows.length];
for (int i = 0; i < rows.length; i++) {
parts[i] = partsModel.getPartAt(partsTable
.convertRowIndexToModel(rows[i]));
}
fos = new FileOutputStream(file);
pw = new PrintWriter(new OutputStreamWriter(fos, "UTF-8"));
// File header
pw.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
ResourceBundle resourceMap = ResourceBundle
.getBundle("mekhq.resources.MekHQ");
// Start the XML root.
pw.println("<parts version=\""
+ resourceMap.getString("Application.version") + "\">");
if (rows.length > 1) {
for (int i = 0; i < rows.length; i++) {
parts[i].writeToXml(pw, 1);
}
} else {
selectedPart.writeToXml(pw, 1);
}
// Okay, we're done.
// Close everything out and be done with it.
pw.println("</parts>");
pw.flush();
pw.close();
fos.close();
// delete the backup file because we didn't need it
if (backupFile.exists()) {
backupFile.delete();
}
MekHQ.logMessage("Parts saved to " + file);
} catch (Exception ex) {
MekHQ.logError(ex);
JOptionPane
.showMessageDialog(
getFrame(),
"Oh no! The program was unable to correctly export your parts. We know this\n"
+ "is annoying and apologize. Please help us out and submit a bug with the\n"
+ "mekhqlog.txt file from this game so we can prevent this from happening in\n"
+ "the future.", "Could not export parts",
JOptionPane.ERROR_MESSAGE);
// restore the backup file
file.delete();
if (backupFile.exists()) {
Utilities.copyfile(backupFile, file);
backupFile.delete();
}
}
}
}
private void exportTable(JTable table, String suggestedName) {
JFileChooser fileChooser = new JFileChooser(".");
fileChooser.setDialogTitle("Save Table");
fileChooser.setFileFilter(new FileFilter() {
@Override
public boolean accept(File dir) {
if (dir.isDirectory()) {
return true;
}
return dir.getName().endsWith(".csv");
}
@Override
public String getDescription() {
return "comma-separated text file";
}
});
fileChooser.setSelectedFile(new File(suggestedName)); //$NON-NLS-1$
int returnVal = fileChooser.showSaveDialog(mainPanel);
if ((returnVal != JFileChooser.APPROVE_OPTION)
|| (fileChooser.getSelectedFile() == null)) {
// I want a file, y'know!
return;
}
File file = fileChooser.getSelectedFile();
if (file == null) {
// I want a file, y'know!
return;
}
String path = file.getPath();
if (!path.endsWith(".csv")) {
path += ".csv";
file = new File(path);
}
// check for existing file and make a back-up if found
String path2 = path + "_backup";
File backupFile = new File(path2);
if (file.exists()) {
Utilities.copyfile(file, backupFile);
}
Utilities.exportTabletoCSV(table, file);
}
public void refreshAllTabs() {
for (int i = 0; i < tabMain.getTabCount(); i++) {
((CampaignGuiTab)tabMain.getComponentAt(i)).refreshAll();
}
}
public void refreshLab() {
MekLabTab lab = (MekLabTab)getTab(GuiTabType.MEKLAB);
if (null == lab) {
return;
}
Unit u = lab.getUnit();
if (null == u) {
return;
}
if (null == getCampaign().getUnit(u.getId())) {
// this unit has been removed so clear the mek lab
lab.clearUnit();
} else {
// put a try-catch here so that bugs in the meklab don't screw up
// other stuff
try {
lab.refreshSummary();
} catch (Exception err) {
err.printStackTrace();
}
}
}
public void refreshCalendar() {
getFrame().setTitle(getCampaign().getTitle());
}
synchronized private void refreshReport() {
List<String> newLogEntries = getCampaign().fetchAndClearNewReports();
panLog.appendLog(newLogEntries);
logDialog.appendLog(newLogEntries);
}
public void initReport() {
String report = getCampaign().getCurrentReportHTML();
panLog.refreshLog(report);
logDialog.refreshLog(report);
getCampaign().fetchAndClearNewReports();
}
private void refreshFunds() {
long funds = getCampaign().getFunds();
NumberFormat numberFormat = NumberFormat.getIntegerInstance();
String inDebt = "";
if (getCampaign().getFinances().isInDebt()) {
inDebt = " <font color='red'>(in Debt)</font>";
}
String text = "<html><b>Funds:</b> " + numberFormat.format(funds)
+ " C-Bills" + inDebt + "</html>";
lblFunds.setText(text);
}
private void refreshRating() {
if (getCampaign().getCampaignOptions().useDragoonRating()) {
String text = "<html><b>Dragoons Rating:</b> "
+ getCampaign().getUnitRating() + "</html>";
lblRating.setText(text);
} else {
lblRating.setText("");
}
}
private void refreshTempAstechs() {
String text = "<html><b>Temp Astechs:</b> "
+ getCampaign().getAstechPool() + "</html>";
lblTempAstechs.setText(text);
}
private void refreshTempMedics() {
String text = "<html><b>Temp Medics:</b> "
+ getCampaign().getMedicPool() + "</html>";
lblTempMedics.setText(text);
}
private ActionScheduler fundsScheduler = new ActionScheduler(this::refreshFunds);
private ActionScheduler ratingScheduler = new ActionScheduler(this::refreshRating);
@Subscribe
public void handle(ReportEvent ev) {
refreshReport();
}
@Subscribe
public void handle(OptionsChangedEvent ev) {
fundsScheduler.schedule();
ratingScheduler.schedule();
}
@Subscribe
public void handle(TransactionEvent ev) {
fundsScheduler.schedule();
ratingScheduler.schedule();
}
@Subscribe
public void handle(LoanEvent ev) {
fundsScheduler.schedule();
ratingScheduler.schedule();
}
@Subscribe
public void handle(AssetEvent ev) {
fundsScheduler.schedule();
ratingScheduler.schedule();
}
@Subscribe
public void handle(MissionEvent ev) {
ratingScheduler.schedule();
}
@Subscribe
public void handle(PersonEvent ev) {
ratingScheduler.schedule();
}
@Subscribe
public void handle(UnitEvent ev) {
ratingScheduler.schedule();
}
@Subscribe
public void handle(AstechPoolChangedEvent ev) {
refreshTempAstechs();
}
@Subscribe
public void handle(MedicPoolChangedEvent ev) {
refreshTempMedics();
}
public void refreshLocation() {
lblLocation.setText(getCampaign().getLocation().getReport(
getCampaign().getCalendar().getTime()));
}
protected MekHQ getApplication() {
return app;
}
public Campaign getCampaign() {
return getApplication().getCampaign();
}
public IconPackage getIconPackage() {
return getApplication().getIconPackage();
}
public JFrame getFrame() {
return frame;
}
public CampaignGUI getCampaignGUI() {
return this;
}
public int getTabIndexByName(String tabTitle) {
int retVal = -1;
for (int i = 0; i < tabMain.getTabCount(); i++) {
if (tabMain.getTitleAt(i).equals(tabTitle)) {
retVal = i;
break;
}
}
return retVal;
}
public void undeployUnit(Unit u) {
Force f = getCampaign().getForce(u.getForceId());
if (f != null) {
undeployForce(f, false);
}
Scenario s = getCampaign().getScenario(u.getScenarioId());
s.removeUnit(u.getId());
u.undeploy();
MekHQ.triggerEvent(new DeploymentChangedEvent(u, s));
}
public void undeployForce(Force f) {
undeployForce(f, true);
}
public void undeployForce(Force f, boolean killSubs) {
int sid = f.getScenarioId();
Scenario scenario = getCampaign().getScenario(sid);
if (null != f && null != scenario) {
f.clearScenarioIds(getCampaign(), killSubs);
scenario.removeForce(f.getId());
if (killSubs) {
for (UUID uid : f.getAllUnits()) {
Unit u = getCampaign().getUnit(uid);
if (null != u) {
scenario.removeUnit(u.getId());
u.undeploy();
}
}
}
// We have to clear out the parents as well.
Force parent = f;
int prevId = f.getId();
while ((parent = parent.getParentForce()) != null) {
if (parent.getScenarioId() == -1) {
break;
}
parent.clearScenarioIds(getCampaign(), false);
scenario.removeForce(parent.getId());
for (Force sub : parent.getSubForces()) {
if (sub.getId() == prevId) {
continue;
}
scenario.addForces(sub.getId());
sub.setScenarioId(scenario.getId());
}
prevId = parent.getId();
}
}
if (null != scenario) {
MekHQ.triggerEvent(new DeploymentChangedEvent(f, scenario));
}
}
public JTabbedPane getTabMain() {
return tabMain;
}
/**
* @return the resourceMap
*/
public ResourceBundle getResourceMap() {
return resourceMap;
}
private void setCampaignOptionsFromGameOptions() {
getCampaign().getCampaignOptions().setUseTactics(getCampaign().getGameOptions().getOption("command_init").booleanValue());
getCampaign().getCampaignOptions().setInitBonus(getCampaign().getGameOptions().getOption("individual_initiative").booleanValue());
getCampaign().getCampaignOptions().setToughness(getCampaign().getGameOptions().getOption("toughness").booleanValue());
getCampaign().getCampaignOptions().setArtillery(getCampaign().getGameOptions().getOption("artillery_skill").booleanValue());
getCampaign().getCampaignOptions().setAbilities(getCampaign().getGameOptions().getOption("pilot_advantages").booleanValue());
getCampaign().getCampaignOptions().setEdge(getCampaign().getGameOptions().getOption("edge").booleanValue());
getCampaign().getCampaignOptions().setImplants(getCampaign().getGameOptions().getOption("manei_domini").booleanValue());
getCampaign().getCampaignOptions().setQuirks(getCampaign().getGameOptions().getOption("stratops_quirks").booleanValue());
getCampaign().getCampaignOptions().setAllowCanonOnly(getCampaign().getGameOptions().getOption("canon_only").booleanValue());
getCampaign().getCampaignOptions().setTechLevel(TechConstants.getSimpleLevel(getCampaign().getGameOptions().getOption("techlevel").stringValue()));
MekHQ.triggerEvent(new OptionsChangedEvent(getCampaign()));
}
}