update changelogs for Debian build
[fw/altos] / altosui / AltosAscent.java
1 /*
2  * Copyright © 2010 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; version 2 of the License.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program; if not, write to the Free Software Foundation, Inc.,
15  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
16  */
17
18 package altosui;
19
20 import java.awt.*;
21 import java.awt.event.*;
22 import javax.swing.*;
23 import javax.swing.filechooser.FileNameExtensionFilter;
24 import javax.swing.table.*;
25 import java.io.*;
26 import java.util.*;
27 import java.text.*;
28 import java.util.prefs.*;
29 import java.util.concurrent.LinkedBlockingQueue;
30
31 public class AltosAscent extends JComponent implements AltosFlightDisplay {
32         GridBagLayout   layout;
33
34         public class AscentStatus {
35                 JLabel          label;
36                 JTextField      value;
37                 AltosLights     lights;
38
39                 void show(AltosState state, int crc_errors) {}
40                 void reset() {
41                         value.setText("");
42                         lights.set(false);
43                 }
44
45                 public AscentStatus (GridBagLayout layout, int y, String text) {
46                         GridBagConstraints      c = new GridBagConstraints();
47                         c.weighty = 1;
48
49                         lights = new AltosLights();
50                         c.gridx = 0; c.gridy = y;
51                         c.anchor = GridBagConstraints.CENTER;
52                         c.fill = GridBagConstraints.VERTICAL;
53                         c.weightx = 0;
54                         layout.setConstraints(lights, c);
55                         add(lights);
56
57                         label = new JLabel(text);
58                         label.setFont(Altos.label_font);
59                         label.setHorizontalAlignment(SwingConstants.LEFT);
60                         c.gridx = 1; c.gridy = y;
61                         c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
62                         c.anchor = GridBagConstraints.WEST;
63                         c.fill = GridBagConstraints.VERTICAL;
64                         c.weightx = 0;
65                         layout.setConstraints(label, c);
66                         add(label);
67
68                         value = new JTextField(Altos.text_width);
69                         value.setFont(Altos.value_font);
70                         value.setHorizontalAlignment(SwingConstants.RIGHT);
71                         c.gridx = 2; c.gridy = y;
72                         c.gridwidth = 2;
73                         c.anchor = GridBagConstraints.WEST;
74                         c.fill = GridBagConstraints.BOTH;
75                         c.weightx = 1;
76                         layout.setConstraints(value, c);
77                         add(value);
78
79                 }
80         }
81
82         public class AscentValue {
83                 JLabel          label;
84                 JTextField      value;
85                 void show(AltosState state, int crc_errors) {}
86
87                 void reset() {
88                         value.setText("");
89                 }
90                 public AscentValue (GridBagLayout layout, int y, String text) {
91                         GridBagConstraints      c = new GridBagConstraints();
92                         c.weighty = 1;
93
94                         label = new JLabel(text);
95                         label.setFont(Altos.label_font);
96                         label.setHorizontalAlignment(SwingConstants.LEFT);
97                         c.gridx = 1; c.gridy = y;
98                         c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
99                         c.anchor = GridBagConstraints.WEST;
100                         c.fill = GridBagConstraints.VERTICAL;
101                         c.weightx = 0;
102                         layout.setConstraints(label, c);
103                         add(label);
104
105                         value = new JTextField(Altos.text_width);
106                         value.setFont(Altos.value_font);
107                         value.setHorizontalAlignment(SwingConstants.RIGHT);
108                         c.gridx = 2; c.gridy = y;
109                         c.anchor = GridBagConstraints.WEST;
110                         c.fill = GridBagConstraints.BOTH;
111                         c.gridwidth = 2;
112                         c.weightx = 1;
113                         layout.setConstraints(value, c);
114                         add(value);
115                 }
116         }
117
118         public class AscentValueHold {
119                 JLabel          label;
120                 JTextField      value;
121                 JTextField      max_value;
122                 double          max;
123
124                 void show(AltosState state, int crc_errors) {}
125
126                 void reset() {
127                         value.setText("");
128                         max_value.setText("");
129                         max = 0;
130                 }
131
132                 void show(String format, double v) {
133                         value.setText(String.format(format, v));
134                         if (v > max) {
135                                 max_value.setText(String.format(format, v));
136                                 max = v;
137                         }
138                 }
139                 public AscentValueHold (GridBagLayout layout, int y, String text) {
140                         GridBagConstraints      c = new GridBagConstraints();
141                         c.weighty = 1;
142
143                         label = new JLabel(text);
144                         label.setFont(Altos.label_font);
145                         label.setHorizontalAlignment(SwingConstants.LEFT);
146                         c.gridx = 1; c.gridy = y;
147                         c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
148                         c.anchor = GridBagConstraints.WEST;
149                         c.fill = GridBagConstraints.VERTICAL;
150                         c.weightx = 0;
151                         layout.setConstraints(label, c);
152                         add(label);
153
154                         value = new JTextField(Altos.text_width);
155                         value.setFont(Altos.value_font);
156                         value.setHorizontalAlignment(SwingConstants.RIGHT);
157                         c.gridx = 2; c.gridy = y;
158                         c.anchor = GridBagConstraints.EAST;
159                         c.fill = GridBagConstraints.BOTH;
160                         c.weightx = 1;
161                         layout.setConstraints(value, c);
162                         add(value);
163
164                         max_value = new JTextField(Altos.text_width);
165                         max_value.setFont(Altos.value_font);
166                         max_value.setHorizontalAlignment(SwingConstants.RIGHT);
167                         c.gridx = 3; c.gridy = y;
168                         c.anchor = GridBagConstraints.EAST;
169                         c.fill = GridBagConstraints.BOTH;
170                         c.weightx = 1;
171                         layout.setConstraints(max_value, c);
172                         add(max_value);
173                 }
174         }
175
176
177         class Height extends AscentValueHold {
178                 void show (AltosState state, int crc_errors) {
179                         show("%6.0f m", state.height);
180                 }
181                 public Height (GridBagLayout layout, int y) {
182                         super (layout, y, "Height");
183                 }
184         }
185
186         Height  height;
187
188         class Speed extends AscentValueHold {
189                 void show (AltosState state, int crc_errors) {
190                         double speed = state.speed;
191                         if (!state.ascent)
192                                 speed = state.baro_speed;
193                         show("%6.0f m/s", speed);
194                 }
195                 public Speed (GridBagLayout layout, int y) {
196                         super (layout, y, "Speed");
197                 }
198         }
199
200         Speed   speed;
201
202         class Accel extends AscentValueHold {
203                 void show (AltosState state, int crc_errors) {
204                         show("%6.0f m/s²", state.acceleration);
205                 }
206                 public Accel (GridBagLayout layout, int y) {
207                         super (layout, y, "Acceleration");
208                 }
209         }
210
211         Accel   accel;
212
213         String pos(double p, String pos, String neg) {
214                 String  h = pos;
215                 if (p < 0) {
216                         h = neg;
217                         p = -p;
218                 }
219                 int deg = (int) Math.floor(p);
220                 double min = (p - Math.floor(p)) * 60.0;
221                 return String.format("%s %4d° %9.6f", h, deg, min);
222         }
223
224         class Apogee extends AscentStatus {
225                 void show (AltosState state, int crc_errors) {
226                         value.setText(String.format("%4.2f V", state.drogue_sense));
227                         lights.set(state.drogue_sense > 3.2);
228                 }
229                 public Apogee (GridBagLayout layout, int y) {
230                         super(layout, y, "Apogee Igniter Voltage");
231                 }
232         }
233
234         Apogee apogee;
235
236         class Main extends AscentStatus {
237                 void show (AltosState state, int crc_errors) {
238                         value.setText(String.format("%4.2f V", state.main_sense));
239                         lights.set(state.main_sense > 3.2);
240                 }
241                 public Main (GridBagLayout layout, int y) {
242                         super(layout, y, "Main Igniter Voltage");
243                 }
244         }
245
246         Main main;
247
248         class Lat extends AscentValue {
249                 void show (AltosState state, int crc_errors) {
250                         if (state.gps != null)
251                                 value.setText(pos(state.gps.lat,"N", "S"));
252                         else
253                                 value.setText("???");
254                 }
255                 public Lat (GridBagLayout layout, int y) {
256                         super (layout, y, "Latitude");
257                 }
258         }
259
260         Lat lat;
261
262         class Lon extends AscentValue {
263                 void show (AltosState state, int crc_errors) {
264                         if (state.gps != null)
265                                 value.setText(pos(state.gps.lon,"E", "W"));
266                         else
267                                 value.setText("???");
268                 }
269                 public Lon (GridBagLayout layout, int y) {
270                         super (layout, y, "Longitude");
271                 }
272         }
273
274         Lon lon;
275
276         public void reset() {
277                 lat.reset();
278                 lon.reset();
279                 main.reset();
280                 apogee.reset();
281                 height.reset();
282                 speed.reset();
283                 accel.reset();
284         }
285
286         public void show(AltosState state, int crc_errors) {
287                 lat.show(state, crc_errors);
288                 lon.show(state, crc_errors);
289                 height.show(state, crc_errors);
290                 main.show(state, crc_errors);
291                 apogee.show(state, crc_errors);
292                 speed.show(state, crc_errors);
293                 accel.show(state, crc_errors);
294         }
295
296         public void labels(GridBagLayout layout, int y) {
297                 GridBagConstraints      c;
298                 JLabel                  cur, max;
299
300                 cur = new JLabel("Current");
301                 cur.setFont(Altos.label_font);
302                 c = new GridBagConstraints();
303                 c.gridx = 2; c.gridy = y;
304                 c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
305                 layout.setConstraints(cur, c);
306                 add(cur);
307
308                 max = new JLabel("Maximum");
309                 max.setFont(Altos.label_font);
310                 c.gridx = 3; c.gridy = y;
311                 layout.setConstraints(max, c);
312                 add(max);
313         }
314
315         public AltosAscent() {
316                 layout = new GridBagLayout();
317
318                 setLayout(layout);
319
320                 /* Elements in ascent display:
321                  *
322                  * lat
323                  * lon
324                  * height
325                  */
326                 labels(layout, 0);
327                 height = new Height(layout, 1);
328                 speed = new Speed(layout, 2);
329                 accel = new Accel(layout, 3);
330                 lat = new Lat(layout, 4);
331                 lon = new Lon(layout, 5);
332                 apogee = new Apogee(layout, 6);
333                 main = new Main(layout, 7);
334         }
335 }