07b94a1cf2c145282af60b5de2d56c2b413950b2
[sw/motorsim] / src / com / billkuker / rocketry / motorsim / visual / workbench / SRFuelEditor.java
1 package com.billkuker.rocketry.motorsim.visual.workbench;
2
3 import java.awt.BorderLayout;
4 import java.awt.Dimension;
5 import java.awt.FlowLayout;
6 import java.awt.event.ActionEvent;
7 import java.awt.event.ActionListener;
8 import java.awt.event.FocusEvent;
9 import java.awt.event.FocusListener;
10 import java.awt.event.TextListener;
11 import java.text.DecimalFormat;
12 import java.text.NumberFormat;
13 import java.util.Collections;
14 import java.util.Vector;
15
16 import javax.measure.quantity.Pressure;
17 import javax.measure.quantity.Velocity;
18 import javax.measure.quantity.VolumetricDensity;
19 import javax.measure.unit.SI;
20 import javax.swing.ButtonGroup;
21 import javax.swing.JButton;
22 import javax.swing.JFrame;
23 import javax.swing.JLabel;
24 import javax.swing.JPanel;
25 import javax.swing.JRadioButton;
26 import javax.swing.JScrollPane;
27 import javax.swing.JSplitPane;
28 import javax.swing.JTable;
29 import javax.swing.JTextField;
30 import javax.swing.SwingUtilities;
31 import javax.swing.event.ChangeEvent;
32 import javax.swing.event.ChangeListener;
33 import javax.swing.event.DocumentEvent;
34 import javax.swing.event.DocumentListener;
35 import javax.swing.table.AbstractTableModel;
36 import javax.swing.table.TableModel;
37
38 import org.jscience.physics.amount.Amount;
39
40 import com.billkuker.rocketry.motorsim.Fuel;
41 import com.billkuker.rocketry.motorsim.RocketScience;
42 import com.billkuker.rocketry.motorsim.RocketScience.UnitPreference;
43 import com.billkuker.rocketry.motorsim.fuel.PiecewiseSaintRobertFuel;
44 import com.billkuker.rocketry.motorsim.fuel.SaintRobertFuel;
45 import com.billkuker.rocketry.motorsim.fuel.EditableFuel.EditableCombustionProduct;
46 import com.billkuker.rocketry.motorsim.fuel.SaintRobertFuel.Type;
47 import com.billkuker.rocketry.motorsim.visual.Chart;
48 import com.billkuker.rocketry.motorsim.visual.Editor;
49 import com.billkuker.rocketry.motorsim.visual.Chart.IntervalDomain;
50
51 public class SRFuelEditor extends JSplitPane {
52         private static final NumberFormat nf = new DecimalFormat("##########.###");
53
54         Chart<Pressure, Velocity> burnRate;
55
56         private class Entry implements Comparable<Entry> {
57                 Amount<Pressure> p = Amount.valueOf(0, RocketScience.UnitPreference.preference.getPreferredUnit(RocketScience.PSI));
58                 double a;
59                 double n;
60
61                 @Override
62                 public int compareTo(Entry o) {
63                         return p.compareTo(o.p);
64                 }
65         }
66
67         public class EditablePSRFuel extends PiecewiseSaintRobertFuel {
68
69                 private Amount<VolumetricDensity> idealDensity = (Amount<VolumetricDensity>) Amount
70                                 .valueOf("1 g/mm^3");
71                 private double combustionEfficiency = 1;
72                 private double densityRatio = 1;
73                 private EditableCombustionProduct cp;
74                 private String name = "New Fuel";
75
76                 public EditablePSRFuel(Type t) {
77                         super(t);
78                         cp = new EditableCombustionProduct();
79                 }
80                 
81                 public void setType(Type t){
82                         super.setType(t);
83                 }
84
85                 public void add(Amount<Pressure> p, final double _a, final double _n) {
86                         super.add(p, _a, _n);
87
88                 }
89
90                 public Amount<VolumetricDensity> getIdealDensity() {
91                         return idealDensity;
92                 }
93
94                 public void setIdealDensity(Amount<VolumetricDensity> idealDensity) {
95                         this.idealDensity = idealDensity;
96                 }
97
98                 public double getCombustionEfficiency() {
99                         return combustionEfficiency;
100                 }
101
102                 public void setCombustionEfficiency(double combustionEfficiency) {
103                         this.combustionEfficiency = combustionEfficiency;
104                 }
105
106                 public double getDensityRatio() {
107                         return densityRatio;
108                 }
109
110                 public void setDensityRatio(double densityRatio) {
111                         this.densityRatio = densityRatio;
112                 }
113
114                 @Override
115                 public CombustionProduct getCombustionProduct() {
116                         return cp;
117                 }
118
119                 public String getName() {
120                         return name;
121                 }
122
123                 public void setName(String name) {
124                         this.name = name;
125                 }
126
127         }
128
129         EditablePSRFuel f = new EditablePSRFuel(SaintRobertFuel.Type.SI);
130
131         private class TM extends AbstractTableModel {
132
133                 @Override
134                 public int getColumnCount() {
135                         return 3;
136                 }
137
138                 @Override
139                 public int getRowCount() {
140                         return entries.size();
141                 }
142
143                 @Override
144                 public String getColumnName(int col) {
145                         switch (col) {
146                         case 0:
147                                 return "Pressure";
148                         case 1:
149                                 return "Coefficient (a)";
150                         case 2:
151                                 return "Exponent (n)";
152                         }
153                         return null;
154                 }
155
156                 @Override
157                 public Object getValueAt(int rowIndex, int columnIndex) {
158                         Entry e = entries.get(rowIndex);
159                         switch (columnIndex) {
160                         case 0:
161                                 //Format like 100 psi or 4.8 Mpa
162                                 return nf.format(e.p.doubleValue(e.p.getUnit())) + " " + e.p.getUnit();
163                         case 1:
164                                 return e.a;
165                         case 2:
166                                 return e.n;
167                         }
168                         return null;
169                 }
170
171                 public boolean isCellEditable(int row, int col) {
172                         return true;
173                 }
174
175                 public void setValueAt(Object value, int row, int col) {
176                         Entry e = entries.get(row);
177                         try {
178                                 switch (col) {
179                                 case 0:
180                                         try {
181                                                 e.p = (Amount<Pressure>) Amount.valueOf((String) value);
182                                         } catch ( Exception ee ){
183                                                 double d = Double.parseDouble((String)value);
184                                                 e.p = (Amount<Pressure>)Amount.valueOf(d, e.p.getUnit());
185                                         }
186                                         break;
187                                 case 1:
188                                         e.a = Double.valueOf((String) value);
189                                         break;
190                                 case 2:
191                                         e.n = Double.valueOf((String) value);
192                                 }
193                         } catch (Exception ex) {
194                                 ex.printStackTrace();
195                         }
196                         Collections.sort(entries);
197                         fireTableDataChanged();
198                         f = new EditablePSRFuel(SaintRobertFuel.Type.NONSI);
199                         for (Entry en : entries) {
200                                 f.add(en.p, en.a, en.n);
201                         }
202
203                         update();
204
205                 }
206
207                 @Override
208                 public void fireTableDataChanged() {
209                         super.fireTableDataChanged();
210                 }
211
212         };
213         
214         public Fuel getFuel(){
215                 return f;
216         }
217
218         private void update() {
219                 SwingUtilities.invokeLater(new Runnable() {
220
221                         @Override
222                         public void run() {
223                                 editTop.setTopComponent(new Editor(f));
224                                 editTop.setBottomComponent(new Editor(f.getCombustionProduct()));
225                                 if (burnRate != null)
226                                         SRFuelEditor.this.remove(burnRate);
227                                 try {
228                                         burnRate = new Chart<Pressure, Velocity>(
229                                                         SI.MEGA(SI.PASCAL), SI.MILLIMETER.divide(SI.SECOND)
230                                                                         .asType(Velocity.class), f, "burnRate");
231                                 } catch (NoSuchMethodException e) {
232                                         throw new Error(e);
233                                 }
234                                 burnRate.setDomain(burnRate.new IntervalDomain(Amount.valueOf(
235                                                 0, SI.MEGA(SI.PASCAL)), Amount.valueOf(11, SI
236                                                 .MEGA(SI.PASCAL)), 50));
237                                 SRFuelEditor.this.setRightComponent(burnRate);
238                                 SRFuelEditor.this.revalidate();
239                         }
240                 });
241         }
242
243         private Vector<Entry> entries = new Vector<Entry>();
244
245         JSplitPane editParent;
246         JSplitPane editTop;
247         JSplitPane editBottom;
248         JPanel controls;
249
250         public SRFuelEditor() {
251                 super(HORIZONTAL_SPLIT);
252                 setResizeWeight(0);
253                 setDividerLocation(.3);
254                 
255                 final TM tm = new TM();
256
257                 editParent = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
258                 editTop = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
259                 editBottom = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
260                 
261                 editParent.setTopComponent(editTop);
262                 editParent.setBottomComponent(editBottom);
263                 
264                 editTop.setTopComponent(new Editor(f));
265
266                 JTable table = new JTable(tm);
267                 JScrollPane scrollpane = new JScrollPane(table);
268                 scrollpane.setMinimumSize(new Dimension(200, 200));
269                 editBottom.setTopComponent(scrollpane);
270
271                 setLeftComponent(editParent);
272
273                 JButton add = new JButton("Add Data");
274                 add.addActionListener(new ActionListener() {
275                         @Override
276                         public void actionPerformed(ActionEvent e) {
277                                 entries.add(new Entry());
278                                 tm.fireTableDataChanged();
279                         }
280                 });
281                 controls = new JPanel();
282                 controls.setPreferredSize(new Dimension(200, 50));
283                 controls.setLayout(new FlowLayout());
284                         
285                 controls.add(add);
286
287                 
288                 final JRadioButton si, nonsi;
289                 ButtonGroup type = new ButtonGroup();
290                 JPanel radio = new JPanel();
291                 radio.add(si = new JRadioButton("SI"));
292                 radio.add(nonsi = new JRadioButton("NonSI"));
293                 controls.add(radio);
294                 type.add(si);
295                 type.add(nonsi);
296
297                 si.setSelected(true);
298                 
299                 si.addChangeListener(new ChangeListener(){
300                         @Override
301                         public void stateChanged(ChangeEvent e) {
302                                 if ( si.isSelected() ){
303                                         System.err.println("SI");
304                                         f.setType(Type.SI);
305                                         RocketScience.UnitPreference.preference = UnitPreference.SI;
306                                 } else {
307                                         System.err.println("NONSI");
308                                         f.setType(Type.NONSI);
309                                         RocketScience.UnitPreference.preference = UnitPreference.NONSI;
310                                 }
311                                 update();
312                         }});
313                 
314                 editBottom.setBottomComponent(controls);
315                 
316                 
317                 editParent.setDividerLocation(.5);
318                 editTop.setDividerLocation(.5);
319                 editBottom.setDividerLocation(.8);
320                 
321                 editParent.resetToPreferredSizes();
322                 revalidate();
323
324                 update();
325         }
326
327         public static void main(String args[]) {
328                 SRFuelEditor ed;
329                 JFrame f = new JFrame();
330                 f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
331                 f.setContentPane(ed = new SRFuelEditor());
332                 f.setSize(800, 600);
333                 f.setVisible(true);
334
335         }
336
337 }