/*
* ChooseRefitDialog.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.dialog;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.GregorianCalendar;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextPane;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableRowSorter;
import megamek.common.Entity;
import megamek.common.MechFileParser;
import megamek.common.MechSummary;
import megamek.common.MechSummaryCache;
import megamek.common.MechView;
import megamek.common.loaders.EntityLoadingException;
import megamek.common.util.EncodeControl;
import mekhq.Utilities;
import mekhq.campaign.Campaign;
import mekhq.campaign.parts.Refit;
import mekhq.campaign.unit.Unit;
import mekhq.gui.CampaignGUI;
/**
*
* @author Taharqa
*/
public class ChooseRefitDialog extends javax.swing.JDialog {
private static final long serialVersionUID = -8038099101234445018L;
private Campaign campaign;
private Unit unit;
private RefitTableModel refitModel;
private CampaignGUI gui;
private javax.swing.JButton btnClose;
private javax.swing.JButton btnOK;
private JTable refitTable;
private JScrollPane scrRefitTable;
private JList<String> lstShopping;
private JScrollPane scrShoppingList;
private JTextPane txtOldUnit;
private JTextPane txtNewUnit;
private JScrollPane scrOldUnit;
private JScrollPane scrNewUnit;
/** Creates new form EditPersonnelLogDialog */
public ChooseRefitDialog(java.awt.Frame parent, boolean modal, Campaign c, Unit u, CampaignGUI gui) {
super(parent, modal);
campaign = c;
unit = u;
this.gui = gui;
populateRefits();
initComponents();
setLocationRelativeTo(parent);
}
private void initComponents() {
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
ResourceBundle resourceMap = ResourceBundle.getBundle("mekhq.resources.ChooseRefitDialog", new EncodeControl()); //$NON-NLS-1$
setTitle(resourceMap.getString("title.text") + " " + unit.getName());
GridBagConstraints gridBagConstraints;
getContentPane().setLayout(new GridBagLayout());
refitTable = new JTable(refitModel);
TableColumn column = null;
for (int i = 0; i < RefitTableModel.N_COL; i++) {
column = refitTable.getColumnModel().getColumn(i);
column.setPreferredWidth(refitModel.getColumnWidth(i));
column.setCellRenderer(refitModel.getRenderer());
}
refitTable.setIntercellSpacing(new Dimension(0, 0));
refitTable.setShowGrid(false);
refitTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
refitTable.getSelectionModel().addListSelectionListener(
new javax.swing.event.ListSelectionListener() {
public void valueChanged(
javax.swing.event.ListSelectionEvent evt) {
refitTableValueChanged();
}
});
TableRowSorter<RefitTableModel> refitSorter = new TableRowSorter<RefitTableModel>(refitModel);
refitSorter.setComparator(RefitTableModel.COL_CLASS, new ClassSorter());
refitSorter.setComparator(RefitTableModel.COL_COST, new FormattedNumberSorter());
refitTable.setRowSorter(refitSorter);
scrRefitTable = new JScrollPane();
scrRefitTable.setViewportView(refitTable);
scrRefitTable.setBorder(BorderFactory.createTitledBorder(resourceMap.getString("refitTable.title")));
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
getContentPane().add(scrRefitTable, gridBagConstraints);
scrShoppingList = new JScrollPane();
scrShoppingList.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createTitledBorder(resourceMap.getString("shoppingList.title")),
BorderFactory.createEmptyBorder(5,5,5,5)));
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 1;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
scrShoppingList.setMinimumSize(new java.awt.Dimension(300, 200));
scrShoppingList.setPreferredSize(new java.awt.Dimension(300, 200));
getContentPane().add(scrShoppingList, gridBagConstraints);
txtOldUnit = new JTextPane();
txtOldUnit.setEditable(false);
txtOldUnit.setContentType("text/html");
txtOldUnit.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createTitledBorder(resourceMap.getString("txtOldUnit.title")),
BorderFactory.createEmptyBorder(5,5,5,5)));
MechView mv = new MechView(unit.getEntity(), false, true);
txtOldUnit.setText("<div style='font: 12pt monospaced'>" + mv.getMechReadout() + "</div>");
scrOldUnit = new JScrollPane(txtOldUnit);
scrOldUnit.setMinimumSize(new java.awt.Dimension(300, 400));
scrOldUnit.setPreferredSize(new java.awt.Dimension(300, 400));
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
scrOldUnit.getVerticalScrollBar().setValue(0);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 0;
gridBagConstraints.gridheight = 2;
gridBagConstraints.weightx = 0.0;
gridBagConstraints.weighty = 1.0;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
getContentPane().add(scrOldUnit, gridBagConstraints);
txtNewUnit = new JTextPane();
txtNewUnit.setEditable(false);
txtNewUnit.setContentType("text/html");
txtNewUnit.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createTitledBorder(resourceMap.getString("txtNewUnit.title")),
BorderFactory.createEmptyBorder(5,5,5,5)));
scrNewUnit = new JScrollPane(txtNewUnit);
scrNewUnit.setMinimumSize(new java.awt.Dimension(300, 400));
scrNewUnit.setPreferredSize(new java.awt.Dimension(300, 400));
gridBagConstraints.gridx = 2;
getContentPane().add(scrNewUnit, gridBagConstraints);
JPanel panBtn = new JPanel(new GridBagLayout());
btnOK = new JButton(resourceMap.getString("btnOK.text")); // NOI18N
btnOK.setEnabled(false);
btnOK.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
beginRefit();
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.fill = java.awt.GridBagConstraints.NONE;
gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
panBtn.add(btnOK, gridBagConstraints);
btnClose = new JButton(resourceMap.getString("btnClose.text")); // NOI18N
btnClose.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
cancel();
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 0;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.fill = java.awt.GridBagConstraints.NONE;
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
panBtn.add(btnClose, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 2;
gridBagConstraints.gridwidth = 3;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 0.0;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
getContentPane().add(panBtn, gridBagConstraints);
pack();
}
private void beginRefit() {
setVisible(false);
gui.refitUnit(getSelectedRefit(), false);
}
private void cancel() {
setVisible(false);
}
private Refit getSelectedRefit() {
int selectedRow = refitTable.getSelectedRow();
if(selectedRow < 0) {
return null;
}
return refitModel.getRefitAt(refitTable.convertRowIndexToModel(selectedRow));
}
private void refitTableValueChanged() {
Refit r = getSelectedRefit();
if(null == r) {
scrShoppingList.setViewportView(null);
txtNewUnit.setText("");
btnOK.setEnabled(false);
return;
}
btnOK.setEnabled(true);
lstShopping = new JList<String>(r.getShoppingListDescription());
scrShoppingList.setViewportView(lstShopping);
MechView mv = new MechView(r.getNewEntity(), false, true);
txtNewUnit.setText("<div style='font: 12pt monospaced'>" + mv.getMechReadout() + "</div>");
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
scrNewUnit.getVerticalScrollBar().setValue(0);
}
});
}
private void populateRefits() {
ArrayList<Refit> refits = new ArrayList<Refit>();
for(String model : Utilities.getAllVariants(unit.getEntity(), campaign.getCalendar().get(GregorianCalendar.YEAR), campaign.getCampaignOptions())) {
MechSummary summary = MechSummaryCache.getInstance().getMech(unit.getEntity().getChassis() + " " + model);
if(null == summary) {
continue;
}
try {
Entity refitEn = new MechFileParser(summary.getSourceFile(), summary.getEntryName()).getEntity();
if(null != refitEn) {
Refit r = new Refit(unit, refitEn, false, false);
if(null == r.checkFixable()) {
refits.add(r);
}
}
} catch (EntityLoadingException ex) {
Logger.getLogger(CampaignGUI.class.getName())
.log(Level.SEVERE, null, ex);
}
}
refitModel = new RefitTableModel(refits);
}
/**
* A table model for displaying parts - similar to the one in CampaignGUI, but not exactly
*/
public class RefitTableModel extends AbstractTableModel {
private static final long serialVersionUID = 534443424190075264L;
protected String[] columnNames;
protected ArrayList<Refit> data;
public final static int COL_MODEL = 0;
public final static int COL_CLASS = 1;
public final static int COL_BV = 2;
public final static int COL_TIME = 3;
public final static int COL_NPART = 4;
public final static int COL_TARGET = 5;
public final static int COL_COST = 6;
public final static int N_COL = 7;
public RefitTableModel(ArrayList<Refit> refits) {
data = refits;
}
public int getRowCount() {
return data.size();
}
public int getColumnCount() {
return N_COL;
}
@Override
public String getColumnName(int column) {
switch(column) {
case COL_MODEL:
return "Model";
case COL_CLASS:
return "Class";
case COL_BV:
return "BV";
case COL_TIME:
return "Time";
case COL_NPART:
return "# Parts";
case COL_COST:
return "Cost";
case COL_TARGET:
return "Kit TN";
default:
return "?";
}
}
public Object getValueAt(int row, int col) {
Refit r;
DecimalFormat formatter = new DecimalFormat();
if(data.isEmpty()) {
return "";
} else {
r = (Refit)data.get(row);
}
if(col == COL_MODEL) {
return r.getNewEntity().getModel();
}
if(col == COL_CLASS) {
return r.getRefitClassName();
}
if(col == COL_BV) {
return r.getNewEntity().calculateBattleValue(true, true);
}
if(col == COL_TIME) {
return r.getTime();
}
if(col == COL_NPART) {
return r.getShoppingList().size();
}
if(col == COL_COST) {
return formatter.format(r.getCost());
}
if(col == COL_TARGET) {
return campaign.getTargetForAcquisition(r, campaign.getLogisticsPerson(), false).getValueAsString();
}
return "?";
}
@Override
public boolean isCellEditable(int row, int col) {
return false;
}
@Override
public Class<? extends Object> getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
public Refit getRefitAt(int row) {
return (Refit) data.get(row);
}
public int getColumnWidth(int c) {
switch(c) {
case COL_MODEL:
return 75;
case COL_CLASS:
return 110;
case COL_COST:
return 40;
default:
return 10;
}
}
public int getAlignment(int col) {
switch(col) {
case COL_MODEL:
case COL_CLASS:
return SwingConstants.LEFT;
default:
return SwingConstants.RIGHT;
}
}
public String getTooltip(int row, int col) {
Refit r;
if(data.isEmpty()) {
return "";
} else {
r = (Refit)data.get(row);
}
switch(col) {
case COL_TARGET:
return campaign.getTargetForAcquisition(r, campaign.getLogisticsPerson(), false).getDesc();
default:
return null;
}
}
//fill table with values
public void setData(ArrayList<Refit> refits) {
data = refits;
fireTableDataChanged();
}
public RefitTableModel.Renderer getRenderer() {
return new RefitTableModel.Renderer();
}
public class Renderer extends DefaultTableCellRenderer {
private static final long serialVersionUID = -6655108546652975061L;
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus,
int row, int column) {
super.getTableCellRendererComponent(table, value, isSelected,
hasFocus, row, column);
setOpaque(true);
int actualCol = table.convertColumnIndexToModel(column);
int actualRow = table.convertRowIndexToModel(row);
setHorizontalAlignment(getAlignment(actualCol));
setToolTipText(getTooltip(actualRow, actualCol));
return this;
}
}
}
/**
* A comparator for numbers that have been formatted with DecimalFormat
* @author Jay Lawson
*
*/
public class FormattedNumberSorter implements Comparator<String> {
@Override
public int compare(String s0, String s1) {
//lets find the weight class integer for each name
DecimalFormat format = new DecimalFormat();
int l0 = 0;
try {
l0 = format.parse(s0).intValue();
} catch (java.text.ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
int l1 = 0;
try {
l1 = format.parse(s1).intValue();
} catch (java.text.ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return ((Comparable<Integer>)l0).compareTo(l1);
}
}
/**
* A comparator for refit classes
* @author Jay Lawson
*
*/
public class ClassSorter implements Comparator<String> {
@Override
public int compare(String s0, String s1) {
int r0 = Refit.NO_CHANGE;
int r1 = Refit.NO_CHANGE;
if(s0.contains("Omni")) {
r0 = Refit.CLASS_OMNI;
}
else if(s0.contains("Class A")) {
r0 = Refit.CLASS_A;
}
else if(s0.contains("Class B")) {
r0 = Refit.CLASS_B;
}
else if(s0.contains("Class C")) {
r0 = Refit.CLASS_C;
}
else if(s0.contains("Class D")) {
r0 = Refit.CLASS_D;
}
else if(s0.contains("Class E")) {
r0 = Refit.CLASS_E;
}
else if(s0.contains("Class F")) {
r0 = Refit.CLASS_F;
}
if(s1.contains("Omni")) {
r1 = Refit.CLASS_OMNI;
}
else if(s1.contains("Class A")) {
r1 = Refit.CLASS_A;
}
else if(s1.contains("Class B")) {
r1 = Refit.CLASS_B;
}
else if(s1.contains("Class C")) {
r1 = Refit.CLASS_C;
}
else if(s1.contains("Class D")) {
r1 = Refit.CLASS_D;
}
else if(s1.contains("Class E")) {
r1 = Refit.CLASS_E;
}
else if(s1.contains("Class F")) {
r1 = Refit.CLASS_F;
}
return ((Comparable<Integer>)r0).compareTo(r1);
}
}
}