0eb73d5c7927afd728c03fd7ffbd1ea08026ee08
[sw/motorsim] / gpl / com / billkuker / rocketry / motorsim / visual / openRocket / RocketSimTable.java
1 package com.billkuker.rocketry.motorsim.visual.openRocket;\r
2 \r
3 import java.awt.BorderLayout;\r
4 import java.awt.Color;\r
5 import java.awt.Component;\r
6 import java.awt.event.MouseAdapter;\r
7 import java.awt.event.MouseEvent;\r
8 import java.io.File;\r
9 import java.util.Iterator;\r
10 import java.util.List;\r
11 import java.util.Vector;\r
12 \r
13 import javax.measure.unit.SI;\r
14 import javax.swing.JLabel;\r
15 import javax.swing.JPanel;\r
16 import javax.swing.JScrollPane;\r
17 import javax.swing.JTable;\r
18 import javax.swing.SwingUtilities;\r
19 import javax.swing.table.AbstractTableModel;\r
20 import javax.swing.table.DefaultTableCellRenderer;\r
21 \r
22 import net.sf.openrocket.aerodynamics.Warning;\r
23 import net.sf.openrocket.document.OpenRocketDocument;\r
24 import net.sf.openrocket.document.Simulation;\r
25 import net.sf.openrocket.file.RocketLoadException;\r
26 import net.sf.openrocket.file.openrocket.OpenRocketLoader;\r
27 import net.sf.openrocket.gui.plot.PlotConfiguration;\r
28 import net.sf.openrocket.gui.plot.SimulationPlotDialog;\r
29 import net.sf.openrocket.gui.util.SwingPreferences;\r
30 import net.sf.openrocket.l10n.ResourceBundleTranslator;\r
31 import net.sf.openrocket.rocketcomponent.MotorMount;\r
32 import net.sf.openrocket.rocketcomponent.RocketComponent;\r
33 import net.sf.openrocket.simulation.exception.SimulationException;\r
34 import net.sf.openrocket.startup.Application;\r
35 import net.sf.openrocket.unit.UnitGroup;\r
36 \r
37 import org.jscience.physics.amount.Amount;\r
38 \r
39 import com.billkuker.rocketry.motorsim.Burn;\r
40 import com.billkuker.rocketry.motorsim.Motor;\r
41 import com.billkuker.rocketry.motorsim.RocketScience;\r
42 import com.billkuker.rocketry.motorsim.RocketScience.UnitPreference;\r
43 import com.billkuker.rocketry.motorsim.visual.workbench.BurnWatcher;\r
44 \r
45 public class RocketSimTable extends JPanel implements BurnWatcher,\r
46                 RocketScience.UnitPreferenceListener {\r
47         static final long serialVersionUID = 1L;\r
48 \r
49         private static final Color RED = new Color(196, 0, 0);\r
50 \r
51         static {\r
52                 Application.setBaseTranslator(new ResourceBundleTranslator(\r
53                                 "l10n.messages"));\r
54                 Application.setMotorSetDatabase(new OneMotorDatabase());\r
55                 Application.setPreferences(new SwingPreferences());\r
56 \r
57         }\r
58 \r
59         class Entry {\r
60                 Entry(Motor m, Simulation s, Burn b) {\r
61                         this.m = m;\r
62                         this.s = s;\r
63                         this.b = b;\r
64                 }\r
65 \r
66                 boolean ready = false;\r
67                 Simulation s;\r
68                 Motor m;\r
69                 Burn b;\r
70         }\r
71 \r
72         List<Entry> entries = new Vector<Entry>();\r
73 \r
74         class TM extends AbstractTableModel {\r
75                 private static final long serialVersionUID = 1L;\r
76 \r
77                 @Override\r
78                 public String getColumnName(int col) {\r
79                         switch (col) {\r
80                         case 0:\r
81                                 return "Motor";\r
82                         case 1:\r
83                                 return "Apogee";\r
84                         case 2:\r
85                                 return "Vmax";\r
86                         case 3:\r
87                                 return "Vdeploy";\r
88                         case 4:\r
89                                 return "Vground";\r
90                         case 5:\r
91                                 return "Tapogee";\r
92                         case 6:\r
93                                 return "Tflight";\r
94                         }\r
95                         return "??";\r
96                 }\r
97 \r
98                 @Override\r
99                 public int getColumnCount() {\r
100                         return 7;\r
101                 }\r
102 \r
103                 @Override\r
104                 public int getRowCount() {\r
105                         return entries.size();\r
106                 }\r
107 \r
108                 @Override\r
109                 public Object getValueAt(int row, int col) {\r
110                         Entry e = entries.get(row);\r
111                         if (e == null)\r
112                                 return "???";\r
113                         if (e.ready == false)\r
114                                 return "...";\r
115                         switch (col) {\r
116                         case 0:\r
117                                 return e.m.getName();\r
118                         case 1:\r
119                                 return RocketScience.ammountToRoundedString(Amount.valueOf(e.s\r
120                                                 .getSimulatedData().getMaxAltitude(), SI.METER));\r
121                         case 2:\r
122                                 return RocketScience.ammountToRoundedString(Amount.valueOf(e.s\r
123                                                 .getSimulatedData().getMaxVelocity(),\r
124                                                 SI.METERS_PER_SECOND));\r
125                         case 3:\r
126                                 return RocketScience.ammountToRoundedString(Amount.valueOf(e.s\r
127                                                 .getSimulatedData().getDeploymentVelocity(),\r
128                                                 SI.METERS_PER_SECOND));\r
129                         case 4:\r
130                                 return RocketScience.ammountToRoundedString(Amount.valueOf(e.s\r
131                                                 .getSimulatedData().getGroundHitVelocity(),\r
132                                                 SI.METERS_PER_SECOND));\r
133                         case 5:\r
134                                 return RocketScience.ammountToRoundedString(Amount.valueOf(e.s\r
135                                                 .getSimulatedData().getTimeToApogee(), SI.SECOND));\r
136                         case 6:\r
137                                 return RocketScience.ammountToRoundedString(Amount.valueOf(e.s\r
138                                                 .getSimulatedData().getFlightTime(), SI.SECOND));\r
139                         }\r
140                         return "??";\r
141                 }\r
142 \r
143         }\r
144 \r
145         private TM tm = new TM();\r
146         private JTable table = new JTable(tm);\r
147         private OpenRocketDocument doc;\r
148 \r
149         public RocketSimTable() {\r
150                 setLayout(new BorderLayout());\r
151                 JScrollPane scroll = new JScrollPane();\r
152                 scroll.setViewportView(table);\r
153                 add(scroll, BorderLayout.CENTER);\r
154 \r
155                 table.setDefaultRenderer(Object.class, new DefaultTableCellRenderer() {\r
156                         private static final long serialVersionUID = 1L;\r
157 \r
158                         public Component getTableCellRendererComponent(JTable table,\r
159                                         Object value, boolean isSelected, boolean hasFocus,\r
160                                         int row, int column) {\r
161                                 Component c = super.getTableCellRendererComponent(table, value,\r
162                                                 isSelected, hasFocus, row, column);\r
163                                 Entry e = entries.get(row);\r
164                                 if (e.ready && e.s.getSimulatedWarnings().size() > 0) {\r
165                                         c.setBackground(RED);\r
166                                         c.setForeground(Color.WHITE);\r
167                                         StringBuilder sb = new StringBuilder();\r
168                                         sb.append("<html>");\r
169                                         for (Warning w : e.s.getSimulatedWarnings()) {\r
170                                                 sb.append(w.toString());\r
171                                                 sb.append("<br>");\r
172                                         }\r
173                                         sb.append("<html>");\r
174                                         setToolTipText(sb.toString());\r
175                                 } else {\r
176                                         c.setBackground(table.getBackground());\r
177                                         c.setForeground(table.getForeground());\r
178                                 }\r
179                                 return c;\r
180                         }\r
181                 });\r
182 \r
183                 RocketScience.addUnitPreferenceListener(this);\r
184                 table.addMouseListener(new MouseAdapter() {\r
185                         public void mouseClicked(MouseEvent e) {\r
186                                 if (e.getClickCount() == 2) {\r
187                                         Entry entry = entries.get(table.getSelectedRow());\r
188                                         SimulationPlotDialog.showPlot(SwingUtilities\r
189                                                         .getWindowAncestor(RocketSimTable.this), entry.s,\r
190                                                         PlotConfiguration.DEFAULT_CONFIGURATIONS[0]\r
191                                                                         .resetUnits());\r
192                                 }\r
193                         }\r
194                 });\r
195                 preferredUnitsChanged();\r
196         }\r
197 \r
198         public void openRocket(File f) throws RocketLoadException {\r
199                 this.doc = new OpenRocketLoader().load(f);\r
200                 JPanel rocketInfo = new JPanel();\r
201                 JLabel name = new JLabel("File: " + f.getAbsolutePath());\r
202                 rocketInfo.add(name);\r
203                 add(rocketInfo, BorderLayout.NORTH);\r
204                 revalidate();\r
205         }\r
206 \r
207         private Entry toEntry(Burn b) {\r
208                 final Entry e = new Entry(b.getMotor(), doc.getSimulation(0).copy(), b);\r
209                 OneMotorDatabase.setBurn(b);\r
210 \r
211                 e.s.getConfiguration().getMotorConfigurationID();\r
212                 Iterator<RocketComponent> iterator = doc.getRocket().iterator();\r
213                 while (iterator.hasNext()) {\r
214                         RocketComponent c = iterator.next();\r
215                         if (c instanceof MotorMount) {\r
216                                 ((MotorMount) c).setMotorDelay(e.s.getConfiguration()\r
217                                                 .getMotorConfigurationID(), b.getMotor()\r
218                                                 .getEjectionDelay().doubleValue(SI.SECOND));\r
219                         }\r
220                 }\r
221 \r
222                 tm.fireTableDataChanged();\r
223                 new Thread() {\r
224                         @Override\r
225                         public void run() {\r
226                                 try {\r
227                                         e.s.simulate();\r
228                                         e.ready = true;\r
229                                         tm.fireTableDataChanged();\r
230                                 } catch (SimulationException e1) {\r
231                                         e1.printStackTrace();\r
232                                 }\r
233 \r
234                         }\r
235                 }.start();\r
236 \r
237                 return e;\r
238         }\r
239 \r
240         @Override\r
241         public void replace(Burn oldBurn, Burn newBurn) {\r
242                 if (doc == null) {\r
243                         return; // TODO, deal with changing rockets\r
244                 }\r
245 \r
246                 if (oldBurn != null) {\r
247                         for (int i = 0; i < entries.size(); i++) {\r
248                                 if (entries.get(i).b == oldBurn) {\r
249                                         if (newBurn != null) {\r
250                                                 entries.set(i, toEntry(newBurn));\r
251                                         } else {\r
252                                                 entries.remove(i);\r
253                                         }\r
254                                         break;\r
255                                 }\r
256                         }\r
257                 } else {\r
258                         entries.add(toEntry(newBurn));\r
259                 }\r
260                 tm.fireTableDataChanged();\r
261         }\r
262 \r
263         @Override\r
264         public void preferredUnitsChanged() {\r
265                 tm.fireTableDataChanged();\r
266                 if (UnitPreference.getUnitPreference() == UnitPreference.NONSI) {\r
267                         System.err.println("NONSI");\r
268                         UnitGroup.setDefaultImperialUnits();\r
269                 } else {\r
270                         System.err.println("SI");\r
271                         UnitGroup.setDefaultMetricUnits();\r
272                 }\r
273         }\r
274 }\r