diff options
18 files changed, 722 insertions, 117 deletions
diff --git a/altosdroid/.gitignore b/altosdroid/.gitignore index 7f0858ea..cf7ad5a8 100644 --- a/altosdroid/.gitignore +++ b/altosdroid/.gitignore @@ -5,3 +5,4 @@ libs google-play-services_lib src/org/altusmetrum/AltosDroid/BuildInfo.java res/drawable/*led.png +AndroidManifest.xml diff --git a/altosdroid/AndroidManifest.xml.in b/altosdroid/AndroidManifest.xml.in index 15b04445..488a6766 100644 --- a/altosdroid/AndroidManifest.xml.in +++ b/altosdroid/AndroidManifest.xml.in @@ -92,6 +92,11 @@ 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 index 00000000..73ba2ad1 --- /dev/null +++ b/altosdroid/res/layout/setup.xml @@ -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> diff --git a/altosdroid/res/menu/option_menu.xml b/altosdroid/res/menu/option_menu.xml index 4de4a16e..b2ca01a4 100644 --- a/altosdroid/res/menu/option_menu.xml +++ b/altosdroid/res/menu/option_menu.xml @@ -25,30 +25,21 @@ <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" /> diff --git a/altosdroid/res/values/strings.xml b/altosdroid/res/values/strings.xml index 6f761a58..7538f7b5 100644 --- a/altosdroid/res/values/strings.xml +++ b/altosdroid/res/values/strings.xml @@ -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> @@ -126,4 +127,12 @@ <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> diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java index e5f56a5a..ea3bbae6 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java @@ -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]; diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidMapInterface.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidMapInterface.java index 944f4b51..43abef0f 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidMapInterface.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidMapInterface.java @@ -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 index 00000000..e2775ef5 --- /dev/null +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidMapSourceListener.java @@ -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); +} diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java index bd3bd942..dd86c818 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java @@ -16,6 +16,10 @@ */ 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); + } + } } diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java index d01bd33c..77dbbcb1 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java @@ -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); diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOffline.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOffline.java index 6edc87a5..bde80cfc 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOffline.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOffline.java @@ -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); } diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOnline.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOnline.java index fd4dc98a..fcdb930b 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOnline.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOnline.java @@ -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); diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/IgniterActivity.java b/altosdroid/src/org/altusmetrum/AltosDroid/IgniterActivity.java index a608bba0..9e3dac67 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/IgniterActivity.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/IgniterActivity.java @@ -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 index 00000000..ef802f0f --- /dev/null +++ b/altosdroid/src/org/altusmetrum/AltosDroid/SetupActivity.java @@ -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(); + } +} diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java index de74420f..19ce86c9 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java @@ -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 index 00000000..b82bda3f --- /dev/null +++ b/altoslib/AltosMapTypeListener.java @@ -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); +} diff --git a/altoslib/AltosPreferences.java b/altoslib/AltosPreferences.java index 43fc9f22..4bf48f6d 100644 --- a/altoslib/AltosPreferences.java +++ b/altoslib/AltosPreferences.java @@ -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); + } + } } diff --git a/altoslib/Makefile.am b/altoslib/Makefile.am index e5d8c964..73638782 100644 --- a/altoslib/Makefile.am +++ b/altoslib/Makefile.am @@ -157,6 +157,7 @@ altoslib_JAVA = \ AltosLaunchSites.java \ AltosMapLoaderListener.java \ AltosMapLoader.java \ + AltosMapTypeListener.java \ AltosVersion.java JAR=altoslib_$(ALTOSLIB_VERSION).jar |