1 package com.billkuker.rocketry.motorsim.visual.workbench;
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;
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;
38 import org.jscience.physics.amount.Amount;
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;
51 public class SRFuelEditor extends JSplitPane {
52 private static final NumberFormat nf = new DecimalFormat("##########.###");
54 Chart<Pressure, Velocity> burnRate;
56 private class Entry implements Comparable<Entry> {
57 Amount<Pressure> p = Amount.valueOf(0, RocketScience.UnitPreference.preference.getPreferredUnit(RocketScience.PSI));
62 public int compareTo(Entry o) {
63 return p.compareTo(o.p);
67 public class EditablePSRFuel extends PiecewiseSaintRobertFuel {
69 private Amount<VolumetricDensity> idealDensity = (Amount<VolumetricDensity>) Amount
71 private double combustionEfficiency = 1;
72 private double densityRatio = 1;
73 private EditableCombustionProduct cp;
74 private String name = "New Fuel";
76 public EditablePSRFuel(Type t) {
78 cp = new EditableCombustionProduct();
81 public void setType(Type t){
85 public void add(Amount<Pressure> p, final double _a, final double _n) {
90 public Amount<VolumetricDensity> getIdealDensity() {
94 public void setIdealDensity(Amount<VolumetricDensity> idealDensity) {
95 this.idealDensity = idealDensity;
98 public double getCombustionEfficiency() {
99 return combustionEfficiency;
102 public void setCombustionEfficiency(double combustionEfficiency) {
103 this.combustionEfficiency = combustionEfficiency;
106 public double getDensityRatio() {
110 public void setDensityRatio(double densityRatio) {
111 this.densityRatio = densityRatio;
115 public CombustionProduct getCombustionProduct() {
119 public String getName() {
123 public void setName(String name) {
129 EditablePSRFuel f = new EditablePSRFuel(SaintRobertFuel.Type.SI);
131 private class TM extends AbstractTableModel {
134 public int getColumnCount() {
139 public int getRowCount() {
140 return entries.size();
144 public String getColumnName(int col) {
149 return "Coefficient (a)";
151 return "Exponent (n)";
157 public Object getValueAt(int rowIndex, int columnIndex) {
158 Entry e = entries.get(rowIndex);
159 switch (columnIndex) {
161 //Format like 100 psi or 4.8 Mpa
162 return nf.format(e.p.doubleValue(e.p.getUnit())) + " " + e.p.getUnit();
171 public boolean isCellEditable(int row, int col) {
175 public void setValueAt(Object value, int row, int col) {
176 Entry e = entries.get(row);
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());
188 e.a = Double.valueOf((String) value);
191 e.n = Double.valueOf((String) value);
193 } catch (Exception ex) {
194 ex.printStackTrace();
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);
208 public void fireTableDataChanged() {
209 super.fireTableDataChanged();
214 public Fuel getFuel(){
218 private void update() {
219 SwingUtilities.invokeLater(new Runnable() {
223 editTop.setTopComponent(new Editor(f));
224 editTop.setBottomComponent(new Editor(f.getCombustionProduct()));
225 if (burnRate != null)
226 SRFuelEditor.this.remove(burnRate);
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) {
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();
243 private Vector<Entry> entries = new Vector<Entry>();
245 JSplitPane editParent;
247 JSplitPane editBottom;
250 public SRFuelEditor() {
251 super(HORIZONTAL_SPLIT);
253 setDividerLocation(.3);
255 final TM tm = new TM();
257 editParent = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
258 editTop = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
259 editBottom = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
261 editParent.setTopComponent(editTop);
262 editParent.setBottomComponent(editBottom);
264 editTop.setTopComponent(new Editor(f));
266 JTable table = new JTable(tm);
267 JScrollPane scrollpane = new JScrollPane(table);
268 scrollpane.setMinimumSize(new Dimension(200, 200));
269 editBottom.setTopComponent(scrollpane);
271 setLeftComponent(editParent);
273 JButton add = new JButton("Add Data");
274 add.addActionListener(new ActionListener() {
276 public void actionPerformed(ActionEvent e) {
277 entries.add(new Entry());
278 tm.fireTableDataChanged();
281 controls = new JPanel();
282 controls.setPreferredSize(new Dimension(200, 50));
283 controls.setLayout(new FlowLayout());
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"));
297 si.setSelected(true);
299 si.addChangeListener(new ChangeListener(){
301 public void stateChanged(ChangeEvent e) {
302 if ( si.isSelected() ){
303 System.err.println("SI");
305 RocketScience.UnitPreference.preference = UnitPreference.SI;
307 System.err.println("NONSI");
308 f.setType(Type.NONSI);
309 RocketScience.UnitPreference.preference = UnitPreference.NONSI;
314 editBottom.setBottomComponent(controls);
317 editParent.setDividerLocation(.5);
318 editTop.setDividerLocation(.5);
319 editBottom.setDividerLocation(.8);
321 editParent.resetToPreferredSizes();
327 public static void main(String args[]) {
329 JFrame f = new JFrame();
330 f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
331 f.setContentPane(ed = new SRFuelEditor());