1 package com.billkuker.rocketry.motorsim.visual.workbench;
3 import java.awt.Dimension;
4 import java.awt.FlowLayout;
5 import java.awt.event.ActionEvent;
6 import java.awt.event.ActionListener;
7 import java.beans.PropertyChangeEvent;
8 import java.text.DecimalFormat;
9 import java.text.NumberFormat;
10 import java.util.Collections;
11 import java.util.Vector;
13 import javax.measure.quantity.Pressure;
14 import javax.measure.quantity.Velocity;
15 import javax.measure.quantity.VolumetricDensity;
16 import javax.measure.unit.SI;
17 import javax.swing.ButtonGroup;
18 import javax.swing.JButton;
19 import javax.swing.JFrame;
20 import javax.swing.JPanel;
21 import javax.swing.JRadioButton;
22 import javax.swing.JScrollPane;
23 import javax.swing.JSplitPane;
24 import javax.swing.JTable;
25 import javax.swing.SwingUtilities;
26 import javax.swing.event.ChangeEvent;
27 import javax.swing.event.ChangeListener;
28 import javax.swing.table.AbstractTableModel;
30 import org.jscience.physics.amount.Amount;
32 import com.billkuker.rocketry.motorsim.Fuel;
33 import com.billkuker.rocketry.motorsim.RocketScience;
34 import com.billkuker.rocketry.motorsim.fuel.EditableFuel.EditableCombustionProduct;
35 import com.billkuker.rocketry.motorsim.fuel.PiecewiseSaintRobertFuel;
36 import com.billkuker.rocketry.motorsim.fuel.SaintRobertFuel;
37 import com.billkuker.rocketry.motorsim.fuel.SaintRobertFuel.Type;
38 import com.billkuker.rocketry.motorsim.visual.Chart;
39 import com.billkuker.rocketry.motorsim.visual.Editor;
41 public class SRFuelEditor extends JSplitPane {
42 private static final NumberFormat nf = new DecimalFormat("##########.###");
44 Chart<Pressure, Velocity> burnRate;
46 private class Entry implements Comparable<Entry> {
47 Amount<Pressure> p = Amount.valueOf(0, RocketScience.UnitPreference.getUnitPreference().getPreferredUnit(RocketScience.PSI));
52 public int compareTo(Entry o) {
53 return p.compareTo(o.p);
57 public static class EditablePSRFuel extends PiecewiseSaintRobertFuel {
59 private Amount<VolumetricDensity> idealDensity = (Amount<VolumetricDensity>) Amount
61 private double combustionEfficiency = 1;
62 private double densityRatio = 1;
63 private EditableCombustionProduct cp;
64 private String name = "New Fuel";
66 public EditablePSRFuel(Type t) {
68 cp = new EditableCombustionProduct();
75 public void setType(Type t){
79 public void add(Amount<Pressure> p, final double _a, final double _n) {
84 public Amount<VolumetricDensity> getIdealDensity() {
88 public void setIdealDensity(Amount<VolumetricDensity> idealDensity) {
89 this.idealDensity = idealDensity;
92 public double getCombustionEfficiency() {
93 return combustionEfficiency;
96 public void setCombustionEfficiency(double combustionEfficiency) {
97 this.combustionEfficiency = combustionEfficiency;
100 public double getDensityRatio() {
104 public void setDensityRatio(double densityRatio) {
105 this.densityRatio = densityRatio;
109 public CombustionProduct getCombustionProduct() {
113 public String getName() {
117 public void setName(String name) {
123 final EditablePSRFuel f = new EditablePSRFuel(SaintRobertFuel.Type.SI);
125 private class TM extends AbstractTableModel {
128 public int getColumnCount() {
133 public int getRowCount() {
134 return entries.size();
138 public String getColumnName(int col) {
143 return "Coefficient (a)";
145 return "Exponent (n)";
151 public Object getValueAt(int rowIndex, int columnIndex) {
152 Entry e = entries.get(rowIndex);
153 switch (columnIndex) {
155 //Format like 100 psi or 4.8 Mpa
156 return nf.format(e.p.doubleValue(e.p.getUnit())) + " " + e.p.getUnit();
165 public boolean isCellEditable(int row, int col) {
169 public void setValueAt(Object value, int row, int col) {
170 Entry e = entries.get(row);
175 e.p = (Amount<Pressure>) Amount.valueOf((String) value);
176 } catch ( Exception ee ){
177 double d = Double.parseDouble((String)value);
178 e.p = (Amount<Pressure>)Amount.valueOf(d, e.p.getUnit());
182 e.a = Double.valueOf((String) value);
185 e.n = Double.valueOf((String) value);
187 } catch (Exception ex) {
188 ex.printStackTrace();
190 Collections.sort(entries);
191 fireTableDataChanged();
192 //f = new EditablePSRFuel(SaintRobertFuel.Type.NONSI);
194 for (Entry en : entries) {
195 f.add(en.p, en.a, en.n);
197 f.firePropertyChange(new PropertyChangeEvent(f,"entries", null, null));
204 public void fireTableDataChanged() {
205 super.fireTableDataChanged();
210 public Fuel getFuel(){
214 private void update() {
215 SwingUtilities.invokeLater(new Runnable() {
219 editTop.setTopComponent(new Editor(f));
220 editTop.setBottomComponent(new Editor(f.getCombustionProduct()));
221 if (burnRate != null)
222 SRFuelEditor.this.remove(burnRate);
224 burnRate = new Chart<Pressure, Velocity>(
225 SI.MEGA(SI.PASCAL), SI.MILLIMETER.divide(SI.SECOND)
226 .asType(Velocity.class), f, "burnRate");
227 } catch (NoSuchMethodException e) {
230 burnRate.setDomain(burnRate.new IntervalDomain(Amount.valueOf(
231 0, SI.MEGA(SI.PASCAL)), Amount.valueOf(11, SI
232 .MEGA(SI.PASCAL)), 50));
233 SRFuelEditor.this.setRightComponent(burnRate);
234 SRFuelEditor.this.revalidate();
239 private Vector<Entry> entries = new Vector<Entry>();
241 JSplitPane editParent;
243 JSplitPane editBottom;
246 public SRFuelEditor() {
247 super(HORIZONTAL_SPLIT);
249 setDividerLocation(.3);
251 final TM tm = new TM();
253 editParent = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
254 editTop = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
255 editBottom = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
257 editParent.setTopComponent(editTop);
258 editParent.setBottomComponent(editBottom);
260 editTop.setTopComponent(new Editor(f));
262 JTable table = new JTable(tm);
263 JScrollPane scrollpane = new JScrollPane(table);
264 scrollpane.setMinimumSize(new Dimension(200, 200));
265 editBottom.setTopComponent(scrollpane);
267 setLeftComponent(editParent);
269 JButton add = new JButton("Add Data");
270 add.addActionListener(new ActionListener() {
272 public void actionPerformed(ActionEvent e) {
273 entries.add(new Entry());
274 tm.fireTableDataChanged();
277 controls = new JPanel();
278 controls.setPreferredSize(new Dimension(200, 50));
279 controls.setLayout(new FlowLayout());
284 final JRadioButton si, nonsi;
285 ButtonGroup type = new ButtonGroup();
286 JPanel radio = new JPanel();
287 radio.add(si = new JRadioButton("SI"));
288 radio.add(nonsi = new JRadioButton("NonSI"));
293 si.setSelected(true);
295 si.addChangeListener(new ChangeListener(){
297 public void stateChanged(ChangeEvent e) {
298 if ( si.isSelected() ){
299 System.err.println("SI");
302 System.err.println("NONSI");
303 f.setType(Type.NONSI);
308 editBottom.setBottomComponent(controls);
311 editParent.setDividerLocation(.5);
312 editTop.setDividerLocation(.5);
313 editBottom.setDividerLocation(.8);
315 editParent.resetToPreferredSizes();
321 public static void main(String args[]) {
323 JFrame f = new JFrame();
324 f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
325 f.setContentPane(ed = new SRFuelEditor());