altosdroid: Switch to four tabs (pad/flight/recover/map)
[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_7.*;
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 Spinner         tile_radius;
65
66         private EditText        latitude;
67         private EditText        longitude;
68
69         private ProgressBar     progress;
70
71         /* AltosMapLoaderListener interfaces */
72         public void loader_start(final int max) {
73                 this.runOnUiThread(new Runnable() {
74                                 public void run() {
75                                         progress.setMax(max);
76                                         progress.setProgress(0);
77                                 }
78                         });
79         }
80
81         public void loader_notify(final int cur, final int max, final String name) {
82                 this.runOnUiThread(new Runnable() {
83                                 public void run() {
84                                         progress.setProgress(cur);
85                                 }
86                         });
87         }
88
89         public void loader_done(int max) {
90                 this.runOnUiThread(new Runnable() {
91                                 public void run() {
92                                         progress.setProgress(0);
93                                         finish();
94                                 }
95                         });
96         }
97
98         /* AltosLaunchSiteListener interface */
99         public void notify_launch_sites(final List<AltosLaunchSite> sites) {
100                 this.runOnUiThread(new Runnable() {
101                                 public void run() {
102                                         for (AltosLaunchSite site : sites)
103                                                 known_sites_adapter.add(site);
104                                 }
105                         });
106         }
107
108         AltosMap        map;
109         AltosMapLoader  loader;
110
111         class PreloadMapImage implements AltosImage {
112                 public void flush() {
113                 }
114
115                 public PreloadMapImage(File file) {
116                 }
117         }
118
119         public AltosMapPath new_path() {
120                 return null;
121         }
122
123         public AltosMapLine new_line() {
124                 return null;
125         }
126
127         public AltosImage load_image(File file) throws Exception {
128                 return new PreloadMapImage(file);
129         }
130
131         public AltosMapMark new_mark(double lat, double lon, int state) {
132                 return null;
133         }
134
135         class PreloadMapTile extends AltosMapTile {
136                 public void paint(AltosMapTransform t) {
137                 }
138
139                 public PreloadMapTile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
140                         super(listener, upper_left, center, zoom, maptype, px_size, 2);
141                 }
142
143         }
144
145         public AltosMapTile new_tile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
146                 return new PreloadMapTile(listener, upper_left, center, zoom, maptype, px_size);
147         }
148
149         public int width() {
150                 return AltosMap.px_size;
151         }
152
153         public int height() {
154                 return AltosMap.px_size;
155         }
156
157         public void repaint() {
158         }
159
160         public void repaint(AltosRectangle damage) {
161         }
162
163         public void set_zoom_label(String label) {
164         }
165
166         public void select_object(AltosLatLon latlon) {
167         }
168
169         public void debug(String format, Object ... arguments) {
170                 AltosDebug.debug(format, arguments);
171         }
172
173         /* LocationProvider interface */
174
175         AltosLaunchSite current_location_site;
176
177         public void onLocationChanged(Location location) {
178                 AltosDebug.debug("location changed");
179                 if (current_location_site == null) {
180                         AltosLaunchSite selected_item = (AltosLaunchSite) known_sites_spinner.getSelectedItem();
181
182                         current_location_site = new AltosLaunchSite("Current Location", location.getLatitude(), location.getLongitude());
183                         known_sites_adapter.insert(current_location_site, 0);
184
185                         if (selected_item != null)
186                                 known_sites_spinner.setSelection(known_sites_adapter.getPosition(selected_item));
187                         else {
188                                 latitude.setText(new StringBuffer(String.format("%12.6f", current_location_site.latitude)));
189                                 longitude.setText(new StringBuffer(String.format("%12.6f", current_location_site.longitude)));
190                         }
191                 } else {
192                         current_location_site.latitude = location.getLatitude();
193                         current_location_site.longitude = location.getLongitude();
194                 }
195         }
196
197         public void onStatusChanged(String provider, int status, Bundle extras) {
198         }
199
200         public void onProviderEnabled(String provider) {
201         }
202
203         public void onProviderDisabled(String provider) {
204         }
205
206         private double text(EditText view) throws ParseException {
207                 return AltosParse.parse_double_locale(view.getEditableText().toString());
208         }
209
210         private double latitude() throws ParseException {
211                 return text(latitude);
212         }
213
214         private double longitude() throws ParseException {
215                 return text(longitude);
216         }
217
218         private int value(Spinner spinner) {
219                 return (Integer) spinner.getSelectedItem();
220         }
221
222         private int min_z() {
223                 return value(min_zoom);
224         }
225
226         private int max_z() {
227                 return value(max_zoom);
228         }
229
230         private int radius() {
231                 return value(tile_radius);
232         }
233
234         private int bit(CheckBox box, int value) {
235                 if (box.isChecked())
236                         return 1 << value;
237                 return 0;
238         }
239
240         private int types() {
241                 return (bit(hybrid, AltosMap.maptype_hybrid) |
242                         bit(satellite, AltosMap.maptype_satellite) |
243                         bit(roadmap, AltosMap.maptype_roadmap) |
244                         bit(terrain, AltosMap.maptype_terrain));
245         }
246
247         private void load() {
248                 try {
249                         double  lat = latitude();
250                         double  lon = longitude();
251                         int     min = min_z();
252                         int     max = max_z();
253                         int     r = radius();
254                         int     t = types();
255
256                         loader.load(lat, lon, min, max, r, t);
257                 } catch (ParseException e) {
258                 }
259         }
260
261         private void add_numbers(Spinner spinner, int min, int max, int def) {
262
263                 ArrayAdapter<Integer> adapter = new ArrayAdapter<Integer>(this, android.R.layout.simple_spinner_item);
264
265                 int     spinner_def = 0;
266                 int     pos = 0;
267
268                 for (int i = min; i <= max; i++) {
269                         adapter.add(new Integer(i));
270                         if (i == def)
271                                 spinner_def = pos;
272                         pos++;
273                 }
274
275                 spinner.setAdapter(adapter);
276                 spinner.setSelection(spinner_def);
277         }
278
279         class SiteListListener implements OnItemSelectedListener {
280                 public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
281                         AltosLaunchSite site = (AltosLaunchSite) parent.getItemAtPosition(pos);
282                         latitude.setText(new StringBuffer(String.format("%12.6f", site.latitude)));
283                         longitude.setText(new StringBuffer(String.format("%12.6f", site.longitude)));
284                 }
285                 public void onNothingSelected(AdapterView<?> parent) {
286                 }
287
288                 public SiteListListener() {
289                 }
290         }
291
292         @Override
293         protected void onCreate(Bundle savedInstanceState) {
294                 super.onCreate(savedInstanceState);
295
296                 // Setup the window
297                 requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
298                 setContentView(R.layout.map_preload);
299
300                 // Set result CANCELED incase the user backs out
301                 setResult(Activity.RESULT_CANCELED);
302
303                 // Initialize the button to perform device discovery
304                 Button loadButton = (Button) findViewById(R.id.preload_load);
305                 loadButton.setOnClickListener(new OnClickListener() {
306                         public void onClick(View v) {
307                                 load();
308                         }
309                 });
310
311                 latitude = (EditText) findViewById(R.id.preload_latitude);
312                 longitude = (EditText) findViewById(R.id.preload_longitude);
313
314                 hybrid = (CheckBox) findViewById(R.id.preload_hybrid);
315                 satellite = (CheckBox) findViewById(R.id.preload_satellite);
316                 roadmap = (CheckBox) findViewById(R.id.preload_roadmap);
317                 terrain = (CheckBox) findViewById(R.id.preload_terrain);
318
319                 hybrid.setChecked(true);
320
321                 min_zoom = (Spinner) findViewById(R.id.preload_min_zoom);
322                 add_numbers(min_zoom,
323                             AltosMap.min_zoom - AltosMap.default_zoom,
324                             AltosMap.max_zoom - AltosMap.default_zoom, -2);
325                 max_zoom = (Spinner) findViewById(R.id.preload_max_zoom);
326                 add_numbers(max_zoom,
327                             AltosMap.min_zoom - AltosMap.default_zoom,
328                             AltosMap.max_zoom - AltosMap.default_zoom, 2);
329                 tile_radius = (Spinner) findViewById(R.id.preload_tile_radius);
330                 add_numbers(tile_radius, 1, 5, 5);
331
332                 progress = (ProgressBar) findViewById(R.id.preload_progress);
333
334                 // Initialize array adapters. One for already paired devices and
335                 // one for newly discovered devices
336                 known_sites_spinner = (Spinner) findViewById(R.id.preload_site_list);
337
338                 known_sites_adapter = new ArrayAdapter<AltosLaunchSite>(this, android.R.layout.simple_spinner_item);
339
340                 known_sites_adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
341
342                 known_sites_spinner.setAdapter(known_sites_adapter);
343                 known_sites_spinner.setOnItemSelectedListener(new SiteListListener());
344
345                 map = new AltosMap(this);
346
347                 loader = new AltosMapLoader(map, this);
348
349                 // Listen for GPS and Network position updates
350                 LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
351
352                 locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 1, this);
353
354                 new AltosLaunchSites(this);
355         }
356
357         @Override
358         protected void onDestroy() {
359                 super.onDestroy();
360
361                 // Stop listening for location updates
362                 ((LocationManager) getSystemService(Context.LOCATION_SERVICE)).removeUpdates(this);
363         }
364 }