Moved some workbench files
authorBill Kuker <bkuker@billkuker.com>
Tue, 14 Jul 2009 01:05:22 +0000 (01:05 +0000)
committerBill Kuker <bkuker@billkuker.com>
Tue, 14 Jul 2009 01:05:22 +0000 (01:05 +0000)
src/com/billkuker/rocketry/motorsim/visual/MotorEditor.java [deleted file]
src/com/billkuker/rocketry/motorsim/visual/MotorWorkbench.java [deleted file]
src/com/billkuker/rocketry/motorsim/visual/workbench/MotorEditor.java [new file with mode: 0644]
src/com/billkuker/rocketry/motorsim/visual/workbench/MotorWorkbench.java [new file with mode: 0644]

diff --git a/src/com/billkuker/rocketry/motorsim/visual/MotorEditor.java b/src/com/billkuker/rocketry/motorsim/visual/MotorEditor.java
deleted file mode 100644 (file)
index 5044bf5..0000000
+++ /dev/null
@@ -1,356 +0,0 @@
-package com.billkuker.rocketry.motorsim.visual;\r
-\r
-import java.awt.BorderLayout;\r
-import java.awt.event.ActionEvent;\r
-import java.awt.event.ActionListener;\r
-import java.beans.PropertyChangeEvent;\r
-import java.beans.PropertyChangeListener;\r
-import java.beans.PropertyVetoException;\r
-import java.io.IOException;\r
-\r
-import javax.measure.quantity.Pressure;\r
-import javax.measure.quantity.Velocity;\r
-import javax.measure.unit.SI;\r
-import javax.swing.BoxLayout;\r
-import javax.swing.JButton;\r
-import javax.swing.JFrame;\r
-import javax.swing.JPanel;\r
-import javax.swing.JSplitPane;\r
-import javax.swing.JTabbedPane;\r
-import javax.swing.SwingUtilities;\r
-import javax.swing.UIManager;\r
-import javax.swing.WindowConstants;\r
-import javax.swing.event.DocumentEvent;\r
-import javax.swing.event.DocumentListener;\r
-\r
-import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;\r
-import org.fife.ui.rsyntaxtextarea.SyntaxConstants;\r
-import org.jscience.physics.amount.Amount;\r
-\r
-import com.billkuker.rocketry.motorsim.Burn;\r
-import com.billkuker.rocketry.motorsim.Chamber;\r
-import com.billkuker.rocketry.motorsim.ConvergentDivergentNozzle;\r
-import com.billkuker.rocketry.motorsim.CylindricalChamber;\r
-import com.billkuker.rocketry.motorsim.Fuel;\r
-import com.billkuker.rocketry.motorsim.Grain;\r
-import com.billkuker.rocketry.motorsim.Motor;\r
-import com.billkuker.rocketry.motorsim.MotorPart;\r
-import com.billkuker.rocketry.motorsim.Nozzle;\r
-import com.billkuker.rocketry.motorsim.fuel.EditableFuel;\r
-import com.billkuker.rocketry.motorsim.fuel.KNDX;\r
-import com.billkuker.rocketry.motorsim.fuel.KNER;\r
-import com.billkuker.rocketry.motorsim.fuel.KNSB;\r
-import com.billkuker.rocketry.motorsim.fuel.KNSU;\r
-import com.billkuker.rocketry.motorsim.grain.CoredCylindricalGrain;\r
-import com.billkuker.rocketry.motorsim.grain.Finocyl;\r
-import com.billkuker.rocketry.motorsim.grain.Moonburner;\r
-import com.billkuker.rocketry.motorsim.grain.MultiGrain;\r
-import com.billkuker.rocketry.motorsim.grain.RodAndTubeGrain;\r
-import com.billkuker.rocketry.motorsim.io.MotorIO;\r
-\r
-public class MotorEditor extends JTabbedPane implements PropertyChangeListener,\r
-               DocumentListener {\r
-       private static final long serialVersionUID = 1L;\r
-       RSyntaxTextArea text = new RSyntaxTextArea();\r
-       Motor motor;\r
-       GrainEditor grainEditor;\r
-       BurnTab bt;\r
-\r
-       private static final int XML_TAB = 0;\r
-       private static final int CASING_TAB = 1;\r
-       private static final int GRAIN_TAB = 2;\r
-       private static final int FUEL_TAB = 3;\r
-       private static final int BURN_TAB = 4;\r
-\r
-       private Class[] grainTypes = { CoredCylindricalGrain.class, Finocyl.class,\r
-                       Moonburner.class, RodAndTubeGrain.class };\r
-\r
-       private Class[] fuelTypes = { KNSB.class, KNSU.class, KNER.class,\r
-                       KNDX.class, EditableFuel.class };\r
-\r
-       private abstract class Chooser<T> extends JPanel {\r
-               private static final long serialVersionUID = 1L;\r
-               private Class<? extends T>[] types;\r
-\r
-               public Chooser(Class<? extends T>... ts) {\r
-                       types = ts;\r
-                       setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));\r
-                       for (final Class<? extends T> c : types) {\r
-                               JButton b = new JButton(c.getSimpleName());\r
-                               add(b);\r
-                               b.addActionListener(new ActionListener() {\r
-                                       public void actionPerformed(ActionEvent e) {\r
-                                               try {\r
-                                                       choiceMade(c.newInstance());\r
-                                               } catch (InstantiationException e1) {\r
-                                                       e1.printStackTrace();\r
-                                               } catch (IllegalAccessException e1) {\r
-                                                       e1.printStackTrace();\r
-                                               }\r
-                                       }\r
-                               });\r
-                       }\r
-               }\r
-\r
-               protected abstract void choiceMade(T o);\r
-       }\r
-\r
-       private class BurnTab extends JPanel {\r
-               public BurnTab() {\r
-                       setLayout(new BorderLayout());\r
-                       setName("Burn");\r
-                       reBurn();\r
-               }\r
-\r
-               public void reBurn() {\r
-                       removeAll();\r
-                       new Thread() {\r
-                               public void run() {\r
-                                       final Burn b = new Burn(motor);\r
-                                       final BurnPanel bp = new BurnPanel(b);\r
-                                       SwingUtilities.invokeLater(new Thread() {\r
-                                               public void run() {\r
-                                                       add(bp, BorderLayout.CENTER);\r
-                                               }\r
-                                       });\r
-                               }\r
-                       }.start();\r
-               }\r
-       }\r
-\r
-       private class GrainEditor extends JSplitPane {\r
-               private static final long serialVersionUID = 1L;\r
-\r
-               public GrainEditor(final Grain g) {\r
-                       super(JSplitPane.HORIZONTAL_SPLIT);\r
-                       setName("Grain");\r
-                       setRightComponent(new GrainPanel(g));\r
-                       if (g instanceof Grain.Composite) {\r
-                               final JPanel p = new JPanel();\r
-                               p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));\r
-                               p.add(new Editor(g));\r
-                               for (Grain gg : ((Grain.Composite) g).getGrains()) {\r
-                                       final int grainEditorIndex = p.getComponentCount() + 1;\r
-                                       p.add(new Chooser<Grain>(grainTypes) {\r
-                                               private static final long serialVersionUID = 1L;\r
-\r
-                                               @Override\r
-                                               protected void choiceMade(Grain ng) {\r
-                                                       if (g instanceof MultiGrain) {\r
-                                                               ((MultiGrain) g).setGrain(ng);\r
-                                                               p.remove(grainEditorIndex);\r
-                                                               p.add(new Editor(ng), grainEditorIndex);\r
-                                                               p.remove(0);\r
-                                                               p.add(new Editor(g), 0);\r
-                                                               // System.out.println("Chose new grain");\r
-                                                       }\r
-                                               }\r
-                                       });\r
-                                       p.add(new Editor(gg));\r
-                                       if (gg instanceof MotorPart) {\r
-                                               ((MotorPart) gg)\r
-                                                               .addPropertyChangeListener(MotorEditor.this);\r
-                                       }\r
-                               }\r
-                               setLeftComponent(p);\r
-                       } else {\r
-                               setLeftComponent(new Editor(g));\r
-                       }\r
-                       // setDividerLocation(.25);\r
-                       // setResizeWeight(.25);\r
-                       if (g instanceof MotorPart) {\r
-                               ((MotorPart) g).addPropertyChangeListener(MotorEditor.this);\r
-                       }\r
-               }\r
-       }\r
-\r
-       private class FuelEditor extends JSplitPane {\r
-               private static final long serialVersionUID = 1L;\r
-\r
-               public FuelEditor(Fuel f) {\r
-                       super(JSplitPane.HORIZONTAL_SPLIT);\r
-                       setName("Fuel");\r
-                       Chart<Pressure, Velocity> burnRate;\r
-                       try {\r
-                               burnRate = new Chart<Pressure, Velocity>(SI.MEGA(SI.PASCAL),\r
-                                               SI.METERS_PER_SECOND, f, "burnRate");\r
-                       } catch (NoSuchMethodException e) {\r
-                               throw new Error(e);\r
-                       }\r
-                       burnRate.setDomain(burnRate.new IntervalDomain(Amount.valueOf(0, SI\r
-                                       .MEGA(SI.PASCAL)), Amount.valueOf(11, SI.MEGA(SI.PASCAL)),\r
-                                       20));\r
-\r
-                       final JPanel p = new JPanel();\r
-                       p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));\r
-\r
-                       p.add(new Chooser<Fuel>(fuelTypes) {\r
-                               @Override\r
-                               protected void choiceMade(Fuel o) {\r
-                                       motor.setFuel(o);\r
-                                       removeTabAt(FUEL_TAB);\r
-                                       MotorEditor.this.add(new FuelEditor(motor.getFuel()),\r
-                                                       FUEL_TAB);\r
-                                       setSelectedIndex(FUEL_TAB);\r
-                               }\r
-                       });\r
-                       p.add(new Editor(f));\r
-                       try {\r
-                               p.add(new Editor(f.getCombustionProduct()));\r
-                       } catch (Exception e) {\r
-\r
-                       }\r
-\r
-                       setLeftComponent(p);\r
-                       setRightComponent(burnRate);\r
-                       // setDividerLocation(.25);\r
-                       // setResizeWeight(.25);\r
-                       if (f instanceof MotorPart) {\r
-                               ((MotorPart) f).addPropertyChangeListener(MotorEditor.this);\r
-                       }\r
-               }\r
-       }\r
-\r
-       private class CaseEditor extends JSplitPane {\r
-               private static final long serialVersionUID = 1L;\r
-\r
-               public CaseEditor(Nozzle n, Chamber c) {\r
-                       super(JSplitPane.HORIZONTAL_SPLIT);\r
-                       setName("Casing");\r
-                       JPanel parts = new JPanel();\r
-                       parts.setLayout(new BoxLayout(parts, BoxLayout.Y_AXIS));\r
-                       setLeftComponent(parts);\r
-                       setRightComponent(new NozzlePanel(n));\r
-\r
-                       parts.add(new Editor(c));\r
-                       parts.add(new Editor(n));\r
-\r
-                       if (n instanceof MotorPart) {\r
-                               ((MotorPart) n).addPropertyChangeListener(MotorEditor.this);\r
-                       }\r
-                       if (c instanceof MotorPart) {\r
-                               ((MotorPart) c).addPropertyChangeListener(MotorEditor.this);\r
-                       }\r
-               }\r
-       }\r
-\r
-       {\r
-               text.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_XML);\r
-\r
-       }\r
-\r
-       public MotorEditor(Motor m) {\r
-               super(JTabbedPane.BOTTOM);\r
-               text.getDocument().addDocumentListener(this);\r
-               text.setName("XML");\r
-               add(text, XML_TAB);\r
-               setMotor(m, true);\r
-       }\r
-\r
-       private void reText() {\r
-               try {\r
-                       text.setText(MotorIO.writeMotor(motor));\r
-               } catch (IOException e) {\r
-                       throw new Error(e);\r
-               }\r
-       }\r
-\r
-       private void setMotor(Motor m, boolean retext) {\r
-               motor = m;\r
-               if (retext)\r
-                       reText();\r
-               if (grainEditor != null)\r
-                       remove(grainEditor);\r
-               while (getTabCount() > 1)\r
-                       removeTabAt(1);\r
-               add(new CaseEditor(motor.getNozzle(), motor.getChamber()), CASING_TAB);\r
-               add(new GrainEditor(motor.getGrain()), GRAIN_TAB);\r
-               add(new FuelEditor(motor.getFuel()), FUEL_TAB);\r
-               add(bt = new BurnTab(), BURN_TAB);\r
-       }\r
-\r
-       @Deprecated\r
-       public static Motor defaultMotor() {\r
-               Motor m = new Motor();\r
-               m.setName("Example Motor");\r
-               m.setFuel(new KNSU());\r
-\r
-               CylindricalChamber c = new CylindricalChamber();\r
-               c.setLength(Amount.valueOf(200, SI.MILLIMETER));\r
-               c.setID(Amount.valueOf(25, SI.MILLIMETER));\r
-               m.setChamber(c);\r
-\r
-               CoredCylindricalGrain g = new CoredCylindricalGrain();\r
-               try {\r
-                       g.setLength(Amount.valueOf(70, SI.MILLIMETER));\r
-                       g.setOD(Amount.valueOf(23.5, SI.MILLIMETER));\r
-                       g.setID(Amount.valueOf(7.9375, SI.MILLIMETER));\r
-               } catch (PropertyVetoException v) {\r
-                       throw new Error(v);\r
-               }\r
-\r
-               m.setGrain(new MultiGrain(g, 2));\r
-\r
-               ConvergentDivergentNozzle n = new ConvergentDivergentNozzle();\r
-               n.setThroatDiameter(Amount.valueOf(7.962, SI.MILLIMETER));\r
-               n.setExitDiameter(Amount.valueOf(13.79, SI.MILLIMETER));\r
-               n.setEfficiency(.85);\r
-               m.setNozzle(n);\r
-\r
-               return m;\r
-       }\r
-\r
-       public void focusOnObject(Object o) {\r
-               if (o instanceof Grain)\r
-                       setSelectedIndex(GRAIN_TAB);\r
-               if (o instanceof Chamber || o instanceof Nozzle)\r
-                       setSelectedIndex(CASING_TAB);\r
-               if (o instanceof Fuel || o instanceof Fuel.CombustionProduct)\r
-                       setSelectedIndex(FUEL_TAB);\r
-       }\r
-\r
-       @Deprecated\r
-       public void showAsWindow() {\r
-               JFrame f = new JFrame();\r
-               f.setSize(1024, 768);\r
-               f.setContentPane(this);\r
-               f.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);\r
-               f.setVisible(true);\r
-       }\r
-\r
-       public static void main(String args[]) throws Exception {\r
-               try {\r
-                       UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());\r
-               } catch (Exception e1) {\r
-                       e1.printStackTrace();\r
-               }\r
-               new MotorEditor(defaultMotor()).showAsWindow();\r
-       }\r
-\r
-       public void propertyChange(PropertyChangeEvent evt) {\r
-               reText();\r
-               bt.reBurn();\r
-       }\r
-\r
-       public void changedUpdate(DocumentEvent e) {\r
-               try {\r
-                       final Motor m = MotorIO.readMotor(text.getText());\r
-                       SwingUtilities.invokeLater(new Runnable() {\r
-                               public void run() {\r
-                                       setMotor(m, false);\r
-                               }\r
-                       });\r
-                       System.out.println("Motor Updated");\r
-               } catch (Throwable e1) {\r
-                       // Leave blank, motor might be broken\r
-               }\r
-       }\r
-\r
-       public void insertUpdate(DocumentEvent e) {\r
-               // TODO Auto-generated method stub\r
-       }\r
-\r
-       public void removeUpdate(DocumentEvent e) {\r
-               // TODO Auto-generated method stub\r
-       }\r
-}\r
diff --git a/src/com/billkuker/rocketry/motorsim/visual/MotorWorkbench.java b/src/com/billkuker/rocketry/motorsim/visual/MotorWorkbench.java
deleted file mode 100644 (file)
index d497e2d..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-package com.billkuker.rocketry.motorsim.visual;\r
-\r
-import java.awt.BorderLayout;\r
-import java.awt.Dimension;\r
-import java.util.HashMap;\r
-\r
-import javax.swing.JButton;\r
-import javax.swing.JFrame;\r
-import javax.swing.JPanel;\r
-import javax.swing.JScrollPane;\r
-import javax.swing.JSplitPane;\r
-import javax.swing.JTabbedPane;\r
-import javax.swing.JToolBar;\r
-import javax.swing.JTree;\r
-import javax.swing.UIManager;\r
-import javax.swing.WindowConstants;\r
-import javax.swing.event.TreeSelectionEvent;\r
-import javax.swing.event.TreeSelectionListener;\r
-import javax.swing.tree.DefaultMutableTreeNode;\r
-import javax.swing.tree.TreePath;\r
-import javax.swing.tree.TreeSelectionModel;\r
-\r
-import com.billkuker.rocketry.motorsim.Motor;\r
-import com.billkuker.rocketry.motorsim.visual.workbench.WorkbenchTreeCellRenderer;\r
-import com.billkuker.rocketry.motorsim.visual.workbench.WorkbenchTreeModel;\r
-\r
-public class MotorWorkbench extends JFrame implements TreeSelectionListener {\r
-       private static final long serialVersionUID = 1L;\r
-       private JPanel top;\r
-       private JSplitPane split;\r
-       private JTree tree;\r
-       private JTabbedPane motors;\r
-       private JToolBar bar;\r
-       private WorkbenchTreeModel tm;\r
-\r
-       private HashMap<Motor, MotorEditor> m2e = new HashMap<Motor, MotorEditor>();\r
-\r
-       public MotorWorkbench() {\r
-               setSize(1024, 768);\r
-               top = new JPanel(new BorderLayout());\r
-               setContentPane(top);\r
-\r
-               bar = new JToolBar();\r
-               bar.add(new JButton("Burn"));\r
-               top.add(bar, BorderLayout.PAGE_START);\r
-\r
-               motors = new JTabbedPane();\r
-\r
-               tree = new JTree(tm = new WorkbenchTreeModel());\r
-               tree.setCellRenderer(new WorkbenchTreeCellRenderer());\r
-               tree.getSelectionModel().setSelectionMode(\r
-                               TreeSelectionModel.SINGLE_TREE_SELECTION);\r
-               tree.setPreferredSize(new Dimension(200, 100));\r
-\r
-               // Listen for when the selection changes.\r
-               tree.addTreeSelectionListener(this);\r
-\r
-               split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, new JScrollPane(\r
-                               tree), motors);\r
-               //split.setDividerLocation(.25);\r
-               //split.setResizeWeight(.25);\r
-               top.add(split, BorderLayout.CENTER);\r
-\r
-               setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);\r
-               setVisible(true);\r
-\r
-               Motor mot = MotorEditor.defaultMotor();\r
-               addMotor(mot);\r
-               //mot = MotorEditor.defaultMotor();\r
-               //addMotor(mot);\r
-       }\r
-\r
-       public void addMotor(Motor m) {\r
-               tm.addMotor(m);\r
-               MotorEditor e = new MotorEditor(m);\r
-               m2e.put(m, e);\r
-               motors.addTab("Motor", e);\r
-       }\r
-\r
-       public static void main(String args[]) throws Exception {\r
-               try {\r
-                       UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());\r
-               } catch (Exception e1) {\r
-                       e1.printStackTrace();\r
-               }\r
-               new MotorWorkbench().show();\r
-       }\r
-\r
-       @Override\r
-       public void valueChanged(TreeSelectionEvent e) {\r
-               Motor m = getMotor(e.getPath());\r
-\r
-               motors.setSelectedComponent(m2e.get(m));\r
-               \r
-               if ( e.getPath().getLastPathComponent() instanceof DefaultMutableTreeNode ){\r
-                       Object o = ((DefaultMutableTreeNode)e.getPath().getLastPathComponent()).getUserObject();\r
-                       m2e.get(m).focusOnObject(o);\r
-               }\r
-       }\r
-\r
-       private Motor getMotor(TreePath p) {\r
-               if (p.getLastPathComponent() instanceof WorkbenchTreeModel.MotorNode) {\r
-                       return ((WorkbenchTreeModel.MotorNode) p.getLastPathComponent())\r
-                                       .getUserObject();\r
-               } else if (p.getPath().length > 1)\r
-                       return getMotor(p.getParentPath());\r
-               return null;\r
-       }\r
-}\r
diff --git a/src/com/billkuker/rocketry/motorsim/visual/workbench/MotorEditor.java b/src/com/billkuker/rocketry/motorsim/visual/workbench/MotorEditor.java
new file mode 100644 (file)
index 0000000..126871b
--- /dev/null
@@ -0,0 +1,362 @@
+package com.billkuker.rocketry.motorsim.visual.workbench;\r
+\r
+import java.awt.BorderLayout;\r
+import java.awt.event.ActionEvent;\r
+import java.awt.event.ActionListener;\r
+import java.beans.PropertyChangeEvent;\r
+import java.beans.PropertyChangeListener;\r
+import java.beans.PropertyVetoException;\r
+import java.io.IOException;\r
+\r
+import javax.measure.quantity.Pressure;\r
+import javax.measure.quantity.Velocity;\r
+import javax.measure.unit.SI;\r
+import javax.swing.BoxLayout;\r
+import javax.swing.JButton;\r
+import javax.swing.JFrame;\r
+import javax.swing.JPanel;\r
+import javax.swing.JSplitPane;\r
+import javax.swing.JTabbedPane;\r
+import javax.swing.SwingUtilities;\r
+import javax.swing.UIManager;\r
+import javax.swing.WindowConstants;\r
+import javax.swing.event.DocumentEvent;\r
+import javax.swing.event.DocumentListener;\r
+\r
+import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;\r
+import org.fife.ui.rsyntaxtextarea.SyntaxConstants;\r
+import org.jscience.physics.amount.Amount;\r
+\r
+import com.billkuker.rocketry.motorsim.Burn;\r
+import com.billkuker.rocketry.motorsim.Chamber;\r
+import com.billkuker.rocketry.motorsim.ConvergentDivergentNozzle;\r
+import com.billkuker.rocketry.motorsim.CylindricalChamber;\r
+import com.billkuker.rocketry.motorsim.Fuel;\r
+import com.billkuker.rocketry.motorsim.Grain;\r
+import com.billkuker.rocketry.motorsim.Motor;\r
+import com.billkuker.rocketry.motorsim.MotorPart;\r
+import com.billkuker.rocketry.motorsim.Nozzle;\r
+import com.billkuker.rocketry.motorsim.fuel.EditableFuel;\r
+import com.billkuker.rocketry.motorsim.fuel.KNDX;\r
+import com.billkuker.rocketry.motorsim.fuel.KNER;\r
+import com.billkuker.rocketry.motorsim.fuel.KNSB;\r
+import com.billkuker.rocketry.motorsim.fuel.KNSU;\r
+import com.billkuker.rocketry.motorsim.grain.CoredCylindricalGrain;\r
+import com.billkuker.rocketry.motorsim.grain.Finocyl;\r
+import com.billkuker.rocketry.motorsim.grain.Moonburner;\r
+import com.billkuker.rocketry.motorsim.grain.MultiGrain;\r
+import com.billkuker.rocketry.motorsim.grain.RodAndTubeGrain;\r
+import com.billkuker.rocketry.motorsim.io.MotorIO;\r
+import com.billkuker.rocketry.motorsim.visual.BurnPanel;\r
+import com.billkuker.rocketry.motorsim.visual.Chart;\r
+import com.billkuker.rocketry.motorsim.visual.Editor;\r
+import com.billkuker.rocketry.motorsim.visual.GrainPanel;\r
+import com.billkuker.rocketry.motorsim.visual.NozzlePanel;\r
+import com.billkuker.rocketry.motorsim.visual.Chart.IntervalDomain;\r
+\r
+public class MotorEditor extends JTabbedPane implements PropertyChangeListener,\r
+               DocumentListener {\r
+       private static final long serialVersionUID = 1L;\r
+       RSyntaxTextArea text = new RSyntaxTextArea();\r
+       Motor motor;\r
+       GrainEditor grainEditor;\r
+       BurnTab bt;\r
+\r
+       private static final int XML_TAB = 0;\r
+       private static final int CASING_TAB = 1;\r
+       private static final int GRAIN_TAB = 2;\r
+       private static final int FUEL_TAB = 3;\r
+       private static final int BURN_TAB = 4;\r
+\r
+       private Class[] grainTypes = { CoredCylindricalGrain.class, Finocyl.class,\r
+                       Moonburner.class, RodAndTubeGrain.class };\r
+\r
+       private Class[] fuelTypes = { KNSB.class, KNSU.class, KNER.class,\r
+                       KNDX.class, EditableFuel.class };\r
+\r
+       private abstract class Chooser<T> extends JPanel {\r
+               private static final long serialVersionUID = 1L;\r
+               private Class<? extends T>[] types;\r
+\r
+               public Chooser(Class<? extends T>... ts) {\r
+                       types = ts;\r
+                       setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));\r
+                       for (final Class<? extends T> c : types) {\r
+                               JButton b = new JButton(c.getSimpleName());\r
+                               add(b);\r
+                               b.addActionListener(new ActionListener() {\r
+                                       public void actionPerformed(ActionEvent e) {\r
+                                               try {\r
+                                                       choiceMade(c.newInstance());\r
+                                               } catch (InstantiationException e1) {\r
+                                                       e1.printStackTrace();\r
+                                               } catch (IllegalAccessException e1) {\r
+                                                       e1.printStackTrace();\r
+                                               }\r
+                                       }\r
+                               });\r
+                       }\r
+               }\r
+\r
+               protected abstract void choiceMade(T o);\r
+       }\r
+\r
+       private class BurnTab extends JPanel {\r
+               public BurnTab() {\r
+                       setLayout(new BorderLayout());\r
+                       setName("Burn");\r
+                       reBurn();\r
+               }\r
+\r
+               public void reBurn() {\r
+                       removeAll();\r
+                       new Thread() {\r
+                               public void run() {\r
+                                       final Burn b = new Burn(motor);\r
+                                       final BurnPanel bp = new BurnPanel(b);\r
+                                       SwingUtilities.invokeLater(new Thread() {\r
+                                               public void run() {\r
+                                                       add(bp, BorderLayout.CENTER);\r
+                                               }\r
+                                       });\r
+                               }\r
+                       }.start();\r
+               }\r
+       }\r
+\r
+       private class GrainEditor extends JSplitPane {\r
+               private static final long serialVersionUID = 1L;\r
+\r
+               public GrainEditor(final Grain g) {\r
+                       super(JSplitPane.HORIZONTAL_SPLIT);\r
+                       setName("Grain");\r
+                       setRightComponent(new GrainPanel(g));\r
+                       if (g instanceof Grain.Composite) {\r
+                               final JPanel p = new JPanel();\r
+                               p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));\r
+                               p.add(new Editor(g));\r
+                               for (Grain gg : ((Grain.Composite) g).getGrains()) {\r
+                                       final int grainEditorIndex = p.getComponentCount() + 1;\r
+                                       p.add(new Chooser<Grain>(grainTypes) {\r
+                                               private static final long serialVersionUID = 1L;\r
+\r
+                                               @Override\r
+                                               protected void choiceMade(Grain ng) {\r
+                                                       if (g instanceof MultiGrain) {\r
+                                                               ((MultiGrain) g).setGrain(ng);\r
+                                                               p.remove(grainEditorIndex);\r
+                                                               p.add(new Editor(ng), grainEditorIndex);\r
+                                                               p.remove(0);\r
+                                                               p.add(new Editor(g), 0);\r
+                                                               // System.out.println("Chose new grain");\r
+                                                       }\r
+                                               }\r
+                                       });\r
+                                       p.add(new Editor(gg));\r
+                                       if (gg instanceof MotorPart) {\r
+                                               ((MotorPart) gg)\r
+                                                               .addPropertyChangeListener(MotorEditor.this);\r
+                                       }\r
+                               }\r
+                               setLeftComponent(p);\r
+                       } else {\r
+                               setLeftComponent(new Editor(g));\r
+                       }\r
+                       // setDividerLocation(.25);\r
+                       // setResizeWeight(.25);\r
+                       if (g instanceof MotorPart) {\r
+                               ((MotorPart) g).addPropertyChangeListener(MotorEditor.this);\r
+                       }\r
+               }\r
+       }\r
+\r
+       private class FuelEditor extends JSplitPane {\r
+               private static final long serialVersionUID = 1L;\r
+\r
+               public FuelEditor(Fuel f) {\r
+                       super(JSplitPane.HORIZONTAL_SPLIT);\r
+                       setName("Fuel");\r
+                       Chart<Pressure, Velocity> burnRate;\r
+                       try {\r
+                               burnRate = new Chart<Pressure, Velocity>(SI.MEGA(SI.PASCAL),\r
+                                               SI.METERS_PER_SECOND, f, "burnRate");\r
+                       } catch (NoSuchMethodException e) {\r
+                               throw new Error(e);\r
+                       }\r
+                       burnRate.setDomain(burnRate.new IntervalDomain(Amount.valueOf(0, SI\r
+                                       .MEGA(SI.PASCAL)), Amount.valueOf(11, SI.MEGA(SI.PASCAL)),\r
+                                       20));\r
+\r
+                       final JPanel p = new JPanel();\r
+                       p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));\r
+\r
+                       p.add(new Chooser<Fuel>(fuelTypes) {\r
+                               @Override\r
+                               protected void choiceMade(Fuel o) {\r
+                                       motor.setFuel(o);\r
+                                       removeTabAt(FUEL_TAB);\r
+                                       MotorEditor.this.add(new FuelEditor(motor.getFuel()),\r
+                                                       FUEL_TAB);\r
+                                       setSelectedIndex(FUEL_TAB);\r
+                               }\r
+                       });\r
+                       p.add(new Editor(f));\r
+                       try {\r
+                               p.add(new Editor(f.getCombustionProduct()));\r
+                       } catch (Exception e) {\r
+\r
+                       }\r
+\r
+                       setLeftComponent(p);\r
+                       setRightComponent(burnRate);\r
+                       // setDividerLocation(.25);\r
+                       // setResizeWeight(.25);\r
+                       if (f instanceof MotorPart) {\r
+                               ((MotorPart) f).addPropertyChangeListener(MotorEditor.this);\r
+                       }\r
+               }\r
+       }\r
+\r
+       private class CaseEditor extends JSplitPane {\r
+               private static final long serialVersionUID = 1L;\r
+\r
+               public CaseEditor(Nozzle n, Chamber c) {\r
+                       super(JSplitPane.HORIZONTAL_SPLIT);\r
+                       setName("Casing");\r
+                       JPanel parts = new JPanel();\r
+                       parts.setLayout(new BoxLayout(parts, BoxLayout.Y_AXIS));\r
+                       setLeftComponent(parts);\r
+                       setRightComponent(new NozzlePanel(n));\r
+\r
+                       parts.add(new Editor(c));\r
+                       parts.add(new Editor(n));\r
+\r
+                       if (n instanceof MotorPart) {\r
+                               ((MotorPart) n).addPropertyChangeListener(MotorEditor.this);\r
+                       }\r
+                       if (c instanceof MotorPart) {\r
+                               ((MotorPart) c).addPropertyChangeListener(MotorEditor.this);\r
+                       }\r
+               }\r
+       }\r
+\r
+       {\r
+               text.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_XML);\r
+\r
+       }\r
+\r
+       public MotorEditor(Motor m) {\r
+               super(JTabbedPane.BOTTOM);\r
+               text.getDocument().addDocumentListener(this);\r
+               text.setName("XML");\r
+               add(text, XML_TAB);\r
+               setMotor(m, true);\r
+       }\r
+\r
+       private void reText() {\r
+               try {\r
+                       text.setText(MotorIO.writeMotor(motor));\r
+               } catch (IOException e) {\r
+                       throw new Error(e);\r
+               }\r
+       }\r
+\r
+       private void setMotor(Motor m, boolean retext) {\r
+               motor = m;\r
+               if (retext)\r
+                       reText();\r
+               if (grainEditor != null)\r
+                       remove(grainEditor);\r
+               while (getTabCount() > 1)\r
+                       removeTabAt(1);\r
+               add(new CaseEditor(motor.getNozzle(), motor.getChamber()), CASING_TAB);\r
+               add(new GrainEditor(motor.getGrain()), GRAIN_TAB);\r
+               add(new FuelEditor(motor.getFuel()), FUEL_TAB);\r
+               add(bt = new BurnTab(), BURN_TAB);\r
+       }\r
+\r
+       @Deprecated\r
+       public static Motor defaultMotor() {\r
+               Motor m = new Motor();\r
+               m.setName("Example Motor");\r
+               m.setFuel(new KNSU());\r
+\r
+               CylindricalChamber c = new CylindricalChamber();\r
+               c.setLength(Amount.valueOf(200, SI.MILLIMETER));\r
+               c.setID(Amount.valueOf(25, SI.MILLIMETER));\r
+               m.setChamber(c);\r
+\r
+               CoredCylindricalGrain g = new CoredCylindricalGrain();\r
+               try {\r
+                       g.setLength(Amount.valueOf(70, SI.MILLIMETER));\r
+                       g.setOD(Amount.valueOf(23.5, SI.MILLIMETER));\r
+                       g.setID(Amount.valueOf(7.9375, SI.MILLIMETER));\r
+               } catch (PropertyVetoException v) {\r
+                       throw new Error(v);\r
+               }\r
+\r
+               m.setGrain(new MultiGrain(g, 2));\r
+\r
+               ConvergentDivergentNozzle n = new ConvergentDivergentNozzle();\r
+               n.setThroatDiameter(Amount.valueOf(7.962, SI.MILLIMETER));\r
+               n.setExitDiameter(Amount.valueOf(13.79, SI.MILLIMETER));\r
+               n.setEfficiency(.85);\r
+               m.setNozzle(n);\r
+\r
+               return m;\r
+       }\r
+\r
+       public void focusOnObject(Object o) {\r
+               if (o instanceof Grain)\r
+                       setSelectedIndex(GRAIN_TAB);\r
+               if (o instanceof Chamber || o instanceof Nozzle)\r
+                       setSelectedIndex(CASING_TAB);\r
+               if (o instanceof Fuel || o instanceof Fuel.CombustionProduct)\r
+                       setSelectedIndex(FUEL_TAB);\r
+       }\r
+\r
+       @Deprecated\r
+       public void showAsWindow() {\r
+               JFrame f = new JFrame();\r
+               f.setSize(1024, 768);\r
+               f.setContentPane(this);\r
+               f.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);\r
+               f.setVisible(true);\r
+       }\r
+\r
+       public static void main(String args[]) throws Exception {\r
+               try {\r
+                       UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());\r
+               } catch (Exception e1) {\r
+                       e1.printStackTrace();\r
+               }\r
+               new MotorEditor(defaultMotor()).showAsWindow();\r
+       }\r
+\r
+       public void propertyChange(PropertyChangeEvent evt) {\r
+               reText();\r
+               bt.reBurn();\r
+       }\r
+\r
+       public void changedUpdate(DocumentEvent e) {\r
+               try {\r
+                       final Motor m = MotorIO.readMotor(text.getText());\r
+                       SwingUtilities.invokeLater(new Runnable() {\r
+                               public void run() {\r
+                                       setMotor(m, false);\r
+                               }\r
+                       });\r
+                       System.out.println("Motor Updated");\r
+               } catch (Throwable e1) {\r
+                       // Leave blank, motor might be broken\r
+               }\r
+       }\r
+\r
+       public void insertUpdate(DocumentEvent e) {\r
+               // TODO Auto-generated method stub\r
+       }\r
+\r
+       public void removeUpdate(DocumentEvent e) {\r
+               // TODO Auto-generated method stub\r
+       }\r
+}\r
diff --git a/src/com/billkuker/rocketry/motorsim/visual/workbench/MotorWorkbench.java b/src/com/billkuker/rocketry/motorsim/visual/workbench/MotorWorkbench.java
new file mode 100644 (file)
index 0000000..f1b8da9
--- /dev/null
@@ -0,0 +1,107 @@
+package com.billkuker.rocketry.motorsim.visual.workbench;\r
+\r
+import java.awt.BorderLayout;\r
+import java.awt.Dimension;\r
+import java.util.HashMap;\r
+\r
+import javax.swing.JButton;\r
+import javax.swing.JFrame;\r
+import javax.swing.JPanel;\r
+import javax.swing.JScrollPane;\r
+import javax.swing.JSplitPane;\r
+import javax.swing.JTabbedPane;\r
+import javax.swing.JToolBar;\r
+import javax.swing.JTree;\r
+import javax.swing.UIManager;\r
+import javax.swing.WindowConstants;\r
+import javax.swing.event.TreeSelectionEvent;\r
+import javax.swing.event.TreeSelectionListener;\r
+import javax.swing.tree.DefaultMutableTreeNode;\r
+import javax.swing.tree.TreePath;\r
+import javax.swing.tree.TreeSelectionModel;\r
+\r
+import com.billkuker.rocketry.motorsim.Motor;\r
+\r
+public class MotorWorkbench extends JFrame implements TreeSelectionListener {\r
+       private static final long serialVersionUID = 1L;\r
+       private JPanel top;\r
+       private JSplitPane split;\r
+       private JTree tree;\r
+       private JTabbedPane motors;\r
+       private JToolBar bar;\r
+       private WorkbenchTreeModel tm;\r
+\r
+       private HashMap<Motor, MotorEditor> m2e = new HashMap<Motor, MotorEditor>();\r
+\r
+       public MotorWorkbench() {\r
+               setSize(1024, 768);\r
+               top = new JPanel(new BorderLayout());\r
+               setContentPane(top);\r
+\r
+               bar = new JToolBar();\r
+               bar.add(new JButton("Burn"));\r
+               top.add(bar, BorderLayout.PAGE_START);\r
+\r
+               motors = new JTabbedPane();\r
+\r
+               tree = new JTree(tm = new WorkbenchTreeModel());\r
+               tree.setCellRenderer(new WorkbenchTreeCellRenderer());\r
+               tree.getSelectionModel().setSelectionMode(\r
+                               TreeSelectionModel.SINGLE_TREE_SELECTION);\r
+               tree.setPreferredSize(new Dimension(200, 100));\r
+\r
+               // Listen for when the selection changes.\r
+               tree.addTreeSelectionListener(this);\r
+\r
+               split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, new JScrollPane(\r
+                               tree), motors);\r
+               //split.setDividerLocation(.25);\r
+               //split.setResizeWeight(.25);\r
+               top.add(split, BorderLayout.CENTER);\r
+\r
+               setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);\r
+               setVisible(true);\r
+\r
+               Motor mot = MotorEditor.defaultMotor();\r
+               addMotor(mot);\r
+               //mot = MotorEditor.defaultMotor();\r
+               //addMotor(mot);\r
+       }\r
+\r
+       public void addMotor(Motor m) {\r
+               tm.addMotor(m);\r
+               MotorEditor e = new MotorEditor(m);\r
+               m2e.put(m, e);\r
+               motors.addTab("Motor", e);\r
+       }\r
+\r
+       public static void main(String args[]) throws Exception {\r
+               try {\r
+                       UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());\r
+               } catch (Exception e1) {\r
+                       e1.printStackTrace();\r
+               }\r
+               new MotorWorkbench().show();\r
+       }\r
+\r
+       @Override\r
+       public void valueChanged(TreeSelectionEvent e) {\r
+               Motor m = getMotor(e.getPath());\r
+\r
+               motors.setSelectedComponent(m2e.get(m));\r
+               \r
+               if ( e.getPath().getLastPathComponent() instanceof DefaultMutableTreeNode ){\r
+                       Object o = ((DefaultMutableTreeNode)e.getPath().getLastPathComponent()).getUserObject();\r
+                       m2e.get(m).focusOnObject(o);\r
+               }\r
+       }\r
+\r
+       private Motor getMotor(TreePath p) {\r
+               if (p.getLastPathComponent() instanceof WorkbenchTreeModel.MotorNode) {\r
+                       return ((WorkbenchTreeModel.MotorNode) p.getLastPathComponent())\r
+                                       .getUserObject();\r
+               } else if (p.getPath().length > 1)\r
+                       return getMotor(p.getParentPath());\r
+               return null;\r
+       }\r
+}\r