/*
* MegaMekLab - Copyright (C) 2008
*
* Original author - jtighe (torren@users.sourceforge.net)
*
* This program 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 2 of the License, or (at your option)
* any later version.
*
* This program 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.
*/
package megameklab.com.ui.Mek.views;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Collections;
import java.util.Vector;
import javax.swing.BorderFactory;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.border.TitledBorder;
import javax.swing.table.TableColumn;
import megamek.common.AmmoType;
import megamek.common.Entity;
import megamek.common.Mech;
import megamek.common.MiscType;
import megamek.common.Mounted;
import megamek.common.WeaponType;
import megamek.common.weapons.Weapon;
import megameklab.com.ui.EntitySource;
import megameklab.com.ui.Mek.tabs.BuildTab;
import megameklab.com.util.CriticalTableModel;
import megameklab.com.util.IView;
import megameklab.com.util.RefreshListener;
import megameklab.com.util.StringUtils;
import megameklab.com.util.UnitUtil;
import megameklab.com.util.CriticalTransferHandler;
/**
* This IView shows all the equipment that's not yet been assigned a location
* @author beerockxs
*
*/
public class BuildView extends IView implements ActionListener, MouseListener {
/**
*
*/
private static final long serialVersionUID = 799195356642563937L;
private CriticalTableModel equipmentList;
private Vector<Mounted> masterEquipmentList = new Vector<Mounted>(10, 1);
private JTable equipmentTable = new JTable();
private JScrollPane equipmentScroll = new JScrollPane();
private int engineHeatSinkCount = 0;
CriticalTransferHandler cth;
public BuildView(EntitySource eSource, RefreshListener refresh) {
super(eSource);
equipmentList = new CriticalTableModel(getMech(), CriticalTableModel.BUILDTABLE);
equipmentTable.setModel(equipmentList);
equipmentTable.setDragEnabled(true);
cth = new CriticalTransferHandler(eSource, refresh);
equipmentTable.setTransferHandler(cth);
TableColumn column = null;
for (int i = 0; i < equipmentList.getColumnCount(); i++) {
column = equipmentTable.getColumnModel().getColumn(i);
if(i == 0) {
column.setPreferredWidth(250);
}
column.setCellRenderer(equipmentList.getRenderer());
}
equipmentTable.setIntercellSpacing(new Dimension(0, 0));
equipmentTable.setShowGrid(false);
equipmentTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
equipmentTable.setDoubleBuffered(true);
equipmentScroll.setViewportView(equipmentTable);
equipmentScroll.setMinimumSize(new java.awt.Dimension(300, 400));
equipmentScroll.setPreferredSize(new java.awt.Dimension(300, 400));
equipmentScroll.setTransferHandler(cth);
equipmentTable.addMouseListener(this);
setLayout(new BorderLayout());
this.add(equipmentScroll, BorderLayout.CENTER);
setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), "Unallocated Equipment", TitledBorder.TOP, TitledBorder.DEFAULT_POSITION));
}
public void addRefreshedListener(RefreshListener l) {
cth.addRefreshListener(l);
}
private void loadEquipmentTable() {
equipmentList.removeAllCrits();
masterEquipmentList.clear();
engineHeatSinkCount = UnitUtil.getCriticalFreeHeatSinks(getMech(), getMech().hasCompactHeatSinks());
for (Mounted mount : getMech().getMisc()) {
if ((mount.getLocation() == Entity.LOC_NONE) && !isEngineHeatSink(mount) && !(mount.getType().getCriticals(getMech()) == 0)) {
masterEquipmentList.add(mount);
}
}
for (Mounted mount : getMech().getWeaponList()) {
if (mount.getLocation() == Entity.LOC_NONE) {
masterEquipmentList.add(mount);
}
}
for (Mounted mount : getMech().getAmmo()) {
if ((mount.getLocation() == Entity.LOC_NONE) && ((mount.getUsableShotsLeft() > 1) || (((AmmoType)mount.getType()).getAmmoType() == AmmoType.T_COOLANT_POD))) {
masterEquipmentList.add(mount);
}
}
Collections.sort(masterEquipmentList, StringUtils.mountedComparator());
// Time to Sort
// HeatSinks first
for (int pos = 0; pos < masterEquipmentList.size(); pos++) {
if (UnitUtil.isHeatSink(masterEquipmentList.get(pos))) {
equipmentList.addCrit(masterEquipmentList.get(pos));
masterEquipmentList.remove(pos);
pos--;
}
}
// Jump Jets
for (int pos = 0; pos < masterEquipmentList.size(); pos++) {
if (UnitUtil.isJumpJet(masterEquipmentList.get(pos).getType())) {
equipmentList.addCrit(masterEquipmentList.get(pos));
masterEquipmentList.remove(pos);
pos--;
}
}
// weapons and ammo
Vector<Mounted> weaponsNAmmoList = new Vector<Mounted>(10, 1);
for (int pos = 0; pos < masterEquipmentList.size(); pos++) {
if ((masterEquipmentList.get(pos).getType() instanceof Weapon) || (masterEquipmentList.get(pos).getType() instanceof AmmoType)) {
weaponsNAmmoList.add(masterEquipmentList.get(pos));
masterEquipmentList.remove(pos);
pos--;
}
}
Collections.sort(weaponsNAmmoList, StringUtils.mountedComparator());
for (Mounted mount : weaponsNAmmoList) {
equipmentList.addCrit(mount);
}
// Equipment
for (int pos = 0; pos < masterEquipmentList.size(); pos++) {
if ((masterEquipmentList.get(pos).getType() instanceof MiscType) && !UnitUtil.isArmor(masterEquipmentList.get(pos).getType()) && !UnitUtil.isTSM(masterEquipmentList.get(pos).getType())) {
equipmentList.addCrit(masterEquipmentList.get(pos));
masterEquipmentList.remove(pos);
pos--;
}
}
// structure
for (int pos = 0; pos < masterEquipmentList.size(); pos++) {
if (UnitUtil.isStructure(masterEquipmentList.get(pos).getType())) {
equipmentList.addCrit(masterEquipmentList.get(pos));
masterEquipmentList.remove(pos);
pos--;
}
}
// armor
for (int pos = 0; pos < masterEquipmentList.size(); pos++) {
if (UnitUtil.isArmor(masterEquipmentList.get(pos).getType())) {
equipmentList.addCrit(masterEquipmentList.get(pos));
masterEquipmentList.remove(pos);
pos--;
}
}
// everything else that is not TSM
for (int pos = 0; pos < masterEquipmentList.size(); pos++) {
if (!UnitUtil.isTSM(masterEquipmentList.get(pos).getType())) {
equipmentList.addCrit(masterEquipmentList.get(pos));
masterEquipmentList.remove(pos);
pos--;
}
}
// TSM
for (int pos = 0; pos < masterEquipmentList.size(); pos++) {
equipmentList.addCrit(masterEquipmentList.get(pos));
}
}
private boolean isEngineHeatSink(Mounted mount) {
if ((mount.getLocation() == Entity.LOC_NONE) && UnitUtil.isHeatSink(mount) && (engineHeatSinkCount > 0)) {
if(mount.getType().hasFlag(MiscType.F_COMPACT_HEAT_SINK) && mount.getType().hasFlag(MiscType.F_DOUBLE_HEAT_SINK)) {
//only single compact HS should be used for engine sinks
return false;
}
engineHeatSinkCount--;
return engineHeatSinkCount >= 0;
}
return false;
}
public void refresh() {
removeAllListeners();
loadEquipmentTable();
fireTableRefresh();
addAllListeners();
}
private void removeAllListeners() {
}
private void addAllListeners() {
}
public void actionPerformed(ActionEvent e) {
fireTableRefresh();
}
private void fireTableRefresh() {
equipmentList.updateUnit(getMech());
equipmentList.refreshModel();
}
public CriticalTableModel getTableModel() {
return equipmentList;
}
public JTable getTable() {
return equipmentTable;
}
public void mouseClicked(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON3) {
JPopupMenu popup = new JPopupMenu();
JMenuItem item;
final int selectedRow = equipmentTable.rowAtPoint(e.getPoint());
Mounted eq = (Mounted)equipmentTable.getModel().getValueAt(selectedRow, CriticalTableModel.EQUIPMENT);
final int totalCrits = UnitUtil.getCritsUsed(getMech(), eq.getType());
String[] locations = getMech().getLocationNames();
String[] abbrLocations = getMech().getLocationAbbrs();
if ((eq.getType().isSpreadable() || eq.isSplitable())
&& (totalCrits > 1)) {
int[] critSpace = UnitUtil.getHighestContinuousNumberOfCritsArray(getMech());
if ((critSpace[Mech.LOC_RT] >= 1) && UnitUtil.isValidLocation(getMech(), eq.getType(), Mech.LOC_RT)) {
JMenu rtMenu = new JMenu(locations[Mech.LOC_RT]);
if (critSpace[Mech.LOC_RT] >= totalCrits) {
item = new JMenuItem(String.format("Add to %1$s", locations[Mech.LOC_RT]));
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
jMenuLoadComponent_actionPerformed(Mech.LOC_RT, selectedRow);
}
});
rtMenu.add(item);
}
int[] splitLocations = new int[]
{ Mech.LOC_CT, Mech.LOC_RARM, Mech.LOC_RLEG };
for (int location = 0; location < 3; location++) {
JMenu subMenu = new JMenu(String.format("%1$s/%2$s", abbrLocations[Mech.LOC_RT], abbrLocations[splitLocations[location]]));
int subCrits = critSpace[splitLocations[location]];
for (int slots = 1; slots <= subCrits; slots++) {
final int primarySlots = totalCrits - slots;
item = new JMenuItem(String.format("%1$s (%2$s)/%3$s (%4$s)", abbrLocations[Mech.LOC_RT], primarySlots, abbrLocations[splitLocations[location]], slots));
final int secondaryLocation = splitLocations[location];
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
jMenuLoadSplitComponent_actionPerformed(Mech.LOC_RT, secondaryLocation, primarySlots, selectedRow);
}
});
subMenu.add(item);
}
rtMenu.add(subMenu);
}
popup.add(rtMenu);
}
if ((critSpace[Mech.LOC_RARM] >= totalCrits) && UnitUtil.isValidLocation(getMech(), eq.getType(), Mech.LOC_RARM)) {
item = new JMenuItem(String.format("Add to %1$s", locations[Mech.LOC_RARM]));
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
jMenuLoadSplitComponent_actionPerformed(Mech.LOC_RARM, Mech.LOC_RARM, totalCrits, selectedRow);
}
});
popup.add(item);
}
if ((critSpace[Mech.LOC_LT] >= 1) && UnitUtil.isValidLocation(getMech(), eq.getType(), Mech.LOC_LT)) {
JMenu ltMenu = new JMenu(locations[Mech.LOC_LT]);
if (critSpace[Mech.LOC_LT] >= totalCrits) {
item = new JMenuItem(String.format("Add to %1$s", locations[Mech.LOC_LT]));
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
jMenuLoadComponent_actionPerformed(Mech.LOC_LT, selectedRow);
}
});
ltMenu.add(item);
}
int[] splitLocations = new int[]
{ Mech.LOC_CT, Mech.LOC_LARM, Mech.LOC_LLEG };
for (int location = 0; location < 3; location++) {
JMenu subMenu = new JMenu(String.format("%1$s/%2$s", abbrLocations[Mech.LOC_LT], abbrLocations[splitLocations[location]]));
int subCrits = critSpace[splitLocations[location]];
for (int slots = 1; slots <= subCrits; slots++) {
final int primarySlots = totalCrits - slots;
item = new JMenuItem(String.format("%1$s (%2$s)/%3$s (%4$s)", abbrLocations[Mech.LOC_LT], primarySlots, abbrLocations[splitLocations[location]], slots));
final int secondaryLocation = splitLocations[location];
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
jMenuLoadSplitComponent_actionPerformed(Mech.LOC_LT, secondaryLocation, primarySlots, selectedRow);
}
});
subMenu.add(item);
}
ltMenu.add(subMenu);
}
popup.add(ltMenu);
}
if ((critSpace[Mech.LOC_LARM] >= totalCrits) && UnitUtil.isValidLocation(getMech(), eq.getType(), Mech.LOC_LARM)) {
item = new JMenuItem(String.format("Add to %1$s", locations[Mech.LOC_LARM]));
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
jMenuLoadSplitComponent_actionPerformed(Mech.LOC_LARM, Mech.LOC_LARM, totalCrits, selectedRow);
}
});
popup.add(item);
}
} else {
for (int location = 0; location < getMech().locations(); location++) {
if ((UnitUtil.getHighestContinuousNumberOfCrits(getMech(), location) >= totalCrits) && UnitUtil.isValidLocation(getMech(), eq.getType(), location)) {
item = new JMenuItem("Add to " + locations[location]);
final int loc = location;
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
jMenuLoadComponent_actionPerformed(loc, selectedRow);
}
});
popup.add(item);
}
}
}
popup.show(this, e.getX(), e.getY());
}
}
public void mouseReleased(MouseEvent e) {
}
private void jMenuLoadSplitComponent_actionPerformed(int location, int secondaryLocation, int primarySlots, int selectedRow) {
Mounted eq = (Mounted)equipmentTable.getModel().getValueAt(selectedRow, CriticalTableModel.EQUIPMENT);
int crits = UnitUtil.getCritsUsed(getMech(), eq.getType());
int openSlots = Math.min(primarySlots, UnitUtil.getHighestContinuousNumberOfCrits(getMech(), location));
eq.setSecondLocation(secondaryLocation);
for (int slot = 0; slot < openSlots; slot++) {
try {
UnitUtil.addMounted(getMech(), eq, location, false);
} catch (Exception ex) {
ex.printStackTrace();
}
}
crits -= openSlots;
for (int slot = 0; slot < crits; slot++) {
try {
UnitUtil.addMounted(getMech(), eq, secondaryLocation, false);
} catch (Exception ex) {
ex.printStackTrace();
}
}
UnitUtil.changeMountStatus(getMech(), eq, location, secondaryLocation, false);
// go back up to grandparent build tab and fire a full refresh.
((BuildTab) getParent().getParent()).refreshAll();
}
private void jMenuLoadComponent_actionPerformed(int location, int selectedRow) {
Mounted eq = (Mounted) equipmentTable.getModel().getValueAt(selectedRow, CriticalTableModel.EQUIPMENT);
try {
if ((eq.getType() instanceof WeaponType) && eq.getType().hasFlag(WeaponType.F_VGL)) {
String[] facings;
if (location == Mech.LOC_LT) {
facings = new String[4];
facings[0] = "Front";
facings[1] = "Front-Left";
facings[2] = "Rear-Left";
facings[3] = "Rear";
} else if (location == Mech.LOC_RT) {
facings = new String[4];
facings[0] = "Front";
facings[1] = "Front-Right";
facings[2] = "Rear-Right";
facings[3] = "Rear";
} else if (location == Mech.LOC_CT) {
facings = new String[2];
facings[0] = "Front";
facings[1] = "Rear";
} else {
JOptionPane.showMessageDialog(this, "VGL must be placed in torso location!", "Invalid location", JOptionPane.WARNING_MESSAGE);
return;
}
String facing = (String)JOptionPane.showInputDialog(this, "Please choose the facing of the VGL", "Choose Facing", JOptionPane.QUESTION_MESSAGE, null, facings, facings[0]);
if (facing == null) {
return;
}
UnitUtil.addMounted(getMech(), eq, location, false);
if (facing.equals("Front-Left")) {
eq.setFacing(5);
} else if (facing.equals("Front-Right")) {
eq.setFacing(1);
} else if (facing.equals("Rear-Right")) {
eq.setFacing(2);
} else if (facing.equals("Rear-Left")) {
eq.setFacing(4);
} else if (facing.equals("Rear")) {
eq.setFacing(3);
UnitUtil.changeMountStatus(getMech(), eq, location, -1, true);
}
} else {
UnitUtil.addMounted(getMech(), eq, location, false);
}
} catch (Exception ex) {
ex.printStackTrace();
}
UnitUtil.changeMountStatus(getMech(), eq, location, -1, false);
// go back up to grandparent build tab and fire a full refresh.
((BuildTab) getParent().getParent()).refreshAll();
}
}