945af7e26104665951e0768093e218d8df7358fb
[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 javax.swing.*;
22 import org.altusmetrum.AltosLib.*;
23
24 public class AltosAscent extends JComponent implements AltosFlightDisplay {
25         GridBagLayout   layout;
26         JLabel                  cur, max;
27
28         public class AscentStatus {
29                 JLabel          label;
30                 JTextField      value;
31                 AltosLights     lights;
32
33                 void show() {
34                         value.setVisible(true);
35                         lights.setVisible(true);
36                         label.setVisible(true);
37                 }
38
39                 void hide() {
40                         value.setVisible(false);
41                         lights.setVisible(false);
42                         label.setVisible(false);
43                 }
44
45                 void show(AltosState state, int crc_errors) {}
46                 void reset() {
47                         value.setText("");
48                         lights.set(false);
49                 }
50
51                 void set_font() {
52                         label.setFont(Altos.label_font);
53                         value.setFont(Altos.value_font);
54                 }
55
56                 public AscentStatus (GridBagLayout layout, int y, String text) {
57                         GridBagConstraints      c = new GridBagConstraints();
58                         c.weighty = 1;
59
60                         lights = new AltosLights();
61                         c.gridx = 0; c.gridy = y;
62                         c.anchor = GridBagConstraints.CENTER;
63                         c.fill = GridBagConstraints.VERTICAL;
64                         c.weightx = 0;
65                         layout.setConstraints(lights, c);
66                         add(lights);
67
68                         label = new JLabel(text);
69                         label.setFont(Altos.label_font);
70                         label.setHorizontalAlignment(SwingConstants.LEFT);
71                         c.gridx = 1; c.gridy = y;
72                         c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
73                         c.anchor = GridBagConstraints.WEST;
74                         c.fill = GridBagConstraints.VERTICAL;
75                         c.weightx = 0;
76                         layout.setConstraints(label, c);
77                         add(label);
78
79                         value = new JTextField(Altos.text_width);
80                         value.setFont(Altos.value_font);
81                         value.setHorizontalAlignment(SwingConstants.RIGHT);
82                         c.gridx = 2; c.gridy = y;
83                         c.gridwidth = 2;
84                         c.anchor = GridBagConstraints.WEST;
85                         c.fill = GridBagConstraints.BOTH;
86                         c.weightx = 1;
87                         layout.setConstraints(value, c);
88                         add(value);
89
90                 }
91         }
92
93         public class AscentValue {
94                 JLabel          label;
95                 JTextField      value;
96                 void show(AltosState state, int crc_errors) {}
97
98                 void reset() {
99                         value.setText("");
100                 }
101
102                 void show() {
103                         label.setVisible(true);
104                         value.setVisible(true);
105                 }
106
107                 void hide() {
108                         label.setVisible(false);
109                         value.setVisible(false);
110                 }
111                 void set_font() {
112                         label.setFont(Altos.label_font);
113                         value.setFont(Altos.value_font);
114                 }
115
116                 public AscentValue (GridBagLayout layout, int y, String text) {
117                         GridBagConstraints      c = new GridBagConstraints();
118                         c.weighty = 1;
119
120                         label = new JLabel(text);
121                         label.setFont(Altos.label_font);
122                         label.setHorizontalAlignment(SwingConstants.LEFT);
123                         c.gridx = 1; c.gridy = y;
124                         c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
125                         c.anchor = GridBagConstraints.WEST;
126                         c.fill = GridBagConstraints.VERTICAL;
127                         c.weightx = 0;
128                         layout.setConstraints(label, c);
129                         add(label);
130
131                         value = new JTextField(Altos.text_width);
132                         value.setFont(Altos.value_font);
133                         value.setHorizontalAlignment(SwingConstants.RIGHT);
134                         c.gridx = 2; c.gridy = y;
135                         c.anchor = GridBagConstraints.WEST;
136                         c.fill = GridBagConstraints.BOTH;
137                         c.gridwidth = 2;
138                         c.weightx = 1;
139                         layout.setConstraints(value, c);
140                         add(value);
141                 }
142         }
143
144         public class AscentValueHold {
145                 JLabel          label;
146                 JTextField      value;
147                 JTextField      max_value;
148                 double          max;
149
150                 void show(AltosState state, int crc_errors) {}
151
152                 void reset() {
153                         value.setText("");
154                         max_value.setText("");
155                         max = AltosRecord.MISSING;
156                 }
157
158                 void set_font() {
159                         label.setFont(Altos.label_font);
160                         value.setFont(Altos.value_font);
161                         max_value.setFont(Altos.value_font);
162                 }
163
164                 void show(AltosUnits units, double v) {
165                         if (v == AltosRecord.MISSING) {
166                                 value.setText("Missing");
167                                 max_value.setText("Missing");
168                         } else {
169                                 value.setText(units.show(8, v));
170                                 if (v > max || max == AltosRecord.MISSING) {
171                                         max_value.setText(units.show(8, v));
172                                         max = v;
173                                 }
174                         }
175                 }
176                 public AscentValueHold (GridBagLayout layout, int y, String text) {
177                         GridBagConstraints      c = new GridBagConstraints();
178                         c.weighty = 1;
179
180                         label = new JLabel(text);
181                         label.setFont(Altos.label_font);
182                         label.setHorizontalAlignment(SwingConstants.LEFT);
183                         c.gridx = 1; c.gridy = y;
184                         c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
185                         c.anchor = GridBagConstraints.WEST;
186                         c.fill = GridBagConstraints.VERTICAL;
187                         c.weightx = 0;
188                         layout.setConstraints(label, c);
189                         add(label);
190
191                         value = new JTextField(Altos.text_width);
192                         value.setFont(Altos.value_font);
193                         value.setHorizontalAlignment(SwingConstants.RIGHT);
194                         c.gridx = 2; c.gridy = y;
195                         c.anchor = GridBagConstraints.EAST;
196                         c.fill = GridBagConstraints.BOTH;
197                         c.weightx = 1;
198                         layout.setConstraints(value, c);
199                         add(value);
200
201                         max_value = new JTextField(Altos.text_width);
202                         max_value.setFont(Altos.value_font);
203                         max_value.setHorizontalAlignment(SwingConstants.RIGHT);
204                         c.gridx = 3; c.gridy = y;
205                         c.anchor = GridBagConstraints.EAST;
206                         c.fill = GridBagConstraints.BOTH;
207                         c.weightx = 1;
208                         layout.setConstraints(max_value, c);
209                         add(max_value);
210                 }
211         }
212
213
214         class Height extends AscentValueHold {
215                 void show (AltosState state, int crc_errors) {
216                         show(AltosConvert.height, state.height);
217                 }
218                 public Height (GridBagLayout layout, int y) {
219                         super (layout, y, "Height");
220                 }
221         }
222
223         Height  height;
224
225         class Speed extends AscentValueHold {
226                 void show (AltosState state, int crc_errors) {
227                         double speed = state.speed;
228                         if (!state.ascent)
229                                 speed = state.baro_speed;
230                         show(AltosConvert.speed, speed);
231                 }
232                 public Speed (GridBagLayout layout, int y) {
233                         super (layout, y, "Speed");
234                 }
235         }
236
237         Speed   speed;
238
239         class Accel extends AscentValueHold {
240                 void show (AltosState state, int crc_errors) {
241                         show(AltosConvert.accel, state.acceleration);
242                 }
243                 public Accel (GridBagLayout layout, int y) {
244                         super (layout, y, "Acceleration");
245                 }
246         }
247
248         Accel   accel;
249
250         String pos(double p, String pos, String neg) {
251                 String  h = pos;
252                 if (p < 0) {
253                         h = neg;
254                         p = -p;
255                 }
256                 int deg = (int) Math.floor(p);
257                 double min = (p - Math.floor(p)) * 60.0;
258                 return String.format("%s %4d° %9.6f", h, deg, min);
259         }
260
261         class Apogee extends AscentStatus {
262                 void show (AltosState state, int crc_errors) {
263                         show();
264                         value.setText(String.format("%4.2f V", state.drogue_sense));
265                         lights.set(state.drogue_sense > 3.2);
266                 }
267                 public Apogee (GridBagLayout layout, int y) {
268                         super(layout, y, "Apogee Igniter Voltage");
269                 }
270         }
271
272         Apogee apogee;
273
274         class Main extends AscentStatus {
275                 void show (AltosState state, int crc_errors) {
276                         show();
277                         value.setText(String.format("%4.2f V", state.main_sense));
278                         lights.set(state.main_sense > 3.2);
279                 }
280                 public Main (GridBagLayout layout, int y) {
281                         super(layout, y, "Main Igniter Voltage");
282                 }
283         }
284
285         Main main;
286
287         class Lat extends AscentValue {
288                 void show (AltosState state, int crc_errors) {
289                         show();
290                         if (state.gps != null)
291                                 value.setText(pos(state.gps.lat,"N", "S"));
292                         else
293                                 value.setText("???");
294                 }
295                 public Lat (GridBagLayout layout, int y) {
296                         super (layout, y, "Latitude");
297                 }
298         }
299
300         Lat lat;
301
302         class Lon extends AscentValue {
303                 void show (AltosState state, int crc_errors) {
304                         show();
305                         if (state.gps != null)
306                                 value.setText(pos(state.gps.lon,"E", "W"));
307                         else
308                                 value.setText("???");
309                 }
310                 public Lon (GridBagLayout layout, int y) {
311                         super (layout, y, "Longitude");
312                 }
313         }
314
315         Lon lon;
316
317         public void reset() {
318                 lat.reset();
319                 lon.reset();
320                 main.reset();
321                 apogee.reset();
322                 height.reset();
323                 speed.reset();
324                 accel.reset();
325         }
326
327         public void set_font() {
328                 cur.setFont(Altos.label_font);
329                 max.setFont(Altos.label_font);
330                 lat.set_font();
331                 lon.set_font();
332                 main.set_font();
333                 apogee.set_font();
334                 height.set_font();
335                 speed.set_font();
336                 accel.set_font();
337         }
338
339         public void show(AltosState state, int crc_errors) {
340                 if (state.gps != null && state.gps.connected) {
341                         lat.show(state, crc_errors);
342                         lon.show(state, crc_errors);
343                 } else {
344                         lat.hide();
345                         lon.hide();
346                 }
347                 height.show(state, crc_errors);
348                 if (state.main_sense != AltosRecord.MISSING)
349                         main.show(state, crc_errors);
350                 else
351                         main.hide();
352                 if (state.drogue_sense != AltosRecord.MISSING)
353                         apogee.show(state, crc_errors);
354                 else
355                         apogee.hide();
356                 speed.show(state, crc_errors);
357                 accel.show(state, crc_errors);
358         }
359
360         public void labels(GridBagLayout layout, int y) {
361                 GridBagConstraints      c;
362
363                 cur = new JLabel("Current");
364                 cur.setFont(Altos.label_font);
365                 c = new GridBagConstraints();
366                 c.gridx = 2; c.gridy = y;
367                 c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
368                 layout.setConstraints(cur, c);
369                 add(cur);
370
371                 max = new JLabel("Maximum");
372                 max.setFont(Altos.label_font);
373                 c.gridx = 3; c.gridy = y;
374                 layout.setConstraints(max, c);
375                 add(max);
376         }
377
378         public AltosAscent() {
379                 layout = new GridBagLayout();
380
381                 setLayout(layout);
382
383                 /* Elements in ascent display:
384                  *
385                  * lat
386                  * lon
387                  * height
388                  */
389                 labels(layout, 0);
390                 height = new Height(layout, 1);
391                 speed = new Speed(layout, 2);
392                 accel = new Accel(layout, 3);
393                 lat = new Lat(layout, 4);
394                 lon = new Lon(layout, 5);
395                 apogee = new Apogee(layout, 6);
396                 main = new Main(layout, 7);
397         }
398 }