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