package com.billkuker.rocketry.motorsim.visual.workbench;\r
\r
-import java.awt.BorderLayout;\r
-import java.awt.Dimension;\r
-import java.awt.FileDialog;\r
+import java.awt.Image;\r
+import java.awt.Toolkit;\r
import java.awt.event.ActionEvent;\r
import java.awt.event.ActionListener;\r
-import java.beans.PropertyChangeEvent;\r
-import java.beans.PropertyChangeListener;\r
-import java.io.File;\r
-import java.util.HashMap;\r
-import java.util.List;\r
-import java.util.Vector;\r
+import java.awt.event.WindowEvent;\r
+import java.awt.event.WindowListener;\r
\r
import javax.swing.ButtonGroup;\r
-import javax.swing.DefaultComboBoxModel;\r
import javax.swing.JFrame;\r
import javax.swing.JMenu;\r
import javax.swing.JMenuBar;\r
import javax.swing.JMenuItem;\r
import javax.swing.JOptionPane;\r
-import javax.swing.JPanel;\r
import javax.swing.JRadioButtonMenuItem;\r
-import javax.swing.JScrollPane;\r
import javax.swing.JSeparator;\r
-import javax.swing.JSplitPane;\r
-import javax.swing.JTabbedPane;\r
-import javax.swing.JTree;\r
-import javax.swing.WindowConstants;\r
-import javax.swing.event.TreeSelectionEvent;\r
-import javax.swing.event.TreeSelectionListener;\r
-import javax.swing.tree.DefaultMutableTreeNode;\r
-import javax.swing.tree.TreePath;\r
-import javax.swing.tree.TreeSelectionModel;\r
\r
-import com.billkuker.rocketry.motorsim.Burn;\r
-import com.billkuker.rocketry.motorsim.Fuel;\r
-import com.billkuker.rocketry.motorsim.Motor;\r
import com.billkuker.rocketry.motorsim.RocketScience.UnitPreference;\r
-import com.billkuker.rocketry.motorsim.fuel.KNDX;\r
-import com.billkuker.rocketry.motorsim.fuel.KNER;\r
-import com.billkuker.rocketry.motorsim.fuel.KNSB;\r
-import com.billkuker.rocketry.motorsim.fuel.KNSU;\r
-import com.billkuker.rocketry.motorsim.io.ENGExporter;\r
-import com.billkuker.rocketry.motorsim.io.MotorIO;\r
-import com.billkuker.rocketry.motorsim.visual.FuelPanel;\r
-import com.billkuker.rocketry.motorsim.visual.workbench.WorkbenchTreeModel.FuelEditNode;\r
-import com.billkuker.rocketry.motorsim.visual.workbench.WorkbenchTreeModel.FuelNode;\r
+import com.billkuker.rocketry.motorsim.debug.DebugFrame;\r
+import com.billkuker.rocketry.motorsim.fuel.FuelsEditor;\r
+import com.billkuker.rocketry.motorsim.visual.RememberJFrame;\r
\r
-public class MotorWorkbench extends JFrame implements TreeSelectionListener {\r
+\r
+public class MotorWorkbench extends RememberJFrame {\r
+ public static final String version = "2.0 BETA3";\r
+ public static final String name = "MotorSim " + version;\r
private static final long serialVersionUID = 1L;\r
\r
- private List<Class<? extends Fuel>> fuelTypes = new Vector<Class<? extends Fuel>>();\r
- {\r
- fuelTypes.add(KNSB.class);\r
- fuelTypes.add(KNSU.class);\r
- fuelTypes.add(KNER.class);\r
- fuelTypes.add(KNDX.class);\r
- }\r
- \r
- private JPanel top;\r
- private JSplitPane split;\r
- private JTree tree;\r
- private JTabbedPane motors;\r
- private WorkbenchTreeModel tm;\r
- private MultiBurnChart mb;\r
+ private MultiMotorThrustChart mb;\r
private JFrame allBurns;\r
-\r
- private HashMap<MotorEditor, File> e2f = new HashMap<MotorEditor, File>();\r
- private HashMap<File, MotorEditor> f2e = new HashMap<File, MotorEditor>();\r
-\r
- private HashMap<Motor, MotorEditor> m2e = new HashMap<Motor, MotorEditor>();\r
\r
- private DefaultComboBoxModel fuels = new DefaultComboBoxModel();\r
+ private SettingsEditor settings = new SettingsEditor(this);\r
+ \r
+ private About about = new About(this);\r
+ \r
+ private JFrame fuelEditorFrame = new RememberJFrame(800,600){\r
+ private static final long serialVersionUID = 1L;\r
+ {\r
+ setIconImage(getIcon());\r
+ setSize(800, 600);\r
+ add(fuelEditor = new FuelsEditor(this));\r
+ JMenuBar b;\r
+ setJMenuBar(b = new JMenuBar());\r
+ b.add(fuelEditor.getMenu());\r
+ setTitle(name + " - Fuel Editor");\r
+ }\r
+ };\r
+ private FuelsEditor fuelEditor;\r
+ \r
+ private MotorsEditor motorsEditor;\r
+\r
+ public static Image getIcon(){\r
+ return Toolkit.getDefaultToolkit().getImage(MotorWorkbench.class.getResource("icon.png"));\r
+ }\r
\r
public MotorWorkbench() {\r
- setTitle("MotorSim 1.0 RC1");\r
+ super(1024, 768);\r
+ setTitle(name);\r
+ setIconImage(getIcon());\r
+\r
+ motorsEditor = new MotorsEditor(this);\r
+ setContentPane(motorsEditor);\r
+ \r
addMenu();\r
- setSize(1024, 768);\r
- top = new JPanel(new BorderLayout());\r
- setContentPane(top);\r
\r
- mb = new MultiBurnChart();\r
+ mb = new MultiMotorThrustChart();\r
allBurns = new JFrame();\r
allBurns.setTitle("All Burns");\r
allBurns.setSize(800, 600);\r
- setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE);\r
allBurns.add(mb);\r
\r
- motors = new JTabbedPane();\r
-\r
- tree = new JTree(tm = new WorkbenchTreeModel());\r
- tree.setCellRenderer(new WorkbenchTreeCellRenderer());\r
- tree.getSelectionModel().setSelectionMode(\r
- TreeSelectionModel.SINGLE_TREE_SELECTION);\r
- tree.setMinimumSize(new Dimension(200, 100));\r
+ setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);\r
\r
- // Listen for when the selection changes.\r
- tree.addTreeSelectionListener(this);\r
+ addWindowListener(new WindowListener() {\r
+ \r
+ @Override\r
+ public void windowOpened(WindowEvent e) {}\r
+ \r
+ @Override\r
+ public void windowIconified(WindowEvent e) {}\r
+ \r
+ @Override\r
+ public void windowDeiconified(WindowEvent e) {}\r
+ \r
+ @Override\r
+ public void windowDeactivated(WindowEvent e) {}\r
+ \r
+ @Override\r
+ public void windowClosing(WindowEvent e) {\r
+ maybeQuit();\r
+ }\r
+ \r
+ @Override\r
+ public void windowClosed(WindowEvent e) {}\r
+ \r
+ @Override\r
+ public void windowActivated(WindowEvent e) {}\r
+ });\r
\r
- split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, new JScrollPane(\r
- tree), motors);\r
- split.setDividerLocation(200);\r
- split.setResizeWeight(0);\r
- split.resetToPreferredSizes();\r
- split.revalidate();\r
- \r
- top.add(split, BorderLayout.CENTER);\r
- \r
- for ( Class<? extends Fuel> f : fuelTypes){\r
- try {\r
- addFuel(f.newInstance());\r
- } catch (InstantiationException e) {\r
- // TODO Auto-generated catch block\r
- e.printStackTrace();\r
- } catch (IllegalAccessException e) {\r
- // TODO Auto-generated catch block\r
- e.printStackTrace();\r
+ }\r
+ \r
+ private void maybeQuit(){\r
+ if (motorsEditor.hasDirty()) {\r
+ int response = JOptionPane\r
+ .showConfirmDialog(\r
+ MotorWorkbench.this,\r
+ "There are unsaved Motors.\nExit Anyway?",\r
+ "Confirm",\r
+ JOptionPane.YES_NO_OPTION);\r
+ if (response == JOptionPane.NO_OPTION) {\r
+ return;\r
}\r
}\r
-\r
- setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);\r
- setVisible(true);\r
-\r
+ if (fuelEditor.hasDirty()) {\r
+ int response = JOptionPane\r
+ .showConfirmDialog(\r
+ MotorWorkbench.this,\r
+ "There are unsaved Fuels.\nExit Anyway?",\r
+ "Confirm",\r
+ JOptionPane.YES_NO_OPTION);\r
+ if (response == JOptionPane.NO_OPTION) {\r
+ return;\r
+ }\r
+ }\r
+ MotorWorkbench.this.dispose();\r
+ System.exit(0);\r
}\r
\r
private void addMenu() {\r
private static final long serialVersionUID = 1L;\r
\r
{\r
- add(new JMenu("File") {\r
+ JMenu file = motorsEditor.getMenu();\r
+ file.add(new JSeparator());\r
+ file.add(new JMenuItem("Quit") {\r
private static final long serialVersionUID = 1L;\r
-\r
{\r
- add(new JMenuItem("New Motor") {\r
- private static final long serialVersionUID = 1L;\r
- {\r
- addActionListener(new ActionListener() {\r
-\r
- @Override\r
- public void actionPerformed(ActionEvent arg0) {\r
- addMotor(MotorEditor.defaultMotor(), null);\r
- }\r
- });\r
-\r
+ addActionListener(new ActionListener() {\r
+ @Override\r
+ public void actionPerformed(ActionEvent e) {\r
+ maybeQuit();\r
}\r
});\r
- add(new JMenuItem("Open...") {\r
- private static final long serialVersionUID = 1L;\r
- {\r
- addActionListener(new ActionListener() {\r
- @Override\r
- public void actionPerformed(ActionEvent arg0) {\r
-\r
- final FileDialog fd = new FileDialog(MotorWorkbench.this, "Open Motor", FileDialog.LOAD);\r
- fd.setVisible(true);\r
- if ( fd.getFile() != null ) {\r
- File file = new File(fd.getDirectory() + fd.getFile());\r
- if (f2e.get(file) != null) {\r
- motors.setSelectedComponent(f2e\r
- .get(file));\r
- return;\r
- }\r
- try {\r
- Motor m = MotorIO\r
- .readMotor(file);\r
- addMotor(m, file);\r
- \r
- } catch (Exception e) {\r
- JOptionPane.showMessageDialog(\r
- MotorWorkbench.this, e\r
- .getMessage());\r
- }\r
- }\r
- }\r
- });\r
+ }\r
+ });\r
+ add(file);\r
+ \r
+ add(new JMenu("Settings") {\r
+ private static final long serialVersionUID = 1L;\r
+ {\r
+ ButtonGroup units = new ButtonGroup();\r
+ JRadioButtonMenuItem sci = new JRadioButtonMenuItem(\r
+ "SI");\r
+ JRadioButtonMenuItem nonsci = new JRadioButtonMenuItem(\r
+ "NonSI");\r
+ units.add(sci);\r
+ units.add(nonsci);\r
+ sci.setSelected(UnitPreference.getUnitPreference() == UnitPreference.SI);\r
+ nonsci.setSelected(UnitPreference.getUnitPreference() == UnitPreference.NONSI);\r
+ sci.addActionListener(new ActionListener() {\r
+ public void actionPerformed(ActionEvent arg0) {\r
+ UnitPreference\r
+ .setUnitPreference(UnitPreference.SI);\r
}\r
});\r
- \r
- add(new JSeparator());\r
- \r
- add(new JMenuItem("Close Motor") {\r
- private static final long serialVersionUID = 1L;\r
- {\r
- addActionListener(new ActionListener() {\r
- @Override\r
- public void actionPerformed(ActionEvent ev) {\r
- MotorEditor e = (MotorEditor) motors\r
- .getSelectedComponent();\r
- tm.removeMotor(e.getMotor());\r
- motors.remove(e);\r
- f2e.remove(e2f.get(e));\r
- e2f.remove(e);\r
- m2e.remove(e.getMotor());\r
- mb.removeBurn(e.burn);\r
- }\r
- });\r
+ nonsci.addActionListener(new ActionListener() {\r
+ public void actionPerformed(ActionEvent arg0) {\r
+ UnitPreference\r
+ .setUnitPreference(UnitPreference.NONSI);\r
}\r
});\r
+ add(sci);\r
+ add(nonsci);\r
\r
- add(new JMenuItem("Save Motor") {\r
+ add(new JSeparator());\r
+ add(new JMenuItem("Simulation Settings"){\r
private static final long serialVersionUID = 1L;\r
{\r
addActionListener(new ActionListener() {\r
@Override\r
public void actionPerformed(ActionEvent e) {\r
- MotorEditor m = (MotorEditor) motors\r
- .getSelectedComponent();\r
- File f = e2f.get(m);\r
- if (f != null)\r
- save(m.getMotor(), f);\r
-\r
+ settings.setVisible(true);\r
}\r
});\r
}\r
});\r
- add(new JMenuItem("Save Motor As...") {\r
+ }\r
+ });\r
+ add(new JMenu("View") {\r
+ private static final long serialVersionUID = 1L;\r
+ {\r
+ add(new JMenuItem("Detach \"All Motors\" tabs") {\r
private static final long serialVersionUID = 1L;\r
{\r
addActionListener(new ActionListener() {\r
@Override\r
public void actionPerformed(ActionEvent arg0) {\r
-\r
- final FileDialog fd = new FileDialog(MotorWorkbench.this, "Save Motor As", FileDialog.SAVE);\r
- fd.setVisible(true);\r
- if (fd.getFile() != null ) {\r
- File file = new File(fd.getDirectory() + fd.getFile());\r
- MotorEditor m = (MotorEditor) motors\r
- .getSelectedComponent();\r
- try {\r
- save(m.getMotor(), file);\r
- e2f.put(m, file);\r
- f2e.put(file, m);\r
- motors.setTitleAt(motors\r
- .getSelectedIndex(),\r
- file.getName());\r
- // TODO Set tab title\r
- } catch (Exception e) {\r
- JOptionPane.showMessageDialog(\r
- MotorWorkbench.this, e\r
- .getMessage());\r
- }\r
- }\r
+ motorsEditor.detach();\r
}\r
});\r
}\r
});\r
- \r
-\r
- add(new JSeparator());\r
- add(new JMenuItem("New Fuel") {\r
+ add(new JMenuItem("Show Fuel Editor") {\r
private static final long serialVersionUID = 1L;\r
{\r
addActionListener(new ActionListener() {\r
@Override\r
public void actionPerformed(ActionEvent arg0) {\r
- newFuel();\r
+ fuelEditorFrame.setVisible(true);\r
+ fuelEditorFrame.toFront();\r
}\r
});\r
-\r
}\r
});\r
- add(new JMenuItem("Save Fuel") {\r
- private static final long serialVersionUID = 1L;\r
- });\r
- add(new JSeparator());\r
- add(new JMenuItem("Export .ENG"){\r
+ }\r
+ });\r
+ add(new JMenu("Help"){\r
+ private static final long serialVersionUID = 1L;\r
+ {\r
+ add(new JMenuItem("About") {\r
private static final long serialVersionUID = 1L;\r
-\r
{\r
addActionListener(new ActionListener() {\r
@Override\r
- public void actionPerformed(ActionEvent arg0) {\r
-\r
- final FileDialog fd = new FileDialog(MotorWorkbench.this, "Export .ENG File", FileDialog.SAVE);\r
- fd.setFile("motorsim.eng");\r
- fd.setVisible(true);\r
- if (fd.getFile() != null ) {\r
- File file = new File(fd.getDirectory() + fd.getFile());\r
- Vector<Burn> bb = new Vector<Burn>();\r
- for( MotorEditor me : m2e.values() )\r
- bb.add(me.burn);\r
- try{\r
- ENGExporter.export(bb, file);\r
- } catch ( Exception e ){\r
- e.printStackTrace();\r
- }\r
- }\r
+ public void actionPerformed(ActionEvent e) {\r
+ about.setVisible(true);\r
}\r
});\r
}\r
});\r
- }\r
- });\r
- add(new JMenu("Settings") {\r
- private static final long serialVersionUID = 1L;\r
- {\r
- ButtonGroup units = new ButtonGroup();\r
- JRadioButtonMenuItem sci = new JRadioButtonMenuItem(\r
- "SI");\r
- JRadioButtonMenuItem nonsci = new JRadioButtonMenuItem(\r
- "NonSI");\r
- units.add(sci);\r
- units.add(nonsci);\r
- sci.setSelected(UnitPreference.getUnitPreference() == UnitPreference.SI);\r
- nonsci.setSelected(UnitPreference.getUnitPreference() == UnitPreference.NONSI);\r
- sci.addActionListener(new ActionListener() {\r
- public void actionPerformed(ActionEvent arg0) {\r
- UnitPreference\r
- .setUnitPreference(UnitPreference.SI);\r
- }\r
- });\r
- nonsci.addActionListener(new ActionListener() {\r
- public void actionPerformed(ActionEvent arg0) {\r
- UnitPreference\r
- .setUnitPreference(UnitPreference.NONSI);\r
- }\r
- });\r
- add(sci);\r
- add(nonsci);\r
- }\r
- });\r
- add(new JMenu("View") {\r
- private static final long serialVersionUID = 1L;\r
- {\r
- add(new JMenuItem("Show All Motors Graph") {\r
+ add(new JMenuItem("Debug") {\r
private static final long serialVersionUID = 1L;\r
{\r
addActionListener(new ActionListener() {\r
@Override\r
- public void actionPerformed(ActionEvent arg0) {\r
- allBurns.setVisible(true);\r
- allBurns.toFront();\r
+ public void actionPerformed(ActionEvent e) {\r
+ new DebugFrame();\r
}\r
});\r
}\r
}\r
});\r
}\r
- \r
- private void addFuel(Fuel f){\r
- \r
- fuels.addElement(f);\r
- FuelPanel fp = new FuelPanel(f);\r
- FuelNode fn = tm.new FuelNode(fp, f);\r
- tm.getFuels().add(fn);\r
- tm.nodeStructureChanged(tm.getFuels());\r
- motors.addTab(f.getName(), fp);\r
- }\r
- \r
- private void newFuel(){\r
- final SRFuelEditor ed = new SRFuelEditor();\r
- fuels.addElement(ed.getFuel());\r
- final FuelEditNode node = tm.new FuelEditNode(ed);\r
- tm.getFuels().add(node);\r
- tm.nodeStructureChanged(tm.getFuels());\r
- motors.addTab(ed.getFuel().getName(), ed);\r
- ed.getFuel().addPropertyChangeListener(new PropertyChangeListener(){\r
- @Override\r
- public void propertyChange(PropertyChangeEvent evt) {\r
- if ( evt.getPropertyName().equals("Name")){\r
- for ( int i = 0; i < motors.getTabCount(); i++ ){\r
- if ( motors.getComponent(i) == ed ){\r
- motors.setTitleAt(i, ed.getFuel().getName());\r
- tm.nodeChanged(node);\r
- }\r
- }\r
- }\r
- }});\r
- }\r
-\r
- private void save(Motor m, File f) {\r
- try {\r
- MotorIO.writeMotor(m, f);\r
- } catch (Throwable t) {\r
- JOptionPane.showMessageDialog(MotorWorkbench.this, t.getMessage());\r
- }\r
- }\r
-\r
- public void addMotor(Motor m, File f) {\r
- tm.addMotor(m);\r
- MotorEditor e = new MotorEditor(m, fuels);\r
- e.addBurnWatcher(mb);\r
- String title;\r
- if (f == null) {\r
- title = "New Motor";\r
- } else {\r
- title = f.getName();\r
- e2f.put(e, f);\r
- f2e.put(f, e);\r
- }\r
- m2e.put(m, e);\r
- motors.addTab(title, e);\r
- }\r
-\r
- @Override\r
- public void valueChanged(TreeSelectionEvent e) { \r
- if ( e.getPath().getLastPathComponent() instanceof FuelNode ){\r
- FuelNode fen = ((FuelNode)e.getPath().getLastPathComponent());\r
- motors.setSelectedComponent(fen.getUserObject()); \r
- }\r
- \r
- Motor m = getMotor(e.getPath());\r
- \r
- if ( m == null )\r
- return;\r
\r
- motors.setSelectedComponent(m2e.get(m));\r
-\r
- if (e.getPath().getLastPathComponent() instanceof DefaultMutableTreeNode) {\r
- Object o = ((DefaultMutableTreeNode) e.getPath()\r
- .getLastPathComponent()).getUserObject();\r
- m2e.get(m).focusOnObject(o);\r
- }\r
- \r
+ \r
\r
- }\r
\r
- private Motor getMotor(TreePath p) {\r
- if (p.getLastPathComponent() instanceof WorkbenchTreeModel.MotorNode) {\r
- return ((WorkbenchTreeModel.MotorNode) p.getLastPathComponent())\r
- .getUserObject();\r
- } else if (p.getPath().length > 1)\r
- return getMotor(p.getParentPath());\r
- return null;\r
- }\r
+ \r
}\r