diff options
Diffstat (limited to 'main/src/cgeo/geocaching/NavigateAnyPointActivity.java')
| -rw-r--r-- | main/src/cgeo/geocaching/NavigateAnyPointActivity.java | 565 |
1 files changed, 565 insertions, 0 deletions
diff --git a/main/src/cgeo/geocaching/NavigateAnyPointActivity.java b/main/src/cgeo/geocaching/NavigateAnyPointActivity.java new file mode 100644 index 0000000..74f656b --- /dev/null +++ b/main/src/cgeo/geocaching/NavigateAnyPointActivity.java @@ -0,0 +1,565 @@ +package cgeo.geocaching; + +import cgeo.geocaching.activity.AbstractActivity; +import cgeo.geocaching.apps.cache.navi.NavigationAppFactory; +import cgeo.geocaching.geopoint.DistanceParser; +import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.geopoint.GeopointFormatter; +import cgeo.geocaching.ui.Formatter; +import cgeo.geocaching.ui.dialog.CoordinatesInputDialog; +import cgeo.geocaching.utils.GeoDirHandler; +import cgeo.geocaching.utils.Log; + +import org.apache.commons.lang3.StringUtils; + +import android.app.Activity; +import android.content.Context; +import android.content.res.Configuration; +import android.os.Bundle; +import android.view.ContextMenu; +import android.view.ContextMenu.ContextMenuInfo; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnCreateContextMenuListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.AdapterView.OnItemSelectedListener; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ListView; +import android.widget.Spinner; +import android.widget.TextView; + +import java.util.List; + +public class NavigateAnyPointActivity extends AbstractActivity { + private static final int MENU_DEFAULT_NAVIGATION = 2; + private static final int MENU_NAVIGATE = 0; + private static final int MENU_CACHES_AROUND = 5; + private static final int MENU_CLEAR_HISTORY = 6; + + private static class DestinationHistoryAdapter extends ArrayAdapter<Destination> { + private LayoutInflater inflater = null; + + public DestinationHistoryAdapter(Context context, + List<Destination> objects) { + super(context, 0, objects); + } + + @Override + public View getView(final int position, final View convertView, final ViewGroup parent) { + + Destination loc = getItem(position); + + View v = convertView; + + if (v == null) { + v = getInflater().inflate(R.layout.simple_way_point, + null); + } + TextView longitude = (TextView) v + .findViewById(R.id.simple_way_point_longitude); + TextView latitude = (TextView) v + .findViewById(R.id.simple_way_point_latitude); + TextView date = (TextView) v.findViewById(R.id.date); + + String lonString = loc.getCoords().format(GeopointFormatter.Format.LON_DECMINUTE); + String latString = loc.getCoords().format(GeopointFormatter.Format.LAT_DECMINUTE); + + longitude.setText(lonString); + latitude.setText(latString); + date.setText(Formatter.formatShortDateTime(getContext(), loc.getDate())); + + return v; + } + + private LayoutInflater getInflater() { + if (inflater == null) { + inflater = ((Activity) getContext()).getLayoutInflater(); + } + + return inflater; + } + } + + private Button latButton = null; + private Button lonButton = null; + private boolean changed = false; + private List<Destination> historyOfSearchedLocations; + private DestinationHistoryAdapter destionationHistoryAdapter; + private ListView historyListView; + private TextView historyFooter; + + private static final int CONTEXT_MENU_NAVIGATE = 1; + private static final int CONTEXT_MENU_DELETE_WAYPOINT = 2; + private static final int CONTEXT_MENU_EDIT_WAYPOINT = 3; + + private int contextMenuItemPosition; + + String distanceUnit = ""; + + public NavigateAnyPointActivity() { + super("c:geo-navigate-any"); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setTheme(); + setContentView(R.layout.point); + setTitle(res.getString(R.string.search_destination)); + + createHistoryView(); + + init(); + } + + private void createHistoryView() { + historyListView = (ListView) findViewById(R.id.historyList); + + final View pointControls = getLayoutInflater().inflate( + R.layout.point_controls, null); + historyListView.addHeaderView(pointControls, null, false); + + if (getHistoryOfSearchedLocations().isEmpty()) { + historyListView.addFooterView(getEmptyHistoryFooter(), null, false); + } + + historyListView.setAdapter(getDestionationHistoryAdapter()); + historyListView.setOnItemClickListener(new OnItemClickListener() { + + @Override + public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, + long arg3) { + final Object selection = arg0.getItemAtPosition(arg2); + if (selection instanceof Destination) { + navigateTo(((Destination) selection).getCoords()); + } + } + }); + + historyListView.setOnCreateContextMenuListener(new OnCreateContextMenuListener() { + @Override + public void onCreateContextMenu(ContextMenu menu, View v, + ContextMenuInfo menuInfo) { + menu.add(Menu.NONE, CONTEXT_MENU_NAVIGATE, Menu.NONE, res.getString(R.string.cache_menu_navigate)); + menu.add(Menu.NONE, CONTEXT_MENU_EDIT_WAYPOINT, Menu.NONE, R.string.waypoint_edit); + menu.add(Menu.NONE, CONTEXT_MENU_DELETE_WAYPOINT, Menu.NONE, R.string.waypoint_delete); + } + }); + } + + @Override + public boolean onContextItemSelected(MenuItem item) { + AdapterView.AdapterContextMenuInfo menuInfo = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo(); + final int position = (null != menuInfo) ? menuInfo.position : contextMenuItemPosition; + Object destination = historyListView.getItemAtPosition(position); + + switch (item.getItemId()) { + case CONTEXT_MENU_NAVIGATE: + contextMenuItemPosition = position; + if (destination instanceof Destination) { + NavigationAppFactory.showNavigationMenu(this, null, null, ((Destination) destination).getCoords()); + return true; + } + break; + + case CONTEXT_MENU_DELETE_WAYPOINT: + if (destination instanceof Destination) { + removeFromHistory((Destination) destination); + } + return true; + + case CONTEXT_MENU_EDIT_WAYPOINT: + if (destination instanceof Destination) { + final Geopoint gp = ((Destination) destination).getCoords(); + latButton.setText(gp.format(GeopointFormatter.Format.LAT_DECMINUTE)); + lonButton.setText(gp.format(GeopointFormatter.Format.LON_DECMINUTE)); + } + return true; + default: + } + + return super.onContextItemSelected(item); + } + + private TextView getEmptyHistoryFooter() { + if (historyFooter == null) { + historyFooter = (TextView) getLayoutInflater().inflate( + R.layout.caches_footer, null); + historyFooter.setText(R.string.search_history_empty); + } + return historyFooter; + } + + private DestinationHistoryAdapter getDestionationHistoryAdapter() { + if (destionationHistoryAdapter == null) { + destionationHistoryAdapter = new DestinationHistoryAdapter(this, + getHistoryOfSearchedLocations()); + } + return destionationHistoryAdapter; + } + + private List<Destination> getHistoryOfSearchedLocations() { + if (historyOfSearchedLocations == null) { + // Load from database + historyOfSearchedLocations = cgData.loadHistoryOfSearchedLocations(); + } + + return historyOfSearchedLocations; + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + + init(); + } + + @Override + public void onResume() { + super.onResume(); + geoDirHandler.startGeo(); + init(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + } + + @Override + public void onStop() { + super.onStop(); + } + + @Override + public void onPause() { + geoDirHandler.stopGeo(); + super.onPause(); + } + + private void init() { + latButton = (Button) findViewById(R.id.buttonLatitude); + lonButton = (Button) findViewById(R.id.buttonLongitude); + + latButton.setOnClickListener(new CoordDialogListener()); + lonButton.setOnClickListener(new CoordDialogListener()); + + final Geopoint coords = Settings.getAnyCoordinates(); + if (coords != null) { + latButton.setText(coords.format(GeopointFormatter.Format.LAT_DECMINUTE)); + lonButton.setText(coords.format(GeopointFormatter.Format.LON_DECMINUTE)); + } + + Button buttonCurrent = (Button) findViewById(R.id.current); + buttonCurrent.setOnClickListener(new CurrentListener()); + + getDestionationHistoryAdapter().notifyDataSetChanged(); + disableSuggestions((EditText) findViewById(R.id.distance)); + + initializeDistanceUnitSelector(); + } + + private void initializeDistanceUnitSelector() { + + Spinner distanceUnitSelector = (Spinner) findViewById(R.id.distanceUnit); + + if (StringUtils.isBlank(distanceUnit)) { + if (Settings.isUseMetricUnits()) { + distanceUnitSelector.setSelection(0); // m + distanceUnit = res.getStringArray(R.array.distance_units)[0]; + } else { + distanceUnitSelector.setSelection(2); // ft + distanceUnit = res.getStringArray(R.array.distance_units)[2]; + } + } + + distanceUnitSelector.setOnItemSelectedListener(new ChangeDistanceUnit(this)); + } + + private class CoordDialogListener implements View.OnClickListener { + + @Override + public void onClick(View arg0) { + Geopoint gp = null; + if (latButton.getText().length() > 0 && lonButton.getText().length() > 0) { + gp = new Geopoint(latButton.getText().toString() + " " + lonButton.getText().toString()); + } + CoordinatesInputDialog coordsDialog = new CoordinatesInputDialog(NavigateAnyPointActivity.this, null, gp, app.currentGeo()); + coordsDialog.setCancelable(true); + coordsDialog.setOnCoordinateUpdate(new CoordinatesInputDialog.CoordinateUpdate() { + @Override + public void update(Geopoint gp) { + latButton.setText(gp.format(GeopointFormatter.Format.LAT_DECMINUTE)); + lonButton.setText(gp.format(GeopointFormatter.Format.LON_DECMINUTE)); + changed = true; + } + }); + coordsDialog.show(); + } + } + + private static class ChangeDistanceUnit implements OnItemSelectedListener { + + private ChangeDistanceUnit(NavigateAnyPointActivity unitView) { + this.unitView = unitView; + } + + private NavigateAnyPointActivity unitView; + + @Override + public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, + long arg3) { + unitView.distanceUnit = (String) arg0.getItemAtPosition(arg2); + } + + @Override + public void onNothingSelected(AdapterView<?> arg0) { + } + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + menu.add(0, MENU_DEFAULT_NAVIGATION, 0, NavigationAppFactory.getDefaultNavigationApplication().getName()).setIcon(R.drawable.ic_menu_compass); // default navigation tool + + menu.add(0, MENU_NAVIGATE, 0, res.getString(R.string.cache_menu_navigate)).setIcon(R.drawable.ic_menu_mapmode); + + menu.add(0, MENU_CACHES_AROUND, 0, res.getString(R.string.cache_menu_around)).setIcon(R.drawable.ic_menu_rotate); // caches around + + menu.add(0, MENU_CLEAR_HISTORY, 0, res.getString(R.string.search_clear_history)).setIcon(R.drawable.ic_menu_delete); // clear history + + return true; + } + + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + super.onPrepareOptionsMenu(menu); + + try { + boolean visible = getDestination() != null; + menu.findItem(MENU_NAVIGATE).setVisible(visible); + menu.findItem(MENU_DEFAULT_NAVIGATION).setVisible(visible); + menu.findItem(MENU_CACHES_AROUND).setVisible(visible); + + menu.findItem(MENU_CLEAR_HISTORY).setEnabled(!getHistoryOfSearchedLocations().isEmpty()); + } catch (Exception e) { + // nothing + } + + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + final int menuItem = item.getItemId(); + + final Geopoint coords = getDestination(); + + if (coords != null) { + addToHistory(coords); + } + + switch (menuItem) { + case MENU_DEFAULT_NAVIGATION: + navigateTo(); + return true; + + case MENU_CACHES_AROUND: + cachesAround(); + return true; + + case MENU_CLEAR_HISTORY: + clearHistory(); + return true; + + case MENU_NAVIGATE: + NavigationAppFactory.showNavigationMenu(this, null, null, coords); + return true; + default: + return false; + } + } + + private void addToHistory(final Geopoint coords) { + // Add locations to history + final Destination loc = new Destination(coords); + + if (!getHistoryOfSearchedLocations().contains(loc)) { + getHistoryOfSearchedLocations().add(0, loc); + + // Save location + cgData.saveSearchedDestination(loc); + + // Ensure to remove the footer + historyListView.removeFooterView(getEmptyHistoryFooter()); + } + } + + private void removeFromHistory(Destination destination) { + if (getHistoryOfSearchedLocations().contains(destination)) { + getHistoryOfSearchedLocations().remove(destination); + + // Save + cgData.removeSearchedDestination(destination); + + if (getHistoryOfSearchedLocations().isEmpty()) { + if (historyListView.getFooterViewsCount() == 0) { + historyListView.addFooterView(getEmptyHistoryFooter()); + } + } + + getDestionationHistoryAdapter().notifyDataSetChanged(); + + showToast(res.getString(R.string.search_remove_destination)); + } + } + + private void clearHistory() { + if (!getHistoryOfSearchedLocations().isEmpty()) { + getHistoryOfSearchedLocations().clear(); + + // Save + cgData.clearSearchedDestinations(); + + if (historyListView.getFooterViewsCount() == 0) { + historyListView.addFooterView(getEmptyHistoryFooter()); + } + + getDestionationHistoryAdapter().notifyDataSetChanged(); + + showToast(res.getString(R.string.search_history_cleared)); + } + } + + private void navigateTo() { + navigateTo(getDestination()); + } + + private void navigateTo(Geopoint geopoint) { + NavigationAppFactory.startDefaultNavigationApplication(1, this, geopoint); + } + + private void cachesAround() { + final Geopoint coords = getDestination(); + + if (coords == null) { + showToast(res.getString(R.string.err_location_unknown)); + return; + } + + cgeocaches.startActivityCoordinates(this, coords); + + finish(); + } + + private final GeoDirHandler geoDirHandler = new GeoDirHandler() { + @Override + public void updateGeoData(final IGeoData geo) { + try { + latButton.setHint(geo.getCoords().format(GeopointFormatter.Format.LAT_DECMINUTE_RAW)); + lonButton.setHint(geo.getCoords().format(GeopointFormatter.Format.LON_DECMINUTE_RAW)); + } catch (final Exception e) { + Log.w("Failed to update location."); + } + } + }; + + private class CurrentListener implements View.OnClickListener { + + @Override + public void onClick(View arg0) { + final Geopoint coords = app.currentGeo().getCoords(); + if (coords == null) { + showToast(res.getString(R.string.err_point_unknown_position)); + return; + } + + latButton.setText(coords.format(GeopointFormatter.Format.LAT_DECMINUTE)); + lonButton.setText(coords.format(GeopointFormatter.Format.LON_DECMINUTE)); + + changed = false; + } + } + + private Geopoint getDestination() { + + String bearingText = ((EditText) findViewById(R.id.bearing)).getText().toString(); + // combine distance from EditText and distanceUnit saved from Spinner + String distanceText = ((EditText) findViewById(R.id.distance)).getText().toString() + distanceUnit; + String latText = latButton.getText().toString(); + String lonText = lonButton.getText().toString(); + + if (StringUtils.isBlank(bearingText) && StringUtils.isBlank(distanceText) + && StringUtils.isBlank(latText) && StringUtils.isBlank(lonText)) { + showToast(res.getString(R.string.err_point_no_position_given)); + return null; + } + + Geopoint coords; + if (StringUtils.isNotBlank(latText) && StringUtils.isNotBlank(lonText)) { + try { + coords = new Geopoint(latText, lonText); + } catch (Geopoint.ParseException e) { + showToast(res.getString(e.resource)); + return null; + } + } else { + if (app.currentGeo().getCoords() == null) { + showToast(res.getString(R.string.err_point_curr_position_unavailable)); + return null; + } + + coords = app.currentGeo().getCoords(); + } + + Geopoint result; + if (StringUtils.isNotBlank(bearingText) && StringUtils.isNotBlank(distanceText)) { + // bearing & distance + double bearing; + try { + bearing = Double.parseDouble(bearingText); + } catch (NumberFormatException e) { + helpDialog(res.getString(R.string.err_point_bear_and_dist_title), res.getString(R.string.err_point_bear_and_dist)); + return null; + } + + double distance; + try { + distance = DistanceParser.parseDistance(distanceText, Settings.isUseMetricUnits()); + } catch (NumberFormatException e) { + showToast(res.getString(R.string.err_parse_dist)); + return null; + } + + final Geopoint coordsDst = coords.project(bearing, distance); + + if (coordsDst == null) { + showToast(res.getString(R.string.err_point_location_error)); + return null; + } + + result = coordsDst; + } else if (coords != null) { + result = coords; + } else { + return null; + } + + saveCoords(result); + + return result; + } + + private void saveCoords(final Geopoint coords) { + if (!changed) { + return; + } + Settings.setAnyCoordinates(coords); + } +} |
