altosdroid: Add map types and map preloading UIs
authorKeith Packard <keithp@keithp.com>
Thu, 28 May 2015 08:05:18 +0000 (01:05 -0700)
committerKeith Packard <keithp@keithp.com>
Thu, 28 May 2015 08:07:25 +0000 (01:07 -0700)
This adds an ugly dialog to select which maps to preload, and also
adds the ability to display other map types.

Signed-off-by: Keith Packard <keithp@keithp.com>
15 files changed:
altosdroid/AndroidManifest.xml
altosdroid/res/drawable-hdpi/ic_maps_indicator_current_position.png [new file with mode: 0644]
altosdroid/res/drawable-mdpi/ic_maps_indicator_current_position.png [new file with mode: 0644]
altosdroid/res/layout/device_list.xml
altosdroid/res/layout/map_preload.xml [new file with mode: 0644]
altosdroid/res/layout/map_type.xml [new file with mode: 0644]
altosdroid/res/menu/option_menu.xml
altosdroid/res/values/strings.xml
altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java
altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java
altosdroid/src/org/altusmetrum/AltosDroid/MapTypeActivity.java [new file with mode: 0644]
altosdroid/src/org/altusmetrum/AltosDroid/PreloadMapActivity.java [new file with mode: 0644]
altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java
altosdroid/src/org/altusmetrum/AltosDroid/TabMapOffline.java
altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java

index 71c6fb1..592373d 100644 (file)
                   android:theme="@android:style/Theme.Dialog"
                   android:configChanges="orientation|keyboardHidden" />
 
+        <activity android:name=".PreloadMapActivity"
+                  android:label="@string/preload_maps"
+                  android:theme="@android:style/Theme.Dialog"
+                  android:configChanges="orientation|keyboardHidden" />
+
+        <activity android:name=".MapTypeActivity"
+                  android:label="@string/map_type"
+                  android:theme="@android:style/Theme.Dialog"
+                  android:configChanges="orientation|keyboardHidden" />
+
         <service android:name=".TelemetryService" />
 
         <meta-data android:name="com.google.android.maps.v2.API_KEY"
diff --git a/altosdroid/res/drawable-hdpi/ic_maps_indicator_current_position.png b/altosdroid/res/drawable-hdpi/ic_maps_indicator_current_position.png
new file mode 100644 (file)
index 0000000..bc9160d
Binary files /dev/null and b/altosdroid/res/drawable-hdpi/ic_maps_indicator_current_position.png differ
diff --git a/altosdroid/res/drawable-mdpi/ic_maps_indicator_current_position.png b/altosdroid/res/drawable-mdpi/ic_maps_indicator_current_position.png
new file mode 100644 (file)
index 0000000..4e427d8
Binary files /dev/null and b/altosdroid/res/drawable-mdpi/ic_maps_indicator_current_position.png differ
index 93d6551..bf295e4 100644 (file)
         android:textColor="#fff"
         android:paddingLeft="5dp"
     />
+    <ListView android:id="@+id/new_devices"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+       android:fadeScrollbars="false"
+       android:scrollbars="vertical"
+    />
     <TextView android:id="@+id/title_paired_devices"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
     <ListView android:id="@+id/paired_devices"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:stackFromBottom="true"
         android:layout_weight="1"
-    />
-    <ListView android:id="@+id/new_devices"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:stackFromBottom="true"
-        android:layout_weight="2"
+       android:fadeScrollbars="false"
+       android:scrollbars="vertical"
     />
 </LinearLayout>
diff --git a/altosdroid/res/layout/map_preload.xml b/altosdroid/res/layout/map_preload.xml
new file mode 100644 (file)
index 0000000..1d1fca3
--- /dev/null
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright © 2015 Keith Packard <keithp@keithp.com>
+
+  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.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along
+  with this program; if not, write to the Free Software Foundation, Inc.,
+  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    >
+  <ScrollView android:layout_width="fill_parent"
+             android:layout_height="wrap_content">
+    <LinearLayout android:layout_width="wrap_content"
+                 android:layout_height="wrap_content"
+                  android:orientation="vertical">
+      <TextView android:id="@+id/preload_site_label"
+               android:layout_width="fill_parent"
+               android:layout_height="wrap_content"
+               android:text="@string/preload_site_label"
+               />
+      <Spinner android:id="@+id/preload_site_list"
+              android:layout_width="fill_parent"
+              android:layout_height="wrap_content"
+              android:prompt="@string/preload_site_label"
+              android:spinnerMode="dropdown"
+              />
+      <TextView android:id="@+id/preload_latitude_label"
+               android:layout_width="fill_parent"
+               android:layout_height="wrap_content"
+               android:text="@string/preload_latitude_label"
+               />
+      <EditText android:id="@+id/preload_latitude"
+               android:layout_width="fill_parent"
+               android:layout_height="wrap_content"
+               android:hint="@string/preload_latitude_label"
+               android:inputType="number"/>
+      <TextView android:id="@+id/preload_longitude_label"
+               android:layout_width="fill_parent"
+               android:layout_height="wrap_content"
+               android:text="@string/preload_longitude_label"
+               />
+      <EditText android:id="@+id/preload_longitude"
+               android:layout_width="fill_parent"
+               android:layout_height="wrap_content"
+               android:hint="@string/preload_longitude_label"
+               android:inputType="number"/>
+      <TextView android:id="@+id/preload_types"
+               android:layout_width="fill_parent"
+               android:layout_height="wrap_content"
+               android:text="@string/preload_types"
+               />
+      <CheckBox android:id="@+id/preload_hybrid"
+               android:layout_width="fill_parent"
+               android:layout_height="wrap_content"
+               android:text="@string/preload_hybrid"
+               />
+      <CheckBox android:id="@+id/preload_satellite"
+               android:layout_width="fill_parent"
+               android:layout_height="wrap_content"
+               android:text="@string/preload_satellite"
+               />
+      <CheckBox android:id="@+id/preload_roadmap"
+               android:layout_width="fill_parent"
+               android:layout_height="wrap_content"
+               android:text="@string/preload_roadmap"
+               />
+      <CheckBox android:id="@+id/preload_terrain"
+               android:layout_width="fill_parent"
+               android:layout_height="wrap_content"
+               android:text="@string/preload_terrain"
+               />
+      <TextView android:id="@+id/preload_min_zoom_label"
+               android:layout_width="fill_parent"
+               android:layout_height="wrap_content"
+               android:text="@string/preload_min_zoom"
+               />
+      <Spinner android:id="@+id/preload_min_zoom"
+              android:layout_width="fill_parent"
+              android:layout_height="wrap_content"
+              android:prompt="@string/preload_min_zoom"
+              android:spinnerMode="dropdown"
+              />
+      <TextView android:id="@+id/preload_max_zoom_label"
+               android:layout_width="fill_parent"
+               android:layout_height="wrap_content"
+               android:text="@string/preload_max_zoom"
+               />
+      <Spinner android:id="@+id/preload_max_zoom"
+              android:layout_width="fill_parent"
+              android:layout_height="wrap_content"
+              android:prompt="@string/preload_max_zoom"
+              android:spinnerMode="dropdown"
+              />
+      <TextView android:id="@+id/preload_tile_radius_label"
+               android:layout_width="fill_parent"
+               android:layout_height="wrap_content"
+               android:text="@string/preload_tile_radius"
+               />
+      <Spinner android:id="@+id/preload_tile_radius"
+              android:layout_width="fill_parent"
+              android:layout_height="wrap_content"
+              android:prompt="@string/preload_tile_radius"
+              android:spinnerMode="dropdown"
+              />
+      <Button android:id="@+id/preload_load"
+              android:layout_width="match_parent"
+              android:layout_height="wrap_content"
+              android:text="@string/preload_load"
+             />
+      <ProgressBar android:id="@+id/preload_progress"
+                  android:layout_width="match_parent"
+                  android:layout_height="wrap_content"
+                  style="@android:style/Widget.ProgressBar.Horizontal"
+                  />
+    </LinearLayout>
+  </ScrollView>
+</LinearLayout>
diff --git a/altosdroid/res/layout/map_type.xml b/altosdroid/res/layout/map_type.xml
new file mode 100644 (file)
index 0000000..610e6bb
--- /dev/null
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright © 2015 Keith Packard <keithp@keithp.com>
+
+  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.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along
+  with this program; if not, write to the Free Software Foundation, Inc.,
+  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    >
+  <Button android:id="@+id/map_type_hybrid"
+          android:layout_width="fill_parent"
+          android:layout_height="wrap_content"
+          android:text="@string/preload_hybrid"
+          android:onClick="selectType"
+          />
+  <Button android:id="@+id/map_type_satellite"
+          android:layout_width="fill_parent"
+          android:layout_height="wrap_content"
+          android:text="@string/preload_satellite"
+          android:onClick="selectType"
+          />
+  <Button android:id="@+id/map_type_roadmap"
+          android:layout_width="fill_parent"
+          android:layout_height="wrap_content"
+          android:text="@string/preload_roadmap"
+          android:onClick="selectType"
+          />
+  <Button android:id="@+id/map_type_terrain"
+          android:layout_width="fill_parent"
+          android:layout_height="wrap_content"
+          android:text="@string/preload_terrain"
+          android:onClick="selectType"
+          />
+</LinearLayout>
index f005e88..2109ae0 100644 (file)
@@ -1,17 +1,19 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!-- 
+  Copyright © 2015 Keith Packard <keithp@keithp.com>
 
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
+  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.
 
-          http://www.apache.org/licenses/LICENSE-2.0
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
 
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
+  You should have received a copy of the GNU General Public License along
+  with this program; if not, write to the Free Software Foundation, Inc.,
+  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
 -->
 <menu xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:id="@+id/connect_scan"
     <item android:id="@+id/change_units"
          android:icon="@android:drawable/ic_menu_view"
          android:title="@string/change_units" />
+    <item android:id="@+id/preload_maps"
+         android:icon="@android:drawable/ic_menu_mapmode"
+         android:title="@string/preload_maps" />
+    <item android:id="@+id/map_type"
+         android:icon="@android:drawable/ic_menu_mapmode"
+         android:title="@string/map_type" />
 </menu>
index 8a5b29b..1af0dbb 100644 (file)
        <string name="select_freq">Select radio frequency</string>
        <string name="select_rate">Select data rate</string>
        <string name="change_units">Change units</string>
+       <string name="preload_maps">Load Maps</string>
+       <string name="map_type">Map Type</string>
+
+       <!-- MapTypeActivity -->
+       <string name="map_type">Map Type</string>
 
        <!-- DeviceListActivity -->
        <string name="scanning">scanning for devices…</string>
        <string name="pad_lon_label">Pad Lon</string>
        <string name="pad_alt_label">Pad Alt</string>
 
+       <!-- Map preload -->
+       <string name="preload_site_label">Known Launch Sites</string>
+       <string name="preload_latitude_label">Latitude</string>
+       <string name="preload_longitude_label">Longitude</string>
+
+       <string name="preload_types">Map Types</string>
+       <string name="preload_hybrid">Hybrid</string>
+       <string name="preload_satellite">Satellite</string>
+       <string name="preload_roadmap">Roadmap</string>
+       <string name="preload_terrain">Terrain</string>
+       <string name="preload_min_zoom">Minimum Zoom</string>
+       <string name="preload_max_zoom">Maximum Zoom</string>
+       <string name="preload_tile_radius">Tile Radius</string>
+       
+       <string name="preload_load">Load Map</string>
 </resources>
index 6561864..97373ab 100644 (file)
@@ -73,6 +73,8 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
        // Intent request codes
        public static final int REQUEST_CONNECT_DEVICE = 1;
        public static final int REQUEST_ENABLE_BT      = 2;
+       public static final int REQUEST_PRELOAD_MAPS   = 3;
+       public static final int REQUEST_MAP_TYPE       = 4;
 
        public static FragmentManager   fm;
 
@@ -630,6 +632,10 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
                                finish();
                        }
                        break;
+               case REQUEST_MAP_TYPE:
+                       if (resultCode == Activity.RESULT_OK)
+                               set_map_type(data);
+                       break;
                }
        }
 
@@ -669,6 +675,16 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
                }
        }
 
+       private void set_map_type(Intent data) {
+               int     mode = data.getIntExtra(MapTypeActivity.EXTRA_MAP_TYPE, -1);
+
+               AltosDebug.debug("intent set_map_type %d\n", mode);
+               if (mode != -1) {
+                       for (AltosDroidTab mTab : mTabs)
+                               mTab.set_map_type(mode);
+               }
+       }
+
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
                MenuInflater inflater = getMenuInflater();
@@ -789,6 +805,14 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
                        boolean imperial = AltosPreferences.imperial_units();
                        AltosPreferences.set_imperial_units(!imperial);
                        return true;
+               case R.id.preload_maps:
+                       serverIntent = new Intent(this, PreloadMapActivity.class);
+                       startActivityForResult(serverIntent, REQUEST_PRELOAD_MAPS);
+                       return true;
+               case R.id.map_type:
+                       serverIntent = new Intent(this, MapTypeActivity.class);
+                       startActivityForResult(serverIntent, REQUEST_MAP_TYPE);
+                       return true;
                }
                return false;
        }
index d33ad05..b3824aa 100644 (file)
@@ -37,6 +37,9 @@ public abstract class AltosDroidTab extends Fragment implements AltosUnitsListen
 
        public abstract String tab_name();
 
+       public void set_map_type(int map_type) {
+       }
+
        public void units_changed(boolean imperial_units) {
                if (!isHidden() && last_state != null)
                        show(last_state, last_from_receiver, last_receiver);
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/MapTypeActivity.java b/altosdroid/src/org/altusmetrum/AltosDroid/MapTypeActivity.java
new file mode 100644 (file)
index 0000000..e43841a
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright © 2015 Keith Packard <keithp@keithp.com>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import java.util.*;
+import org.altusmetrum.AltosDroid.R;
+
+import android.app.Activity;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+import android.view.View;
+import android.view.Window;
+import android.view.View.OnClickListener;
+import android.widget.*;
+import android.widget.AdapterView.*;
+
+import org.altusmetrum.altoslib_7.*;
+
+public class MapTypeActivity extends Activity {
+       private Button hybrid;
+       private Button satellite;
+       private Button roadmap;
+       private Button terrain;
+       private int selected_type;
+
+       public static final String EXTRA_MAP_TYPE = "map_type";
+
+       private void done(int type) {
+
+               Intent intent = new Intent();
+               intent.putExtra(EXTRA_MAP_TYPE, type);
+               setResult(Activity.RESULT_OK, intent);
+               finish();
+       }
+
+       public void selectType(View view) {
+               AltosDebug.debug("selectType %s", view.toString());
+               if (view == hybrid)
+                       done(AltosMap.maptype_hybrid);
+               if (view == satellite)
+                       done(AltosMap.maptype_satellite);
+               if (view == roadmap)
+                       done(AltosMap.maptype_roadmap);
+               if (view == terrain)
+                       done(AltosMap.maptype_terrain);
+       }
+
+       @Override
+       protected void onCreate(Bundle savedInstanceState) {
+               super.onCreate(savedInstanceState);
+
+               // Setup the window
+               requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
+               setContentView(R.layout.map_type);
+
+               hybrid = (Button) findViewById(R.id.map_type_hybrid);
+               satellite = (Button) findViewById(R.id.map_type_satellite);
+               roadmap = (Button) findViewById(R.id.map_type_roadmap);
+               terrain = (Button) findViewById(R.id.map_type_terrain);
+
+               // Set result CANCELED incase the user backs out
+               setResult(Activity.RESULT_CANCELED);
+       }
+}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/PreloadMapActivity.java b/altosdroid/src/org/altusmetrum/AltosDroid/PreloadMapActivity.java
new file mode 100644 (file)
index 0000000..2febaf2
--- /dev/null
@@ -0,0 +1,322 @@
+/*
+ * Copyright © 2015 Keith Packard <keithp@keithp.com>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import java.util.*;
+import java.io.*;
+import java.text.*;
+
+import org.altusmetrum.AltosDroid.R;
+
+import android.app.Activity;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+import android.view.View;
+import android.view.Window;
+import android.view.View.OnClickListener;
+import android.widget.*;
+import android.widget.AdapterView.*;
+
+import org.altusmetrum.altoslib_7.*;
+
+/**
+ * This Activity appears as a dialog. It lists any paired devices and
+ * devices detected in the area after discovery. When a device is chosen
+ * by the user, the MAC address of the device is sent back to the parent
+ * Activity in the result Intent.
+ */
+public class PreloadMapActivity extends Activity implements AltosLaunchSiteListener, AltosMapInterface, AltosMapLoaderListener {
+
+       private ArrayAdapter<AltosLaunchSite> known_sites_adapter;
+
+       private CheckBox        hybrid;
+       private CheckBox        satellite;
+       private CheckBox        roadmap;
+       private CheckBox        terrain;
+
+       private Spinner         min_zoom;
+       private Spinner         max_zoom;
+       private Spinner         tile_radius;
+
+       private EditText        latitude;
+       private EditText        longitude;
+
+       private ProgressBar     progress;
+
+       /* AltosMapLoaderListener interfaces */
+       public void loader_start(final int max) {
+               AltosDebug.debug("loader_start max %d\n", max);
+               this.runOnUiThread(new Runnable() {
+                               public void run() {
+                                       progress.setMax(max);
+                                       progress.setProgress(0);
+                               }
+                       });
+       }
+
+       public void loader_notify(final int cur, final int max, final String name) {
+               AltosDebug.debug("loader_notify cur %4d max %4d %s\n", cur, max, name);
+               this.runOnUiThread(new Runnable() {
+                               public void run() {
+                                       progress.setProgress(cur);
+                               }
+                       });
+       }
+
+       public void loader_done(int max) {
+               AltosDebug.debug("loader_done max %d\n", max);
+               this.runOnUiThread(new Runnable() {
+                               public void run() {
+                                       progress.setProgress(0);
+                                       finish();
+                               }
+                       });
+       }
+
+       /* AltosLaunchSiteListener interface */
+       public void notify_launch_sites(final List<AltosLaunchSite> sites) {
+               this.runOnUiThread(new Runnable() {
+                               public void run() {
+                                       for (AltosLaunchSite site : sites)
+                                               known_sites_adapter.add(site);
+                               }
+                       });
+       }
+
+       AltosMap        map;
+       AltosMapLoader  loader;
+
+       class PreloadMapImage implements AltosImage {
+               public void flush() {
+               }
+
+               public PreloadMapImage(File file) {
+                       AltosDebug.debug("preload file %s\n", file.toString());
+               }
+       }
+
+       public AltosMapPath new_path() {
+               return null;
+       }
+
+       public AltosMapLine new_line() {
+               return null;
+       }
+
+       public AltosImage load_image(File file) throws Exception {
+               return new PreloadMapImage(file);
+       }
+
+       public AltosMapMark new_mark(double lat, double lon, int state) {
+               return null;
+       }
+
+       class PreloadMapTile extends AltosMapTile {
+               public void paint(AltosMapTransform t) {
+               }
+
+               public PreloadMapTile(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 AltosMapTile new_tile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
+               return new PreloadMapTile(listener, upper_left, center, zoom, maptype, px_size);
+       }
+
+       public int width() {
+               return AltosMap.px_size;
+       }
+
+       public int height() {
+               return AltosMap.px_size;
+       }
+
+       public void repaint() {
+       }
+
+       public void repaint(AltosRectangle damage) {
+       }
+
+       public void set_zoom_label(String label) {
+               AltosDebug.debug("zoom label %s\n", label);
+       }
+
+       private double text(EditText view) throws ParseException {
+               return AltosParse.parse_double_locale(view.getEditableText().toString());
+       }
+
+       private double latitude() throws ParseException {
+               return text(latitude);
+       }
+
+       private double longitude() throws ParseException {
+               return text(longitude);
+       }
+
+       private int value(Spinner spinner) {
+               return (Integer) spinner.getSelectedItem();
+       }
+
+       private int min_z() {
+               return value(min_zoom);
+       }
+
+       private int max_z() {
+               return value(max_zoom);
+       }
+
+       private int radius() {
+               return value(tile_radius);
+       }
+
+       private int bit(CheckBox box, int value) {
+               if (box.isChecked())
+                       return 1 << value;
+               return 0;
+       }
+
+       private int types() {
+               return (bit(hybrid, AltosMap.maptype_hybrid) |
+                       bit(satellite, AltosMap.maptype_satellite) |
+                       bit(roadmap, AltosMap.maptype_roadmap) |
+                       bit(terrain, AltosMap.maptype_terrain));
+       }
+
+       private void load() {
+               try {
+                       double  lat = latitude();
+                       double  lon = longitude();
+                       int     min = min_z();
+                       int     max = max_z();
+                       int     r = radius();
+                       int     t = types();
+
+                       AltosDebug.debug("load lat %12.6f lon %12.6f min %d max %d r %d types %x\n",
+                                        lat, lon, min, max, r, t);
+                       loader.load(lat, lon, min, max, r, t);
+               } catch (ParseException e) {
+               }
+       }
+
+       private void add_numbers(Spinner spinner, int min, int max, int def) {
+
+               ArrayAdapter<Integer> adapter = new ArrayAdapter<Integer>(this, android.R.layout.simple_spinner_item);
+
+               int     spinner_def = 0;
+               int     pos = 0;
+
+               for (int i = min; i <= max; i++) {
+                       adapter.add(new Integer(i));
+                       if (i == def)
+                               spinner_def = pos;
+                       pos++;
+               }
+
+               spinner.setAdapter(adapter);
+               spinner.setSelection(spinner_def);
+       }
+
+       class SiteListListener implements OnItemSelectedListener {
+               public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
+                       AltosLaunchSite site = (AltosLaunchSite) parent.getItemAtPosition(pos);
+                       AltosDebug.debug("Site selected: %s\n", site.toString());
+
+                       latitude.setText(new StringBuffer(String.format("%12.6f", site.latitude)));
+                       longitude.setText(new StringBuffer(String.format("%12.6f", site.longitude)));
+               }
+               public void onNothingSelected(AdapterView<?> parent) {
+               }
+
+               public SiteListListener() {
+               }
+       }
+
+       @Override
+       protected void onCreate(Bundle savedInstanceState) {
+               super.onCreate(savedInstanceState);
+
+               AltosDebug.debug("preload map onCreate");
+
+               // Setup the window
+               requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
+               setContentView(R.layout.map_preload);
+
+               // Set result CANCELED incase the user backs out
+               setResult(Activity.RESULT_CANCELED);
+
+               // Initialize the button to perform device discovery
+               Button loadButton = (Button) findViewById(R.id.preload_load);
+               loadButton.setOnClickListener(new OnClickListener() {
+                       public void onClick(View v) {
+                               load();
+                       }
+               });
+
+               latitude = (EditText) findViewById(R.id.preload_latitude);
+               longitude = (EditText) findViewById(R.id.preload_longitude);
+
+               hybrid = (CheckBox) findViewById(R.id.preload_hybrid);
+               satellite = (CheckBox) findViewById(R.id.preload_satellite);
+               roadmap = (CheckBox) findViewById(R.id.preload_roadmap);
+               terrain = (CheckBox) findViewById(R.id.preload_terrain);
+
+               hybrid.setChecked(true);
+
+               min_zoom = (Spinner) findViewById(R.id.preload_min_zoom);
+               add_numbers(min_zoom,
+                           AltosMap.min_zoom - AltosMap.default_zoom,
+                           AltosMap.max_zoom - AltosMap.default_zoom, -2);
+               max_zoom = (Spinner) findViewById(R.id.preload_max_zoom);
+               add_numbers(max_zoom,
+                           AltosMap.min_zoom - AltosMap.default_zoom,
+                           AltosMap.max_zoom - AltosMap.default_zoom, 2);
+               tile_radius = (Spinner) findViewById(R.id.preload_tile_radius);
+               add_numbers(tile_radius, 1, 5, 3);
+
+               progress = (ProgressBar) findViewById(R.id.preload_progress);
+
+               // Initialize array adapters. One for already paired devices and
+               // one for newly discovered devices
+               Spinner known_sites_spinner = (Spinner) findViewById(R.id.preload_site_list);
+
+               known_sites_adapter = new ArrayAdapter<AltosLaunchSite>(this, android.R.layout.simple_spinner_item);
+
+               known_sites_adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+
+               known_sites_spinner.setAdapter(known_sites_adapter);
+               known_sites_spinner.setOnItemSelectedListener(new SiteListListener());
+
+               map = new AltosMap(this);
+
+               loader = new AltosMapLoader(map, this);
+
+               new AltosLaunchSites(this);
+       }
+
+       @Override
+       protected void onDestroy() {
+               super.onDestroy();
+       }
+}
index 83c8f7f..5376d42 100644 (file)
@@ -199,6 +199,19 @@ public class TabMap extends AltosDroidTab {
 
        }
 
+       public void set_map_type(int map_type) {
+               if (mMap != null) {
+                       if (map_type == AltosMap.maptype_hybrid)
+                               mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
+                       else if (map_type == AltosMap.maptype_satellite)
+                               mMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
+                       else if (map_type == AltosMap.maptype_terrain)
+                               mMap.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
+                       else
+                               mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
+               }
+       }
+
        public TabMap() {
        }
 }
index 6742e60..31acda7 100644 (file)
@@ -39,6 +39,7 @@ public class TabMapOffline extends AltosDroidTab implements AltosMapInterface {
        AltosMap map;
 
        AltosLatLon     here;
+       AltosLatLon     pad;
 
        Canvas  canvas;
        Paint   paint;
@@ -84,6 +85,7 @@ public class TabMapOffline extends AltosDroidTab implements AltosMapInterface {
                                canvas.drawLine((float) rocket_screen.x, (float) rocket_screen.y,
                                                (float) here_screen.x, (float) here_screen.y, paint);
                        }
+                       draw_bitmap(pad, pad_bitmap, pad_off_x, pad_off_y);
                        draw_bitmap(map.last_position, rocket_bitmap, rocket_off_x, rocket_off_y);
                        draw_bitmap(here, here_bitmap, here_off_x, here_off_y);
                }
@@ -271,8 +273,6 @@ public class TabMapOffline extends AltosDroidTab implements AltosMapInterface {
 
        class MapMark extends AltosMapMark {
                public void paint(AltosMapTransform t) {
-                       if (state == AltosLib.ao_flight_boost)
-                               draw_bitmap(lat_lon, pad_bitmap, pad_off_x, pad_off_y);
                }
 
                MapMark(double lat, double lon, int state) {
@@ -472,6 +472,8 @@ public class TabMapOffline extends AltosDroidTab implements AltosMapInterface {
                                if (state.gps.locked && state.gps.nsat >= 4)
                                        center (state.gps.lat, state.gps.lon, 10);
                        }
+                       if (state.pad_lat != AltosLib.MISSING && pad == null)
+                               pad = new AltosLatLon(state.pad_lat, state.pad_lon);
                }
 
                if (receiver != null) {
@@ -489,6 +491,11 @@ public class TabMapOffline extends AltosDroidTab implements AltosMapInterface {
 
        }
 
+       public void set_map_type(int map_type) {
+               if (map != null)
+                       map.set_maptype(map_type);
+       }
+
        public TabMapOffline() {
        }
 }
index 627f595..eae360d 100644 (file)
@@ -334,7 +334,6 @@ public class TelemetryService extends Service implements LocationListener {
 
        private void start_altos_bluetooth(DeviceAddress address, boolean pause) {
                // Get the BLuetoothDevice object
-               AltosDebug.check_ui("start_altos_bluetooth\n");
                BluetoothDevice device = bluetooth_adapter.getRemoteDevice(address.address);
 
                disconnect(false);