clean up all existing lintian warnings
[fw/altos] / altosui / AltosSiteMapPreload.java
1 /*
2  * Copyright © 2011 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.image.*;
22 import java.awt.event.*;
23 import javax.swing.*;
24 import javax.swing.event.MouseInputAdapter;
25 import javax.imageio.ImageIO;
26 import javax.swing.table.*;
27 import java.io.*;
28 import java.util.*;
29 import java.text.*;
30 import java.util.prefs.*;
31 import java.lang.Math;
32 import java.awt.geom.Point2D;
33 import java.awt.geom.Line2D;
34 import java.net.URL;
35 import java.net.URLConnection;
36
37 class AltosMapPos extends Box {
38         AltosUI         owner;
39         JLabel          label;
40         JComboBox       hemi;
41         JTextField      deg;
42         JLabel          deg_label;
43         JTextField      min;
44         JLabel          min_label;
45
46         public void set_value(double new_value) {
47                 double  d, m;
48                 int     h;
49
50                 h = 0;
51                 if (new_value < 0) {
52                         h = 1;
53                         new_value = -new_value;
54                 }
55                 d = Math.floor(new_value);
56                 deg.setText(String.format("%3.0f", d));
57                 m = (new_value - d) * 60.0;
58                 min.setText(String.format("%7.4f", m));
59                 hemi.setSelectedIndex(h);
60         }
61
62         public double get_value() throws NumberFormatException {
63                 int     h = hemi.getSelectedIndex();
64                 String  d_t = deg.getText();
65                 String  m_t = min.getText();
66                 double  d, m, v;
67                 try {
68                         d = Double.parseDouble(d_t);
69                 } catch (NumberFormatException ne) {
70                         JOptionPane.showMessageDialog(owner,
71                                                       String.format("Invalid degrees \"%s\"",
72                                                                     d_t),
73                                                       "Invalid number",
74                                                       JOptionPane.ERROR_MESSAGE);
75                         throw ne;
76                 }
77                 try {
78                         if (m_t.equals(""))
79                                 m = 0;
80                         else
81                                 m = Double.parseDouble(m_t);
82                 } catch (NumberFormatException ne) {
83                         JOptionPane.showMessageDialog(owner,
84                                                       String.format("Invalid minutes \"%s\"",
85                                                                     m_t),
86                                                       "Invalid number",
87                                                       JOptionPane.ERROR_MESSAGE);
88                         throw ne;
89                 }
90                 v = d + m/60.0;
91                 if (h == 1)
92                         v = -v;
93                 return v;
94         }
95
96         public AltosMapPos(AltosUI in_owner,
97                            String label_value,
98                            String[] hemi_names,
99                            double default_value) {
100                 super(BoxLayout.X_AXIS);
101                 owner = in_owner;
102                 label = new JLabel(label_value);
103                 hemi = new JComboBox(hemi_names);
104                 hemi.setEditable(false);
105                 deg = new JTextField(5);
106                 deg.setMinimumSize(deg.getPreferredSize());
107                 deg.setHorizontalAlignment(JTextField.RIGHT);
108                 deg_label = new JLabel("°");
109                 min = new JTextField(9);
110                 min.setMinimumSize(min.getPreferredSize());
111                 min_label = new JLabel("'");
112                 set_value(default_value);
113                 add(label);
114                 add(Box.createRigidArea(new Dimension(5, 0)));
115                 add(hemi);
116                 add(Box.createRigidArea(new Dimension(5, 0)));
117                 add(deg);
118                 add(Box.createRigidArea(new Dimension(5, 0)));
119                 add(deg_label);
120                 add(Box.createRigidArea(new Dimension(5, 0)));
121                 add(min);
122                 add(Box.createRigidArea(new Dimension(5, 0)));
123                 add(min_label);
124         }
125 }
126
127 class AltosSite {
128         String  name;
129         double  latitude;
130         double  longitude;
131
132         public String toString() {
133                 return name;
134         }
135
136         public AltosSite(String in_name, double in_latitude, double in_longitude) {
137                 name = in_name;
138                 latitude = in_latitude;
139                 longitude = in_longitude;
140         }
141
142         public AltosSite(String line) throws ParseException {
143                 String[]        elements = line.split(":");
144
145                 if (elements.length < 3)
146                         throw new ParseException(String.format("Invalid site line %s", line), 0);
147
148                 name = elements[0];
149
150                 try {
151                         latitude = Double.parseDouble(elements[1]);
152                         longitude = Double.parseDouble(elements[2]);
153                 } catch (NumberFormatException ne) {
154                         throw new ParseException(String.format("Invalid site line %s", line), 0);
155                 }
156         }
157 }
158
159 class AltosSites extends Thread {
160         AltosSiteMapPreload     preload;
161         URL                     url;
162         LinkedList<AltosSite>   sites;
163
164         void notify_complete() {
165                 SwingUtilities.invokeLater(new Runnable() {
166                                 public void run() {
167                                         preload.set_sites();
168                                 }
169                         });
170         }
171
172         void add(AltosSite site) {
173                 sites.add(site);
174         }
175
176         void add(String line) {
177                 try {
178                         add(new AltosSite(line));
179                 } catch (ParseException pe) {
180                 }
181         }
182
183         public void run() {
184                 try {
185                         URLConnection uc = url.openConnection();
186                         int length = uc.getContentLength();
187                         
188                         InputStreamReader in_stream = new InputStreamReader(uc.getInputStream(), Altos.unicode_set);
189                         BufferedReader in = new BufferedReader(in_stream);
190
191                         for (;;) {
192                                 String line = in.readLine();
193                                 if (line == null)
194                                         break;
195                                 add(line);
196                         }
197                 } catch (IOException e) {
198                 } finally {
199                         notify_complete();
200                 }
201         }
202
203         public AltosSites(AltosSiteMapPreload in_preload) {
204                 sites = new LinkedList<AltosSite>();
205                 preload = in_preload;
206                 try {
207                         url = new URL("http://gag.com/~keithp/launch-sites.txt");
208                 } catch (java.net.MalformedURLException e) {
209                         notify_complete();
210                 }
211                 start();
212         }
213 }
214
215 public class AltosSiteMapPreload extends JDialog implements ActionListener, ItemListener {
216         AltosUI         owner;
217         AltosSiteMap    map;
218
219         AltosMapPos     lat;
220         AltosMapPos     lon;
221
222         final static int        radius = 4;
223         final static int        width = (radius * 2 + 1);
224         final static int        height = (radius * 2 + 1);
225
226         JProgressBar    pbar;
227
228         AltosSites      sites;
229         JLabel          site_list_label;
230         JComboBox       site_list;
231                 
232         JToggleButton   load_button;
233         boolean         loading;
234         JButton         close_button;
235
236         static final String[]   lat_hemi_names = { "N", "S" };
237         static final String[]   lon_hemi_names = { "E", "W" };
238
239         class updatePbar implements Runnable {
240                 int             n;
241                 String          s;
242
243                 public updatePbar(int x, int y, String in_s) {
244                         n = (x + radius) + (y + radius) * width + 1;
245                         s = in_s;
246                 }
247
248                 public void run() {
249                         pbar.setValue(n);
250                         pbar.setString(s);
251                         if (n < width * height) {
252                                 pbar.setValue(n);
253                                 pbar.setString(s);
254                         } else {
255                                 pbar.setValue(0);
256                                 pbar.setString("");
257                                 load_button.setSelected(false);
258                                 loading = false;
259                         }
260                 }
261         }
262
263         class bgLoad extends Thread {
264
265                 AltosSiteMap    map;
266
267                 public bgLoad(AltosSiteMap in_map) {
268                         map = in_map;
269                 }
270
271                 public void run() {
272                         for (int y = -map.radius; y <= map.radius; y++) {
273                                 for (int x = -map.radius; x <= map.radius; x++) {
274                                         String  pngfile;
275                                         pngfile = map.initMap(new Point(x,y));
276                                         SwingUtilities.invokeLater(new updatePbar(x, y, pngfile));
277                                 }
278                         }
279                 }
280         }
281
282         public void set_sites() {
283                 int     i = 1;
284                 for (AltosSite site : sites.sites) {
285                         site_list.insertItemAt(site, i);
286                         i++;
287                 }
288         }
289
290         public void itemStateChanged(ItemEvent e) {
291                 int             state = e.getStateChange();
292
293                 if (state == ItemEvent.SELECTED) {
294                         Object  o = e.getItem();
295                         if (o instanceof AltosSite) {
296                                 AltosSite       site = (AltosSite) o;
297                                 lat.set_value(site.latitude);
298                                 lon.set_value(site.longitude);
299                         }
300                 }
301         }
302
303         public void actionPerformed(ActionEvent e) {
304                 String  cmd = e.getActionCommand();
305
306                 if (cmd.equals("close"))
307                         setVisible(false);
308
309                 if (cmd.equals("load")) {
310                         if (!loading) {
311                                 try {
312                                         final double    latitude = lat.get_value();
313                                         final double    longitude = lon.get_value();
314                                         map.setBaseLocation(latitude,longitude);
315                                         map.draw_circle(latitude,longitude);
316                                         loading = true;
317                                         bgLoad thread = new bgLoad(map);
318                                         thread.start();
319                                 } catch (NumberFormatException ne) {
320                                         load_button.setSelected(false);
321                                 }
322                         }
323                 }
324         }
325
326         public AltosSiteMapPreload(AltosUI in_owner) {
327                 owner = in_owner;
328
329                 Container               pane = getContentPane();
330                 GridBagConstraints      c = new GridBagConstraints();
331                 Insets                  i = new Insets(4,4,4,4);
332
333                 pane.setLayout(new GridBagLayout());
334
335                 map = new AltosSiteMap(4);
336
337                 c.fill = GridBagConstraints.BOTH;
338                 c.anchor = GridBagConstraints.CENTER;
339                 c.insets = i;
340                 c.weightx = 1;
341                 c.weighty = 1;
342
343                 c.gridx = 0;
344                 c.gridy = 0;
345                 c.gridwidth = 2;
346                 c.anchor = GridBagConstraints.CENTER;
347
348                 pane.add(map, c);
349
350                 pbar = new JProgressBar();
351                 pbar.setMinimum(0);
352                 pbar.setMaximum(width * height);
353                 pbar.setValue(0);
354                 pbar.setString("");
355                 pbar.setStringPainted(true);
356                 
357                 c.fill = GridBagConstraints.HORIZONTAL;
358                 c.anchor = GridBagConstraints.CENTER;
359                 c.insets = i;
360                 c.weightx = 1;
361                 c.weighty = 0;
362
363                 c.gridx = 0;
364                 c.gridy = 1;
365                 c.gridwidth = 2;
366
367                 pane.add(pbar, c);
368
369                 site_list_label = new JLabel ("Known Launch Sites:");
370
371                 c.fill = GridBagConstraints.NONE;
372                 c.anchor = GridBagConstraints.CENTER;
373                 c.insets = i;
374                 c.weightx = 1;
375                 c.weighty = 0;
376
377                 c.gridx = 0;
378                 c.gridy = 2;
379                 c.gridwidth = 1;
380
381                 pane.add(site_list_label, c);
382                 
383                 site_list = new JComboBox(new String[] { "Site List" });
384                 site_list.addItemListener(this);
385
386                 sites = new AltosSites(this);
387
388                 c.fill = GridBagConstraints.HORIZONTAL;
389                 c.anchor = GridBagConstraints.CENTER;
390                 c.insets = i;
391                 c.weightx = 1;
392                 c.weighty = 0;
393
394                 c.gridx = 1;
395                 c.gridy = 2;
396                 c.gridwidth = 1;
397
398                 pane.add(site_list, c);
399                 
400                 lat = new AltosMapPos(owner,
401                                       "Latitude:",
402                                       lat_hemi_names,
403                                       37.167833333);
404                 c.fill = GridBagConstraints.NONE;
405                 c.anchor = GridBagConstraints.CENTER;
406                 c.insets = i;
407                 c.weightx = 0;
408                 c.weighty = 0;
409
410                 c.gridx = 0;
411                 c.gridy = 3;
412                 c.gridwidth = 1;
413                 c.anchor = GridBagConstraints.CENTER;
414
415                 pane.add(lat, c);
416                 
417                 lon = new AltosMapPos(owner,
418                                       "Longitude:",
419                                       lon_hemi_names,
420                                       -97.73975);
421
422                 c.fill = GridBagConstraints.NONE;
423                 c.anchor = GridBagConstraints.CENTER;
424                 c.insets = i;
425                 c.weightx = 0;
426                 c.weighty = 0;
427
428                 c.gridx = 1;
429                 c.gridy = 3;
430                 c.gridwidth = 1;
431                 c.anchor = GridBagConstraints.CENTER;
432
433                 pane.add(lon, c);
434
435                 load_button = new JToggleButton("Load Map");
436                 load_button.addActionListener(this);
437                 load_button.setActionCommand("load");
438                 
439                 c.fill = GridBagConstraints.NONE;
440                 c.anchor = GridBagConstraints.CENTER;
441                 c.insets = i;
442                 c.weightx = 1;
443                 c.weighty = 0;
444
445                 c.gridx = 0;
446                 c.gridy = 4;
447                 c.gridwidth = 1;
448                 c.anchor = GridBagConstraints.CENTER;
449
450                 pane.add(load_button, c);
451
452                 close_button = new JButton("Close");
453                 close_button.addActionListener(this);
454                 close_button.setActionCommand("close");
455                 
456                 c.fill = GridBagConstraints.NONE;
457                 c.anchor = GridBagConstraints.CENTER;
458                 c.insets = i;
459                 c.weightx = 1;
460                 c.weighty = 0;
461
462                 c.gridx = 1;
463                 c.gridy = 4;
464                 c.gridwidth = 1;
465                 c.anchor = GridBagConstraints.CENTER;
466
467                 pane.add(close_button, c);
468
469                 pack();
470                 setLocationRelativeTo(owner);
471                 setVisible(true);
472         }
473 }