altosui: Make Windows java test "smarter"
[fw/altos] / micropeak / MicroDownload.java
1 /*
2  * Copyright © 2012 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 org.altusmetrum.micropeak;
19
20 import java.awt.*;
21 import java.awt.event.*;
22 import javax.swing.*;
23 import java.io.*;
24 import java.util.concurrent.*;
25 import java.util.*;
26 import org.altusmetrum.altoslib_5.*;
27 import org.altusmetrum.altosuilib_3.*;
28
29 public class MicroDownload extends AltosUIDialog implements Runnable, ActionListener, MicroSerialLog, WindowListener {
30         MicroPeak       owner;
31         Container       pane;
32         AltosDevice     device;
33         JButton         cancel;
34         MicroData       data;
35         MicroSerial     serial;
36         LinkedList<Integer> log_queue = new LinkedList<Integer>();
37         Runnable        log_run;
38         JTextArea       serial_log;
39         JLabel          status_value;
40         int             log_column;
41
42         public void windowActivated(WindowEvent e) {
43         }
44
45         public void windowClosed(WindowEvent e) {
46                 setVisible(false);
47                 dispose();
48         }
49
50         public void windowClosing(WindowEvent e) {
51         }
52
53         public void windowDeactivated(WindowEvent e) {
54         }
55
56         public void windowDeiconified(WindowEvent e) {
57         }
58
59         public void windowIconified(WindowEvent e) {
60         }
61
62         public void windowOpened(WindowEvent e) {
63         }
64
65         private void done_internal() {
66                 setVisible(false);
67                 dispose();
68
69                 if (data != null && data.crc_valid) {
70                         status_value.setText("Received MicroPeak Data");
71                         owner = owner.SetData(data);
72                         MicroSave save = new MicroSave(owner, data);
73                         if (save.runDialog())
74                                 owner.SetName(data.name);
75                 } else {
76                         JOptionPane.showMessageDialog(owner,
77                                                       "Download Failed",
78                                                       "Flight data corrupted",
79                                                       JOptionPane.ERROR_MESSAGE);
80                 }
81         }
82
83         public void drain_queue() {
84                 for (;;) {
85                         int     c;
86                         synchronized(this) {
87                                 if (log_queue.isEmpty()) {
88                                         log_run = null;
89                                         break;
90                                 }
91                                 c = log_queue.remove();
92                         }
93                         if (c == '\r')
94                                 continue;
95                         if (c == '\0')
96                                 continue;
97                         String s;
98                         if (c == '\n') {
99                                 s = "\n";
100                                 log_column = 0;
101                         } else if (' ' <= c && c <= '~') {
102                                 byte[] bytes = new byte[1];
103                                 bytes[0] = (byte) c;
104                                 s = new String(bytes, AltosLib.unicode_set);
105                                 log_column += 1;
106                         } else {
107                                 s = String.format("\\0x%02x", c & 0xff);
108                                 log_column += 5;
109                         }
110                         serial_log.append(s);
111                         if (log_column > 40) {
112                                 serial_log.append("\n");
113                                 log_column = 0;
114                         }
115                 }
116         }
117
118         public void log_char(int c) {
119                 synchronized(this) {
120                         log_queue.add(c);
121                         if (log_run == null) {
122                                 log_run = new Runnable() {
123                                                 public void run() {
124                                                         drain_queue();
125                                                 }
126                                         };
127                                 SwingUtilities.invokeLater(log_run);
128                         }
129                 }
130         }
131
132         public void done() {
133                 Runnable r = new Runnable() {
134                                 public void run() {
135                                         try {
136                                                 done_internal();
137                                         } catch (Exception ex) {
138                                         }
139                                 }
140                         };
141                 SwingUtilities.invokeLater(r);
142         }
143
144         public void run() {
145                 try {
146                         for (;;) {
147                                 try {
148                                         data = new MicroData(serial, device.toShortString());
149                                         if (data != null && data.crc_valid)
150                                                 break;
151                                 } catch (MicroData.NonHexcharException nhe) {
152                                 }
153                         }
154                 } catch (FileNotFoundException fe) {
155                 } catch (IOException ioe) {
156                 } catch (InterruptedException ie) {
157                 } catch (MicroData.FileEndedException fee) {
158                 }
159                 serial.close();
160                 done();
161         }
162
163         Thread  serial_thread;
164
165         public void start() {
166                 try {
167                         serial = new MicroSerial(device);
168                         serial.set_log(this);
169                 } catch (FileNotFoundException fe) {
170                         return;
171                 }
172                 serial_thread = new Thread(this);
173                 serial_thread.start();
174         }
175
176         public void actionPerformed(ActionEvent ae) {
177                 if (serial_thread != null) {
178                         serial.close();
179                         serial_thread.interrupt();
180                 }
181                 setVisible(false);
182         }
183
184         public MicroDownload(MicroPeak owner, AltosDevice device) {
185                 super (owner, "Download MicroPeak Data", false);
186
187                 int y = 0;
188
189                 GridBagConstraints c;
190                 Insets il = new Insets(4,4,4,4);
191                 Insets ir = new Insets(4,4,4,4);
192
193                 this.owner = owner;
194                 this.device = device;
195
196                 pane = getContentPane();
197                 pane.setLayout(new GridBagLayout());
198
199                 c = new GridBagConstraints();
200                 c.gridx = 0; c.gridy = y;
201                 c.fill = GridBagConstraints.NONE;
202                 c.anchor = GridBagConstraints.LINE_START;
203                 c.insets = il;
204                 JLabel device_label = new JLabel("Device:");
205                 pane.add(device_label, c);
206
207                 c = new GridBagConstraints();
208                 c.gridx = 1; c.gridy = y;
209                 c.fill = GridBagConstraints.NONE;
210                 c.weightx = 1;
211                 c.anchor = GridBagConstraints.LINE_START;
212                 c.insets = ir;
213                 JLabel device_value = new JLabel(device.toString());
214                 pane.add(device_value, c);
215                 y++;
216
217                 c = new GridBagConstraints();
218                 c.gridx = 0; c.gridy = y;
219                 c.gridwidth = GridBagConstraints.REMAINDER;
220                 c.fill = GridBagConstraints.HORIZONTAL;
221                 c.weightx = 0;
222                 c.anchor = GridBagConstraints.LINE_START;
223                 c.insets = ir;
224                 JLabel help_text = new JLabel(
225                         "<html><i>Turn on the MicroPeak and place the LED inside the<br>" +
226                         "opening in the top of the MicroPeak USB adapter.<br> " +
227                         "Verify that the blue LED in the side of the USB adapter<br>" +
228                         "is blinking along with the orange LED on the MicroPeak.</i></html>");
229 //              help_text.setEditable(false);
230
231                 pane.add(help_text, c);
232                 y++;
233
234                 c = new GridBagConstraints();
235                 c.gridx = 0; c.gridy = y;
236                 c.gridwidth = 2;
237                 c.fill = GridBagConstraints.HORIZONTAL;
238                 c.weightx = 1;
239                 c.anchor = GridBagConstraints.LINE_START;
240                 c.insets = ir;
241                 status_value = new JLabel("Waiting for MicroPeak data...");
242                 pane.add(status_value, c);
243                 y++;
244
245                 serial_log = new JTextArea(10, 20);
246                 serial_log.setEditable(false);
247
248                 JScrollPane serial_scroll = new JScrollPane(serial_log);
249                 serial_scroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
250
251                 c = new GridBagConstraints();
252                 c.gridx = 0; c.gridy = y;
253                 c.gridwidth = GridBagConstraints.REMAINDER;
254                 c.fill = GridBagConstraints.BOTH;
255                 c.weightx = 1;
256                 c.weighty = 1;
257                 c.anchor = GridBagConstraints.LINE_START;
258                 c.insets = ir;
259
260                 pane.add(serial_scroll, c);
261                 y++;
262
263                 cancel = new JButton("Cancel");
264                 c = new GridBagConstraints();
265                 c.fill = GridBagConstraints.NONE;
266                 c.anchor = GridBagConstraints.EAST;
267                 c.gridx = 0; c.gridy = y;
268                 c.gridwidth = GridBagConstraints.REMAINDER;
269                 Insets ic = new Insets(4,4,4,4);
270                 c.insets = ic;
271                 pane.add(cancel, c);
272                 y++;
273
274                 cancel.addActionListener(this);
275
276                 pack();
277                 setLocationRelativeTo(owner);
278                 setVisible(true);
279                 start();
280         }
281 }