Merge remote-tracking branch 'mjb/altosdroid'
authorKeith Packard <keithp@keithp.com>
Thu, 7 Mar 2013 21:00:44 +0000 (13:00 -0800)
committerKeith Packard <keithp@keithp.com>
Thu, 7 Mar 2013 21:00:44 +0000 (13:00 -0800)
21 files changed:
altosdroid/.classpath
altosdroid/.gitignore
altosdroid/AndroidManifest.xml
altosdroid/Makefile.am
altosdroid/project.properties
altosdroid/res/layout/altosdroid.xml
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]

index 0ca188f976cb1ad5ecb928955d6393cf283d7a0d..fce248e6a6bf25602288b07adcc6fcab5aeb80d7 100644 (file)
@@ -1,8 +1,10 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
        <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+       <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
        <classpathentry kind="src" path="src"/>
        <classpathentry kind="src" path="gen"/>
-       <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+       <classpathentry kind="lib" path="libs/android-support-v4.jar"/>
+       <classpathentry kind="lib" path="libs/altoslib_1.jar"/>
        <classpathentry kind="output" path="bin/classes"/>
 </classpath>
index 0d2ee6e0b5c12d6212c25ddd28db36a7eea586ff..7f0858eafbaefc752503fb6f4e89da24ca3ac5cc 100644 (file)
@@ -2,4 +2,6 @@ local.properties
 bin
 gen
 libs
+google-play-services_lib
 src/org/altusmetrum/AltosDroid/BuildInfo.java
+res/drawable/*led.png
index 8ecfcbb52e0a3f7d259a123debca1720f4430ec5..237c6dcf40e1dbf01498337c169709233cbd8cff 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-      package="org.altusmetrum.AltosDroid"
-      android:versionCode="1"
-      android:versionName="1.1.9.3">
+          package="org.altusmetrum.AltosDroid"
+          android:versionCode="1"
+          android:versionName="1.1.9.3">
     <uses-sdk android:targetSdkVersion="10" android:minSdkVersion="10"/>
+    <!-- Google Maps -->
+    <uses-feature android:glEsVersion="0x00020000" android:required="true"/>
+
+    <!-- Permissions needed to access bluetooth -->
     <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
     <uses-permission android:name="android.permission.BLUETOOTH" />
+    <!-- Permissions needed to save Telemetry logs to SD card -->
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <!-- Permissions needed for GoogleMaps -->
+    <uses-permission android:name="android.permission.INTERNET"/>
+    <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
+    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
+    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
+
+    <permission android:name="org.altusmetrum.AltosDroid.permission.MAPS_RECEIVE"
+                android:protectionLevel="signature"/>
+    <uses-permission android:name="org.altusmetrum.AltosDroid.permission.MAPS_RECEIVE"/>
+
 
     <application android:label="@string/app_name"
-                 android:icon="@drawable/app_icon" >
-        <activity android:label="@string/app_name"
-                  android:configChanges="orientation|keyboardHidden" android:name="org.altusmetrum.AltosDroid.AltosDroid">
+                 android:icon="@drawable/app_icon"
+                 android:allowBackup="true" >
+        <activity android:name="org.altusmetrum.AltosDroid.AltosDroid"
+                  android:label="@string/app_name"
+                  android:configChanges="orientation|keyboardHidden" >
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
@@ -38,9 +55,9 @@
                   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"
+                   android:value="AIzaSyDSr6u4i9TJmVGhgGk4g0wUUhTy9FGyn0s"/>
     </application>
 </manifest>
index 39f3c2b6a48439d82a08811c012ea778fa2f99d8..3dbabdd7361603595e11c9becdb538dd077a528d 100644 (file)
@@ -1,12 +1,11 @@
 if ANDROID
-all_target=bin/AltosDroid-debug.apk bin/AltosDroid-release.apk
-clean_command=ant clean
+all_target=bin/AltosDroid-debug.apk bin/AltosDroid-release-unsigned.apk
 else
 all_target=
-clean_command=echo done
 endif
 
 SDK=$(ANDROID_SDK)
+SDK_TARGET=$(shell sed -ne 's/^target=//p' project.properties)
 
 DX=$(SDK)/platform-tools/dx
 ADB=$(SDK)/platform-tools/adb
@@ -14,34 +13,52 @@ AAPT=$(SDK)/platform-tools/aapt
 APKBUILDER=$(SDK)/tools/apkbuilder
 ZIPALIGN=$(SDK)/tools/zipalign
 
-SRC_DIR=src/org/altusmetrum/AltosDroid
+JAVA_SRC_DIR=src/org/altusmetrum/AltosDroid
 EXT_LIBDIR=libs
+DRAWABLE_DIR=res/drawable
 ALTOSLIB_SRCDIR=../altoslib
 ALTOSLIB_JAR=altoslib_$(ALTOSLIB_VERSION).jar
 
 ALTOSLIB=$(EXT_LIBDIR)/$(ALTOSLIB_JAR)
 
-SRC=\
-       $(SRC_DIR)/AltosDroid.java \
-       $(SRC_DIR)/AltosDroidPreferences.java \
-       $(SRC_DIR)/AltosVoice.java \
-       $(SRC_DIR)/TelemetryService.java \
-       $(SRC_DIR)/TelemetryReader.java \
-       $(SRC_DIR)/TelemetryLogger.java \
-       $(SRC_DIR)/AltosBluetooth.java \
-       $(SRC_DIR)/DeviceListActivity.java \
-       $(SRC_DIR)/BuildInfo.java \
-       $(SRC_DIR)/Dumper.java
+SUPPORT_V4_SRCDIR=$(SDK)/extras/android/support/v4
+SUPPORT_V4_JAR=android-support-v4.jar
+
+SUPPORT_V4=$(EXT_LIBDIR)/$(SUPPORT_V4_JAR)
+
+GOOGLE_PLAY_SERVICES_LIB_SRCDIR=$(SDK)/extras/google/google_play_services/libproject
+GOOGLE_PLAY_SERVICES_LIB=google-play-services_lib
+
+JAVA_SRC=$(JAVA_SRC_DIR)/*.java
+
+DRAWABLES=\
+    $(DRAWABLE_DIR)/redled.png \
+    $(DRAWABLE_DIR)/greenled.png \
+    $(DRAWABLE_DIR)/grayled.png
+
+SRC=$(JAVA_SRC) $(DRAWABLES)
 
 all: $(all_target)
 
-$(ALTOSLIB): $(ALTOSLIB_SRCDIR)/$(ALTOSLIB_JAR)
+$(EXT_LIBDIR):
        mkdir -p $(EXT_LIBDIR)
-       cd $(EXT_LIBDIR) && ln -s $(shell echo $(EXT_LIBDIR) | sed 's|[^/]\+|..|g')/$(ALTOSLIB_SRCDIR)/$(ALTOSLIB_JAR) .
 
-$(SRC_DIR)/BuildInfo.java:
+$(ALTOSLIB): $(EXT_LIBDIR) $(ALTOSLIB_SRCDIR)/$(ALTOSLIB_JAR)
+       cd $(EXT_LIBDIR) && ln -sf $(shell echo $(EXT_LIBDIR) | sed 's|[^/]\+|..|g')/$(ALTOSLIB_SRCDIR)/$(ALTOSLIB_JAR) .
+
+$(SUPPORT_V4): $(EXT_LIBDIR) $(SUPPORT_V4_SRCDIR)/$(SUPPORT_V4_JAR)
+       cd $(EXT_LIBDIR) && ln -sf $(SUPPORT_V4_SRCDIR)/$(SUPPORT_V4_JAR) .
+
+$(GOOGLE_PLAY_SERVICES_LIB): $(GOOGLE_PLAY_SERVICES_LIB_SRCDIR)/$(GOOGLE_PLAY_SERVICES_LIB)
+       cp -a $(GOOGLE_PLAY_SERVICES_LIB_SRCDIR)/$(GOOGLE_PLAY_SERVICES_LIB) .
+       cd $(GOOGLE_PLAY_SERVICES_LIB) && $(SDK)/tools/android update project --target $(SDK_TARGET) --path .
+
+$(JAVA_SRC_DIR)/BuildInfo.java: $(JAVA_SRC)
        ./buildinfo.sh
 
+$(DRAWABLE_DIR)/%.png: ../icon/%.png
+       cd $(DRAWABLE_DIR) && ln -sf $(shell echo $(DRAWABLE_DIR) | sed 's|[^/]\+|..|g')/$< .
+
 if ANDROID
 install-release: bin/AltosDroid-release.apk
        $(ADB) install -r bin/AltosDroid-release.apk
@@ -49,26 +66,29 @@ install-release: bin/AltosDroid-release.apk
 install-debug: bin/AltosDroid-debug.apk
        $(ADB) install -r bin/AltosDroid-debug.apk
 
-bin/AltosDroid-debug.apk: $(SRC) $(ALTOSLIB)
+bin/AltosDroid-debug.apk: $(SRC) $(ALTOSLIB) $(SUPPORT_V4) $(GOOGLE_PLAY_SERVICES_LIB)
        ant debug
 
-bin/AltosDroid-release.apk: $(SRC) $(ALTOSLIB)
+bin/AltosDroid-release-unsigned.apk: $(SRC) $(ALTOSLIB) $(SUPPORT_V4) $(GOOGLE_PLAY_SERVICES_LIB)
        ant release
 
-sign:
+release: bin/AltosDroid-release-unsigned.apk
        jarsigner -keystore release.keystore \
           -signedjar bin/AltosDroid-release-signed.apk \
           bin/AltosDroid-release-unsigned.apk AltosDroid
-       $(SDK)/tools/zipalign -f 4 \
+       $(ZIPALIGN) -f 4 \
           bin/AltosDroid-release-signed.apk \
           bin/AltosDroid-release.apk
 
-endif
+clean: $(GOOGLE_PLAY_SERVICES_LIB)
+       ant clean
+       rm -rf $(EXT_LIBDIR)
+       rm -f $(DRAWABLES)
+       rm -rf $(GOOGLE_PLAY_SERVICES_LIB)
 
-clean: clean-local
-       $(clean_command)
+else
 
-clean-local:
-       rm -rf $(EXT_LIBDIR)
+clean:
+
+endif
 
-.PHONY: $(SRC_DIR)/BuildInfo.java
index 0a80e6441afd15821b54b0dd2a7affab4251c681..96b9551ce02b63037f437646af32581a9c4e5a5a 100644 (file)
@@ -8,4 +8,5 @@
 # project structure.
 
 # Project target.
-target=Google Inc.:Google APIs:10
+target=android-10
+android.library.reference.1=google-play-services_lib/
index 691c5e0467f5c4a659b2ee420083c0f81a979b99..ce812414232ad42d681478dd78c2a98fb219317e 100644 (file)
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!--
+        Copyright © 2012-2013 Mike Beattie <mike@ethernal.org>
 
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
+        This program is free software; you can redistribute it and/or modify
+        it under the terms of the GNU General Public License as published by
+        the Free Software Foundation; version 2 of the License.
 
-          http://www.apache.org/licenses/LICENSE-2.0
+        This program is distributed in the hope that it will be useful, but
+        WITHOUT ANY WARRANTY; without even the implied warranty of
+        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+        General Public License for more details.
 
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
+        You should have received a copy of the GNU General Public License along
+        with this program; if not, write to the Free Software Foundation, Inc.,
+        59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
 -->
-    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:layout_width="fill_parent"
-        android:layout_height="wrap_content"
-        android:layout_weight="0" >
-
-        <RelativeLayout
-            android:id="@+id/strut"
-            android:layout_width="10dip"
-            android:layout_height="wrap_content"
-            android:layout_centerHorizontal="true" >
-
-        </RelativeLayout>
-
-        <RelativeLayout
-            android:id="@+id/callsign_container"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_alignParentLeft="true"
-            android:layout_toLeftOf="@+id/strut" >
-
-            <TextView
-                android:id="@+id/callsign_label"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:text="@string/callsign_label" />
-
-            <TextView
-                android:id="@+id/callsign_value"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_alignParentRight="true"
-                android:layout_below="@id/callsign_label"
-                android:text=""
-                android:textAppearance="?android:attr/textAppearanceLarge" />
-
-        </RelativeLayout>
-
-        <RelativeLayout
-            android:id="@+id/rssi_container"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_toRightOf="@id/strut"
-            android:layout_alignParentRight="true" >
-
-            <TextView
-                android:id="@+id/rssi_label"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:text="@string/rssi_label" />
-
-            <TextView
-                android:id="@+id/rssi_value"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_alignParentRight="true"
-                android:layout_below="@+id/rssi_label"
-                android:textAppearance="?android:attr/textAppearanceLarge" />
-        </RelativeLayout>
-
-        <RelativeLayout
-            android:id="@+id/serial_container"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_below="@+id/callsign_container"
-            android:layout_toLeftOf="@+id/strut" >
-
-            <TextView
-                android:id="@+id/serial_label"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:text="@string/serial_label" />
-
-            <TextView
-                android:id="@+id/serial_value"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_alignParentRight="true"
-                android:layout_below="@+id/serial_label"
-                android:textAppearance="?android:attr/textAppearanceLarge" />
-        </RelativeLayout>
-
-        <RelativeLayout
-            android:id="@+id/flight_container"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_below="@+id/callsign_container"
-            android:layout_toRightOf="@+id/strut"
-            android:layout_alignParentRight="true" >
-
-            <TextView
-                android:id="@+id/flight_label"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:text="@string/flight_label" />
-
-            <TextView
-                android:id="@+id/flight_value"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_alignParentRight="true"
-                android:layout_below="@+id/flight_label"
-                android:textAppearance="?android:attr/textAppearanceLarge" />
-        </RelativeLayout>
-
-        <RelativeLayout
-            android:id="@+id/state_container"
-            android:layout_width="fill_parent"
-            android:layout_height="wrap_content"
-            android:layout_below="@+id/serial_container" >
-
-            <TextView
-                android:id="@+id/state_label"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:text="@string/state_label" />
-
-            <TextView
-                android:id="@+id/state_value"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_below="@+id/state_label"
-                android:layout_centerInParent="true"
-                android:textAppearance="?android:attr/textAppearanceLarge"
-                android:textSize="50dip" />
-
-        </RelativeLayout>
-
-        <RelativeLayout
-            android:id="@+id/speed_container"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_alignParentLeft="true"
-            android:layout_below="@+id/state_container"
-            android:layout_toLeftOf="@+id/strut" >
-
-            <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:id="@+id/accel_container"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_alignParentRight="true"
-            android:layout_below="@+id/state_container"
-            android:layout_toRightOf="@+id/strut" >
-
-            <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:id="@+id/range_container"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_alignParentLeft="true"
-            android:layout_below="@+id/speed_container"
-            android:layout_toLeftOf="@+id/strut" >
-
-            <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>
-
-        <RelativeLayout
-            android:id="@+id/height_container"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_alignParentRight="true"
-            android:layout_below="@id/speed_container"
-            android:layout_toRightOf="@id/strut" >
-
-            <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:id="@+id/elevation_container"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_alignParentLeft="true"
-            android:layout_below="@id/range_container"
-            android:layout_toLeftOf="@id/strut" >
-
-            <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:id="@+id/bearing_container"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_alignParentRight="true"
-            android:layout_below="@+id/range_container"
-            android:layout_toRightOf="@+id/strut" >
-
-            <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:id="@+id/latitude_container"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_below="@+id/elevation_container" >
-
-            <TextView
-                android:id="@+id/latitude_label"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:text="@string/latitude_label" />
-
-            <TextView
-                android:id="@+id/latitude_value"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_alignParentRight="true"
-                android:layout_below="@+id/latitude_label"
-                android:text=""
-                android:textAppearance="?android:attr/textAppearanceLarge" />
-
-        </RelativeLayout>
-
-        <RelativeLayout
-            android:id="@+id/longitude_container"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_below="@id/latitude_container" >
-
-            <TextView
-                android:id="@+id/longitude_label"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:text="@string/longitude_label" />
-
-            <TextView
-                android:id="@+id/longitude_value"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_alignParentRight="true"
-                android:layout_below="@+id/longitude_label"
-                android:text=""
-                android:textAppearance="?android:attr/textAppearanceLarge" />
-
-        </RelativeLayout>
-
-
-        <RelativeLayout
-            android:id="@+id/text_container"
-            android:layout_width="wrap_content"
-            android:layout_height="fill_parent"
-            android:layout_below="@id/longitude_container" >
-
-               <TextView
-                   android:id="@+id/text"
-                   android:layout_width="fill_parent"
-                   android:layout_height="fill_parent"
-                   android:layout_above="@+id/version"
-                   android:scrollbars="vertical"
-                   android:textSize="7dp"
-                   android:typeface="monospace" />
-        
-            <TextView
-                android:id="@+id/version"
-                android:layout_width="fill_parent"
-                android:layout_height="10dip"
-                android:layout_alignParentBottom="true"
-                android:gravity="bottom|right"
-                android:textSize="7dp"
-                android:typeface="monospace" />
-
-        </RelativeLayout>
-
-    </RelativeLayout>
+<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" >
+
+       <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:id="@+id/callsign_container"
+                       android:layout_width="0dp"
+                       android:layout_height="wrap_content"
+                       android:layout_weight="1" >
+
+                       <TextView
+                               android:id="@+id/callsign_label"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:text="@string/callsign_label" />
+
+                       <TextView
+                               android:id="@+id/callsign_value"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:layout_below="@+id/callsign_label"
+                               android:text=""
+                               android:textAppearance="?android:attr/textAppearanceLarge" />
+               </RelativeLayout>
+
+               <RelativeLayout
+                       android:id="@+id/serial_container"
+                       android:layout_width="0dp"
+                       android:layout_height="wrap_content"
+                       android:layout_weight="1" >
+
+                       <TextView
+                               android:id="@+id/serial_label"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:text="@string/serial_label" />
+
+                       <TextView
+                               android:id="@+id/serial_value"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:layout_below="@+id/serial_label"
+                               android:textAppearance="?android:attr/textAppearanceLarge" />
+               </RelativeLayout>
+
+               <RelativeLayout
+                       android:id="@+id/flight_container"
+                       android:layout_width="0dp"
+                       android:layout_height="wrap_content"
+                       android:layout_weight="1" >
+
+                       <TextView
+                               android:id="@+id/flight_label"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:text="@string/flight_label" />
+
+                       <TextView
+                               android:id="@+id/flight_value"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:layout_below="@+id/flight_label"
+                               android:textAppearance="?android:attr/textAppearanceLarge" />
+               </RelativeLayout>
+
+               <RelativeLayout
+                       android:id="@+id/state_container"
+                       android:layout_width="0dp"
+                       android:layout_height="wrap_content"
+                       android:layout_weight="1" >
+
+                       <TextView
+                               android:id="@+id/state_label"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:text="@string/state_label" />
+
+                       <TextView
+                               android:id="@+id/state_value"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:layout_below="@+id/state_label"
+                               android:textAppearance="?android:attr/textAppearanceLarge" />
+               </RelativeLayout>
+
+               <RelativeLayout
+                       android:id="@+id/rssi_container"
+                       android:layout_width="0dp"
+                       android:layout_height="wrap_content"
+                       android:layout_weight="1" >
+
+                       <TextView
+                               android:id="@+id/rssi_label"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:text="@string/rssi_label" />
+
+                       <TextView
+                               android:id="@+id/rssi_value"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:layout_below="@+id/rssi_label"
+                               android:textAppearance="?android:attr/textAppearanceLarge" />
+               </RelativeLayout>
+
+               <RelativeLayout
+                       android:id="@+id/age_container"
+                       android:layout_width="0dp"
+                       android:layout_height="wrap_content"
+                       android:layout_weight="1" >
+
+                       <TextView
+                               android:id="@+id/age_label"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:text="@string/age_label" />
+
+                       <TextView
+                               android:id="@+id/age_value"
+                               android:layout_width="wrap_content"
+                               android:layout_height="wrap_content"
+                               android:layout_below="@+id/age_label"
+                               android:textAppearance="?android:attr/textAppearanceLarge" />
+               </RelativeLayout>
+       </LinearLayout>
+
+       <TabHost
+               xmlns:android="http://schemas.android.com/apk/res/android"
+               android:id="@android:id/tabhost"
+               android:layout_width="fill_parent"
+               android:layout_height="0dp"
+               android:layout_weight="1" >
+
+               <LinearLayout
+                       android:layout_width="match_parent"
+                       android:layout_height="match_parent"
+                       android:orientation="vertical" >
+
+                       <TabWidget
+                               android:id="@android:id/tabs"
+                               android:layout_width="match_parent"
+                               android:layout_height="wrap_content"
+                               android:layout_weight="0"
+                               android:orientation="horizontal" />
+
+                       <FrameLayout
+                               android:id="@android:id/tabcontent"
+                               android:layout_width="0dp"
+                               android:layout_height="0dp"
+                               android:layout_weight="0" />
+
+                       <android.support.v4.view.ViewPager
+                               android:id="@+id/pager"
+                               android:layout_width="match_parent"
+                               android:layout_height="0dp"
+                               android:layout_weight="1" />
+               </LinearLayout>
+       </TabHost>
+
+       <TextView
+               android:id="@+id/version"
+               android:layout_width="fill_parent"
+               android:layout_height="10dip"
+               android:layout_weight="0"
+               android:gravity="bottom|right"
+               android:textSize="7sp"
+               android:typeface="monospace" />
+
+</LinearLayout>
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 1b28284a33b4911dedb77e6b7deaaa5d2f65e0e6..639611c20053711007bca29fbc1d0d8fd3c22d77 100644 (file)
@@ -1,60 +1,79 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!--
+        Copyright © 2012-2013 Mike Beattie <mike@ethernal.org>
 
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
+        This program is free software; you can redistribute it and/or modify
+        it under the terms of the GNU General Public License as published by
+        the Free Software Foundation; version 2 of the License.
 
-          http://www.apache.org/licenses/LICENSE-2.0
+        This program is distributed in the hope that it will be useful, but
+        WITHOUT ANY WARRANTY; without even the implied warranty of
+        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+        General Public License for more details.
 
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
+        You should have received a copy of the GNU General Public License along
+        with this program; if not, write to the Free Software Foundation, Inc.,
+        59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
 -->
-
 <resources>
-    <string name="app_name">AltosDroid</string>
 
-    <!--  AltosDroid -->
-    <string name="bt_not_enabled">Bluetooth was not enabled.</string>
-    <string name="title_connecting">connecting…</string>
-    <string name="title_connected_to">connected: </string>
-    <string name="title_not_connected">not connected</string>
+       <string name="app_name">AltosDroid</string>
 
-    <!-- Options Menu -->
-    <string name="connect_device">Connect a device</string>
-    <string name="select_freq">Select radio frequency</string>
+       <!-- AltosDroid -->
+       <string name="bt_not_enabled">Bluetooth was not enabled.</string>
+       <string name="title_connecting">connecting…</string>
+       <string name="title_connected_to">connected: </string>
+       <string name="title_not_connected">not connected</string>
 
-    <!--  DeviceListActivity -->
-    <string name="scanning">scanning for devices…</string>
-    <string name="select_device">select a device to connect</string>
-    <string name="none_paired">No devices have been paired</string>
-    <string name="none_found">No devices found</string>
-    <string name="title_paired_devices">Paired Devices</string>
-    <string name="title_other_devices">Other Available Devices</string>
-    <string name="button_scan">Scan for devices</string>
+       <!-- Options Menu -->
+       <string name="connect_device">Connect a device</string>
+       <string name="select_freq">Select radio frequency</string>
 
-    <!-- Service -->
-    <string name="telemetry_service_label">AltosDroid Telemetry Service</string>
-    <string name="telemetry_service_started">Telemetry Service Started</string>
-    <string name="telemetry_service_stopped">Telemetry Service Stopped</string>
+       <!-- DeviceListActivity -->
+       <string name="scanning">scanning for devices…</string>
+       <string name="select_device">select a device to connect</string>
+       <string name="none_paired">No devices have been paired</string>
+       <string name="none_found">No devices found</string>
+       <string name="title_paired_devices">Paired Devices</string>
+       <string name="title_other_devices">Other Available Devices</string>
+       <string name="button_scan">Scan for devices</string>
 
+       <!-- Service -->
+       <string name="telemetry_service_label">AltosDroid Telemetry Service</string>
+       <string name="telemetry_service_started">Telemetry Service Started</string>
+       <string name="telemetry_service_stopped">Telemetry Service Stopped</string>
 
        <!-- UI fields -->
-    <string name="callsign_label">Callsign</string>
-    <string name="serial_label">Serial no.</string>
-    <string name="flight_label">Flight no.</string>
-    <string name="rssi_label">RSSI</string>
-    <string name="state_label">State</string>
-    <string name="speed_label">Speed</string>
-    <string name="accel_label">Acceleration</string>
-    <string name="range_label">Range</string>
-    <string name="height_label">Height</string>
-    <string name="elevation_label">Elevation</string>
-    <string name="bearing_label">Bearing</string>
-    <string name="latitude_label">Latitude</string>
-    <string name="longitude_label">Longitude</string>
+       <!-- 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 61931731ff320094db1efe2dace1f529a3d396df..63043abd503468e9e1730cf5ebbcd0290f45a8c8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2012 Mike Beattie <mike@ethernal.org>
+ * Copyright © 2012-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
@@ -18,6 +18,9 @@
 package org.altusmetrum.AltosDroid;
 
 import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Timer;
+import java.util.TimerTask;
 
 import android.app.Activity;
 import android.bluetooth.BluetoothAdapter;
@@ -33,18 +36,21 @@ import android.os.Handler;
 import android.os.Message;
 import android.os.Messenger;
 import android.os.RemoteException;
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.view.ViewPager;
 import android.util.Log;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.Window;
+import android.widget.TabHost;
 import android.widget.TextView;
 import android.widget.Toast;
 import android.app.AlertDialog;
 
 import org.altusmetrum.altoslib_1.*;
 
-public class AltosDroid extends Activity {
+public class AltosDroid extends FragmentActivity {
        // Debugging
        private static final String TAG = "AltosDroid";
        private static final boolean D = true;
@@ -52,6 +58,7 @@ public class AltosDroid extends Activity {
        // Message types received by our Handler
        public static final int MSG_STATE_CHANGE    = 1;
        public static final int MSG_TELEMETRY       = 2;
+       public static final int MSG_UPDATE_AGE      = 3;
 
        // Intent request codes
        private static final int REQUEST_CONNECT_DEVICE = 1;
@@ -66,18 +73,21 @@ public class AltosDroid extends Activity {
        private TextView mSerialView;
        private TextView mFlightView;
        private TextView mStateView;
-       private TextView mSpeedView;
-       private TextView mAccelView;
-       private TextView mRangeView;
-       private TextView mHeightView;
-       private TextView mElevationView;
-       private TextView mBearingView;
-       private TextView mLatitudeView;
-       private TextView mLongitudeView;
+       private TextView mAgeView;
 
        // field to display the version at the bottom of the screen
        private TextView mVersion;
 
+       // Tabs
+       TabHost     mTabHost;
+       ViewPager   mViewPager;
+       TabsAdapter mTabsAdapter;
+       ArrayList<AltosDroidTab> mTabs = new ArrayList<AltosDroidTab>();
+
+       // Timer and Saved flight state for Age calculation
+       private Timer timer = new Timer();
+       AltosState saved_state;
+
        // Service
        private boolean mIsBound   = false;
        private Messenger mService = null;
@@ -127,6 +137,11 @@ public class AltosDroid extends Activity {
                        case MSG_TELEMETRY:
                                ad.update_ui((AltosState) msg.obj);
                                break;
+                       case MSG_UPDATE_AGE:
+                               if (ad.saved_state != null) {
+                                       ad.mAgeView.setText(String.format("%d", (System.currentTimeMillis() - ad.saved_state.report_time + 500) / 1000));
+                               }
+                               break;
                        }
                }
        };
@@ -150,7 +165,6 @@ public class AltosDroid extends Activity {
                }
        };
 
-
        void doBindService() {
                bindService(new Intent(this, TelemetryService.class), mConnection, Context.BIND_AUTO_CREATE);
                mIsBound = true;
@@ -174,26 +188,53 @@ public class AltosDroid extends Activity {
                }
        }
 
+       public void registerTab(AltosDroidTab mTab) {
+               mTabs.add(mTab);
+       }
+
+       public void unregisterTab(AltosDroidTab mTab) {
+               mTabs.remove(mTab);
+       }
+
        void update_ui(AltosState state) {
+               if (saved_state != null) {
+                       if (saved_state.state != state.state) {
+                               String currentTab = mTabHost.getCurrentTabTag();
+                               switch (state.state) {
+                               case AltosLib.ao_flight_boost:
+                                       if (currentTab.equals("pad")) mTabHost.setCurrentTabByTag("ascent");
+                                       break;
+                               case AltosLib.ao_flight_drogue:
+                                       if (currentTab.equals("ascent")) mTabHost.setCurrentTabByTag("descent");
+                                       break;
+                               case AltosLib.ao_flight_landed:
+                                       if (currentTab.equals("descent")) mTabHost.setCurrentTabByTag("landed");
+                                       break;
+                               }
+                       }
+               }
+               saved_state = state;
+
                mCallsignView.setText(state.data.callsign);
-               mRSSIView.setText(String.format("%d", state.data.rssi));
                mSerialView.setText(String.format("%d", state.data.serial));
                mFlightView.setText(String.format("%d", state.data.flight));
                mStateView.setText(state.data.state());
-               mSpeedView.setText(String.format("%6.0f m/s", state.speed()));
-               mAccelView.setText(String.format("%6.0f m/s²", state.acceleration));
-               mRangeView.setText(String.format("%6.0f m", state.range));
-               mHeightView.setText(String.format("%6.0f m", state.height));
-               mElevationView.setText(String.format("%3.0f°", state.elevation));
-               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"));
+               mRSSIView.setText(String.format("%d", state.data.rssi));
+
+               for (AltosDroidTab mTab : mTabs)
+                       mTab.update_ui(state);
 
                mAltosVoice.tell(state);
        }
 
-       String pos(double p, String pos, String neg) {
+       private void onTimerTick() {
+               try {
+                       mMessenger.send(Message.obtain(null, MSG_UPDATE_AGE));
+               } catch (RemoteException e) {
+               }
+       }
+
+       static String pos(double p, String pos, String neg) {
                String  h = pos;
                if (p < 0) {
                        h = neg;
@@ -228,6 +269,21 @@ public class AltosDroid extends Activity {
                setContentView(R.layout.altosdroid);
                getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.custom_title);
 
+               mTabHost = (TabHost)findViewById(android.R.id.tabhost);
+               mTabHost.setup();
+
+               mViewPager = (ViewPager)findViewById(R.id.pager);
+               mViewPager.setOffscreenPageLimit(4);
+
+               mTabsAdapter = new TabsAdapter(this, mTabHost, mViewPager);
+
+               mTabsAdapter.addTab(mTabHost.newTabSpec("pad").setIndicator("Pad"), TabPad.class, null);
+               mTabsAdapter.addTab(mTabHost.newTabSpec("ascent").setIndicator("Ascent"), TabAscent.class, null);
+               mTabsAdapter.addTab(mTabHost.newTabSpec("descent").setIndicator("Descent"), TabDescent.class, null);
+               mTabsAdapter.addTab(mTabHost.newTabSpec("landed").setIndicator("Landed"), TabLanded.class, null);
+               mTabsAdapter.addTab(mTabHost.newTabSpec("map").setIndicator("Map"), TabMap.class, null);
+
+
                // Set up the custom title
                mTitle = (TextView) findViewById(R.id.title_left_text);
                mTitle.setText(R.string.app_name);
@@ -244,14 +300,9 @@ public class AltosDroid extends Activity {
                mSerialView    = (TextView) findViewById(R.id.serial_value);
                mFlightView    = (TextView) findViewById(R.id.flight_value);
                mStateView     = (TextView) findViewById(R.id.state_value);
-               mSpeedView     = (TextView) findViewById(R.id.speed_value);
-               mAccelView     = (TextView) findViewById(R.id.accel_value);
-               mRangeView     = (TextView) findViewById(R.id.range_value);
-               mHeightView    = (TextView) findViewById(R.id.height_value);
-               mElevationView = (TextView) findViewById(R.id.elevation_value);
-               mBearingView   = (TextView) findViewById(R.id.bearing_value);
-               mLatitudeView  = (TextView) findViewById(R.id.latitude_value);
-               mLongitudeView = (TextView) findViewById(R.id.longitude_value);
+               mAgeView       = (TextView) findViewById(R.id.age_value);
+
+               timer.scheduleAtFixedRate(new TimerTask(){ public void run() {onTimerTick();}}, 1000L, 100L);
 
                mAltosVoice = new AltosVoice(this);
        }
@@ -300,9 +351,6 @@ public class AltosDroid extends Activity {
                mAltosVoice.stop();
        }
 
-
-
-
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
                if(D) Log.d(TAG, "onActivityResult " + resultCode);
                switch (requestCode) {
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) {
+       }
+}