20ad137f62e5d19c017ac7d6db92be0a1e4df615
[fw/altos] / altosui / AltosTerra.java
1 /*
2  * Copyright © 2011 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 javax.swing.event.*;
26 import java.io.*;
27 import java.util.*;
28 import java.text.*;
29 import java.util.prefs.*;
30 import java.util.concurrent.LinkedBlockingQueue;
31
32 public class AltosTerra
33         extends JDialog
34         implements ActionListener
35 {
36         JFrame          owner;
37         JTextArea       text_area;
38         Container       pane;
39         JButton         prev, next, enter;
40
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;
46
47         int             current_tab;
48         int             displayed_tab;
49         AltosState      current_state;
50
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;
57                         display();
58                 }
59                 if (cmd.equals("next")) {
60                         displayed_tab = displayed_tab + 1;
61                         if (displayed_tab > landing_tab)
62                                 displayed_tab = info_tab;
63                         display();
64                 }
65         }
66
67         int which_tab(AltosState state) {
68                 if (state.state < Altos.ao_flight_boost)
69                         return pad_tab;
70                 if (state.state <= Altos.ao_flight_coast)
71                         return ascent_tab;
72                 if (state.state <= Altos.ao_flight_main)
73                         return descent_tab;
74                 return landing_tab;
75         }
76
77         String[]        lines = { "", "" };
78
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);
83         }
84
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';
96                 default:
97                 case Altos.ao_flight_invalid: return '*';
98                 }
99         }
100
101         int boolchar(boolean b) {
102                 if (b)
103                         return '+';
104                 return ' ';
105         }
106
107         String pos(double p, String pos, String neg) {
108                 String  h = pos;
109                 if (p < 0) {
110                         h = neg;
111                         p = -p;
112                 }
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);
116         }
117
118         public void display() {
119                 switch (displayed_tab) {
120                 default:
121                 case info_tab:
122                         setLine(0, "%-7sN %-5d %c",
123                                 current_state.data.callsign,
124                                 current_state.data.serial,
125                                 state_char(current_state));
126                         setLine(1, "F %-4d RSSI %3d",
127                                 current_state.data.flight,
128                                 current_state.data.rssi);
129                         break;
130                 case pad_tab:
131                         setLine(0, "D%c  M%c  B%c  G%c %c",
132                                 boolchar(current_state.drogue_sense > 3.2),
133                                 boolchar(current_state.main_sense > 3.2),
134                                 boolchar(current_state.battery > 3.7),
135                                 boolchar(current_state.gps.locked),
136                                 state_char(current_state));
137                         setLine(1, "SAT %2d RSSI %3d",
138                                 current_state.gps.nsat,
139                                 current_state.data.rssi);
140                         break;
141                 case ascent_tab:
142                         setLine(0, "S:%5d S⌈%5d%c",
143                                 (int) Math.floor(current_state.speed + 0.5),
144                                 (int) Math.floor(current_state.max_speed + 0.5),
145                                 state_char(current_state));
146                         setLine(1, "H:%5d H⌈%5d",
147                                 (int) Math.floor(current_state.height + 0.5),
148                                 (int) Math.floor(current_state.max_height + 0.5));
149                         break;
150                 case descent_tab:
151                         setLine(0, "→%5d  ↑%5d %c",
152                                 (int) Math.floor (current_state.from_pad.bearing + 0.5),
153                                 (int) Math.floor (current_state.elevation + 0.5),
154                                 state_char(current_state));
155                         setLine(1, "H%5d  S%5d",
156                                 (int) Math.floor(current_state.height + 0.5),
157                                 (int) Math.floor(current_state.baro_speed + 0.5));
158                         break;
159                 case landing_tab:
160                         setLine(0, "%s%c", pos(current_state.gps.lat, "N", "S"),
161                                 state_char(current_state));
162                         setLine(1, "%s", pos(current_state.gps.lon, "E", "W"));
163                 }
164         }
165
166         public void display(AltosState state) {
167                 int     tab = which_tab(state);
168                 if (tab != current_tab)
169                         current_tab = displayed_tab = tab;
170                 current_state = state;
171                 display();
172         }
173
174         public AltosTerra(JFrame in_owner) {
175                 super(in_owner, "AltosTerra", false);
176
177                 GridBagConstraints      c;
178
179                 Insets  insets = new Insets(4,4,4,4);
180
181                 owner = in_owner;
182
183                 pane = getContentPane();
184                 pane.setLayout(new GridBagLayout());
185                 
186                 c = new GridBagConstraints();
187                 c.insets = insets;
188                 c.fill = GridBagConstraints.NONE;
189                 c.anchor = GridBagConstraints.WEST;
190
191                 text_area = new JTextArea(2, 16);
192                 text_area.setFont(new Font("Monospaced", Font.PLAIN, 22));
193                 text_area.setEditable(false);
194
195                 /* Text area */
196                 c.gridx = 0;
197                 c.gridy = 0;
198                 c.gridwidth = 1;
199                 c.gridheight = 3;
200                 c.fill = GridBagConstraints.NONE;
201                 c.anchor = GridBagConstraints.CENTER;
202                 pane.add(text_area, c);
203
204                 /* Prev button */
205                 prev = new JButton("Prev");
206                 prev.addActionListener(this);
207                 prev.setActionCommand("prev");
208                 c.gridx = 1;
209                 c.gridy = 0;
210                 c.gridwidth = 1;
211                 c.gridheight = 1;
212                 c.fill = GridBagConstraints.BOTH;
213                 c.anchor = GridBagConstraints.CENTER;
214                 pane.add(prev, c);
215
216                 /* Next button */
217                 next = new JButton("Next");
218                 next.addActionListener(this);
219                 next.setActionCommand("next");
220                 c.gridx = 1;
221                 c.gridy = 1;
222                 c.gridwidth = 1;
223                 c.gridheight = 1;
224                 c.fill = GridBagConstraints.BOTH;
225                 c.anchor = GridBagConstraints.CENTER;
226                 pane.add(next, c);
227
228                 /* Enter button */
229                 enter = new JButton("Enter");
230                 enter.addActionListener(this);
231                 enter.setActionCommand("enter");
232                 c.gridx = 1;
233                 c.gridy = 2;
234                 c.gridwidth = 1;
235                 c.gridheight = 1;
236                 c.fill = GridBagConstraints.BOTH;
237                 c.anchor = GridBagConstraints.CENTER;
238                 pane.add(enter, c);
239
240                 pack();
241         }
242 }