Switch from GPLv2 to GPLv2+
[fw/altos] / altosdroid / src / org / altusmetrum / AltosDroid / AltosMapOffline.java
index 3ff6ff25add55c533f95d0fcfac86a0075686e31..76771adcfce6246ae3b57078be6ff2338f4f5a7e 100644 (file)
@@ -3,7 +3,8 @@
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -20,7 +21,7 @@ package org.altusmetrum.AltosDroid;
 import java.util.*;
 import java.io.*;
 
-import org.altusmetrum.altoslib_7.*;
+import org.altusmetrum.altoslib_11.*;
 
 import android.app.Activity;
 import android.graphics.*;
@@ -36,7 +37,9 @@ import android.util.*;
 class Rocket implements Comparable {
        AltosLatLon     position;
        String          name;
+       int             serial;
        long            last_packet;
+       boolean         active;
        AltosMapOffline map_offline;
 
        void paint() {
@@ -49,14 +52,18 @@ class Rocket implements Comparable {
                this.last_packet = last_packet;
        }
 
-       Rocket(String name, AltosMapOffline map_offline) {
-               this.name = name;
-               this.map_offline = map_offline;
+       void set_active(boolean active) {
+               this.active = active;
        }
 
        public int compareTo(Object o) {
                Rocket other = (Rocket) o;
 
+               if (active && !other.active)
+                       return 1;
+               if (other.active && !active)
+                       return -1;
+
                long    diff = last_packet - other.last_packet;
 
                if (diff > 0)
@@ -65,14 +72,24 @@ class Rocket implements Comparable {
                        return -1;
                return 0;
        }
+
+       Rocket(int serial, AltosMapOffline map_offline) {
+               this.serial = serial;
+               this.name = String.format("%d", serial);
+               this.map_offline = map_offline;
+       }
 }
 
-public class AltosMapOffline extends View implements ScaleGestureDetector.OnScaleGestureListener, AltosMapInterface, AltosDroidMapInterface {
+public class AltosMapOffline extends View implements ScaleGestureDetector.OnScaleGestureListener, AltosMapInterface, AltosDroidMapInterface, AltosMapTypeListener {
        ScaleGestureDetector    scale_detector;
        boolean                 scaling;
        AltosMap                map;
+       AltosDroid              altos_droid;
+
+       static int scale = 2;
 
        AltosLatLon     here;
+       AltosLatLon     there;
        AltosLatLon     pad;
 
        Canvas  canvas;
@@ -119,7 +136,7 @@ public class AltosMapOffline extends View implements ScaleGestureDetector.OnScal
                        if (canvas.quickReject(pt.x, pt.y, pt.x + px_size, pt.y + px_size, Canvas.EdgeType.AA))
                                return;
 
-                       AltosImage              altos_image = cache.get(this, store, px_size, px_size);
+                       AltosImage              altos_image = this.get_image();
 
                        MapImage                map_image = (MapImage) altos_image;
 
@@ -136,8 +153,8 @@ public class AltosMapOffline extends View implements ScaleGestureDetector.OnScal
                                if (t.has_location()) {
                                        String  message = null;
                                        switch (status) {
-                                       case AltosMapTile.loading:
-                                               message = "Loading...";
+                                       case AltosMapTile.fetching:
+                                               message = "Fetching...";
                                                break;
                                        case AltosMapTile.bad_request:
                                                message = "Internal error";
@@ -167,14 +184,14 @@ public class AltosMapOffline extends View implements ScaleGestureDetector.OnScal
                        }
                }
 
-               public MapTile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
-                       super(listener, upper_left, center, zoom, maptype, px_size, 2);
+               public MapTile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size, int scale) {
+                       super(cache, upper_left, center, zoom, maptype, px_size, scale);
                }
 
        }
 
-       public AltosMapTile new_tile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
-               return new MapTile(listener, upper_left, center, zoom, maptype, px_size);
+       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);
        }
 
        public AltosMapPath new_path() {
@@ -236,6 +253,27 @@ public class AltosMapOffline extends View implements ScaleGestureDetector.OnScal
        public void set_zoom_label(String label) {
        }
 
+       public void select_object(AltosLatLon latlon) {
+               if (map.transform == null)
+                       return;
+               ArrayList<Integer>      near = new ArrayList<Integer>();
+
+               for (Rocket rocket : sorted_rockets()) {
+                       if (rocket.position == null) {
+                               debug("rocket %d has no position\n", rocket.serial);
+                               continue;
+                       }
+                       double distance = map.transform.hypot(latlon, rocket.position);
+                       debug("check select %d distance %g width %d\n", rocket.serial, distance, rocket_bitmap.getWidth());
+                       if (distance < rocket_bitmap.getWidth() * 2.0) {
+                               debug("selecting %d\n", rocket.serial);
+                               near.add(rocket.serial);
+                       }
+               }
+               if (near.size() != 0)
+                       altos_droid.touch_trackers(near.toArray(new Integer[0]));
+       }
+
        class Line {
                AltosLatLon     a, b;
 
@@ -295,16 +333,20 @@ public class AltosMapOffline extends View implements ScaleGestureDetector.OnScal
                }
        }
 
+       private Rocket[] sorted_rockets() {
+               Rocket[]        rocket_array = rockets.values().toArray(new Rocket[0]);
+
+               Arrays.sort(rocket_array);
+               return rocket_array;
+       }
+
        private void draw_positions() {
-               line.set_a(map.last_position);
+               line.set_a(there);
                line.set_b(here);
                line.paint();
                draw_bitmap(pad, pad_bitmap, pad_off_x, pad_off_y);
 
-               Rocket[]        rocket_array = rockets.values().toArray(new Rocket[0]);
-
-               Arrays.sort(rocket_array);
-               for (Rocket rocket : rocket_array)
+               for (Rocket rocket : sorted_rockets())
                        rocket.paint();
                draw_bitmap(here, here_bitmap, here_off_x, here_off_y);
        }
@@ -323,7 +365,6 @@ public class AltosMapOffline extends View implements ScaleGestureDetector.OnScal
 
        @Override
        protected void onDraw(Canvas view_canvas) {
-               debug("onDraw");
                if (map == null) {
                        debug("MapView draw without map\n");
                        return;
@@ -379,6 +420,8 @@ public class AltosMapOffline extends View implements ScaleGestureDetector.OnScal
                        map.touch_start((int) event.getX(), (int) event.getY(), true);
                } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
                        map.touch_continue((int) event.getX(), (int) event.getY(), true);
+               } else if (event.getAction() == MotionEvent.ACTION_UP) {
+                       map.touch_stop((int) event.getX(), (int) event.getY(), true);
                }
                return true;
        }
@@ -386,7 +429,7 @@ public class AltosMapOffline extends View implements ScaleGestureDetector.OnScal
        double  mapAccuracy;
 
        public void center(double lat, double lon, double accuracy) {
-               if (mapAccuracy < 0 || accuracy < mapAccuracy/10) {
+               if (mapAccuracy <= 0 || accuracy < mapAccuracy/10 || (map != null && !map.has_centre())) {
                        if (map != null)
                                map.maybe_centre(lat, lon);
                        mapAccuracy = accuracy;
@@ -401,6 +444,8 @@ public class AltosMapOffline extends View implements ScaleGestureDetector.OnScal
        }
 
        public void show(TelemetryState telem_state, AltosState state, AltosGreatCircle from_receiver, Location receiver) {
+               boolean changed = false;
+
                if (state != null) {
                        map.show(state, null);
                        if (state.pad_lat != AltosLib.MISSING && pad == null)
@@ -425,21 +470,34 @@ public class AltosMapOffline extends View implements ScaleGestureDetector.OnScal
                                if (rockets.containsKey(serial))
                                        rocket = rockets.get(serial);
                                else {
-                                       rocket = new Rocket(String.format("%d", serial), this);
+                                       rocket = new Rocket(serial, this);
                                        rockets.put(serial, rocket);
                                }
-                               if (t_state.gps != null)
-                                       rocket.set_position(new AltosLatLon(t_state.gps.lat, t_state.gps.lon), t_state.received_time);
+                               if (t_state.gps != null) {
+                                       AltosLatLon     latlon = new AltosLatLon(t_state.gps.lat, t_state.gps.lon);
+                                       rocket.set_position(latlon, t_state.received_time);
+                                       if (state.serial == serial)
+                                               there = latlon;
+                               }
+                               if (state != null)
+                                       rocket.set_active(state.serial == serial);
                        }
                }
                if (receiver != null) {
-                       here = new AltosLatLon(receiver.getLatitude(), receiver.getLongitude());
+                       AltosLatLon new_here = new AltosLatLon(receiver.getLatitude(), receiver.getLongitude());
+                       if (!new_here.equals(here)) {
+                               here = new_here;
+                               AltosDebug.debug("Location changed, redraw");
+                               repaint();
+                       }
                }
        }
 
-       public void onCreateView(int map_type) {
-               map = new AltosMap(this);
-               map.set_maptype(map_type);
+       public void onCreateView(AltosDroid altos_droid) {
+               this.altos_droid = altos_droid;
+               map = new AltosMap(this, scale);
+               AltosPreferences.register_map_type_listener(this);
+               map.set_maptype(AltosPreferences.map_type());
 
                pad_bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.pad);
                /* arrow at the bottom of the launchpad image */
@@ -457,13 +515,18 @@ public class AltosMapOffline extends View implements ScaleGestureDetector.OnScal
                here_off_y = here_bitmap.getHeight() / 2;
        }
 
-       public void set_map_type(int map_type) {
+       public void onDestroyView() {
+               AltosPreferences.unregister_map_type_listener(this);
+       }
+
+       public void map_type_changed(int map_type) {
                if (map != null)
                        map.set_maptype(map_type);
        }
 
        public AltosMapOffline(Context context, AttributeSet attrs) {
                super(context, attrs);
+               this.altos_droid = altos_droid;
                scale_detector = new ScaleGestureDetector(context, this);
        }
 }