/* * 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.BattleArmor.views; 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.BoxLayout; import javax.swing.JMenuItem; import javax.swing.JPanel; 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.BattleArmor; import megamek.common.EquipmentType; import megamek.common.MiscType; import megamek.common.Mounted; import megamek.common.WeaponType; import megamek.common.verifier.TestBattleArmor; import megamek.common.weapons.Weapon; import megamek.common.weapons.infantry.InfantryWeapon; import megameklab.com.ui.EntitySource; import megameklab.com.ui.BattleArmor.tabs.BuildTab; import megameklab.com.util.CriticalTableModel; import megameklab.com.util.CriticalTransferHandler; import megameklab.com.util.IView; import megameklab.com.util.RefreshListener; import megameklab.com.util.StringUtils; import megameklab.com.util.UnitUtil; /** * A component that display a table listing all of the unallocated equipment * for the squad and allows dragging of the equipment to criticals to mount it. * * @author Taharqa * @author arlith * */ public class BuildView extends IView implements ActionListener, MouseListener { /** * */ private static final long serialVersionUID = 799195356642563937L; private JPanel mainPanel = new JPanel(); private CriticalTableModel equipmentList; private Vector<Mounted> masterEquipmentList = new Vector<Mounted>(10, 1); private JTable equipmentTable = new JTable(); private JScrollPane equipmentScroll = new JScrollPane(); public BuildView(EntitySource eSource) { super(eSource); mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS)); equipmentList = new CriticalTableModel(getBattleArmor(), CriticalTableModel.BUILDTABLE); equipmentTable.setModel(equipmentList); equipmentTable.setDragEnabled(true); CriticalTransferHandler cth = new CriticalTransferHandler(eSource, null); equipmentTable.setTransferHandler(cth); equipmentList.initColumnSizes(equipmentTable); 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.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); // equipmentScroll.setToolTipText(""); // equipmentScroll.setPreferredSize(new Dimension(getWidth(), // getHeight())); equipmentTable.setDoubleBuffered(true); equipmentScroll.setViewportView(equipmentTable); equipmentScroll.setMinimumSize(new java.awt.Dimension(450, 450)); equipmentScroll.setPreferredSize(new java.awt.Dimension(450, 450)); equipmentScroll.setTransferHandler(cth); mainPanel.add(equipmentScroll); equipmentTable.addMouseListener(this); this.add(mainPanel); // loadEquipmentTable(); setBorder(BorderFactory.createTitledBorder( BorderFactory.createEmptyBorder(), "Unallocated Equipment", TitledBorder.TOP, TitledBorder.DEFAULT_POSITION)); } public void addRefreshedListener(RefreshListener l) { } private void loadEquipmentTable() { equipmentList.removeAllCrits(); masterEquipmentList.clear(); for (Mounted mount : getBattleArmor().getMisc()) { if ((mount.getBaMountLoc() == BattleArmor.MOUNT_LOC_NONE && !mount.getType().hasFlag(MiscType.F_BA_MANIPULATOR) && !mount.getName().contains("BA Standard"))) { masterEquipmentList.add(mount); } } for (Mounted mount : getBattleArmor().getWeaponList()) { // Don't display weapons mounted in a detachable weapon pack if (mount.isDWPMounted() || mount.isAPMMounted()){ continue; } if ((mount.getBaMountLoc() == BattleArmor.MOUNT_LOC_NONE) && (UnitUtil.isBattleArmorWeapon(mount.getType(), getBattleArmor()) || UnitUtil.isBattleArmorAPWeapon(mount.getType()))) { masterEquipmentList.add(mount); } } for (Mounted mount : getBattleArmor().getAmmo()) { // Ignore ammo for one-shot launchers if (mount.getLinkedBy() != null && mount.getLinkedBy().isOneShot()){ continue; } // Ignore DWP-mounted ammo if (mount.isDWPMounted()){ continue; } if (mount.getBaMountLoc() == BattleArmor.MOUNT_LOC_NONE) { masterEquipmentList.add(mount); } } Collections.sort(masterEquipmentList, StringUtils.mountedComparator()); // 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.isTSM(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 for (int pos = 0; pos < masterEquipmentList.size(); pos++) { equipmentList.addCrit(masterEquipmentList.get(pos)); } } public void refresh() { removeAllListeners(); loadEquipmentTable(); fireTableRefresh(); addAllListeners(); } private void removeAllListeners() { } private void addAllListeners() { } public void actionPerformed(ActionEvent e) { fireTableRefresh(); } private void fireTableRefresh() { equipmentList.updateUnit(getBattleArmor()); equipmentList.refreshModel(); // equipmentScroll.setPreferredSize(new Dimension(getWidth() * 90 / 100, // getHeight() * 90 / 100)); // equipmentScroll.setBounds(0, 0, getWidth(), getHeight()); // equipmentScroll.repaint(); } 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()); final Mounted eq = (Mounted)equipmentTable.getModel().getValueAt( selectedRow, CriticalTableModel.EQUIPMENT); final String[] locNames = BattleArmor.MOUNT_LOC_NAMES; // A list of the valid locations we can add the selected eq to ArrayList<Integer> validLocs = new ArrayList<Integer>(); int numLocs = BattleArmor.MOUNT_NUM_LOCS; for (int loc = 0; loc < numLocs; loc++){ if (TestBattleArmor.isMountLegal(getBattleArmor(), eq, loc)){ validLocs.add(loc); } } if (eq.getLocation() == BattleArmor.LOC_SQUAD && !(eq.getType() instanceof InfantryWeapon)){ // Add a menu item for each potential location for (Integer location: validLocs) { if (UnitUtil.isValidLocation(getBattleArmor(), eq.getType(), location)) { item = new JMenuItem("Add to " + locNames[location]); final int loc = location; item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { mountEquipmentInLocation(loc, selectedRow); } }); popup.add(item); } } if (!UnitUtil.isArmor(eq.getType()) && !eq.isSquadSupportWeapon()) { item = new JMenuItem("Make individual weapon"); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { eq.setLocation(BattleArmor.LOC_TROOPER_1); ((BuildTab) getParent().getParent()).refreshAll(); } }); popup.add(item); } } else { if (!UnitUtil.isArmor(eq.getType()) && !(eq.getType() instanceof InfantryWeapon) && !((eq.getType() instanceof WeaponType) && (eq.getType().hasFlag(WeaponType.F_TASER) || ((WeaponType)eq.getType()).getAmmoType() == AmmoType.T_NARC))) { item = new JMenuItem("Make squad weapon"); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { eq.setLocation(BattleArmor.LOC_SQUAD); ((BuildTab) getParent().getParent()).refreshAll(); } }); popup.add(item); } } // Allow number of shots selection if ((getBattleArmor() instanceof BattleArmor) && eq.getType() instanceof AmmoType){ AmmoType at = (AmmoType) eq.getType(); int maxNumShots = 4; int stepSize = 1; if (at.getAmmoType() == AmmoType.T_BA_TUBE) { maxNumShots = 8; stepSize = 2; } for (int i = at.getShots(); i <= maxNumShots; i += stepSize){ if (i == eq.getBaseShotsLeft()){ continue; } item = new JMenuItem("Set Shots: " + i); final int shots = i; item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { eq.setShotsLeft(shots); ((BuildTab) getParent().getParent()).refreshAll(); } }); popup.add(item); } } // Allow making this a squad support weapon if ((eq.getType() instanceof WeaponType) && !eq.isSquadSupportWeapon() && !eq.getType().hasFlag(WeaponType.F_INFANTRY) && eq.getLocation() == BattleArmor.LOC_SQUAD && getBattleArmor().getChassisType() != BattleArmor.CHASSIS_TYPE_QUAD){ item = new JMenuItem("Mount as squad support weapon"); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { eq.setSquadSupportWeapon(true); ((BuildTab) getParent().getParent()).refreshAll(); } }); popup.add(item); } // Adding ammo as a squad support mount is slightly different if ((eq.getType() instanceof AmmoType) && !eq.getType().hasFlag(WeaponType.F_MISSILE) && !eq.isSquadSupportWeapon() && eq.getLocation() == BattleArmor.LOC_SQUAD && getBattleArmor().getChassisType() != BattleArmor.CHASSIS_TYPE_QUAD){ boolean enabled = false; for (Mounted weapon : getBattleArmor().getWeaponList()){ WeaponType wtype = (WeaponType)weapon.getType(); if (weapon.isSquadSupportWeapon() && AmmoType.isAmmoValid(eq, wtype)){ enabled = true; } } item = new JMenuItem("Mount as squad support weapon"); item.setEnabled(enabled); item.setToolTipText("Ammo can only be squad mounted along " + "with a weapon that uses it"); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { eq.setSquadSupportWeapon(true); ((BuildTab) getParent().getParent()).refreshAll(); } }); popup.add(item); } // Allow removing squad support weapon if (eq.isSquadSupportWeapon()){ item = new JMenuItem("Remove squad support weapon mount"); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { eq.setSquadSupportWeapon(false); // Can't have squad support weapon ammo with no // squad support weapon for (Mounted ammo : getBattleArmor().getAmmo()){ ammo.setSquadSupportWeapon(false); } ((BuildTab) getParent().getParent()).refreshAll(); } }); popup.add(item); } // See if we should allow linking this to a DWP if (getBattleArmor().hasWorkingMisc(MiscType.F_DETACHABLE_WEAPON_PACK) && !eq.getType().hasFlag(MiscType.F_DETACHABLE_WEAPON_PACK) && !eq.getType().hasFlag(WeaponType.F_MISSILE) && !(eq.getType() instanceof AmmoType) && !eq.isDWPMounted() && (getBattleArmor()).canMountDWP()){ for (Mounted m : getBattleArmor().getMisc()){ // If this isn't a DWP or it's a full DWP, skip if (!m.getType().hasFlag(MiscType.F_DETACHABLE_WEAPON_PACK) || m.getLinked() != null){ continue; } String locName; if (m.getBaMountLoc() == BattleArmor.MOUNT_LOC_NONE){ locName = "None"; } else { locName = BattleArmor.MOUNT_LOC_NAMES[m.getBaMountLoc()]; } item = new JMenuItem("Mount in " + m.getName() + " (" + locName + ")"); final Mounted dwp = m; item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { eq.setLinked(dwp); dwp.setLinked(eq); eq.setDWPMounted(true); ((BuildTab) getParent().getParent()).refreshAll(); } }); popup.add(item); } } // Should we allow mounting Ammo in a DWP? if ((eq.getType() instanceof AmmoType) && getBattleArmor().hasWorkingMisc(MiscType.F_DETACHABLE_WEAPON_PACK) && !eq.isDWPMounted() && (getBattleArmor()).canMountDWP()){ for (final Mounted m : getBattleArmor().getMisc()){ // If this isn't a DWP, skip if (!m.getType().hasFlag( MiscType.F_DETACHABLE_WEAPON_PACK)){ continue; } // We only want to enable the menu item if the DWP has a // mounted weapon and we clicked on a valid ammo type boolean enabled = false; if (m.getLinked() != null){ EquipmentType etype = m.getLinked().getType(); if (etype instanceof WeaponType){ WeaponType wtype = (WeaponType)etype; if (AmmoType.isAmmoValid(eq, wtype)){ enabled = true; } } } String locName; if (m.getBaMountLoc() == BattleArmor.MOUNT_LOC_NONE){ locName = "None"; } else { locName = BattleArmor.MOUNT_LOC_NAMES[m.getBaMountLoc()]; } item = new JMenuItem("Mount in " + m.getName() + " (" + locName + ")"); item.setToolTipText("Ammo can only be mounted in a DWP " + "with a valid weapon."); item.setEnabled(enabled); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { m.getLinked().setLinked(eq); eq.setDWPMounted(true); ((BuildTab) getParent().getParent()).refreshAll(); } }); popup.add(item); } } // Right-clicked on a DWP that has an attached weapon if (eq.getType().hasFlag(MiscType.F_DETACHABLE_WEAPON_PACK) && eq.getLinked() != null){ item = new JMenuItem("Remove attached weapon"); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Mounted attached = eq.getLinked(); attached.setDWPMounted(false); eq.setLinked(null); eq.setLinkedBy(null); attached.setLinked(null); attached.setLinkedBy(null); // Remove any attached ammo for (Mounted ammo : getBattleArmor().getAmmo()){ if (attached.equals(ammo.getLinkedBy())){ ammo.setDWPMounted(false); ammo.setLinked(null); ammo.setLinkedBy(null); } } ((BuildTab) getParent().getParent()).refreshAll(); } }); popup.add(item); } // See if we should allow linking this to an AP Mount if (getBattleArmor().hasWorkingMisc(MiscType.F_AP_MOUNT) && eq.getType().hasFlag(WeaponType.F_INFANTRY) && !eq.isAPMMounted()){ for (Mounted m : getBattleArmor().getMisc()){ // If this isn't an AP Mount or it's a full AP Mount, skip if (!m.getType().hasFlag(MiscType.F_AP_MOUNT) || m.getLinked() != null){ continue; } // Armored gloves can only carry 1 additional weapon, // regardless of the number of gloves if (m.getType().hasFlag(MiscType.F_ARMORED_GLOVE)) { boolean hasUsedGlove = false; for (Mounted m2 : getBattleArmor().getMisc()){ if (m2.getType().hasFlag(MiscType.F_ARMORED_GLOVE) && (m2.getLinked() != null)) { hasUsedGlove = true; } } if (hasUsedGlove) { continue; } } // Only armored gloves can carry infantry support weapons if (!m.getType().hasFlag(MiscType.F_ARMORED_GLOVE) && eq.getType().hasFlag(WeaponType.F_INF_SUPPORT)) { continue; } String locName; if (m.getBaMountLoc() == BattleArmor.MOUNT_LOC_NONE){ locName = "None"; } else { locName = BattleArmor.MOUNT_LOC_NAMES[m.getBaMountLoc()]; } item = new JMenuItem("Mount in " + m.getName() + " (" + locName + ")"); final Mounted apm = m; item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { eq.setLinked(apm); apm.setLinked(eq); eq.setAPMMounted(true); ((BuildTab) getParent().getParent()).refreshAll(); } }); popup.add(item); } } // Right-clicked on a AP Mount that has an attached weapon if (eq.getType().hasFlag(MiscType.F_AP_MOUNT) && eq.getLinked() != null){ item = new JMenuItem("Remove attached weapon"); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Mounted attached = eq.getLinked(); attached.setAPMMounted(false); eq.setLinked(null); eq.setLinkedBy(null); attached.setLinked(null); attached.setLinkedBy(null); ((BuildTab) getParent().getParent()).refreshAll(); } }); 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 mountEquipmentInLocation(int location, int selectedRow) { Mounted eq = (Mounted) equipmentTable.getModel().getValueAt(selectedRow, CriticalTableModel.EQUIPMENT); try { eq.setBaMountLoc(location); } catch (Exception ex) { ex.printStackTrace(); } UnitUtil.changeMountStatus(getBattleArmor(), eq, BattleArmor.LOC_SQUAD, -1, false); // go back up to grandparent build tab and fire a full refresh. ((BuildTab) getParent().getParent()).refreshAll(); } }