/* * MMLMekUICustom.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.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.io.File; import java.util.Calendar; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.BorderFactory; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTabbedPane; import megamek.common.Aero; import megamek.common.AmmoType; import megamek.common.BattleArmor; import megamek.common.Engine; import megamek.common.Entity; import megamek.common.Infantry; import megamek.common.Mech; import megamek.common.MechFileParser; import megamek.common.MechSummary; import megamek.common.MechSummaryCache; import megamek.common.Mounted; import megamek.common.Tank; import megamek.common.WeaponType; import megamek.common.loaders.EntityLoadingException; import megamek.common.verifier.EntityVerifier; import megamek.common.verifier.TestAero; import megamek.common.verifier.TestBattleArmor; import megamek.common.verifier.TestEntity; import megamek.common.verifier.TestInfantry; import megamek.common.verifier.TestMech; import megamek.common.verifier.TestTank; import megameklab.com.MegaMekLab; import megameklab.com.ui.EntitySource; import megameklab.com.util.CConfig; import megameklab.com.util.RefreshListener; import megameklab.com.util.UnitUtil; import mekhq.MekHQ; import mekhq.Utilities; import mekhq.campaign.parts.Refit; import mekhq.campaign.unit.Unit; public class MekLabTab extends CampaignGuiTab { private static final long serialVersionUID = -5836932822468918198L; CampaignGUI campaignGUI; Unit unit; TestEntity testEntity; EntityVerifier entityVerifier; Refit refit; EntityPanel labPanel; JPanel summaryPane = new JPanel(); JPanel emptyPanel; private JLabel lblName; private JPanel refitPanel; private JLabel lblRefit; private JLabel lblTime; private JLabel lblCost; private JButton btnRefit; private JButton btnClear; private JButton btnRemove; private JPanel statPanel; private JLabel lblMove; private JLabel lblBV; private JLabel lblHeat; private JLabel lblTons; private JPanel shoppingPanel; MekLabTab(CampaignGUI gui, String name) { super(gui, name); this.campaignGUI = gui; this.repaint(); } @Override public void initTab() { entityVerifier = EntityVerifier.getInstance(new File("data/mechfiles/UnitVerifierOptions.xml")); UnitUtil.loadFonts(); new CConfig(); MekHQ.logMessage("Staring MegaMekLab version: " + MegaMekLab.VERSION); btnRefit = new JButton("Begin Refit"); btnRefit.addActionListener(evt -> { Entity entity = labPanel.getEntity(); if (null != entity && entity.getWeight() > testEntity.calculateWeight()) { int response = JOptionPane.showConfirmDialog(null, "This unit is underweight. Do you want to continue?", "Underweight Unit", JOptionPane.YES_NO_OPTION); if (response == JOptionPane.NO_OPTION) { return; } } campaignGUI.refitUnit(refit, true); }); btnClear = new JButton("Clear Changes"); btnClear.addActionListener(evt -> resetUnit()); btnRemove = new JButton("Remove from Lab"); btnRemove.addActionListener(evt -> clearUnit()); setLayout(new BorderLayout()); emptyPanel = new JPanel(new BorderLayout()); emptyPanel.add(new JLabel("No Unit Loaded"), BorderLayout.PAGE_START); add(emptyPanel, BorderLayout.CENTER); } @Override public void refreshAll() { // TODO Auto-generated method stub } @Override public GuiTabType tabType() { return GuiTabType.MEKLAB; } public Unit getUnit() { return unit; } public void loadUnit(Unit u) { unit = u; MechSummary mechSummary = MechSummaryCache.getInstance().getMech(unit.getEntity().getShortNameRaw()); Entity entity = null; try { entity = (new MechFileParser(mechSummary.getSourceFile(), mechSummary.getEntryName())).getEntity(); } catch (EntityLoadingException ex) { Logger.getLogger(CampaignGUI.class.getName()).log(Level.SEVERE, null, ex); } entity.setYear(unit.campaign.getCalendar().get(Calendar.YEAR)); UnitUtil.updateLoadedMech(entity); entity.setModel(entity.getModel() + " Mk II"); removeAll(); labPanel = getCorrectLab(entity); refreshSummary(); add(summaryPane, BorderLayout.LINE_START); add(labPanel, BorderLayout.CENTER); labPanel.refreshAll(); } public void clearUnit() { this.unit = null; removeAll(); add(emptyPanel, BorderLayout.CENTER); this.repaint(); } public void resetUnit() { MechSummary mechSummary = MechSummaryCache.getInstance().getMech(unit.getEntity().getShortName()); Entity entity = null; try { entity = (new MechFileParser(mechSummary.getSourceFile(), mechSummary.getEntryName())).getEntity(); } catch (EntityLoadingException ex) { Logger.getLogger(CampaignGUI.class.getName()).log(Level.SEVERE, null, ex); } entity.setYear(unit.campaign.getCalendar().get(Calendar.YEAR)); UnitUtil.updateLoadedMech(entity); removeAll(); labPanel = getCorrectLab(entity); refreshSummary(); add(summaryPane, BorderLayout.LINE_START); add(labPanel, BorderLayout.CENTER); labPanel.refreshAll(); } public void refreshSummary() { if (null == labPanel) { return; } Entity entity = labPanel.getEntity(); if (null == entity) { return; } refit = new Refit(unit, entity, true, false); testEntity = null; if (entity instanceof Aero) { testEntity = new TestAero((Aero) entity, entityVerifier.aeroOption, null); } else if (entity instanceof Mech) { testEntity = new TestMech((Mech) entity, entityVerifier.mechOption, null); } else if (entity instanceof Tank) { testEntity = new TestTank((Tank) entity, entityVerifier.tankOption, null); } else if (entity instanceof BattleArmor) { testEntity = new TestBattleArmor((BattleArmor) entity, entityVerifier.baOption, null); } else if (entity instanceof Infantry) { testEntity = new TestInfantry((Infantry) entity, entityVerifier.tankOption, null); } if (null == testEntity) { return; } StringBuffer sb = new StringBuffer(); testEntity.correctEntity(sb); int walk = entity.getOriginalWalkMP(); int run = entity.getRunMP(); if (entity instanceof Mech) { run = ((Mech) entity).getOriginalRunMPwithoutMASC(); } int jump = entity.getOriginalJumpMP(); int heat = entity.getHeatCapacity(); double totalHeat = calculateTotalHeat(); int bvDiff = entity.calculateBattleValue(true, true) - unit.getEntity().calculateBattleValue(true, true); double currentTonnage = testEntity.calculateWeight(); currentTonnage += UnitUtil.getUnallocatedAmmoTonnage(entity); double tonnage = entity.getWeight(); if (entity.getWeight() < testEntity.calculateWeight()) { btnRefit.setEnabled(false); btnRefit.setToolTipText("Unit is overweight."); // } else if (entity.getWeight() > testEntity.calculateWeight()) { // Taharqa: We are now going to allow users to build underweight // units, we will just give // them an are you sure warning pop up // btnRefit.setEnabled(false); // btnRefit.setToolTipText("Unit is underweight."); } else if (sb.length() > 0) { btnRefit.setEnabled(false); btnRefit.setToolTipText(sb.toString()); } else if (null != refit.checkFixable()) { btnRefit.setEnabled(false); btnRefit.setToolTipText(refit.checkFixable()); } else if (refit.getRefitClass() == Refit.NO_CHANGE && entity.getWeight() == testEntity.calculateWeight()) { btnRefit.setEnabled(false); btnRefit.setToolTipText("Nothing to change."); } else { btnRefit.setEnabled(true); btnRefit.setToolTipText(null); } summaryPane.removeAll(); summaryPane.setLayout(new GridBagLayout()); GridBagConstraints c = new GridBagConstraints(); lblName = new JLabel("<html><b>" + unit.getName() + "</b></html>"); lblRefit = new JLabel(refit.getRefitClassName()); lblTime = new JLabel(refit.getTime() + " minutes"); lblCost = new JLabel(Utilities.getCurrencyString(refit.getCost())); lblMove = new JLabel("Movement: " + walk + "/" + run + "/" + jump); if (bvDiff > 0) { lblBV = new JLabel("<html>BV: " + entity.calculateBattleValue(true, true) + " (<font color='green'>+" + bvDiff + "</font>)</html>"); } else if (bvDiff < 0) { lblBV = new JLabel("<html>BV: " + entity.calculateBattleValue(true, true) + " (<font color='red'>" + bvDiff + "</font>)</html>"); } else { lblBV = new JLabel("<html>BV: " + entity.calculateBattleValue(true, true) + " (+" + bvDiff + ")</html>"); } if (currentTonnage != tonnage) { lblTons = new JLabel( "<html>Tonnage: <font color='red'>" + currentTonnage + "/" + tonnage + "</font></html>"); } else { lblTons = new JLabel("Tonnage: " + currentTonnage + "/" + tonnage); } if (totalHeat > heat) { lblHeat = new JLabel("<html>Heat: <font color='red'>" + totalHeat + "/" + heat + "</font></html>"); } else { lblHeat = new JLabel("<html>Heat: " + totalHeat + "/" + heat + "</html>"); } refitPanel = new JPanel(); refitPanel.setLayout(new BoxLayout(refitPanel, BoxLayout.PAGE_AXIS)); refitPanel.setBorder(BorderFactory.createTitledBorder("Refit Statistics")); refitPanel.add(lblRefit); refitPanel.add(lblTime); refitPanel.add(lblCost); statPanel = new JPanel(); statPanel.setLayout(new BoxLayout(statPanel, BoxLayout.PAGE_AXIS)); statPanel.setBorder(BorderFactory.createTitledBorder("Unit Statistics")); statPanel.add(lblMove); statPanel.add(lblBV); statPanel.add(lblTons); statPanel.add(lblHeat); shoppingPanel = new JPanel(); shoppingPanel.setLayout(new BoxLayout(shoppingPanel, BoxLayout.PAGE_AXIS)); shoppingPanel.setBorder(BorderFactory.createTitledBorder("Needed Parts")); JLabel lblItem; for (String name : refit.getShoppingListDescription()) { lblItem = new JLabel(name); shoppingPanel.add(lblItem); } if (refit.getShoppingListDescription().length == 0) { lblItem = new JLabel("None"); shoppingPanel.add(lblItem); } c.gridx = 0; c.gridy = 0; c.anchor = GridBagConstraints.NORTHWEST; c.fill = GridBagConstraints.HORIZONTAL; c.insets = new Insets(10, 5, 2, 5); summaryPane.add(lblName, c); c.gridy++; c.insets = new Insets(0, 5, 2, 5); summaryPane.add(btnRefit, c); c.gridy++; summaryPane.add(btnClear, c); c.gridy++; summaryPane.add(btnRemove, c); c.gridy++; summaryPane.add(statPanel, c); c.gridy++; summaryPane.add(refitPanel, c); c.gridy++; c.weighty = 1.0; summaryPane.add(shoppingPanel, c); // TODO: compare units dialog that pops up mech views back-to-back } public double calculateTotalHeat() { double heat = 0; Entity entity = labPanel.getEntity(); if (entity.getOriginalJumpMP() > 0 && !(entity instanceof Infantry)) { if (entity.getJumpType() == Mech.JUMP_IMPROVED) { heat += Math.max(3, entity.getOriginalJumpMP() / 2); } else if (entity.getJumpType() != Mech.JUMP_BOOSTER) { heat += Math.max(3, entity.getOriginalJumpMP()); } if (entity.getEngine().getEngineType() == Engine.XXL_ENGINE) { heat *= 2; } } else if (!(entity instanceof Infantry) && entity.getEngine().getEngineType() == Engine.XXL_ENGINE) { heat += 6; } else if (!(entity instanceof Infantry)) { heat += 2; } if (entity instanceof Mech) { if (((Mech) entity).hasNullSig()) { heat += 10; } if (((Mech) entity).hasChameleonShield()) { heat += 6; } } for (Mounted mounted : entity.getWeaponList()) { WeaponType wtype = (WeaponType) mounted.getType(); double weaponHeat = wtype.getHeat(); // only count non-damaged equipment if (mounted.isMissing() || mounted.isHit() || mounted.isDestroyed() || mounted.isBreached()) { continue; } // one shot weapons count 1/4 if ((wtype.getAmmoType() == AmmoType.T_ROCKET_LAUNCHER) || wtype.hasFlag(WeaponType.F_ONESHOT)) { weaponHeat *= 0.25; } // double heat for ultras if ((wtype.getAmmoType() == AmmoType.T_AC_ULTRA) || (wtype.getAmmoType() == AmmoType.T_AC_ULTRA_THB)) { weaponHeat *= 2; } // Six times heat for RAC if (wtype.getAmmoType() == AmmoType.T_AC_ROTARY) { weaponHeat *= 6; } // half heat for streaks if ((wtype.getAmmoType() == AmmoType.T_SRM_STREAK) || (wtype.getAmmoType() == AmmoType.T_MRM_STREAK) || (wtype.getAmmoType() == AmmoType.T_LRM_STREAK)) { weaponHeat *= 0.5; } heat += weaponHeat; } return heat; } private EntityPanel getCorrectLab(Entity en) { if (en instanceof Aero) { return new AeroPanel((Aero) en); } else if (en instanceof Mech) { return new MekPanel((Mech) en); } else if (en instanceof Tank) { return new TankPanel((Tank) en); } else if (en instanceof BattleArmor) { return new BattleArmorPanel((BattleArmor) en); } else if (en instanceof Infantry) { return new InfantryPanel((Infantry) en); } return null; } private abstract class EntityPanel extends JTabbedPane implements RefreshListener, EntitySource { /** * */ private static final long serialVersionUID = 6886946112861955446L; @Override public abstract Entity getEntity(); } private class AeroPanel extends EntityPanel { /** * */ private static final long serialVersionUID = 6894731868670529166L; private Aero entity; private megameklab.com.ui.Aero.tabs.StructureTab structureTab; private megameklab.com.ui.Aero.tabs.EquipmentTab equipmentTab; private megameklab.com.ui.Aero.tabs.BuildTab buildTab; private megameklab.com.ui.Aero.tabs.PreviewTab previewTab; public AeroPanel(Aero a) { entity = a; reloadTabs(); } @Override public Entity getEntity() { return entity; } public void reloadTabs() { removeAll(); structureTab = new megameklab.com.ui.Aero.tabs.StructureTab(this); structureTab.setAsCustomization(); previewTab = new megameklab.com.ui.Aero.tabs.PreviewTab(this); equipmentTab = new megameklab.com.ui.Aero.tabs.EquipmentTab(this); buildTab = new megameklab.com.ui.Aero.tabs.BuildTab(this, equipmentTab); structureTab.addRefreshedListener(this); equipmentTab.addRefreshedListener(this); buildTab.addRefreshedListener(this); addTab("Structure/Armor", new JScrollPane(structureTab)); addTab("Equipment", new JScrollPane(equipmentTab)); addTab("Assign Criticals", new JScrollPane(buildTab)); addTab("Preview", new JScrollPane(previewTab)); this.repaint(); } @Override public void refreshAll() { structureTab.refresh(); equipmentTab.refresh(); buildTab.refresh(); previewTab.refresh(); refreshSummary(); } @Override public void refreshArmor() { refreshSummary(); } @Override public void refreshBuild() { buildTab.refresh(); refreshSummary(); } @Override public void refreshEquipment() { equipmentTab.refresh(); refreshSummary(); } @Override public void refreshStatus() { refreshSummary(); } @Override public void refreshStructure() { structureTab.refresh(); refreshSummary(); } @Override public void refreshWeapons() { refreshSummary(); } @Override public void refreshHeader() { } @Override public void refreshPreview() { previewTab.refresh(); } } private class MekPanel extends EntityPanel { /** * */ private static final long serialVersionUID = 6894731868670529166L; private Mech entity; private megameklab.com.ui.Mek.tabs.StructureTab structureTab; private megameklab.com.ui.Mek.tabs.EquipmentTab equipmentTab; private megameklab.com.ui.Mek.tabs.BuildTab buildTab; private megameklab.com.ui.Mek.tabs.PreviewTab previewTab; public MekPanel(Mech m) { entity = m; reloadTabs(); } @Override public Entity getEntity() { return entity; } public void reloadTabs() { removeAll(); structureTab = new megameklab.com.ui.Mek.tabs.StructureTab(this); structureTab.setAsCustomization(); equipmentTab = new megameklab.com.ui.Mek.tabs.EquipmentTab(this); previewTab = new megameklab.com.ui.Mek.tabs.PreviewTab(this); buildTab = new megameklab.com.ui.Mek.tabs.BuildTab(this, equipmentTab); structureTab.addRefreshedListener(this); equipmentTab.addRefreshedListener(this); buildTab.addRefreshedListener(this); addTab("Structure/Armor", new JScrollPane(structureTab)); addTab("Equipment", new JScrollPane(equipmentTab)); addTab("Assign Critical", new JScrollPane(buildTab)); addTab("Preview", new JScrollPane(previewTab)); this.repaint(); } @Override public void refreshAll() { structureTab.refresh(); equipmentTab.refresh(); buildTab.refresh(); previewTab.refresh(); refreshSummary(); } @Override public void refreshArmor() { refreshSummary(); } @Override public void refreshBuild() { buildTab.refresh(); refreshSummary(); } @Override public void refreshEquipment() { equipmentTab.refresh(); refreshSummary(); } @Override public void refreshStatus() { refreshSummary(); } @Override public void refreshStructure() { structureTab.refresh(); refreshSummary(); } @Override public void refreshWeapons() { refreshSummary(); } @Override public void refreshHeader() { } @Override public void refreshPreview() { previewTab.refresh(); } } private class TankPanel extends EntityPanel { /** * */ private static final long serialVersionUID = 6894731868670529166L; private Tank entity; private megameklab.com.ui.Vehicle.tabs.StructureTab structureTab; private megameklab.com.ui.Vehicle.tabs.EquipmentTab equipmentTab; private megameklab.com.ui.Vehicle.tabs.BuildTab buildTab; public TankPanel(Tank t) { entity = t; reloadTabs(); } @Override public Entity getEntity() { return entity; } public void reloadTabs() { removeAll(); structureTab = new megameklab.com.ui.Vehicle.tabs.StructureTab(this); equipmentTab = new megameklab.com.ui.Vehicle.tabs.EquipmentTab(this); buildTab = new megameklab.com.ui.Vehicle.tabs.BuildTab(this, equipmentTab); structureTab.addRefreshedListener(this); equipmentTab.addRefreshedListener(this); buildTab.addRefreshedListener(this); addTab("Structure", new JScrollPane(structureTab)); addTab("Equipment", new JScrollPane(equipmentTab)); addTab("Build", new JScrollPane(buildTab)); this.repaint(); } @Override public void refreshAll() { structureTab.refresh(); equipmentTab.refresh(); buildTab.refresh(); refreshSummary(); } @Override public void refreshArmor() { refreshSummary(); } @Override public void refreshBuild() { buildTab.refresh(); refreshSummary(); } @Override public void refreshEquipment() { equipmentTab.refresh(); refreshSummary(); } @Override public void refreshStatus() { refreshSummary(); } @Override public void refreshStructure() { structureTab.refresh(); refreshSummary(); } @Override public void refreshWeapons() { refreshSummary(); } @Override public void refreshHeader() { } @Override public void refreshPreview() { } } private class BattleArmorPanel extends EntityPanel { /** * */ private static final long serialVersionUID = 6894731868670529166L; private BattleArmor entity; private megameklab.com.ui.BattleArmor.tabs.StructureTab structureTab; private megameklab.com.ui.BattleArmor.tabs.EquipmentTab equipmentTab; private megameklab.com.ui.BattleArmor.tabs.BuildTab buildTab; public BattleArmorPanel(BattleArmor ba) { entity = ba; reloadTabs(); } @Override public Entity getEntity() { return entity; } public void reloadTabs() { removeAll(); structureTab = new megameklab.com.ui.BattleArmor.tabs.StructureTab(this); structureTab.setAsCustomization(); equipmentTab = new megameklab.com.ui.BattleArmor.tabs.EquipmentTab(this); buildTab = new megameklab.com.ui.BattleArmor.tabs.BuildTab(this); structureTab.addRefreshedListener(this); equipmentTab.addRefreshedListener(this); buildTab.addRefreshedListener(this); addTab("Structure", new JScrollPane(structureTab)); addTab("Equipment", new JScrollPane(equipmentTab)); addTab("Assign Criticals", new JScrollPane(buildTab)); this.repaint(); } @Override public void refreshAll() { structureTab.refresh(); equipmentTab.refresh(); buildTab.refresh(); refreshSummary(); } @Override public void refreshArmor() { refreshSummary(); } @Override public void refreshBuild() { buildTab.refresh(); refreshSummary(); } @Override public void refreshEquipment() { equipmentTab.refresh(); refreshSummary(); } @Override public void refreshStatus() { refreshSummary(); } @Override public void refreshStructure() { structureTab.refresh(); refreshSummary(); } @Override public void refreshWeapons() { refreshSummary(); } @Override public void refreshHeader() { } @Override public void refreshPreview() { structureTab.refresh(); } } private class InfantryPanel extends EntityPanel { /** * */ private static final long serialVersionUID = 6894731868670529166L; private Infantry entity; private megameklab.com.ui.Infantry.tabs.StructureTab structureTab; private megameklab.com.ui.Infantry.tabs.PreviewTab previewTab; public InfantryPanel(Infantry inf) { entity = inf; reloadTabs(); } @Override public Entity getEntity() { return entity; } public void reloadTabs() { removeAll(); structureTab = new megameklab.com.ui.Infantry.tabs.StructureTab(this); structureTab.setAsCustomization(); structureTab.addRefreshedListener(this); previewTab = new megameklab.com.ui.Infantry.tabs.PreviewTab(this); addTab("Build", new JScrollPane(structureTab)); addTab("Preview", new JScrollPane(previewTab)); this.repaint(); } @Override public void refreshAll() { structureTab.refresh(); previewTab.refresh(); refreshSummary(); } @Override public void refreshArmor() { refreshSummary(); } @Override public void refreshBuild() { refreshSummary(); } @Override public void refreshEquipment() { refreshSummary(); } @Override public void refreshStatus() { refreshSummary(); } @Override public void refreshStructure() { structureTab.refresh(); refreshSummary(); } @Override public void refreshWeapons() { refreshSummary(); } @Override public void refreshHeader() { } @Override public void refreshPreview() { previewTab.refresh(); } } }