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; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
22 import java.awt.event.*;
24 import javax.swing.event.*;
26 import java.util.concurrent.*;
27 import java.util.Arrays;
28 import org.altusmetrum.altoslib_14.*;
29 import org.altusmetrum.altosuilib_14.*;
31 public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDisplay, AltosIdleMonitorListener, DocumentListener {
35 AltosInfoTable flightInfo;
36 AltosFlightStatus flightStatus;
38 AltosIdleMonitor thread;
49 } catch (InterruptedException ie) {
64 public void font_size_changed(int font_size) {
65 pad.font_size_changed(font_size);
66 flightInfo.font_size_changed(font_size);
69 public void units_changed(boolean imperial_units) {
70 pad.units_changed(imperial_units);
71 flightInfo.units_changed(imperial_units);
74 AltosFlightStatusUpdate status_update;
76 public void show(AltosState state, AltosListenerState listener_state) {
77 status_update.saved_state = state;
78 if (igniter.should_show(state)) {
80 pane.add("Ignitor", igniter);
89 if (state.gps != null && state.gps.connected) {
91 pane.add("Site Map", sitemap);
102 pad.show(state, listener_state);
103 flightStatus.show(state, listener_state);
104 flightInfo.show(state, listener_state);
106 igniter.show(state, listener_state);
108 sitemap.show(state, listener_state);
109 // } catch (Exception e) {
110 // System.out.print("Show exception " + e);
114 public void update(final AltosState state, final AltosListenerState listener_state) {
115 Runnable r = new Runnable() {
117 show(state, listener_state);
120 SwingUtilities.invokeLater(r);
123 public void failed() {
124 Runnable r = new Runnable() {
129 SwingUtilities.invokeLater(r);
132 public void error(final String reason) {
133 Runnable r = new Runnable() {
136 JOptionPane.showMessageDialog(AltosIdleMonitorUI.this,
138 "Error fetching data",
139 JOptionPane.ERROR_MESSAGE);
142 SwingUtilities.invokeLater(r);
146 AltosUIFreqList frequencies;
147 JTextField callsign_value;
149 /* DocumentListener interface methods */
150 public void changedUpdate(DocumentEvent e) {
151 if (callsign_value != null) {
152 String callsign = callsign_value.getText();
153 System.out.printf("callsign set to %s\n", callsign);
154 thread.set_callsign(callsign);
155 AltosUIPreferences.set_callsign(callsign);
159 public void insertUpdate(DocumentEvent e) {
163 public void removeUpdate(DocumentEvent e) {
167 void idle_exception(JFrame owner, Exception e) {
168 if (e instanceof FileNotFoundException) {
169 JOptionPane.showMessageDialog(owner,
170 ((FileNotFoundException) e).getMessage(),
171 "Cannot open target device",
172 JOptionPane.ERROR_MESSAGE);
173 } else if (e instanceof AltosSerialInUseException) {
174 JOptionPane.showMessageDialog(owner,
175 String.format("Device \"%s\" already in use",
176 device.toShortString()),
178 JOptionPane.ERROR_MESSAGE);
179 } else if (e instanceof IOException) {
180 IOException ee = (IOException) e;
181 JOptionPane.showMessageDialog(owner,
182 device.toShortString(),
183 ee.getLocalizedMessage(),
184 JOptionPane.ERROR_MESSAGE);
186 JOptionPane.showMessageDialog(owner,
187 String.format("Connection to \"%s\" failed",
188 device.toShortString()),
190 JOptionPane.ERROR_MESSAGE);
194 private void close() {
197 } catch (Exception ex) {
198 System.out.printf("Exception %s\n", ex.toString());
199 for (StackTraceElement el : ex.getStackTrace())
200 System.out.printf("%s\n", el.toString());
204 AltosUIPreferences.unregister_font_listener(AltosIdleMonitorUI.this);
207 public AltosIdleMonitorUI(JFrame in_owner)
208 throws FileNotFoundException, TimeoutException, InterruptedException {
210 device = AltosDeviceUIDialog.show(in_owner, Altos.product_any);
212 if (device.matchProduct(Altos.product_basestation))
215 serial = device.getSerial();
219 link = new AltosSerial(device);
220 } catch (Exception ex) {
221 idle_exception(in_owner, ex);
224 link.set_frame(this);
226 /* We let the user set the freq/callsign, so don't bother with the cancel dialog */
227 link.set_cancel_enable(false);
229 bag = getScrollablePane();
230 bag.setLayout(new GridBagLayout());
232 setTitle(String.format("AltOS %s", device.toShortString()));
234 /* Stick frequency selector at top of table for telemetry monitoring */
235 if (remote && serial >= 0) {
239 frequencies = new AltosUIFreqList(AltosUIPreferences.frequency(serial));
240 frequencies.addActionListener(new ActionListener() {
241 public void actionPerformed(ActionEvent e) {
242 double frequency = frequencies.frequency();
243 thread.set_frequency(frequency);
244 AltosUIPreferences.set_frequency(device.getSerial(),
248 bag.add (frequencies, constraints(0, 1));
249 bag.add (new JLabel("Callsign:"), constraints(1, 1));
250 /* Add callsign configuration */
251 callsign_value = new JTextField(AltosUIPreferences.callsign());
252 callsign_value.getDocument().addDocumentListener(this);
253 callsign_value.setToolTipText("Callsign sent in packet mode");
254 bag.add(callsign_value, constraints(2, 1, GridBagConstraints.HORIZONTAL));
260 /* Flight status is always visible */
261 flightStatus = new AltosFlightStatus();
262 bag.add(flightStatus, constraints(0, 4, GridBagConstraints.HORIZONTAL));
266 /* The rest of the window uses a tabbed pane to
267 * show one of the alternate data views
269 pane = new JTabbedPane();
271 pad = new AltosPad();
272 pane.add("Launch Pad", pad);
274 flightInfo = new AltosInfoTable();
275 pane.add("Table", new JScrollPane(flightInfo));
277 igniter = new AltosIgnitor();
279 sitemap = new AltosUIMap();
281 /* Make the tabbed pane use the rest of the window space */
282 bag.add(pane, constraints(0, 4, GridBagConstraints.BOTH));
284 setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
286 AltosUIPreferences.register_font_listener(this);
288 addWindowListener(new WindowAdapter() {
290 public void windowClosing(WindowEvent e) {
298 thread = new AltosIdleMonitor(this, link, (boolean) remote);
300 thread.set_frequency(AltosUIPreferences.frequency(serial));
302 status_update = new AltosFlightStatusUpdate(flightStatus);
304 new javax.swing.Timer(100, status_update).start();