/******************************************************************************* * Gaggle is Copyright 2010 by Geeksville Industries LLC, a California limited liability corporation. * * Gaggle is distributed under a dual license. We've chosen this approach because within Gaggle we've used a number * of components that Geeksville Industries LLC might reuse for commercial products. Gaggle can be distributed under * either of the two licenses listed below. * * 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. * * Commercial Distribution License * If you would like to distribute Gaggle (or portions thereof) under a license other than * the "GNU General Public License, version 2", contact Geeksville Industries. Geeksville Industries reserves * the right to release Gaggle source code under a commercial license of its choice. * * GNU Public License, version 2 * All other distribution of Gaggle must conform to the terms of the GNU Public License, version 2. The full * text of this license is included in the Gaggle source, see assets/manual/gpl-2.0.txt. ******************************************************************************/ package com.geeksville.gaggle; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.SharedPreferences; import android.preference.PreferenceManager; import android.text.InputFilter; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.EditText; import android.widget.Spinner; import android.widget.TextView; import com.geeksville.info.Units; import com.geeksville.info.Units.CoordinateSet; import com.geeksville.location.LocationUtils; import com.geeksville.location.Waypoint; import com.geeksville.view.EnhancedSpinner; import com.geeksville.view.NumberEdit; /** * FIXME - add support for showing fractional minutes instead of DMS * * @author kevinh * */ public class WaypointDialog implements DialogInterface.OnClickListener { private Waypoint waypoint; private View layout; private EditText name; private EditText description; private AlertDialog alertDialog; private NumberEdit altitudeView; private Runnable onOkay, onGoto; private EnhancedSpinner typeSpinner; public WaypointDialog(Context c, Waypoint w, final Runnable onOkay, Runnable onGoto) { waypoint = w; this.onOkay = onOkay; this.onGoto = onGoto; LayoutInflater inflater = (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE); layout = inflater.inflate(R.layout.waypoint_edit, null); name = (EditText) layout.findViewById(R.id.name); description = (EditText) layout.findViewById(R.id.description); typeSpinner = (EnhancedSpinner) layout.findViewById(R.id.type); typeSpinner.setSelection(w.type.ordinal()); name.setText(w.name); description.setText(w.description); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(c); CoordinateSet coordinatesset = CoordinateSet.valueOf(prefs.getString("coordinateset_pref", "DMS")); fillPosition(R.id.latitude, w.latitude, true, coordinatesset); fillPosition(R.id.longitude, w.longitude, false, coordinatesset); altitudeView = ((NumberEdit) layout.findViewById(R.id.altitude)); altitudeView.setText(Units.instance.metersToAltitude(w.altitude)); altitudeView.setIntOnly(true); TextView altUnits = (TextView) layout.findViewById(R.id.altitude_units); altUnits.setText(Units.instance.getAltitudeUnits()); AlertDialog.Builder builder = new AlertDialog.Builder(c); builder.setTitle(R.string.edit_waypoint); builder.setView(layout); builder.setCancelable(true); builder.setPositiveButton(R.string.okay, this); builder.setNeutralButton(R.string.go_to, this); builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }); alertDialog = builder.create(); } public void show() { alertDialog.show(); } /** * Read text fields to generate a latitude * * @param groupId * @param isLatitude * @return */ private double readPosition(int groupId, boolean isLatitude) throws NumberFormatException { ViewGroup group = (ViewGroup) layout.findViewById(groupId); // FIXME, also validate ranges on params double degs = ((NumberEdit) group.findViewById(R.id.degree)).getDouble(); double mins = ((NumberEdit) group.findViewById(R.id.minute)).getDouble(); double secs = ((NumberEdit) group.findViewById(R.id.second)).getDouble(); boolean isPositive = "NE".contains(((Spinner) group.findViewById(R.id.hemisphere)).getSelectedItem().toString()); return LocationUtils.DMSToDegrees(degs, mins, secs, isPositive); } /** * Fill a lat or long group text fields with a given position * * @param groupId * @param degIn * @param isLatitude */ private void fillPosition(int groupId, double degIn, boolean isLatitude, CoordinateSet coordinateset) { ViewGroup group = (ViewGroup) layout.findViewById(groupId); String[] dms = null; NumberEdit vd = ((NumberEdit) group.findViewById(R.id.degree)); NumberEdit vm = ((NumberEdit) group.findViewById(R.id.minute)); NumberEdit vs = ((NumberEdit) group.findViewById(R.id.second)); ViewGroup.LayoutParams params; dms = (coordinateset == CoordinateSet.DMS) ? LocationUtils.degreesToDMS(degIn, isLatitude) : (coordinateset == CoordinateSet.DM) ? LocationUtils.degreesToDM(degIn, isLatitude) : LocationUtils.degreesToD(degIn, isLatitude); switch(coordinateset){ case DMS: vs.setIntOnly(false); break; case DM: vm.setIntOnly(false); vm.setFilters(new InputFilter[]{new InputFilter.LengthFilter(8)}); params = vm.getLayoutParams(); params.width = 120; vm.setLayoutParams(params); vm.setIntOnly(false); vs.setVisibility(View.GONE); group.findViewById(R.id.symbol_second).setVisibility(View.GONE); break; case D: vd.setIntOnly(false); vd.setFilters(new InputFilter[]{new InputFilter.LengthFilter(9)}); params = vd.getLayoutParams(); params.width = 160; vd.setLayoutParams(params); vs.setVisibility(View.GONE); vm.setVisibility(View.GONE); group.findViewById(R.id.symbol_second).setVisibility(View.GONE); group.findViewById(R.id.symbol_minute).setVisibility(View.GONE); break; } vd.setMinMax(0, isLatitude ? 90 : 180); vd.setText(dms[0]); vm.setMinMax(0,60); vm.setText(dms[1]); vs.setMinMax(0,60); vs.setText(dms[2]); Spinner NSEW = (Spinner) group.findViewById(R.id.hemisphere); if ("NE".contains(dms[3])) NSEW.setSelection(0); else NSEW.setSelection(1); } /** * Handle the okay or goto buttons */ @Override public void onClick(DialogInterface dialog, int which) { double latitude = readPosition(R.id.latitude, true); double longitude = readPosition(R.id.longitude, false); int alt = (int) altitudeView.getDouble(); // FIXME, validate names for uniqueness waypoint.name = name.getText().toString().trim(); waypoint.description = description.getText().toString().trim(); waypoint.altitude = (int) Units.instance.altitudeToMeters(alt); waypoint.latitude = latitude; waypoint.longitude = longitude; waypoint.type = Waypoint.Type.values()[typeSpinner.getSelectedItemPosition()]; // Write our state back to the DB if (which == AlertDialog.BUTTON_POSITIVE) onOkay.run(); else if (which == AlertDialog.BUTTON_NEUTRAL) onGoto.run(); } }