altosdroid: Split setup functions to separate dialog
authorKeith Packard <keithp@keithp.com>
Wed, 27 Apr 2016 01:01:44 +0000 (21:01 -0400)
committerKeith Packard <keithp@keithp.com>
Wed, 27 Apr 2016 01:02:40 +0000 (21:02 -0400)
Remove them from the options menu, handle all preferences through
listeners.

Signed-off-by: Keith Packard <keithp@keithp.com>
18 files changed:
altosdroid/.gitignore
altosdroid/AndroidManifest.xml.in
altosdroid/res/layout/setup.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/AltosDroidMapInterface.java
altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidMapSourceListener.java [new file with mode: 0644]
altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java
altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java
altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOffline.java
altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOnline.java
altosdroid/src/org/altusmetrum/AltosDroid/IgniterActivity.java
altosdroid/src/org/altusmetrum/AltosDroid/SetupActivity.java [new file with mode: 0644]
altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java
altoslib/AltosMapTypeListener.java [new file with mode: 0644]
altoslib/AltosPreferences.java
altoslib/Makefile.am

index 7f0858e..cf7ad5a 100644 (file)
@@ -5,3 +5,4 @@ libs
 google-play-services_lib
 src/org/altusmetrum/AltosDroid/BuildInfo.java
 res/drawable/*led.png
+AndroidManifest.xml
index 15b0444..488a676 100644 (file)
                   android:theme="@android:style/Theme.Dialog"
                   android:configChanges="orientation|keyboardHidden" />
 
+       <activity android:name=".SetupActivity"
+                 android:label="@string/setup"
+                  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/layout/setup.xml b/altosdroid/res/layout/setup.xml
new file mode 100644 (file)
index 0000000..73ba2ad
--- /dev/null
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ Copyright © 2016 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"
+    >
+  <TableLayout
+      xmlns:android="http://schemas.android.com/apk/res/android"
+      android:stretchColumns="2,3"
+      android:layout_weight="0"
+      android:layout_width="fill_parent"
+      android:layout_height="wrap_content">
+
+    <TableRow
+       android:layout_gravity="center"
+       android:layout_weight="1"
+       android:padding="2dip"
+       android:layout_width="wrap_content"
+       android:layout_height="wrap_content">
+      <TextView
+         android:id="@+id/select_rate_label"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:text="@string/telemetry_rate"
+         />
+      <Spinner android:id="@+id/select_rate"
+              android:layout_width="fill_parent"
+              android:layout_height="wrap_content"
+              android:prompt="@string/telemetry_rate"
+              android:spinnerMode="dropdown"
+              />
+    </TableRow>
+    <TableRow
+       android:layout_gravity="center"
+       android:layout_weight="1"
+       android:padding="2dip"
+       android:layout_width="wrap_content"
+       android:layout_height="wrap_content">
+      <TextView
+         android:id="@+id/set_units_label"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:text="@string/set_units"
+         />
+      <Spinner android:id="@+id/set_units"
+              android:layout_width="fill_parent"
+              android:layout_height="wrap_content"
+              android:prompt="@string/set_units"
+              android:spinnerMode="dropdown"
+              />
+    </TableRow>
+    <TableRow
+       android:layout_gravity="center"
+       android:layout_weight="1"
+       android:padding="2dip"
+       android:layout_width="wrap_content"
+       android:layout_height="wrap_content">
+      <TextView
+         android:id="@+id/map_type_label"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:text="@string/map_type"
+         />
+      <Spinner android:id="@+id/map_type"
+              android:layout_width="fill_parent"
+              android:layout_height="wrap_content"
+              android:prompt="@string/map_type"
+              android:spinnerMode="dropdown"
+              />
+    </TableRow>
+    <TableRow
+       android:layout_gravity="center"
+       android:layout_weight="1"
+       android:padding="2dip"
+       android:layout_width="wrap_content"
+       android:layout_height="wrap_content">
+      <TextView
+         android:id="@+id/map_source_label"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:text="@string/map_source"
+         />
+      <Spinner android:id="@+id/map_source"
+              android:layout_width="fill_parent"
+              android:layout_height="wrap_content"
+              android:prompt="@string/map_source"
+              android:spinnerMode="dropdown"
+              />
+    </TableRow>
+  </TableLayout>
+  <Button android:id="@+id/preload_maps"
+          android:layout_width="match_parent"
+          android:layout_height="wrap_content"
+         android:text="@string/preload_maps"
+         />
+  <Button android:id="@+id/done"
+          android:layout_width="match_parent"
+          android:layout_height="wrap_content"
+         android:text="@string/done"
+         />
+</LinearLayout>
index 4de4a16..b2ca01a 100644 (file)
     <item android:id="@+id/select_freq"
           android:icon="@android:drawable/ic_menu_preferences"
           android:title="@string/select_freq" />
-    <item android:id="@+id/select_rate"
-          android:icon="@android:drawable/ic_menu_preferences"
-          android:title="@string/select_rate" />
-    <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" />
-    <item android:id="@+id/map_source"
-         android:icon="@android:drawable/ic_menu_mapmode"
-         android:title="@string/map_source" />
+
     <item android:id="@+id/select_tracker"
          android:icon="@android:drawable/ic_menu_view"
          android:title="@string/select_tracker"/>
     <item android:id="@+id/delete_track"
          android:icon="@android:drawable/ic_notification_clear_all"
          android:title="@string/delete_track"/>
+
+    <item android:id="@+id/setup"
+          android:icon="@android:drawable/ic_menu_preferences"
+          android:title="@string/setup" />
     <item android:id="@+id/idle_mode"
           android:icon="@android:drawable/ic_menu_preferences"
           android:title="@string/idle_mode" />
+
     <item android:id="@+id/quit"
           android:icon="@android:drawable/ic_menu_close_clear_cancel"
           android:title="@string/quit" />
index 6f761a5..7538f7b 100644 (file)
@@ -29,6 +29,7 @@
        <string name="connect_device">Connect a device</string>
        <string name="disconnect_device">Disconnect device</string>
        <string name="quit">Quit</string>
+       <string name="setup">Setup</string>
        <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="igniter_armed">Armed</string>
        <string name="igniter_fire">Fire</string>
        
+       <!-- setup -->
+       <string name="telemetry_rate">Telemetry Rate</string>
+       <string name="set_units">Units</string>
+       <string name="map_type">Map Type</string>
+       <string name="map_source">Map Source</string>
+       <string name="preload_maps">Preload Maps</string>
+       <string name="done">Done</string>
+       
 </resources>
index e5f56a5..ea3bbae 100644 (file)
@@ -71,15 +71,19 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,
        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 final int REQUEST_IDLE_MODE      = 5;
        public static final int REQUEST_IGNITERS       = 6;
+       public static final int REQUEST_SETUP          = 7;
 
        public static final String EXTRA_IDLE_MODE = "idle_mode";
        public static final String EXTRA_IDLE_RESULT = "idle_result";
        public static final String EXTRA_TELEMETRY_SERVICE = "telemetry_service";
 
-       public int map_type = AltosMap.maptype_hybrid;
+       // Setup result bits
+       public static final int SETUP_BAUD = 1;
+       public static final int SETUP_UNITS = 2;
+       public static final int SETUP_MAP_SOURCE = 4;
+       public static final int SETUP_MAP_TYPE = 8;
 
        public static FragmentManager   fm;
 
@@ -534,11 +538,6 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,
                return tab_view;
        }
 
-       public void set_map_source(int source) {
-               for (AltosDroidTab mTab : mTabs)
-                       mTab.set_map_source(source);
-       }
-
        @Override
        public void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
@@ -757,17 +756,39 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,
                                AltosDebug.debug("BT not enabled");
                        }
                        break;
-               case REQUEST_MAP_TYPE:
-                       if (resultCode == Activity.RESULT_OK)
-                               set_map_type(data);
-                       break;
                case REQUEST_IDLE_MODE:
                        if (resultCode == Activity.RESULT_OK)
                                idle_mode(data);
                        break;
                case REQUEST_IGNITERS:
                        break;
+               case REQUEST_SETUP:
+                       if (resultCode == Activity.RESULT_OK)
+                               note_setup_changes(data);
+                       break;
+               }
+       }
+
+       private void note_setup_changes(Intent data) {
+               int changes = data.getIntExtra(SetupActivity.EXTRA_SETUP_CHANGES, 0);
+
+               if ((changes & SETUP_BAUD) != 0) {
+                       try {
+                               mService.send(Message.obtain(null, TelemetryService.MSG_SETBAUD,
+                                                            AltosPreferences.telemetry_rate(1)));
+                       } catch (RemoteException re) {
+                       }
                }
+               if ((changes & SETUP_UNITS) != 0) {
+                       /* nothing to do here */
+               }
+               if ((changes & SETUP_MAP_SOURCE) != 0) {
+                       /* nothing to do here */
+               }
+               if ((changes & SETUP_MAP_TYPE) != 0) {
+                       /* nothing to do here */
+               }
+               set_switch_time();
        }
 
        private void connectUsb(UsbDevice device) {
@@ -814,17 +835,6 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,
                }
        }
 
-       private void set_map_type(Intent data) {
-               int type = data.getIntExtra(MapTypeActivity.EXTRA_MAP_TYPE, -1);
-
-               AltosDebug.debug("intent set_map_type %d\n", type);
-               if (type != -1) {
-                       map_type = type;
-                       for (AltosDroidTab mTab : mTabs)
-                               mTab.set_map_type(map_type);
-               }
-       }
-
        private void idle_mode(Intent data) {
                int type = data.getIntExtra(IdleModeActivity.EXTRA_IDLE_RESULT, -1);
                Message msg;
@@ -981,6 +991,10 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,
                        disconnectDevice();
                        finish();
                        return true;
+               case R.id.setup:
+                       serverIntent = new Intent(this, SetupActivity.class);
+                       startActivityForResult(serverIntent, REQUEST_SETUP);
+                       return true;
                case R.id.select_freq:
                        // Set the TBT radio frequency
 
@@ -1008,44 +1022,6 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,
                        AlertDialog alert_freq = builder_freq.create();
                        alert_freq.show();
                        return true;
-               case R.id.select_rate:
-                       // Set the TBT baud rate
-
-                       final String[] rates = {
-                               "38400",
-                               "9600",
-                               "2400",
-                       };
-
-                       AlertDialog.Builder builder_rate = new AlertDialog.Builder(this);
-                       builder_rate.setTitle("Pick a baud rate");
-                       builder_rate.setItems(rates,
-                                        new DialogInterface.OnClickListener() {
-                                                public void onClick(DialogInterface dialog, int item) {
-                                                        setBaud(rates[item]);
-                                                }
-                                        });
-                       AlertDialog alert_rate = builder_rate.create();
-                       alert_rate.show();
-                       return true;
-               case R.id.change_units:
-                       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;
-               case R.id.map_source:
-                       int source = AltosDroidPreferences.map_source();
-                       int new_source = source == AltosDroidPreferences.MAP_SOURCE_ONLINE ? AltosDroidPreferences.MAP_SOURCE_OFFLINE : AltosDroidPreferences.MAP_SOURCE_ONLINE;
-                       AltosDroidPreferences.set_map_source(new_source);
-                       set_map_source(new_source);
-                       return true;
                case R.id.select_tracker:
                        if (serials != null) {
                                String[] trackers = new String[serials.length+1];
index 944f4b5..43abef0 100644 (file)
@@ -25,6 +25,8 @@ import org.altusmetrum.altoslib_10.*;
 public interface AltosDroidMapInterface {
        public void onCreateView(AltosDroid altos_droid);
 
+       public void onDestroyView();
+
        public void set_visible(boolean visible);
 
        public void center(double lat, double lon, double accuracy);
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidMapSourceListener.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidMapSourceListener.java
new file mode 100644 (file)
index 0000000..e2775ef
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright © 2016 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;
+
+public interface AltosDroidMapSourceListener {
+       public void map_source_changed(int map_source);
+}
index bd3bd94..dd86c81 100644 (file)
  */
 package org.altusmetrum.AltosDroid;
 
+import java.io.*;
+import java.util.*;
+import java.text.*;
+
 import android.content.Context;
 import org.altusmetrum.altoslib_10.*;
 
@@ -65,12 +69,19 @@ public class AltosDroidPreferences extends AltosPreferences {
                }
        }
 
+       static LinkedList<AltosDroidMapSourceListener> map_source_listeners;
+
        public static void set_map_source(int map_source) {
                synchronized(backend) {
                        AltosDroidPreferences.map_source = map_source;
                        backend.putInt(mapSourcePreference, map_source);
                        flush_preferences();
                }
+               if (map_source_listeners != null) {
+                       for (AltosDroidMapSourceListener l : map_source_listeners) {
+                               l.map_source_changed(map_source);
+                       }
+               }
        }
 
        public static int map_source() {
@@ -78,4 +89,18 @@ public class AltosDroidPreferences extends AltosPreferences {
                        return map_source;
                }
        }
+
+       public static void register_map_source_listener(AltosDroidMapSourceListener l) {
+               synchronized(backend) {
+                       if (map_source_listeners == null)
+                               map_source_listeners = new LinkedList<AltosDroidMapSourceListener>();
+                       map_source_listeners.add(l);
+               }
+       }
+
+       public static void unregister_map_source_listener(AltosDroidMapSourceListener l) {
+               synchronized(backend) {
+                       map_source_listeners.remove(l);
+               }
+       }
 }
index d01bd33..77dbbcb 100644 (file)
@@ -39,12 +39,6 @@ public abstract class AltosDroidTab extends Fragment implements AltosUnitsListen
 
        public abstract String tab_name();
 
-       public void set_map_type(int map_type) {
-       }
-
-       public void set_map_source(int map_source) {
-       }
-
        public void units_changed(boolean imperial_units) {
                if (!isHidden())
                        show(last_telem_state, last_state, last_from_receiver, last_receiver);
index 6edc87a..bde80cf 100644 (file)
@@ -79,7 +79,7 @@ class Rocket implements Comparable {
        }
 }
 
-public class AltosMapOffline extends View implements ScaleGestureDetector.OnScaleGestureListener, AltosMapInterface, AltosDroidMapInterface {
+public class AltosMapOffline extends View implements ScaleGestureDetector.OnScaleGestureListener, AltosMapInterface, AltosDroidMapInterface, AltosMapTypeListener {
        ScaleGestureDetector    scale_detector;
        boolean                 scaling;
        AltosMap                map;
@@ -493,7 +493,8 @@ public class AltosMapOffline extends View implements ScaleGestureDetector.OnScal
        public void onCreateView(AltosDroid altos_droid) {
                this.altos_droid = altos_droid;
                map = new AltosMap(this);
-               map.set_maptype(altos_droid.map_type);
+               AltosPreferences.register_map_type_listener(this);
+               map.set_maptype(AltosPreferences.map_type());
 
                pad_bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.pad);
                /* arrow at the bottom of the launchpad image */
@@ -511,7 +512,11 @@ public class AltosMapOffline extends View implements ScaleGestureDetector.OnScal
                here_off_y = here_bitmap.getHeight() / 2;
        }
 
-       public void set_map_type(int map_type) {
+       public void onDestroyView() {
+               AltosPreferences.unregister_map_type_listener(this);
+       }
+
+       public void map_type_changed(int map_type) {
                if (map != null)
                        map.set_maptype(map_type);
        }
index fd4dc98..fcdb930 100644 (file)
@@ -102,7 +102,7 @@ class RocketOnline implements Comparable {
        }
 }
 
-public class AltosMapOnline implements AltosDroidMapInterface, GoogleMap.OnMarkerClickListener, GoogleMap.OnMapClickListener {
+public class AltosMapOnline implements AltosDroidMapInterface, GoogleMap.OnMarkerClickListener, GoogleMap.OnMapClickListener, AltosMapTypeListener {
        public SupportMapFragment mMapFragment;
        private GoogleMap mMap;
        private boolean mapLoaded = false;
@@ -124,7 +124,8 @@ public class AltosMapOnline implements AltosDroidMapInterface, GoogleMap.OnMarke
 
        public void onCreateView(AltosDroid altos_droid) {
                this.altos_droid = altos_droid;
-               final int map_type = altos_droid.map_type;
+               final int map_type = AltosPreferences.map_type();
+               AltosPreferences.register_map_type_listener(this);
                mMapFragment = new SupportMapFragment() {
                        @Override
                        public void onActivityCreated(Bundle savedInstanceState) {
@@ -144,9 +145,9 @@ public class AltosMapOnline implements AltosDroidMapInterface, GoogleMap.OnMarke
                };
        }
 
-//     public void onActivityCreated() {
-//             getChildFragmentManager().beginTransaction().add(R.id.map, mMapFragment).commit();
-//     }
+       public void onDestroyView() {
+               AltosPreferences.unregister_map_type_listener(this);
+       }
 
        private double pixel_distance(LatLng a, LatLng b) {
                Projection projection = mMap.getProjection();
@@ -190,7 +191,7 @@ public class AltosMapOnline implements AltosDroidMapInterface, GoogleMap.OnMarke
        public void setupMap(int map_type) {
                mMap = mMapFragment.getMap();
                if (mMap != null) {
-                       set_map_type(map_type);
+                       map_type_changed(map_type);
                        mMap.setMyLocationEnabled(true);
                        mMap.getUiSettings().setTiltGesturesEnabled(false);
                        mMap.getUiSettings().setZoomControlsEnabled(false);
@@ -308,7 +309,7 @@ public class AltosMapOnline implements AltosDroidMapInterface, GoogleMap.OnMarke
 
        }
 
-       public void set_map_type(int map_type) {
+       public void map_type_changed(int map_type) {
                if (mMap != null) {
                        if (map_type == AltosMap.maptype_hybrid)
                                mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
index a608bba..9e3dac6 100644 (file)
@@ -36,36 +36,41 @@ import org.altusmetrum.altoslib_10.*;
 
 class IgniterItem {
        public String name;
+       public String pretty;
        public String status;
        public LinearLayout igniter_view = null;
-       public TextView name_view = null;
+       public TextView pretty_view = null;
        public TextView status_view = null;
 
        private void update() {
-               AltosDebug.debug("update item %s %s", name, status);
-               if (name_view != null)
-                       name_view.setText(name);
+               AltosDebug.debug("update item %s %s", pretty, status);
+               if (pretty_view != null)
+                       pretty_view.setText(pretty);
                if (status_view != null)
                        status_view.setText(status);
        }
 
-       public void set(String name, String status) {
-               if (!name.equals(this.name) || !status.equals(this.status)) {
+       public void set(String name, String pretty, String status) {
+               if (!name.equals(this.name) ||
+                   !pretty.equals(this.pretty) ||
+                   !status.equals(this.status))
+               {
                        this.name = name;
+                       this.pretty = pretty;
                        this.status = status;
                        update();
                }
        }
 
        public void realize(LinearLayout igniter_view,
-                           TextView name_view,
+                           TextView pretty_view,
                            TextView status_view) {
                if (igniter_view != this.igniter_view ||
-                   name_view != this.name_view ||
+                   pretty_view != this.pretty_view ||
                    status_view != this.status_view)
                {
                        this.igniter_view = igniter_view;
-                       this.name_view = name_view;
+                       this.pretty_view = pretty_view;
                        this.status_view = status_view;
                        update();
                }
@@ -124,6 +129,9 @@ public class IgniterActivity extends Activity {
 
        private Timer timer;
 
+       private Timer arm_timer;
+       private int arm_remaining;
+
        public static final int IGNITER_QUERY = 1;
        public static final int IGNITER_FIRE = 2;
 
@@ -175,10 +183,44 @@ public class IgniterActivity extends Activity {
                finish();
        }
 
+       class FireThread extends Thread {
+               private final String igniter;
+
+               @Override
+               public void run() {
+                       Message msg = Message.obtain(null, TelemetryService.MSG_IGNITER_FIRE, igniter);
+                       try {
+                               service.send(msg);
+                       } catch (RemoteException re) {
+                       }
+               }
+
+               public FireThread(String igniter) {
+                       this.igniter = igniter;
+               }
+       }
+
        private void fire_igniter() {
+               if (igniters_adapter.selected_item >= 0) {
+                       IgniterItem     item = igniters_adapter.getItem(igniters_adapter.selected_item);
+                       FireThread      ft = new FireThread(item.name);
+                       ft.run();
+               }
        }
 
        private void arm_igniter(boolean is_checked) {
+               if (is_checked) {
+                       arm_timer = new Timer();
+                       fire.setEnabled(true);
+                       arm_timer.scheduleAtFixedRate(new TimerTask() {
+                                       public void run() {
+                                               arm_timer_tick();
+                                       }},
+                               1000L, 1000L);
+               } else {
+                       arm_timer.cancel();
+                       fire.setEnabled(false);
+               }
        }
 
        private synchronized void timer_tick() {
@@ -190,6 +232,7 @@ public class IgniterActivity extends Activity {
                        msg.replyTo = messenger;
                        service.send(msg);
                } catch (RemoteException re) {
+                       timer_running = false;
                }
        }
 
@@ -205,7 +248,7 @@ public class IgniterActivity extends Activity {
                } else
                        item = igniters.get(name);
 
-               item.set(pretty, AltosIgnite.status_string(status.get(name)));
+               item.set(name, pretty, AltosIgnite.status_string(status.get(name)));
                return true;
        }
 
@@ -227,16 +270,44 @@ public class IgniterActivity extends Activity {
 //                     igniters_view.setSelection(selected_item);
        }
 
-       private class IgniterItemClickListener implements ListView.OnItemClickListener {
-               @Override
-               public void onItemClick(AdapterView<?> av, View v, int position, long id) {
+       private void arm_set_text() {
+               String  text = String.format("Armed %d", arm_remaining);
+
+               arm.setTextOn(text);
+       }
+
+       private void arm_timer_tick() {
+               --arm_remaining;
+               if (arm_remaining <= 0) {
+                       timer.cancel();
+                       arm.setChecked(false);
+                       fire.setEnabled(false);
+               } else
+                       arm_set_text();
+       }
+
+       private void select_item(int position) {
+               if (position != igniters_adapter.selected_item) {
                        if (igniters_adapter.selected_item >= 0)
                                igniters_view.setItemChecked(igniters_adapter.selected_item, false);
-                       igniters_view.setItemChecked(position, true);
+                       if (position >= 0) {
+                               igniters_view.setItemChecked(position, true);
+                               arm.setEnabled(true);
+                               arm_remaining = 10;
+                               arm_set_text();
+                       } else
+                               arm.setEnabled(false);
                        igniters_adapter.selected_item = position;
                }
        }
 
+       private class IgniterItemClickListener implements ListView.OnItemClickListener {
+               @Override
+               public void onItemClick(AdapterView<?> av, View v, int position, long id) {
+                       select_item(position);
+               }
+       }
+
        @Override
        protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
@@ -261,6 +332,7 @@ public class IgniterActivity extends Activity {
                        });
 
                arm = (ToggleButton) findViewById(R.id.igniter_arm);
+               arm.setEnabled(false);
                arm.setOnCheckedChangeListener(new ToggleButton.OnCheckedChangeListener() {
                                public void onCheckedChanged(CompoundButton v, boolean is_checked) {
                                        arm_igniter(is_checked);
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/SetupActivity.java b/altosdroid/src/org/altusmetrum/AltosDroid/SetupActivity.java
new file mode 100644 (file)
index 0000000..ef802f0
--- /dev/null
@@ -0,0 +1,326 @@
+/*
+ * Copyright © 2016 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.lang.ref.WeakReference;
+import java.util.*;
+import org.altusmetrum.AltosDroid.R;
+
+import android.app.Activity;
+import android.bluetooth.*;
+import android.content.*;
+import android.os.*;
+import android.view.*;
+import android.view.View.*;
+import android.widget.*;
+import android.widget.AdapterView.*;
+
+import org.altusmetrum.altoslib_10.*;
+
+public class SetupActivity extends Activity {
+       private Spinner select_rate;
+       private Spinner set_units;
+       private Spinner map_type;
+       private Spinner map_source;
+       private Button preload_maps;
+       private Button done;
+
+       private boolean is_bound;
+       private Messenger service = null;
+
+       public final static String EXTRA_SETUP_CHANGES = "setup_changes";
+
+       private ServiceConnection connection = new ServiceConnection() {
+               public void onServiceConnected(ComponentName className, IBinder binder) {
+                       service = new Messenger(binder);
+               }
+
+               public void onServiceDisconnected(ComponentName className) {
+                       // This is called when the connection with the service has been unexpectedly disconnected - process crashed.
+                       service = null;
+               }
+       };
+
+       void doBindService() {
+               bindService(new Intent(this, TelemetryService.class), connection, Context.BIND_AUTO_CREATE);
+               is_bound = true;
+       }
+
+       void doUnbindService() {
+               if (is_bound) {
+                       // If we have received the service, and hence registered with it, then now is the time to unregister.
+                       unbindService(connection);
+                       is_bound = false;
+               }
+       }
+
+       static final String[] rates = {
+               "38400",
+               "9600",
+               "2400",
+       };
+
+       static final String[] map_types = {
+               "Hybrid",
+               "Satellite",
+               "Roadmap",
+               "Terrain"
+       };
+
+       static final int[] map_type_values = {
+               AltosMap.maptype_hybrid,
+               AltosMap.maptype_satellite,
+               AltosMap.maptype_roadmap,
+               AltosMap.maptype_terrain,
+       };
+
+       static final String[] map_sources = {
+               "Online",
+               "Offline"
+       };
+
+       private int     set_telemetry_rate;
+       private int     set_map_source;
+       private int     set_map_type;
+       private boolean set_imperial_units;
+
+       private int     changes = 0;
+
+       private void add_change(int change) {
+               changes |= change;
+       }
+
+       private void done() {
+               Intent intent = new Intent();
+               if ((changes & AltosDroid.SETUP_BAUD) != 0)
+                       AltosPreferences.set_telemetry_rate(1, set_telemetry_rate);
+               if ((changes & AltosDroid.SETUP_UNITS) != 0)
+                       AltosPreferences.set_imperial_units(set_imperial_units);
+               if ((changes & AltosDroid.SETUP_MAP_SOURCE) != 0)
+                       AltosDroidPreferences.set_map_source(set_map_source);
+               if ((changes & AltosDroid.SETUP_MAP_TYPE) != 0)
+                       AltosPreferences.set_map_type(set_map_type);
+               intent.putExtra(EXTRA_SETUP_CHANGES, changes);
+               setResult(Activity.RESULT_OK, intent);
+               finish();
+       }
+
+       private void add_strings(Spinner spinner, String[] strings, int def) {
+               ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item);
+
+               for (int i = 0; i < strings.length; i++)
+                       adapter.add(strings[i]);
+
+               spinner.setAdapter(adapter);
+               if (def >= 0)
+                       spinner.setSelection(def);
+       }
+
+       private int default_rate_pos() {
+               int     default_rate = AltosPreferences.telemetry_rate(1);
+
+               for (int pos = 0; pos < rates.length; pos++) {
+                       if (string_to_rate(rates[pos]) == default_rate)
+                               return pos;
+               }
+               return -1;
+       }
+
+       private void setBaud(int baud) {
+               try {
+                       service.send(Message.obtain(null, TelemetryService.MSG_SETBAUD, baud));
+                       set_telemetry_rate = baud;
+                       add_change(AltosDroid.SETUP_BAUD);
+               } catch (RemoteException e) {
+               }
+       }
+
+       private int string_to_rate(String baud) {
+               int     rate = AltosLib.ao_telemetry_rate_38400;
+               try {
+                       int     value = Integer.parseInt(baud);
+                       switch (value) {
+                       case 2400:
+                               rate = AltosLib.ao_telemetry_rate_2400;
+                               break;
+                       case 9600:
+                               rate = AltosLib.ao_telemetry_rate_9600;
+                               break;
+                       case 38400:
+                               rate = AltosLib.ao_telemetry_rate_38400;
+                               break;
+                       }
+               } catch (NumberFormatException e) {
+               }
+               return rate;
+       }
+
+       private void setBaud(String baud) {
+               setBaud(string_to_rate(baud));
+       }
+
+       private void select_rate(int pos) {
+               setBaud(rates[pos]);
+       }
+
+       static final String[] units = {
+               "Metric",
+               "Imperial"
+       };
+
+       private int default_units_pos() {
+               boolean imperial = AltosPreferences.imperial_units();
+
+               if (imperial)
+                       return 1;
+               return 0;
+       }
+
+       private void set_units(int pos) {
+               switch (pos) {
+               default:
+                       set_imperial_units = false;
+                       break;
+               case 1:
+                       set_imperial_units = true;
+                       break;
+               }
+               add_change(AltosDroid.SETUP_UNITS);
+       }
+
+       private int default_map_type_pos() {
+               int     default_map_type = AltosPreferences.map_type();
+
+               for (int pos = 0; pos < map_types.length; pos++)
+                       if (map_type_values[pos] == default_map_type)
+                               return pos;
+               return 0;
+       }
+
+       private void select_map_type(int pos) {
+               set_map_type = map_type_values[pos];
+               add_change(AltosDroid.SETUP_MAP_TYPE);
+       }
+
+       private int default_map_source_pos() {
+               int     default_source = AltosDroidPreferences.map_source();
+
+               switch (default_source) {
+               case AltosDroidPreferences.MAP_SOURCE_OFFLINE:
+                       return 1;
+               default:
+                       return 0;
+               }
+       }
+
+       private void select_map_source(int pos) {
+               switch (pos) {
+               default:
+                       set_map_source = AltosDroidPreferences.MAP_SOURCE_ONLINE;
+                       break;
+               case 1:
+                       set_map_source = AltosDroidPreferences.MAP_SOURCE_OFFLINE;
+                       break;
+               }
+               add_change(AltosDroid.SETUP_MAP_SOURCE);
+       }
+
+       private void preload_maps(){
+               Intent intent = new Intent(this, PreloadMapActivity.class);
+               startActivity(intent);
+       }
+
+       @Override
+       protected void onCreate(Bundle savedInstanceState) {
+               super.onCreate(savedInstanceState);
+
+               // Setup the window
+               requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
+               setContentView(R.layout.setup);
+
+               select_rate = (Spinner) findViewById(R.id.select_rate);
+               add_strings(select_rate, rates, default_rate_pos());
+               select_rate.setOnItemSelectedListener(new OnItemSelectedListener() {
+                               public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
+                                       select_rate(pos);
+                               }
+                               public void onNothingSelected(AdapterView<?> parent) {
+                               }
+                       });
+
+               set_units = (Spinner) findViewById(R.id.set_units);
+               add_strings(set_units, units, default_units_pos());
+               set_units.setOnItemSelectedListener(new OnItemSelectedListener() {
+                               public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
+                                       set_units(pos);
+                               }
+                               public void onNothingSelected(AdapterView<?> parent) {
+                               }
+                       });
+
+               map_type = (Spinner) findViewById(R.id.map_type);
+               add_strings(map_type, map_types, default_map_type_pos());
+               map_type.setOnItemSelectedListener(new OnItemSelectedListener() {
+                               public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
+                                       select_map_type(pos);
+                               }
+                               public void onNothingSelected(AdapterView<?> parent) {
+                               }
+                       });
+
+               map_source = (Spinner) findViewById(R.id.map_source);
+               add_strings(map_source, map_sources, default_map_source_pos());
+               map_source.setOnItemSelectedListener(new OnItemSelectedListener() {
+                               public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
+                                       select_map_source(pos);
+                               }
+                               public void onNothingSelected(AdapterView<?> parent) {
+                               }
+                       });
+
+
+               preload_maps = (Button) findViewById(R.id.preload_maps);
+               preload_maps.setOnClickListener(new OnClickListener() {
+                               public void onClick(View v) {
+                                       preload_maps();
+                               }
+                       });
+
+               done = (Button) findViewById(R.id.done);
+               done.setOnClickListener(new OnClickListener() {
+                               public void onClick(View v) {
+                                       done();
+                               }
+                       });
+
+               // Set result for when the user backs out
+               setResult(Activity.RESULT_CANCELED);
+       }
+
+       @Override
+       protected void onStart() {
+               super.onStart();
+               doBindService();
+       }
+
+       @Override
+       protected void onStop() {
+               super.onStop();
+               doUnbindService();
+       }
+}
index de74420..19ce86c 100644 (file)
@@ -32,7 +32,7 @@ import android.widget.*;
 import android.location.Location;
 import android.content.*;
 
-public class TabMap extends AltosDroidTab {
+public class TabMap extends AltosDroidTab implements AltosDroidMapSourceListener {
 
        AltosLatLon     here;
 
@@ -74,7 +74,8 @@ public class TabMap extends AltosDroidTab {
                map_offline.onCreateView(altos_droid);
                map_online = new AltosMapOnline(view.getContext());
                map_online.onCreateView(altos_droid);
-               set_map_source(AltosDroidPreferences.map_source());
+               map_source_changed(AltosDroidPreferences.map_source());
+               AltosDroidPreferences.register_map_source_listener(this);
                return view;
        }
 
@@ -88,6 +89,9 @@ public class TabMap extends AltosDroidTab {
        @Override
        public void onDestroyView() {
                super.onDestroyView();
+               map_offline.onDestroyView();
+               map_online.onDestroyView();
+               AltosDroidPreferences.unregister_map_source_listener(this);
        }
 
        public String tab_name() { return AltosDroid.tab_map_name; }
@@ -144,16 +148,7 @@ public class TabMap extends AltosDroidTab {
                }
        }
 
-       @Override
-       public void set_map_type(int map_type) {
-               if (map_offline != null)
-                       map_offline.set_map_type(map_type);
-               if (map_online != null)
-                       map_online.set_map_type(map_type);
-       }
-
-       @Override
-       public void set_map_source(int map_source) {
+       public void map_source_changed(int map_source) {
                this.map_source = map_source;
                if (map_source == AltosDroidPreferences.MAP_SOURCE_OFFLINE) {
                        if (map_online != null)
diff --git a/altoslib/AltosMapTypeListener.java b/altoslib/AltosMapTypeListener.java
new file mode 100644 (file)
index 0000000..b82bda3
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright © 2012 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.altoslib_10;
+
+public interface AltosMapTypeListener {
+       public void map_type_changed(int map_type);
+}
index 43fc9f2..4bf48f6 100644 (file)
@@ -128,6 +128,9 @@ public class AltosPreferences {
 
        public static int map_cache = 9;
 
+       final static String mapTypePreference = "MAP-TYPE";
+       static int      map_type;
+
        public static AltosFrequency[] load_common_frequencies() {
                AltosFrequency[] frequencies = null;
                boolean existing = false;
@@ -221,6 +224,7 @@ public class AltosPreferences {
 
                map_cache = backend.getInt(mapCachePreference, 9);
                map_cache_listeners = new LinkedList<AltosMapCacheListener>();
+               map_type = backend.getInt(mapTypePreference, AltosMap.maptype_hybrid);
        }
 
        public static void flush_preferences() {
@@ -638,4 +642,39 @@ public class AltosPreferences {
                        return map_cache;
                }
        }
+
+       static LinkedList<AltosMapTypeListener> map_type_listeners;
+
+       public static void set_map_type(int map_type) {
+               synchronized(backend) {
+                       AltosPreferences.map_type = map_type;
+                       backend.putInt(mapTypePreference, map_type);
+                       flush_preferences();
+               }
+               if (map_type_listeners != null) {
+                       for (AltosMapTypeListener l : map_type_listeners) {
+                               l.map_type_changed(map_type);
+                       }
+               }
+       }
+
+       public static int map_type() {
+               synchronized(backend) {
+                       return map_type;
+               }
+       }
+
+       public static void register_map_type_listener(AltosMapTypeListener l) {
+               synchronized(backend) {
+                       if (map_type_listeners == null)
+                               map_type_listeners = new LinkedList<AltosMapTypeListener>();
+                       map_type_listeners.add(l);
+               }
+       }
+
+       public static void unregister_map_type_listener(AltosMapTypeListener l) {
+               synchronized(backend) {
+                       map_type_listeners.remove(l);
+               }
+       }
 }
index e5d8c96..7363878 100644 (file)
@@ -157,6 +157,7 @@ altoslib_JAVA = \
        AltosLaunchSites.java \
        AltosMapLoaderListener.java \
        AltosMapLoader.java \
+       AltosMapTypeListener.java \
        AltosVersion.java
 
 JAR=altoslib_$(ALTOSLIB_VERSION).jar