From 6561f8e4e7c72cb545691ed69e3ba6faa0ea7baf Mon Sep 17 00:00:00 2001 From: Pavel Braginskiy Date: Fri, 10 Jan 2025 23:58:33 -0800 Subject: [PATCH] Add option to drop unsaved changes to unit --- megameklab/build.gradle | 6 +++ .../megameklab/resources/Menu.properties | 1 + .../src/megameklab/ui/MegaMekLabMainUI.java | 14 +++++++ .../src/megameklab/ui/MegaMekLabTabbedUI.java | 24 +++++++++-- megameklab/src/megameklab/ui/MenuBar.java | 42 ++++++++++++++++++- .../src/megameklab/ui/mek/BMBuildTab.java | 18 ++++++-- 6 files changed, 95 insertions(+), 10 deletions(-) diff --git a/megameklab/build.gradle b/megameklab/build.gradle index 2dc1a24b6..d080b8c6f 100644 --- a/megameklab/build.gradle +++ b/megameklab/build.gradle @@ -9,6 +9,7 @@ plugins { id 'jacoco' id 'java' id 'org.ec4j.editorconfig' version '0.1.0' + id 'org.openjfx.javafxplugin' version '0.1.0' } java { @@ -16,6 +17,11 @@ java { targetCompatibility = JavaVersion.VERSION_17 } +javafx { + version = "22.0.2" + modules = [ 'javafx.base' ] +} + sourceSets { main { java { diff --git a/megameklab/resources/megameklab/resources/Menu.properties b/megameklab/resources/megameklab/resources/Menu.properties index fd834eea0..c361dc03c 100644 --- a/megameklab/resources/megameklab/resources/Menu.properties +++ b/megameklab/resources/megameklab/resources/Menu.properties @@ -15,6 +15,7 @@ MenuBar.accessibleName=Main Menu Bar ### File Menu fileMenu.text=File miResetCurrentUnit.text=Reset Current Unit +miDropChanges.text=Revert Unsaved Changes miNewTab.text=New Tab miCloseTab.text=Close Tab miReopenTab.text=Reopen Closed Tab diff --git a/megameklab/src/megameklab/ui/MegaMekLabMainUI.java b/megameklab/src/megameklab/ui/MegaMekLabMainUI.java index 237cc1e14..aee92522c 100644 --- a/megameklab/src/megameklab/ui/MegaMekLabMainUI.java +++ b/megameklab/src/megameklab/ui/MegaMekLabMainUI.java @@ -98,6 +98,20 @@ public boolean safetyPrompt() { } } + public boolean safetyPrompt(boolean askSave) { + if (askSave) { + return safetyPrompt(); + } else { + int savePrompt = JOptionPane.showConfirmDialog(this, + "All unsaved changes in the current unit will be discarded. Are you sure you wish to continue?", + "Discard Changes?", + JOptionPane.YES_NO_OPTION, + JOptionPane.WARNING_MESSAGE); + + return savePrompt == JOptionPane.YES_OPTION; + } + } + @Override public boolean exit() { if (!safetyPrompt()) { diff --git a/megameklab/src/megameklab/ui/MegaMekLabTabbedUI.java b/megameklab/src/megameklab/ui/MegaMekLabTabbedUI.java index 6242cee7d..8a4592424 100644 --- a/megameklab/src/megameklab/ui/MegaMekLabTabbedUI.java +++ b/megameklab/src/megameklab/ui/MegaMekLabTabbedUI.java @@ -538,20 +538,35 @@ public void markChanged(boolean changed) { public EditorTab(String name, MegaMekLabMainUI mainUI) { JLabel unitName = new JLabel(name); changesIndicator = new JLabel(); + add(unitName); + add(changesIndicator); + editor = mainUI; setOpaque(false); + + // ⮐ symbol + JButton resetButton = new JButton("\u2B90"); + resetButton.setFont(symbolFont); + resetButton.setForeground(Color.ORANGE); + resetButton.setFocusable(false); + resetButton.setBorder(BorderFactory.createEmptyBorder()); + resetButton.setToolTipText("Undo any unsaved changes"); + resetButton.addActionListener(l -> { + tabs.setSelectedComponent(editor.getContentPane()); + getMMLMenuBar().dropChanges(); + } + ); + add(resetButton); + // ✖ symbol JButton closeButton = new JButton("\u2716"); closeButton.setFont(symbolFont); closeButton.setForeground(Color.RED); closeButton.setFocusable(false); closeButton.setBorder(BorderFactory.createEmptyBorder()); - closeButton.setToolTipText("Shift-click to skip the save confirmation dialog"); - add(unitName); - add(changesIndicator); - add(closeButton); + closeButton.setToolTipText("Close tab
Shift-click to skip the save confirmation dialog"); closeButton.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { @@ -560,6 +575,7 @@ public void mouseClicked(MouseEvent e) { } } }); + add(closeButton); } } diff --git a/megameklab/src/megameklab/ui/MenuBar.java b/megameklab/src/megameklab/ui/MenuBar.java index f3c76b187..27fa9b94f 100644 --- a/megameklab/src/megameklab/ui/MenuBar.java +++ b/megameklab/src/megameklab/ui/MenuBar.java @@ -42,6 +42,7 @@ import megamek.client.ui.swing.util.UIUtil; import megamek.common.*; import megamek.common.annotations.Nullable; +import megamek.common.loaders.EntityLoadingException; import megamek.common.templates.TROView; import megamek.logging.MMLogger; import megameklab.MMLConstants; @@ -156,10 +157,17 @@ private JMenu createFileMenu() { final JMenuItem miResetCurrentUnit = new JMenuItem(resources.getString("miResetCurrentUnit.text")); miResetCurrentUnit.setName("miResetCurrentUnit"); miResetCurrentUnit.setMnemonic(KeyEvent.VK_R); - miResetCurrentUnit.addActionListener(this::jMenuResetEntity_actionPerformed); + miResetCurrentUnit.addActionListener(this::resetEntity); miResetCurrentUnit.setEnabled(isUnitGui()); fileMenu.add(miResetCurrentUnit); + final JMenuItem miDropChanges = new JMenuItem(resources.getString("miDropChanges.text")); + miDropChanges.setName("miDropChanges"); + miDropChanges.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK)); + miDropChanges.addActionListener(i -> dropChanges()); + miDropChanges.setEnabled(isUnitGui()); + fileMenu.add(miDropChanges); + fileMenu.add(createSwitchUnitTypeMenu()); fileMenu.add(createLoadMenu()); fileMenu.add(createSaveMenu()); @@ -1076,7 +1084,7 @@ private void recordSheetImagesAction() { dlg.setVisible(true); } - private void jMenuResetEntity_actionPerformed(ActionEvent event) { + private void resetEntity(ActionEvent event) { if (!owner.safetyPrompt() || !isUnitGui()) { return; } @@ -1107,11 +1115,41 @@ private void jMenuResetEntity_actionPerformed(ActionEvent event) { } else { logger.warn("Received unknown entityType!"); } + getUnitMainUi().setFileName(""); reload(); refresh(); getUnitMainUi().repaint(); } + public void dropChanges() { + var editor = getUnitMainUi(); + + if (!editor.safetyPrompt(false)) { + return; + } + + var filename = editor.getFileName(); + if (filename == null || filename.isBlank()) { + resetEntity(null); + return; + } + + var file = new File(filename); + if (!file.isFile()) { + resetEntity(null); + } else { + try { + var entity = new MekFileParser(file).getEntity(); + UnitUtil.updateLoadedUnit(entity); + editor.setEntity(entity, filename); + reload(); + refresh(); + } catch (EntityLoadingException e) { + logger.error(e, "Could not reset unit", "Reset error"); + } + } + } + private String entitySummaryText(ViewFormatting formatting) { if (CConfig.getBooleanParam(CConfig.MISC_SUMMARY_FORMAT_TRO) && formatting != ViewFormatting.DISCORD) { TROView view = TROView.createView(owner.getEntity(), formatting); diff --git a/megameklab/src/megameklab/ui/mek/BMBuildTab.java b/megameklab/src/megameklab/ui/mek/BMBuildTab.java index 102e4577d..607492916 100644 --- a/megameklab/src/megameklab/ui/mek/BMBuildTab.java +++ b/megameklab/src/megameklab/ui/mek/BMBuildTab.java @@ -29,6 +29,7 @@ import javax.swing.border.EmptyBorder; import javax.swing.border.LineBorder; +import javafx.collections.ListChangeListener; import megamek.client.ui.swing.util.UIUtil; import megamek.common.Mounted; import megameklab.ui.EntitySource; @@ -38,7 +39,10 @@ import megameklab.util.MekUtil; import megameklab.util.UnitUtil; -public class BMBuildTab extends ITab { +public class BMBuildTab extends ITab implements ListChangeListener> { + + // Upon loading a unit, we don't want to run auto-sort or auto-compact until the user has made any sort of change related to crit slots. + private boolean touched = false; private RefreshListener refresh = null; private final BMCriticalView critView; @@ -70,6 +74,7 @@ public BMBuildTab(EntitySource eSource) { add(leftSide); add(buildView); refresh(); + getMek().replaceEquipmentChangedListener(this); } private JComponent createButtonPanel() { @@ -137,7 +142,7 @@ public void refresh() { } private void autoFillUnHitTables() { - if (autoFillUnHitTables.isSelected()) { + if (autoFillUnHitTables.isSelected() && touched) { MekUtil.fillInFMU(getMek()); } } @@ -163,7 +168,7 @@ private void resetCrits() { * It is important that this method does not call a refresh to avoid a loop! */ private void autoCompactCrits() { - if (autoCompact.isSelected() && !autoSort.isSelected()) { + if (autoCompact.isSelected() && !autoSort.isSelected() && touched) { MekUtil.compactCriticals(getMek()); } } @@ -191,7 +196,7 @@ private void sortCrits() { * It is important that this method does not call a refresh to avoid a loop! */ private void autoSortCrits() { - if (autoSort.isSelected()) { + if (autoSort.isSelected() && touched) { MekUtil.sortCrits(getMek()); } } @@ -207,4 +212,9 @@ public void refreshAll() { refresh.refreshAll(); } } + + @Override + public void onChanged(Change> c) { + touched = true; + } }