From e1c86f6a7411e8473f01b45890d518bd813deb02 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Thu, 23 Mar 2023 01:20:58 +0100 Subject: [PATCH] [#2131] Throw warning message when design filename contains illegal characters --- core/resources/l10n/messages.properties | 4 + .../sf/openrocket/gui/main/BasicFrame.java | 10 +- ....java => DesignFileSaveAsFileChooser.java} | 232 +++++++++--------- .../gui/widgets/SaveFileChooser.java | 45 ++++ 4 files changed, 172 insertions(+), 119 deletions(-) rename swing/src/net/sf/openrocket/gui/main/{SaveAsFileChooser.java => DesignFileSaveAsFileChooser.java} (88%) create mode 100644 swing/src/net/sf/openrocket/gui/widgets/SaveFileChooser.java diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties index 6d70535fc..e607c6497 100644 --- a/core/resources/l10n/messages.properties +++ b/core/resources/l10n/messages.properties @@ -1341,6 +1341,10 @@ SaveRktWarningDialog.donotshow=Do not show this dialog again saveAs.openrocket.title=Save as OpenRocket ork file saveAs.rocksim.title=Export as RockSim rkt file +! SaveAsFileChooser +SaveAsFileChooser.illegalFilename.title = Illegal filename +SaveAsFileChooser.illegalFilename.message = The filename '%s' may not contain the character ' %c '. Please remove it. + ! StorageOptionChooser StorageOptChooser.lbl.Simdatatostore = Simulated data to store: StorageOptChooser.rdbut.Allsimdata = All simulated data diff --git a/swing/src/net/sf/openrocket/gui/main/BasicFrame.java b/swing/src/net/sf/openrocket/gui/main/BasicFrame.java index 260f27d7d..4efe32789 100644 --- a/swing/src/net/sf/openrocket/gui/main/BasicFrame.java +++ b/swing/src/net/sf/openrocket/gui/main/BasicFrame.java @@ -86,6 +86,7 @@ import net.sf.openrocket.gui.util.OpenFileWorker; import net.sf.openrocket.gui.util.SaveFileWorker; import net.sf.openrocket.gui.util.SwingPreferences; import net.sf.openrocket.gui.util.URLUtil; +import net.sf.openrocket.gui.widgets.SaveFileChooser; import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.logging.Markers; import net.sf.openrocket.rocketcomponent.ComponentChangeEvent; @@ -1410,7 +1411,7 @@ public class BasicFrame extends JFrame { public boolean exportRockSimAction() { File file; - final SaveAsFileChooser chooser = SaveAsFileChooser.build(document, FileType.ROCKSIM); + final DesignFileSaveAsFileChooser chooser = DesignFileSaveAsFileChooser.build(document, FileType.ROCKSIM); int option = chooser.showSaveDialog(BasicFrame.this); @@ -1507,10 +1508,15 @@ public class BasicFrame extends JFrame { private boolean saveAsAction() { File file = null; - final SaveAsFileChooser chooser = SaveAsFileChooser.build(document, FileType.OPENROCKET); + final DesignFileSaveAsFileChooser chooser = DesignFileSaveAsFileChooser.build(document, FileType.OPENROCKET); int option = chooser.showSaveDialog(BasicFrame.this); + // If the user entered an illegal filename, show the dialog again + while (option == SaveFileChooser.ILLEGAL_FILENAME_ERROR) { + option = chooser.showSaveDialog(BasicFrame.this); + } + if (option != JFileChooser.APPROVE_OPTION) { log.info(Markers.USER_MARKER, "User decided not to save, option=" + option); return false; diff --git a/swing/src/net/sf/openrocket/gui/main/SaveAsFileChooser.java b/swing/src/net/sf/openrocket/gui/main/DesignFileSaveAsFileChooser.java similarity index 88% rename from swing/src/net/sf/openrocket/gui/main/SaveAsFileChooser.java rename to swing/src/net/sf/openrocket/gui/main/DesignFileSaveAsFileChooser.java index 755e64827..4344d8e10 100644 --- a/swing/src/net/sf/openrocket/gui/main/SaveAsFileChooser.java +++ b/swing/src/net/sf/openrocket/gui/main/DesignFileSaveAsFileChooser.java @@ -1,117 +1,115 @@ -package net.sf.openrocket.gui.main; - -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.io.File; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import javax.swing.JFileChooser; - -import net.sf.openrocket.document.OpenRocketDocument; -import net.sf.openrocket.document.StorageOptions; -import net.sf.openrocket.document.StorageOptions.FileType; -import net.sf.openrocket.gui.util.FileHelper; -import net.sf.openrocket.gui.util.SimpleFileFilter; -import net.sf.openrocket.gui.util.SwingPreferences; -import net.sf.openrocket.l10n.Translator; -import net.sf.openrocket.startup.Application; - -public class SaveAsFileChooser extends JFileChooser { - - private final FileType type; - private final OpenRocketDocument document; - private final StorageOptionChooser storageChooser; - - private static final Translator trans = Application.getTranslator(); - - public static SaveAsFileChooser build( OpenRocketDocument document, FileType type ) { - return new SaveAsFileChooser(document,type); - } - - private SaveAsFileChooser( OpenRocketDocument document, FileType type ) { - this.document = document; - this.type = type; - - this.setAcceptAllFileFilterUsed(false); - - File defaultFilename = document.getFileNoExtension(); - - switch( type ) { - default: - case OPENROCKET: - defaultFilename = FileHelper.forceExtension(defaultFilename,"ork"); - this.setDialogTitle(trans.get("saveAs.openrocket.title")); - storageChooser = new StorageOptionChooser(document, document.getDefaultStorageOptions()); - this.setAccessory(storageChooser); - this.addChoosableFileFilter(FileHelper.OPENROCKET_DESIGN_FILTER); - this.setFileFilter(FileHelper.OPENROCKET_DESIGN_FILTER); - break; - case ROCKSIM: - defaultFilename = FileHelper.forceExtension(defaultFilename,"rkt"); - this.setDialogTitle(trans.get("saveAs.rocksim.title")); - storageChooser = null; - this.addChoosableFileFilter(FileHelper.ROCKSIM_DESIGN_FILTER); - this.setFileFilter(FileHelper.ROCKSIM_DESIGN_FILTER); - break; - } - - final RememberFilenamePropertyListener listener = new RememberFilenamePropertyListener(); - this.addPropertyChangeListener(JFileChooser.FILE_FILTER_CHANGED_PROPERTY, listener); - this.addPropertyChangeListener(JFileChooser.SELECTED_FILE_CHANGED_PROPERTY, listener); - this.addPropertyChangeListener(JFileChooser.SELECTED_FILES_CHANGED_PROPERTY, listener); - - this.setCurrentDirectory(((SwingPreferences) Application.getPreferences()).getDefaultDirectory()); - - if (defaultFilename != null) { - this.setSelectedFile(defaultFilename); - } - } - - public void storeOptions(StorageOptions opts) { - if ( storageChooser != null ) { - storageChooser.storeOptions(opts); - } - } - -} - -class RememberFilenamePropertyListener implements PropertyChangeListener { - private String oldFileName=null; - - @Override - public void propertyChange(PropertyChangeEvent event){ - if( JFileChooser.SELECTED_FILE_CHANGED_PROPERTY.equals(event.getPropertyName())){ - if(null != event.getOldValue()){ - this.oldFileName = ((File)event.getOldValue()).getName(); - } - }else if(JFileChooser.FILE_FILTER_CHANGED_PROPERTY.equals(event.getPropertyName())) { - JFileChooser chooser = (JFileChooser)event.getSource(); - if( chooser.getFileFilter() instanceof SimpleFileFilter) { - SimpleFileFilter filter = (SimpleFileFilter) (chooser.getFileFilter()); - String desiredExtension = filter.getExtensions()[0]; - - if (null == this.oldFileName) { - return; - } - String thisFileName = this.oldFileName; - - if (filter.accept(new File(thisFileName))) { - // nop - return; - } else { - String[] splitResults = thisFileName.split("\\."); - if (0 < splitResults.length) { - thisFileName = splitResults[0]; - } - chooser.setSelectedFile(new File(thisFileName + desiredExtension)); - return; - } - } - } - } - -} - - +package net.sf.openrocket.gui.main; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.io.File; + +import javax.swing.JFileChooser; + +import net.sf.openrocket.document.OpenRocketDocument; +import net.sf.openrocket.document.StorageOptions; +import net.sf.openrocket.document.StorageOptions.FileType; +import net.sf.openrocket.gui.util.FileHelper; +import net.sf.openrocket.gui.util.SimpleFileFilter; +import net.sf.openrocket.gui.util.SwingPreferences; +import net.sf.openrocket.gui.widgets.SaveFileChooser; +import net.sf.openrocket.l10n.Translator; +import net.sf.openrocket.startup.Application; + +public class DesignFileSaveAsFileChooser extends SaveFileChooser { + + private final FileType type; + private final OpenRocketDocument document; + private final StorageOptionChooser storageChooser; + + private static final Translator trans = Application.getTranslator(); + + public static DesignFileSaveAsFileChooser build(OpenRocketDocument document, FileType type ) { + return new DesignFileSaveAsFileChooser(document,type); + } + + private DesignFileSaveAsFileChooser(OpenRocketDocument document, FileType type ) { + this.document = document; + this.type = type; + + this.setAcceptAllFileFilterUsed(false); + + File defaultFilename = document.getFileNoExtension(); + + switch( type ) { + default: + case OPENROCKET: + defaultFilename = FileHelper.forceExtension(defaultFilename,"ork"); + this.setDialogTitle(trans.get("saveAs.openrocket.title")); + storageChooser = new StorageOptionChooser(document, document.getDefaultStorageOptions()); + this.setAccessory(storageChooser); + this.addChoosableFileFilter(FileHelper.OPENROCKET_DESIGN_FILTER); + this.setFileFilter(FileHelper.OPENROCKET_DESIGN_FILTER); + break; + case ROCKSIM: + defaultFilename = FileHelper.forceExtension(defaultFilename,"rkt"); + this.setDialogTitle(trans.get("saveAs.rocksim.title")); + storageChooser = null; + this.addChoosableFileFilter(FileHelper.ROCKSIM_DESIGN_FILTER); + this.setFileFilter(FileHelper.ROCKSIM_DESIGN_FILTER); + break; + } + + final RememberFilenamePropertyListener listener = new RememberFilenamePropertyListener(); + this.addPropertyChangeListener(JFileChooser.FILE_FILTER_CHANGED_PROPERTY, listener); + this.addPropertyChangeListener(JFileChooser.SELECTED_FILE_CHANGED_PROPERTY, listener); + this.addPropertyChangeListener(JFileChooser.SELECTED_FILES_CHANGED_PROPERTY, listener); + + this.setCurrentDirectory(((SwingPreferences) Application.getPreferences()).getDefaultDirectory()); + + if (defaultFilename != null) { + this.setSelectedFile(defaultFilename); + } + } + + public void storeOptions(StorageOptions opts) { + if ( storageChooser != null ) { + storageChooser.storeOptions(opts); + } + } + +} + +class RememberFilenamePropertyListener implements PropertyChangeListener { + private String oldFileName=null; + + @Override + public void propertyChange(PropertyChangeEvent event){ + if( JFileChooser.SELECTED_FILE_CHANGED_PROPERTY.equals(event.getPropertyName())){ + if(null != event.getOldValue()){ + this.oldFileName = ((File)event.getOldValue()).getName(); + } + }else if(JFileChooser.FILE_FILTER_CHANGED_PROPERTY.equals(event.getPropertyName())) { + JFileChooser chooser = (JFileChooser)event.getSource(); + if( chooser.getFileFilter() instanceof SimpleFileFilter) { + SimpleFileFilter filter = (SimpleFileFilter) (chooser.getFileFilter()); + String desiredExtension = filter.getExtensions()[0]; + + if (null == this.oldFileName) { + return; + } + String thisFileName = this.oldFileName; + + if (filter.accept(new File(thisFileName))) { + // nop + return; + } else { + String[] splitResults = thisFileName.split("\\."); + if (0 < splitResults.length) { + thisFileName = splitResults[0]; + } + chooser.setSelectedFile(new File(thisFileName + desiredExtension)); + return; + } + } + } + } + +} + + diff --git a/swing/src/net/sf/openrocket/gui/widgets/SaveFileChooser.java b/swing/src/net/sf/openrocket/gui/widgets/SaveFileChooser.java new file mode 100644 index 000000000..6ec9b0011 --- /dev/null +++ b/swing/src/net/sf/openrocket/gui/widgets/SaveFileChooser.java @@ -0,0 +1,45 @@ +package net.sf.openrocket.gui.widgets; + +import net.sf.openrocket.l10n.Translator; +import net.sf.openrocket.startup.Application; + +import javax.swing.JFileChooser; +import javax.swing.JOptionPane; +import java.awt.Component; +import java.awt.HeadlessException; +import java.io.File; + +public class SaveFileChooser extends JFileChooser { + private static final Translator trans = Application.getTranslator(); + + private static final char[] ILLEGAL_CHARS = new char[] { '/', '\\', ':', '*', '?', '"', '<', '>', '|' }; + public static final int ILLEGAL_FILENAME_ERROR = 23111998; + + + @Override + public int showSaveDialog(Component parent) throws HeadlessException { + int option = super.showSaveDialog(parent); + if (option != JFileChooser.APPROVE_OPTION) { + return option; + } + + // Check for invalid characters + File file = getSelectedFile(); + if (file == null) { + return ERROR_OPTION; + } + String filename = file.getName(); + for (char c : ILLEGAL_CHARS) { + if (filename.indexOf(c) >= 0) { + // Illegal character found + JOptionPane.showMessageDialog(parent, + String.format(trans.get("SaveAsFileChooser.illegalFilename.message"), filename, c), + trans.get("SaveAsFileChooser.illegalFilename.title"), + JOptionPane.WARNING_MESSAGE); + return ILLEGAL_FILENAME_ERROR; + } + } + + return option; + } +}