From 1df5dc1cf9b4114241e312dc260258d48a41f535 Mon Sep 17 00:00:00 2001 From: Pavel Braginskiy Date: Fri, 3 Jan 2025 18:25:33 -0800 Subject: [PATCH 1/2] New ways to open a new tab --- .../src/megameklab/ui/MegaMekLabTabbedUI.java | 101 ++++++++++++++++-- megameklab/src/megameklab/ui/MenuBar.java | 2 +- 2 files changed, 95 insertions(+), 8 deletions(-) diff --git a/megameklab/src/megameklab/ui/MegaMekLabTabbedUI.java b/megameklab/src/megameklab/ui/MegaMekLabTabbedUI.java index 0d8fae8da..bbb891685 100644 --- a/megameklab/src/megameklab/ui/MegaMekLabTabbedUI.java +++ b/megameklab/src/megameklab/ui/MegaMekLabTabbedUI.java @@ -348,17 +348,104 @@ public MenuBar getMMLMenuBar() { private class NewTabButton extends JPanel { public NewTabButton() { setOpaque(false); - var button = new JButton("➕"); - button.setForeground(Color.GREEN); - button.setFont(Font.getFont("Symbola")); - button.setFocusable(false); - button.setBorder(BorderFactory.createEmptyBorder()); + var newUnitButton = new JButton("➕"); + newUnitButton.setForeground(Color.GREEN); + newUnitButton.setFont(Font.getFont("Symbola")); + newUnitButton.setFocusable(false); + newUnitButton.setBorder(BorderFactory.createEmptyBorder()); + newUnitButton.setToolTipText("New Blank Mek
Right Click: Select Unit Type"); + + newUnitButton.addActionListener(e -> newTab()); + newUnitButton.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + if (e.isPopupTrigger()) { + newUnitPopupMenu().show(e.getComponent(), e.getX(), e.getY()); + } + } + + @Override + public void mouseReleased(MouseEvent e) { + if (e.isPopupTrigger()) { + newUnitPopupMenu().show(e.getComponent(), e.getX(), e.getY()); + } + } + }); + + add(newUnitButton); + + var loadUnitButton = new JButton("⌸"); + loadUnitButton.setFont(Font.getFont("Symbola")); + loadUnitButton.setForeground(Color.CYAN); + loadUnitButton.setFocusable(false); + loadUnitButton.setBorder(BorderFactory.createEmptyBorder()); + loadUnitButton.setToolTipText("Load unit from cache
Right Click: Load Unit Menu"); + + loadUnitButton.addActionListener(e -> StartupGUI.selectAndLoadUnitFromCache(MegaMekLabTabbedUI.this)); + loadUnitButton.addMouseListener(new MouseAdapter() { + + @Override + public void mousePressed(MouseEvent e) { + if (e.isPopupTrigger()) { + loadUnitMenu().show(e.getComponent(), e.getX(), e.getY()); + } + } + + @Override + public void mouseReleased(MouseEvent e) { + if (e.isPopupTrigger()) { + loadUnitMenu().show(e.getComponent(), e.getX(), e.getY()); + } + } + }); + + add(loadUnitButton); + } + + private JPopupMenu newUnitPopupMenu() { + var menu = new JPopupMenu(); + menu.add(newUnitItem("New Mek", Entity.ETYPE_MEK, false)); + menu.add(newUnitItem("New Fighter", Entity.ETYPE_AERO, false)); + menu.add(newUnitItem("New DropShip/Small Craft", Entity.ETYPE_DROPSHIP, false)); + menu.add(newUnitItem("New Advanced Aerospace", Entity.ETYPE_JUMPSHIP, false)); + menu.add(newUnitItem("New Tank", Entity.ETYPE_TANK, false)); + menu.add(newUnitItem("New Support Vehicle", Entity.ETYPE_SUPPORT_TANK, false)); + menu.add(newUnitItem("New Battle Armor", Entity.ETYPE_BATTLEARMOR, false)); + menu.add(newUnitItem("New Conventional Infantry", Entity.ETYPE_INFANTRY, false)); + menu.add(newUnitItem("New ProtoMek", Entity.ETYPE_PROTOMEK, false)); + + var primitive = new JMenu("New Primitive..."); + primitive.add(newUnitItem("New Mek", Entity.ETYPE_MEK, true)); + primitive.add(newUnitItem("New Fighter", Entity.ETYPE_AERO, true)); + primitive.add(newUnitItem("New DropShip/Small Craft", Entity.ETYPE_DROPSHIP, true)); + primitive.add(newUnitItem("New JumpShip", Entity.ETYPE_JUMPSHIP, true)); + + menu.add(primitive); + + return menu; + } - button.addActionListener(e -> { + private JMenuItem newUnitItem(String name, long entityType, boolean primitive) { + var item = new JMenuItem(name); + item.addActionListener(e -> { newTab(); + newUnit(entityType, primitive); }); + return item; + } + + private JPopupMenu loadUnitMenu() { + var menu = new JPopupMenu(); + + var fromCache = new JMenuItem("Load from cache"); + fromCache.addActionListener(e -> StartupGUI.selectAndLoadUnitFromCache(MegaMekLabTabbedUI.this)); + menu.add(fromCache); + + var fromFile = new JMenuItem("Load from file"); + fromFile.addActionListener(e -> getMMLMenuBar().loadUnitFromFile(-1)); + menu.add(fromFile); - add(button); + return menu; } } diff --git a/megameklab/src/megameklab/ui/MenuBar.java b/megameklab/src/megameklab/ui/MenuBar.java index 4ff5dd196..539e88a0a 100644 --- a/megameklab/src/megameklab/ui/MenuBar.java +++ b/megameklab/src/megameklab/ui/MenuBar.java @@ -1216,7 +1216,7 @@ private void exportSummary(ViewFormatting formatting) { } } - private void loadUnitFromFile(int fileNumber) { + public void loadUnitFromFile(int fileNumber) { File unitFile; if (fileNumber > 0) { String recentFileName = CConfig.getRecentFile(fileNumber); From b4ceda1954101abef7b33da0a938e75329240451 Mon Sep 17 00:00:00 2001 From: Pavel Braginskiy Date: Sun, 5 Jan 2025 03:41:11 -0800 Subject: [PATCH 2/2] When restoring tabs, remember unsaved equipment not given a location --- .../src/megameklab/ui/MegaMekLabMainUI.java | 9 ++++ .../megameklab/ui/battleArmor/BABuildTab.java | 5 ++ .../ui/battleArmor/BABuildView.java | 6 +++ .../megameklab/ui/battleArmor/BAMainUI.java | 14 +++-- .../ui/combatVehicle/CVBuildTab.java | 5 ++ .../megameklab/ui/combatVehicle/CVMainUI.java | 10 +++- .../megameklab/ui/fighterAero/ASBuildTab.java | 5 ++ .../ui/fighterAero/ASBuildView.java | 6 +++ .../megameklab/ui/fighterAero/ASMainUI.java | 16 +++--- .../ui/generalUnit/UnallocatedView.java | 6 +++ .../src/megameklab/ui/infantry/CIMainUI.java | 8 ++- .../src/megameklab/ui/largeAero/DSMainUI.java | 6 +++ .../megameklab/ui/largeAero/LABuildTab.java | 5 ++ .../megameklab/ui/largeAero/LABuildView.java | 5 ++ .../src/megameklab/ui/largeAero/WSMainUI.java | 6 +++ .../src/megameklab/ui/mek/BMBuildTab.java | 5 ++ .../src/megameklab/ui/mek/BMBuildView.java | 7 ++- .../src/megameklab/ui/mek/BMMainUI.java | 6 +++ .../megameklab/ui/protoMek/PMBuildTab.java | 5 ++ .../megameklab/ui/protoMek/PMBuildView.java | 6 +++ .../src/megameklab/ui/protoMek/PMMainUI.java | 6 +++ .../ui/supportVehicle/SVBuildTab.java | 5 ++ .../ui/supportVehicle/SVMainUI.java | 8 ++- .../src/megameklab/ui/util/TabStateUtil.java | 52 ++++++++++++++++--- 24 files changed, 187 insertions(+), 25 deletions(-) diff --git a/megameklab/src/megameklab/ui/MegaMekLabMainUI.java b/megameklab/src/megameklab/ui/MegaMekLabMainUI.java index a39cf3bb8..4f1789816 100644 --- a/megameklab/src/megameklab/ui/MegaMekLabMainUI.java +++ b/megameklab/src/megameklab/ui/MegaMekLabMainUI.java @@ -18,6 +18,7 @@ import megamek.MegaMek; import megamek.client.ui.swing.util.UIUtil; import megamek.common.Entity; +import megamek.common.Mounted; import megamek.common.preference.PreferenceManager; import megameklab.MMLConstants; import megameklab.MegaMekLab; @@ -212,4 +213,12 @@ public MenuBar getMMLMenuBar() { public void setOwner(MegaMekLabTabbedUI owner) { this.owner = owner; } + + /** + * Retrieves a list of mounted components that are currently not assigned to a location. + * Such equipment would be deleted on save and reload. + * + * @return a List containing unallocated Mounted objects. + */ + public abstract java.util.List> getUnallocatedMounted(); } diff --git a/megameklab/src/megameklab/ui/battleArmor/BABuildTab.java b/megameklab/src/megameklab/ui/battleArmor/BABuildTab.java index 71e7243f2..64b093e07 100644 --- a/megameklab/src/megameklab/ui/battleArmor/BABuildTab.java +++ b/megameklab/src/megameklab/ui/battleArmor/BABuildTab.java @@ -43,6 +43,11 @@ public class BABuildTab extends ITab { private RefreshListener refresh = null; private final ArrayList critViews = new ArrayList<>(); + + public BABuildView getBuildView() { + return buildView; + } + private final BABuildView buildView; /** Panel for displaying the critical trees for each trooper in the squad. */ diff --git a/megameklab/src/megameklab/ui/battleArmor/BABuildView.java b/megameklab/src/megameklab/ui/battleArmor/BABuildView.java index 7f15e8585..d56b0f903 100644 --- a/megameklab/src/megameklab/ui/battleArmor/BABuildView.java +++ b/megameklab/src/megameklab/ui/battleArmor/BABuildView.java @@ -20,6 +20,7 @@ import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.util.ArrayList; +import java.util.List; import java.util.Vector; import javax.swing.BorderFactory; @@ -66,6 +67,11 @@ public class BABuildView extends IView implements ActionListener, MouseListener private JPanel mainPanel = new JPanel(); private CriticalTableModel equipmentList; + + public List> getEquipment() { + return equipmentList.getCrits(); + } + private Vector> masterEquipmentList = new Vector<>(10, 1); private JTable equipmentTable = new JTable(); private JScrollPane equipmentScroll = new JScrollPane(); diff --git a/megameklab/src/megameklab/ui/battleArmor/BAMainUI.java b/megameklab/src/megameklab/ui/battleArmor/BAMainUI.java index 2ebc2574a..8a973a7ae 100644 --- a/megameklab/src/megameklab/ui/battleArmor/BAMainUI.java +++ b/megameklab/src/megameklab/ui/battleArmor/BAMainUI.java @@ -25,6 +25,7 @@ import javax.swing.*; import java.awt.*; +import java.util.List; public class BAMainUI extends MegaMekLabMainUI { @@ -123,7 +124,7 @@ public void refreshBuild() { public void refreshEquipment() { equipTab.refresh(); } - + @Override public void refreshTransport() { // not used for ba @@ -146,10 +147,10 @@ public void refreshWeapons() { } public void refreshPreview() { structureTab.refreshPreview(); } - + @Override public void refreshSummary() { } - + @Override public void refreshEquipmentTable() { equipTab.refreshTable(); @@ -164,4 +165,9 @@ public ITechManager getTechManager() { public JDialog getFloatingEquipmentDatabase() { return floatingEquipmentDatabase; } -} \ No newline at end of file + + @Override + public List> getUnallocatedMounted() { + return buildTab.getBuildView().getEquipment(); + } +} diff --git a/megameklab/src/megameklab/ui/combatVehicle/CVBuildTab.java b/megameklab/src/megameklab/ui/combatVehicle/CVBuildTab.java index b1864fa77..34ad7c199 100644 --- a/megameklab/src/megameklab/ui/combatVehicle/CVBuildTab.java +++ b/megameklab/src/megameklab/ui/combatVehicle/CVBuildTab.java @@ -41,6 +41,11 @@ public class CVBuildTab extends ITab implements ActionListener { private RefreshListener refresh = null; private CVCriticalView critView; + + public UnallocatedView getUnallocatedView() { + return unallocatedView; + } + private UnallocatedView unallocatedView; private JButton autoFillButton = new JButton("Auto Fill"); diff --git a/megameklab/src/megameklab/ui/combatVehicle/CVMainUI.java b/megameklab/src/megameklab/ui/combatVehicle/CVMainUI.java index e5c2a4c62..5b235649e 100644 --- a/megameklab/src/megameklab/ui/combatVehicle/CVMainUI.java +++ b/megameklab/src/megameklab/ui/combatVehicle/CVMainUI.java @@ -28,6 +28,7 @@ import javax.swing.*; import java.awt.*; +import java.util.List; public class CVMainUI extends MegaMekLabMainUI { @@ -63,7 +64,7 @@ public void reloadTabs() { buildTab.addRefreshedListener(this); fluffTab.setRefreshedListener(this); statusbar.addRefreshedListener(this); - + previewTab = new PreviewTab(this); configPane.addTab("Structure/Armor", new TabScrollPane(structureTab)); @@ -217,4 +218,9 @@ public ITechManager getTechManager() { public JDialog getFloatingEquipmentDatabase() { return floatingEquipmentDatabase; } -} \ No newline at end of file + + @Override + public List> getUnallocatedMounted() { + return buildTab.getUnallocatedView().getEquipment(); + } +} diff --git a/megameklab/src/megameklab/ui/fighterAero/ASBuildTab.java b/megameklab/src/megameklab/ui/fighterAero/ASBuildTab.java index bd2bb8e5d..0ee16ac85 100644 --- a/megameklab/src/megameklab/ui/fighterAero/ASBuildTab.java +++ b/megameklab/src/megameklab/ui/fighterAero/ASBuildTab.java @@ -36,6 +36,11 @@ public class ASBuildTab extends ITab implements ActionListener { private RefreshListener refresh = null; private ASCriticalView critView = null; + + public ASBuildView getBuildView() { + return buildView; + } + private ASBuildView buildView = null; private JPanel buttonPanel = new JPanel(); private JPanel mainPanel = new JPanel(); diff --git a/megameklab/src/megameklab/ui/fighterAero/ASBuildView.java b/megameklab/src/megameklab/ui/fighterAero/ASBuildView.java index f60b82bee..728c5a44f 100644 --- a/megameklab/src/megameklab/ui/fighterAero/ASBuildView.java +++ b/megameklab/src/megameklab/ui/fighterAero/ASBuildView.java @@ -22,6 +22,7 @@ import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.util.ArrayList; +import java.util.List; import java.util.Vector; import javax.swing.BorderFactory; @@ -60,6 +61,11 @@ public class ASBuildView extends IView implements ActionListener, MouseListener private static final MMLogger logger = MMLogger.create(ASBuildView.class); private CriticalTableModel equipmentList; + + public List> getEquipment() { + return equipmentList.getCrits(); + } + private Vector> masterEquipmentList = new Vector<>(10, 1); private JTable equipmentTable = new JTable(); private JScrollPane equipmentScroll = new JScrollPane(); diff --git a/megameklab/src/megameklab/ui/fighterAero/ASMainUI.java b/megameklab/src/megameklab/ui/fighterAero/ASMainUI.java index bbf74114c..89fb707c9 100644 --- a/megameklab/src/megameklab/ui/fighterAero/ASMainUI.java +++ b/megameklab/src/megameklab/ui/fighterAero/ASMainUI.java @@ -16,20 +16,13 @@ package megameklab.ui.fighterAero; import java.awt.BorderLayout; +import java.util.List; import javax.swing.JDialog; import javax.swing.JTabbedPane; import javax.swing.SwingConstants; -import megamek.common.Aero; -import megamek.common.AeroSpaceFighter; -import megamek.common.ConvFighter; -import megamek.common.Engine; -import megamek.common.Entity; -import megamek.common.EquipmentType; -import megamek.common.ITechManager; -import megamek.common.SimpleTechLevel; -import megamek.common.TechConstants; +import megamek.common.*; import megamek.logging.MMLogger; import megameklab.ui.MegaMekLabMainUI; import megameklab.ui.dialog.FloatingEquipmentDatabaseDialog; @@ -219,4 +212,9 @@ public ITechManager getTechManager() { public JDialog getFloatingEquipmentDatabase() { return floatingEquipmentDatabase; } + + @Override + public List> getUnallocatedMounted() { + return buildTab.getBuildView().getEquipment(); + } } diff --git a/megameklab/src/megameklab/ui/generalUnit/UnallocatedView.java b/megameklab/src/megameklab/ui/generalUnit/UnallocatedView.java index 833d3e386..52e9b73be 100644 --- a/megameklab/src/megameklab/ui/generalUnit/UnallocatedView.java +++ b/megameklab/src/megameklab/ui/generalUnit/UnallocatedView.java @@ -20,6 +20,7 @@ import java.awt.event.ActionListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; +import java.util.List; import java.util.Vector; import java.util.function.Supplier; @@ -52,6 +53,11 @@ public class UnallocatedView extends IView implements ActionListener, MouseListe private static final MMLogger logger = MMLogger.create(UnallocatedView.class); private CriticalTableModel equipmentList; + + public List> getEquipment() { + return equipmentList.getCrits(); + } + private Vector> masterEquipmentList = new Vector<>(10, 1); private JTable equipmentTable = new JTable(); diff --git a/megameklab/src/megameklab/ui/infantry/CIMainUI.java b/megameklab/src/megameklab/ui/infantry/CIMainUI.java index 248862181..5c1e3a35a 100644 --- a/megameklab/src/megameklab/ui/infantry/CIMainUI.java +++ b/megameklab/src/megameklab/ui/infantry/CIMainUI.java @@ -17,6 +17,7 @@ package megameklab.ui.infantry; import java.awt.BorderLayout; +import java.util.List; import javax.swing.*; @@ -129,6 +130,11 @@ public JDialog getFloatingEquipmentDatabase() { return null; } + @Override + public List> getUnallocatedMounted() { + return List.of(); + } + @Override public void refreshSummary() { } @@ -144,4 +150,4 @@ public ITechManager getTechManager() { } return null; } -} \ No newline at end of file +} diff --git a/megameklab/src/megameklab/ui/largeAero/DSMainUI.java b/megameklab/src/megameklab/ui/largeAero/DSMainUI.java index fc54b5b28..26c5f9494 100644 --- a/megameklab/src/megameklab/ui/largeAero/DSMainUI.java +++ b/megameklab/src/megameklab/ui/largeAero/DSMainUI.java @@ -14,6 +14,7 @@ package megameklab.ui.largeAero; import java.awt.BorderLayout; +import java.util.List; import javax.swing.JDialog; import javax.swing.JTabbedPane; @@ -233,4 +234,9 @@ public void refreshPreview() { public JDialog getFloatingEquipmentDatabase() { return floatingEquipmentDatabase; } + + @Override + public List> getUnallocatedMounted() { + return buildTab.getBuildView().getEquipment(); + } } diff --git a/megameklab/src/megameklab/ui/largeAero/LABuildTab.java b/megameklab/src/megameklab/ui/largeAero/LABuildTab.java index a34e088ce..19dd277b3 100644 --- a/megameklab/src/megameklab/ui/largeAero/LABuildTab.java +++ b/megameklab/src/megameklab/ui/largeAero/LABuildTab.java @@ -37,6 +37,11 @@ public class LABuildTab extends ITab implements ActionListener { private RefreshListener refresh = null; private LACriticalView critView = null; + + public LABuildView getBuildView() { + return buildView; + } + private LABuildView buildView = null; private JPanel buttonPanel = new JPanel(); private JPanel mainPanel = new JPanel(); diff --git a/megameklab/src/megameklab/ui/largeAero/LABuildView.java b/megameklab/src/megameklab/ui/largeAero/LABuildView.java index 191016ab6..3c7a84a56 100644 --- a/megameklab/src/megameklab/ui/largeAero/LABuildView.java +++ b/megameklab/src/megameklab/ui/largeAero/LABuildView.java @@ -63,6 +63,11 @@ public void addArcView(BayWeaponCriticalTree l) { } private CriticalTableModel equipmentList; + + public List> getEquipment() { + return equipmentList.getCrits(); + } + private Vector> masterEquipmentList = new Vector<>(10, 1); private JTable equipmentTable = new JTable(); private JScrollPane equipmentScroll = new JScrollPane(); diff --git a/megameklab/src/megameklab/ui/largeAero/WSMainUI.java b/megameklab/src/megameklab/ui/largeAero/WSMainUI.java index b7e4601a6..62b70e7cb 100644 --- a/megameklab/src/megameklab/ui/largeAero/WSMainUI.java +++ b/megameklab/src/megameklab/ui/largeAero/WSMainUI.java @@ -14,6 +14,7 @@ package megameklab.ui.largeAero; import java.awt.BorderLayout; +import java.util.List; import javax.swing.JDialog; import javax.swing.JTabbedPane; @@ -250,4 +251,9 @@ public void refreshPreview() { public JDialog getFloatingEquipmentDatabase() { return floatingEquipmentDatabase; } + + @Override + public List> getUnallocatedMounted() { + return buildTab.getBuildView().getEquipment(); + } } diff --git a/megameklab/src/megameklab/ui/mek/BMBuildTab.java b/megameklab/src/megameklab/ui/mek/BMBuildTab.java index 18bc3c4e3..102e4577d 100644 --- a/megameklab/src/megameklab/ui/mek/BMBuildTab.java +++ b/megameklab/src/megameklab/ui/mek/BMBuildTab.java @@ -42,6 +42,11 @@ public class BMBuildTab extends ITab { private RefreshListener refresh = null; private final BMCriticalView critView; + + public BMBuildView getBuildView() { + return buildView; + } + private final BMBuildView buildView; private final ResourceBundle resources = ResourceBundle.getBundle("megameklab.resources.Tabs"); diff --git a/megameklab/src/megameklab/ui/mek/BMBuildView.java b/megameklab/src/megameklab/ui/mek/BMBuildView.java index 0b3f4ca3f..6af46040c 100644 --- a/megameklab/src/megameklab/ui/mek/BMBuildView.java +++ b/megameklab/src/megameklab/ui/mek/BMBuildView.java @@ -67,6 +67,7 @@ public class BMBuildView extends IView implements ActionListener, MouseListener private int engineHeatSinkCount = 0; private final CriticalTransferHandler transferHandler; private RefreshListener refresh; + private List> masterEquipmentList; public BMBuildView(EntitySource eSource, RefreshListener refresh, BMCriticalView critView) { super(eSource); @@ -101,7 +102,7 @@ public void addRefreshedListener(RefreshListener l) { } private void loadEquipmentTable() { - final List> masterEquipmentList = new ArrayList<>(); + masterEquipmentList = new ArrayList<>(); equipmentList.removeAllCrits(); engineHeatSinkCount = UnitUtil.getCriticalFreeHeatSinks(getMek(), getMek().hasCompactHeatSinks()); for (Mounted mount : getMek().getMisc()) { @@ -122,6 +123,10 @@ private void loadEquipmentTable() { masterEquipmentList.forEach(equipmentList::addCrit); } + public List> getEquipment() { + return masterEquipmentList; + } + private boolean isEngineHeatSink(Mounted mount) { // Note: prototype DHS and compact DHS cannot be used as engine HS if ((mount.getType() instanceof MiscType) diff --git a/megameklab/src/megameklab/ui/mek/BMMainUI.java b/megameklab/src/megameklab/ui/mek/BMMainUI.java index c2d2692c3..131e12f46 100644 --- a/megameklab/src/megameklab/ui/mek/BMMainUI.java +++ b/megameklab/src/megameklab/ui/mek/BMMainUI.java @@ -27,6 +27,7 @@ import javax.swing.*; import java.awt.*; +import java.util.List; public class BMMainUI extends MegaMekLabMainUI { @@ -232,4 +233,9 @@ public ITechManager getTechManager() { public JDialog getFloatingEquipmentDatabase() { return floatingEquipmentDatabase; } + + @Override + public List> getUnallocatedMounted() { + return this.buildTab.getBuildView().getEquipment(); + } } diff --git a/megameklab/src/megameklab/ui/protoMek/PMBuildTab.java b/megameklab/src/megameklab/ui/protoMek/PMBuildTab.java index 2d6977cd4..11aaf239a 100644 --- a/megameklab/src/megameklab/ui/protoMek/PMBuildTab.java +++ b/megameklab/src/megameklab/ui/protoMek/PMBuildTab.java @@ -42,6 +42,11 @@ public class PMBuildTab extends ITab implements ActionListener { private RefreshListener refresh; private PMCriticalView critView; + + public PMBuildView getBuildView() { + return buildView; + } + private PMBuildView buildView; private JPanel buttonPanel = new JPanel(); private JPanel mainPanel = new JPanel(); diff --git a/megameklab/src/megameklab/ui/protoMek/PMBuildView.java b/megameklab/src/megameklab/ui/protoMek/PMBuildView.java index 928ec75bd..50863bcda 100644 --- a/megameklab/src/megameklab/ui/protoMek/PMBuildView.java +++ b/megameklab/src/megameklab/ui/protoMek/PMBuildView.java @@ -33,6 +33,7 @@ import java.awt.event.ActionListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; +import java.util.List; import java.util.Vector; /** @@ -44,6 +45,11 @@ public class PMBuildView extends IView implements ActionListener, MouseListener private JPanel mainPanel = new JPanel(); private CriticalTableModel equipmentList; + + public List> getEquipment() { + return equipmentList.getCrits(); + } + private Vector> masterEquipmentList = new Vector<>(10, 1); private JTable equipmentTable = new JTable(); private JScrollPane equipmentScroll = new JScrollPane(); diff --git a/megameklab/src/megameklab/ui/protoMek/PMMainUI.java b/megameklab/src/megameklab/ui/protoMek/PMMainUI.java index 79a5fcd44..5b82b29fc 100644 --- a/megameklab/src/megameklab/ui/protoMek/PMMainUI.java +++ b/megameklab/src/megameklab/ui/protoMek/PMMainUI.java @@ -25,6 +25,7 @@ import javax.swing.*; import java.awt.*; +import java.util.List; /** * Main UI for building protomeks @@ -188,4 +189,9 @@ public ITechManager getTechManager() { public JDialog getFloatingEquipmentDatabase() { return floatingEquipmentDatabase; } + + @Override + public List> getUnallocatedMounted() { + return buildTab.getBuildView().getEquipment(); + } } diff --git a/megameklab/src/megameklab/ui/supportVehicle/SVBuildTab.java b/megameklab/src/megameklab/ui/supportVehicle/SVBuildTab.java index 2036c3886..57857e048 100644 --- a/megameklab/src/megameklab/ui/supportVehicle/SVBuildTab.java +++ b/megameklab/src/megameklab/ui/supportVehicle/SVBuildTab.java @@ -47,6 +47,11 @@ public class SVBuildTab extends ITab implements ActionListener { private RefreshListener refresh = null; private SVCriticalView critView; + + public UnallocatedView getUnallocatedView() { + return unallocatedView; + } + private UnallocatedView unallocatedView; private JButton autoFillButton = new JButton("Auto Fill"); diff --git a/megameklab/src/megameklab/ui/supportVehicle/SVMainUI.java b/megameklab/src/megameklab/ui/supportVehicle/SVMainUI.java index 911b3aefb..ec357612b 100644 --- a/megameklab/src/megameklab/ui/supportVehicle/SVMainUI.java +++ b/megameklab/src/megameklab/ui/supportVehicle/SVMainUI.java @@ -26,6 +26,7 @@ import javax.swing.*; import java.awt.*; +import java.util.List; /** * Main window for support vehicle construction @@ -231,4 +232,9 @@ public ITechManager getTechManager() { public JDialog getFloatingEquipmentDatabase() { return floatingEquipmentDatabase; } -} \ No newline at end of file + + @Override + public List> getUnallocatedMounted() { + return buildTab.getUnallocatedView().getEquipment(); + } +} diff --git a/megameklab/src/megameklab/ui/util/TabStateUtil.java b/megameklab/src/megameklab/ui/util/TabStateUtil.java index ecce9602b..df01b09c0 100644 --- a/megameklab/src/megameklab/ui/util/TabStateUtil.java +++ b/megameklab/src/megameklab/ui/util/TabStateUtil.java @@ -19,12 +19,11 @@ package megameklab.ui.util; -import megamek.common.Entity; -import megamek.common.Mek; -import megamek.common.MekFileParser; +import megamek.common.*; import megamek.common.loaders.BLKFile; import megamek.common.loaders.EntityLoadingException; import megamek.common.loaders.EntitySavingException; +import megamek.common.loaders.MtfFile; import megamek.common.preference.PreferenceManager; import megamek.logging.MMLogger; import megameklab.ui.MegaMekLabMainUI; @@ -32,10 +31,7 @@ import megameklab.util.UnitUtil; import org.apache.commons.io.FileUtils; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.PrintStream; +import java.io.*; import java.nio.file.Files; import java.nio.file.Paths; import java.util.*; @@ -85,6 +81,29 @@ public static void saveTabState(List editors) throws IOExcepti } } + // Meta File Format: + // First line: an integer n + // Next n lines: equipment added to the unit but not allocated to a location + var metaFile = new File(unitFile.getAbsolutePath().replaceFirst("\\.tmp$", ".meta")); + try ( + var fos = new FileOutputStream(metaFile); + var ps = new PrintStream(fos); + ) { + var unallocatedEquipment = editor.getUnallocatedMounted(); + ps.println(unallocatedEquipment.size()); + for (var m : unallocatedEquipment) { + var type = m.getType(); + if (type.isVariableSize()) { + ps.printf("%s%s%f\n", type.getInternalName(), MtfFile.SIZE, m.getSize()); + } else { + ps.println(type.getInternalName()); + } + } + } catch (Exception e) { + logger.fatal("Failed to write unit metadata while saving tab state.", e); + return; + } + var fileName = editor.getFileName(); if (fileName == null || fileName.isBlank()) { fileName = " "; @@ -141,6 +160,25 @@ public static List loadTabState() throws IOException { try { Entity loadedUnit = new MekFileParser(newFile).getEntity(); + + var metaFile = new File(entityFile.getAbsolutePath().replaceFirst("\\.tmp$", ".meta")); + if (metaFile.exists()) { + try (var sc = new Scanner(metaFile)) { + int unallocatedEquipment = Integer.parseInt(sc.nextLine()); + for (int j = 0; j < unallocatedEquipment; j++) { + var line = sc.nextLine().split(Pattern.quote(MtfFile.SIZE)); + var type = EquipmentType.get(line[0]); + var mounted = Mounted.createMounted(loadedUnit, type); + if (line.length > 1) { + mounted.setSize(Double.parseDouble(line[1])); + } + loadedUnit.addEquipment(mounted, Entity.LOC_NONE, false); + } + } catch (Exception e) { + logger.warn("Could not read meta file for entity file %s:%s".formatted(entityFile, fileName), e); + } + } + var editor = UiLoader.getUI(UnitUtil.getEditorTypeForEntity(loadedUnit), loadedUnit.isPrimitive(), loadedUnit.isIndustrialMek()); editor.setEntity(loadedUnit); editor.setFileName(fileName);