altosdroid: Add configurable frequency set
authorKeith Packard <keithp@keithp.com>
Wed, 27 Apr 2016 05:40:47 +0000 (01:40 -0400)
committerKeith Packard <keithp@keithp.com>
Wed, 27 Apr 2016 05:40:47 +0000 (01:40 -0400)
Signed-off-by: Keith Packard <keithp@keithp.com>
altosdroid/AndroidManifest.xml.in
altosdroid/res/layout/frequency.xml [new file with mode: 0644]
altosdroid/res/layout/manage_frequencies.xml [new file with mode: 0644]
altosdroid/res/layout/setup.xml
altosdroid/res/values/strings.xml
altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java
altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferencesBackend.java
altosdroid/src/org/altusmetrum/AltosDroid/ManageFrequenciesActivity.java [new file with mode: 0644]
altosdroid/src/org/altusmetrum/AltosDroid/SetupActivity.java
altoslib/AltosFrequency.java

index 3409c9f..2644d74 100644 (file)
        <activity android:name=".SetupActivity"
                  android:label="@string/setup"
                   android:theme="@android:style/Theme.Dialog"
-                  android:configChanges="orientation|keyboardHidden" />
+                  android:configChanges="orientation" />
+                 
+       <activity android:name=".ManageFrequenciesActivity"
+                 android:label="@string/manage_frequencies"
+                  android:theme="@android:style/Theme.Dialog"
+                  android:configChanges="orientation|keyboard" />
                  
         <service android:name=".TelemetryService" />
 
diff --git a/altosdroid/res/layout/frequency.xml b/altosdroid/res/layout/frequency.xml
new file mode 100644 (file)
index 0000000..7f8d404
--- /dev/null
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ Copyright © 2016 Keith Packard <keithp@keithp.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:orientation="horizontal"
+    >
+  <TextView
+      android:id="@+id/frequency"
+      android:layout_width="wrap_content"
+      android:layout_height="fill_parent"
+      android:padding="10dp"
+      android:layout_weight="1"
+      />
+</LinearLayout>
diff --git a/altosdroid/res/layout/manage_frequencies.xml b/altosdroid/res/layout/manage_frequencies.xml
new file mode 100644 (file)
index 0000000..77ded1d
--- /dev/null
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ Copyright © 2016 Keith Packard <keithp@keithp.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    >
+
+    <LinearLayout
+       xmlns:android="http://schemas.android.com/apk/res/android"
+       android:id="@+id/set_layout"
+       android:layout_width="fill_parent"
+       android:layout_height="wrap_content"
+       android:orientation="horizontal"
+       >
+      <EditText
+         android:id="@+id/set_frequency"
+         android:layout_width="wrap_content"
+         android:layout_height="fill_parent"
+         android:padding="10dp"
+         android:layout_weight="1"
+         android:hint="@string/frequency"
+         android:inputType="number|numberDecimal"/>
+      />
+      <TextView
+         android:id="@+id/mhz"
+         android:layout_width="wrap_content"
+         android:layout_height="fill_parent"
+         android:padding="10dp"
+         android:layout_weight="0"
+         android:text="@string/mhz"
+         />
+      <EditText
+         android:id="@+id/set_description"
+         android:layout_width="wrap_content"
+         android:layout_height="fill_parent"  
+         android:padding="10dp"
+         android:layout_weight="2"
+         android:hint="@string/description"
+         />
+    </LinearLayout>
+    <LinearLayout
+       android:orientation="horizontal"
+       android:layout_width="match_parent"
+       android:layout_height="wrap_content"
+       >
+      <Button android:id="@+id/set"
+              android:layout_width="wrap_content"
+              android:layout_height="wrap_content"
+              android:text="@string/set"
+             android:layout_weight="1"
+             />
+      
+      <Button android:id="@+id/remove"
+              android:layout_width="wrap_content"
+              android:layout_height="wrap_content"
+              android:text="@string/remove"
+             android:layout_weight="1"
+             />
+      
+      <Button android:id="@+id/done"
+              android:layout_width="wrap_content"
+              android:layout_height="wrap_content"
+              android:text="@string/done"
+             android:layout_weight="1"
+             />
+    </LinearLayout>
+
+    <ListView android:id="@+id/frequencies"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+       android:fadeScrollbars="false"
+       android:scrollbars="vertical"
+       android:choiceMode="singleChoice"
+       />
+
+    
+</LinearLayout>
index 73ba2ad..630378a 100644 (file)
           android:layout_height="wrap_content"
          android:text="@string/preload_maps"
          />
+  <Button android:id="@+id/manage_frequencies"
+          android:layout_width="match_parent"
+          android:layout_height="wrap_content"
+         android:text="@string/manage_frequencies"
+         />
   <Button android:id="@+id/done"
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
index 7538f7b..58057ca 100644 (file)
        <string name="map_type">Map Type</string>
        <string name="map_source">Map Source</string>
        <string name="preload_maps">Preload Maps</string>
-       <string name="done">Done</string>
+       <string name="manage_frequencies">Manage Frequencies</string>
+       <string name="done">OK</string>
        
+       <!-- manage frequencies -->
+       <string name="set">Set</string>
+       <string name="mhz">MHz</string>
+       <string name="remove">Remove</string>
+       <string name="done">OK</string>
+       <string name="frequency">Frequency</string>
+       <string name="description">Description</string>
 </resources>
index ea3bbae..026e836 100644 (file)
@@ -109,9 +109,6 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,
        // field to display the version at the bottom of the screen
        private TextView mVersion;
 
-       private double frequency;
-       private int telemetry_rate;
-
        private boolean idle_mode = false;
 
        public Location location = null;
@@ -884,11 +881,8 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,
                }
        }
 
-       void setFrequency(String freq) {
-               try {
-                       setFrequency (AltosParse.parse_double_net(freq.substring(11, 17)));
-               } catch (ParseException e) {
-               }
+       void setFrequency(AltosFrequency frequency) {
+               setFrequency (frequency.frequency);
        }
 
        void setBaud(int baud) {
@@ -998,22 +992,14 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,
                case R.id.select_freq:
                        // Set the TBT radio frequency
 
-                       final String[] frequencies = {
-                               "Channel 0 (434.550MHz)",
-                               "Channel 1 (434.650MHz)",
-                               "Channel 2 (434.750MHz)",
-                               "Channel 3 (434.850MHz)",
-                               "Channel 4 (434.950MHz)",
-                               "Channel 5 (435.050MHz)",
-                               "Channel 6 (435.150MHz)",
-                               "Channel 7 (435.250MHz)",
-                               "Channel 8 (435.350MHz)",
-                               "Channel 9 (435.450MHz)"
-                       };
+                       final AltosFrequency[] frequencies = AltosPreferences.common_frequencies();
+                       String[] frequency_strings = new String[frequencies.length];
+                       for (int i = 0; i < frequencies.length; i++)
+                               frequency_strings[i] = frequencies[i].toString();
 
                        AlertDialog.Builder builder_freq = new AlertDialog.Builder(this);
                        builder_freq.setTitle("Pick a frequency");
-                       builder_freq.setItems(frequencies,
+                       builder_freq.setItems(frequency_strings,
                                         new DialogInterface.OnClickListener() {
                                                 public void onClick(DialogInterface dialog, int item) {
                                                         setFrequency(frequencies[item]);
index fac523d..c2db377 100644 (file)
@@ -53,6 +53,8 @@ public class AltosDroidPreferencesBackend implements AltosPreferencesBackend {
        }
 
        public AltosPreferencesBackend node(String key) {
+               if (!nodeExists(key))
+                       putBoolean(key, true);
                return new AltosDroidPreferencesBackend(context, key);
        }
 
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/ManageFrequenciesActivity.java b/altosdroid/src/org/altusmetrum/AltosDroid/ManageFrequenciesActivity.java
new file mode 100644 (file)
index 0000000..172c44f
--- /dev/null
@@ -0,0 +1,280 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import java.lang.ref.WeakReference;
+import java.util.*;
+import java.text.*;
+import org.altusmetrum.AltosDroid.R;
+
+import android.app.Activity;
+import android.content.*;
+import android.graphics.*;
+import android.os.*;
+import android.view.*;
+import android.view.View.*;
+import android.widget.*;
+import android.widget.AdapterView.*;
+
+import org.altusmetrum.altoslib_10.*;
+
+class FrequencyItem {
+       public AltosFrequency frequency;
+       public LinearLayout frequency_view = null;
+       public TextView pretty_view = null;
+
+       private void update() {
+               if (pretty_view != null && frequency != null)
+                       pretty_view.setText(frequency.toString());
+       }
+
+       public void realize(LinearLayout frequency_view,
+                           TextView pretty_view) {
+               if (frequency_view != this.frequency_view ||
+                   pretty_view != this.pretty_view)
+               {
+                       this.frequency_view = frequency_view;
+                       this.pretty_view = pretty_view;
+                       update();
+               }
+       }
+
+       public void set_frequency(AltosFrequency frequency) {
+               this.frequency = frequency;
+               update();
+       }
+
+       public FrequencyItem(AltosFrequency frequency) {
+               this.frequency = frequency;
+       }
+}
+
+class FrequencyAdapter extends ArrayAdapter<FrequencyItem> {
+       int resource;
+       int selected_item = -1;
+
+       public FrequencyAdapter(Context context, int in_resource) {
+               super(context, in_resource);
+               resource = in_resource;
+       }
+
+       public int count() {
+               int     count;
+
+               for (count = 0;; count++) {
+                       try {
+                               getItem(count);
+                       } catch (IndexOutOfBoundsException ie) {
+                               return count;
+                       }
+               }
+       }
+
+       @Override
+       public View getView(int position, View convertView, ViewGroup parent) {
+               FrequencyItem item = getItem(position);
+               if (item.frequency_view == null) {
+                       LinearLayout frequency_view = new LinearLayout(getContext());
+                       String inflater = Context.LAYOUT_INFLATER_SERVICE;
+                       LayoutInflater li = (LayoutInflater) getContext().getSystemService(inflater);
+                       li.inflate(resource, frequency_view, true);
+
+                       item.realize(frequency_view,
+                                    (TextView) frequency_view.findViewById(R.id.frequency));
+               }
+               if (position == selected_item)
+                       item.frequency_view.setBackgroundColor(Color.RED);
+               else
+                       item.frequency_view.setBackgroundColor(Color.BLACK);
+               return item.frequency_view;
+       }
+}
+
+public class ManageFrequenciesActivity extends Activity {
+       private ListView frequencies_view;
+
+       private Button set;
+       private Button remove;
+       private Button done;
+
+       private EditText set_frequency;
+       private EditText set_description;
+
+       private HashMap<String,FrequencyItem> frequencies = new HashMap<String,FrequencyItem>();;
+
+       private FrequencyAdapter frequencies_adapter;
+
+       private boolean is_bound;
+       private boolean changed = false;
+
+       private void done() {
+
+               if (changed) {
+                       AltosFrequency[] frequencies = new AltosFrequency[frequencies_adapter.count()];
+                       for (int i = 0; i < frequencies.length; i++)
+                               frequencies[i] = frequencies_adapter.getItem(i).frequency;
+                       AltosPreferences.set_common_frequencies(frequencies);
+               }
+
+               Intent intent = new Intent();
+               setResult(Activity.RESULT_OK, intent);
+               finish();
+       }
+
+       private void load_item() {
+               if (frequencies_adapter.selected_item >= 0) {
+                       FrequencyItem item = frequencies_adapter.getItem(frequencies_adapter.selected_item);
+
+                       set_frequency.setText(item.frequency.frequency_string());
+                       set_description.setText(item.frequency.description);
+               } else {
+                       set_frequency.setText("");
+                       set_description.setText("");
+               }
+       }
+
+       private void select_item(int position) {
+               if (position != frequencies_adapter.selected_item) {
+                       if (frequencies_adapter.selected_item >= 0)
+                               frequencies_view.setItemChecked(frequencies_adapter.selected_item, false);
+                       if (position >= 0)
+                               frequencies_view.setItemChecked(position, true);
+                       frequencies_adapter.selected_item = position;
+               } else {
+                       if (frequencies_adapter.selected_item >= 0)
+                               frequencies_view.setItemChecked(frequencies_adapter.selected_item, false);
+                       frequencies_adapter.selected_item = -1;
+               }
+               load_item();
+       }
+
+       private int insert_item(AltosFrequency frequency) {
+               FrequencyItem new_item = new FrequencyItem(frequency);
+               int     pos;
+               for (pos = 0; pos < frequencies_adapter.getCount(); pos++) {
+                       FrequencyItem   item = frequencies_adapter.getItem(pos);
+                       if (item.frequency.frequency == new_item.frequency.frequency) {
+                               item.set_frequency(frequency);
+                               return pos;
+                       }
+                       if (item.frequency.frequency > new_item.frequency.frequency)
+                               break;
+               }
+               frequencies_adapter.insert(new_item, pos);
+               return pos;
+       }
+
+       private class FrequencyItemClickListener implements ListView.OnItemClickListener {
+               @Override
+               public void onItemClick(AdapterView<?> av, View v, int position, long id) {
+                       select_item(position);
+               }
+       }
+
+       private void set() {
+               String  frequency_text = set_frequency.getEditableText().toString();
+               String  description_text = set_description.getEditableText().toString();
+
+               try {
+                       double  f = AltosParse.parse_double_locale(frequency_text);
+
+                       int pos = insert_item(new AltosFrequency(f, description_text));
+                       frequencies_adapter.selected_item = -1;
+                       select_item(pos);
+                       changed = true;
+               } catch (ParseException pe) {
+               }
+       }
+
+       private void remove() {
+               if (frequencies_adapter.selected_item >= 0) {
+                       frequencies_adapter.remove(frequencies_adapter.getItem(frequencies_adapter.selected_item));
+                       select_item(-1);
+                       frequencies_view.setAdapter(frequencies_adapter);
+                       changed = true;
+               }
+       }
+
+       @Override
+       protected void onCreate(Bundle savedInstanceState) {
+               super.onCreate(savedInstanceState);
+
+               // Setup the window
+               requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
+               setContentView(R.layout.manage_frequencies);
+
+               frequencies_view = (ListView) findViewById(R.id.frequencies);
+               frequencies_view.setClickable(true);
+
+               frequencies_adapter = new FrequencyAdapter(this, R.layout.frequency);
+
+               frequencies_view.setAdapter(frequencies_adapter);
+               frequencies_view.setOnItemClickListener(new FrequencyItemClickListener());
+
+               AltosFrequency[] frequencies = AltosPreferences.common_frequencies();
+               for (AltosFrequency frequency : frequencies)
+                       insert_item(frequency);
+
+               set_frequency = (EditText) findViewById(R.id.set_frequency);
+               set_description = (EditText) findViewById(R.id.set_description);
+
+               set = (Button) findViewById(R.id.set);
+               set.setOnClickListener(new OnClickListener() {
+                               public void onClick(View v) {
+                                       set();
+                               }
+                       });
+
+               remove = (Button) findViewById(R.id.remove);
+               remove.setOnClickListener(new OnClickListener() {
+                               public void onClick(View v) {
+                                       remove();
+                               }
+                       });
+
+               done = (Button) findViewById(R.id.done);
+               done.setOnClickListener(new OnClickListener() {
+                               public void onClick(View v) {
+                                       done();
+                               }
+                       });
+
+               // Set result CANCELED incase the user backs out
+               setResult(Activity.RESULT_CANCELED);
+       }
+
+       @Override
+       protected void onStart() {
+               super.onStart();
+       }
+
+       @Override
+       protected void onResume() {
+               super.onResume();
+       }
+
+       @Override
+       protected void onPause() {
+               super.onPause();
+       }
+
+       @Override
+       protected void onStop() {
+               super.onStop();
+       }
+}
index ef802f0..fdffc2b 100644 (file)
@@ -37,6 +37,7 @@ public class SetupActivity extends Activity {
        private Spinner set_units;
        private Spinner map_type;
        private Spinner map_source;
+       private Button manage_frequencies;
        private Button preload_maps;
        private Button done;
 
@@ -240,6 +241,11 @@ public class SetupActivity extends Activity {
                add_change(AltosDroid.SETUP_MAP_SOURCE);
        }
 
+       private void manage_frequencies(){
+               Intent intent = new Intent(this, ManageFrequenciesActivity.class);
+               startActivity(intent);
+       }
+
        private void preload_maps(){
                Intent intent = new Intent(this, PreloadMapActivity.class);
                startActivity(intent);
@@ -294,6 +300,13 @@ public class SetupActivity extends Activity {
                        });
 
 
+               manage_frequencies = (Button) findViewById(R.id.manage_frequencies);
+               manage_frequencies.setOnClickListener(new OnClickListener() {
+                               public void onClick(View v) {
+                                       manage_frequencies();
+                               }
+                       });
+
                preload_maps = (Button) findViewById(R.id.preload_maps);
                preload_maps.setOnClickListener(new OnClickListener() {
                                public void onClick(View v) {
index 183d455..80e0d72 100644 (file)
@@ -44,6 +44,10 @@ public class AltosFrequency {
                                     frequency, description);
        }
 
+       public String frequency_string() {
+               return String.format("%7.3f", frequency);
+       }
+
        public boolean close(double f) {
                double  diff = Math.abs(frequency - f);