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