altoslib: Allow map preloading to be aborted
authorKeith Packard <keithp@keithp.com>
Wed, 11 May 2016 06:02:09 +0000 (23:02 -0700)
committerKeith Packard <keithp@keithp.com>
Thu, 12 May 2016 06:22:15 +0000 (23:22 -0700)
Close the map preload dialog and it would be nice to stop loading map
bits.

Signed-off-by: Keith Packard <keithp@keithp.com>
altosdroid/src/org/altusmetrum/AltosDroid/PreloadMapActivity.java
altoslib/AltosMapLoader.java
altoslib/AltosMapTile.java
altosuilib/AltosUIMapPreloadNew.java

index 0bf3aa1..ab5e433 100644 (file)
@@ -69,6 +69,10 @@ public class PreloadMapActivity extends Activity implements AltosLaunchSiteListe
 
        private ProgressBar     progress;
 
+       private AltosMapLoader  loader;
+
+       long    loader_notify_time;
+
        /* AltosMapLoaderListener interfaces */
        public void loader_start(final int max) {
                this.runOnUiThread(new Runnable() {
@@ -88,6 +92,7 @@ public class PreloadMapActivity extends Activity implements AltosLaunchSiteListe
        }
 
        public void loader_done(int max) {
+               loader = null;
                this.runOnUiThread(new Runnable() {
                                public void run() {
                                        progress.setProgress(0);
@@ -254,6 +259,9 @@ public class PreloadMapActivity extends Activity implements AltosLaunchSiteListe
        }
 
        private void load() {
+               if (loader != null)
+                       return;
+
                try {
                        double  lat = latitude();
                        double  lon = longitude();
@@ -264,7 +272,7 @@ public class PreloadMapActivity extends Activity implements AltosLaunchSiteListe
 
                        AltosDebug.debug("PreloadMap load %f %f %d %d %f %d\n",
                                         lat, lon, min, max, r, t);
-                       new AltosMapLoader(map, this, lat, lon, min, max, r, t);
+                       loader = new AltosMapLoader(map, this, lat, lon, min, max, r, t);
                } catch (ParseException e) {
                        AltosDebug.debug("PreloadMap load raised exception %s", e.toString());
                }
@@ -409,6 +417,9 @@ public class PreloadMapActivity extends Activity implements AltosLaunchSiteListe
        protected void onDestroy() {
                super.onDestroy();
 
+               if (loader != null)
+                       loader.abort();
+
                // Stop listening for location updates
                ((LocationManager) getSystemService(Context.LOCATION_SERVICE)).removeUpdates(this);
        }
index 7112a1c..8b856e1 100644 (file)
@@ -19,6 +19,7 @@ package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 import java.util.*;
+import java.util.concurrent.*;
 import java.text.*;
 import java.lang.Math;
 import java.net.URL;
@@ -42,6 +43,12 @@ public class AltosMapLoader extends Thread implements AltosMapTileListener {
        int     layers_total;
        int     layers_loaded;
 
+       private static final int        MAX_LOADING = 200;
+
+       private Semaphore       loading = new Semaphore(MAX_LOADING);
+
+       boolean abort;
+
        AltosMap        map;
 
        int tile_radius(int zoom) {
@@ -62,7 +69,7 @@ public class AltosMapLoader extends Thread implements AltosMapTileListener {
                return (tile_radius * 2 + 1) * (tile_radius * 2 + 1);
        }
 
-       public void do_load() {
+       private boolean do_load() {
                tiles_this_layer = tiles_per_layer(cur_z);
                tiles_loaded_layer = 0;
                listener.debug("tiles_this_layer %d (zoom %d)\n", tiles_this_layer, cur_z);
@@ -88,16 +95,24 @@ public class AltosMapLoader extends Thread implements AltosMapTileListener {
 
                for (int y = (int) upper_left.y; y <= lower_right.y; y += AltosMap.px_size) {
                        for (int x = (int) upper_left.x; x <= lower_right.x; x += AltosMap.px_size) {
+                               try {
+                                       loading.acquire();
+                               } catch (InterruptedException ie) {
+                                       return false;
+                               }
                                AltosPointInt   point = new AltosPointInt(x, y);
                                AltosLatLon     ul = transform.lat_lon(point);
                                AltosLatLon     center = transform.lat_lon(new AltosPointDouble(x + AltosMap.px_size/2, y + AltosMap.px_size/2));
-                               AltosMapTile    tile = map.map_interface.new_tile(null, ul, center, zoom, maptype, AltosMap.px_size);
+                               AltosMapTile    tile = new AltosMapTile(null, ul, center, zoom, maptype, AltosMap.px_size);
                                tile.add_listener(this);
+                               if (abort)
+                                       return false;
                        }
                }
+               return true;
        }
 
-       public int next_type(int start) {
+       private int next_type(int start) {
                int next_type;
                for (next_type = start;
                     next_type <= AltosMap.maptype_terrain && (all_types & (1 << next_type)) == 0;
@@ -106,19 +121,19 @@ public class AltosMapLoader extends Thread implements AltosMapTileListener {
                return next_type;
        }
 
-       public void next_load() {
+       private boolean next_load() {
                int next_type = next_type(cur_type + 1);
 
                if (next_type > AltosMap.maptype_terrain) {
                        if (cur_z == max_z) {
-                               return;
+                               return false;
                        } else {
                                cur_z++;
                        }
                        next_type = next_type(0);
                }
                cur_type = next_type;
-               do_load();
+               return true;
        }
 
        public void run() {
@@ -147,7 +162,12 @@ public class AltosMapLoader extends Thread implements AltosMapTileListener {
                listener.debug("total tiles %d layers %d\n", tiles_total, layers_total);
 
                listener.loader_start(tiles_total);
-               do_load();
+               do {
+                       if (!do_load())
+                               break;
+               } while (next_load());
+               if (abort)
+                       listener.loader_done(tiles_total);
        }
 
        public synchronized void notify_tile(AltosMapTile tile, int status) {
@@ -155,6 +175,8 @@ public class AltosMapLoader extends Thread implements AltosMapTileListener {
                if (status == AltosMapTile.fetching)
                        return;
 
+               loading.release();
+
                tile.remove_listener(this);
 
                if (layers_loaded >= layers_total)
@@ -174,12 +196,13 @@ public class AltosMapLoader extends Thread implements AltosMapTileListener {
 
                if (tiles_loaded_total == tiles_total)
                        listener.loader_done(tiles_total);
-               else {
+               else
                        listener.loader_notify(tiles_loaded_total,
                                               tiles_total, tile.store.file.toString());
-                       if (do_next)
-                               next_load();
-               }
+       }
+
+       public void abort() {
+               this.abort = true;
        }
 
        public AltosMapLoader(AltosMap map, AltosMapLoaderListener listener,
@@ -194,6 +217,7 @@ public class AltosMapLoader extends Thread implements AltosMapTileListener {
                this.max_z = max_z;
                this.radius = radius;
                this.all_types = all_types;
+               this.abort = false;
                start();
        }
 }
index 1d86309..d921fd1 100644 (file)
@@ -20,7 +20,7 @@ package org.altusmetrum.altoslib_10;
 import java.io.*;
 import java.util.*;
 
-public abstract class AltosMapTile implements AltosFontListener, AltosMapStoreListener {
+public class AltosMapTile implements AltosFontListener, AltosMapStoreListener {
        LinkedList<AltosMapTileListener>        listeners = new LinkedList<AltosMapTileListener>();
        public AltosLatLon      upper_left, center;
        public int              px_size;
@@ -98,7 +98,8 @@ public abstract class AltosMapTile implements AltosFontListener, AltosMapStoreLi
                notify_listeners(status);
        }
 
-       public abstract void paint(AltosMapTransform t);
+       public void paint(AltosMapTransform t) {
+       }
 
        public AltosImage get_image() {
                if (cache == null)
index d6c257e..3e4a604 100644 (file)
@@ -131,7 +131,6 @@ public class AltosUIMapPreloadNew extends AltosUIFrame implements ActionListener
        JComboBox<AltosLaunchSite>      site_list;
 
        JToggleButton   load_button;
-       boolean         loading;
        JButton         close_button;
 
        JCheckBox[]     maptypes = new JCheckBox[AltosMap.maptype_terrain - AltosMap.maptype_hybrid + 1];
@@ -147,6 +146,7 @@ public class AltosUIMapPreloadNew extends AltosUIFrame implements ActionListener
        Double[]        radius_km = { 2.0, 5.0, 10.0, 20.0, 30.0 };
        Double          radius_def_km = 10.0;
 
+       AltosMapLoader  loader;
 
        static final String[]   lat_hemi_names = { "N", "S" };
        static final String[]   lon_hemi_names = { "E", "W" };
@@ -187,12 +187,12 @@ public class AltosUIMapPreloadNew extends AltosUIFrame implements ActionListener
        }
 
        public void loader_done(int max) {
+               loader = null;
                SwingUtilities.invokeLater(new Runnable() {
                                public void run() {
                                        pbar.setValue(0);
                                        pbar.setString("");
                                        load_button.setSelected(false);
-                                       loading = false;
                                }
                        });
        }
@@ -227,11 +227,14 @@ public class AltosUIMapPreloadNew extends AltosUIFrame implements ActionListener
        public void actionPerformed(ActionEvent e) {
                String  cmd = e.getActionCommand();
 
-               if (cmd.equals("close"))
+               if (cmd.equals("close")) {
+                       if (loader != null)
+                               loader.abort();
                        setVisible(false);
+               }
 
                if (cmd.equals("load")) {
-                       if (!loading) {
+                       if (loader == null) {
                                try {
                                        latitude = lat.get_value();
                                        longitude = lon.get_value();
@@ -245,11 +248,10 @@ public class AltosUIMapPreloadNew extends AltosUIFrame implements ActionListener
                                                r = AltosConvert.miles_to_meters(r);
                                        else
                                                r = r * 1000;
-                                       loading = true;
 
-                                       new AltosMapLoader(map.map, this,
-                                                          latitude, longitude,
-                                                          min_z, max_z, r, all_types());
+                                       loader = new AltosMapLoader(map.map, this,
+                                                                   latitude, longitude,
+                                                                   min_z, max_z, r, all_types());
 
                                } catch (ParseException pe) {
                                        load_button.setSelected(false);