altosdroid: Import initial versions of XML and Java for Tab content
authorMike Beattie <mike@ethernal.org>
Thu, 7 Mar 2013 08:28:45 +0000 (21:28 +1300)
committerMike Beattie <mike@ethernal.org>
Thu, 7 Mar 2013 08:28:45 +0000 (21:28 +1300)
* Includes TabsAdapter class borrowed from Support Library sample code
* New "GoNoGoLights" class for dealing with the red/green/gray LEDs
* extra required strings in strings.xml
* Couple of support functions in AltosDroid.java
* rudimentary Maps tab - does nothing at present.

Signed-off-by: Mike Beattie <mike@ethernal.org>
15 files changed:
altosdroid/res/layout/tab_ascent.xml [new file with mode: 0644]
altosdroid/res/layout/tab_descent.xml [new file with mode: 0644]
altosdroid/res/layout/tab_landed.xml [new file with mode: 0644]
altosdroid/res/layout/tab_map.xml [new file with mode: 0644]
altosdroid/res/layout/tab_pad.xml [new file with mode: 0644]
altosdroid/res/values/strings.xml
altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java
altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java [new file with mode: 0644]
altosdroid/src/org/altusmetrum/AltosDroid/GoNoGoLights.java [new file with mode: 0644]
altosdroid/src/org/altusmetrum/AltosDroid/TabAscent.java [new file with mode: 0644]
altosdroid/src/org/altusmetrum/AltosDroid/TabDescent.java [new file with mode: 0644]
altosdroid/src/org/altusmetrum/AltosDroid/TabLanded.java [new file with mode: 0644]
altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java [new file with mode: 0644]
altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java [new file with mode: 0644]
altosdroid/src/org/altusmetrum/AltosDroid/TabsAdapter.java [new file with mode: 0644]

diff --git a/altosdroid/res/layout/tab_ascent.xml b/altosdroid/res/layout/tab_ascent.xml
new file mode 100644 (file)
index 0000000..b7e9708
--- /dev/null
@@ -0,0 +1,299 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright © 2013 Mike Beattie <mike@ethernal.org>
+
+     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:layout_width="fill_parent"
+       android:layout_height="wrap_content"
+       android:orientation="vertical" >
+
+       <LinearLayout
+               xmlns:android="http://schemas.android.com/apk/res/android"
+               android:layout_width="fill_parent"
+               android:layout_height="wrap_content"
+               android:layout_weight="0"
+               android:baselineAligned="true"
+               android:orientation="horizontal"
+               android:paddingTop="5dp" >
+
+               <RelativeLayout
+                       android:layout_width="0dp"
+                       android:layout_height="wrap_content"
+                       android:layout_weight="1" >
+
+                       <TextView
+                               android:id="@+id/height_label"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:text="@string/height_label" />
+
+                       <TextView
+                               android:id="@+id/height_value"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:layout_alignParentRight="true"
+                               android:layout_below="@id/height_label"
+                               android:text=""
+                               android:textAppearance="?android:attr/textAppearanceLarge" />
+               </RelativeLayout>
+
+               <RelativeLayout
+                       android:layout_width="0dp"
+                       android:layout_height="wrap_content"
+                       android:layout_weight="1" >
+
+                       <TextView
+                               android:id="@+id/max_height_label"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:text="@string/max_height_label" />
+
+                       <TextView
+                               android:id="@+id/max_height_value"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:layout_alignParentRight="true"
+                               android:layout_below="@id/max_height_label"
+                               android:text=""
+                               android:textAppearance="?android:attr/textAppearanceLarge" />
+               </RelativeLayout>
+       </LinearLayout>
+
+       <LinearLayout
+               xmlns:android="http://schemas.android.com/apk/res/android"
+               android:layout_width="fill_parent"
+               android:layout_height="wrap_content"
+               android:layout_weight="0"
+               android:baselineAligned="true"
+               android:orientation="horizontal"
+               android:paddingTop="5dp" >
+
+               <RelativeLayout
+                       android:layout_width="0dp"
+                       android:layout_height="wrap_content"
+                       android:layout_weight="1" >
+
+                       <TextView
+                               android:id="@+id/speed_label"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:text="@string/speed_label" />
+
+                       <TextView
+                               android:id="@+id/speed_value"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:layout_alignParentRight="true"
+                               android:layout_below="@id/speed_label"
+                               android:text=""
+                               android:textAppearance="?android:attr/textAppearanceLarge" />
+               </RelativeLayout>
+
+               <RelativeLayout
+                       android:layout_width="0dp"
+                       android:layout_height="wrap_content"
+                       android:layout_weight="1" >
+
+                       <TextView
+                               android:id="@+id/max_speed_label"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:text="@string/max_speed_label" />
+
+                       <TextView
+                               android:id="@+id/max_speed_value"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:layout_alignParentRight="true"
+                               android:layout_below="@id/max_speed_label"
+                               android:text=""
+                               android:textAppearance="?android:attr/textAppearanceLarge" />
+               </RelativeLayout>
+       </LinearLayout>
+
+       <LinearLayout
+               xmlns:android="http://schemas.android.com/apk/res/android"
+               android:layout_width="fill_parent"
+               android:layout_height="wrap_content"
+               android:layout_weight="0"
+               android:baselineAligned="true"
+               android:orientation="horizontal"
+               android:paddingTop="5dp" >
+
+               <RelativeLayout
+                       android:layout_width="0dp"
+                       android:layout_height="wrap_content"
+                       android:layout_weight="1" >
+
+                       <TextView
+                               android:id="@+id/accel_label"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:text="@string/accel_label" />
+
+                       <TextView
+                               android:id="@+id/accel_value"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:layout_alignParentRight="true"
+                               android:layout_below="@id/accel_label"
+                               android:text=""
+                               android:textAppearance="?android:attr/textAppearanceLarge" />
+               </RelativeLayout>
+
+               <RelativeLayout
+                       android:layout_width="0dp"
+                       android:layout_height="wrap_content"
+                       android:layout_weight="1" >
+
+                       <TextView
+                               android:id="@+id/max_accel_label"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:text="@string/max_accel_label" />
+
+                       <TextView
+                               android:id="@+id/max_accel_value"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:layout_alignParentRight="true"
+                               android:layout_below="@id/max_accel_label"
+                               android:text=""
+                               android:textAppearance="?android:attr/textAppearanceLarge" />
+               </RelativeLayout>
+       </LinearLayout>
+
+       <RelativeLayout
+               android:layout_width="wrap_content"
+               android:layout_height="wrap_content"
+               android:paddingTop="5dp" >
+
+               <TextView
+                       android:id="@+id/lat_label"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:text="@string/latitude_label" />
+
+               <TextView
+                       android:id="@+id/lat_value"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_alignParentRight="true"
+                       android:layout_below="@id/lat_label"
+                       android:text=""
+                       android:textAppearance="?android:attr/textAppearanceLarge" />
+       </RelativeLayout>
+
+       <RelativeLayout
+               android:layout_width="wrap_content"
+               android:layout_height="wrap_content"
+               android:paddingTop="5dp" >
+
+               <TextView
+                       android:id="@+id/lon_label"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:text="@string/longitude_label" />
+
+               <TextView
+                       android:id="@+id/lon_value"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_alignParentRight="true"
+                       android:layout_below="@id/lon_label"
+                       android:text=""
+                       android:textAppearance="?android:attr/textAppearanceLarge" />
+       </RelativeLayout>
+
+       <RelativeLayout
+               android:layout_width="wrap_content"
+               android:layout_height="wrap_content"
+               android:paddingTop="5dp" >
+
+               <ImageView
+                       android:id="@+id/apogee_redled"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:contentDescription="@string/apogee_voltage_label"
+                       android:src="@drawable/redled" />
+
+               <ImageView
+                       android:id="@+id/apogee_greenled"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_toRightOf="@id/apogee_redled"
+                       android:contentDescription="@string/apogee_voltage_label"
+                       android:paddingRight="5dp"
+                       android:src="@drawable/grayled" />
+
+               <TextView
+                       android:id="@+id/apogee_voltage_label"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_toRightOf="@id/apogee_greenled"
+                       android:text="@string/apogee_voltage_label" />
+
+               <TextView
+                       android:id="@+id/apogee_voltage_value"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_alignParentRight="true"
+                       android:layout_below="@id/apogee_voltage_label"
+                       android:layout_toRightOf="@id/apogee_greenled"
+                       android:text=""
+                       android:textAppearance="?android:attr/textAppearanceLarge" />
+       </RelativeLayout>
+
+       <RelativeLayout
+               android:layout_width="wrap_content"
+               android:layout_height="wrap_content"
+               android:paddingTop="5dp" >
+
+               <ImageView
+                       android:id="@+id/main_redled"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:contentDescription="@string/main_voltage_label"
+                       android:src="@drawable/redled" />
+
+               <ImageView
+                       android:id="@+id/main_greenled"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_toRightOf="@id/main_redled"
+                       android:contentDescription="@string/main_voltage_label"
+                       android:paddingRight="5dp"
+                       android:src="@drawable/grayled" />
+
+               <TextView
+                       android:id="@+id/main_voltage_label"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_toRightOf="@id/main_greenled"
+                       android:text="@string/main_voltage_label" />
+
+               <TextView
+                       android:id="@+id/main_voltage_value"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_alignParentRight="true"
+                       android:layout_below="@id/main_voltage_label"
+                       android:layout_toRightOf="@id/main_greenled"
+                       android:text=""
+                       android:textAppearance="?android:attr/textAppearanceLarge" />
+       </RelativeLayout>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/altosdroid/res/layout/tab_descent.xml b/altosdroid/res/layout/tab_descent.xml
new file mode 100644 (file)
index 0000000..4b62acf
--- /dev/null
@@ -0,0 +1,339 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright © 2013 Mike Beattie <mike@ethernal.org>
+
+     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:layout_width="fill_parent"
+       android:layout_height="wrap_content"
+       android:orientation="vertical" >
+
+       <LinearLayout
+               xmlns:android="http://schemas.android.com/apk/res/android"
+               android:layout_width="fill_parent"
+               android:layout_height="wrap_content"
+               android:layout_weight="0"
+               android:baselineAligned="true"
+               android:orientation="horizontal" >
+
+               <RelativeLayout
+                       android:layout_width="0dp"
+                       android:layout_height="wrap_content"
+                       android:layout_weight="1" >
+
+                       <TextView
+                               android:id="@+id/speed_label"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:text="@string/speed_label" />
+
+                       <TextView
+                               android:id="@+id/speed_value"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:layout_alignParentRight="true"
+                               android:layout_below="@id/speed_label"
+                               android:text=""
+                               android:textAppearance="?android:attr/textAppearanceLarge" />
+               </RelativeLayout>
+
+               <RelativeLayout
+                       android:layout_width="0dp"
+                       android:layout_height="wrap_content"
+                       android:layout_weight="1" >
+
+                       <TextView
+                               android:id="@+id/height_label"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:text="@string/height_label" />
+
+                       <TextView
+                               android:id="@+id/height_value"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:layout_alignParentRight="true"
+                               android:layout_below="@id/height_label"
+                               android:text=""
+                               android:textAppearance="?android:attr/textAppearanceLarge" />
+               </RelativeLayout>
+
+       </LinearLayout>
+
+       <LinearLayout
+               xmlns:android="http://schemas.android.com/apk/res/android"
+               android:layout_width="fill_parent"
+               android:layout_height="wrap_content"
+               android:layout_weight="0"
+               android:baselineAligned="true"
+               android:orientation="horizontal"
+               android:paddingTop="5dp" >
+
+               <RelativeLayout
+                       android:layout_width="0dp"
+                       android:layout_height="wrap_content"
+                       android:layout_weight="1" >
+
+                       <TextView
+                               android:id="@+id/elevation_label"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:text="@string/elevation_label" />
+
+                       <TextView
+                               android:id="@+id/elevation_value"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:layout_alignParentRight="true"
+                               android:layout_below="@id/elevation_label"
+                               android:text=""
+                               android:textAppearance="?android:attr/textAppearanceLarge" />
+               </RelativeLayout>
+
+               <RelativeLayout
+                       android:layout_width="0dp"
+                       android:layout_height="wrap_content"
+                       android:layout_weight="1" >
+
+                       <TextView
+                               android:id="@+id/range_label"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:text="@string/range_label" />
+
+                       <TextView
+                               android:id="@+id/range_value"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:layout_alignParentRight="true"
+                               android:layout_below="@id/range_label"
+                               android:text=""
+                               android:textAppearance="?android:attr/textAppearanceLarge" />
+               </RelativeLayout>
+
+       </LinearLayout>
+
+       <LinearLayout
+               xmlns:android="http://schemas.android.com/apk/res/android"
+               android:layout_width="fill_parent"
+               android:layout_height="wrap_content"
+               android:layout_weight="0"
+               android:baselineAligned="true"
+               android:orientation="horizontal"
+               android:paddingTop="5dp" >
+
+               <RelativeLayout
+                       android:layout_width="0dp"
+                       android:layout_height="wrap_content"
+                       android:layout_weight="1" >
+
+                       <TextView
+                               android:id="@+id/bearing_label"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:text="@string/bearing_label" />
+
+                       <TextView
+                               android:id="@+id/bearing_value"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:layout_alignParentRight="true"
+                               android:layout_below="@id/bearing_label"
+                               android:text=""
+                               android:textAppearance="?android:attr/textAppearanceLarge" />
+               </RelativeLayout>
+
+               <RelativeLayout
+                       android:layout_width="0dp"
+                       android:layout_height="wrap_content"
+                       android:layout_weight="1" >
+
+                       <TextView
+                               android:id="@+id/compass_label"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:text="" />
+
+                       <TextView
+                               android:id="@+id/compass_value"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:layout_alignParentRight="true"
+                               android:layout_below="@id/compass_label"
+                               android:text=""
+                               android:textAppearance="?android:attr/textAppearanceLarge" />
+               </RelativeLayout>
+
+       </LinearLayout>
+
+       <LinearLayout
+               xmlns:android="http://schemas.android.com/apk/res/android"
+               android:layout_width="fill_parent"
+               android:layout_height="wrap_content"
+               android:layout_weight="0"
+               android:baselineAligned="true"
+               android:orientation="horizontal"
+               android:paddingTop="5dp" >
+
+               <RelativeLayout
+                       android:layout_width="0dp"
+                       android:layout_height="wrap_content"
+                       android:layout_weight="1" >
+
+                       <TextView
+                               android:id="@+id/distance_label"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:text="@string/gnd_distance_label" />
+
+                       <TextView
+                               android:id="@+id/distance_value"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:layout_alignParentRight="true"
+                               android:layout_below="@id/distance_label"
+                               android:text=""
+                               android:textAppearance="?android:attr/textAppearanceLarge" />
+               </RelativeLayout>
+
+               <TextView
+                       android:layout_width="0dp"
+                       android:layout_height="wrap_content"
+                       android:layout_weight="1" >
+               </TextView>
+
+       </LinearLayout>
+
+       <RelativeLayout
+               android:layout_width="wrap_content"
+               android:layout_height="wrap_content"
+               android:paddingTop="5dp" >
+
+               <TextView
+                       android:id="@+id/lat_label"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:text="@string/latitude_label" />
+
+               <TextView
+                       android:id="@+id/lat_value"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_alignParentRight="true"
+                       android:layout_below="@id/lat_label"
+                       android:text=""
+                       android:textAppearance="?android:attr/textAppearanceLarge" />
+       </RelativeLayout>
+
+       <RelativeLayout
+               android:layout_width="wrap_content"
+               android:layout_height="wrap_content"
+               android:paddingTop="5dp" >
+
+               <TextView
+                       android:id="@+id/lon_label"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:text="@string/longitude_label" />
+
+               <TextView
+                       android:id="@+id/lon_value"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_alignParentRight="true"
+                       android:layout_below="@id/lon_label"
+                       android:text=""
+                       android:textAppearance="?android:attr/textAppearanceLarge" />
+       </RelativeLayout>
+
+       <RelativeLayout
+               android:layout_width="wrap_content"
+               android:layout_height="wrap_content"
+               android:paddingTop="5dp" >
+
+               <ImageView
+                       android:id="@+id/apogee_redled"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:contentDescription="@string/apogee_voltage_label"
+                       android:src="@drawable/redled" />
+
+               <ImageView
+                       android:id="@+id/apogee_greenled"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_toRightOf="@id/apogee_redled"
+                       android:contentDescription="@string/apogee_voltage_label"
+                       android:paddingRight="5dp"
+                       android:src="@drawable/grayled" />
+
+               <TextView
+                       android:id="@+id/apogee_voltage_label"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_toRightOf="@id/apogee_greenled"
+                       android:text="@string/apogee_voltage_label" />
+
+               <TextView
+                       android:id="@+id/apogee_voltage_value"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_alignParentRight="true"
+                       android:layout_below="@id/apogee_voltage_label"
+                       android:layout_toRightOf="@id/apogee_greenled"
+                       android:text=""
+                       android:textAppearance="?android:attr/textAppearanceLarge" />
+       </RelativeLayout>
+
+       <RelativeLayout
+               android:layout_width="wrap_content"
+               android:layout_height="wrap_content"
+               android:paddingTop="5dp" >
+
+               <ImageView
+                       android:id="@+id/main_redled"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:contentDescription="@string/main_voltage_label"
+                       android:src="@drawable/redled" />
+
+               <ImageView
+                       android:id="@+id/main_greenled"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_toRightOf="@id/main_redled"
+                       android:contentDescription="@string/main_voltage_label"
+                       android:paddingRight="5dp"
+                       android:src="@drawable/grayled" />
+
+               <TextView
+                       android:id="@+id/main_voltage_label"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_toRightOf="@id/main_greenled"
+                       android:text="@string/main_voltage_label" />
+
+               <TextView
+                       android:id="@+id/main_voltage_value"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_alignParentRight="true"
+                       android:layout_below="@id/main_voltage_label"
+                       android:layout_toRightOf="@id/main_greenled"
+                       android:text=""
+                       android:textAppearance="?android:attr/textAppearanceLarge" />
+       </RelativeLayout>
+
+</LinearLayout>
diff --git a/altosdroid/res/layout/tab_landed.xml b/altosdroid/res/layout/tab_landed.xml
new file mode 100644 (file)
index 0000000..b5c8d8c
--- /dev/null
@@ -0,0 +1,169 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright © 2013 Mike Beattie <mike@ethernal.org>
+
+     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:layout_width="fill_parent"
+       android:layout_height="wrap_content"
+       android:orientation="vertical" >
+
+       <RelativeLayout
+               android:layout_width="wrap_content"
+               android:layout_height="wrap_content" >
+
+               <TextView
+                       android:id="@+id/bearing_label"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:text="@string/bearing_label" />
+
+               <TextView
+                       android:id="@+id/bearing_value"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_alignParentRight="true"
+                       android:layout_below="@+id/bearing_label"
+                       android:text=""
+                       android:textAppearance="?android:attr/textAppearanceLarge" />
+       </RelativeLayout>
+
+       <RelativeLayout
+               android:layout_width="wrap_content"
+               android:layout_height="wrap_content"
+               android:paddingTop="5dp" >
+
+               <TextView
+                       android:id="@+id/distance_label"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:text="@string/distance_label" />
+
+               <TextView
+                       android:id="@+id/distance_value"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_alignParentRight="true"
+                       android:layout_below="@+id/distance_label"
+                       android:text=""
+                       android:textAppearance="?android:attr/textAppearanceLarge" />
+       </RelativeLayout>
+
+       <RelativeLayout
+               android:layout_width="wrap_content"
+               android:layout_height="wrap_content"
+               android:paddingTop="5dp" >
+
+               <TextView
+                       android:id="@+id/lat_label"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:text="@string/latitude_label" />
+
+               <TextView
+                       android:id="@+id/lat_value"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_alignParentRight="true"
+                       android:layout_below="@id/lat_label"
+                       android:text=""
+                       android:textAppearance="?android:attr/textAppearanceLarge" />
+       </RelativeLayout>
+
+       <RelativeLayout
+               android:layout_width="wrap_content"
+               android:layout_height="wrap_content"
+               android:paddingTop="5dp" >
+
+               <TextView
+                       android:id="@+id/lon_label"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:text="@string/longitude_label" />
+
+               <TextView
+                       android:id="@+id/lon_value"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_alignParentRight="true"
+                       android:layout_below="@id/lon_label"
+                       android:text=""
+                       android:textAppearance="?android:attr/textAppearanceLarge" />
+       </RelativeLayout>
+
+       <RelativeLayout
+               android:layout_width="wrap_content"
+               android:layout_height="wrap_content"
+               android:paddingTop="5dp" >
+
+               <TextView
+                       android:id="@+id/max_height_label"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:text="@string/max_height_label" />
+
+               <TextView
+                       android:id="@+id/max_height_value"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_alignParentRight="true"
+                       android:layout_below="@id/max_height_label"
+                       android:text=""
+                       android:textAppearance="?android:attr/textAppearanceLarge" />
+       </RelativeLayout>
+
+       <RelativeLayout
+               android:layout_width="wrap_content"
+               android:layout_height="wrap_content"
+               android:paddingTop="5dp" >
+
+               <TextView
+                       android:id="@+id/max_speed_label"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:text="@string/max_speed_label" />
+
+               <TextView
+                       android:id="@+id/max_speed_value"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_alignParentRight="true"
+                       android:layout_below="@id/max_speed_label"
+                       android:text=""
+                       android:textAppearance="?android:attr/textAppearanceLarge" />
+       </RelativeLayout>
+
+       <RelativeLayout
+               android:layout_width="wrap_content"
+               android:layout_height="wrap_content"
+               android:paddingTop="5dp" >
+
+               <TextView
+                       android:id="@+id/max_accel_label"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:text="@string/max_accel_label" />
+
+               <TextView
+                       android:id="@+id/max_accel_value"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_alignParentRight="true"
+                       android:layout_below="@id/max_accel_label"
+                       android:text=""
+                       android:textAppearance="?android:attr/textAppearanceLarge" />
+       </RelativeLayout>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/altosdroid/res/layout/tab_map.xml b/altosdroid/res/layout/tab_map.xml
new file mode 100644 (file)
index 0000000..4737fae
--- /dev/null
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright © 2013 Mike Beattie <mike@ethernal.org>
+
+     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.
+-->
+<fragment xmlns:android="http://schemas.android.com/apk/res/android"
+       android:id="@+id/map"
+       android:layout_width="match_parent"
+       android:layout_height="match_parent"
+       class="com.google.android.gms.maps.SupportMapFragment"/>
diff --git a/altosdroid/res/layout/tab_pad.xml b/altosdroid/res/layout/tab_pad.xml
new file mode 100644 (file)
index 0000000..f5ec46b
--- /dev/null
@@ -0,0 +1,320 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright © 2013 Mike Beattie <mike@ethernal.org>
+
+     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:layout_width="fill_parent"
+       android:layout_height="wrap_content"
+       android:layout_weight="0"
+       android:orientation="vertical" >
+
+       <RelativeLayout
+               android:layout_width="wrap_content"
+               android:layout_height="wrap_content" >
+
+               <ImageView
+                       android:id="@+id/battery_redled"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:contentDescription="@string/battery_voltage_label"
+                       android:src="@drawable/redled" />
+
+               <ImageView
+                       android:id="@+id/battery_greenled"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_toRightOf="@id/battery_redled"
+                       android:contentDescription="@string/battery_voltage_label"
+                       android:paddingRight="5dp"
+                       android:src="@drawable/grayled" />
+
+               <TextView
+                       android:id="@+id/battery_voltage_label"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_toRightOf="@id/battery_greenled"
+                       android:text="@string/battery_voltage_label" />
+
+               <TextView
+                       android:id="@+id/battery_voltage_value"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_below="@id/battery_voltage_label"
+                       android:layout_toRightOf="@id/battery_greenled"
+                       android:text=""
+                       android:textAppearance="?android:attr/textAppearanceLarge" />
+       </RelativeLayout>
+
+       <RelativeLayout
+               android:layout_width="wrap_content"
+               android:layout_height="wrap_content"
+               android:paddingTop="5dp" >
+
+               <ImageView
+                       android:id="@+id/apogee_redled"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:contentDescription="@string/apogee_voltage_label"
+                       android:src="@drawable/redled" />
+
+               <ImageView
+                       android:id="@+id/apogee_greenled"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_toRightOf="@id/apogee_redled"
+                       android:contentDescription="@string/apogee_voltage_label"
+                       android:paddingRight="5dp"
+                       android:src="@drawable/grayled" />
+
+               <TextView
+                       android:id="@+id/apogee_voltage_label"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_toRightOf="@id/apogee_greenled"
+                       android:text="@string/apogee_voltage_label" />
+
+               <TextView
+                       android:id="@+id/apogee_voltage_value"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_below="@id/apogee_voltage_label"
+                       android:layout_toRightOf="@id/apogee_greenled"
+                       android:text=""
+                       android:textAppearance="?android:attr/textAppearanceLarge" />
+       </RelativeLayout>
+
+       <RelativeLayout
+               android:layout_width="wrap_content"
+               android:layout_height="wrap_content"
+               android:paddingTop="5dp" >
+
+               <ImageView
+                       android:id="@+id/main_redled"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:contentDescription="@string/main_voltage_label"
+                       android:src="@drawable/redled" />
+
+               <ImageView
+                       android:id="@+id/main_greenled"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_toRightOf="@id/main_redled"
+                       android:contentDescription="@string/main_voltage_label"
+                       android:paddingRight="5dp"
+                       android:src="@drawable/grayled" />
+
+               <TextView
+                       android:id="@+id/main_voltage_label"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_toRightOf="@id/main_greenled"
+                       android:text="@string/main_voltage_label" />
+
+               <TextView
+                       android:id="@+id/main_voltage_value"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_below="@id/main_voltage_label"
+                       android:layout_toRightOf="@id/main_greenled"
+                       android:text=""
+                       android:textAppearance="?android:attr/textAppearanceLarge" />
+       </RelativeLayout>
+
+       <RelativeLayout
+               android:layout_width="wrap_content"
+               android:layout_height="wrap_content"
+               android:paddingTop="5dp" >
+
+               <ImageView
+                       android:id="@+id/logging_redled"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:contentDescription="@string/logging_label"
+                       android:src="@drawable/redled" />
+
+               <ImageView
+                       android:id="@+id/logging_greenled"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_toRightOf="@id/logging_redled"
+                       android:contentDescription="@string/logging_label"
+                       android:paddingRight="5dp"
+                       android:src="@drawable/grayled" />
+
+               <TextView
+                       android:id="@+id/logging_label"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_toRightOf="@id/logging_greenled"
+                       android:text="@string/logging_label" />
+
+               <TextView
+                       android:id="@+id/logging_value"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_below="@id/logging_label"
+                       android:layout_toRightOf="@id/logging_greenled"
+                       android:text=""
+                       android:textAppearance="?android:attr/textAppearanceLarge" />
+       </RelativeLayout>
+
+       <RelativeLayout
+               android:layout_width="wrap_content"
+               android:layout_height="wrap_content"
+               android:paddingTop="5dp" >
+
+               <ImageView
+                       android:id="@+id/gps_locked_redled"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:contentDescription="@string/gps_locked_label"
+                       android:src="@drawable/redled" />
+
+               <ImageView
+                       android:id="@+id/gps_locked_greenled"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_toRightOf="@id/gps_locked_redled"
+                       android:contentDescription="@string/gps_locked_label"
+                       android:paddingRight="5dp"
+                       android:src="@drawable/grayled" />
+
+               <TextView
+                       android:id="@+id/gps_locked_label"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_toRightOf="@id/gps_locked_greenled"
+                       android:text="@string/gps_locked_label" />
+
+               <TextView
+                       android:id="@+id/gps_locked_value"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_below="@id/gps_locked_label"
+                       android:layout_toRightOf="@id/gps_locked_greenled"
+                       android:text=""
+                       android:textAppearance="?android:attr/textAppearanceLarge" />
+       </RelativeLayout>
+
+       <RelativeLayout
+               android:layout_width="wrap_content"
+               android:layout_height="wrap_content"
+               android:paddingTop="5dp" >
+
+               <ImageView
+                       android:id="@+id/gps_ready_redled"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:contentDescription="@string/gps_ready_label"
+                       android:src="@drawable/redled" />
+
+               <ImageView
+                       android:id="@+id/gps_ready_greenled"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_toRightOf="@id/gps_ready_redled"
+                       android:contentDescription="@string/gps_ready_label"
+                       android:paddingRight="5dp"
+                       android:src="@drawable/grayled" />
+
+               <TextView
+                       android:id="@+id/gps_ready_label"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_toRightOf="@id/gps_ready_greenled"
+                       android:text="@string/gps_ready_label" />
+
+               <TextView
+                       android:id="@+id/gps_ready_value"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_below="@id/gps_ready_label"
+                       android:layout_toRightOf="@id/gps_ready_greenled"
+                       android:text=""
+                       android:textAppearance="?android:attr/textAppearanceLarge" />
+       </RelativeLayout>
+
+       <RelativeLayout
+               android:layout_width="wrap_content"
+               android:layout_height="wrap_content"
+               android:paddingLeft="69dp"
+               android:paddingTop="5dp" >
+
+               <TextView
+                       android:id="@+id/pad_lat_label"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_toRightOf="@id/gps_ready_greenled"
+                       android:text="@string/pad_lat_label" />
+
+               <TextView
+                       android:id="@+id/pad_lat_value"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_below="@id/pad_lat_label"
+                       android:layout_toRightOf="@id/gps_ready_greenled"
+                       android:text=""
+                       android:textAppearance="?android:attr/textAppearanceLarge" />
+       </RelativeLayout>
+
+       <RelativeLayout
+               android:layout_width="wrap_content"
+               android:layout_height="wrap_content"
+               android:paddingLeft="69dp"
+               android:paddingTop="5dp" >
+
+               <TextView
+                       android:id="@+id/pad_lon_label"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_toRightOf="@id/gps_ready_greenled"
+                       android:text="@string/pad_lon_label" />
+
+               <TextView
+                       android:id="@+id/pad_lon_value"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_below="@id/pad_lon_label"
+                       android:layout_toRightOf="@id/gps_ready_greenled"
+                       android:text=""
+                       android:textAppearance="?android:attr/textAppearanceLarge" />
+       </RelativeLayout>
+
+       <RelativeLayout
+               android:layout_width="wrap_content"
+               android:layout_height="wrap_content"
+               android:paddingLeft="69dp"
+               android:paddingTop="5dp" >
+
+               <TextView
+                       android:id="@+id/pad_alt_label"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_toRightOf="@id/gps_ready_greenled"
+                       android:text="@string/pad_alt_label" />
+
+               <TextView
+                       android:id="@+id/pad_alt_value"
+                       android:layout_width="wrap_content"
+                       android:layout_height="wrap_content"
+                       android:layout_below="@id/pad_alt_label"
+                       android:layout_toRightOf="@id/gps_ready_greenled"
+                       android:text=""
+                       android:textAppearance="?android:attr/textAppearanceLarge" />
+       </RelativeLayout>
+
+</LinearLayout>
\ No newline at end of file
index 679dc0195deaa2e4bcdb0c2c036f266c8834b894..639611c20053711007bca29fbc1d0d8fd3c22d77 100644 (file)
        <string name="telemetry_service_stopped">Telemetry Service Stopped</string>
 
        <!-- UI fields -->
+       <!-- Header -->
        <string name="callsign_label">Callsign</string>
        <string name="serial_label">Serial</string>
        <string name="flight_label">Flight</string>
        <string name="state_label">State</string>
        <string name="rssi_label">RSSI</string>
+       <string name="age_label">Age</string>
+
+       <!-- Tab fields -->
        <string name="height_label">Height</string>
        <string name="speed_label">Speed</string>
        <string name="accel_label">Acceleration</string>
        <string name="bearing_label">Bearing</string>
        <string name="elevation_label">Elevation</string>
        <string name="range_label">Range</string>
+       <string name="distance_label">Distance</string>
+       <string name="gnd_distance_label">Ground Distance</string>
+       <string name="max_height_label">Max Height</string>
+       <string name="max_speed_label">Max Speed</string>
+       <string name="max_accel_label">Max Accel</string>
+       <string name="battery_voltage_label">Battery Voltage</string>
+       <string name="apogee_voltage_label">Apogee Igniter Voltage</string>
+       <string name="main_voltage_label">Main Igniter Voltage</string>
+       <string name="logging_label">On-board Data Logging</string>
+       <string name="gps_locked_label">GPS Locked</string>
+       <string name="gps_ready_label">GPS Ready</string>
        <string name="latitude_label">Latitude</string>
        <string name="longitude_label">Longitude</string>
+       <string name="pad_lat_label">Pad Latitude</string>
+       <string name="pad_lon_label">Pad Longitude</string>
+       <string name="pad_alt_label">Pad Altitude</string>
 
 </resources>
index 5be70953010120e780deafa08f9185d66680d0f0..625a2eee430d7f278a023264d47dbd8112911f3a 100644 (file)
@@ -173,6 +173,12 @@ public class AltosDroid extends Activity {
                }
        }
 
+       public void registerTab(AltosDroidTab mTab) {
+       }
+
+       public void unregisterTab(AltosDroidTab mTab) {
+       }
+
        void update_ui(AltosState state) {
                mCallsignView.setText(state.data.callsign);
                mRSSIView.setText(String.format("%d", state.data.rssi));
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java
new file mode 100644 (file)
index 0000000..68bbe59
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright © 2013 Mike Beattie <mike@ethernal.org>
+ *
+ * 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 org.altusmetrum.altoslib_1.AltosState;
+
+public interface AltosDroidTab {
+       public void update_ui(AltosState state);
+}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/GoNoGoLights.java b/altosdroid/src/org/altusmetrum/AltosDroid/GoNoGoLights.java
new file mode 100644 (file)
index 0000000..0f95bc2
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright © 2013 Mike Beattie <mike@ethernal.org>
+ *
+ * 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 android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.widget.ImageView;
+
+public class GoNoGoLights {
+       private Boolean state;
+
+       private ImageView red;
+       private ImageView green;
+
+       private Drawable dRed;
+       private Drawable dGreen;
+       private Drawable dGray;
+
+       public GoNoGoLights(ImageView in_red, ImageView in_green, Resources r) {
+               red = in_red;
+               green = in_green;
+               state = false;
+
+               dRed   = r.getDrawable(R.drawable.redled);
+               dGreen = r.getDrawable(R.drawable.greenled);
+               dGray  = r.getDrawable(R.drawable.grayled);
+       }
+
+       public void set(Boolean s) {
+               if (s == state) return;
+               state = s;
+               if (state) {
+                       red.setImageDrawable(dGray);
+                       green.setImageDrawable(dGreen);
+               } else {
+                       red.setImageDrawable(dRed);
+                       green.setImageDrawable(dGray);
+               }
+       }
+}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabAscent.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabAscent.java
new file mode 100644 (file)
index 0000000..bda6b1f
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright © 2013 Mike Beattie <mike@ethernal.org>
+ *
+ * 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 org.altusmetrum.altoslib_1.AltosState;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+public class TabAscent extends Fragment implements AltosDroidTab {
+       AltosDroid mAltosDroid;
+
+       private TextView mHeightView;
+       private TextView mMaxHeightView;
+       private TextView mSpeedView;
+       private TextView mMaxSpeedView;
+       private TextView mAccelView;
+       private TextView mMaxAccelView;
+       private TextView mLatitudeView;
+       private TextView mLongitudeView;
+       private TextView mApogeeVoltageView;
+       private GoNoGoLights mApogeeLights;
+       private TextView mMainVoltageView;
+       private GoNoGoLights mMainLights;
+
+       @Override
+       public void onAttach(Activity activity) {
+               super.onAttach(activity);
+               mAltosDroid = (AltosDroid) activity;
+               mAltosDroid.registerTab(this);
+       }
+
+       @Override
+       public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+               View v = inflater.inflate(R.layout.tab_ascent, container, false);
+
+               mHeightView    = (TextView) v.findViewById(R.id.height_value);
+               mMaxHeightView = (TextView) v.findViewById(R.id.max_height_value);
+               mSpeedView     = (TextView) v.findViewById(R.id.speed_value);
+               mMaxSpeedView  = (TextView) v.findViewById(R.id.max_speed_value);
+               mAccelView     = (TextView) v.findViewById(R.id.accel_value);
+               mMaxAccelView  = (TextView) v.findViewById(R.id.max_accel_value);
+               mLatitudeView  = (TextView) v.findViewById(R.id.lat_value);
+               mLongitudeView = (TextView) v.findViewById(R.id.lon_value);
+
+               mApogeeVoltageView = (TextView) v.findViewById(R.id.apogee_voltage_value);
+               mApogeeLights = new GoNoGoLights((ImageView) v.findViewById(R.id.apogee_redled),
+                                                (ImageView) v.findViewById(R.id.apogee_greenled),
+                                                getResources());
+
+               mMainVoltageView = (TextView) v.findViewById(R.id.main_voltage_value);
+               mMainLights = new GoNoGoLights((ImageView) v.findViewById(R.id.main_redled),
+                                              (ImageView) v.findViewById(R.id.main_greenled),
+                                              getResources());
+
+               return v;
+       }
+
+       @Override
+       public void onDestroy() {
+               super.onDestroy();
+               mAltosDroid.unregisterTab(this);
+               mAltosDroid = null;
+       }
+
+       public void update_ui(AltosState state) {
+               mHeightView.setText(String.format("%6.0f m", state.height));
+               mMaxHeightView.setText(String.format("%6.0f m", state.max_height));
+               mSpeedView.setText(String.format("%6.0f m/s", state.speed()));
+               mMaxSpeedView.setText(String.format("%6.0f m/s", state.max_speed()));
+               mAccelView.setText(String.format("%6.0f m/s²", state.acceleration));
+               mMaxAccelView.setText(String.format("%6.0f m/s²", state.max_acceleration));
+
+               mLatitudeView.setText(AltosDroid.pos(state.gps.lat, "N", "S"));
+               mLongitudeView.setText(AltosDroid.pos(state.gps.lon, "W", "E"));
+
+               mApogeeVoltageView.setText(String.format("%4.2f V", state.drogue_sense));
+               mApogeeLights.set(state.drogue_sense > 3.2);
+
+               mMainVoltageView.setText(String.format("%4.2f V", state.main_sense));
+               mMainLights.set(state.main_sense > 3.2);
+       }
+}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabDescent.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabDescent.java
new file mode 100644 (file)
index 0000000..3805b7e
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright © 2013 Mike Beattie <mike@ethernal.org>
+ *
+ * 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 org.altusmetrum.altoslib_1.AltosGreatCircle;
+import org.altusmetrum.altoslib_1.AltosState;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+public class TabDescent extends Fragment implements AltosDroidTab {
+       AltosDroid mAltosDroid;
+
+       private TextView mSpeedView;
+       private TextView mHeightView;
+       private TextView mElevationView;
+       private TextView mRangeView;
+       private TextView mBearingView;
+       private TextView mCompassView;
+       private TextView mDistanceView;
+       private TextView mLatitudeView;
+       private TextView mLongitudeView;
+       private TextView mApogeeVoltageView;
+       private GoNoGoLights mApogeeLights;
+       private TextView mMainVoltageView;
+       private GoNoGoLights mMainLights;
+
+
+       @Override
+       public void onAttach(Activity activity) {
+               super.onAttach(activity);
+               mAltosDroid = (AltosDroid) activity;
+               mAltosDroid.registerTab(this);
+       }
+
+       @Override
+       public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+               View v = inflater.inflate(R.layout.tab_descent, container, false);
+
+               mSpeedView     = (TextView) v.findViewById(R.id.speed_value);
+               mHeightView    = (TextView) v.findViewById(R.id.height_value);
+               mElevationView = (TextView) v.findViewById(R.id.elevation_value);
+               mRangeView     = (TextView) v.findViewById(R.id.range_value);
+               mBearingView   = (TextView) v.findViewById(R.id.bearing_value);
+               mCompassView   = (TextView) v.findViewById(R.id.compass_value);
+               mDistanceView  = (TextView) v.findViewById(R.id.distance_value);
+               mLatitudeView  = (TextView) v.findViewById(R.id.lat_value);
+               mLongitudeView = (TextView) v.findViewById(R.id.lon_value);
+
+               mApogeeVoltageView = (TextView) v.findViewById(R.id.apogee_voltage_value);
+               mApogeeLights = new GoNoGoLights((ImageView) v.findViewById(R.id.apogee_redled),
+                                                (ImageView) v.findViewById(R.id.apogee_greenled),
+                                                getResources());
+
+               mMainVoltageView = (TextView) v.findViewById(R.id.main_voltage_value);
+               mMainLights = new GoNoGoLights((ImageView) v.findViewById(R.id.main_redled),
+                                              (ImageView) v.findViewById(R.id.main_greenled),
+                                              getResources());
+
+               return v;
+       }
+
+
+       @Override
+       public void onDestroy() {
+               super.onDestroy();
+               mAltosDroid.unregisterTab(this);
+               mAltosDroid = null;
+       }
+
+       public void update_ui(AltosState state) {
+               mSpeedView.setText(String.format("%6.0f m/s", state.speed()));
+               mHeightView.setText(String.format("%6.0f m", state.height));
+               mElevationView.setText(String.format("%3.0f°", state.elevation));
+               mRangeView.setText(String.format("%6.0f m", state.range));
+               if (state.from_pad != null) {
+                       mBearingView.setText(String.format("%3.0f°", state.from_pad.bearing));
+                       mCompassView.setText(state.from_pad.bearing_words(AltosGreatCircle.BEARING_LONG));
+               }
+               mDistanceView.setText(String.format("%6.0f m", state.range));
+               mLatitudeView.setText(AltosDroid.pos(state.gps.lat, "N", "S"));
+               mLongitudeView.setText(AltosDroid.pos(state.gps.lon, "W", "E"));
+
+               mApogeeVoltageView.setText(String.format("%4.2f V", state.drogue_sense));
+               mApogeeLights.set(state.drogue_sense > 3.2);
+
+               mMainVoltageView.setText(String.format("%4.2f V", state.main_sense));
+               mMainLights.set(state.main_sense > 3.2);
+       }
+
+}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabLanded.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabLanded.java
new file mode 100644 (file)
index 0000000..a95e914
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright © 2013 Mike Beattie <mike@ethernal.org>
+ *
+ * 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 org.altusmetrum.altoslib_1.AltosState;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+public class TabLanded extends Fragment implements AltosDroidTab {
+       AltosDroid mAltosDroid;
+
+       private TextView mBearingView;
+       private TextView mDistanceView;
+       private TextView mLatitudeView;
+       private TextView mLongitudeView;
+       private TextView mMaxHeightView;
+       private TextView mMaxSpeedView;
+       private TextView mMaxAccelView;
+
+
+       @Override
+       public void onAttach(Activity activity) {
+               super.onAttach(activity);
+               mAltosDroid = (AltosDroid) activity;
+               mAltosDroid.registerTab(this);
+       }
+
+       @Override
+       public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+               View v = inflater.inflate(R.layout.tab_landed, container, false);
+
+               mBearingView   = (TextView) v.findViewById(R.id.bearing_value);
+               mDistanceView  = (TextView) v.findViewById(R.id.distance_value);
+               mLatitudeView  = (TextView) v.findViewById(R.id.lat_value);
+               mLongitudeView = (TextView) v.findViewById(R.id.lon_value);
+               mMaxHeightView = (TextView) v.findViewById(R.id.max_height_value);
+               mMaxSpeedView  = (TextView) v.findViewById(R.id.max_speed_value);
+               mMaxAccelView  = (TextView) v.findViewById(R.id.max_accel_value);
+
+               return v;
+       }
+
+       @Override
+       public void onDestroy() {
+               super.onDestroy();
+               mAltosDroid.unregisterTab(this);
+               mAltosDroid = null;
+       }
+
+       public void update_ui(AltosState state) {
+               if (state.from_pad != null) {
+                       mBearingView.setText(String.format("%3.0f°", state.from_pad.bearing));
+                       mDistanceView.setText(String.format("%6.0f m", state.from_pad.distance));
+               }
+               mLatitudeView.setText(AltosDroid.pos(state.gps.lat, "N", "S"));
+               mLongitudeView.setText(AltosDroid.pos(state.gps.lon, "W", "E"));
+               mMaxHeightView.setText(String.format("%6.0f m", state.max_height));
+               mMaxAccelView.setText(String.format("%6.0f m/s²", state.max_acceleration));
+               mMaxSpeedView.setText(String.format("%6.0f m/s", state.max_speed()));
+       }
+
+}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java
new file mode 100644 (file)
index 0000000..b30b469
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright © 2013 Mike Beattie <mike@ethernal.org>
+ *
+ * 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 org.altusmetrum.altoslib_1.AltosState;
+
+import com.google.android.gms.maps.GoogleMap;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentTransaction;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class TabMap extends Fragment implements AltosDroidTab {
+       AltosDroid mAltosDroid;
+
+       private GoogleMap mMap;
+
+
+       @Override
+       public void onAttach(Activity activity) {
+               super.onAttach(activity);
+               mAltosDroid = (AltosDroid) activity;
+               mAltosDroid.registerTab(this);
+       }
+
+       @Override
+       public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+               View v = inflater.inflate(R.layout.tab_map, container, false);
+               return v;
+       }
+
+       @Override
+       public void onDestroyView() {
+               super.onDestroyView();
+
+               mAltosDroid.unregisterTab(this);
+               mAltosDroid = null;
+
+               //Fragment fragment = (getFragmentManager().findFragmentById(R.id.map));
+               //FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
+               //ft.remove(fragment);
+               //ft.commit();
+       }
+
+       public void update_ui(AltosState state) {
+//             mRangeView.setText(String.format("%6.0f m", state.range));
+//             if (state.from_pad != null)
+//                     mBearingView.setText(String.format("%3.0f°", state.from_pad.bearing));
+//             mLatitudeView.setText(pos(state.gps.lat, "N", "S"));
+//             mLongitudeView.setText(pos(state.gps.lon, "W", "E"));
+       }
+
+}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java
new file mode 100644 (file)
index 0000000..41776c1
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * Copyright © 2013 Mike Beattie <mike@ethernal.org>
+ *
+ * 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 org.altusmetrum.altoslib_1.*;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+public class TabPad extends Fragment implements AltosDroidTab {
+       AltosDroid mAltosDroid;
+
+       private TextView mBatteryVoltageView;
+       private GoNoGoLights mBatteryLights;
+       private TextView mApogeeVoltageView;
+       private GoNoGoLights mApogeeLights;
+       private TextView mMainVoltageView;
+       private GoNoGoLights mMainLights;
+       private TextView mDataLoggingView;
+       private GoNoGoLights mDataLoggingLights;
+       private TextView mGPSLockedView;
+       private GoNoGoLights mGPSLockedLights;
+       private TextView mGPSReadyView;
+       private GoNoGoLights mGPSReadyLights;
+       private TextView mPadLatitudeView;
+       private TextView mPadLongitudeView;
+       private TextView mPadAltitudeView;
+
+       @Override
+       public void onAttach(Activity activity) {
+               super.onAttach(activity);
+               mAltosDroid = (AltosDroid) activity;
+               mAltosDroid.registerTab(this);
+       }
+
+       @Override
+       public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+               View v = inflater.inflate(R.layout.tab_pad, container, false);
+               mBatteryVoltageView = (TextView) v.findViewById(R.id.battery_voltage_value);
+               mBatteryLights = new GoNoGoLights((ImageView) v.findViewById(R.id.battery_redled),
+                                                 (ImageView) v.findViewById(R.id.battery_greenled),
+                                                 getResources());
+
+               mApogeeVoltageView = (TextView) v.findViewById(R.id.apogee_voltage_value);
+               mApogeeLights = new GoNoGoLights((ImageView) v.findViewById(R.id.apogee_redled),
+                                                (ImageView) v.findViewById(R.id.apogee_greenled),
+                                                getResources());
+
+               mMainVoltageView = (TextView) v.findViewById(R.id.main_voltage_value);
+               mMainLights = new GoNoGoLights((ImageView) v.findViewById(R.id.main_redled),
+                                              (ImageView) v.findViewById(R.id.main_greenled),
+                                              getResources());
+
+               mDataLoggingView = (TextView) v.findViewById(R.id.logging_value);
+               mDataLoggingLights = new GoNoGoLights((ImageView) v.findViewById(R.id.logging_redled),
+                                                     (ImageView) v.findViewById(R.id.logging_greenled),
+                                                     getResources());
+
+               mGPSLockedView = (TextView) v.findViewById(R.id.gps_locked_value);
+               mGPSLockedLights = new GoNoGoLights((ImageView) v.findViewById(R.id.gps_locked_redled),
+                                                   (ImageView) v.findViewById(R.id.gps_locked_greenled),
+                                                   getResources());
+
+               mGPSReadyView = (TextView) v.findViewById(R.id.gps_ready_value);
+               mGPSReadyLights = new GoNoGoLights((ImageView) v.findViewById(R.id.gps_ready_redled),
+                                                  (ImageView) v.findViewById(R.id.gps_ready_greenled),
+                                                  getResources());
+
+               mPadLatitudeView = (TextView) v.findViewById(R.id.pad_lat_value);
+               mPadLongitudeView = (TextView) v.findViewById(R.id.pad_lon_value);
+               mPadAltitudeView = (TextView) v.findViewById(R.id.pad_alt_value);
+        return v;
+       }
+
+       @Override
+       public void onDestroy() {
+               super.onDestroy();
+               mAltosDroid.unregisterTab(this);
+               mAltosDroid = null;
+       }
+
+       public void update_ui(AltosState state) {
+               mBatteryVoltageView.setText(String.format("%4.2f V", state.battery));
+               mBatteryLights.set(state.battery > 3.7);
+
+               mApogeeVoltageView.setText(String.format("%4.2f V", state.drogue_sense));
+               mApogeeLights.set(state.drogue_sense > 3.2);
+
+               mMainVoltageView.setText(String.format("%4.2f V", state.main_sense));
+               mMainLights.set(state.main_sense > 3.2);
+
+               if (state.data.flight != 0) {
+                       if (state.data.state <= AltosLib.ao_flight_pad)
+                               mDataLoggingView.setText("Ready to record");
+                       else if (state.data.state < AltosLib.ao_flight_landed)
+                               mDataLoggingView.setText("Recording data");
+                       else
+                               mDataLoggingView.setText("Recorded data");
+               } else {
+                       mDataLoggingView.setText("Storage full");
+               }
+               mDataLoggingLights.set(state.data.flight != 0);
+
+               mGPSLockedView.setText(String.format("%4d sats", state.gps.nsat));
+               mGPSLockedLights.set(state.gps.locked && state.gps.nsat >= 4);
+
+               if (state.gps_ready)
+                       mGPSReadyView.setText("Ready");
+               else
+                       mGPSReadyView.setText(String.format("Waiting %d", state.gps_waiting));
+               mGPSReadyLights.set(state.gps_ready);
+
+               mPadLatitudeView.setText(AltosDroid.pos(state.pad_lat, "N", "S"));
+               mPadLongitudeView.setText(AltosDroid.pos(state.pad_lon, "W", "E"));
+               mPadAltitudeView.setText(String.format("%4.0f m", state.pad_alt));
+       }
+
+}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabsAdapter.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabsAdapter.java
new file mode 100644 (file)
index 0000000..a4758c3
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import java.util.ArrayList;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.FragmentPagerAdapter;
+import android.support.v4.view.ViewPager;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TabHost;
+import android.widget.TabWidget;
+
+
+
+/**
+ * This is a helper class that implements the management of tabs and all
+ * details of connecting a ViewPager with associated TabHost.  It relies on a
+ * trick.  Normally a tab host has a simple API for supplying a View or
+ * Intent that each tab will show.  This is not sufficient for switching
+ * between pages.  So instead we make the content part of the tab host
+ * 0dp high (it is not shown) and the TabsAdapter supplies its own dummy
+ * view to show as the tab content.  It listens to changes in tabs, and takes
+ * care of switch to the correct paged in the ViewPager whenever the selected
+ * tab changes.
+ */
+public class TabsAdapter extends FragmentPagerAdapter
+               implements TabHost.OnTabChangeListener, ViewPager.OnPageChangeListener {
+       private final Context mContext;
+       private final TabHost mTabHost;
+       private final ViewPager mViewPager;
+       private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
+
+       static final class TabInfo {
+               private final String tag;
+               private final Class<?> clss;
+               private final Bundle args;
+
+               TabInfo(String _tag, Class<?> _class, Bundle _args) {
+                       tag = _tag;
+                       clss = _class;
+                       args = _args;
+               }
+       }
+
+       static class DummyTabFactory implements TabHost.TabContentFactory {
+               private final Context mContext;
+
+               public DummyTabFactory(Context context) {
+                       mContext = context;
+               }
+
+               public View createTabContent(String tag) {
+                       View v = new View(mContext);
+                       v.setMinimumWidth(0);
+                       v.setMinimumHeight(0);
+                       return v;
+               }
+       }
+
+       public TabsAdapter(FragmentActivity activity, TabHost tabHost, ViewPager pager) {
+               super(activity.getSupportFragmentManager());
+               mContext = activity;
+               mTabHost = tabHost;
+               mViewPager = pager;
+               mTabHost.setOnTabChangedListener(this);
+               mViewPager.setAdapter(this);
+               mViewPager.setOnPageChangeListener(this);
+       }
+
+       public void addTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args) {
+               tabSpec.setContent(new DummyTabFactory(mContext));
+               String tag = tabSpec.getTag();
+
+               TabInfo info = new TabInfo(tag, clss, args);
+               mTabs.add(info);
+               mTabHost.addTab(tabSpec);
+               notifyDataSetChanged();
+       }
+
+       @Override
+       public int getCount() {
+               return mTabs.size();
+       }
+
+       @Override
+       public Fragment getItem(int position) {
+               TabInfo info = mTabs.get(position);
+               return Fragment.instantiate(mContext, info.clss.getName(), info.args);
+       }
+
+       public void onTabChanged(String tabId) {
+               int position = mTabHost.getCurrentTab();
+               mViewPager.setCurrentItem(position);
+       }
+
+       public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
+       }
+
+       public void onPageSelected(int position) {
+               // Unfortunately when TabHost changes the current tab, it kindly
+               // also takes care of putting focus on it when not in touch mode.
+               // The jerk.
+               // This hack tries to prevent this from pulling focus out of our
+               // ViewPager.
+               TabWidget widget = mTabHost.getTabWidget();
+               int oldFocusability = widget.getDescendantFocusability();
+               widget.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
+               mTabHost.setCurrentTab(position);
+               widget.setDescendantFocusability(oldFocusability);
+       }
+
+       public void onPageScrollStateChanged(int state) {
+       }
+}