Add search neighborhood cities

This commit is contained in:
Victor Shcherb 2013-06-03 23:41:04 +02:00
parent 7de85b7cf6
commit 33f7399149
5 changed files with 234 additions and 55 deletions

View file

@ -8,10 +8,10 @@
<string name="ga_debug">true</string> <string name="ga_debug">true</string>
<string name="versionFeatures">+play_market +gps_status -parking_plugin -blackberry -free_version -amazon</string> <string name="versionFeatures">+play_market +gps_status -parking_plugin -blackberry -free_version -amazon</string>
<string name="next_tips_and_tricks_not_translate"> <string name="next_tips_and_tricks_not_translate">
* Order waypoints in optimal way to visit all (Travelling salesman, door-to-door)
* New downlad screen * New downlad screen
* Planning mode * Planning mode
* Delete SRTM files * Delete SRTM files
* GPX subfolders structure * GPX subfolders structure
* Order waypoints in optimal way (Travel salesman)
</string> </string>
</resources> </resources>

View file

@ -9,6 +9,7 @@
3. All your modified/created strings are in the top of the file (to make easier find what\'s translated). 3. All your modified/created strings are in the top of the file (to make easier find what\'s translated).
PLEASE: Have a look at http://code.google.com/p/osmand/wiki/UIConsistency, it may really improve your and our work :-) Thx - Hardy PLEASE: Have a look at http://code.google.com/p/osmand/wiki/UIConsistency, it may really improve your and our work :-) Thx - Hardy
--> -->
<string name="search_street_in_neighborhood_cities">Search street in neighborhood cities</string>
<string name="intermediate_items_sort_return">Positions ordered to form optimal way from map position to the target location</string> <string name="intermediate_items_sort_return">Positions ordered to form optimal way from map position to the target location</string>
<string name="intermediate_items_sort_by_distance">Sort (door-to-door)</string> <string name="intermediate_items_sort_by_distance">Sort (door-to-door)</string>
<string name="local_osm_changes_backup_successful">OSM change file succesfully generated %1$s</string> <string name="local_osm_changes_backup_successful">OSM change file succesfully generated %1$s</string>

View file

@ -1,5 +1,7 @@
package net.osmand.plus.activities; package net.osmand.plus.activities;
import gnu.trove.list.array.TIntArrayList;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -12,26 +14,25 @@ import net.osmand.plus.R;
import net.osmand.plus.TargetPointsHelper; import net.osmand.plus.TargetPointsHelper;
import net.osmand.util.MapUtils; import net.osmand.util.MapUtils;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder; import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.DialogInterface.OnShowListener;
import android.graphics.Color; import android.graphics.Color;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener; import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox; import android.widget.CheckBox;
import android.widget.CompoundButton; import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ImageButton; import android.widget.ImageButton;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.ListView; import android.widget.ListView;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.ScrollView;
import android.widget.TextView; import android.widget.TextView;
public class IntermediatePointsDialog { public class IntermediatePointsDialog {
@ -45,57 +46,31 @@ public class IntermediatePointsDialog {
final OsmandApplication app, final boolean changeOrder){ final OsmandApplication app, final boolean changeOrder){
TargetPointsHelper targets = app.getTargetPointsHelper(); TargetPointsHelper targets = app.getTargetPointsHelper();
final List<LatLon> intermediates = targets.getIntermediatePointsWithTarget(); final List<LatLon> intermediates = targets.getIntermediatePointsWithTarget();
final TIntArrayList originalPositions = new TIntArrayList(intermediates.size());
for(int j = 1; j <= intermediates.size(); j++) {
originalPositions.add(j);
}
final List<String> names = targets.getIntermediatePointNamesWithTarget(); final List<String> names = targets.getIntermediatePointNamesWithTarget();
final boolean[] checkedIntermediates = new boolean[intermediates.size()]; final boolean[] checkedIntermediates = new boolean[intermediates.size()];
final ArrayAdapter<LatLon> listadapter = getListAdapter(app, activity, changeOrder, intermediates, names, checkedIntermediates); final ArrayAdapter<LatLon> listadapter = getListAdapter(app, activity, changeOrder, intermediates, originalPositions, names, checkedIntermediates);
ListView lv = new ListView(activity); ListView lv = new ListView(activity);
View contentView = lv;
final ProgressBar pb = new ProgressBar(activity); final ProgressBar pb = new ProgressBar(activity);
pb.setVisibility(View.GONE); pb.setVisibility(View.GONE);
final TextView textInfo = new TextView(activity); final TextView textInfo = new TextView(activity);
textInfo.setText(R.string.intermediate_items_sort_return); textInfo.setText(R.string.intermediate_items_sort_return);
textInfo.setVisibility(View.GONE); textInfo.setVisibility(View.GONE);
if (changeOrder) { if (changeOrder) {
Button btn = new Button(activity); LinearLayout ll = new LinearLayout(activity);
btn.setText(R.string.intermediate_items_sort_by_distance); ll.setOrientation(LinearLayout.VERTICAL);
btn.setOnClickListener(new OnClickListener() { ll.addView(lv);
@Override ll.addView(pb);
public void onClick(View v) { ll.addView(textInfo);
new AsyncTask<Void, Void, int[]>() { contentView = ll;
protected void onPreExecute() { // lv.addFooterView(pb);
pb.setVisibility(View.VISIBLE); // lv.addFooterView(textInfo);
textInfo.setVisibility(View.VISIBLE);
};
protected int[] doInBackground(Void[] params) {
ArrayList<LatLon> lt = new ArrayList<LatLon>(intermediates);
LatLon start = new LatLon(activity.getMapView().getLatitude(), activity.getMapView().getLongitude());
LatLon end = lt.remove(lt.size() - 1);
return new TspAnt().readGraph(lt, start, end).solve();
};
protected void onPostExecute(int[] result) {
pb.setVisibility(View.GONE);
List<LatLon> alocs = new ArrayList<LatLon>();
List<String> anames = new ArrayList<String>();
for (int i = 0; i < result.length; i++) {
if(result[i] > 0) {
alocs.add(intermediates.get(result[i] - 1));
anames.add(names.get(result[i] - 1));
}
}
intermediates.clear();
intermediates.addAll(alocs);
names.clear();
names.addAll(anames);
listadapter.notifyDataSetChanged();
};
}.execute(new Void[0]);
}
});
lv.addFooterView(pb);
lv.addFooterView(textInfo);
lv.addFooterView(btn);
} }
lv.setAdapter(listadapter); lv.setAdapter(listadapter);
lv.setOnItemClickListener(new OnItemClickListener() { lv.setOnItemClickListener(new OnItemClickListener() {
@ -114,7 +89,7 @@ public class IntermediatePointsDialog {
}); });
Builder builder = new AccessibleAlertBuilder(activity); Builder builder = new AccessibleAlertBuilder(activity);
builder.setView(lv); builder.setView(contentView);
builder.setInverseBackgroundForced(true); builder.setInverseBackgroundForced(true);
lv.setBackgroundColor(Color.WHITE); lv.setBackgroundColor(Color.WHITE);
builder.setPositiveButton(R.string.default_buttons_ok, new DialogInterface.OnClickListener() { builder.setPositiveButton(R.string.default_buttons_ok, new DialogInterface.OnClickListener() {
@ -135,13 +110,79 @@ public class IntermediatePointsDialog {
openIntermediatePointsDialog(activity, app, true); openIntermediatePointsDialog(activity, app, true);
} }
}); });
} else {
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
} }
builder.show(); });
} }
AlertDialog dlg = builder.create();
if (changeOrder) {
applySortTargets(dlg, activity, intermediates, originalPositions, names, listadapter, pb, textInfo);
}
dlg.show();
}
private static void applySortTargets(AlertDialog dlg, final MapActivity activity, final List<LatLon> intermediates,
final TIntArrayList originalPositions,
final List<String> names, final ArrayAdapter<LatLon> 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) {
ArrayList<LatLon> lt = new ArrayList<LatLon>(intermediates);
LatLon start = new LatLon(activity.getMapView().getLatitude(), activity.getMapView().getLongitude());
LatLon end = lt.remove(lt.size() - 1);
return new TspAnt().readGraph(lt, start, end).solve();
};
protected void onPostExecute(int[] result) {
pb.setVisibility(View.GONE);
List<LatLon> alocs = new ArrayList<LatLon>();
List<String> anames = new ArrayList<String>();
TIntArrayList newOriginalPositions = new TIntArrayList();
for (int i = 0; i < result.length; i++) {
if (result[i] > 0) {
LatLon loc = intermediates.get(result[i] - 1);
alocs.add(loc);
newOriginalPositions.add(originalPositions.get(intermediates.indexOf(loc)));
anames.add(names.get(result[i] - 1));
}
}
intermediates.clear();
intermediates.addAll(alocs);
names.clear();
names.addAll(anames);
originalPositions.clear();
originalPositions.addAll(newOriginalPositions);
listadapter.notifyDataSetChanged();
};
}.execute(new Void[0]);
}
});
}
});
}
private static ArrayAdapter<LatLon> getListAdapter(final OsmandApplication app, final Activity activity, final boolean changeOrder, private static ArrayAdapter<LatLon> getListAdapter(final OsmandApplication app, final Activity activity, final boolean changeOrder,
final List<LatLon> intermediates, final List<String> names, final boolean[] checkedIntermediates) { final List<LatLon> intermediates, final TIntArrayList originalPositions, final List<String> names, final boolean[] checkedIntermediates) {
final int padding = (int) (12 * activity.getResources().getDisplayMetrics().density + 0.5f); final int padding = (int) (12 * activity.getResources().getDisplayMetrics().density + 0.5f);
final ArrayAdapter<LatLon> listadapter = new ArrayAdapter<LatLon>(app, final ArrayAdapter<LatLon> listadapter = new ArrayAdapter<LatLon>(app,
changeOrder? R.layout.change_order_item : R.layout.list_menu_item, R.id.title, changeOrder? R.layout.change_order_item : R.layout.list_menu_item, R.id.title,
@ -152,7 +193,7 @@ public class IntermediatePointsDialog {
// User super class to create the View // User super class to create the View
View v = super.getView(position, convertView, parent); View v = super.getView(position, convertView, parent);
TextView tv = (TextView) v.findViewById(R.id.title); TextView tv = (TextView) v.findViewById(R.id.title);
String nm = (position + 1) + ". "; String nm = originalPositions.get(position) + ". ";
String distString = ""; String distString = "";
if(activity instanceof MapActivity) { if(activity instanceof MapActivity) {
double lat = ((MapActivity) activity).getMapView().getLatitude(); double lat = ((MapActivity) activity).getMapView().getLatitude();
@ -175,8 +216,10 @@ public class IntermediatePointsDialog {
if(position > 0) { if(position > 0) {
LatLon old = intermediates.remove(position - 1); LatLon old = intermediates.remove(position - 1);
String oldN = names.remove(position - 1); String oldN = names.remove(position - 1);
int oldI = originalPositions.removeAt(position -1 );
names.add(position, oldN); names.add(position, oldN);
intermediates.add(position, old); intermediates.add(position, old);
originalPositions.insert(position, oldI);
notifyDataSetInvalidated(); notifyDataSetInvalidated();
} }
} }
@ -187,8 +230,10 @@ public class IntermediatePointsDialog {
if(position < intermediates.size() - 1) { if(position < intermediates.size() - 1) {
LatLon old = intermediates.remove(position + 1); LatLon old = intermediates.remove(position + 1);
String oldN = names.remove(position + 1); String oldN = names.remove(position + 1);
int oldI = originalPositions.removeAt(position + 1 );
names.add(position, oldN); names.add(position, oldN);
intermediates.add(position, old); intermediates.add(position, old);
originalPositions.insert(position, oldI);
notifyDataSetInvalidated(); notifyDataSetInvalidated();
} }
} }

View file

@ -32,6 +32,7 @@ import android.os.Message;
import android.text.Editable; import android.text.Editable;
import android.text.Spannable; import android.text.Spannable;
import android.text.TextWatcher; import android.text.TextWatcher;
import android.text.style.ForegroundColorSpan;
import android.text.style.StyleSpan; import android.text.style.StyleSpan;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -45,6 +46,7 @@ import android.widget.Filter;
import android.widget.ListView; import android.widget.ListView;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;
import android.widget.TextView.BufferType;
import android.widget.TextView.OnEditorActionListener; import android.widget.TextView.OnEditorActionListener;
@ -137,8 +139,9 @@ public abstract class SearchByNameAbstractActivity<T> extends OsmandListActivity
findViewById(R.id.ResetButton).setOnClickListener(new View.OnClickListener(){ findViewById(R.id.ResetButton).setOnClickListener(new View.OnClickListener(){
@Override @Override
public void onClick(View v) { public void onClick(View v) {
searchText.setText(""); reset();
} }
}); });
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
if(initializeTask != null){ if(initializeTask != null){
@ -146,6 +149,10 @@ public abstract class SearchByNameAbstractActivity<T> extends OsmandListActivity
} }
} }
protected void reset() {
searchText.setText("");
}
protected void addFooterViews() { protected void addFooterViews() {
} }
@ -189,6 +196,10 @@ public abstract class SearchByNameAbstractActivity<T> extends OsmandListActivity
querySearch(currentFilter); querySearch(currentFilter);
} }
protected View getFooterView() {
return null;
}
private void querySearch(final String filter) { private void querySearch(final String filter) {
if (!currentFilter.equals(filter) || !initFilter) { if (!currentFilter.equals(filter) || !initFilter) {
currentFilter = filter; currentFilter = filter;
@ -242,6 +253,10 @@ public abstract class SearchByNameAbstractActivity<T> extends OsmandListActivity
protected abstract Comparator<? super T> createComparator(); protected abstract Comparator<? super T> createComparator();
public String getDistanceText(T obj) {
return null;
}
public abstract String getText(T obj); public abstract String getText(T obj);
public String getShortText(T obj) { public String getShortText(T obj) {
@ -413,7 +428,15 @@ public abstract class SearchByNameAbstractActivity<T> extends OsmandListActivity
row = inflater.inflate(R.layout.searchbyname_list, parent, false); row = inflater.inflate(R.layout.searchbyname_list, parent, false);
} }
TextView label = (TextView) row.findViewById(R.id.NameLabel); TextView label = (TextView) row.findViewById(R.id.NameLabel);
label.setText(getText(getItem(position))); String distanceText = getDistanceText(getItem(position));
String text = getText(getItem(position));
if(distanceText == null) {
label.setText(text);
} else {
label.setText(distanceText + " " + text, BufferType.SPANNABLE);
((Spannable) label.getText()).setSpan(new ForegroundColorSpan(getResources().getColor(R.color.color_distance)), 0,
distanceText.length(), 0);
}
return row; return row;
} }
} }

View file

@ -10,22 +10,69 @@ import net.osmand.CollatorStringMatcher;
import net.osmand.CollatorStringMatcher.StringMatcherMode; import net.osmand.CollatorStringMatcher.StringMatcherMode;
import net.osmand.ResultMatcher; import net.osmand.ResultMatcher;
import net.osmand.data.City; import net.osmand.data.City;
import net.osmand.data.MapObject;
import net.osmand.data.MapObject.MapObjectComparator; import net.osmand.data.MapObject.MapObjectComparator;
import net.osmand.data.Street; import net.osmand.data.Street;
import net.osmand.plus.OsmAndFormatter;
import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R; import net.osmand.plus.R;
import net.osmand.plus.resources.RegionAddressRepository; import net.osmand.plus.resources.RegionAddressRepository;
import net.osmand.util.Algorithms;
import net.osmand.util.MapUtils;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Message; import android.os.Message;
import android.view.Gravity;
import android.view.View; import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.FrameLayout;
public class SearchStreetByNameActivity extends SearchByNameAbstractActivity<Street> { public class SearchStreetByNameActivity extends SearchByNameAbstractActivity<Street> {
private RegionAddressRepository region; private RegionAddressRepository region;
private City city; private City city;
private Button searchAllStrets;
private int searchWithCity = -1; // -1 - default, 0 - filter city, 1 - deep search
@Override @Override
protected Comparator<? super Street> createComparator() { protected Comparator<? super Street> createComparator() {
return new MapObjectComparator(getMyApplication().getSettings().usingEnglishNames()); return new MapObjectComparator(getMyApplication().getSettings().usingEnglishNames()) {
@Override
public int compare(MapObject o1, MapObject o2) {
if(searchWithCity >= 0 && city != null) {
double d1 = MapUtils.getDistance(city.getLocation(), o1.getLocation());
double d2 = MapUtils.getDistance(city.getLocation(), o2.getLocation());
return Double.compare(d1, d2);
}
return super.compare(o1, o2);
}
};
}
@Override
protected void reset() {
searchWithCity = -1;
super.reset();
}
@Override
protected void addFooterViews() {
final FrameLayout ll = new FrameLayout(this);
searchAllStrets = new Button(this);
android.widget.FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
lp.gravity = Gravity.CENTER_HORIZONTAL;
searchAllStrets.setLayoutParams(lp);
searchAllStrets.setText(R.string.search_street_in_neighborhood_cities);
ll.addView(searchAllStrets);
searchAllStrets.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
searchWithCity = 1;
research();
}
});
getListView().addFooterView(ll);
} }
@Override @Override
@ -50,7 +97,7 @@ public class SearchStreetByNameActivity extends SearchByNameAbstractActivity<Str
if (region != null) { if (region != null) {
city = region.getCityById(settings.getLastSearchedCity(), settings.getLastSearchedCityName()); city = region.getCityById(settings.getLastSearchedCity(), settings.getLastSearchedCityName());
if (city == null) { if (city == null) {
return null; return new ArrayList<Street>();
} }
region.preloadStreets(city, new ResultMatcher<Street>() { region.preloadStreets(city, new ResultMatcher<Street>() {
@Override @Override
@ -73,6 +120,53 @@ public class SearchStreetByNameActivity extends SearchByNameAbstractActivity<Str
@Override @Override
protected void filterLoop(String query, Collection<Street> list) { protected void filterLoop(String query, Collection<Street> list) {
if(searchWithCity == -1){
filter(query, list);
} else if(searchWithCity == 0){
for (Street obj : list) {
if(namesFilter.isCancelled){
break;
}
if(filterObject(obj, query)){
Message msg = uiHandler.obtainMessage(MESSAGE_ADD_ENTITY, obj);
msg.sendToTarget();
}
}
} else {
searchWithCity = 0;
final List res = region.searchMapObjectsByName(query, new ResultMatcher<MapObject>() {
@Override
public boolean publish(MapObject object) {
if (object instanceof Street) {
if(city == null ||
MapUtils.getDistance(city.getLocation(), object.getLocation()) < 100*1000) {
Message msg = uiHandler.obtainMessage(MESSAGE_ADD_ENTITY, object);
msg.sendToTarget();
return true;
}
}
return false;
}
@Override
public boolean isCancelled() {
return namesFilter.isCancelled;
}
});
runOnUiThread(new Runnable() {
@Override
public void run() {
finishInitializing(res);
}
});
}
}
private void filter(String query, Collection<Street> list) {
boolean emptyQuery = query == null || query.length() == 0; boolean emptyQuery = query == null || query.length() == 0;
for (Street obj : list) { for (Street obj : list) {
if (namesFilter.isCancelled) { if (namesFilter.isCancelled) {
@ -99,12 +193,28 @@ public class SearchStreetByNameActivity extends SearchByNameAbstractActivity<Str
@Override @Override
public String getText(Street obj) { public String getText(Street obj) {
if(searchWithCity >= 0 || city == null) {
String nameWithCity = obj.getName(region.useEnglishNames()) + " - " + obj.getCity().getName(region.useEnglishNames());
return nameWithCity ;
}
return obj.getName(region.useEnglishNames()); return obj.getName(region.useEnglishNames());
} }
@Override
public String getDistanceText(Street obj) {
if(searchWithCity >= 0 && city != null) {
return OsmAndFormatter.getFormattedDistance((float) MapUtils.getDistance(obj.getLocation(), city.getLocation()),
getMyApplication());
}
return null;
}
@Override @Override
public void itemSelected(Street obj) { public void itemSelected(Street obj) {
if(!Algorithms.objectEquals(settings.getLastSearchedCity(), obj.getCity().getId())) {
settings.setLastSearchedCity(obj.getCity().getId(), obj.getCity().getName(), obj.getLocation());
}
settings.setLastSearchedStreet(obj.getName(region.useEnglishNames()), obj.getLocation()); settings.setLastSearchedStreet(obj.getName(region.useEnglishNames()), obj.getLocation());
finish(); finish();