2 * Copyright © 2011 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.
21 import java.awt.event.*;
23 import javax.swing.filechooser.FileNameExtensionFilter;
24 import javax.swing.table.*;
25 import javax.swing.event.*;
29 import java.util.prefs.*;
30 import java.util.concurrent.LinkedBlockingQueue;
32 public class AltosTerra
34 implements ActionListener
39 JButton prev, next, enter;
41 static final int info_tab = 1;
42 static final int pad_tab = 2;
43 static final int ascent_tab = 3;
44 static final int descent_tab = 4;
45 static final int landing_tab = 5;
49 AltosState current_state;
51 public void actionPerformed(ActionEvent e) {
52 String cmd = e.getActionCommand();
53 if (cmd.equals("prev")) {
54 displayed_tab = displayed_tab - 1;
55 if (displayed_tab < info_tab)
56 displayed_tab = landing_tab;
59 if (cmd.equals("next")) {
60 displayed_tab = displayed_tab + 1;
61 if (displayed_tab > landing_tab)
62 displayed_tab = info_tab;
67 int which_tab(AltosState state) {
68 if (state.state < Altos.ao_flight_boost)
70 if (state.state <= Altos.ao_flight_coast)
72 if (state.state <= Altos.ao_flight_main)
77 String[] lines = { "", "" };
79 public void setLine(int line, String format, Object... args) {
80 lines[line] = String.format(format, args);
81 String result = lines[0].concat("\n").concat(lines[1]);
82 text_area.setText(result);
85 public int state_char(AltosState state) {
86 switch (state.state) {
87 case Altos.ao_flight_startup: return 'S';
88 case Altos.ao_flight_idle: return 'I';
89 case Altos.ao_flight_pad: return 'P';
90 case Altos.ao_flight_boost: return 'B';
91 case Altos.ao_flight_fast: return 'F';
92 case Altos.ao_flight_coast: return 'C';
93 case Altos.ao_flight_drogue: return 'D';
94 case Altos.ao_flight_main: return 'M';
95 case Altos.ao_flight_landed: return 'L';
97 case Altos.ao_flight_invalid: return '*';
101 int boolchar(boolean b) {
107 String pos(double p, String pos, String neg) {
113 int deg = (int) Math.floor(p);
114 double min = (p - Math.floor(p)) * 60.0;
115 return String.format("%s%3d°%9.6f'", h, deg, min);
118 public void display() {
119 double speed = current_state.speed;
120 if (!current_state.ascent)
121 speed = current_state.baro_speed;
123 switch (displayed_tab) {
126 setLine(0, "%-7sN %-5d %c",
127 current_state.data.callsign,
128 current_state.data.serial,
129 state_char(current_state));
130 setLine(1, "F %-4d RSSI %3d",
131 current_state.data.flight,
132 current_state.data.rssi);
135 setLine(0, "D%c M%c B%c G%c %c",
136 boolchar(current_state.drogue_sense > 3.2),
137 boolchar(current_state.main_sense > 3.2),
138 boolchar(current_state.battery > 3.7),
139 boolchar(current_state.gps.locked),
140 state_char(current_state));
141 setLine(1, "SAT %2d RSSI %3d",
142 current_state.gps.nsat,
143 current_state.data.rssi);
146 setLine(0, "S:%5d S⌈%5d%c",
147 (int) Math.floor(speed + 0.5),
148 (int) Math.floor(current_state.max_speed + 0.5),
149 state_char(current_state));
150 setLine(1, "H:%5d H⌈%5d",
151 (int) Math.floor(current_state.height + 0.5),
152 (int) Math.floor(current_state.max_height + 0.5));
155 setLine(0, "→%5d ↑%5d %c",
156 (int) Math.floor (current_state.from_pad.bearing + 0.5),
157 (int) Math.floor (current_state.elevation + 0.5),
158 state_char(current_state));
159 setLine(1, "H%5d S%5d",
160 (int) Math.floor(current_state.height + 0.5),
161 (int) Math.floor(speed + 0.5));
164 setLine(0, "%s%c", pos(current_state.gps.lat, "N", "S"),
165 state_char(current_state));
166 setLine(1, "%s", pos(current_state.gps.lon, "E", "W"));
170 public void display(AltosState state) {
171 int tab = which_tab(state);
172 if (tab != current_tab)
173 current_tab = displayed_tab = tab;
174 current_state = state;
178 public AltosTerra(JFrame in_owner) {
179 super(in_owner, "AltosTerra", false);
181 GridBagConstraints c;
183 Insets insets = new Insets(4,4,4,4);
187 pane = getContentPane();
188 pane.setLayout(new GridBagLayout());
190 c = new GridBagConstraints();
192 c.fill = GridBagConstraints.NONE;
193 c.anchor = GridBagConstraints.WEST;
195 text_area = new JTextArea(2, 16);
196 text_area.setFont(new Font("Monospaced", Font.PLAIN, 22));
197 text_area.setEditable(false);
204 c.fill = GridBagConstraints.NONE;
205 c.anchor = GridBagConstraints.CENTER;
206 pane.add(text_area, c);
209 prev = new JButton("Prev");
210 prev.addActionListener(this);
211 prev.setActionCommand("prev");
216 c.fill = GridBagConstraints.BOTH;
217 c.anchor = GridBagConstraints.CENTER;
221 next = new JButton("Next");
222 next.addActionListener(this);
223 next.setActionCommand("next");
228 c.fill = GridBagConstraints.BOTH;
229 c.anchor = GridBagConstraints.CENTER;
233 enter = new JButton("Enter");
234 enter.addActionListener(this);
235 enter.setActionCommand("enter");
240 c.fill = GridBagConstraints.BOTH;
241 c.anchor = GridBagConstraints.CENTER;