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