altosui: Replace flight status table with labels, fix resize.
[fw/altos] / ao-tools / altosui / AltosDescent.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 java.awt.event.*;
22 import javax.swing.*;
23 import javax.swing.filechooser.FileNameExtensionFilter;
24 import javax.swing.table.*;
25 import java.io.*;
26 import java.util.*;
27 import java.text.*;
28 import java.util.prefs.*;
29 import java.util.concurrent.LinkedBlockingQueue;
30
31 public class AltosDescent extends JComponent implements AltosFlightDisplay {
32         GridBagLayout   layout;
33         Font            label_font;
34         Font            value_font;
35
36         public class DescentValue {
37                 JLabel          label;
38                 JTextField      value;
39                 void show(AltosState state, int crc_errors) {}
40
41                 void reset() {
42                         value.setText("");
43                 }
44
45                 void show(String format, double v) {
46                         value.setText(String.format(format, v));
47                 }
48
49                 public DescentValue (GridBagLayout layout, int y, String text) {
50                         GridBagConstraints      c = new GridBagConstraints();
51                         c.weighty = 1;
52
53                         label = new JLabel(text);
54                         label.setFont(label_font);
55                         label.setHorizontalAlignment(SwingConstants.LEFT);
56                         c.gridx = 0; c.gridy = y;
57                         c.insets = new Insets(10, 10, 10, 10);
58                         c.anchor = GridBagConstraints.WEST;
59                         c.fill = GridBagConstraints.VERTICAL;
60                         c.weightx = 0;
61                         layout.setConstraints(label, c);
62                         add(label);
63
64                         value = new JTextField(30);
65                         value.setFont(value_font);
66                         value.setHorizontalAlignment(SwingConstants.RIGHT);
67                         c.gridx = 1; c.gridy = y;
68                         c.gridwidth = 2;
69                         c.anchor = GridBagConstraints.WEST;
70                         c.fill = GridBagConstraints.BOTH;
71                         c.weightx = 1;
72                         layout.setConstraints(value, c);
73                         add(value);
74                 }
75         }
76
77         class Height extends DescentValue {
78                 void show (AltosState state, int crc_errors) {
79                         show("%6.0f m", state.height);
80                 }
81                 public Height (GridBagLayout layout, int y) {
82                         super (layout, y, "Height");
83                 }
84         }
85
86         Height  height;
87
88         class Speed extends DescentValue {
89                 void show (AltosState state, int crc_errors) {
90                         double speed = state.speed;
91                         if (!state.ascent)
92                                 speed = state.baro_speed;
93                         show("%6.0f m/s", speed);
94                 }
95                 public Speed (GridBagLayout layout, int y) {
96                         super (layout, y, "Speed");
97                 }
98         }
99
100         Speed   speed;
101
102         String pos(double p, String pos, String neg) {
103                 String  h = pos;
104                 if (p < 0) {
105                         h = neg;
106                         p = -p;
107                 }
108                 int deg = (int) Math.floor(p);
109                 double min = (p - Math.floor(p)) * 60.0;
110                 return String.format("%s %4d° %9.6f", h, deg, min);
111         }
112
113         class Lat extends DescentValue {
114                 void show (AltosState state, int crc_errors) {
115                         if (state.gps != null)
116                                 value.setText(pos(state.gps.lat,"N", "S"));
117                         else
118                                 value.setText("???");
119                 }
120                 public Lat (GridBagLayout layout, int y) {
121                         super (layout, y, "Latitude");
122                 }
123         }
124
125         Lat lat;
126
127         class Lon extends DescentValue {
128                 void show (AltosState state, int crc_errors) {
129                         if (state.gps != null)
130                                 value.setText(pos(state.gps.lon,"E", "W"));
131                         else
132                                 value.setText("???");
133                 }
134                 public Lon (GridBagLayout layout, int y) {
135                         super (layout, y, "Longitude");
136                 }
137         }
138
139         Lon lon;
140
141         class Bearing {
142                 JLabel          label;
143                 JTextField      value;
144                 JTextField      value_deg;
145                 void reset () {
146                         value.setText("");
147                         value_deg.setText("");
148                 }
149                 void show (AltosState state, int crc_errors) {
150                         if (state.from_pad != null) {
151                                 value.setText(state.from_pad.bearing_words(
152                                                       AltosGreatCircle.BEARING_LONG));
153                                 value_deg.setText(String.format("%3.0f°", state.from_pad.bearing));
154                         } else {
155                                 value.setText("???");
156                                 value_deg.setText("???");
157                         }
158                 }
159                 public Bearing (GridBagLayout layout, int y) {
160                         GridBagConstraints      c = new GridBagConstraints();
161                         c.weighty = 1;
162
163                         label = new JLabel("Bearing");
164                         label.setFont(label_font);
165                         label.setHorizontalAlignment(SwingConstants.LEFT);
166                         c.gridx = 0; c.gridy = y;
167                         c.insets = new Insets(10, 10, 10, 10);
168                         c.anchor = GridBagConstraints.WEST;
169                         c.weightx = 0;
170                         c.fill = GridBagConstraints.VERTICAL;
171                         layout.setConstraints(label, c);
172                         add(label);
173
174                         value = new JTextField(30);
175                         value.setFont(value_font);
176                         value.setHorizontalAlignment(SwingConstants.RIGHT);
177                         c.gridx = 1; c.gridy = y;
178                         c.anchor = GridBagConstraints.EAST;
179                         c.weightx = 1;
180                         c.fill = GridBagConstraints.BOTH;
181                         layout.setConstraints(value, c);
182                         add(value);
183
184                         value_deg = new JTextField(5);
185                         value_deg.setFont(value_font);
186                         value_deg.setHorizontalAlignment(SwingConstants.RIGHT);
187                         c.gridx = 2; c.gridy = y;
188                         c.anchor = GridBagConstraints.EAST;
189                         c.weightx = 1;
190                         c.fill = GridBagConstraints.BOTH;
191                         layout.setConstraints(value_deg, c);
192                         add(value_deg);
193                 }
194         }
195
196         Bearing bearing;
197
198         class Elevation extends DescentValue {
199                 void show (AltosState state, int crc_errors) {
200                         if (state.from_pad != null)
201                                 show("%3.0f°", state.elevation);
202                         else
203                                 value.setText("???");
204                 }
205                 public Elevation (GridBagLayout layout, int y) {
206                         super (layout, y, "Elevation");
207                 }
208         }
209
210         Elevation elevation;
211
212         class Range extends DescentValue {
213                 void show (AltosState state, int crc_errors) {
214                         show("%6.0f m", state.range);
215                 }
216                 public Range (GridBagLayout layout, int y) {
217                         super (layout, y, "Range");
218                 }
219         }
220
221         Range range;
222
223         public void reset() {
224                 lat.reset();
225                 lon.reset();
226                 height.reset();
227                 speed.reset();
228                 bearing.reset();
229                 elevation.reset();
230                 range.reset();
231         }
232
233         public void show(AltosState state, int crc_errors) {
234                 height.show(state, crc_errors);
235                 speed.show(state, crc_errors);
236                 bearing.show(state, crc_errors);
237                 elevation.show(state, crc_errors);
238                 range.show(state, crc_errors);
239                 lat.show(state, crc_errors);
240                 lon.show(state, crc_errors);
241         }
242
243         public AltosDescent() {
244                 layout = new GridBagLayout();
245
246                 label_font = new Font("Dialog", Font.PLAIN, 24);
247                 value_font = new Font("Monospaced", Font.PLAIN, 24);
248                 setLayout(layout);
249
250                 /* Elements in descent display */
251                 speed = new Speed(layout, 0);
252                 height = new Height(layout, 1);
253                 bearing = new Bearing(layout, 2);
254                 elevation = new Elevation(layout, 3);
255                 range = new Range(layout, 4);
256                 lat = new Lat(layout, 5);
257                 lon = new Lon(layout, 6);
258         }
259 }