/*
* 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.Aero.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.ArrayList;
import java.util.Collections;
import java.util.Vector;
import javax.swing.BorderFactory;
import javax.swing.JMenuItem;
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.Aero;
import megamek.common.AmmoType;
import megamek.common.Entity;
import megamek.common.MiscType;
import megamek.common.Mounted;
import megamek.common.WeaponType;
import megamek.common.verifier.TestAero;
import megamek.common.weapons.Weapon;
import megameklab.com.ui.EntitySource;
import megameklab.com.ui.Aero.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
* @author arlith
*
*/
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(getAero(), 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(350);
}
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(400, 400));
equipmentScroll.setPreferredSize(new java.awt.Dimension(400, 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();
for (Mounted mount : getAero().getMisc()) {
if ((mount.getLocation() == Entity.LOC_NONE) &&
!isEngineHeatSink(mount)) {
masterEquipmentList.add(mount);
}
}
for (Mounted mount : getAero().getWeaponList()) {
if (mount.getLocation() == Entity.LOC_NONE) {
masterEquipmentList.add(mount);
}
}
for (Mounted mount : getAero().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(getAero());
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) {
// On right-click, we want to generate menu items to add to specific
// locations, but only if those locations are make sense
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);
String[] locNames = getAero().getLocationNames();
// A list of the valid locations we can add the selected eq to
ArrayList<Integer> validLocs = new ArrayList<Integer>();
// The number of possible locations, Aeros' have LOC_WINGS, which we
// want ot ignore, hence -1
int numLocs = getAero().locations() - 1;
// If it's a weapon, there are restrictions
if (eq.getType() instanceof WeaponType){
int[] availSpace = TestAero.availableSpace(getAero());
int numWeapons[] = new int[availSpace.length];
for (Mounted m : getAero().getWeaponList()){
if (m.getLocation() != Aero.LOC_NONE){
numWeapons[m.getLocation()]++;
}
}
for (int loc = 0; loc < numLocs; loc++){
if ((numWeapons[loc]+1) < availSpace[loc]){
validLocs.add(loc);
}
}
// If it's not a weapon there are no space requirements
} else {
for (int loc = 0; loc < numLocs; loc++){
validLocs.add(loc);
}
}
// Add a menu item for each potential location
for (Integer location: validLocs) {
if (UnitUtil.isValidLocation(getAero(), eq.getType(), location)) {
item = new JMenuItem("Add to " + locNames[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) {
}
/**
* When the user right-clicks on the equipment table, a context menu is
* generated that his menu items for each possible location that is clicked.
* When the location is clicked, this is the method that adds the selected
* equipment to the desired location.
*
* @param location
* @param selectedRow
*/
private void jMenuLoadComponent_actionPerformed(int location,
int selectedRow) {
Mounted eq = (Mounted)
equipmentTable.getModel().getValueAt(selectedRow,
CriticalTableModel.EQUIPMENT);
try {
getAero().addEquipment(eq, location, false);
} catch (Exception ex) {
ex.printStackTrace();
}
UnitUtil.changeMountStatus(getAero(), eq, location, -1, false);
// go back up to grandparent build tab and fire a full refresh.
((BuildTab) getParent().getParent()).refreshAll();
}
}