package net.osmand.plus.activities; import android.app.Activity; import android.app.Dialog; import android.content.DialogInterface; import android.content.DialogInterface.OnShowListener; import android.graphics.Color; import android.os.AsyncTask; import android.support.v7.app.AlertDialog; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.ImageButton; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.ProgressBar; import android.widget.TextView; import net.osmand.Location; import net.osmand.TspAnt; import net.osmand.data.LatLon; import net.osmand.plus.OsmAndFormatter; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.TargetPointsHelper; import net.osmand.plus.TargetPointsHelper.TargetPoint; import net.osmand.util.MapUtils; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import gnu.trove.list.array.TIntArrayList; public class IntermediatePointsDialog { public static void openIntermediatePointsDialog(final Activity activity, final OsmandApplication app, final boolean changeOrder){ TargetPointsHelper targets = app.getTargetPointsHelper(); final List<TargetPoint> intermediates = targets.getIntermediatePointsWithTarget(); final TIntArrayList originalPositions = new TIntArrayList(intermediates.size()); for(int j = 1; j <= intermediates.size(); j++) { originalPositions.add(j); } final boolean[] checkedIntermediates = new boolean[intermediates.size()]; Arrays.fill(checkedIntermediates, true); final ArrayAdapter<TargetPoint> listadapter = getListAdapter(app, activity, changeOrder, intermediates, originalPositions, checkedIntermediates); ListView lv = new ListView(activity); View contentView = lv; final ProgressBar pb = new ProgressBar(activity); pb.setVisibility(View.GONE); final TextView textInfo = new TextView(activity); textInfo.setText(R.string.intermediate_items_sort_return); textInfo.setVisibility(View.GONE); if (changeOrder) { LinearLayout ll = new LinearLayout(activity); ll.setOrientation(LinearLayout.VERTICAL); ll.addView(lv); ll.addView(pb); ll.addView(textInfo); contentView = ll; // lv.addFooterView(pb); // lv.addFooterView(textInfo); } lv.setAdapter(listadapter); lv.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { if (activity instanceof MapActivity) { // AnimateDraggingMapThread thread = mapActivity.getMapView().getAnimatedDraggingThread(); TargetPoint pointToNavigate = intermediates.get(position); int fZoom = ((MapActivity) activity).getMapView().getZoom() < 15 ? 15 : ((MapActivity) activity).getMapView().getZoom(); // thread.startMoving(pointToNavigate.getLatitude(), pointToNavigate.getLongitude(), fZoom, true); ((MapActivity) activity).getMapView().setIntZoom(fZoom); ((MapActivity) activity).getMapView().setLatLon(pointToNavigate.getLatitude(), pointToNavigate.getLongitude()); listadapter.notifyDataSetInvalidated(); } } }); AlertDialog.Builder builder = new AlertDialog.Builder(activity); builder.setView(contentView); builder.setInverseBackgroundForced(true); lv.setBackgroundColor(Color.WHITE); builder.setPositiveButton(R.string.shared_string_ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { if(changeOrder) { commitChangePointsOrder(app, intermediates); } else { commitPointsRemoval(app, checkedIntermediates); } } }); if (!changeOrder && intermediates.size() > 1) { builder.setNeutralButton(R.string.intermediate_points_change_order, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { openIntermediatePointsDialog(activity, app, true); } }); } else if (intermediates.size() > 1) { builder.setNeutralButton(R.string.intermediate_items_sort_by_distance, new Dialog.OnClickListener() { @Override public void onClick(DialogInterface d, int which) { // Do nothing here. We override the onclick } }); } AlertDialog dlg = builder.create(); if (changeOrder) { applySortTargets(dlg, activity, intermediates, originalPositions, listadapter, pb, textInfo); } dlg.show(); } private static void applySortTargets(AlertDialog dlg, final Activity activity, final List<TargetPoint> intermediates, final TIntArrayList originalPositions, final ArrayAdapter<TargetPoint> listadapter, final ProgressBar pb, final TextView textInfo) { dlg.setOnShowListener(new OnShowListener() { @Override public void onShow(DialogInterface dialog) { ((AlertDialog) dialog).getButton(AlertDialog.BUTTON_NEUTRAL).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new AsyncTask<Void, Void, int[]>() { protected void onPreExecute() { pb.setVisibility(View.VISIBLE); textInfo.setVisibility(View.VISIBLE); }; protected int[] doInBackground(Void[] params) { OsmandApplication app = (OsmandApplication) activity.getApplication(); Location cll = app.getLocationProvider().getLastKnownLocation(); ArrayList<TargetPoint> lt = new ArrayList<TargetPoint>(intermediates); TargetPoint start ; if(cll != null) { LatLon ll = new LatLon(cll.getLatitude(), cll.getLongitude()); start = TargetPoint.create(ll, null); } else if(app.getTargetPointsHelper().getPointToStart() != null) { TargetPoint ps = app.getTargetPointsHelper().getPointToStart(); LatLon ll = new LatLon(ps.getLatitude(), ps.getLongitude()); start = TargetPoint.create(ll, null); // } else if(activity instanceof MapActivity) { // LatLon ll = new LatLon(((MapActivity) activity).getMapView().getLatitude(), ((MapActivity) activity).getMapView().getLongitude()); // start = TargetPoint.create(ll, null); } else { start = lt.get(0); } TargetPoint end = lt.remove(lt.size() - 1); ArrayList<LatLon> al = new ArrayList<LatLon>(); for(TargetPoint p : lt){ al.add(p.point); } return new TspAnt().readGraph(al, start.point, end.point).solve(); }; protected void onPostExecute(int[] result) { pb.setVisibility(View.GONE); List<TargetPoint> alocs = new ArrayList<TargetPoint>(); TIntArrayList newOriginalPositions = new TIntArrayList(); for (int i = 0; i < result.length; i++) { if (result[i] > 0) { TargetPoint loc = intermediates.get(result[i] - 1); alocs.add(loc); newOriginalPositions.add(originalPositions.get(intermediates.indexOf(loc))); } } intermediates.clear(); intermediates.addAll(alocs); originalPositions.clear(); originalPositions.addAll(newOriginalPositions); listadapter.notifyDataSetChanged(); }; }.execute(new Void[0]); } }); } }); } private static ArrayAdapter<TargetPoint> getListAdapter(final OsmandApplication app, final Activity activity, final boolean changeOrder, final List<TargetPoint> intermediates, final TIntArrayList originalPositions, final boolean[] checkedIntermediates) { final int padding = (int) (12 * activity.getResources().getDisplayMetrics().density + 0.5f); final ArrayAdapter<TargetPoint> listadapter = new ArrayAdapter<TargetPoint>(app, changeOrder? R.layout.change_order_item : R.layout.list_menu_item_native, R.id.title, intermediates) { @Override public View getView(final int position, View convertView, ViewGroup parent) { // User super class to create the View View v = super.getView(position, convertView, parent); TextView tv = (TextView) v.findViewById(R.id.title); String nm = originalPositions.get(position) + ". "; TargetPoint tp = intermediates.get(position); String distString = ""; if(activity instanceof MapActivity) { double lat = ((MapActivity) activity).getMapView().getLatitude(); double lon = ((MapActivity) activity).getMapView().getLongitude(); double meters = MapUtils.getDistance(tp.point, lat, lon); distString = OsmAndFormatter.getFormattedDistance((float) meters, app); } if(position < intermediates.size() - 1) { nm += app.getString(R.string.target_point, distString); } else { nm += app.getString(R.string.destination_point, distString); } String descr = tp.getOnlyName(); if(descr != null && descr.trim().length() > 0) { nm += "\n" + descr; } tv.setText(nm); if (changeOrder) { ((ImageButton) v.findViewById(R.id.up)).setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v) { if(position > 0) { TargetPoint old = intermediates.remove(position - 1); int oldI = originalPositions.removeAt(position -1 ); intermediates.add(position, old); originalPositions.insert(position, oldI); notifyDataSetInvalidated(); } } }); ((ImageButton) v.findViewById(R.id.down)).setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v) { if(position < intermediates.size() - 1) { TargetPoint old = intermediates.remove(position + 1); int oldI = originalPositions.removeAt(position + 1 ); intermediates.add(position, old); originalPositions.insert(position, oldI); notifyDataSetInvalidated(); } } }); } else { int icon = position == intermediates.size() - 1? R.drawable.ic_action_target: R.drawable.ic_action_intermediate; tv.setCompoundDrawablesWithIntrinsicBounds(app.getIconsCache().getThemedIcon(icon), null, null, null); tv.setCompoundDrawablePadding(padding); final CheckBox ch = ((CheckBox) v.findViewById(R.id.toggle_item)); ch.setVisibility(View.VISIBLE); ch.setOnCheckedChangeListener(null); ch.setChecked(checkedIntermediates[position]); ch.setOnCheckedChangeListener(new OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { checkedIntermediates[position] = isChecked; } }); } return v; } }; return listadapter; } public static void commitPointsRemoval(OsmandApplication app, final boolean[] checkedIntermediates) { int cnt = 0; for (int i = checkedIntermediates.length - 1; i >= 0; i--) { if (!checkedIntermediates[i]) { cnt++; } } if (cnt > 0) { boolean changeDestinationFlag = !checkedIntermediates[checkedIntermediates.length - 1]; if (cnt == checkedIntermediates.length) { // there is no alternative destination if all points are to be // removed? app.getTargetPointsHelper().removeAllWayPoints(true, true); } else { for (int i = checkedIntermediates.length - 2; i >= 0; i--) { // skip the destination until a retained // waypoint is found if (checkedIntermediates[i] && changeDestinationFlag) { // Find a valid replacement for the // destination app.getTargetPointsHelper().makeWayPointDestination(cnt == 0, i); changeDestinationFlag = false; } else if (!checkedIntermediates[i]) { cnt--; app.getTargetPointsHelper().removeWayPoint(cnt == 0, i); } } } } } private static void commitChangePointsOrder(OsmandApplication app, List<TargetPoint> target) { TargetPointsHelper targets = app.getTargetPointsHelper(); List<TargetPoint> cur = targets.getIntermediatePointsWithTarget(); boolean eq = true; for(int j = 0; j < cur.size() && j < target.size() ; j++) { if(cur.get(j) != target.get(j)) { eq = false; break; } } if(!eq) { targets.reorderAllTargetPoints(target, true); } } }