(no commit message)
[sw/motorsim] / src / com / billkuker / rocketry / motorsim / visual / workbench / MotorWorkbench.java
1 package com.billkuker.rocketry.motorsim.visual.workbench;\r
2 \r
3 import java.awt.BorderLayout;\r
4 import java.awt.Component;\r
5 import java.awt.Dimension;\r
6 import java.awt.FileDialog;\r
7 import java.awt.event.ActionEvent;\r
8 import java.awt.event.ActionListener;\r
9 import java.beans.PropertyChangeEvent;\r
10 import java.beans.PropertyChangeListener;\r
11 import java.io.File;\r
12 import java.util.HashMap;\r
13 import java.util.HashSet;\r
14 import java.util.List;\r
15 import java.util.Vector;\r
16 \r
17 import javax.swing.ButtonGroup;\r
18 import javax.swing.DefaultComboBoxModel;\r
19 import javax.swing.JFileChooser;\r
20 import javax.swing.JFrame;\r
21 import javax.swing.JMenu;\r
22 import javax.swing.JMenuBar;\r
23 import javax.swing.JMenuItem;\r
24 import javax.swing.JOptionPane;\r
25 import javax.swing.JPanel;\r
26 import javax.swing.JRadioButtonMenuItem;\r
27 import javax.swing.JScrollPane;\r
28 import javax.swing.JSeparator;\r
29 import javax.swing.JSplitPane;\r
30 import javax.swing.JTabbedPane;\r
31 import javax.swing.JTree;\r
32 import javax.swing.WindowConstants;\r
33 import javax.swing.event.TreeSelectionEvent;\r
34 import javax.swing.event.TreeSelectionListener;\r
35 import javax.swing.tree.DefaultMutableTreeNode;\r
36 import javax.swing.tree.TreePath;\r
37 import javax.swing.tree.TreeSelectionModel;\r
38 \r
39 import com.billkuker.rocketry.motorsim.Burn;\r
40 import com.billkuker.rocketry.motorsim.Fuel;\r
41 import com.billkuker.rocketry.motorsim.Motor;\r
42 import com.billkuker.rocketry.motorsim.RocketScience.UnitPreference;\r
43 import com.billkuker.rocketry.motorsim.fuel.EditableFuel;\r
44 import com.billkuker.rocketry.motorsim.fuel.KNDX;\r
45 import com.billkuker.rocketry.motorsim.fuel.KNER;\r
46 import com.billkuker.rocketry.motorsim.fuel.KNSB;\r
47 import com.billkuker.rocketry.motorsim.fuel.KNSU;\r
48 import com.billkuker.rocketry.motorsim.io.ENGExporter;\r
49 import com.billkuker.rocketry.motorsim.io.MotorIO;\r
50 import com.billkuker.rocketry.motorsim.visual.FuelPanel;\r
51 import com.billkuker.rocketry.motorsim.visual.workbench.WorkbenchTreeModel.FuelEditNode;\r
52 import com.billkuker.rocketry.motorsim.visual.workbench.WorkbenchTreeModel.FuelNode;\r
53 \r
54 public class MotorWorkbench extends JFrame implements TreeSelectionListener {\r
55         private static final long serialVersionUID = 1L;\r
56         \r
57         @SuppressWarnings("unchecked")\r
58         private Class[] fuelTypes = { KNSB.class, KNSU.class, KNER.class,\r
59                         KNDX.class };\r
60         \r
61         private JPanel top;\r
62         private JSplitPane split;\r
63         private JTree tree;\r
64         private JTabbedPane motors;\r
65         private WorkbenchTreeModel tm;\r
66         private MultiBurnChart mb;\r
67         private JFrame allBurns;\r
68 \r
69         private HashMap<MotorEditor, File> e2f = new HashMap<MotorEditor, File>();\r
70         private HashMap<File, MotorEditor> f2e = new HashMap<File, MotorEditor>();\r
71 \r
72         private HashMap<Motor, MotorEditor> m2e = new HashMap<Motor, MotorEditor>();\r
73         \r
74         private DefaultComboBoxModel fuels = new DefaultComboBoxModel();\r
75         \r
76         public MotorWorkbench() {\r
77                 setTitle("MotorSim 1.0 RC1");\r
78                 addMenu();\r
79                 setSize(1024, 768);\r
80                 top = new JPanel(new BorderLayout());\r
81                 setContentPane(top);\r
82                 \r
83                 mb = new MultiBurnChart();\r
84                 allBurns = new JFrame();\r
85                 allBurns.setTitle("All Burns");\r
86                 allBurns.setSize(800, 600);\r
87                 setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE);\r
88                 allBurns.add(mb);\r
89                 allBurns.setVisible(true);\r
90                 \r
91                 motors = new JTabbedPane();\r
92 \r
93                 tree = new JTree(tm = new WorkbenchTreeModel());\r
94                 tree.setCellRenderer(new WorkbenchTreeCellRenderer());\r
95                 tree.getSelectionModel().setSelectionMode(\r
96                                 TreeSelectionModel.SINGLE_TREE_SELECTION);\r
97                 tree.setMinimumSize(new Dimension(200, 100));\r
98 \r
99                 // Listen for when the selection changes.\r
100                 tree.addTreeSelectionListener(this);\r
101 \r
102                 split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, new JScrollPane(\r
103                                 tree), motors);\r
104                 split.setDividerLocation(200);\r
105                 split.setResizeWeight(0);\r
106                 split.resetToPreferredSizes();\r
107                 split.revalidate();\r
108                 \r
109                 top.add(split, BorderLayout.CENTER);\r
110                 \r
111                 for ( Class<Fuel> f : fuelTypes){\r
112                         try {\r
113                                 addFuel(f.newInstance());\r
114                         } catch (InstantiationException e) {\r
115                                 // TODO Auto-generated catch block\r
116                                 e.printStackTrace();\r
117                         } catch (IllegalAccessException e) {\r
118                                 // TODO Auto-generated catch block\r
119                                 e.printStackTrace();\r
120                         }\r
121                 }\r
122 \r
123                 setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);\r
124                 setVisible(true);\r
125 \r
126         }\r
127 \r
128         private void addMenu() {\r
129 \r
130                 setJMenuBar(new JMenuBar() {\r
131                         private static final long serialVersionUID = 1L;\r
132 \r
133                         {\r
134                                 add(new JMenu("File") {\r
135                                         private static final long serialVersionUID = 1L;\r
136 \r
137                                         {\r
138                                                 add(new JMenuItem("New Motor") {\r
139                                                         private static final long serialVersionUID = 1L;\r
140                                                         {\r
141                                                                 addActionListener(new ActionListener() {\r
142 \r
143                                                                         @Override\r
144                                                                         public void actionPerformed(ActionEvent arg0) {\r
145                                                                                 addMotor(MotorEditor.defaultMotor(),\r
146                                                                                                 null);\r
147                                                                         }\r
148                                                                 });\r
149 \r
150                                                         }\r
151                                                 });\r
152                                                 add(new JMenuItem("Open...") {\r
153                                                         private static final long serialVersionUID = 1L;\r
154                                                         {\r
155                                                                 addActionListener(new ActionListener() {\r
156                                                                         @Override\r
157                                                                         public void actionPerformed(ActionEvent arg0) {\r
158 \r
159                                                                                 final FileDialog fd = new FileDialog(MotorWorkbench.this, "Open Motor", FileDialog.LOAD);\r
160                                                                                 fd.setVisible(true);\r
161                                                                                 if ( fd.getFile() != null ) {\r
162                                                                                         File file = new File(fd.getDirectory() + fd.getFile());\r
163                                                                                         if (f2e.get(file) != null) {\r
164                                                                                                 motors.setSelectedComponent(f2e\r
165                                                                                                                 .get(file));\r
166                                                                                                 return;\r
167                                                                                         }\r
168                                                                                         try {\r
169                                                                                                 Motor m = MotorIO\r
170                                                                                                                 .readMotor(file);\r
171                                                                                                 addMotor(m, file);\r
172                                                                                         } catch (Exception e) {\r
173                                                                                                 JOptionPane.showMessageDialog(\r
174                                                                                                                 MotorWorkbench.this, e\r
175                                                                                                                                 .getMessage());\r
176                                                                                         }\r
177                                                                                 }\r
178                                                                         }\r
179                                                                 });\r
180                                                         }\r
181                                                 });\r
182                                                 \r
183                                                 add(new JSeparator());\r
184                                                 \r
185                                                 add(new JMenuItem("Close Motor") {\r
186                                                         private static final long serialVersionUID = 1L;\r
187                                                         {\r
188                                                                 addActionListener(new ActionListener() {\r
189                                                                         @Override\r
190                                                                         public void actionPerformed(ActionEvent ev) {\r
191                                                                                 MotorEditor e = (MotorEditor) motors\r
192                                                                                                 .getSelectedComponent();\r
193                                                                                 tm.removeMotor(e.getMotor());\r
194                                                                                 motors.remove(e);\r
195                                                                                 f2e.remove(e2f.get(e));\r
196                                                                                 e2f.remove(e);\r
197                                                                                 m2e.remove(e.getMotor());\r
198                                                                                 mb.removeBurn(e.burn);\r
199                                                                         }\r
200                                                                 });\r
201                                                         }\r
202                                                 });\r
203                                                 \r
204                                                 add(new JMenuItem("Save Motor") {\r
205                                                         private static final long serialVersionUID = 1L;\r
206                                                         {\r
207                                                                 addActionListener(new ActionListener() {\r
208                                                                         @Override\r
209                                                                         public void actionPerformed(ActionEvent e) {\r
210                                                                                 MotorEditor m = (MotorEditor) motors\r
211                                                                                                 .getSelectedComponent();\r
212                                                                                 File f = e2f.get(m);\r
213                                                                                 if (f != null)\r
214                                                                                         save(m.getMotor(), f);\r
215 \r
216                                                                         }\r
217                                                                 });\r
218                                                         }\r
219                                                 });\r
220                                                 add(new JMenuItem("Save Motor As...") {\r
221                                                         private static final long serialVersionUID = 1L;\r
222                                                         {\r
223                                                                 addActionListener(new ActionListener() {\r
224                                                                         @Override\r
225                                                                         public void actionPerformed(ActionEvent arg0) {\r
226 \r
227                                                                                 final FileDialog fd = new FileDialog(MotorWorkbench.this, "Save Motor As", FileDialog.SAVE);\r
228                                                                                 fd.setVisible(true);\r
229                                                                                 if (fd.getFile() != null ) {\r
230                                                                                         File file = new File(fd.getDirectory() + fd.getFile());\r
231                                                                                         MotorEditor m = (MotorEditor) motors\r
232                                                                                                         .getSelectedComponent();\r
233                                                                                         try {\r
234                                                                                                 save(m.getMotor(), file);\r
235                                                                                                 e2f.put(m, file);\r
236                                                                                                 f2e.put(file, m);\r
237                                                                                                 motors.setTitleAt(motors\r
238                                                                                                                 .getSelectedIndex(),\r
239                                                                                                                 file.getName());\r
240                                                                                                 // TODO Set tab title\r
241                                                                                         } catch (Exception e) {\r
242                                                                                                 JOptionPane.showMessageDialog(\r
243                                                                                                                 MotorWorkbench.this, e\r
244                                                                                                                                 .getMessage());\r
245                                                                                         }\r
246                                                                                 }\r
247                                                                         }\r
248                                                                 });\r
249                                                         }\r
250                                                 });\r
251                                                 \r
252 \r
253                                                 add(new JSeparator());\r
254                                                 add(new JMenuItem("New Fuel") {\r
255                                                         private static final long serialVersionUID = 1L;\r
256                                                         {\r
257                                                                 addActionListener(new ActionListener() {\r
258                                                                         @Override\r
259                                                                         public void actionPerformed(ActionEvent arg0) {\r
260                                                                                 newFuel();\r
261                                                                         }\r
262                                                                 });\r
263 \r
264                                                         }\r
265                                                 });\r
266                                                 add(new JMenuItem("Save Fuel") {});\r
267                                                 add(new JSeparator());\r
268                                                 add(new JMenuItem("Export .ENG"){\r
269                                                         private static final long serialVersionUID = 1L;\r
270 \r
271                                                         {\r
272                                                                 addActionListener(new ActionListener() {\r
273                                                                         @Override\r
274                                                                         public void actionPerformed(ActionEvent arg0) {\r
275 \r
276                                                                                 final FileDialog fd = new FileDialog(MotorWorkbench.this, "Export .ENG File", FileDialog.SAVE);\r
277                                                                                 fd.setFile("motorsim.eng");\r
278                                                                                 fd.setVisible(true);\r
279                                                                                 if (fd.getFile() != null ) {\r
280                                                                                         File file = new File(fd.getDirectory() + fd.getFile());\r
281                                                                                         Vector<Burn> bb = new Vector<Burn>();\r
282                                                                                         for( MotorEditor me : m2e.values() )\r
283                                                                                                 bb.add(me.burn);\r
284                                                                                         try{\r
285                                                                                                 ENGExporter.export(bb, file);\r
286                                                                                         } catch ( Exception e ){\r
287                                                                                                 e.printStackTrace();\r
288                                                                                         }\r
289                                                                                 }\r
290                                                                         }\r
291                                                                 });\r
292                                                         }\r
293                                                 });\r
294                                         }\r
295                                 });\r
296                                 add(new JMenu("Settings") {\r
297                                         private static final long serialVersionUID = 1L;\r
298                                         {\r
299                                                 ButtonGroup units = new ButtonGroup();\r
300                                                 JRadioButtonMenuItem sci = new JRadioButtonMenuItem(\r
301                                                                 "SI");\r
302                                                 JRadioButtonMenuItem nonsci = new JRadioButtonMenuItem(\r
303                                                                 "NonSI");\r
304                                                 units.add(sci);\r
305                                                 units.add(nonsci);\r
306                                                 sci.setSelected(true);\r
307                                                 sci.addActionListener(new ActionListener() {\r
308                                                         public void actionPerformed(ActionEvent arg0) {\r
309                                                                 UnitPreference.preference = UnitPreference.SI;\r
310                                                         }\r
311                                                 });\r
312                                                 nonsci.addActionListener(new ActionListener() {\r
313                                                         public void actionPerformed(ActionEvent arg0) {\r
314                                                                 UnitPreference.preference = UnitPreference.NONSI;\r
315                                                         }\r
316                                                 });\r
317                                                 add(sci);\r
318                                                 add(nonsci);\r
319                                         }\r
320                                 });\r
321                         }\r
322                 });\r
323         }\r
324         \r
325         private void addFuel(Fuel f){\r
326                 fuels.addElement(f);\r
327                 FuelPanel fp = new FuelPanel(f);\r
328                 FuelNode fn = tm.new FuelNode(fp, f);\r
329                 tm.getFuels().add(fn);\r
330                 tm.nodeStructureChanged(tm.getFuels());\r
331                 motors.addTab(f.getName(), fp);\r
332         }\r
333         \r
334         private void newFuel(){\r
335                 final SRFuelEditor ed = new SRFuelEditor();\r
336                 fuels.addElement(ed.getFuel());\r
337                 final FuelEditNode node = tm.new FuelEditNode(ed);\r
338                 tm.getFuels().add(node);\r
339                 tm.nodeStructureChanged(tm.getFuels());\r
340                 motors.addTab(ed.getFuel().getName(), ed);\r
341                 ed.getFuel().addPropertyChangeListener(new PropertyChangeListener(){\r
342                         @Override\r
343                         public void propertyChange(PropertyChangeEvent evt) {\r
344                                 if ( evt.getPropertyName().equals("Name")){\r
345                                         for ( int i = 0; i < motors.getTabCount(); i++ ){\r
346                                                 if ( motors.getComponent(i) == ed ){\r
347                                                         motors.setTitleAt(i, ed.getFuel().getName());\r
348                                                         tm.nodeChanged(node);\r
349                                                 }\r
350                                         }\r
351                                 }\r
352                         }});\r
353         }\r
354 \r
355         private void save(Motor m, File f) {\r
356                 try {\r
357                         MotorIO.writeMotor(m, f);\r
358                 } catch (Throwable t) {\r
359                         JOptionPane.showMessageDialog(MotorWorkbench.this, t.getMessage());\r
360                 }\r
361         }\r
362 \r
363         public void addMotor(Motor m, File f) {\r
364                 tm.addMotor(m);\r
365                 MotorEditor e = new MotorEditor(m, fuels);\r
366                 e.addBurnWatcher(mb);\r
367                 String title;\r
368                 if (f == null) {\r
369                         title = "New Motor";\r
370                 } else {\r
371                         title = f.getName();\r
372                         e2f.put(e, f);\r
373                         f2e.put(f, e);\r
374                 }\r
375                 m2e.put(m, e);\r
376                 motors.addTab(title, e);\r
377         }\r
378 \r
379         @Override\r
380         public void valueChanged(TreeSelectionEvent e) {\r
381                 if ( e.getPath().getLastPathComponent() == tm.getMotors() ){\r
382                         allBurns.setVisible(true);\r
383                         allBurns.toFront();\r
384                 }\r
385                 \r
386                 if ( e.getPath().getLastPathComponent() instanceof FuelNode ){\r
387                         FuelNode fen = ((FuelNode)e.getPath().getLastPathComponent());\r
388                                 motors.setSelectedComponent(fen.getUserObject());                       \r
389                 }\r
390                 \r
391                 Motor m = getMotor(e.getPath());\r
392                 \r
393                 if ( m == null )\r
394                         return;\r
395 \r
396                 motors.setSelectedComponent(m2e.get(m));\r
397 \r
398                 if (e.getPath().getLastPathComponent() instanceof DefaultMutableTreeNode) {\r
399                         Object o = ((DefaultMutableTreeNode) e.getPath()\r
400                                         .getLastPathComponent()).getUserObject();\r
401                         m2e.get(m).focusOnObject(o);\r
402                 }\r
403                 \r
404 \r
405         }\r
406 \r
407         private Motor getMotor(TreePath p) {\r
408                 if (p.getLastPathComponent() instanceof WorkbenchTreeModel.MotorNode) {\r
409                         return ((WorkbenchTreeModel.MotorNode) p.getLastPathComponent())\r
410                                         .getUserObject();\r
411                 } else if (p.getPath().length > 1)\r
412                         return getMotor(p.getParentPath());\r
413                 return null;\r
414         }\r
415 }\r