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