Update java library versions
[fw/altos] / altosdroid / src / org / altusmetrum / AltosDroid / PreloadMapActivity.java
1 /*
2  * Copyright © 2015 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 org.altusmetrum.AltosDroid;
19
20 import java.util.*;
21 import java.io.*;
22 import java.text.*;
23
24 import org.altusmetrum.AltosDroid.R;
25
26 import android.app.Activity;
27 import android.bluetooth.BluetoothAdapter;
28 import android.bluetooth.BluetoothDevice;
29 import android.content.BroadcastReceiver;
30 import android.content.Context;
31 import android.content.Intent;
32 import android.content.IntentFilter;
33 import android.os.Bundle;
34 import android.view.View;
35 import android.view.Window;
36 import android.view.View.OnClickListener;
37 import android.widget.*;
38 import android.widget.AdapterView.*;
39 import android.location.Location;
40 import android.location.LocationManager;
41 import android.location.LocationListener;
42 import android.location.Criteria;
43
44 import org.altusmetrum.altoslib_9.*;
45
46 /**
47  * This Activity appears as a dialog. It lists any paired devices and
48  * devices detected in the area after discovery. When a device is chosen
49  * by the user, the MAC address of the device is sent back to the parent
50  * Activity in the result Intent.
51  */
52 public class PreloadMapActivity extends Activity implements AltosLaunchSiteListener, AltosMapInterface, AltosMapLoaderListener, LocationListener {
53
54         private ArrayAdapter<AltosLaunchSite> known_sites_adapter;
55
56         private CheckBox        hybrid;
57         private CheckBox        satellite;
58         private CheckBox        roadmap;
59         private CheckBox        terrain;
60
61         private Spinner         known_sites_spinner;
62         private Spinner         min_zoom;
63         private Spinner         max_zoom;
64         private TextView        radius_label;
65         private Spinner         radius;
66
67         private EditText        latitude;
68         private EditText        longitude;
69
70         private ProgressBar     progress;
71
72         /* AltosMapLoaderListener interfaces */
73         public void loader_start(final int max) {
74                 this.runOnUiThread(new Runnable() {
75                                 public void run() {
76                                         progress.setMax(max);
77                                         progress.setProgress(0);
78                                 }
79                         });
80         }
81
82         public void loader_notify(final int cur, final int max, final String name) {
83                 this.runOnUiThread(new Runnable() {
84                                 public void run() {
85                                         progress.setProgress(cur);
86                                 }
87                         });
88         }
89
90         public void loader_done(int max) {
91                 this.runOnUiThread(new Runnable() {
92                                 public void run() {
93                                         progress.setProgress(0);
94                                         finish();
95                                 }
96                         });
97         }
98
99         /* AltosLaunchSiteListener interface */
100         public void notify_launch_sites(final List<AltosLaunchSite> sites) {
101                 this.runOnUiThread(new Runnable() {
102                                 public void run() {
103                                         for (AltosLaunchSite site : sites)
104                                                 known_sites_adapter.add(site);
105                                 }
106                         });
107         }
108
109         AltosMap        map;
110         AltosMapLoader  loader;
111
112         class PreloadMapImage implements AltosImage {
113                 public void flush() {
114                 }
115
116                 public PreloadMapImage(File file) {
117                 }
118         }
119
120         public AltosMapPath new_path() {
121                 return null;
122         }
123
124         public AltosMapLine new_line() {
125                 return null;
126         }
127
128         public AltosImage load_image(File file) throws Exception {
129                 return new PreloadMapImage(file);
130         }
131
132         public AltosMapMark new_mark(double lat, double lon, int state) {
133                 return null;
134         }
135
136         class PreloadMapTile extends AltosMapTile {
137                 public void paint(AltosMapTransform t) {
138                 }
139
140                 public PreloadMapTile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
141                         super(listener, upper_left, center, zoom, maptype, px_size, 2);
142                 }
143
144         }
145
146         public AltosMapTile new_tile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
147                 return new PreloadMapTile(listener, upper_left, center, zoom, maptype, px_size);
148         }
149
150         public int width() {
151                 return AltosMap.px_size;
152         }
153
154         public int height() {
155                 return AltosMap.px_size;
156         }
157
158         public void repaint() {
159         }
160
161         public void repaint(AltosRectangle damage) {
162         }
163
164         public void set_zoom_label(String label) {
165         }
166
167         public void select_object(AltosLatLon latlon) {
168         }
169
170         public void debug(String format, Object ... arguments) {
171                 AltosDebug.debug(format, arguments);
172         }
173
174         /* LocationProvider interface */
175
176         AltosLaunchSite current_location_site;
177
178         public void onLocationChanged(Location location) {
179                 AltosDebug.debug("location changed");
180                 if (current_location_site == null) {
181                         AltosLaunchSite selected_item = (AltosLaunchSite) known_sites_spinner.getSelectedItem();
182
183                         current_location_site = new AltosLaunchSite("Current Location", location.getLatitude(), location.getLongitude());
184                         known_sites_adapter.insert(current_location_site, 0);
185
186                         if (selected_item != null)
187                                 known_sites_spinner.setSelection(known_sites_adapter.getPosition(selected_item));
188                         else {
189                                 latitude.setText(new StringBuffer(String.format("%12.6f", current_location_site.latitude)));
190                                 longitude.setText(new StringBuffer(String.format("%12.6f", current_location_site.longitude)));
191                         }
192                 } else {
193                         current_location_site.latitude = location.getLatitude();
194                         current_location_site.longitude = location.getLongitude();
195                 }
196         }
197
198         public void onStatusChanged(String provider, int status, Bundle extras) {
199         }
200
201         public void onProviderEnabled(String provider) {
202         }
203
204         public void onProviderDisabled(String provider) {
205         }
206
207         private double text(EditText view) throws ParseException {
208                 return AltosParse.parse_double_locale(view.getEditableText().toString());
209         }
210
211         private double latitude() throws ParseException {
212                 return text(latitude);
213         }
214
215         private double longitude() throws ParseException {
216                 return text(longitude);
217         }
218
219         private int value(Spinner spinner) {
220                 return (Integer) spinner.getSelectedItem();
221         }
222
223         private int min_z() {
224                 return value(min_zoom);
225         }
226
227         private int max_z() {
228                 return value(max_zoom);
229         }
230
231         private double value_distance(Spinner spinner) {
232                 return (Double) spinner.getSelectedItem();
233         }
234
235         private double radius() {
236                 double r = value_distance(radius);
237                 if (AltosPreferences.imperial_units())
238                         r = AltosConvert.distance.inverse(r);
239                 else
240                         r = r * 1000;
241                 return r;
242         }
243
244         private int bit(CheckBox box, int value) {
245                 if (box.isChecked())
246                         return 1 << value;
247                 return 0;
248         }
249
250         private int types() {
251                 return (bit(hybrid, AltosMap.maptype_hybrid) |
252                         bit(satellite, AltosMap.maptype_satellite) |
253                         bit(roadmap, AltosMap.maptype_roadmap) |
254                         bit(terrain, AltosMap.maptype_terrain));
255         }
256
257         private void load() {
258                 try {
259                         double  lat = latitude();
260                         double  lon = longitude();
261                         int     min = min_z();
262                         int     max = max_z();
263                         double  r = radius();
264                         int     t = types();
265
266                         AltosDebug.debug("PreloadMap load %f %f %d %d %f %d\n",
267                                          lat, lon, min, max, r, t);
268                         loader.load(lat, lon, min, max, r, t);
269                 } catch (ParseException e) {
270                         AltosDebug.debug("PreloadMap load raised exception %s", e.toString());
271                 }
272         }
273
274         private void add_numbers(Spinner spinner, int min, int max, int def) {
275
276                 ArrayAdapter<Integer> adapter = new ArrayAdapter<Integer>(this, android.R.layout.simple_spinner_item);
277
278                 int     spinner_def = 0;
279                 int     pos = 0;
280
281                 for (int i = min; i <= max; i++) {
282                         adapter.add(new Integer(i));
283                         if (i == def)
284                                 spinner_def = pos;
285                         pos++;
286                 }
287
288                 spinner.setAdapter(adapter);
289                 spinner.setSelection(spinner_def);
290         }
291
292
293         private void add_distance(Spinner spinner, double[] distances_km, double def_km, double[] distances_mi, double def_mi) {
294
295                 ArrayAdapter<Double> adapter = new ArrayAdapter<Double>(this, android.R.layout.simple_spinner_item);
296
297                 int     spinner_def = 0;
298                 int     pos = 0;
299
300                 double[] distances;
301                 double  def;
302                 if (AltosPreferences.imperial_units()) {
303                         distances = distances_mi;
304                         def = def_mi;
305                 } else {
306                         distances = distances_km;
307                         def = def_km;
308                 }
309
310                 for (int i = 0; i < distances.length; i++) {
311                         adapter.add(distances[i]);
312                         if (distances[i] == def)
313                                 spinner_def = pos;
314                         pos++;
315                 }
316
317                 spinner.setAdapter(adapter);
318                 spinner.setSelection(spinner_def);
319         }
320
321
322
323         class SiteListListener implements OnItemSelectedListener {
324                 public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
325                         AltosLaunchSite site = (AltosLaunchSite) parent.getItemAtPosition(pos);
326                         latitude.setText(new StringBuffer(String.format("%12.6f", site.latitude)));
327                         longitude.setText(new StringBuffer(String.format("%12.6f", site.longitude)));
328                 }
329                 public void onNothingSelected(AdapterView<?> parent) {
330                 }
331
332                 public SiteListListener() {
333                 }
334         }
335
336         double[]        radius_mi = { 1, 2, 5, 10, 20 };
337         double          radius_def_mi = 2;
338         double[]        radius_km = { 1, 2, 5, 10, 20, 30 };
339         double          radius_def_km = 2;
340
341         @Override
342         protected void onCreate(Bundle savedInstanceState) {
343                 super.onCreate(savedInstanceState);
344
345                 // Setup the window
346                 requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
347                 setContentView(R.layout.map_preload);
348
349                 // Set result CANCELED incase the user backs out
350                 setResult(Activity.RESULT_CANCELED);
351
352                 // Initialize the button to perform device discovery
353                 Button loadButton = (Button) findViewById(R.id.preload_load);
354                 loadButton.setOnClickListener(new OnClickListener() {
355                         public void onClick(View v) {
356                                 load();
357                         }
358                 });
359
360                 latitude = (EditText) findViewById(R.id.preload_latitude);
361                 longitude = (EditText) findViewById(R.id.preload_longitude);
362
363                 hybrid = (CheckBox) findViewById(R.id.preload_hybrid);
364                 satellite = (CheckBox) findViewById(R.id.preload_satellite);
365                 roadmap = (CheckBox) findViewById(R.id.preload_roadmap);
366                 terrain = (CheckBox) findViewById(R.id.preload_terrain);
367
368                 hybrid.setChecked(true);
369
370                 min_zoom = (Spinner) findViewById(R.id.preload_min_zoom);
371                 add_numbers(min_zoom,
372                             AltosMap.min_zoom - AltosMap.default_zoom,
373                             AltosMap.max_zoom - AltosMap.default_zoom, -2);
374                 max_zoom = (Spinner) findViewById(R.id.preload_max_zoom);
375                 add_numbers(max_zoom,
376                             AltosMap.min_zoom - AltosMap.default_zoom,
377                             AltosMap.max_zoom - AltosMap.default_zoom, 2);
378                 radius_label = (TextView) findViewById(R.id.preload_radius_label);
379                 radius = (Spinner) findViewById(R.id.preload_radius);
380                 if (AltosPreferences.imperial_units())
381                         radius_label.setText("Radius (miles)");
382                 else
383                         radius_label.setText("Radius (km)");
384                 add_distance(radius, radius_km, radius_def_km, radius_mi, radius_def_mi);
385
386                 progress = (ProgressBar) findViewById(R.id.preload_progress);
387
388                 // Initialize array adapters. One for already paired devices and
389                 // one for newly discovered devices
390                 known_sites_spinner = (Spinner) findViewById(R.id.preload_site_list);
391
392                 known_sites_adapter = new ArrayAdapter<AltosLaunchSite>(this, android.R.layout.simple_spinner_item);
393
394                 known_sites_adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
395
396                 known_sites_spinner.setAdapter(known_sites_adapter);
397                 known_sites_spinner.setOnItemSelectedListener(new SiteListListener());
398
399                 map = new AltosMap(this);
400
401                 loader = new AltosMapLoader(map, this);
402
403                 // Listen for GPS and Network position updates
404                 LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
405
406                 locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 1, this);
407
408                 new AltosLaunchSites(this);
409         }
410
411         @Override
412         protected void onDestroy() {
413                 super.onDestroy();
414
415                 // Stop listening for location updates
416                 ((LocationManager) getSystemService(Context.LOCATION_SERVICE)).removeUpdates(this);
417         }
418 }