altosui: Move AltosEepromChunk.java to lib
[fw/altos] / altosui / AltosFlightUI.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.*;
30 import org.altusmetrum.AltosLib.*;
31
32 public class AltosFlightUI extends AltosFrame implements AltosFlightDisplay, AltosFontListener {
33         AltosVoice              voice;
34         AltosFlightReader       reader;
35         AltosDisplayThread      thread;
36
37         JTabbedPane     pane;
38
39         AltosPad        pad;
40         AltosAscent     ascent;
41         AltosDescent    descent;
42         AltosLanded     landed;
43         AltosCompanionInfo      companion;
44         AltosSiteMap    sitemap;
45         boolean         has_map;
46         boolean         has_companion;
47
48         private AltosFlightStatus flightStatus;
49         private AltosInfoTable flightInfo;
50
51         boolean exit_on_close = false;
52
53         JComponent cur_tab = null;
54         JComponent which_tab(AltosState state) {
55                 if (state.state < Altos.ao_flight_boost)
56                         return pad;
57                 if (state.state <= Altos.ao_flight_coast)
58                         return ascent;
59                 if (state.state <= Altos.ao_flight_main)
60                         return descent;
61                 return landed;
62         }
63
64         void stop_display() {
65                 if (thread != null && thread.isAlive()) {
66                         thread.interrupt();
67                         try {
68                                 thread.join();
69                         } catch (InterruptedException ie) {}
70                 }
71                 thread = null;
72         }
73
74         void disconnect() {
75                 stop_display();
76         }
77
78         public void reset() {
79                 pad.reset();
80                 ascent.reset();
81                 descent.reset();
82                 landed.reset();
83                 flightInfo.clear();
84                 sitemap.reset();
85         }
86
87         public void set_font() {
88                 pad.set_font();
89                 ascent.set_font();
90                 descent.set_font();
91                 landed.set_font();
92                 flightStatus.set_font();
93                 flightInfo.set_font();
94                 sitemap.set_font();
95                 companion.set_font();
96         }
97
98         public void font_size_changed(int font_size) {
99                 set_font();
100         }
101
102         public void show(AltosState state, int crc_errors) {
103                 JComponent tab = which_tab(state);
104                 try {
105                 pad.show(state, crc_errors);
106                 ascent.show(state, crc_errors);
107                 descent.show(state, crc_errors);
108                 landed.show(state, crc_errors);
109                 if (tab != cur_tab) {
110                         if (cur_tab == pane.getSelectedComponent()) {
111                                 pane.setSelectedComponent(tab);
112                         }
113                         cur_tab = tab;
114                 }
115                 flightStatus.show(state, crc_errors);
116                 flightInfo.show(state, crc_errors);
117
118                 if (state.data.companion != null) {
119                         if (!has_companion) {
120                                 pane.add("Companion", companion);
121                                 has_companion= true;
122                         }
123                         companion.show(state, crc_errors);
124                 } else {
125                         if (has_companion) {
126                                 pane.remove(companion);
127                                 has_companion = false;
128                         }
129                 }
130                 if (state.gps != null && state.gps.connected) {
131                         if (!has_map) {
132                                 pane.add("Site Map", sitemap);
133                                 has_map = true;
134                         }
135                         sitemap.show(state, crc_errors);
136                 } else {
137                         if (has_map) {
138                                 pane.remove(sitemap);
139                                 has_map = false;
140                         }
141                 }
142                 } catch (Exception e) {
143                         System.out.print("Show exception" + e);
144                 }
145         }
146
147         public void set_exit_on_close() {
148                 exit_on_close = true;
149         }
150
151         Container       bag;
152         AltosFreqList   frequencies;
153         JComboBox       telemetries;
154
155         public AltosFlightUI(AltosVoice in_voice, AltosFlightReader in_reader, final int serial) {
156                 AltosUIPreferences.set_component(this);
157
158                 voice = in_voice;
159                 reader = in_reader;
160
161                 bag = getContentPane();
162                 bag.setLayout(new GridBagLayout());
163
164                 GridBagConstraints c = new GridBagConstraints();
165
166                 java.net.URL imgURL = AltosUI.class.getResource("/altus-metrum-16x16.jpg");
167                 if (imgURL != null)
168                         setIconImage(new ImageIcon(imgURL).getImage());
169
170                 setTitle(String.format("AltOS %s", reader.name));
171
172                 /* Stick channel selector at top of table for telemetry monitoring */
173                 if (serial >= 0) {
174                         // Channel menu
175                         frequencies = new AltosFreqList(AltosUIPreferences.frequency(serial));
176                         frequencies.set_product("Monitor");
177                         frequencies.set_serial(serial);
178                         frequencies.addActionListener(new ActionListener() {
179                                         public void actionPerformed(ActionEvent e) {
180                                                 double frequency = frequencies.frequency();
181                                                 try {
182                                                         reader.set_frequency(frequency);
183                                                 } catch (TimeoutException te) {
184                                                 } catch (InterruptedException ie) {
185                                                 }
186                                                 reader.save_frequency();
187                                         }
188                         });
189                         c.gridx = 0;
190                         c.gridy = 0;
191                         c.weightx = 0;
192                         c.weighty = 0;
193                         c.insets = new Insets(3, 3, 3, 3);
194                         c.fill = GridBagConstraints.NONE;
195                         c.anchor = GridBagConstraints.WEST;
196                         bag.add (frequencies, c);
197
198                         // Telemetry format menu
199                         telemetries = new JComboBox();
200                         for (int i = 1; i <= Altos.ao_telemetry_max; i++)
201                                 telemetries.addItem(Altos.telemetry_name(i));
202                         int telemetry = AltosUIPreferences.telemetry(serial);
203                         if (telemetry <= Altos.ao_telemetry_off ||
204                             telemetry > Altos.ao_telemetry_max)
205                                 telemetry = Altos.ao_telemetry_standard;
206                         telemetries.setSelectedIndex(telemetry - 1);
207                         telemetries.setMaximumRowCount(Altos.ao_telemetry_max);
208                         telemetries.setPreferredSize(null);
209                         telemetries.revalidate();
210                         telemetries.addActionListener(new ActionListener() {
211                                         public void actionPerformed(ActionEvent e) {
212                                                 int telemetry = telemetries.getSelectedIndex() + 1;
213                                                 reader.set_telemetry(telemetry);
214                                                 reader.save_telemetry();
215                                         }
216                                 });
217                         c.gridx = 1;
218                         c.gridy = 0;
219                         c.weightx = 0;
220                         c.weighty = 0;
221                         c.fill = GridBagConstraints.NONE;
222                         c.anchor = GridBagConstraints.WEST;
223                         bag.add (telemetries, c);
224                         c.insets = new Insets(0, 0, 0, 0);
225                 }
226
227                 /* Flight status is always visible */
228                 flightStatus = new AltosFlightStatus();
229                 c.gridx = 0;
230                 c.gridy = 1;
231                 c.fill = GridBagConstraints.HORIZONTAL;
232                 c.weightx = 1;
233                 c.gridwidth = 2;
234                 bag.add(flightStatus, c);
235                 c.gridwidth = 1;
236
237                 /* The rest of the window uses a tabbed pane to
238                  * show one of the alternate data views
239                  */
240                 pane = new JTabbedPane();
241
242                 pad = new AltosPad();
243                 pane.add("Launch Pad", pad);
244
245                 ascent = new AltosAscent();
246                 pane.add("Ascent", ascent);
247
248                 descent = new AltosDescent();
249                 pane.add("Descent", descent);
250
251                 landed = new AltosLanded(reader);
252                 pane.add("Landed", landed);
253
254                 flightInfo = new AltosInfoTable();
255                 pane.add("Table", new JScrollPane(flightInfo));
256
257                 companion = new AltosCompanionInfo();
258                 has_companion = false;
259
260                 sitemap = new AltosSiteMap();
261                 has_map = false;
262
263                 /* Make the tabbed pane use the rest of the window space */
264                 c.gridx = 0;
265                 c.gridy = 2;
266                 c.fill = GridBagConstraints.BOTH;
267                 c.weightx = 1;
268                 c.weighty = 1;
269                 c.gridwidth = 2;
270                 bag.add(pane, c);
271
272                 setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
273
274                 AltosUIPreferences.register_font_listener(this);
275
276                 addWindowListener(new WindowAdapter() {
277                                 @Override
278                                 public void windowClosing(WindowEvent e) {
279                                         disconnect();
280                                         setVisible(false);
281                                         dispose();
282                                         AltosUIPreferences.unregister_font_listener(AltosFlightUI.this);
283                                         if (exit_on_close)
284                                                 System.exit(0);
285                                 }
286                         });
287
288                 pack();
289                 setVisible(true);
290
291                 thread = new AltosDisplayThread(this, voice, this, reader);
292
293                 thread.start();
294         }
295
296         public AltosFlightUI (AltosVoice in_voice, AltosFlightReader in_reader) {
297                 this(in_voice, in_reader, -1);
298         }
299 }