package net.osmand.plus.activities.search; import android.os.AsyncTask; import android.os.Message; import android.view.Gravity; import android.view.View; import android.view.ViewGroup.LayoutParams; import android.widget.Button; import android.widget.FrameLayout; import net.osmand.CollatorStringMatcher; import net.osmand.CollatorStringMatcher.StringMatcherMode; import net.osmand.ResultMatcher; import net.osmand.data.City; import net.osmand.data.MapObject; import net.osmand.data.MapObject.MapObjectComparator; import net.osmand.data.Street; import net.osmand.plus.OsmAndFormatter; import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandSettings; import net.osmand.plus.R; import net.osmand.plus.activities.search.SearchAddressFragment.AddressInformation; import net.osmand.plus.resources.RegionAddressRepository; import net.osmand.util.Algorithms; import net.osmand.util.MapUtils; import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; import java.util.List; public class SearchStreetByNameActivity extends SearchByNameAbstractActivity<Street> { private RegionAddressRepository region; private City city; private Button searchAllStrets; private int searchWithCity = -1; // -1 - default, 0 - filter city, 1 - deep search private OsmandSettings osmandSettings; @Override protected Comparator<? super Street> createComparator() { return new MapObjectComparator(getMyApplication().getSettings().MAP_PREFERRED_LOCALE.get(), getMyApplication().getSettings().MAP_TRANSLITERATE_NAMES.get()) { @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() { //This is really only a "clear input text field", hence do not reset settings here //searchWithCity = -1; //osmandSettings.setLastSearchedStreet("", null); 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 public AsyncTask<Object, ?, ?> getInitializeTask() { return new AsyncTask<Object, Street, List<Street>>() { @Override protected void onPostExecute(List<Street> result) { setLabelText(R.string.incremental_search_street); progress.setVisibility(View.INVISIBLE); finishInitializing(result); } @Override protected void onPreExecute() { setLabelText(R.string.loading_streets); progress.setVisibility(View.VISIBLE); } @Override protected List<Street> doInBackground(Object... params) { region = ((OsmandApplication) getApplication()).getResourceManager().getRegionRepository(settings.getLastSearchedRegion()); if (region != null) { city = region.getCityById(settings.getLastSearchedCity(), settings.getLastSearchedCityName()); if (city == null) { return new ArrayList<Street>(); } region.preloadStreets(city, new ResultMatcher<Street>() { @Override public boolean publish(Street object) { addObjectToInitialList(object); return true; } @Override public boolean isCancelled() { return false; } }); return new ArrayList<Street>(city.getStreets()); } return null; } }; } @Override protected boolean filterLoop(String query, Collection<Street> list) { final boolean[] result = {false}; if (searchWithCity == -1) { filter(query, list); } else if (searchWithCity == 0) { for (Street obj : list) { if (namesFilter.isCancelled) { break; } if (filterObject(obj, query)) { result[0] = true; 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) { result[0] = true; 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); } }); } return result[0]; } private void filter(String query, Collection<Street> list) { boolean emptyQuery = query == null || query.length() == 0; List<Street> streetsToSend = new ArrayList<>(); for (Street obj : list) { if (namesFilter.isCancelled) { break; } if (emptyQuery || CollatorStringMatcher.cmatches(collator, obj.getNameWithoutCityPart(settings.MAP_PREFERRED_LOCALE.get(), settings.MAP_TRANSLITERATE_NAMES.get()), query, StringMatcherMode.CHECK_ONLY_STARTS_WITH)) { streetsToSend.add(obj); } if (!emptyQuery && CollatorStringMatcher.cmatches(collator, obj.getNameWithoutCityPart(settings.MAP_PREFERRED_LOCALE.get(), settings.MAP_TRANSLITERATE_NAMES.get()), query, StringMatcherMode.CHECK_STARTS_FROM_SPACE_NOT_BEGINNING)) { streetsToSend.add(obj); } } final int loopSize = 100; for (int i = 0; i < streetsToSend.size(); i += loopSize) { int endIndex = i + loopSize; if (endIndex > streetsToSend.size()) { endIndex = streetsToSend.size(); } List<Street> listToSend = streetsToSend.subList(i, endIndex); Message msg = uiHandler.obtainMessage(MESSAGE_ADD_ENTITIES, listToSend); msg.sendToTarget(); } } @Override public String getText(Street obj) { if(searchWithCity >= 0 || city == null) { String nameWithCity = getLangPreferredName(obj) + " - " + getLangPreferredName(obj.getCity()); return nameWithCity ; } return getLangPreferredName(obj); } @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 public void itemSelected(Street obj) { if(!Algorithms.objectEquals(settings.getLastSearchedCity(), obj.getCity().getId())) { settings.setLastSearchedCity(obj.getCity().getId(), getLangPreferredName(obj.getCity()), obj.getLocation()); region.addCityToPreloadedList(obj.getCity()); } settings.setLastSearchedStreet(getLangPreferredName(obj), obj.getLocation()); // if(obj.getBuildings().size() == 0){ // quitActivity(null); // } else { quitActivity(SearchBuildingByNameActivity.class); // } } protected AddressInformation getAddressInformation() { return AddressInformation.buildCity(this, settings); } }