telegps: Fixup windows fat build harder
[fw/altos] / telegps / TeleGPSInfo.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 org.altusmetrum.telegps;
19
20 import java.awt.*;
21 import javax.swing.*;
22 import org.altusmetrum.altoslib_4.*;
23 import org.altusmetrum.altosuilib_2.*;
24
25 public class TeleGPSInfo extends JComponent implements AltosFlightDisplay {
26         GridBagLayout   layout;
27         JLabel                  cur, max;
28
29         public abstract class Info implements AltosFontListener, AltosUnitsListener {
30                 JLabel          label;
31                 JTextField      value;
32                 AltosLights     lights;
33                 double          v;
34                 AltosUnits      units;
35
36                 void show() {
37                         value.setVisible(true);
38                         lights.setVisible(true);
39                         label.setVisible(true);
40                 }
41
42                 void hide() {
43                         value.setVisible(false);
44                         lights.setVisible(false);
45                         label.setVisible(false);
46                 }
47
48                 abstract void show(AltosState state, AltosListenerState listener_state);
49
50                 void show(String s) {
51                         show();
52                         value.setText(s);
53                 }
54
55                 void show(double v) {
56                         this.v = v;
57                         show(units.show(8, v));
58                 }
59
60                 void show(String format, double v) {
61                         show(String.format(format, v));
62                 }
63
64                 void show(String format, int v) {
65                         show(String.format(format, v));
66                 }
67
68                 void reset() {
69                         lights.set(false);
70                         value.setText("");
71                 }
72
73                 public void font_size_changed(int font_size) {
74                         label.setFont(AltosUILib.label_font);
75                         value.setFont(AltosUILib.value_font);
76                 }
77
78                 public void units_changed(boolean imperial_units) {
79                         if (units != null)
80                                 show(v);
81                 }
82
83                 public Info (GridBagLayout layout, int y, AltosUnits units, String text) {
84                         this.units = units;
85
86                         GridBagConstraints      c = new GridBagConstraints();
87                         c.weighty = 1;
88
89                         lights = new AltosLights();
90                         c.gridx = 0; c.gridy = y;
91                         c.anchor = GridBagConstraints.CENTER;
92                         c.fill = GridBagConstraints.VERTICAL;
93                         c.weightx = 0;
94                         layout.setConstraints(lights, c);
95                         add(lights);
96
97                         label = new JLabel(text);
98                         label.setFont(AltosUILib.label_font);
99                         label.setHorizontalAlignment(SwingConstants.LEFT);
100                         c.gridx = 1; c.gridy = y;
101                         c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad);
102                         c.anchor = GridBagConstraints.WEST;
103                         c.fill = GridBagConstraints.VERTICAL;
104                         c.weightx = 0;
105                         layout.setConstraints(label, c);
106                         add(label);
107
108                         value = new JTextField(AltosUILib.text_width);
109                         value.setFont(AltosUILib.value_font);
110                         value.setHorizontalAlignment(SwingConstants.RIGHT);
111                         c.gridx = 2; c.gridy = y;
112                         c.gridwidth = 2;
113                         c.anchor = GridBagConstraints.WEST;
114                         c.fill = GridBagConstraints.BOTH;
115                         c.weightx = 1;
116                         layout.setConstraints(value, c);
117                         add(value);
118                 }
119
120                 public Info (GridBagLayout layout, int y, String text) {
121                         this(layout, y, null, text);
122                 }
123         }
124
125         public abstract class Value implements AltosFontListener, AltosUnitsListener {
126                 JLabel          label;
127                 JTextField      value;
128                 AltosUnits      units;
129                 double          v = AltosLib.MISSING;
130
131                 abstract void show(AltosState state, AltosListenerState listener_state);
132
133                 void reset() {
134                         value.setText("");
135                 }
136
137                 void show() {
138                         label.setVisible(true);
139                         value.setVisible(true);
140                 }
141
142                 void show(String s) {
143                         show();
144                         value.setText(s);
145                 }
146
147                 void show(double v) {
148                         this.v = v;
149                         show(units.show(8, v));
150                 }
151
152                 void show(String format, double v) {
153                         show(String.format(format, v));
154                 }
155
156                 void hide() {
157                         label.setVisible(false);
158                         value.setVisible(false);
159                 }
160                 public void font_size_changed(int font_size) {
161                         label.setFont(AltosUILib.label_font);
162                         value.setFont(AltosUILib.value_font);
163                 }
164                 public void units_changed(boolean imperial_units) {
165                         if (units != null)
166                                 show(v);
167                 }
168
169                 public Value (GridBagLayout layout, int y, String text) {
170                         GridBagConstraints      c = new GridBagConstraints();
171                         c.weighty = 1;
172
173                         label = new JLabel(text);
174                         label.setFont(AltosUILib.label_font);
175                         label.setHorizontalAlignment(SwingConstants.LEFT);
176                         c.gridx = 1; c.gridy = y;
177                         c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad);
178                         c.anchor = GridBagConstraints.WEST;
179                         c.fill = GridBagConstraints.VERTICAL;
180                         c.weightx = 0;
181                         layout.setConstraints(label, c);
182                         add(label);
183
184                         value = new JTextField(AltosUILib.text_width);
185                         value.setFont(AltosUILib.value_font);
186                         value.setHorizontalAlignment(SwingConstants.RIGHT);
187                         c.gridx = 2; c.gridy = y;
188                         c.anchor = GridBagConstraints.WEST;
189                         c.fill = GridBagConstraints.BOTH;
190                         c.gridwidth = 2;
191                         c.weightx = 1;
192                         layout.setConstraints(value, c);
193                         add(value);
194                 }
195         }
196
197         public abstract class DualValue implements AltosFontListener, AltosUnitsListener {
198                 AltosLights     lights;
199                 JLabel          label;
200                 JTextField      value1;
201                 JTextField      value2;
202
203                 void reset() {
204                         if (lights != null)
205                                 lights.set(false);
206                         value1.setText("");
207                         value2.setText("");
208                 }
209
210                 void show() {
211                         if (lights != null)
212                                 lights.setVisible(true);
213                         label.setVisible(true);
214                         value1.setVisible(true);
215                         value2.setVisible(true);
216                 }
217
218                 void hide() {
219                         if (lights != null)
220                                 lights.setVisible(false);
221                         label.setVisible(false);
222                         value1.setVisible(false);
223                         value2.setVisible(false);
224                 }
225
226                 public void font_size_changed(int font_size) {
227                         label.setFont(AltosUILib.label_font);
228                         value1.setFont(AltosUILib.value_font);
229                         value2.setFont(AltosUILib.value_font);
230                 }
231
232                 public void units_changed(boolean imperial_units) {
233                 }
234
235                 abstract void show(AltosState state, AltosListenerState listener_state);
236
237                 void show(String v1, String v2) {
238                         show();
239                         value1.setText(v1);
240                         value2.setText(v2);
241                 }
242
243                 void show(String f1, double v1, String f2, double v2) {
244                         show();
245                         value1.setText(String.format(f1, v1));
246                         value2.setText(String.format(f2, v2));
247                 }
248
249                 void show(String f1, int v1, String f2, int v2) {
250                         show();
251                         value1.setText(String.format(f1, v1));
252                         value2.setText(String.format(f2, v2));
253                 }
254
255                 public DualValue (GridBagLayout layout, int y, String text, boolean want_lights) {
256                         GridBagConstraints      c = new GridBagConstraints();
257                         c.weighty = 1;
258
259                         if (want_lights) {
260                                 lights = new AltosLights();
261                                 c.gridx = 0; c.gridy = y;
262                                 c.anchor = GridBagConstraints.CENTER;
263                                 c.fill = GridBagConstraints.VERTICAL;
264                                 c.weightx = 0;
265                                 layout.setConstraints(lights, c);
266                                 add(lights);
267                         }
268
269                         label = new JLabel(text);
270                         label.setFont(AltosUILib.label_font);
271                         label.setHorizontalAlignment(SwingConstants.LEFT);
272                         c.gridx = 1; c.gridy = y;
273                         c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad);
274                         c.anchor = GridBagConstraints.WEST;
275                         c.fill = GridBagConstraints.VERTICAL;
276                         c.weightx = 0;
277                         layout.setConstraints(label, c);
278                         add(label);
279
280                         value1 = new JTextField(AltosUILib.text_width);
281                         value1.setFont(AltosUILib.value_font);
282                         value1.setHorizontalAlignment(SwingConstants.RIGHT);
283                         c.gridx = 2; c.gridy = y;
284                         c.anchor = GridBagConstraints.WEST;
285                         c.fill = GridBagConstraints.BOTH;
286                         c.weightx = 1;
287                         layout.setConstraints(value1, c);
288                         add(value1);
289
290                         value2 = new JTextField(AltosUILib.text_width);
291                         value2.setFont(AltosUILib.value_font);
292                         value2.setHorizontalAlignment(SwingConstants.RIGHT);
293                         c.gridx = 3; c.gridy = y;
294                         c.anchor = GridBagConstraints.WEST;
295                         c.fill = GridBagConstraints.BOTH;
296                         c.weightx = 1;
297                         c.gridwidth = 1;
298                         layout.setConstraints(value2, c);
299                         add(value2);
300                 }
301         }
302
303         abstract public class ValueHold implements AltosFontListener, AltosUnitsListener {
304                 JLabel          label;
305                 JTextField      value;
306                 JTextField      max_value;
307                 double          v;
308                 double          max;
309                 AltosUnits      units;
310
311                 abstract void show(AltosState state, AltosListenerState listener_state);
312
313                 void reset() {
314                         value.setText("");
315                         max_value.setText("");
316                         max = AltosLib.MISSING;
317                 }
318
319                 public void font_size_changed(int font_size) {
320                         label.setFont(AltosUILib.label_font);
321                         value.setFont(AltosUILib.value_font);
322                         max_value.setFont(AltosUILib.value_font);
323                 }
324
325                 public void units_changed(boolean imperial_units) {
326                         show(v);
327                 }
328
329                 void show(double v) {
330                         this.v = v;
331                         if (v == AltosLib.MISSING) {
332                                 value.setText("Missing");
333                         } else {
334                                 value.setText(units.show(8, v));
335                                 if (v > max || max == AltosLib.MISSING)
336                                         max = v;
337                         }
338                         if (max == AltosLib.MISSING)
339                                 max_value.setText("Missing");
340                         else
341                                 max_value.setText(units.show(8, max));
342                 }
343
344                 void hide() {
345                         label.setVisible(false);
346                         value.setVisible(false);
347                         max_value.setVisible(false);
348                 }
349
350                 public ValueHold (GridBagLayout layout, int y, AltosUnits units, String text) {
351                         this.units = units;
352                         GridBagConstraints      c = new GridBagConstraints();
353                         c.weighty = 1;
354
355                         label = new JLabel(text);
356                         label.setFont(AltosUILib.label_font);
357                         label.setHorizontalAlignment(SwingConstants.LEFT);
358                         c.gridx = 1; c.gridy = y;
359                         c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad);
360                         c.anchor = GridBagConstraints.WEST;
361                         c.fill = GridBagConstraints.VERTICAL;
362                         c.weightx = 0;
363                         layout.setConstraints(label, c);
364                         add(label);
365
366                         value = new JTextField(AltosUILib.text_width);
367                         value.setFont(AltosUILib.value_font);
368                         value.setHorizontalAlignment(SwingConstants.RIGHT);
369                         c.gridx = 2; c.gridy = y;
370                         c.anchor = GridBagConstraints.EAST;
371                         c.fill = GridBagConstraints.BOTH;
372                         c.weightx = 1;
373                         layout.setConstraints(value, c);
374                         add(value);
375
376                         max_value = new JTextField(AltosUILib.text_width);
377                         max_value.setFont(AltosUILib.value_font);
378                         max_value.setHorizontalAlignment(SwingConstants.RIGHT);
379                         c.gridx = 3; c.gridy = y;
380                         c.anchor = GridBagConstraints.EAST;
381                         c.fill = GridBagConstraints.BOTH;
382                         c.weightx = 1;
383                         layout.setConstraints(max_value, c);
384                         add(max_value);
385                 }
386         }
387
388
389         class Altitude extends ValueHold {
390                 void show (AltosState state, AltosListenerState listener_state) {
391                         show(state.altitude());
392                 }
393                 public Altitude (GridBagLayout layout, int y) {
394                         super (layout, y, AltosConvert.height, "Altitude");
395                 }
396         }
397
398         Altitude        altitude;
399
400         class AscentRate extends ValueHold {
401                 void show (AltosState state, AltosListenerState listener_state) {
402                         show(state.gps_ascent_rate());
403                 }
404                 public AscentRate (GridBagLayout layout, int y) {
405                         super (layout, y, AltosConvert.speed, "Ascent Rate");
406                 }
407         }
408
409         AscentRate      ascent_rate;
410
411         class GroundSpeed extends ValueHold {
412                 void show (AltosState state, AltosListenerState listener_state) {
413                         show(state.gps_ground_speed());
414                 }
415                 public GroundSpeed (GridBagLayout layout, int y) {
416                         super (layout, y, AltosConvert.speed, "Ground Speed");
417                 }
418         }
419
420         GroundSpeed     ground_speed;
421
422         String pos(double p, String pos, String neg) {
423                 String  h = pos;
424                 if (p < 0) {
425                         h = neg;
426                         p = -p;
427                 }
428                 int deg = (int) Math.floor(p);
429                 double min = (p - Math.floor(p)) * 60.0;
430                 return String.format("%s %4d° %9.6f", h, deg, min);
431         }
432
433         class Course extends DualValue {
434                 void show (AltosState state, AltosListenerState listener_state) {
435                         double  course = state.gps_course();
436                         if (course != AltosLib.MISSING)
437                                 show( String.format("%3.0f°", course),
438                                       AltosConvert.bearing_to_words(
439                                               AltosConvert.BEARING_LONG,
440                                               course));
441                 }
442                 public Course (GridBagLayout layout, int y) {
443                         super (layout, y, "Course", false);
444                 }
445         }
446
447         Course          course;
448
449         class Lat extends Value {
450                 void show (AltosState state, AltosListenerState listener_state) {
451                         if (state.gps != null && state.gps.connected && state.gps.lat != AltosLib.MISSING)
452                                 show(pos(state.gps.lat,"N", "S"));
453                         else
454                                 show("???");
455                 }
456                 public Lat (GridBagLayout layout, int y) {
457                         super (layout, y, "Latitude");
458                 }
459         }
460
461         Lat lat;
462
463         class Lon extends Value {
464                 void show (AltosState state, AltosListenerState listener_state) {
465                         if (state.gps != null && state.gps.connected && state.gps.lon != AltosLib.MISSING)
466                                 show(pos(state.gps.lon,"E", "W"));
467                         else
468                                 show("???");
469                 }
470                 public Lon (GridBagLayout layout, int y) {
471                         super (layout, y, "Longitude");
472                 }
473         }
474
475         Lon lon;
476
477         class GPSLocked extends DualValue {
478                 void show (AltosState state, AltosListenerState listener_state) {
479                         if (state == null || state.gps == null)
480                                 hide();
481                         else {
482                                 int soln = state.gps.nsat;
483                                 int nsat = state.gps.cc_gps_sat != null ? state.gps.cc_gps_sat.length : 0;
484                                 show("%4d in solution", soln,
485                                      "%4d in view", nsat);
486                                 lights.set(state.gps.locked && soln >= 4);
487                         }
488                 }
489                 public GPSLocked (GridBagLayout layout, int y) {
490                         super (layout, y, "GPS Locked", true);
491                 }
492         }
493
494         GPSLocked gps_locked;
495
496         public void reset() {
497                 lat.reset();
498                 lon.reset();
499                 altitude.reset();
500                 ground_speed.reset();
501                 ascent_rate.reset();
502                 course.reset();
503                 gps_locked.reset();
504         }
505
506         public void font_size_changed(int font_size) {
507                 cur.setFont(AltosUILib.label_font);
508                 max.setFont(AltosUILib.label_font);
509                 lat.font_size_changed(font_size);
510                 lon.font_size_changed(font_size);
511                 altitude.font_size_changed(font_size);
512                 ground_speed.font_size_changed(font_size);
513                 ascent_rate.font_size_changed(font_size);
514                 course.font_size_changed(font_size);
515                 gps_locked.font_size_changed(font_size);
516         }
517
518         public void units_changed(boolean imperial_units) {
519                 lat.units_changed(imperial_units);
520                 lon.units_changed(imperial_units);
521                 altitude.units_changed(imperial_units);
522                 ground_speed.units_changed(imperial_units);
523                 ascent_rate.units_changed(imperial_units);
524                 course.units_changed(imperial_units);
525                 gps_locked.units_changed(imperial_units);
526         }
527
528         public void show(AltosState state, AltosListenerState listener_state) {
529                 if (state.gps != null && state.gps.connected) {
530                         lat.show(state, listener_state);
531                         lon.show(state, listener_state);
532                 } else {
533                         lat.hide();
534                         lon.hide();
535                 }
536                 altitude.show(state, listener_state);
537                 ground_speed.show(state, listener_state);
538                 ascent_rate.show(state, listener_state);
539                 course.show(state, listener_state);
540                 gps_locked.show(state, listener_state);
541         }
542
543         public void labels(GridBagLayout layout, int y) {
544                 GridBagConstraints      c;
545
546                 cur = new JLabel("Current");
547                 cur.setFont(AltosUILib.label_font);
548                 c = new GridBagConstraints();
549                 c.gridx = 2; c.gridy = y;
550                 c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad);
551                 layout.setConstraints(cur, c);
552                 add(cur);
553
554                 max = new JLabel("Maximum");
555                 max.setFont(AltosUILib.label_font);
556                 c.gridx = 3; c.gridy = y;
557                 layout.setConstraints(max, c);
558                 add(max);
559         }
560
561         public String getName() {
562                 return "Info";
563         }
564
565         public TeleGPSInfo() {
566                 layout = new GridBagLayout();
567
568                 setLayout(layout);
569
570                 /* Elements in ascent display:
571                  *
572                  * lat
573                  * lon
574                  * height
575                  */
576                 int y = 0;
577                 labels(layout, y++);
578                 altitude = new Altitude(layout, y++);
579                 ground_speed = new GroundSpeed(layout, y++);
580                 ascent_rate = new AscentRate(layout, y++);
581                 course = new Course(layout, y++);
582                 lat = new Lat(layout, y++);
583                 lon = new Lon(layout, y++);
584                 gps_locked = new GPSLocked(layout, y++);
585         }
586 }