2 * Copyright © 2010 Keith Packard <keithp@keithp.com>
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.
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.
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.
18 package org.altusmetrum.telegps;
21 import java.awt.event.*;
23 import org.altusmetrum.altoslib_4.*;
24 import org.altusmetrum.altosuilib_2.*;
26 public class TeleGPSInfo extends JComponent implements AltosFlightDisplay, HierarchyListener {
30 private AltosState last_state;
31 private AltosListenerState last_listener_state;
33 public abstract class Info implements AltosFontListener, AltosUnitsListener {
41 value.setVisible(true);
42 lights.setVisible(true);
43 label.setVisible(true);
47 value.setVisible(false);
48 lights.setVisible(false);
49 label.setVisible(false);
52 abstract void show(AltosState state, AltosListenerState listener_state);
61 show(units.show(8, v));
64 void show(String format, double v) {
65 show(String.format(format, v));
68 void show(String format, int v) {
69 show(String.format(format, v));
77 public void font_size_changed(int font_size) {
78 label.setFont(AltosUILib.label_font);
79 value.setFont(AltosUILib.value_font);
82 public void units_changed(boolean imperial_units) {
87 public Info (GridBagLayout layout, int y, AltosUnits units, String text) {
90 GridBagConstraints c = new GridBagConstraints();
93 lights = new AltosLights();
94 c.gridx = 0; c.gridy = y;
95 c.anchor = GridBagConstraints.CENTER;
96 c.fill = GridBagConstraints.VERTICAL;
98 layout.setConstraints(lights, c);
101 label = new JLabel(text);
102 label.setFont(AltosUILib.label_font);
103 label.setHorizontalAlignment(SwingConstants.LEFT);
104 c.gridx = 1; c.gridy = y;
105 c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad);
106 c.anchor = GridBagConstraints.WEST;
107 c.fill = GridBagConstraints.VERTICAL;
109 layout.setConstraints(label, c);
112 value = new JTextField(AltosUILib.text_width);
113 value.setFont(AltosUILib.value_font);
114 value.setHorizontalAlignment(SwingConstants.RIGHT);
115 c.gridx = 2; c.gridy = y;
117 c.anchor = GridBagConstraints.WEST;
118 c.fill = GridBagConstraints.BOTH;
120 layout.setConstraints(value, c);
124 public Info (GridBagLayout layout, int y, String text) {
125 this(layout, y, null, text);
129 public abstract class Value implements AltosFontListener, AltosUnitsListener {
133 double v = AltosLib.MISSING;
135 abstract void show(AltosState state, AltosListenerState listener_state);
142 label.setVisible(true);
143 value.setVisible(true);
146 void show(String s) {
151 void show(double v) {
153 show(units.show(8, v));
156 void show(String format, double v) {
157 show(String.format(format, v));
161 label.setVisible(false);
162 value.setVisible(false);
164 public void font_size_changed(int font_size) {
165 label.setFont(AltosUILib.label_font);
166 value.setFont(AltosUILib.value_font);
168 public void units_changed(boolean imperial_units) {
173 public Value (GridBagLayout layout, int y, String text) {
174 GridBagConstraints c = new GridBagConstraints();
177 label = new JLabel(text);
178 label.setFont(AltosUILib.label_font);
179 label.setHorizontalAlignment(SwingConstants.LEFT);
180 c.gridx = 1; c.gridy = y;
181 c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad);
182 c.anchor = GridBagConstraints.WEST;
183 c.fill = GridBagConstraints.VERTICAL;
185 layout.setConstraints(label, c);
188 value = new JTextField(AltosUILib.text_width);
189 value.setFont(AltosUILib.value_font);
190 value.setHorizontalAlignment(SwingConstants.RIGHT);
191 c.gridx = 2; c.gridy = y;
192 c.anchor = GridBagConstraints.WEST;
193 c.fill = GridBagConstraints.BOTH;
196 layout.setConstraints(value, c);
201 public abstract class DualValue implements AltosFontListener, AltosUnitsListener {
216 lights.setVisible(true);
217 label.setVisible(true);
218 value1.setVisible(true);
219 value2.setVisible(true);
224 lights.setVisible(false);
225 label.setVisible(false);
226 value1.setVisible(false);
227 value2.setVisible(false);
230 public void font_size_changed(int font_size) {
231 label.setFont(AltosUILib.label_font);
232 value1.setFont(AltosUILib.value_font);
233 value2.setFont(AltosUILib.value_font);
236 public void units_changed(boolean imperial_units) {
239 abstract void show(AltosState state, AltosListenerState listener_state);
241 void show(String v1, String v2) {
247 void show(String f1, double v1, String f2, double v2) {
249 value1.setText(String.format(f1, v1));
250 value2.setText(String.format(f2, v2));
253 void show(String f1, int v1, String f2, int v2) {
255 value1.setText(String.format(f1, v1));
256 value2.setText(String.format(f2, v2));
259 public DualValue (GridBagLayout layout, int y, String text, boolean want_lights) {
260 GridBagConstraints c = new GridBagConstraints();
264 lights = new AltosLights();
265 c.gridx = 0; c.gridy = y;
266 c.anchor = GridBagConstraints.CENTER;
267 c.fill = GridBagConstraints.VERTICAL;
269 layout.setConstraints(lights, c);
273 label = new JLabel(text);
274 label.setFont(AltosUILib.label_font);
275 label.setHorizontalAlignment(SwingConstants.LEFT);
276 c.gridx = 1; c.gridy = y;
277 c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad);
278 c.anchor = GridBagConstraints.WEST;
279 c.fill = GridBagConstraints.VERTICAL;
281 layout.setConstraints(label, c);
284 value1 = new JTextField(AltosUILib.text_width);
285 value1.setFont(AltosUILib.value_font);
286 value1.setHorizontalAlignment(SwingConstants.RIGHT);
287 value1.setEditable(false);
288 c.gridx = 2; c.gridy = y;
289 c.anchor = GridBagConstraints.WEST;
290 c.fill = GridBagConstraints.BOTH;
292 layout.setConstraints(value1, c);
295 value2 = new JTextField(AltosUILib.text_width);
296 value2.setFont(AltosUILib.value_font);
297 value2.setHorizontalAlignment(SwingConstants.RIGHT);
298 value1.setEditable(false);
299 c.gridx = 3; c.gridy = y;
300 c.anchor = GridBagConstraints.WEST;
301 c.fill = GridBagConstraints.BOTH;
304 layout.setConstraints(value2, c);
309 abstract public class ValueHold implements AltosFontListener, AltosUnitsListener {
312 JTextField max_value;
317 abstract void show(AltosState state, AltosListenerState listener_state);
321 max_value.setText("");
322 max = AltosLib.MISSING;
325 public void font_size_changed(int font_size) {
326 label.setFont(AltosUILib.label_font);
327 value.setFont(AltosUILib.value_font);
328 max_value.setFont(AltosUILib.value_font);
331 public void units_changed(boolean imperial_units) {
335 void show(double v, double max) {
338 if (v == AltosLib.MISSING)
339 value.setText("Missing");
341 value.setText(units.show(8, v));
342 if (max == AltosLib.MISSING)
343 max_value.setText("Missing");
345 max_value.setText(units.show(8, max));
349 label.setVisible(false);
350 value.setVisible(false);
351 max_value.setVisible(false);
354 public ValueHold (GridBagLayout layout, int y, AltosUnits units, String text) {
356 GridBagConstraints c = new GridBagConstraints();
359 label = new JLabel(text);
360 label.setFont(AltosUILib.label_font);
361 label.setHorizontalAlignment(SwingConstants.LEFT);
362 c.gridx = 1; c.gridy = y;
363 c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad);
364 c.anchor = GridBagConstraints.WEST;
365 c.fill = GridBagConstraints.VERTICAL;
367 layout.setConstraints(label, c);
370 value = new JTextField(AltosUILib.text_width);
371 value.setEditable(false);
372 value.setFont(AltosUILib.value_font);
373 value.setHorizontalAlignment(SwingConstants.RIGHT);
374 c.gridx = 2; c.gridy = y;
375 c.anchor = GridBagConstraints.EAST;
376 c.fill = GridBagConstraints.BOTH;
378 layout.setConstraints(value, c);
381 max_value = new JTextField(AltosUILib.text_width);
382 max_value.setEditable(false);
383 max_value.setFont(AltosUILib.value_font);
384 max_value.setHorizontalAlignment(SwingConstants.RIGHT);
385 c.gridx = 3; c.gridy = y;
386 c.anchor = GridBagConstraints.EAST;
387 c.fill = GridBagConstraints.BOTH;
389 layout.setConstraints(max_value, c);
395 class Altitude extends ValueHold {
396 void show (AltosState state, AltosListenerState listener_state) {
397 show(state.altitude(), state.max_altitude());
399 public Altitude (GridBagLayout layout, int y) {
400 super (layout, y, AltosConvert.height, "Altitude");
406 class AscentRate extends ValueHold {
407 void show (AltosState state, AltosListenerState listener_state) {
408 show(state.gps_ascent_rate(), state.max_gps_ascent_rate());
410 public AscentRate (GridBagLayout layout, int y) {
411 super (layout, y, AltosConvert.speed, "Ascent Rate");
415 AscentRate ascent_rate;
417 class GroundSpeed extends ValueHold {
418 void show (AltosState state, AltosListenerState listener_state) {
419 show(state.gps_ground_speed(), state.max_gps_ground_speed());
421 public GroundSpeed (GridBagLayout layout, int y) {
422 super (layout, y, AltosConvert.speed, "Ground Speed");
426 GroundSpeed ground_speed;
428 String pos(double p, String pos, String neg) {
434 int deg = (int) Math.floor(p);
435 double min = (p - Math.floor(p)) * 60.0;
436 return String.format("%s %4d° %9.6f", h, deg, min);
439 class Course extends DualValue {
440 void show (AltosState state, AltosListenerState listener_state) {
441 double course = state.gps_course();
442 if (course != AltosLib.MISSING)
443 show( String.format("%3.0f°", course),
444 AltosConvert.bearing_to_words(
445 AltosConvert.BEARING_LONG,
448 public Course (GridBagLayout layout, int y) {
449 super (layout, y, "Course", false);
455 class Lat extends Value {
456 void show (AltosState state, AltosListenerState listener_state) {
457 if (state.gps != null && state.gps.connected && state.gps.lat != AltosLib.MISSING)
458 show(pos(state.gps.lat,"N", "S"));
462 public Lat (GridBagLayout layout, int y) {
463 super (layout, y, "Latitude");
469 class Lon extends Value {
470 void show (AltosState state, AltosListenerState listener_state) {
471 if (state.gps != null && state.gps.connected && state.gps.lon != AltosLib.MISSING)
472 show(pos(state.gps.lon,"E", "W"));
476 public Lon (GridBagLayout layout, int y) {
477 super (layout, y, "Longitude");
483 class GPSLocked extends DualValue {
484 void show (AltosState state, AltosListenerState listener_state) {
485 if (state == null || state.gps == null)
488 int soln = state.gps.nsat;
489 int nsat = state.gps.cc_gps_sat != null ? state.gps.cc_gps_sat.length : 0;
490 show("%4d in solution", soln,
491 "%4d in view", nsat);
492 lights.set(state.gps.locked && soln >= 4);
495 public GPSLocked (GridBagLayout layout, int y) {
496 super (layout, y, "GPS Locked", true);
500 GPSLocked gps_locked;
502 public void reset() {
506 ground_speed.reset();
512 public void font_size_changed(int font_size) {
513 cur.setFont(AltosUILib.label_font);
514 max.setFont(AltosUILib.label_font);
515 lat.font_size_changed(font_size);
516 lon.font_size_changed(font_size);
517 altitude.font_size_changed(font_size);
518 ground_speed.font_size_changed(font_size);
519 ascent_rate.font_size_changed(font_size);
520 course.font_size_changed(font_size);
521 gps_locked.font_size_changed(font_size);
524 public void units_changed(boolean imperial_units) {
525 lat.units_changed(imperial_units);
526 lon.units_changed(imperial_units);
527 altitude.units_changed(imperial_units);
528 ground_speed.units_changed(imperial_units);
529 ascent_rate.units_changed(imperial_units);
530 course.units_changed(imperial_units);
531 gps_locked.units_changed(imperial_units);
534 public void show(AltosState state, AltosListenerState listener_state) {
537 last_listener_state = listener_state;
541 if (state.gps != null && state.gps.connected) {
542 lat.show(state, listener_state);
543 lon.show(state, listener_state);
548 altitude.show(state, listener_state);
549 ground_speed.show(state, listener_state);
550 ascent_rate.show(state, listener_state);
551 course.show(state, listener_state);
552 gps_locked.show(state, listener_state);
555 public void labels(GridBagLayout layout, int y) {
556 GridBagConstraints c;
558 cur = new JLabel("Current");
559 cur.setFont(AltosUILib.label_font);
560 c = new GridBagConstraints();
561 c.gridx = 2; c.gridy = y;
562 c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad);
563 layout.setConstraints(cur, c);
566 max = new JLabel("Maximum");
567 max.setFont(AltosUILib.label_font);
568 c.gridx = 3; c.gridy = y;
569 layout.setConstraints(max, c);
573 public String getName() {
577 public void hierarchyChanged(HierarchyEvent e) {
578 if (last_state != null && isShowing()) {
579 AltosState state = last_state;
580 AltosListenerState listener_state = last_listener_state;
583 last_listener_state = null;
584 show(state, listener_state);
588 public TeleGPSInfo() {
589 layout = new GridBagLayout();
593 /* Elements in ascent display:
601 altitude = new Altitude(layout, y++);
602 ground_speed = new GroundSpeed(layout, y++);
603 ascent_rate = new AscentRate(layout, y++);
604 course = new Course(layout, y++);
605 lat = new Lat(layout, y++);
606 lon = new Lon(layout, y++);
607 gps_locked = new GPSLocked(layout, y++);
608 addHierarchyListener(this);