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.
21 import java.awt.event.*;
23 import javax.swing.event.*;
25 import java.util.concurrent.*;
26 import java.util.Arrays;
27 import org.altusmetrum.altoslib_11.*;
28 import org.altusmetrum.altosuilib_11.*;
30 public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDisplay, AltosIdleMonitorListener, DocumentListener {
34 AltosInfoTable flightInfo;
35 AltosFlightStatus flightStatus;
37 AltosIdleMonitor thread;
48 } catch (InterruptedException ie) {
63 public void font_size_changed(int font_size) {
64 pad.font_size_changed(font_size);
65 flightInfo.font_size_changed(font_size);
68 public void units_changed(boolean imperial_units) {
69 pad.units_changed(imperial_units);
70 flightInfo.units_changed(imperial_units);
73 AltosFlightStatusUpdate status_update;
75 public void show(AltosState state, AltosListenerState listener_state) {
76 status_update.saved_state = state;
77 if (ignitor.should_show(state)) {
79 pane.add("Ignitor", ignitor);
88 if (state.gps != null && state.gps.connected) {
90 pane.add("Site Map", sitemap);
101 pad.show(state, listener_state);
102 flightStatus.show(state, listener_state);
103 flightInfo.show(state, listener_state);
105 ignitor.show(state, listener_state);
107 sitemap.show(state, listener_state);
108 // } catch (Exception e) {
109 // System.out.print("Show exception " + e);
113 public void update(final AltosState state, final AltosListenerState listener_state) {
114 Runnable r = new Runnable() {
116 show(state, listener_state);
119 SwingUtilities.invokeLater(r);
122 public void failed() {
123 Runnable r = new Runnable() {
128 SwingUtilities.invokeLater(r);
131 public void error(final String reason) {
132 Runnable r = new Runnable() {
135 JOptionPane.showMessageDialog(AltosIdleMonitorUI.this,
137 "Error fetching data",
138 JOptionPane.ERROR_MESSAGE);
141 SwingUtilities.invokeLater(r);
145 AltosUIFreqList frequencies;
146 JTextField callsign_value;
148 /* DocumentListener interface methods */
149 public void changedUpdate(DocumentEvent e) {
150 if (callsign_value != null) {
151 String callsign = callsign_value.getText();
152 System.out.printf("callsign set to %s\n", callsign);
153 thread.set_callsign(callsign);
154 AltosUIPreferences.set_callsign(callsign);
158 public void insertUpdate(DocumentEvent e) {
162 public void removeUpdate(DocumentEvent e) {
166 void idle_exception(JFrame owner, Exception e) {
167 if (e instanceof FileNotFoundException) {
168 JOptionPane.showMessageDialog(owner,
169 ((FileNotFoundException) e).getMessage(),
170 "Cannot open target device",
171 JOptionPane.ERROR_MESSAGE);
172 } else if (e instanceof AltosSerialInUseException) {
173 JOptionPane.showMessageDialog(owner,
174 String.format("Device \"%s\" already in use",
175 device.toShortString()),
177 JOptionPane.ERROR_MESSAGE);
178 } else if (e instanceof IOException) {
179 IOException ee = (IOException) e;
180 JOptionPane.showMessageDialog(owner,
181 device.toShortString(),
182 ee.getLocalizedMessage(),
183 JOptionPane.ERROR_MESSAGE);
185 JOptionPane.showMessageDialog(owner,
186 String.format("Connection to \"%s\" failed",
187 device.toShortString()),
189 JOptionPane.ERROR_MESSAGE);
193 private void close() {
196 } catch (Exception ex) {
197 System.out.printf("Exception %s\n", ex.toString());
198 for (StackTraceElement el : ex.getStackTrace())
199 System.out.printf("%s\n", el.toString());
203 AltosUIPreferences.unregister_font_listener(AltosIdleMonitorUI.this);
206 public AltosIdleMonitorUI(JFrame in_owner)
207 throws FileNotFoundException, TimeoutException, InterruptedException {
209 device = AltosDeviceUIDialog.show(in_owner, Altos.product_any);
211 if (!device.matchProduct(Altos.product_altimeter))
214 serial = device.getSerial();
218 link = new AltosSerial(device);
219 } catch (Exception ex) {
220 idle_exception(in_owner, ex);
223 link.set_frame(this);
225 /* We let the user set the freq/callsign, so don't bother with the cancel dialog */
226 link.set_cancel_enable(false);
228 bag = getContentPane();
229 bag.setLayout(new GridBagLayout());
231 setTitle(String.format("AltOS %s", device.toShortString()));
233 /* Stick frequency selector at top of table for telemetry monitoring */
234 if (remote && serial >= 0) {
238 frequencies = new AltosUIFreqList(AltosUIPreferences.frequency(serial));
239 frequencies.addActionListener(new ActionListener() {
240 public void actionPerformed(ActionEvent e) {
241 double frequency = frequencies.frequency();
242 thread.set_frequency(frequency);
243 AltosUIPreferences.set_frequency(device.getSerial(),
247 bag.add (frequencies, constraints(0, 1));
248 bag.add (new JLabel("Callsign:"), constraints(1, 1));
249 /* Add callsign configuration */
250 callsign_value = new JTextField(AltosUIPreferences.callsign());
251 callsign_value.getDocument().addDocumentListener(this);
252 callsign_value.setToolTipText("Callsign sent in packet mode");
253 bag.add(callsign_value, constraints(2, 1, GridBagConstraints.HORIZONTAL));
259 /* Flight status is always visible */
260 flightStatus = new AltosFlightStatus();
261 bag.add(flightStatus, constraints(0, 4, GridBagConstraints.HORIZONTAL));
265 /* The rest of the window uses a tabbed pane to
266 * show one of the alternate data views
268 pane = new JTabbedPane();
270 pad = new AltosPad();
271 pane.add("Launch Pad", pad);
273 flightInfo = new AltosInfoTable();
274 pane.add("Table", new JScrollPane(flightInfo));
276 ignitor = new AltosIgnitor();
278 sitemap = new AltosUIMap();
280 /* Make the tabbed pane use the rest of the window space */
281 bag.add(pane, constraints(0, 4, GridBagConstraints.BOTH));
283 setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
285 AltosUIPreferences.register_font_listener(this);
287 addWindowListener(new WindowAdapter() {
289 public void windowClosing(WindowEvent e) {
297 thread = new AltosIdleMonitor((AltosIdleMonitorListener) this, link, (boolean) remote);
299 status_update = new AltosFlightStatusUpdate(flightStatus);
301 new javax.swing.Timer(100, status_update).start();