first cut at turnon scripts for EasyTimer v2
[fw/altos] / altosuilib / AltosUIMap.java
index 2e1e8f160bf8f5a2899c1993c1a534a9bdb224d6..0a80959fe80a9c02416968f8e35beed860f03f3e 100644 (file)
@@ -16,7 +16,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altosuilib_12;
+package org.altusmetrum.altosuilib_14;
 
 import java.awt.*;
 import java.awt.event.*;
@@ -28,7 +28,7 @@ import java.awt.geom.*;
 import java.util.*;
 import java.util.concurrent.*;
 import javax.imageio.*;
-import org.altusmetrum.altoslib_12.*;
+import org.altusmetrum.altoslib_14.*;
 
 public class AltosUIMap extends JComponent implements AltosFlightDisplay, AltosMapInterface {
 
@@ -36,6 +36,7 @@ public class AltosUIMap extends JComponent implements AltosFlightDisplay, AltosM
        Graphics2D      g;
        Font            tile_font;
        Font            line_font;
+       AltosMapMark    nearest_mark;
 
        static Point2D.Double point2d(AltosPointDouble pt) {
                return new Point2D.Double(pt.x, pt.y);
@@ -47,20 +48,48 @@ public class AltosUIMap extends JComponent implements AltosFlightDisplay, AltosM
 
        class MapMark extends AltosMapMark {
                public void paint(AltosMapTransform t) {
-                       AltosPointDouble pt = t.screen(lat_lon);
-
-                       g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
-                                          RenderingHints.VALUE_ANTIALIAS_ON);
-                       g.setStroke(new BasicStroke(stroke_width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
-
-                       if (0 <= state && state < AltosUIMap.stateColors.length)
-                               g.setColor(AltosUIMap.stateColors[state]);
-                       else
-                               g.setColor(AltosUIMap.stateColors[AltosLib.ao_flight_invalid]);
+                       double lat = lat_lon.lat;
+                       double lon;
+                       double first_lon = t.first_lon(lat_lon.lon);
+                       double last_lon = t.last_lon(lat_lon.lon);
+                       for (lon = first_lon; lon <= last_lon; lon += 360.0) {
+                               AltosPointDouble pt = t.screen(lat, lon);
+
+                               g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+                                                  RenderingHints.VALUE_ANTIALIAS_ON);
+                               g.setStroke(new BasicStroke(stroke_width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
+
+                               if (0 <= state && state < AltosUIMap.stateColors.length)
+                                       g.setColor(AltosUIMap.stateColors[state]);
+                               else
+                                       g.setColor(AltosUIMap.stateColors[AltosLib.ao_flight_invalid]);
+
+                               g.drawOval((int)pt.x-5, (int)pt.y-5, 10, 10);
+                               g.drawOval((int)pt.x-20, (int)pt.y-20, 40, 40);
+                               g.drawOval((int)pt.x-35, (int)pt.y-35, 70, 70);
+
+                               if (label != null) {
+                                       Rectangle2D     bounds;
+                                       bounds = line_font.getStringBounds(label, g.getFontRenderContext());
+                                       float x = (float) pt.x;
+                                       float y = (float) pt.y + (float) bounds.getHeight() / 2.0f;
+
+                                       g.setFont(line_font);
+                                       g.setColor(Color.WHITE);
+                                       for (int dy = -2; dy <= 2; dy += 2)
+                                               for (int dx = -2; dx <= 2; dx += 2)
+                                                       g.drawString(label, x + dx, y + dy);
+                                       if (0 <= state && state < AltosUIMap.stateColors.length)
+                                               g.setColor(AltosUIMap.stateColors[state]);
+                                       else
+                                               g.setColor(AltosUIMap.stateColors[AltosLib.ao_flight_invalid]);
+                                       g.drawString(label, x, y);
+                               }
+                       }
+               }
 
-                       g.drawOval((int)pt.x-5, (int)pt.y-5, 10, 10);
-                       g.drawOval((int)pt.x-20, (int)pt.y-20, 40, 40);
-                       g.drawOval((int)pt.x-35, (int)pt.y-35, 70, 70);
+               MapMark(double lat, double lon, int state, String label) {
+                       super(lat, lon, state, label);
                }
 
                MapMark(double lat, double lon, int state) {
@@ -106,7 +135,7 @@ public class AltosUIMap extends JComponent implements AltosFlightDisplay, AltosM
                }
 
                private boolean is_drag_event(MouseEvent e) {
-                       return e.getModifiers() == InputEvent.BUTTON1_MASK;
+                       return e.getModifiersEx() == InputEvent.BUTTON1_DOWN_MASK;
                }
 
                /* MouseMotionListener methods */
@@ -115,7 +144,61 @@ public class AltosUIMap extends JComponent implements AltosFlightDisplay, AltosM
                        map.touch_continue(e.getPoint().x, e.getPoint().y, is_drag_event(e));
                }
 
+               String pos(double p, String pos, String neg) {
+                       if (p == AltosLib.MISSING)
+                               return "";
+                       String  h = pos;
+                       if (p < 0) {
+                               h = neg;
+                               p = -p;
+                       }
+                       int deg = (int) Math.floor(p);
+                       double min = (p - Math.floor(p)) * 60.0;
+                       return String.format("%s %4d° %9.6f'", h, deg, min);
+               }
+
+               String height(double h, String label) {
+                       if (h == AltosLib.MISSING)
+                               return "";
+                       return String.format(" %s%s",
+                                            AltosConvert.height.show(6, h),
+                                            label);
+               }
+
+               String speed(double s, String label) {
+                       if (s == AltosLib.MISSING)
+                               return "";
+                       return String.format(" %s%s",
+                                            AltosConvert.speed.show(6, s),
+                                            label);
+               }
+
                public void mouseMoved(MouseEvent e) {
+                       AltosMapPathPoint point = map.nearest(e.getPoint().x, e.getPoint().y);
+
+                       if (point != null) {
+                               if (nearest_mark == null)
+                                       nearest_mark = map.add_mark(point.gps.lat,
+                                                                   point.gps.lon,
+                                                                   point.state);
+                               else {
+                                       nearest_mark.lat_lon.lat = point.gps.lat;
+                                       nearest_mark.lat_lon.lon = point.gps.lon;
+                                       nearest_mark.state = point.state;
+                               }
+                               nearest_label.setText(String.format("%9.2f sec %s%s%s%s",
+                                                                   point.time,
+                                                                   pos(point.gps.lat,
+                                                                       "N", "S"),
+                                                                   pos(point.gps.lon,
+                                                                       "E", "W"),
+                                                                   height(point.gps_height, ""),
+                                                                   speed(point.gps.ground_speed, "(h)"),
+                                                                   speed(point.gps.climb_rate, "(v)")));
+                       } else {
+                               nearest_label.setText("");
+                       }
+                       repaint();
                }
 
                /* MouseListener methods */
@@ -222,7 +305,7 @@ public class AltosUIMap extends JComponent implements AltosFlightDisplay, AltosM
                        g.setStroke(new BasicStroke(stroke_width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
 
                        for (AltosMapPathPoint point : points) {
-                               Point2D.Double  cur = point2d(t.screen(point.lat_lon));
+                               Point2D.Double  cur = point2d(t.screen(point.gps.lat, point.gps.lon));
                                if (prev != null) {
                                        Line2D.Double   line = new Line2D.Double (prev, cur);
                                        Rectangle       bounds = line.getBounds();
@@ -264,6 +347,21 @@ public class AltosUIMap extends JComponent implements AltosFlightDisplay, AltosM
 
                        if (image != null) {
                                g.drawImage(image, point.x, point.y, null);
+/*
+ * Useful when debugging map fetching problems
+ *
+                               String message = String.format("%.6f %.6f", center.lat, center.lon);
+                               g.setFont(tile_font);
+                               g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+                               Rectangle2D bounds = tile_font.getStringBounds(message, g.getFontRenderContext());
+
+                               float x = px_size / 2.0f;
+                               float y = px_size / 2.0f;
+                               x = x - (float) bounds.getWidth() / 2.0f;
+                               y = y + (float) bounds.getHeight() / 2.0f;
+                               g.setColor(Color.RED);
+                               g.drawString(message, (float) point_double.x + x, (float) point_double.y + y);
+*/
                        } else {
                                g.setColor(Color.GRAY);
                                g.fillRect(point.x, point.y, px_size, px_size);
@@ -278,10 +376,10 @@ public class AltosUIMap extends JComponent implements AltosFlightDisplay, AltosM
                                                message = "Internal error";
                                                break;
                                        case AltosMapTile.failed:
-                                               message = "Network error, check connection";
+                                               message = "Network error";
                                                break;
                                        case AltosMapTile.forbidden:
-                                               message = "Too many requests, try later";
+                                               message = "Outside of known launch areas";
                                                break;
                                        }
                                        if (message != null && tile_font != null) {
@@ -333,6 +431,10 @@ public class AltosUIMap extends JComponent implements AltosFlightDisplay, AltosM
                return new MapMark(lat, lon, state);
        }
 
+       public AltosMapMark new_mark(double lat, double lon, int state, String label) {
+               return new MapMark(lat, lon, state, label);
+       }
+
        public AltosMapTile new_tile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size, int scale) {
                return new MapTile(cache, upper_left, center, zoom, maptype, px_size, scale);
        }
@@ -372,6 +474,8 @@ public class AltosUIMap extends JComponent implements AltosFlightDisplay, AltosM
        public void set_font() {
                tile_font = AltosUILib.value_font;
                line_font = AltosUILib.status_font;
+               if (nearest_label != null)
+                       nearest_label.setFont(AltosUILib.value_font);
        }
 
        public void font_size_changed(int font_size) {
@@ -385,9 +489,13 @@ public class AltosUIMap extends JComponent implements AltosFlightDisplay, AltosM
 
        JLabel  zoom_label;
 
+       JLabel  nearest_label;
+
        public void set_maptype(int type) {
+/*
                map.set_maptype(type);
                maptype_combo.setSelectedIndex(type);
+*/
        }
 
        /* AltosUIMapPreload functions */
@@ -400,6 +508,10 @@ public class AltosUIMap extends JComponent implements AltosFlightDisplay, AltosM
                map.add_mark(lat, lon, status);
        }
 
+       public void add_mark(double lat, double lon, int status, String label) {
+               map.add_mark(lat, lon, status, label);
+       }
+
        public void clear_marks() {
                map.clear_marks();
        }
@@ -413,8 +525,8 @@ public class AltosUIMap extends JComponent implements AltosFlightDisplay, AltosM
                map.show(state, listener_state);
        }
 
-       public void show(AltosGPS gps, int state) {
-               map.show(gps, state);
+       public void show(AltosGPS gps, double time, int state, double gps_height) {
+               map.show(gps, time, state, gps_height);
        }
 
        public String getName() {
@@ -433,7 +545,9 @@ public class AltosUIMap extends JComponent implements AltosFlightDisplay, AltosM
        /* internal layout bits */
        private GridBagLayout layout = new GridBagLayout();
 
+/*
        JComboBox<String>       maptype_combo;
+*/
 
        MapView view;
 
@@ -522,6 +636,21 @@ public class AltosUIMap extends JComponent implements AltosFlightDisplay, AltosM
                c.weighty = 0;
                add(zoom_out, c);
 
+
+               nearest_label = new JLabel("", JLabel.LEFT);
+               nearest_label.setFont(tile_font);
+
+               c = new GridBagConstraints();
+               c.anchor = GridBagConstraints.CENTER;
+               c.fill = GridBagConstraints.HORIZONTAL;
+               c.gridx = 0;
+               c.gridy = 11;
+               c.weightx = 0;
+               c.weighty = 0;
+               c.gridwidth = 1;
+               c.gridheight = 1;
+               add(nearest_label, c);
+/*
                maptype_combo = new JComboBox<String>(map.maptype_labels);
 
                maptype_combo.setEditable(false);
@@ -540,7 +669,7 @@ public class AltosUIMap extends JComponent implements AltosFlightDisplay, AltosM
                c.weightx = 0;
                c.weighty = 0;
                add(maptype_combo, c);
-
+*/
                map = new AltosMap(this);
        }
 }