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