]> git.gag.com Git - sw/motorsim/blob - src/com/billkuker/rocketry/motorsim/visual/workbench/MotorEditor.java
Cleaned up many warnings
[sw/motorsim] / src / com / billkuker / rocketry / motorsim / visual / workbench / MotorEditor.java
1 package com.billkuker.rocketry.motorsim.visual.workbench;\r
2 \r
3 import java.awt.BorderLayout;\r
4 import java.awt.event.ActionEvent;\r
5 import java.awt.event.ActionListener;\r
6 import java.awt.event.FocusEvent;\r
7 import java.awt.event.FocusListener;\r
8 import java.beans.PropertyChangeEvent;\r
9 import java.beans.PropertyChangeListener;\r
10 import java.beans.PropertyVetoException;\r
11 import java.io.IOException;\r
12 \r
13 import javax.measure.quantity.Pressure;\r
14 import javax.measure.quantity.Velocity;\r
15 import javax.measure.unit.SI;\r
16 import javax.swing.BoxLayout;\r
17 import javax.swing.JButton;\r
18 import javax.swing.JFrame;\r
19 import javax.swing.JPanel;\r
20 import javax.swing.JProgressBar;\r
21 import javax.swing.JSplitPane;\r
22 import javax.swing.JTabbedPane;\r
23 import javax.swing.JTextField;\r
24 import javax.swing.SwingUtilities;\r
25 import javax.swing.UIManager;\r
26 import javax.swing.WindowConstants;\r
27 \r
28 import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;\r
29 import org.fife.ui.rsyntaxtextarea.SyntaxConstants;\r
30 import org.jscience.physics.amount.Amount;\r
31 \r
32 import com.billkuker.rocketry.motorsim.Burn;\r
33 import com.billkuker.rocketry.motorsim.Chamber;\r
34 import com.billkuker.rocketry.motorsim.ChangeListening;\r
35 import com.billkuker.rocketry.motorsim.ConvergentDivergentNozzle;\r
36 import com.billkuker.rocketry.motorsim.CylindricalChamber;\r
37 import com.billkuker.rocketry.motorsim.Fuel;\r
38 import com.billkuker.rocketry.motorsim.Grain;\r
39 import com.billkuker.rocketry.motorsim.Motor;\r
40 import com.billkuker.rocketry.motorsim.Nozzle;\r
41 import com.billkuker.rocketry.motorsim.fuel.EditableFuel;\r
42 import com.billkuker.rocketry.motorsim.fuel.KNDX;\r
43 import com.billkuker.rocketry.motorsim.fuel.KNER;\r
44 import com.billkuker.rocketry.motorsim.fuel.KNSB;\r
45 import com.billkuker.rocketry.motorsim.fuel.KNSU;\r
46 import com.billkuker.rocketry.motorsim.grain.CoredCylindricalGrain;\r
47 import com.billkuker.rocketry.motorsim.grain.Finocyl;\r
48 import com.billkuker.rocketry.motorsim.grain.Moonburner;\r
49 import com.billkuker.rocketry.motorsim.grain.MultiGrain;\r
50 import com.billkuker.rocketry.motorsim.grain.RodAndTubeGrain;\r
51 import com.billkuker.rocketry.motorsim.io.MotorIO;\r
52 import com.billkuker.rocketry.motorsim.visual.BurnPanel;\r
53 import com.billkuker.rocketry.motorsim.visual.Chart;\r
54 import com.billkuker.rocketry.motorsim.visual.Editor;\r
55 import com.billkuker.rocketry.motorsim.visual.GrainPanel;\r
56 import com.billkuker.rocketry.motorsim.visual.NozzlePanel;\r
57 \r
58 public class MotorEditor extends JTabbedPane implements PropertyChangeListener {\r
59         private static final long serialVersionUID = 1L;\r
60         RSyntaxTextArea text = new RSyntaxTextArea();\r
61         Motor motor;\r
62         GrainEditor grainEditor;\r
63         BurnTab bt;\r
64 \r
65         private static final int XML_TAB = 0;\r
66         private static final int CASING_TAB = 1;\r
67         private static final int GRAIN_TAB = 2;\r
68         private static final int FUEL_TAB = 3;\r
69         private static final int BURN_TAB = 4;\r
70 \r
71         @SuppressWarnings("unchecked")\r
72         private Class[] grainTypes = { CoredCylindricalGrain.class, Finocyl.class,\r
73                         Moonburner.class, RodAndTubeGrain.class };\r
74 \r
75         @SuppressWarnings("unchecked")\r
76         private Class[] fuelTypes = { KNSB.class, KNSU.class, KNER.class,\r
77                         KNDX.class, EditableFuel.class };\r
78 \r
79         private abstract class Chooser<T> extends JPanel {\r
80                 private static final long serialVersionUID = 1L;\r
81                 private Class<? extends T>[] types;\r
82 \r
83                 public Chooser(Class<? extends T>... ts) {\r
84                         types = ts;\r
85                         setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));\r
86                         for (final Class<? extends T> c : types) {\r
87                                 JButton b = new JButton(c.getSimpleName());\r
88                                 add(b);\r
89                                 b.addActionListener(new ActionListener() {\r
90                                         public void actionPerformed(ActionEvent e) {\r
91                                                 try {\r
92                                                         choiceMade(c.newInstance());\r
93                                                 } catch (InstantiationException e1) {\r
94                                                         e1.printStackTrace();\r
95                                                 } catch (IllegalAccessException e1) {\r
96                                                         e1.printStackTrace();\r
97                                                 }\r
98                                         }\r
99                                 });\r
100                         }\r
101                 }\r
102 \r
103                 protected abstract void choiceMade(T o);\r
104         }\r
105 \r
106         private class BurnTab extends JPanel {\r
107                 private static final long serialVersionUID = 1L;\r
108                 public BurnTab() {\r
109                         setLayout(new BorderLayout());\r
110                         setName("Burn");\r
111                         reBurn();\r
112                 }\r
113 \r
114                 public void reBurn() {\r
115                         removeAll();\r
116                         new Thread() {\r
117                                 public void run() {\r
118                                         final JProgressBar bar = new JProgressBar(0,100);\r
119                                         add(bar);\r
120                                         final Burn b = new Burn(motor, new Burn.BurnProgressListener(){\r
121                                                 @Override\r
122                                                 public void setProgress(float f){\r
123                                                         bar.setValue((int)(f*100));\r
124                                                 }\r
125                                         });\r
126                                         final BurnPanel bp = new BurnPanel(b);\r
127                                         SwingUtilities.invokeLater(new Thread() {\r
128                                                 public void run() {\r
129                                                         remove(bar);\r
130                                                         add(bp, BorderLayout.CENTER);\r
131                                                         \r
132                                                         revalidate();\r
133                                                 }\r
134                                         });\r
135                                 }\r
136                         }.start();\r
137                 }\r
138         }\r
139 \r
140         private class GrainEditor extends JSplitPane {\r
141                 private static final long serialVersionUID = 1L;\r
142 \r
143                 public GrainEditor(final Grain g) {\r
144                         super(JSplitPane.HORIZONTAL_SPLIT);\r
145                         setName("Grain");\r
146                         setRightComponent(new GrainPanel(g));\r
147                         if (g instanceof Grain.Composite) {\r
148                                 final JPanel p = new JPanel();\r
149                                 p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));\r
150                                 p.add(new Editor(g));\r
151                                 for (Grain gg : ((Grain.Composite) g).getGrains()) {\r
152                                         final int grainEditorIndex = p.getComponentCount() + 1;\r
153                                         p.add(new Chooser<Grain>(grainTypes) {\r
154                                                 private static final long serialVersionUID = 1L;\r
155 \r
156                                                 @Override\r
157                                                 protected void choiceMade(Grain ng) {\r
158                                                         if (g instanceof MultiGrain) {\r
159                                                                 ((MultiGrain) g).setGrain(ng);\r
160                                                                 p.remove(grainEditorIndex);\r
161                                                                 p.add(new Editor(ng), grainEditorIndex);\r
162                                                                 p.remove(0);\r
163                                                                 p.add(new Editor(g), 0);\r
164                                                                 // System.out.println("Chose new grain");\r
165                                                         }\r
166                                                 }\r
167                                         });\r
168                                         p.add(new Editor(gg));\r
169                                         if (gg instanceof ChangeListening.Subject) {\r
170                                                 ((ChangeListening.Subject) gg)\r
171                                                                 .addPropertyChangeListener(MotorEditor.this);\r
172                                         }\r
173                                 }\r
174                                 setLeftComponent(p);\r
175                         } else {\r
176                                 setLeftComponent(new Editor(g));\r
177                         }\r
178                         // setDividerLocation(.25);\r
179                         // setResizeWeight(.25);\r
180                         if (g instanceof ChangeListening.Subject) {\r
181                                 ((ChangeListening.Subject) g).addPropertyChangeListener(MotorEditor.this);\r
182                         }\r
183                 }\r
184         }\r
185 \r
186         private class FuelEditor extends JSplitPane {\r
187                 private static final long serialVersionUID = 1L;\r
188 \r
189                 public FuelEditor(Fuel f) {\r
190                         super(JSplitPane.HORIZONTAL_SPLIT);\r
191                         setName("Fuel");\r
192                         Chart<Pressure, Velocity> burnRate;\r
193                         try {\r
194                                 burnRate = new Chart<Pressure, Velocity>(SI.MEGA(SI.PASCAL),\r
195                                                 SI.METERS_PER_SECOND, f, "burnRate");\r
196                         } catch (NoSuchMethodException e) {\r
197                                 throw new Error(e);\r
198                         }\r
199                         burnRate.setDomain(burnRate.new IntervalDomain(Amount.valueOf(0, SI\r
200                                         .MEGA(SI.PASCAL)), Amount.valueOf(11, SI.MEGA(SI.PASCAL)),\r
201                                         20));\r
202 \r
203                         final JPanel p = new JPanel();\r
204                         p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));\r
205 \r
206                         p.add(new Chooser<Fuel>(fuelTypes) {\r
207                                 private static final long serialVersionUID = 1L;\r
208                                 @Override\r
209                                 protected void choiceMade(Fuel o) {\r
210                                         motor.setFuel(o);\r
211                                         removeTabAt(FUEL_TAB);\r
212                                         MotorEditor.this.add(new FuelEditor(motor.getFuel()),\r
213                                                         FUEL_TAB);\r
214                                         setSelectedIndex(FUEL_TAB);\r
215                                 }\r
216                         });\r
217                         p.add(new Editor(f));\r
218                         try {\r
219                                 p.add(new Editor(f.getCombustionProduct()));\r
220                         } catch (Exception e) {\r
221 \r
222                         }\r
223 \r
224                         setLeftComponent(p);\r
225                         setRightComponent(burnRate);\r
226                         // setDividerLocation(.25);\r
227                         // setResizeWeight(.25);\r
228                         if (f instanceof ChangeListening.Subject) {\r
229                                 ((ChangeListening.Subject) f).addPropertyChangeListener(MotorEditor.this);\r
230                         }\r
231                 }\r
232         }\r
233 \r
234         private class CaseEditor extends JSplitPane {\r
235                 private static final long serialVersionUID = 1L;\r
236 \r
237                 public CaseEditor(Nozzle n, Chamber c) {\r
238                         super(JSplitPane.HORIZONTAL_SPLIT);\r
239                         setName("Casing");\r
240                         JPanel parts = new JPanel();\r
241                         parts.setLayout(new BoxLayout(parts, BoxLayout.Y_AXIS));\r
242                         setLeftComponent(parts);\r
243                         setRightComponent(new NozzlePanel(n));\r
244 \r
245                         parts.add(new JTextField(motor.getName()){\r
246                                 private static final long serialVersionUID = 1L;\r
247                                 {\r
248                                         final JTextField t = this;\r
249                                         addFocusListener(new FocusListener() {\r
250                                                 \r
251                                                 @Override\r
252                                                 public void focusLost(FocusEvent e) {\r
253                                                         String n = t.getText();\r
254                                                         if ( !"".equals(n) && !n.equals(motor.getName()) ){\r
255                                                                 System.out.println("Name Changed");\r
256                                                                 motor.setName(n);\r
257                                                         } else {\r
258                                                                 t.setText(motor.getName());\r
259                                                         }\r
260                                                 }\r
261                                                 \r
262                                                 @Override\r
263                                                 public void focusGained(FocusEvent e) {\r
264                                                 \r
265                                                 }\r
266                                         });\r
267                                         \r
268                                 }\r
269                         });\r
270                         \r
271                         parts.add(new Editor(c));\r
272                         parts.add(new Editor(n));\r
273 \r
274                         if (n instanceof ChangeListening.Subject) {\r
275                                 ((ChangeListening.Subject) n).addPropertyChangeListener(MotorEditor.this);\r
276                         }\r
277                         if (c instanceof ChangeListening.Subject) {\r
278                                 ((ChangeListening.Subject) c).addPropertyChangeListener(MotorEditor.this);\r
279                         }\r
280                 }\r
281         }\r
282 \r
283         {\r
284                 text.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_XML);\r
285 \r
286         }\r
287 \r
288         public MotorEditor(Motor m) {\r
289                 super(JTabbedPane.BOTTOM);\r
290                 text.setName("XML");\r
291                 text.setEditable(false);\r
292                 add(text, XML_TAB);\r
293                 setMotor(m, true);\r
294         }\r
295         \r
296         public Motor getMotor(){\r
297                 return motor;\r
298         }\r
299 \r
300         private void reText() {\r
301                 try {\r
302                         text.setText(MotorIO.writeMotor(motor));\r
303                 } catch (IOException e) {\r
304                         throw new Error(e);\r
305                 }\r
306         }\r
307 \r
308         private void setMotor(Motor m, boolean retext) {\r
309                 if ( motor != null )\r
310                         motor.removePropertyChangeListener(this);\r
311                 motor = m;\r
312                 motor.addPropertyChangeListener(this);\r
313                 if (retext)\r
314                         reText();\r
315                 if (grainEditor != null)\r
316                         remove(grainEditor);\r
317                 while (getTabCount() > 1)\r
318                         removeTabAt(1);\r
319                 add(new CaseEditor(motor.getNozzle(), motor.getChamber()), CASING_TAB);\r
320                 add(new GrainEditor(motor.getGrain()), GRAIN_TAB);\r
321                 add(new FuelEditor(motor.getFuel()), FUEL_TAB);\r
322                 add(bt = new BurnTab(), BURN_TAB);\r
323         }\r
324 \r
325         @Deprecated\r
326         public static Motor defaultMotor() {\r
327                 Motor m = new Motor();\r
328                 m.setName("Example Motor");\r
329                 m.setFuel(new KNSU());\r
330 \r
331                 CylindricalChamber c = new CylindricalChamber();\r
332                 c.setLength(Amount.valueOf(200, SI.MILLIMETER));\r
333                 c.setID(Amount.valueOf(25, SI.MILLIMETER));\r
334                 m.setChamber(c);\r
335 \r
336                 CoredCylindricalGrain g = new CoredCylindricalGrain();\r
337                 try {\r
338                         g.setLength(Amount.valueOf(70, SI.MILLIMETER));\r
339                         g.setOD(Amount.valueOf(23.5, SI.MILLIMETER));\r
340                         g.setID(Amount.valueOf(7.9375, SI.MILLIMETER));\r
341                 } catch (PropertyVetoException v) {\r
342                         throw new Error(v);\r
343                 }\r
344 \r
345                 m.setGrain(new MultiGrain(g, 2));\r
346 \r
347                 ConvergentDivergentNozzle n = new ConvergentDivergentNozzle();\r
348                 n.setThroatDiameter(Amount.valueOf(7.962, SI.MILLIMETER));\r
349                 n.setExitDiameter(Amount.valueOf(13.79, SI.MILLIMETER));\r
350                 n.setEfficiency(.85);\r
351                 m.setNozzle(n);\r
352 \r
353                 return m;\r
354         }\r
355 \r
356         public void focusOnObject(Object o) {\r
357                 if (o instanceof Grain)\r
358                         setSelectedIndex(GRAIN_TAB);\r
359                 if (o instanceof Chamber || o instanceof Nozzle)\r
360                         setSelectedIndex(CASING_TAB);\r
361                 if (o instanceof Fuel || o instanceof Fuel.CombustionProduct)\r
362                         setSelectedIndex(FUEL_TAB);\r
363         }\r
364 \r
365         @Deprecated\r
366         public void showAsWindow() {\r
367                 JFrame f = new JFrame();\r
368                 f.setSize(1024, 768);\r
369                 f.setContentPane(this);\r
370                 f.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);\r
371                 f.setVisible(true);\r
372         }\r
373 \r
374         public static void main(String args[]) throws Exception {\r
375                 try {\r
376                         UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());\r
377                 } catch (Exception e1) {\r
378                         e1.printStackTrace();\r
379                 }\r
380                 new MotorEditor(defaultMotor()).showAsWindow();\r
381         }\r
382 \r
383         public void propertyChange(PropertyChangeEvent evt) {\r
384                 reText();\r
385                 //Dont re-burn for a name change!\r
386                 if ( !evt.getPropertyName().equals("Name") )\r
387                         bt.reBurn();\r
388         }\r
389 \r
390 }\r