Merge pull request #2257 from SiboVG/ask-metadata

Open dialog to save design information when saving the file
This commit is contained in:
Joe Pfeiffer 2023-07-17 18:29:29 -06:00 committed by GitHub
commit 81ea69d489
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 166 additions and 15 deletions

View File

@ -95,7 +95,10 @@ BasicFrame.WarningDialog.title = Warnings while opening file
BasicFrame.WarningDialog.saving.title = Warnings while opening file
BasicFrame.ErrorWarningDialog.txt1 = <html>Please <b>correct the errors</b>.</html>
BasicFrame.ErrorWarningDialog.saving.title = Errors/Warnings while saving file
BasicFrame.lbl.SaveRocketInfo = Save Design Info
! SaveDesignInfoPanel
SaveDesignInfoPanel.lbl.FillInInfo = (Optional) Fill in the design information for this file
! General error messages used in multiple contexts
error.fileExists.title = File exists

View File

@ -82,6 +82,7 @@ public abstract class Preferences implements ChangeSource {
private static final String AUTO_OPEN_LAST_DESIGN = "AutoOpenLastDesign";
private static final String OPEN_LEFTMOST_DESIGN_TAB = "OpenLeftmostDesignTab";
private static final String SHOW_DISCARD_CONFIRMATION = "IgnoreDiscardEditingWarning";
private static final String SHOW_SAVE_ROCKET_INFO = "ShowSaveRocketInfo";
private static final String SHOW_DISCARD_SIMULATION_CONFIRMATION = "IgnoreDiscardSimulationEditingWarning";
private static final String SHOW_DISCARD_PREFERENCES_CONFIRMATION = "IgnoreDiscardPreferencesWarning";
public static final String MARKER_STYLE_ICON = "MarkerStyleIcon";
@ -592,6 +593,21 @@ public abstract class Preferences implements ChangeSource {
this.putBoolean(SHOW_DISCARD_CONFIRMATION, enabled);
}
/**
* Returns whether a 'save rocket information' dialog should be shown after saving a new design file.
* @return true if the 'save rocket information' dialog should be shown.
*/
public final boolean isShowSaveRocketInfo() {
return this.getBoolean(SHOW_SAVE_ROCKET_INFO, true);
}
/**
* Enable/Disable showing a 'save rocket information' dialog after saving a new design file.
* @return true if the 'save rocket information' dialog should be shown.
*/
public final void setShowSaveRocketInfo(boolean enabled) {
this.putBoolean(SHOW_SAVE_ROCKET_INFO, enabled);
}
/**
* Answer if a confirmation dialog should be shown when canceling a simulation config operation.
*

View File

@ -39,7 +39,6 @@ import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.gui.SpinnerEditor;
import net.sf.openrocket.gui.adaptors.BooleanModel;
import net.sf.openrocket.gui.adaptors.DoubleModel;
import net.sf.openrocket.gui.adaptors.IntegerModel;
import net.sf.openrocket.gui.adaptors.PresetModel;
import net.sf.openrocket.gui.adaptors.TextComponentSelectionKeyListener;
import net.sf.openrocket.gui.components.BasicSlider;
@ -70,7 +69,7 @@ public class RocketComponentConfig extends JPanel {
protected final OpenRocketDocument document;
protected final RocketComponent component;
protected final JTabbedPane tabbedPane;
protected final ComponentConfigDialog parent;
protected final JDialog parent;
protected boolean isNewComponent = false; // Checks whether this config dialog is editing an existing component, or a new one
private final List<Invalidatable> invalidatables = new ArrayList<Invalidatable>();
@ -87,7 +86,7 @@ public class RocketComponentConfig extends JPanel {
private DescriptionArea componentInfo;
private IconToggleButton infoBtn;
private JPanel buttonPanel;
protected JPanel buttonPanel;
protected JButton okButton;
protected JButton cancelButton;
private AppearancePanel appearancePanel = null;
@ -103,11 +102,7 @@ public class RocketComponentConfig extends JPanel {
this.document = document;
this.component = component;
if (parent instanceof ComponentConfigDialog) {
this.parent = (ComponentConfigDialog) parent;
} else {
this.parent = null;
}
this.parent = parent;
// Check the listeners for the same type and massive status
allSameType = true;
@ -195,7 +190,7 @@ public class RocketComponentConfig extends JPanel {
/**
* Add a section to the component configuration dialog that displays information about the component.
*/
private void addComponentInfo(JPanel buttonPanel) {
protected void addComponentInfo(JPanel buttonPanel) {
// Don't add the info panel if this is a multi-comp edit
List<RocketComponent> listeners = component.getConfigListeners();
if (listeners != null && listeners.size() > 0) {
@ -274,14 +269,14 @@ public class RocketComponentConfig extends JPanel {
@Override
public void actionPerformed(ActionEvent arg0) {
// Don't do anything on cancel if you are editing an existing component, and it is not modified
if (!isNewComponent && parent != null && !parent.isModified()) {
ComponentConfigDialog.disposeDialog();
if (!isNewComponent && parent != null && (parent instanceof ComponentConfigDialog && !((ComponentConfigDialog) parent).isModified())) {
disposeDialog();
return;
}
// Apply the cancel operation if set to auto discard in preferences
if (!preferences.isShowDiscardConfirmation()) {
ComponentConfigDialog.clearConfigListeners = false; // Undo action => config listeners of new component will be cleared
ComponentConfigDialog.disposeDialog();
disposeDialog();
document.undo();
return;
}
@ -292,7 +287,7 @@ public class RocketComponentConfig extends JPanel {
trans.get("RocketCompCfg.CancelOperation.title"), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
if (resultYesNo == JOptionPane.YES_OPTION) {
ComponentConfigDialog.clearConfigListeners = false; // Undo action => config listeners of new component will be cleared
ComponentConfigDialog.disposeDialog();
disposeDialog();
document.undo();
}
}
@ -305,7 +300,7 @@ public class RocketComponentConfig extends JPanel {
okButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
ComponentConfigDialog.disposeDialog();
disposeDialog();
}
});
buttonPanel.add(okButton);
@ -315,7 +310,17 @@ public class RocketComponentConfig extends JPanel {
this.add(buttonPanel, "newline, spanx, growx");
}
private JPanel createCancelOperationContent() {
protected void disposeDialog() {
if (parent != null) {
if (parent instanceof ComponentConfigDialog) {
ComponentConfigDialog.disposeDialog();
} else {
parent.dispose();
}
}
}
protected JPanel createCancelOperationContent() {
JPanel panel = new JPanel(new MigLayout());
String msg = isNewComponent ? trans.get("RocketCompCfg.CancelOperation.msg.undoAdd") :
trans.get("RocketCompCfg.CancelOperation.msg.discardChanges");

View File

@ -0,0 +1,104 @@
package net.sf.openrocket.gui.configdialog;
import net.miginfocom.swing.MigLayout;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.gui.components.StyledLabel;
import net.sf.openrocket.gui.widgets.SelectColorButton;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.startup.Preferences;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
* This class is used to create a panel that is shown when a new design file is saved. It is used to fill in the design
* information for the file.
*/
public class SaveDesignInfoPanel extends RocketConfig {
private static final Translator trans = Application.getTranslator();
private static final Preferences preferences = Application.getPreferences();
public SaveDesignInfoPanel(OpenRocketDocument d, RocketComponent c, JDialog parent) {
super(d, c, parent);
// (Optional) Fill in the design information for this file
StyledLabel label = new StyledLabel(trans.get("SaveDesignInfoPanel.lbl.FillInInfo"), StyledLabel.Style.BOLD);
this.add(label, "spanx, wrap para", 0);
}
@Override
protected void addButtons(JButton... buttons) {
if (buttonPanel != null) {
this.remove(buttonPanel);
}
buttonPanel = new JPanel(new MigLayout("fill, ins 5, hidemode 3"));
//// Don't show this dialog again
JCheckBox dontShowAgain = new JCheckBox(trans.get("welcome.dlg.checkbox.dontShowAgain"));
dontShowAgain.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
preferences.setShowSaveRocketInfo(!((JCheckBox) e.getSource()).isSelected());
}
});
buttonPanel.add(dontShowAgain, "gapright 10, growx");
//// Cancel button
this.cancelButton = new SelectColorButton(trans.get("dlg.but.cancel"));
this.cancelButton.setToolTipText(trans.get("RocketCompCfg.btn.Cancel.ttip"));
cancelButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
// Don't do anything on cancel if you are editing an existing component, and it is not modified
if (!isNewComponent && parent != null && (parent instanceof ComponentConfigDialog && !((ComponentConfigDialog) parent).isModified())) {
disposeDialog();
return;
}
// Apply the cancel operation if set to auto discard in preferences
if (!preferences.isShowDiscardConfirmation()) {
ComponentConfigDialog.clearConfigListeners = false; // Undo action => config listeners of new component will be cleared
disposeDialog();
document.undo();
return;
}
// Yes/No dialog: Are you sure you want to discard your changes?
JPanel msg = createCancelOperationContent();
int resultYesNo = JOptionPane.showConfirmDialog(SaveDesignInfoPanel.this, msg,
trans.get("RocketCompCfg.CancelOperation.title"), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
if (resultYesNo == JOptionPane.YES_OPTION) {
ComponentConfigDialog.clearConfigListeners = false; // Undo action => config listeners of new component will be cleared
disposeDialog();
document.undo();
}
}
});
buttonPanel.add(cancelButton, "split 2, right, gapleft 30lp");
//// Ok button
this.okButton = new SelectColorButton(trans.get("dlg.but.ok"));
this.okButton.setToolTipText(trans.get("RocketCompCfg.btn.OK.ttip"));
okButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
disposeDialog();
}
});
buttonPanel.add(okButton);
this.add(buttonPanel, "newline, spanx, growx");
}
@Override
public void updateFields() {
// Do nothing
}
}

View File

@ -49,6 +49,7 @@ import javax.swing.tree.DefaultTreeSelectionModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import net.miginfocom.swing.MigLayout;
import net.sf.openrocket.gui.configdialog.SaveDesignInfoPanel;
import net.sf.openrocket.gui.dialogs.ErrorWarningDialog;
import net.sf.openrocket.logging.ErrorSet;
import net.sf.openrocket.logging.WarningSet;
@ -1596,6 +1597,9 @@ public class BasicFrame extends JFrame {
* @return true if the file was saved, false otherwise
*/
private boolean saveAsAction() {
// Open dialog for saving rocket info
showSaveRocketInfoDialog();
File file = openFileSaveAsDialog(FileType.OPENROCKET);
if (file == null) {
return false;
@ -1610,6 +1614,25 @@ public class BasicFrame extends JFrame {
return result;
}
private void showSaveRocketInfoDialog() {
if (!prefs.isShowSaveRocketInfo()) {
return;
}
// Select the rocket in the component tree to indicate to users that they can edit the rocket info by editing the rocket
setSelectedComponent(rocket);
// Open the save rocket info
JDialog dialog = new JDialog();
SaveDesignInfoPanel panel = new SaveDesignInfoPanel(document, rocket, dialog);
dialog.setContentPane(panel);
dialog.pack();
dialog.setTitle(trans.get("BasicFrame.lbl.SaveRocketInfo"));
dialog.setModal(true);
dialog.setLocationRelativeTo(null);
dialog.setVisible(true);
}
/**
* Perform the writing of the design to the given file in OpenRocket format.