diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties
index 72f5c27ab..c5338156b 100644
--- a/core/resources/l10n/messages.properties
+++ b/core/resources/l10n/messages.properties
@@ -258,6 +258,7 @@ pref.dlg.tab.Design = Design
pref.dlg.tab.Simulation = Simulation
pref.dlg.tab.Launch = Launch
pref.dlg.tab.Miscellaneousoptions = Miscellaneous options
+pref.dlg.lbl.RockSimWarning = Show warning when saving in RockSim format
pref.dlg.tab.Graphics = Graphics
pref.dlg.lbl.DecalEditor = Graphics Editor
@@ -1134,6 +1135,13 @@ FinsetCfg.ttip.Finfillets1 = Adds the predicted mass of fin fillets to the
FinsetCfg.ttip.Finfillets2 = Assumes the fillet is concave and tangent to the body tube and fin.
FinsetCfg.ttip.Finfillets3 = Zero radius will give no fillet.
+! Save RKT Warning Dialog
+SaveRktWarningDialog.txt1=Exporting to RockSim file format does not support all features of OpenRocket.
+SaveRktWarningDialog.donotshow=Do not show this dialog again
+
+saveAs.openrocket.title=Save as OpenRocket ork file
+saveAs.rocksim.title=Export as RockSim rkt file
+
! StorageOptionChooser
StorageOptChooser.lbl.Simdatatostore = Simulated data to store:
StorageOptChooser.rdbut.Allsimdata = All simulated data
@@ -1201,26 +1209,30 @@ main.menu.file.desc = File-handling related tasks
main.menu.file.new = New
main.menu.file.new.desc = Create a new rocket design
main.menu.file.open = Open...
-BasicFrame.item.Openrocketdesign = Open a rocket design
+main.menu.file.open.desc = Open a rocket design
main.menu.file.openRecent = Open Recent...
-BasicFrame.item.Openrecentrocketdesign = Open a recent rocket design
-main.menu.file.openExample = Open example...
-BasicFrame.item.Openexamplerocketdesign = Open an example rocket design
+main.menu.file.openRecent.desc = Open a recent rocket design
+main.menu.file.openExample = Open Example...
+main.menu.file.openExample.desc = Open an example rocket design
main.menu.file.save = Save
-BasicFrame.item.SavecurRocketdesign = Save the current rocket design
+main.menu.file.save.desc = Save the current rocket design
main.menu.file.saveAs = Save as...
-BasicFrame.item.SavecurRocketdesnewfile = Save the current rocket design to a new file
+main.menu.file.saveAs.desc = Save the current rocket design to a new file
+main.menu.file.import = Import...
+main.menu.file.import.desc = Import model from RockSim rkt file
+main.menu.file.export = Export...
+main.menu.file.export.desc = Export model to RockSim rkt file
main.menu.file.print = Print / Export PDF...
main.menu.file.print.desc = Print or save as PDF the parts list and fin templates
main.menu.file.close = Close
-BasicFrame.item.Closedesign = Close the current rocket design
+main.menu.file.close.desc = Close the current rocket design
main.menu.file.quit = Quit
-BasicFrame.item.Quitprogram = Quit the program
+main.menu.file.quit.desc = Quit the program
main.menu.file.exportDecal = Export Decal
main.menu.file.exportDecal.desc = Export a decal from the current rocket design to a file for editing.
main.menu.edit = Edit
-BasicFrame.menu.Rocketedt = Rocket editing
+main.menu.edit.desc = Rocket editing
main.menu.edit.undo = Undo
main.menu.edit.undo.desc = Undo the previous operation
main.menu.edit.redo = Redo
diff --git a/core/src/net/sf/openrocket/file/openrocket/importt/OpenRocketLoader.java b/core/src/net/sf/openrocket/file/openrocket/importt/OpenRocketLoader.java
index 464dda9c4..8bfba9ae7 100644
--- a/core/src/net/sf/openrocket/file/openrocket/importt/OpenRocketLoader.java
+++ b/core/src/net/sf/openrocket/file/openrocket/importt/OpenRocketLoader.java
@@ -4,9 +4,15 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.List;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.document.Simulation;
import net.sf.openrocket.document.StorageOptions;
+import net.sf.openrocket.document.StorageOptions.FileType;
import net.sf.openrocket.file.AbstractRocketLoader;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.RocketLoadException;
@@ -15,11 +21,6 @@ import net.sf.openrocket.simulation.FlightDataBranch;
import net.sf.openrocket.simulation.FlightDataType;
import net.sf.openrocket.simulation.extension.SimulationExtension;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-
/**
* Class that loads a rocket definition from an OpenRocket rocket file.
@@ -70,7 +71,7 @@ public class OpenRocketLoader extends AbstractRocketLoader {
List list = branch.get(FlightDataType.TYPE_TIME);
if (list == null)
continue;
-
+
double previousTime = Double.NaN;
for (double time : list) {
if (time - previousTime < timeSkip)
@@ -81,6 +82,7 @@ public class OpenRocketLoader extends AbstractRocketLoader {
timeSkip = Math.rint(timeSkip * 100) / 100;
doc.getDefaultStorageOptions().setSimulationTimeSkip(timeSkip);
doc.getDefaultStorageOptions().setExplicitlySet(false);
+ doc.getDefaultStorageOptions().setFileType(FileType.OPENROCKET);
// Call simulation extensions
for (Simulation sim : doc.getSimulations()) {
diff --git a/core/src/net/sf/openrocket/file/rocksim/importt/RocksimLoader.java b/core/src/net/sf/openrocket/file/rocksim/importt/RocksimLoader.java
index 60bea006a..bf452c20e 100644
--- a/core/src/net/sf/openrocket/file/rocksim/importt/RocksimLoader.java
+++ b/core/src/net/sf/openrocket/file/rocksim/importt/RocksimLoader.java
@@ -6,14 +6,15 @@ package net.sf.openrocket.file.rocksim.importt;
import java.io.IOException;
import java.io.InputStream;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+import net.sf.openrocket.document.StorageOptions.FileType;
import net.sf.openrocket.file.AbstractRocketLoader;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.RocketLoadException;
import net.sf.openrocket.file.simplesax.SimpleSAX;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-
/**
* This class is the main entry point for Rocksim design file imported to OpenRocket. Currently only Rocksim v9
* file formats are supported, although it is possible that v8 formats will work for most components.
@@ -52,5 +53,6 @@ public class RocksimLoader extends AbstractRocketLoader {
context.getOpenRocketDocument().setFile(null);
context.getOpenRocketDocument().clearUndo();
+ context.getOpenRocketDocument().getDefaultStorageOptions().setFileType(FileType.ROCKSIM);
}
}
diff --git a/core/src/net/sf/openrocket/startup/Preferences.java b/core/src/net/sf/openrocket/startup/Preferences.java
index a759d9d48..4a542a4d3 100644
--- a/core/src/net/sf/openrocket/startup/Preferences.java
+++ b/core/src/net/sf/openrocket/startup/Preferences.java
@@ -61,6 +61,7 @@ public abstract class Preferences implements ChangeSource {
// Node names
public static final String PREFERRED_THRUST_CURVE_MOTOR_NODE = "preferredThrustCurveMotors";
private static final String AUTO_OPEN_LAST_DESIGN = "AUTO_OPEN_LAST_DESIGN";
+ private static final String SHOW_ROCKSIM_FORMAT_WARNING = "SHOW_ROCKSIM_FORMAT_WARNING";
//Preferences related to 3D graphics
public static final String OPENGL_ENABLED = "OpenGL_Is_Enabled";
@@ -162,6 +163,14 @@ public abstract class Preferences implements ChangeSource {
this.putBoolean(LAUNCH_INTO_WIND, check);
}
+ public final boolean getShowRockSimFormatWarning() {
+ return this.getBoolean(SHOW_ROCKSIM_FORMAT_WARNING, true);
+ }
+
+ public final void setShowRockSimFormatWarning(boolean check) {
+ this.putBoolean(SHOW_ROCKSIM_FORMAT_WARNING, check);
+ }
+
public final double getDefaultMach() {
return Application.getPreferences().getChoice(Preferences.DEFAULT_MACH_NUMBER, 0.9, 0.3);
}
@@ -533,7 +542,7 @@ public abstract class Preferences implements ChangeSource {
String color = get("componentColors", c, StaticFieldHolder.DEFAULT_COLORS);
if (color == null)
return Color.BLACK;
-
+
Color clr = parseColor(color);
if (clr != null) {
return clr;
@@ -584,7 +593,7 @@ public abstract class Preferences implements ChangeSource {
public Material getDefaultComponentMaterial(
Class extends RocketComponent> componentClass,
Material.Type type) {
-
+
String material = get("componentMaterials", componentClass, null);
if (material != null) {
try {
@@ -613,7 +622,7 @@ public abstract class Preferences implements ChangeSource {
*/
public void setDefaultComponentMaterial(
Class extends RocketComponent> componentClass, Material material) {
-
+
putString("componentMaterials", componentClass.getSimpleName(),
material == null ? null : material.toStorableString());
}
@@ -689,7 +698,7 @@ public abstract class Preferences implements ChangeSource {
protected String get(String directory,
Class extends RocketComponent> componentClass,
Map, String> defaultMap) {
-
+
// Search preferences
Class> c = componentClass;
while (c != null && RocketComponent.class.isAssignableFrom(c)) {
@@ -701,7 +710,7 @@ public abstract class Preferences implements ChangeSource {
if (defaultMap == null)
return null;
-
+
// Search defaults
c = componentClass;
while (RocketComponent.class.isAssignableFrom(c)) {
@@ -736,12 +745,14 @@ public abstract class Preferences implements ChangeSource {
*/
private static final HashMap, String> DEFAULT_LINE_STYLES = new HashMap, String>();
+
static {
DEFAULT_LINE_STYLES.put(RocketComponent.class, LineStyle.SOLID.name());
DEFAULT_LINE_STYLES.put(MassObject.class, LineStyle.DASHED.name());
}
private static final HashMap, String> DEFAULT_COLORS = new HashMap, String>();
+
static {
DEFAULT_COLORS.put(BodyComponent.class, "0,0,240");
DEFAULT_COLORS.put(TubeFinSet.class, "0,0,200");
diff --git a/swing/src/net/sf/openrocket/gui/dialogs/preferences/GeneralPreferencesPanel.java b/swing/src/net/sf/openrocket/gui/dialogs/preferences/GeneralPreferencesPanel.java
index 607b42cbf..43183f537 100644
--- a/swing/src/net/sf/openrocket/gui/dialogs/preferences/GeneralPreferencesPanel.java
+++ b/swing/src/net/sf/openrocket/gui/dialogs/preferences/GeneralPreferencesPanel.java
@@ -208,6 +208,30 @@ public class GeneralPreferencesPanel extends PreferencesPanel {
}
});
this.add(button, "right, wrap");
+
+ //// Open most recent file on startup
+ final JCheckBox openRecentOnStartupBox = new JCheckBox(trans.get("pref.dlg.but.openlast"));
+ openRecentOnStartupBox.setSelected(preferences.isAutoOpenLastDesignOnStartupEnabled());
+ openRecentOnStartupBox.addActionListener( new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ preferences.setAutoOpenLastDesignOnStartup(openRecentOnStartupBox.isSelected());
+ }
+ });
+ this.add(openRecentOnStartupBox,"spanx, wrap");
+
+ //// Save RockSim Format warning dialog
+ final JCheckBox rocksimWarningDialogBox = new JCheckBox(trans.get("pref.dlg.lbl.RockSimWarning"));
+ rocksimWarningDialogBox.setSelected(preferences.getShowRockSimFormatWarning());
+ rocksimWarningDialogBox.addActionListener( new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ preferences.setShowRockSimFormatWarning(rocksimWarningDialogBox.isSelected());
+ }
+ });
+ this.add(rocksimWarningDialogBox,"spanx, wrap");
+
+
}
diff --git a/swing/src/net/sf/openrocket/gui/main/BasicFrame.java b/swing/src/net/sf/openrocket/gui/main/BasicFrame.java
index 9cac11c80..ddfd3dcef 100644
--- a/swing/src/net/sf/openrocket/gui/main/BasicFrame.java
+++ b/swing/src/net/sf/openrocket/gui/main/BasicFrame.java
@@ -12,8 +12,6 @@ import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
@@ -33,6 +31,7 @@ import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.InputMap;
import javax.swing.JButton;
+import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
@@ -54,22 +53,25 @@ import javax.swing.ScrollPaneConstants;
import javax.swing.SwingUtilities;
import javax.swing.border.BevelBorder;
import javax.swing.border.TitledBorder;
+import javax.swing.event.ChangeEvent;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
-import javax.swing.event.ChangeEvent;
import javax.swing.tree.DefaultTreeSelectionModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import net.miginfocom.swing.MigLayout;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.document.OpenRocketDocumentFactory;
import net.sf.openrocket.document.StorageOptions;
+import net.sf.openrocket.document.StorageOptions.FileType;
import net.sf.openrocket.file.GeneralRocketSaver;
import net.sf.openrocket.file.RocketLoadException;
-import net.sf.openrocket.gui.ExportDecalDialog;
-import net.sf.openrocket.gui.StorageOptionChooser;
+import net.sf.openrocket.gui.components.StyledLabel;
import net.sf.openrocket.gui.configdialog.ComponentConfigDialog;
import net.sf.openrocket.gui.customexpression.CustomExpressionDialog;
import net.sf.openrocket.gui.dialogs.AboutDialog;
@@ -94,7 +96,6 @@ import net.sf.openrocket.gui.util.GUIUtil;
import net.sf.openrocket.gui.util.Icons;
import net.sf.openrocket.gui.util.OpenFileWorker;
import net.sf.openrocket.gui.util.SaveFileWorker;
-import net.sf.openrocket.gui.util.SimpleFileFilter;
import net.sf.openrocket.gui.util.SwingPreferences;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.logging.Markers;
@@ -103,6 +104,7 @@ import net.sf.openrocket.rocketcomponent.ComponentChangeListener;
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.startup.Application;
+import net.sf.openrocket.startup.Preferences;
import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.MemoryManagement;
import net.sf.openrocket.util.MemoryManagement.MemoryData;
@@ -111,55 +113,51 @@ import net.sf.openrocket.util.StateChangeListener;
import net.sf.openrocket.util.TestRockets;
import net.sf.openrocket.utils.ComponentPresetEditor;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class BasicFrame extends JFrame implements PropertyChangeListener {
+public class BasicFrame extends JFrame {
private static final Logger log = LoggerFactory.getLogger(BasicFrame.class);
-
+
private static final GeneralRocketSaver ROCKET_SAVER = new GeneralRocketSaver();
-
+
private static final Translator trans = Application.getTranslator();
-
+ private static final Preferences prefs = Application.getPreferences();
+
private static final int SHORTCUT_KEY = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
-
+
public static final int COMPONENT_TAB = 0;
public static final int CONFIGURATION_TAB = 1;
public static final int SIMULATION_TAB = 2;
-
-
+
+
/**
* List of currently open frames. When the list goes empty
* it is time to exit the application.
*/
private static final ArrayList frames = new ArrayList();
-
-
+
+
/**
* Whether "New" and "Open" should replace this frame.
* Should be set to false on the first rocket modification.
*/
private boolean replaceable = false;
-
-
-
+
private final OpenRocketDocument document;
private final Rocket rocket;
-
+
private JTabbedPane tabbedPane;
private RocketPanel rocketpanel;
private ComponentTree tree = null;
-
+
private final DocumentSelectionModel selectionModel;
private final TreeSelectionModel componentSelectionModel;
private final ListSelectionModel simulationSelectionModel;
-
+
/** Actions available for rocket modifications */
private final RocketActions actions;
-
+
private SimulationPanel simulationPanel;
-
-
+
+
/**
* Sole constructor. Creates a new frame based on the supplied document
* and adds it to the current frames list.
@@ -168,36 +166,36 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
*/
public BasicFrame(OpenRocketDocument document) {
log.debug("Instantiating new BasicFrame");
-
+
this.document = document;
this.rocket = document.getRocket();
this.rocket.getDefaultConfiguration().setAllStages();
-
+
// Create the component tree selection model that will be used
componentSelectionModel = new DefaultTreeSelectionModel();
componentSelectionModel.setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
-
+
// Obtain the simulation selection model that will be used
simulationPanel = new SimulationPanel(document);
simulationSelectionModel = simulationPanel.getSimulationListSelectionModel();
-
+
// Combine into a DocumentSelectionModel
selectionModel = new DocumentSelectionModel(document);
selectionModel.attachComponentTreeSelectionModel(componentSelectionModel);
selectionModel.attachSimulationListSelectionModel(simulationSelectionModel);
-
-
+
+
actions = new RocketActions(document, selectionModel, this);
-
-
+
+
log.debug("Constructing the BasicFrame UI");
-
+
// The main vertical split pane
JSplitPane vertical = new JSplitPane(JSplitPane.VERTICAL_SPLIT, true);
vertical.setResizeWeight(0.5);
this.add(vertical);
-
-
+
+
// The top tabbed pane
tabbedPane = new JTabbedPane();
//// Rocket design
@@ -206,51 +204,51 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
tabbedPane.addTab(trans.get("BasicFrame.tab.Flightconfig"), null, new FlightConfigurationPanel(document));
//// Flight simulations
tabbedPane.addTab(trans.get("BasicFrame.tab.Flightsim"), null, simulationPanel);
-
+
// Add change listener to catch when the tabs are changed. This is to run simulations
// automagically when the simulation tab is selected.
tabbedPane.addChangeListener(new BasicFrame_changeAdapter(this));
-
-
+
+
vertical.setTopComponent(tabbedPane);
-
-
-
+
+
+
// Bottom segment, rocket figure
-
+
rocketpanel = new RocketPanel(document);
vertical.setBottomComponent(rocketpanel);
-
+
rocketpanel.setSelectionModel(tree.getSelectionModel());
-
-
+
+
createMenu();
-
-
+
+
rocket.addComponentChangeListener(new ComponentChangeListener() {
@Override
public void componentChanged(ComponentChangeEvent e) {
setTitle();
}
});
-
+
setTitle();
this.pack();
-
-
+
+
// Set initial window size
Dimension size = Toolkit.getDefaultToolkit().getScreenSize();
size.width = size.width * 9 / 10;
size.height = size.height * 9 / 10;
this.setSize(size);
-
+
// Remember changed size
GUIUtil.rememberWindowSize(this);
-
+
this.setLocationByPlatform(true);
-
+
GUIUtil.setWindowIcons(this);
-
+
this.validate();
vertical.setDividerLocation(0.4);
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
@@ -260,11 +258,11 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
closeAction();
}
});
-
+
frames.add(this);
log.debug("BasicFrame instantiation complete");
}
-
+
/**
* Construct the "Rocket design" tab. This contains a horizontal split pane
* with the left component the design tree and the right component buttons
@@ -273,15 +271,15 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
private JComponent designTab() {
JSplitPane horizontal = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true);
horizontal.setResizeWeight(0.5);
-
-
+
+
// Upper-left segment, component tree
-
+
JPanel panel = new JPanel(new MigLayout("fill, flowy", "[grow][grow 0]","[grow]"));
-
+
tree = new ComponentTree(document);
tree.setSelectionModel(componentSelectionModel);
-
+
// Remove JTree key events that interfere with menu accelerators
InputMap im = SwingUtilities.getUIInputMap(tree, JComponent.WHEN_FOCUSED);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_X, SHORTCUT_KEY), null);
@@ -291,9 +289,9 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_S, SHORTCUT_KEY), null);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_O, SHORTCUT_KEY), null);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_N, SHORTCUT_KEY), null);
-
-
-
+
+
+
// Double-click opens config dialog
MouseListener ml = new MouseAdapter() {
@Override
@@ -311,7 +309,7 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
}
};
tree.addMouseListener(ml);
-
+
// Update dialog when selection is changed
componentSelectionModel.addTreeSelectionListener(new TreeSelectionListener() {
@Override
@@ -321,7 +319,7 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
if (path == null)
return;
tree.scrollPathToVisible(path);
-
+
if (!ComponentConfigDialog.isDialogVisible())
return;
RocketComponent c = (RocketComponent) path.getLastPathComponent();
@@ -329,57 +327,57 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
BasicFrame.this.document, c);
}
});
-
+
// Place tree inside scroll pane
JScrollPane scroll = new JScrollPane(tree);
panel.add(scroll, "spany, grow, wrap");
-
-
+
+
// Buttons
JButton button = new JButton(actions.getMoveUpAction());
panel.add(button, "sizegroup buttons, aligny 65%");
-
+
button = new JButton(actions.getMoveDownAction());
panel.add(button, "sizegroup buttons, aligny 0%");
-
+
button = new JButton(actions.getEditAction());
panel.add(button, "sizegroup buttons");
-
+
button = new JButton(actions.getNewStageAction());
panel.add(button, "sizegroup buttons");
-
+
button = new JButton(actions.getDeleteAction());
button.setIcon(null);
button.setMnemonic(0);
panel.add(button, "sizegroup buttons");
-
+
horizontal.setLeftComponent(panel);
-
-
+
+
// Upper-right segment, component addition buttons
-
+
panel = new JPanel(new MigLayout("fill, insets 0", "[0::]"));
-
+
scroll = new JScrollPane(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
scroll.setViewportView(new ComponentAddButtons(document, componentSelectionModel,
scroll.getViewport()));
scroll.setBorder(null);
scroll.setViewportBorder(null);
-
+
TitledBorder border = BorderFactory.createTitledBorder(trans.get("BasicFrame.title.Addnewcomp"));
GUIUtil.changeFontStyle(border, Font.BOLD);
scroll.setBorder(border);
-
+
panel.add(scroll, "grow");
-
+
horizontal.setRightComponent(panel);
-
+
return horizontal;
}
-
-
-
+
+
+
/**
* Return the currently selected rocket component, or null
if none selected.
*/
@@ -388,11 +386,11 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
if (path == null)
return null;
tree.scrollPathToVisible(path);
-
+
return (RocketComponent) path.getLastPathComponent();
}
-
-
+
+
/**
* Creates the menu for the window.
*/
@@ -400,14 +398,14 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
JMenuBar menubar = new JMenuBar();
JMenu menu;
JMenuItem item;
-
+
//// File
menu = new JMenu(trans.get("main.menu.file"));
menu.setMnemonic(KeyEvent.VK_F);
//// File-handling related tasks
menu.getAccessibleContext().setAccessibleDescription(trans.get("main.menu.file.desc"));
menubar.add(menu);
-
+
//// New
item = new JMenuItem(trans.get("main.menu.file.new"), KeyEvent.VK_N);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, SHORTCUT_KEY));
@@ -424,12 +422,12 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
}
});
menu.add(item);
-
+
//// Open...
item = new JMenuItem(trans.get("main.menu.file.open"), KeyEvent.VK_O);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, SHORTCUT_KEY));
//// Open a rocket design
- item.getAccessibleContext().setAccessibleDescription(trans.get("BasicFrame.item.Openrocketdesign"));
+ item.getAccessibleContext().setAccessibleDescription(trans.get("main.menu.file.open.desc"));
item.setIcon(Icons.FILE_OPEN);
item.addActionListener(new ActionListener() {
@Override
@@ -439,26 +437,26 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
}
});
menu.add(item);
-
+
//// Open Recent...
item = new MRUDesignFileAction(trans.get("main.menu.file.openRecent"), this);
- item.getAccessibleContext().setAccessibleDescription(trans.get("BasicFrame.item.Openrecentrocketdesign"));
+ item.getAccessibleContext().setAccessibleDescription(trans.get("main.menu.file.openRecent.desc"));
item.setIcon(Icons.FILE_OPEN);
menu.add(item);
-
+
//// Open example...
item = new ExampleDesignFileAction(trans.get("main.menu.file.openExample"), this);
- item.getAccessibleContext().setAccessibleDescription(trans.get("BasicFrame.item.Openexamplerocketdesign"));
+ item.getAccessibleContext().setAccessibleDescription(trans.get("main.menu.file.openExample.desc"));
item.setIcon(Icons.FILE_OPEN_EXAMPLE);
menu.add(item);
-
+
menu.addSeparator();
-
+
//// Save
item = new JMenuItem(trans.get("main.menu.file.save"), KeyEvent.VK_S);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, SHORTCUT_KEY));
//// Save the current rocket design
- item.getAccessibleContext().setAccessibleDescription(trans.get("BasicFrame.item.SavecurRocketdesign"));
+ item.getAccessibleContext().setAccessibleDescription(trans.get("main.menu.file.save.desc"));
item.setIcon(Icons.FILE_SAVE);
item.addActionListener(new ActionListener() {
@Override
@@ -468,13 +466,13 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
}
});
menu.add(item);
-
+
//// Save as...
item = new JMenuItem(trans.get("main.menu.file.saveAs"), KeyEvent.VK_A);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S,
SHORTCUT_KEY | ActionEvent.SHIFT_MASK));
//// Save the current rocket design to a new file
- item.getAccessibleContext().setAccessibleDescription(trans.get("BasicFrame.item.SavecurRocketdesnewfile"));
+ item.getAccessibleContext().setAccessibleDescription(trans.get("main.menu.file.saveAs.desc"));
item.setIcon(Icons.FILE_SAVE_AS);
item.addActionListener(new ActionListener() {
@Override
@@ -484,8 +482,33 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
}
});
menu.add(item);
-
-
+
+ menu.addSeparator();
+
+ //// Import Rocksim
+ item = new JMenuItem(trans.get("main.menu.file.import"));
+ item.getAccessibleContext().setAccessibleDescription(trans.get("main.menu.file.import.desc"));
+ item.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ log.info(Markers.USER_MARKER, "Import... selected");
+ importAction();
+ }
+ });
+ menu.add(item);
+
+ //// Export Rocksim
+ item = new JMenuItem(trans.get("main.menu.file.export"));
+ item.getAccessibleContext().setAccessibleDescription(trans.get("main.menu.file.export.desc"));
+ item.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ log.info(Markers.USER_MARKER, "Export... selected");
+ exportAction();
+ }
+ });
+ menu.add(item);
+
//// Export decal...
item = new JMenuItem(trans.get("main.menu.file.exportDecal"));
item.getAccessibleContext().setAccessibleDescription(trans.get("main.menu.file.exportDecal.desc"));
@@ -498,16 +521,16 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
item.setEnabled(document.getDecalList().size() > 0);
final JMenuItem exportMenuItem = item;
document.getRocket().addChangeListener(new StateChangeListener() {
-
+
@Override
public void stateChanged(EventObject e) {
exportMenuItem.setEnabled(document.getDecalList().size() > 0);
}
-
+
});
menu.add(item);
-
-
+
+
//// Print...
item = new JMenuItem(trans.get("main.menu.file.print"), KeyEvent.VK_P);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_P, SHORTCUT_KEY));
@@ -522,15 +545,15 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
}
});
menu.add(item);
-
-
+
+
menu.addSeparator();
-
+
//// Close
item = new JMenuItem(trans.get("main.menu.file.close"), KeyEvent.VK_C);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_W, SHORTCUT_KEY));
//// Close the current rocket design
- item.getAccessibleContext().setAccessibleDescription(trans.get("BasicFrame.item.Closedesign"));
+ item.getAccessibleContext().setAccessibleDescription(trans.get("main.menu.file.close.desc"));
item.setIcon(Icons.FILE_CLOSE);
item.addActionListener(new ActionListener() {
@Override
@@ -540,14 +563,14 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
}
});
menu.add(item);
-
+
menu.addSeparator();
-
+
//// Quit
item = new JMenuItem(trans.get("main.menu.file.quit"), KeyEvent.VK_Q);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, SHORTCUT_KEY));
//// Quit the program
- item.getAccessibleContext().setAccessibleDescription(trans.get("BasicFrame.item.Quitprogram"));
+ item.getAccessibleContext().setAccessibleDescription(trans.get("main.menu.file.quit.desc"));
item.setIcon(Icons.FILE_QUIT);
item.addActionListener(new ActionListener() {
@Override
@@ -557,26 +580,26 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
}
});
menu.add(item);
-
-
-
+
+
+
//// Edit
menu = new JMenu(trans.get("main.menu.edit"));
menu.setMnemonic(KeyEvent.VK_E);
//// Rocket editing
- menu.getAccessibleContext().setAccessibleDescription(trans.get("BasicFrame.menu.Rocketedt"));
+ menu.getAccessibleContext().setAccessibleDescription(trans.get("main.menu.edit.desc"));
menubar.add(menu);
-
-
+
+
Action action = UndoRedoAction.newUndoAction(document);
item = new JMenuItem(action);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z, SHORTCUT_KEY));
item.setMnemonic(KeyEvent.VK_U);
//// Undo the previous operation
item.getAccessibleContext().setAccessibleDescription(trans.get("main.menu.edit.undo.desc"));
-
+
menu.add(item);
-
+
action = UndoRedoAction.newRedoAction(document);
item = new JMenuItem(action);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Y, SHORTCUT_KEY));
@@ -584,26 +607,26 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
//// Redo the previously undone operation
item.getAccessibleContext().setAccessibleDescription(trans.get("main.menu.edit.redo.desc"));
menu.add(item);
-
+
menu.addSeparator();
-
-
+
+
item = new JMenuItem(actions.getCutAction());
menu.add(item);
-
+
item = new JMenuItem(actions.getCopyAction());
menu.add(item);
-
+
item = new JMenuItem(actions.getPasteAction());
menu.add(item);
-
+
item = new JMenuItem(actions.getDeleteAction());
menu.add(item);
-
+
menu.addSeparator();
-
-
-
+
+
+
item = new JMenuItem(trans.get("main.menu.edit.resize"));
item.setIcon(Icons.EDIT_SCALE);
item.getAccessibleContext().setAccessibleDescription(trans.get("main.menu.edit.resize.desc"));
@@ -617,9 +640,9 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
}
});
menu.add(item);
-
-
-
+
+
+
//// Preferences
item = new JMenuItem(trans.get("main.menu.edit.preferences"));
item.setIcon(Icons.PREFERENCES);
@@ -633,7 +656,7 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
}
});
menu.add(item);
-
+
//// Edit Component Preset File
if (System.getProperty("openrocket.preseteditor.menu") != null) {
item = new JMenuItem(trans.get("main.menu.edit.editpreset"));
@@ -649,15 +672,15 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
});
menu.add(item);
}
-
-
+
+
//// Analyze
menu = new JMenu(trans.get("main.menu.analyze"));
menu.setMnemonic(KeyEvent.VK_A);
//// Analyzing the rocket
menu.getAccessibleContext().setAccessibleDescription(trans.get("main.menu.analyze.desc"));
menubar.add(menu);
-
+
//// Component analysis
item = new JMenuItem(trans.get("main.menu.analyze.componentAnalysis"), KeyEvent.VK_C);
//// Analyze the rocket components separately
@@ -670,7 +693,7 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
}
});
menu.add(item);
-
+
//// Optimize
item = new JMenuItem(trans.get("main.menu.analyze.optimization"), KeyEvent.VK_O);
item.getAccessibleContext().setAccessibleDescription(trans.get("main.menu.analyze.optimization.desc"));
@@ -682,7 +705,7 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
}
});
menu.add(item);
-
+
//// Custom expressions
item = new JMenuItem(trans.get("main.menu.analyze.customExpressions"), KeyEvent.VK_E);
item.getAccessibleContext().setAccessibleDescription(trans.get("main.menu.analyze.customExpressions.desc"));
@@ -694,7 +717,7 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
}
});
menu.add(item);
-
+
item = new JMenuItem(trans.get("PhotoFrame.title"), KeyEvent.VK_P);
item.getAccessibleContext().setAccessibleDescription(trans.get("PhotoFrame.desc"));
item.addActionListener(new ActionListener() {
@@ -706,25 +729,25 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
}
});
menu.add(item);
-
+
//// Debug
// (shown if openrocket.debug.menu is defined)
if (System.getProperty("openrocket.debug.menu") != null) {
menubar.add(makeDebugMenu());
}
-
-
-
+
+
+
//// Help
-
+
menu = new JMenu(trans.get("main.menu.help"));
menu.setMnemonic(KeyEvent.VK_H);
menu.getAccessibleContext().setAccessibleDescription(trans.get("main.menu.help.desc"));
menubar.add(menu);
-
-
+
+
// Guided tours
-
+
item = new JMenuItem(trans.get("main.menu.help.tours"), KeyEvent.VK_L);
item.setIcon(Icons.HELP_TOURS);
item.getAccessibleContext().setAccessibleDescription(trans.get("main.menu.help.tours.desc"));
@@ -736,9 +759,9 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
}
});
menu.add(item);
-
+
menu.addSeparator();
-
+
//// Bug report
item = new JMenuItem(trans.get("main.menu.help.bugReport"), KeyEvent.VK_B);
item.setIcon(Icons.HELP_BUG_REPORT);
@@ -751,7 +774,7 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
}
});
menu.add(item);
-
+
//// Debug log
item = new JMenuItem(trans.get("main.menu.help.debugLog"));
item.setIcon(Icons.HELP_DEBUG_LOG);
@@ -764,10 +787,10 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
}
});
menu.add(item);
-
+
menu.addSeparator();
-
-
+
+
//// License
item = new JMenuItem(trans.get("main.menu.help.license"), KeyEvent.VK_L);
item.setIcon(Icons.HELP_LICENSE);
@@ -780,8 +803,8 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
}
});
menu.add(item);
-
-
+
+
//// About
item = new JMenuItem(trans.get("main.menu.help.about"), KeyEvent.VK_A);
item.setIcon(Icons.HELP_ABOUT);
@@ -794,24 +817,24 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
}
});
menu.add(item);
-
-
+
+
this.setJMenuBar(menubar);
}
-
+
private JMenu makeDebugMenu() {
JMenu menu;
JMenuItem item;
-
+
/*
* This menu is intentionally left untranslated.
*/
-
+
//// Debug menu
menu = new JMenu("Debug");
//// OpenRocket debugging tasks
menu.getAccessibleContext().setAccessibleDescription("OpenRocket debugging tasks");
-
+
//// What is this menu?
item = new JMenuItem("What is this menu?");
item.addActionListener(new ActionListener() {
@@ -822,16 +845,16 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
new Object[] {
"The 'Debug' menu includes actions for testing and debugging " +
"OpenRocket.", " ",
- "The menu is made visible by defining the system property " +
- "'openrocket.debug.menu' when starting OpenRocket.",
- "It should not be visible by default." },
+ "The menu is made visible by defining the system property " +
+ "'openrocket.debug.menu' when starting OpenRocket.",
+ "It should not be visible by default." },
"Debug menu", JOptionPane.INFORMATION_MESSAGE);
}
});
menu.add(item);
-
+
menu.addSeparator();
-
+
//// Create test rocket
item = new JMenuItem("Create test rocket");
item.addActionListener(new ActionListener() {
@@ -845,8 +868,8 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
}, "Generate random test rocket", JOptionPane.DEFAULT_OPTION,
JOptionPane.QUESTION_MESSAGE, null, new Object[] {
"Random", "OK"
- }, "OK");
-
+ }, "OK");
+
Rocket r;
if (sel == 0) {
r = new TestRockets(null).makeTestRocket();
@@ -855,7 +878,7 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
} else {
return;
}
-
+
OpenRocketDocument doc = OpenRocketDocumentFactory.createDocumentFromRocket(r);
doc.setSaved(true);
BasicFrame frame = new BasicFrame(doc);
@@ -863,9 +886,9 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
}
});
menu.add(item);
-
-
-
+
+
+
item = new JMenuItem("Create 'Iso-Haisu'");
item.addActionListener(new ActionListener() {
@Override
@@ -879,8 +902,8 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
}
});
menu.add(item);
-
-
+
+
item = new JMenuItem("Create 'Big Blue'");
item.addActionListener(new ActionListener() {
@Override
@@ -894,16 +917,16 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
}
});
menu.add(item);
-
+
menu.addSeparator();
-
-
+
+
item = new JMenuItem("Memory statistics");
item.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
log.info(Markers.USER_MARKER, "Memory statistics selected");
-
+
// Get discarded but remaining objects (this also runs System.gc multiple times)
List objects = MemoryManagement.getRemainingCollectableObjects();
StringBuilder sb = new StringBuilder();
@@ -914,13 +937,13 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
if (o == null)
continue;
sb.append("Age ").append(System.currentTimeMillis() - data.getRegistrationTime())
- .append(" ms: ").append(o).append('\n');
+ .append(" ms: ").append(o).append('\n');
count++;
// Explicitly null the strong reference to avoid possibility of invisible references
o = null;
}
sb.append("Total: " + count);
-
+
// Get basic memory stats
System.gc();
long max = Runtime.getRuntime().maxMemory();
@@ -931,14 +954,14 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
stats[1] = String.format(" Max memory: %.1f MB", max / 1024.0 / 1024.0);
stats[2] = String.format(" Used memory: %.1f MB (%.0f%%)", used / 1024.0 / 1024.0, 100.0 * used / max);
stats[3] = String.format(" Free memory: %.1f MB (%.0f%%)", free / 1024.0 / 1024.0, 100.0 * free / max);
-
-
+
+
DetailDialog.showDetailedMessageDialog(BasicFrame.this, stats, sb.toString(),
"Memory statistics", JOptionPane.INFORMATION_MESSAGE);
}
});
menu.add(item);
-
+
//// Exhaust memory
item = new JMenuItem("Exhaust memory");
item.addActionListener(new ActionListener() {
@@ -968,10 +991,10 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
}
});
menu.add(item);
-
-
+
+
menu.addSeparator();
-
+
//// Exception here
item = new JMenuItem("Exception here");
item.addActionListener(new ActionListener() {
@@ -982,7 +1005,7 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
}
});
menu.add(item);
-
+
item = new JMenuItem("Exception from EDT");
item.addActionListener(new ActionListener() {
@Override
@@ -998,7 +1021,7 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
}
});
menu.add(item);
-
+
item = new JMenuItem("Exception from other thread");
item.addActionListener(new ActionListener() {
@Override
@@ -1013,7 +1036,7 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
}
});
menu.add(item);
-
+
item = new JMenuItem("OutOfMemoryError here");
item.addActionListener(new ActionListener() {
@Override
@@ -1023,11 +1046,11 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
}
});
menu.add(item);
-
-
+
+
menu.addSeparator();
-
-
+
+
item = new JMenuItem("Test popup");
item.addActionListener(new ActionListener() {
@Override
@@ -1043,14 +1066,14 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
}
});
menu.add(item);
-
-
-
-
+
+
+
+
return menu;
}
-
-
+
+
/**
* Select the tab on the main pane.
*
@@ -1059,17 +1082,16 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
public void selectTab(int tab) {
tabbedPane.setSelectedIndex(tab);
}
-
-
-
+
+
+
private void openAction() {
JFileChooser chooser = new JFileChooser();
-
+
chooser.addChoosableFileFilter(FileHelper.ALL_DESIGNS_FILTER);
chooser.addChoosableFileFilter(FileHelper.OPENROCKET_DESIGN_FILTER);
- chooser.addChoosableFileFilter(FileHelper.ROCKSIM_DESIGN_FILTER);
- chooser.setFileFilter(FileHelper.ALL_DESIGNS_FILTER);
-
+ chooser.setFileFilter(FileHelper.OPENROCKET_DESIGN_FILTER);
+
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
chooser.setMultiSelectionEnabled(true);
chooser.setCurrentDirectory(((SwingPreferences) Application.getPreferences()).getDefaultDirectory());
@@ -1078,12 +1100,12 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
log.info(Markers.USER_MARKER, "Decided not to open files, option=" + option);
return;
}
-
+
((SwingPreferences) Application.getPreferences()).setDefaultDirectory(chooser.getCurrentDirectory());
-
+
File[] files = chooser.getSelectedFiles();
log.info(Markers.USER_MARKER, "Opening files " + Arrays.toString(files));
-
+
for (File file : files) {
log.info("Opening file: " + file);
if (open(file, this)) {
@@ -1092,20 +1114,51 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
}
}
}
-
+
+ private void importAction() {
+ JFileChooser chooser = new JFileChooser();
+
+ chooser.addChoosableFileFilter(FileHelper.ALL_DESIGNS_FILTER);
+ chooser.addChoosableFileFilter(FileHelper.ROCKSIM_DESIGN_FILTER);
+ chooser.setFileFilter(FileHelper.ROCKSIM_DESIGN_FILTER);
+
+ chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
+ chooser.setMultiSelectionEnabled(true);
+ chooser.setCurrentDirectory(((SwingPreferences) Application.getPreferences()).getDefaultDirectory());
+ int option = chooser.showOpenDialog(this);
+ if (option != JFileChooser.APPROVE_OPTION) {
+ log.info(Markers.USER_MARKER, "Decided not to open files, option=" + option);
+ return;
+ }
+
+ ((SwingPreferences) Application.getPreferences()).setDefaultDirectory(chooser.getCurrentDirectory());
+
+ File[] files = chooser.getSelectedFiles();
+ log.info(Markers.USER_MARKER, "Opening files " + Arrays.toString(files));
+
+ for (File file : files) {
+ log.info("Opening file: " + file);
+ if (open(file, this)) {
+ MRUDesignFile opts = MRUDesignFile.getInstance();
+ opts.addFile(file.getAbsolutePath());
+ }
+ }
+ }
+
+
void closeIfReplaceable() {
// Close previous window if replacing
if (replaceable && document.isSaved()) {
// We are replacing the frame, make new window have current location
BasicFrame newFrame = frames.get(frames.size() - 1);
newFrame.setLocation(this.getLocation());
-
+
log.info("Closing window because it is replaceable");
closeAction();
}
-
+
}
-
+
/**
* Open a file based on a URL.
* @param url the file to open.
@@ -1115,14 +1168,14 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
public static void open(URL url, BasicFrame parent) {
String displayName = null;
// First figure out the file name from the URL
-
+
// Try using URI.getPath();
try {
URI uri = url.toURI();
displayName = uri.getPath();
} catch (URISyntaxException ignore) {
}
-
+
// Try URL-decoding the URL
if (displayName == null) {
try {
@@ -1130,25 +1183,25 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
} catch (UnsupportedEncodingException ignore) {
}
}
-
+
if (displayName == null) {
displayName = "";
}
-
+
// Remove path from filename
if (displayName.lastIndexOf('/') >= 0) {
displayName = displayName.substring(displayName.lastIndexOf('/') + 1);
}
-
-
+
+
// Open the file
log.info("Opening file from url=" + url + " filename=" + displayName);
-
+
OpenFileWorker worker = new OpenFileWorker(url);
open(worker, displayName, parent, true);
}
-
-
+
+
/**
* Open the specified file in a new design frame. If an error occurs, an error
* dialog is shown and false
is returned.
@@ -1161,8 +1214,8 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
OpenFileWorker worker = new OpenFileWorker(file);
return open(worker, file.getName(), parent, false);
}
-
-
+
+
/**
* Open the specified file using the provided worker.
*
@@ -1181,50 +1234,50 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
log.info("User cancelled the OpenFileWorker");
return false;
}
-
-
+
+
// Handle the document
OpenRocketDocument doc = null;
try {
-
+
doc = worker.get();
-
+
} catch (ExecutionException e) {
-
+
Throwable cause = e.getCause();
-
+
if (cause instanceof FileNotFoundException) {
-
+
log.warn("File not found", cause);
JOptionPane.showMessageDialog(parent,
"File not found: " + displayName,
"Error opening file", JOptionPane.ERROR_MESSAGE);
return false;
-
+
} else if (cause instanceof RocketLoadException) {
-
+
log.warn("Error loading the file", cause);
JOptionPane.showMessageDialog(parent,
"Unable to open file '" + displayName + "': "
+ cause.getMessage(),
- "Error opening file", JOptionPane.ERROR_MESSAGE);
+ "Error opening file", JOptionPane.ERROR_MESSAGE);
return false;
-
+
} else {
-
+
throw new BugException("Unknown error when opening file", e);
-
+
}
-
+
} catch (InterruptedException e) {
throw new BugException("EDT was interrupted", e);
}
-
+
if (doc == null) {
throw new BugException("Document loader returned null");
}
-
-
+
+
// Show warnings
WarningSet warnings = worker.getRocketLoader().getWarnings();
if (!warnings.isEmpty()) {
@@ -1235,26 +1288,26 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
trans.get("BasicFrame.WarningDialog.txt1") + " " + displayName + ".",
//// Some design features may not have been loaded correctly.
trans.get("BasicFrame.WarningDialog.txt2")
- },
+ },
//// Warnings while opening file
trans.get("BasicFrame.WarningDialog.title"), warnings);
}
-
+
// Open the frame
log.debug("Opening new frame with the document");
BasicFrame frame = new BasicFrame(doc);
frame.setVisible(true);
-
+
if (parent != null && parent instanceof BasicFrame) {
((BasicFrame) parent).closeIfReplaceable();
}
if (openRocketConfigDialog) {
ComponentConfigDialog.showDialog(frame, doc, doc.getRocket());
}
-
+
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
@@ -1265,114 +1318,47 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
*/
private boolean saveAction() {
File file = document.getFile();
- if (file == null) {
+ if (file == null || document.getDefaultStorageOptions().getFileType().equals(FileType.ROCKSIM)) {
log.info("Document does not contain file, opening save as dialog instead");
return saveAsAction();
}
+
log.info("Saving document to " + file);
-
- if (FileHelper.ROCKSIM_DESIGN_FILTER.accept(file)) {
- return saveAsRocksim(file);
- }
- return saveAs(file);
+
+ return saveAsOpenRocket(file);
}
-
- private static String oldFileName=null;
- public void propertyChange(PropertyChangeEvent event){
- if( JFileChooser.SELECTED_FILE_CHANGED_PROPERTY == event.getPropertyName()){
- if(null != event.getOldValue()){
- BasicFrame.oldFileName = ((File)event.getOldValue()).getName();
- }
- return;
- }else if(JFileChooser.FILE_FILTER_CHANGED_PROPERTY == event.getPropertyName()){
- JFileChooser chooser = (JFileChooser)event.getSource();
- SimpleFileFilter filter = (SimpleFileFilter)(chooser.getFileFilter());
- String desiredExtension = filter.getExtensions()[0];
-
- if( null == BasicFrame.oldFileName){
- return;
- }
- String thisFileName = BasicFrame.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;
- }
- }
- }
-
+
+
/**
- * "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.
+ * "Export" action.
*
* @return true if the file was saved, false otherwise
*/
- private boolean saveAsAction() {
+ private boolean exportAction() {
File file = null;
-
- StorageOptionChooser storageChooser =
- new StorageOptionChooser(document, document.getDefaultStorageOptions());
- final JFileChooser chooser = new JFileChooser();
- chooser.setAcceptAllFileFilterUsed(false);
- chooser.addChoosableFileFilter(FileHelper.OPENROCKET_DESIGN_FILTER);
- chooser.addChoosableFileFilter(FileHelper.ROCKSIM_DESIGN_FILTER);
- chooser.addPropertyChangeListener(JFileChooser.FILE_FILTER_CHANGED_PROPERTY, this);
- chooser.addPropertyChangeListener(JFileChooser.SELECTED_FILE_CHANGED_PROPERTY, this);
- chooser.addPropertyChangeListener(JFileChooser.SELECTED_FILES_CHANGED_PROPERTY, this);
-
- //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) {
- chooser.setSelectedFile(document.getFile());
- }
-
+
+ final SaveAsFileChooser chooser = SaveAsFileChooser.build(document, FileType.ROCKSIM);
+
int option = chooser.showSaveDialog(BasicFrame.this);
+
if (option != JFileChooser.APPROVE_OPTION) {
log.info(Markers.USER_MARKER, "User decided not to save, option=" + option);
return false;
}
-
+
file = chooser.getSelectedFile();
if (file == null) {
log.info(Markers.USER_MARKER, "User did not select a file");
return false;
}
-
+
((SwingPreferences) Application.getPreferences()).setDefaultDirectory(chooser.getCurrentDirectory());
- storageChooser.storeOptions(document.getDefaultStorageOptions());
-
- if (chooser.getFileFilter().equals(FileHelper.ROCKSIM_DESIGN_FILTER)) {
+
+ file = FileHelper.forceExtension(file, "ork");
+ if (FileHelper.confirmWrite(file, this) ) {
return saveAsRocksim(file);
}
- else {
- file = FileHelper.forceExtension(file, "ork");
- boolean result = FileHelper.confirmWrite(file, this) && saveAs(file);
- if (result) {
- MRUDesignFile opts = MRUDesignFile.getInstance();
- opts.addFile(file.getAbsolutePath());
- }
- return result;
- }
+ return false;
}
/**
@@ -1383,11 +1369,35 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
* @return true if the file was written
*/
private boolean saveAsRocksim(File file) {
- file = FileHelper.forceExtension(file, "rkt");
+ if ( prefs.getShowRockSimFormatWarning() ) {
+ // Show Rocksim format warning
+ JPanel panel = new JPanel(new MigLayout());
+ panel.add(new StyledLabel(trans.get("SaveRktWarningDialog.txt1")), "wrap");
+ final JCheckBox check = new JCheckBox(trans.get("SaveRktWarningDialog.donotshow"));
+ check.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ prefs.setShowRockSimFormatWarning(!check.isSelected());
+ }
+ });
+ panel.add(check);
+ int sel = JOptionPane.showOptionDialog(null,
+ panel,
+ "", // title
+ JOptionPane.OK_CANCEL_OPTION,
+ JOptionPane.WARNING_MESSAGE,
+ null, // icon
+ null, // options
+ null // default option
+ );
+ if ( sel == 1 ) {
+ return false;
+ }
+ }
if (!FileHelper.confirmWrite(file, this)) {
return false;
}
-
+
try {
StorageOptions options = new StorageOptions();
options.setFileType(StorageOptions.FileType.ROCKSIM);
@@ -1398,7 +1408,42 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
return false;
}
}
-
+
+ /**
+ * "Save As" action.
+ *
+ * @return true if the file was saved, false otherwise
+ */
+ private boolean saveAsAction() {
+ File file = null;
+
+ final SaveAsFileChooser chooser = SaveAsFileChooser.build(document, FileType.OPENROCKET);
+
+ int option = chooser.showSaveDialog(BasicFrame.this);
+
+ if (option != JFileChooser.APPROVE_OPTION) {
+ log.info(Markers.USER_MARKER, "User decided not to save, option=" + option);
+ return false;
+ }
+
+ file = chooser.getSelectedFile();
+ if (file == null) {
+ log.info(Markers.USER_MARKER, "User did not select a file");
+ return false;
+ }
+
+ ((SwingPreferences) Application.getPreferences()).setDefaultDirectory(chooser.getCurrentDirectory());
+ chooser.storeOptions(document.getDefaultStorageOptions());
+
+ file = FileHelper.forceExtension(file, "ork");
+ boolean result = FileHelper.confirmWrite(file, this) && saveAsOpenRocket(file);
+ if (result) {
+ MRUDesignFile opts = MRUDesignFile.getInstance();
+ opts.addFile(file.getAbsolutePath());
+ }
+ return result;
+ }
+
/**
* Perform the writing of the design to the given file in OpenRocket format.
*
@@ -1406,38 +1451,38 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
*
* @return true if the file was written
*/
- private boolean saveAs(File file) {
+ private boolean saveAsOpenRocket(File file) {
+ file = FileHelper.forceExtension(file, "ork");
log.info("Saving document as " + file);
- boolean saved = false;
-
+
if (!StorageOptionChooser.verifyStorageOptions(document, this)) {
// User cancelled the dialog
log.info(Markers.USER_MARKER, "User cancelled saving in storage options dialog");
return false;
}
-
-
+
+ document.getDefaultStorageOptions().setFileType(FileType.OPENROCKET);
SaveFileWorker worker = new SaveFileWorker(document, file, ROCKET_SAVER);
-
+
if (!SwingWorkerDialog.runWorker(this, "Saving file",
"Writing " + file.getName() + "...", worker)) {
-
+
// User cancelled the save
log.info(Markers.USER_MARKER, "User cancelled the save, deleting the file");
file.delete();
return false;
}
-
+
try {
worker.get();
document.setFile(file);
document.setSaved(true);
- saved = true;
setTitle();
+ return true;
} catch (ExecutionException e) {
-
+
Throwable cause = e.getCause();
-
+
if (cause instanceof IOException) {
log.warn("An I/O error occurred while saving " + file, cause);
JOptionPane.showMessageDialog(this, new String[] {
@@ -1447,23 +1492,23 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
} else {
Reflection.handleWrappedException(e);
}
-
+
} catch (InterruptedException e) {
throw new BugException("EDT was interrupted", e);
}
-
- return saved;
+
+ return false;
}
-
-
+
+
private boolean closeAction() {
if (!document.isSaved()) {
log.info("Confirming whether to save the design");
ComponentConfigDialog.hideDialog();
int result = JOptionPane.showConfirmDialog(this,
trans.get("BasicFrame.dlg.lbl1") + rocket.getName() +
- trans.get("BasicFrame.dlg.lbl2") + " " +
- trans.get("BasicFrame.dlg.lbl3"),
+ trans.get("BasicFrame.dlg.lbl2") + " " +
+ trans.get("BasicFrame.dlg.lbl3"),
trans.get("BasicFrame.dlg.title"), JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE);
if (result == JOptionPane.YES_OPTION) {
@@ -1482,14 +1527,14 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
return false;
}
}
-
+
// Rocket has been saved or discarded
log.debug("Disposing window");
this.dispose();
-
+
ComponentConfigDialog.hideDialog();
ComponentAnalysisDialog.hideDialog();
-
+
frames.remove(this);
if (frames.isEmpty()) {
log.info("Last frame closed, exiting");
@@ -1497,33 +1542,30 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
}
return true;
}
-
+
public void exportDecalAction() {
new ExportDecalDialog(this, document).setVisible(true);
}
-
-
+
+
public void printAction() {
- Double rotation = rocketpanel.getFigure().getRotation();
- if (rotation == null) {
- rotation = 0d;
- }
+ double rotation = rocketpanel.getFigure().getRotation();
new PrintDialog(this, document, rotation).setVisible(true);
}
-
+
/**
* Open a new design window with a basic rocket+stage.
*/
public static void newAction() {
log.info("New action initiated");
-
+
OpenRocketDocument doc = OpenRocketDocumentFactory.createNewRocket();
-
+
BasicFrame frame = new BasicFrame(doc);
frame.replaceable = true;
frame.setVisible(true);
}
-
+
/**
* Quit the application. Confirms saving unsaved designs. The action of File->Quit.
*/
@@ -1541,8 +1583,8 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
log.error("Should already have exited application");
System.exit(0);
}
-
-
+
+
/**
* Set the title of the frame, taking into account the name of the rocket, file it
* has been saved to (if any) and saved status.
@@ -1551,19 +1593,19 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
File file = document.getFile();
boolean saved = document.isSaved();
String title;
-
+
title = rocket.getName();
if (file != null) {
title = title + " (" + file.getName() + ")";
}
if (!saved)
title = "*" + title;
-
+
setTitle(title);
}
-
-
-
+
+
+
/**
* Find a currently open BasicFrame containing the specified rocket. This method
* can be used to map a Rocket to a BasicFrame from GUI methods.
@@ -1581,7 +1623,7 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
log.debug("Could not find frame for rocket " + rocket);
return null;
}
-
+
/**
* Find a currently open document by the rocket object. This method can be used
* to map a Rocket to OpenRocketDocument from GUI methods.
@@ -1597,24 +1639,25 @@ public class BasicFrame extends JFrame implements PropertyChangeListener {
return null;
}
}
-
+
public void stateChanged(ChangeEvent e) {
- JTabbedPane tabSource = (JTabbedPane) e.getSource();
- String tab = tabSource.getTitleAt(tabSource.getSelectedIndex());
- if (tab.equals(trans.get("BasicFrame.tab.Flightsim"))) {
- simulationPanel.activating();
- }
- }
+ JTabbedPane tabSource = (JTabbedPane) e.getSource();
+ String tab = tabSource.getTitleAt(tabSource.getSelectedIndex());
+ if (tab.equals(trans.get("BasicFrame.tab.Flightsim"))) {
+ simulationPanel.activating();
+ }
+ }
}
class BasicFrame_changeAdapter implements javax.swing.event.ChangeListener {
BasicFrame adaptee;
- BasicFrame_changeAdapter(BasicFrame adaptee) {
- this.adaptee = adaptee;
- }
- public void stateChanged(ChangeEvent e) {
- adaptee.stateChanged(e);
- }
-}
\ No newline at end of file
+ BasicFrame_changeAdapter(BasicFrame adaptee) {
+ this.adaptee = adaptee;
+ }
+ public void stateChanged(ChangeEvent e) {
+ adaptee.stateChanged(e);
+ }
+}
+
diff --git a/swing/src/net/sf/openrocket/gui/ExportDecalDialog.java b/swing/src/net/sf/openrocket/gui/main/ExportDecalDialog.java
similarity index 99%
rename from swing/src/net/sf/openrocket/gui/ExportDecalDialog.java
rename to swing/src/net/sf/openrocket/gui/main/ExportDecalDialog.java
index 457dfa54e..b3505784d 100644
--- a/swing/src/net/sf/openrocket/gui/ExportDecalDialog.java
+++ b/swing/src/net/sf/openrocket/gui/main/ExportDecalDialog.java
@@ -1,4 +1,4 @@
-package net.sf.openrocket.gui;
+package net.sf.openrocket.gui.main;
import java.awt.Window;
import java.awt.event.ActionEvent;
diff --git a/swing/src/net/sf/openrocket/gui/main/SaveAsFileChooser.java b/swing/src/net/sf/openrocket/gui/main/SaveAsFileChooser.java
new file mode 100644
index 000000000..80bffaaf7
--- /dev/null
+++ b/swing/src/net/sf/openrocket/gui/main/SaveAsFileChooser.java
@@ -0,0 +1,113 @@
+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.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(true);
+
+ File defaultFilename = document.getFile();
+
+ 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 listner = new RememberFilenamePropertyListener();
+ this.addPropertyChangeListener(JFileChooser.FILE_FILTER_CHANGED_PROPERTY, listner);
+ this.addPropertyChangeListener(JFileChooser.SELECTED_FILE_CHANGED_PROPERTY, listner);
+ this.addPropertyChangeListener(JFileChooser.SELECTED_FILES_CHANGED_PROPERTY, listner);
+
+ 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 == event.getPropertyName()){
+ if(null != event.getOldValue()){
+ this.oldFileName = ((File)event.getOldValue()).getName();
+ }
+ return;
+ }else if(JFileChooser.FILE_FILTER_CHANGED_PROPERTY == event.getPropertyName()){
+ JFileChooser chooser = (JFileChooser)event.getSource();
+ 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/StorageOptionChooser.java b/swing/src/net/sf/openrocket/gui/main/StorageOptionChooser.java
similarity index 99%
rename from swing/src/net/sf/openrocket/gui/StorageOptionChooser.java
rename to swing/src/net/sf/openrocket/gui/main/StorageOptionChooser.java
index eac318011..ad836c882 100644
--- a/swing/src/net/sf/openrocket/gui/StorageOptionChooser.java
+++ b/swing/src/net/sf/openrocket/gui/main/StorageOptionChooser.java
@@ -1,4 +1,4 @@
-package net.sf.openrocket.gui;
+package net.sf.openrocket.gui.main;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
diff --git a/swing/src/net/sf/openrocket/gui/util/FileHelper.java b/swing/src/net/sf/openrocket/gui/util/FileHelper.java
index aab125ffc..d43ceffec 100644
--- a/swing/src/net/sf/openrocket/gui/util/FileHelper.java
+++ b/swing/src/net/sf/openrocket/gui/util/FileHelper.java
@@ -117,7 +117,9 @@ public final class FileHelper {
* @return the resulting file
*/
public static File forceExtension(File original, String extension) {
-
+ if ( original == null ) {
+ return null;
+ }
if (!original.getName().toLowerCase(Locale.ENGLISH).endsWith(extension.toLowerCase(Locale.ENGLISH))) {
log.debug("File name does not contain extension, adding '" + extension + "'");
String name = original.getAbsolutePath();