2 * Copyright © 2011 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.image.*;
22 import java.awt.event.*;
24 import javax.swing.event.MouseInputAdapter;
25 import javax.imageio.ImageIO;
26 import javax.swing.table.*;
30 import java.util.prefs.*;
31 import java.lang.Math;
32 import java.awt.geom.Point2D;
33 import java.awt.geom.Line2D;
35 import java.net.URLConnection;
37 class AltosMapPos extends Box {
46 public void set_value(double new_value) {
53 new_value = -new_value;
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);
62 public double get_value() throws NumberFormatException {
63 int h = hemi.getSelectedIndex();
64 String d_t = deg.getText();
65 String m_t = min.getText();
68 d = Double.parseDouble(d_t);
69 } catch (NumberFormatException ne) {
70 JOptionPane.showMessageDialog(owner,
71 String.format("Invalid degrees \"%s\"",
74 JOptionPane.ERROR_MESSAGE);
81 m = Double.parseDouble(m_t);
82 } catch (NumberFormatException ne) {
83 JOptionPane.showMessageDialog(owner,
84 String.format("Invalid minutes \"%s\"",
87 JOptionPane.ERROR_MESSAGE);
96 public AltosMapPos(AltosUI in_owner,
99 double default_value) {
100 super(BoxLayout.X_AXIS);
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);
114 add(Box.createRigidArea(new Dimension(5, 0)));
116 add(Box.createRigidArea(new Dimension(5, 0)));
118 add(Box.createRigidArea(new Dimension(5, 0)));
120 add(Box.createRigidArea(new Dimension(5, 0)));
122 add(Box.createRigidArea(new Dimension(5, 0)));
132 public String toString() {
136 public AltosSite(String in_name, double in_latitude, double in_longitude) {
138 latitude = in_latitude;
139 longitude = in_longitude;
142 public AltosSite(String line) throws ParseException {
143 String[] elements = line.split(":");
145 if (elements.length < 3)
146 throw new ParseException(String.format("Invalid site line %s", line), 0);
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);
159 class AltosSites extends Thread {
160 AltosSiteMapPreload preload;
162 LinkedList<AltosSite> sites;
164 void notify_complete() {
165 SwingUtilities.invokeLater(new Runnable() {
172 void add(AltosSite site) {
176 void add(String line) {
178 add(new AltosSite(line));
179 } catch (ParseException pe) {
185 URLConnection uc = url.openConnection();
186 int length = uc.getContentLength();
188 InputStreamReader in_stream = new InputStreamReader(uc.getInputStream(), Altos.unicode_set);
189 BufferedReader in = new BufferedReader(in_stream);
192 String line = in.readLine();
197 } catch (IOException e) {
203 public AltosSites(AltosSiteMapPreload in_preload) {
204 sites = new LinkedList<AltosSite>();
205 preload = in_preload;
207 url = new URL("http://gag.com/~keithp/launch-sites.txt");
208 } catch (java.net.MalformedURLException e) {
215 public class AltosSiteMapPreload extends JDialog implements ActionListener, ItemListener {
222 final static int radius = 4;
223 final static int width = (radius * 2 + 1);
224 final static int height = (radius * 2 + 1);
229 JLabel site_list_label;
232 JToggleButton load_button;
234 JButton close_button;
236 static final String[] lat_hemi_names = { "N", "S" };
237 static final String[] lon_hemi_names = { "E", "W" };
239 class updatePbar implements Runnable {
243 public updatePbar(int x, int y, String in_s) {
244 n = (x + radius) + (y + radius) * width + 1;
251 if (n < width * height) {
257 load_button.setSelected(false);
263 class bgLoad extends Thread {
267 public bgLoad(AltosSiteMap in_map) {
272 for (int y = -map.radius; y <= map.radius; y++) {
273 for (int x = -map.radius; x <= map.radius; x++) {
275 pngfile = map.initMap(new Point(x,y));
276 SwingUtilities.invokeLater(new updatePbar(x, y, pngfile));
282 public void set_sites() {
284 for (AltosSite site : sites.sites) {
285 site_list.insertItemAt(site, i);
290 public void itemStateChanged(ItemEvent e) {
291 int state = e.getStateChange();
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);
303 public void actionPerformed(ActionEvent e) {
304 String cmd = e.getActionCommand();
306 if (cmd.equals("close"))
309 if (cmd.equals("load")) {
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);
317 bgLoad thread = new bgLoad(map);
319 } catch (NumberFormatException ne) {
320 load_button.setSelected(false);
326 public AltosSiteMapPreload(AltosUI in_owner) {
329 Container pane = getContentPane();
330 GridBagConstraints c = new GridBagConstraints();
331 Insets i = new Insets(4,4,4,4);
333 pane.setLayout(new GridBagLayout());
335 map = new AltosSiteMap(4);
337 c.fill = GridBagConstraints.BOTH;
338 c.anchor = GridBagConstraints.CENTER;
346 c.anchor = GridBagConstraints.CENTER;
350 pbar = new JProgressBar();
352 pbar.setMaximum(width * height);
355 pbar.setStringPainted(true);
357 c.fill = GridBagConstraints.HORIZONTAL;
358 c.anchor = GridBagConstraints.CENTER;
369 site_list_label = new JLabel ("Known Launch Sites:");
371 c.fill = GridBagConstraints.NONE;
372 c.anchor = GridBagConstraints.CENTER;
381 pane.add(site_list_label, c);
383 site_list = new JComboBox(new String[] { "Site List" });
384 site_list.addItemListener(this);
386 sites = new AltosSites(this);
388 c.fill = GridBagConstraints.HORIZONTAL;
389 c.anchor = GridBagConstraints.CENTER;
398 pane.add(site_list, c);
400 lat = new AltosMapPos(owner,
404 c.fill = GridBagConstraints.NONE;
405 c.anchor = GridBagConstraints.CENTER;
413 c.anchor = GridBagConstraints.CENTER;
417 lon = new AltosMapPos(owner,
422 c.fill = GridBagConstraints.NONE;
423 c.anchor = GridBagConstraints.CENTER;
431 c.anchor = GridBagConstraints.CENTER;
435 load_button = new JToggleButton("Load Map");
436 load_button.addActionListener(this);
437 load_button.setActionCommand("load");
439 c.fill = GridBagConstraints.NONE;
440 c.anchor = GridBagConstraints.CENTER;
448 c.anchor = GridBagConstraints.CENTER;
450 pane.add(load_button, c);
452 close_button = new JButton("Close");
453 close_button.addActionListener(this);
454 close_button.setActionCommand("close");
456 c.fill = GridBagConstraints.NONE;
457 c.anchor = GridBagConstraints.CENTER;
465 c.anchor = GridBagConstraints.CENTER;
467 pane.add(close_button, c);
470 setLocationRelativeTo(owner);