package net.osmand.plus.activities.search; import android.app.Activity; import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; import android.support.v4.app.FragmentActivity; import android.support.v4.view.ViewCompat; import android.support.v7.app.AlertDialog; import android.support.v7.widget.PopupMenu; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; import android.widget.TextView.BufferType; import net.osmand.data.LatLon; import net.osmand.data.PointDescription; import net.osmand.plus.IconsCache; import net.osmand.plus.OsmAndFormatter; import net.osmand.plus.OsmAndLocationProvider.OsmAndCompassListener; import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandSettings; import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.activities.search.SearchActivity.SearchActivityChild; import net.osmand.plus.base.OsmAndListFragment; import net.osmand.plus.dashboard.DashLocationFragment; import net.osmand.plus.helpers.SearchHistoryHelper; import net.osmand.plus.helpers.SearchHistoryHelper.HistoryEntry; import net.osmand.util.MapUtils; import java.util.List; public class SearchHistoryFragment extends OsmAndListFragment implements SearchActivityChild, OsmAndCompassListener { private LatLon location; private SearchHistoryHelper helper; private Button clearButton; public static final String SEARCH_LAT = SearchActivity.SEARCH_LAT; public static final String SEARCH_LON = SearchActivity.SEARCH_LON; private HistoryAdapter historyAdapter; private Float heading; private boolean searchAroundLocation; private boolean compassRegistered; private int screenOrientation; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); View view = inflater.inflate(R.layout.search_history, container, false); clearButton = (Button) view.findViewById(R.id.clearAll); clearButton.setText(R.string.shared_string_clear_all); clearButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { clearWithConfirmation(); } }); ((ListView)view.findViewById(android.R.id.list)).setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { onListItemClick((ListView) parent, view, position, id); } }); return view; } private void clearWithConfirmation() { AlertDialog.Builder bld = new AlertDialog.Builder(getActivity()); bld.setMessage(R.string.confirmation_to_clear_history); bld.setPositiveButton(R.string.shared_string_yes, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { clearWithoutConfirmation(); } }); bld.setNegativeButton(R.string.shared_string_no, null); bld.show(); } @Override public ArrayAdapter<?> getAdapter() { return historyAdapter; } private void clearWithoutConfirmation() { helper.removeAll(); historyAdapter.clear(); clearButton.setVisibility(View.GONE); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); helper = SearchHistoryHelper.getInstance((OsmandApplication) getActivity().getApplicationContext()); } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); historyAdapter = new HistoryAdapter(helper.getHistoryEntries()); setListAdapter(historyAdapter); setHasOptionsMenu(true); } @Override public void onResume() { super.onResume(); //Hardy: onResume() code is needed so that search origin is properly reflected in tab contents when origin has been changed on one tab, then tab is changed to another one. location = null; FragmentActivity activity = getActivity(); Intent intent = activity.getIntent(); if (intent != null) { double lat = intent.getDoubleExtra(SEARCH_LAT, 0); double lon = intent.getDoubleExtra(SEARCH_LON, 0); if (lat != 0 || lon != 0) { historyAdapter.location = new LatLon(lat, lon); } } if (location == null && activity instanceof SearchActivity) { location = ((SearchActivity) activity).getSearchPoint(); } if (location == null) { location = ((OsmandApplication) activity.getApplication()).getSettings().getLastKnownMapLocation(); } historyAdapter.clear(); for (HistoryEntry entry : helper.getHistoryEntries()) { historyAdapter.add(entry); } locationUpdate(location); clearButton.setVisibility(historyAdapter.isEmpty() ? View.GONE : View.VISIBLE); screenOrientation = DashLocationFragment.getScreenOrientation(getActivity()); } @Override public void locationUpdate(LatLon l) { //location = l; if (getActivity() instanceof SearchActivity) { if (((SearchActivity) getActivity()).isSearchAroundCurrentLocation() && l != null) { if (!compassRegistered) { OsmandApplication app = getMyApplication(); app.getLocationProvider().removeCompassListener(app.getLocationProvider().getNavigationInfo()); app.getLocationProvider().addCompassListener(this); compassRegistered = true; } searchAroundLocation = true; } else { searchAroundLocation = false; } } if (historyAdapter != null) { historyAdapter.updateLocation(l); } } @Override public void onPause() { super.onPause(); if(getActivity() instanceof SearchActivity) { OsmandApplication app = getMyApplication(); app.getLocationProvider().removeCompassListener(this); app.getLocationProvider().addCompassListener(app.getLocationProvider().getNavigationInfo()); compassRegistered = false; } } @Override public void onListItemClick(ListView l, View v, int position, long id) { HistoryEntry model = ((HistoryAdapter) getListAdapter()).getItem(position); selectModel(model); } private void selectModel(final HistoryEntry model) { PointDescription name = model.getName(); OsmandSettings settings = ((OsmandApplication) getActivity().getApplication()).getSettings(); LatLon location = new LatLon(model.getLat(), model.getLon()); settings.setMapLocationToShow(location.getLatitude(), location.getLongitude(), settings.getLastKnownMapZoom(), name, true, model); //$NON-NLS-1$ MapActivity.launchMapActivityMoveToTop(getActivity()); } private void selectModelOptions(final HistoryEntry model, View v) { final PopupMenu optionsMenu = new PopupMenu(getActivity(), v); MenuItem item = optionsMenu.getMenu().add( R.string.shared_string_remove).setIcon( getMyApplication().getIconsCache().getThemedIcon(R.drawable.ic_action_delete_dark)); item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { helper.remove(model); historyAdapter.remove(model); return true; } }); optionsMenu.show(); } class HistoryAdapter extends ArrayAdapter<HistoryEntry> { private LatLon location; public void updateLocation(LatLon l) { location = l; notifyDataSetChanged(); } public HistoryAdapter(List<HistoryEntry> list) { super(getActivity(), R.layout.search_history_list_item, list); } @Override public View getView(final int position, View convertView, ViewGroup parent) { View row = convertView; if (row == null) { LayoutInflater inflater = getActivity().getLayoutInflater(); row = inflater.inflate(R.layout.search_history_list_item, parent, false); } final HistoryEntry historyEntry = getItem(position); udpateHistoryItem(historyEntry, row, location, getActivity(), getMyApplication()); TextView distanceText = (TextView) row.findViewById(R.id.distance); ImageView direction = (ImageView) row.findViewById(R.id.direction); DashLocationFragment.updateLocationView(!searchAroundLocation, location, heading, direction, distanceText, historyEntry.getLat(), historyEntry.getLon(), screenOrientation, getMyApplication(), getActivity()); ImageButton options = (ImageButton) row.findViewById(R.id.options); options.setImageDrawable(getMyApplication().getIconsCache().getThemedIcon(R.drawable.ic_overflow_menu_white)); options.setVisibility(View.VISIBLE); options.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { selectModelOptions(historyEntry, v); } }); if (getActivity() instanceof SearchActivity) ViewCompat.setAccessibilityDelegate(row, ((SearchActivity)getActivity()).getAccessibilityAssistant()); return row; } } public static void udpateHistoryItem(final HistoryEntry historyEntry, View row, LatLon location, Activity activity, OsmandApplication app) { TextView nameText = (TextView) row.findViewById(R.id.name); TextView distanceText = (TextView) row.findViewById(R.id.distance); ImageView direction = (ImageView) row.findViewById(R.id.direction); IconsCache ic = app.getIconsCache(); direction.setImageDrawable(ic.getIcon(R.drawable.ic_direction_arrow, R.color.color_distance)); String distance = ""; if (location != null) { int dist = (int) (MapUtils.getDistance(location, historyEntry.getLat(), historyEntry.getLon())); distance = OsmAndFormatter.getFormattedDistance(dist, (OsmandApplication) activity.getApplication()) + " "; } distanceText.setText(distance); PointDescription pd = historyEntry.getName(); nameText.setText(pd.getSimpleName(activity, false), BufferType.SPANNABLE); ImageView icon = ((ImageView) row.findViewById(R.id.icon)); icon.setImageDrawable(ic.getThemedIcon(getItemIcon(historyEntry.getName()))); String typeName = historyEntry.getName().getTypeName(); if (typeName != null && !typeName.isEmpty()) { ImageView group = (ImageView) row.findViewById(R.id.type_name_icon); group.setVisibility(View.VISIBLE); group.setImageDrawable(ic.getThemedIcon(R.drawable.ic_small_group)); ((TextView) row.findViewById(R.id.type_name)).setText(typeName); } else { row.findViewById(R.id.type_name_icon).setVisibility(View.GONE); ((TextView) row.findViewById(R.id.type_name)).setText(""); } } public static int getItemIcon(PointDescription pd) { int iconId; if (pd.isAddress()) { iconId = R.drawable.ic_type_address; } else if (pd.isFavorite()) { iconId = R.drawable.ic_type_favorites; } else if (pd.isLocation()) { iconId = R.drawable.ic_type_coordinates; } else if (pd.isPoi()) { iconId = R.drawable.ic_type_info; } else if (pd.isWpt()) { iconId = R.drawable.ic_type_waypoint; } else if (pd.isAudioNote()) { iconId = R.drawable.ic_type_audio; } else if (pd.isVideoNote()) { iconId = R.drawable.ic_type_video; }else if (pd.isPhotoNote()) { iconId = R.drawable.ic_type_img; } else { iconId = R.drawable.ic_type_address; } return iconId; } @Override public void onCreateOptionsMenu(Menu onCreate, MenuInflater inflater) { if (getActivity() instanceof SearchActivity) { ((SearchActivity) getActivity()).getClearToolbar(false); } } public OsmandApplication getMyApplication() { return (OsmandApplication) getActivity().getApplication(); } @Override public void updateCompassValue(float value) { // 99 in next line used to one-time initalize arrows (with reference vs. fixed-north direction) on non-compass // devices FragmentActivity activity = getActivity(); float lastHeading = heading != null ? heading : 99; heading = value; if (heading != null && Math.abs(MapUtils.degreesDiff(lastHeading, heading)) > 5) { if (activity instanceof SearchActivity) { ((SearchActivity)activity).getAccessibilityAssistant().lockEvents(); historyAdapter.notifyDataSetChanged(); ((SearchActivity)activity).getAccessibilityAssistant().unlockEvents(); } else { historyAdapter.notifyDataSetChanged(); } } else { heading = lastHeading; } if (activity instanceof SearchActivity) { final View selected = ((SearchActivity)activity).getAccessibilityAssistant().getFocusedView(); if (selected != null) { try { int position = getListView().getPositionForView(selected); if ((position != AdapterView.INVALID_POSITION) && (position >= getListView().getHeaderViewsCount())) { HistoryEntry historyEntry = historyAdapter.getItem(position - getListView().getHeaderViewsCount()); LatLon location = new LatLon(historyEntry.getLat(), historyEntry.getLon()); ((SearchActivity)activity).getNavigationInfo().updateTargetDirection(location, heading.floatValue()); } } catch (Exception e) { return; } } } } }