return true;
}
-
-
-
-
+ /**
+ * "Save" action. If the design is new, then this is identical to "Save As", with a default file filter for .ork.
+ * If the rocket being edited previously was opened from a .ork file, then it will be saved immediately to the same
+ * file. But clicking on 'Save' for an existing design file with a .rkt will bring up a confirmation dialog because
+ * it's potentially a destructive write (loss of some fidelity if it's truly an original Rocksim generated file).
+ *
+ * @return true if the file was saved, false otherwise
+ */
private boolean saveAction() {
File file = document.getFile();
if (file == null) {
}
log.info("Saving document to " + file);
- // Saving RockSim designs is not supported
if (FileHelper.ROCKSIM_DESIGN_FILTER.accept(file)) {
- file = new File(file.getAbsolutePath().replaceAll(".[rR][kK][tT](.[gG][zZ])?$",
- ".ork"));
-
- log.info("Attempting to save in RockSim format, renaming to " + file);
- int option = JOptionPane.showConfirmDialog(this, new Object[] {
- "Saving designs in RockSim format is not supported.",
- "Save in OpenRocket format instead (" + file.getName() + ")?"
- }, "Save " + file.getName(), JOptionPane.YES_NO_OPTION,
- JOptionPane.QUESTION_MESSAGE, null);
- if (option != JOptionPane.YES_OPTION) {
- log.user("User chose not to save");
- return false;
- }
-
- document.setFile(file);
+ return saveAsRocksim(file);
}
return saveAs(file);
}
-
-
+
+ /**
+ * "Save As" action.
+ *
+ * Never should a .rkt file contain an OpenRocket content, or an .ork file contain a Rocksim design. Regardless of
+ * what extension the user has chosen, it would violate the Principle of Least Astonishment to do otherwise
+ * (and we want to make doing the wrong thing really hard to do). So always force the appropriate extension.
+ *
+ * This can result in some odd looking filenames (MyDesign.rkt.ork, MyDesign.rkt.ork.rkt, etc.) if the user is
+ * not paying attention, but the user can control that by modifying the filename in the dialog.
+ *
+ * @return true if the file was saved, false otherwise
+ */
private boolean saveAsAction() {
File file = null;
-
- // TODO: HIGH: what if *.rkt chosen?
+
StorageOptionChooser storageChooser =
new StorageOptionChooser(document, document.getDefaultStorageOptions());
- JFileChooser chooser = new JFileChooser();
+ final JFileChooser chooser = new JFileChooser();
chooser.addChoosableFileFilter(FileHelper.OPENROCKET_DESIGN_FILTER);
chooser.addChoosableFileFilter(FileHelper.ROCKSIM_DESIGN_FILTER);
- chooser.setFileFilter(FileHelper.OPENROCKET_DESIGN_FILTER);
+
+ //Force the file filter to match the file extension that was opened. Will default to OR if the file is null.
+ if (FileHelper.ROCKSIM_DESIGN_FILTER.accept(document.getFile())) {
+ chooser.setFileFilter(FileHelper.ROCKSIM_DESIGN_FILTER);
+ }
+ else {
+ chooser.setFileFilter(FileHelper.OPENROCKET_DESIGN_FILTER);
+ }
chooser.setCurrentDirectory(((SwingPreferences) Application.getPreferences()).getDefaultDirectory());
chooser.setAccessory(storageChooser);
- if (document.getFile() != null)
+ if (document.getFile() != null) {
chooser.setSelectedFile(document.getFile());
-
+ }
+
int option = chooser.showSaveDialog(BasicFrame.this);
if (option != JFileChooser.APPROVE_OPTION) {
log.user("User decided not to save, option=" + option);
((SwingPreferences) Application.getPreferences()).setDefaultDirectory(chooser.getCurrentDirectory());
storageChooser.storeOptions(document.getDefaultStorageOptions());
-
- if (chooser.getFileFilter().equals(FileHelper.OPENROCKET_DESIGN_FILTER)) {
- file = FileHelper.ensureExtension(file, "ork");
- if (!FileHelper.confirmWrite(file, this)) {
- return false;
- }
-
- return saveAs(file);
- }
- else if (chooser.getFileFilter().equals(FileHelper.ROCKSIM_DESIGN_FILTER)) {
- file = FileHelper.ensureExtension(file, "rkt");
- if (!FileHelper.confirmWrite(file, this)) {
- return false;
- }
-
- try {
- new RocksimSaver().save(file, document);
- return true;
- } catch (IOException e) {
- return false;
- }
+
+ if (chooser.getFileFilter().equals(FileHelper.ROCKSIM_DESIGN_FILTER)) {
+ return saveAsRocksim(file);
}
else {
- return false;
+ file = FileHelper.forceExtension(file, "ork");
+ return FileHelper.confirmWrite(file, this) && saveAs(file);
}
}
-
- private boolean saveAs(File file) {
+
+ /**
+ * Perform the writing of the design to the given file in Rocksim format.
+ *
+ * @param file the chosen file
+ *
+ * @return true if the file was written
+ */
+ private boolean saveAsRocksim(File file) {
+ file = FileHelper.forceExtension(file, "rkt");
+ if (!FileHelper.confirmWrite(file, this)) {
+ return false;
+ }
+
+ try {
+ new RocksimSaver().save(file, document);
+ return true;
+ } catch (IOException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Perform the writing of the design to the given file in OpenRocket format.
+ *
+ * @param file the chosen file
+ *
+ * @return true if the file was written
+ */
+ private boolean saveAs(File file) {
log.info("Saving document as " + file);
boolean saved = false;
package net.sf.openrocket.gui.util;
-import java.awt.Component;
-import java.io.File;
-import java.io.IOException;
-
-import javax.swing.JOptionPane;
-import javax.swing.filechooser.FileFilter;
-
import net.sf.openrocket.l10n.L10N;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.logging.LogHelper;
import net.sf.openrocket.startup.Application;
+import javax.swing.*;
+import javax.swing.filechooser.FileFilter;
+import java.awt.*;
+import java.io.File;
+import java.io.IOException;
+
/**
* Helper methods related to user-initiated file manipulation.
* <p>
*
* @param original the original file
* @param extension the extension to append if none exists (without preceding dot)
- * @return the resulting filen
+ * @return the resulting file
*/
public static File ensureExtension(File original, String extension) {
return original;
}
-
+ /**
+ * Ensure that the provided file has the given file extension. This differs from ensureExtension in that this
+ * method guarantees that the file will have the extension, whereas ensureExtension only treats the extension
+ * as a default.
+ *
+ * @param original the original file
+ * @param extension the extension to guarantee (without preceding dot)
+ * @return the resulting file
+ */
+ public static File forceExtension(File original, String extension) {
+
+ if (!original.getName().toLowerCase().endsWith(extension.toLowerCase())) {
+ log.debug(1, "File name does not contain extension, adding '" + extension + "'");
+ String name = original.getAbsolutePath();
+ if (extension.startsWith(".")) {
+ name = name + extension;
+ }
+ else {
+ name = name + "." + extension;
+ }
+ return new File(name);
+ }
+
+ return original;
+ }
+
+
/**
* Confirm that it is allowed to write to a file. If the file exists,
* a confirmation dialog will be presented to the user to ensure overwriting is ok.