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