Fix #3156
This commit is contained in:
parent
700e77c9c5
commit
5f0add31a3
4 changed files with 282 additions and 26 deletions
|
@ -1,8 +1,18 @@
|
|||
package net.osmand.map;
|
||||
|
||||
|
||||
import gnu.trove.iterator.TIntObjectIterator;
|
||||
import gnu.trove.list.array.TIntArrayList;
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.ResultMatcher;
|
||||
import net.osmand.binary.BinaryMapDataObject;
|
||||
import net.osmand.binary.BinaryMapIndexReader;
|
||||
import net.osmand.binary.BinaryMapIndexReader.MapIndex;
|
||||
import net.osmand.binary.BinaryMapIndexReader.TagValuePair;
|
||||
import net.osmand.data.LatLon;
|
||||
import net.osmand.data.QuadRect;
|
||||
import net.osmand.data.QuadTree;
|
||||
import net.osmand.util.Algorithms;
|
||||
import net.osmand.util.MapAlgorithms;
|
||||
import net.osmand.util.MapUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
@ -21,19 +31,8 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.ResultMatcher;
|
||||
import net.osmand.binary.BinaryMapDataObject;
|
||||
import net.osmand.binary.BinaryMapIndexReader;
|
||||
import net.osmand.binary.BinaryMapIndexReader.MapIndex;
|
||||
import net.osmand.binary.BinaryMapIndexReader.TagValuePair;
|
||||
import net.osmand.data.LatLon;
|
||||
import net.osmand.data.QuadRect;
|
||||
import net.osmand.data.QuadTree;
|
||||
import net.osmand.osm.edit.Node;
|
||||
import net.osmand.util.Algorithms;
|
||||
import net.osmand.util.MapAlgorithms;
|
||||
import net.osmand.util.MapUtils;
|
||||
import gnu.trove.iterator.TIntObjectIterator;
|
||||
import gnu.trove.list.array.TIntArrayList;
|
||||
|
||||
public class OsmandRegions {
|
||||
|
||||
|
@ -686,4 +685,53 @@ public class OsmandRegions {
|
|||
}
|
||||
}
|
||||
|
||||
public BinaryMapDataObject findBinaryMapDataObject(LatLon latLon) {
|
||||
int point31x = MapUtils.get31TileNumberX(latLon.getLongitude());
|
||||
int point31y = MapUtils.get31TileNumberY(latLon.getLatitude());
|
||||
|
||||
BinaryMapDataObject res = null;
|
||||
List<BinaryMapDataObject> mapDataObjects = null;
|
||||
try {
|
||||
mapDataObjects = queryBbox(point31x, point31x, point31y, point31y);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (mapDataObjects != null) {
|
||||
Iterator<BinaryMapDataObject> it = mapDataObjects.iterator();
|
||||
while (it.hasNext()) {
|
||||
BinaryMapDataObject o = it.next();
|
||||
if (o.getTypes() != null) {
|
||||
boolean isRegion = true;
|
||||
for (int i = 0; i < o.getTypes().length; i++) {
|
||||
TagValuePair tp = o.getMapIndex().decodeType(o.getTypes()[i]);
|
||||
if ("boundary".equals(tp.value)) {
|
||||
isRegion = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
WorldRegion downloadRegion = getRegionData(getFullName(o));
|
||||
if (!isRegion
|
||||
|| downloadRegion == null
|
||||
|| !downloadRegion.isRegionMapDownload()
|
||||
|| !contain(o, point31x, point31y)) {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
double smallestArea = -1;
|
||||
for (BinaryMapDataObject o : mapDataObjects) {
|
||||
double area = OsmandRegions.getArea(o);
|
||||
if (smallestArea == -1) {
|
||||
smallestArea = area;
|
||||
res = o;
|
||||
} else if (area < smallestArea) {
|
||||
smallestArea = area;
|
||||
res = o;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
31
OsmAnd/src/net/osmand/plus/download/CityItem.java
Normal file
31
OsmAnd/src/net/osmand/plus/download/CityItem.java
Normal file
|
@ -0,0 +1,31 @@
|
|||
package net.osmand.plus.download;
|
||||
|
||||
import net.osmand.data.Amenity;
|
||||
|
||||
public class CityItem {
|
||||
private String name;
|
||||
private Amenity amenity;
|
||||
private IndexItem indexItem;
|
||||
|
||||
public CityItem(String name, Amenity amenity, IndexItem indexItem) {
|
||||
this.name = name;
|
||||
this.amenity = amenity;
|
||||
this.indexItem = indexItem;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Amenity getAmenity() {
|
||||
return amenity;
|
||||
}
|
||||
|
||||
public IndexItem getIndexItem() {
|
||||
return indexItem;
|
||||
}
|
||||
|
||||
public void setIndexItem(IndexItem indexItem) {
|
||||
this.indexItem = indexItem;
|
||||
}
|
||||
}
|
|
@ -25,6 +25,7 @@ import net.osmand.plus.R;
|
|||
import net.osmand.plus.Version;
|
||||
import net.osmand.plus.activities.LocalIndexHelper.LocalIndexType;
|
||||
import net.osmand.plus.activities.LocalIndexInfo;
|
||||
import net.osmand.plus.download.CityItem;
|
||||
import net.osmand.plus.download.DownloadActivity;
|
||||
import net.osmand.plus.download.DownloadActivityType;
|
||||
import net.osmand.plus.download.DownloadResourceGroup;
|
||||
|
@ -33,6 +34,7 @@ import net.osmand.plus.download.IndexItem;
|
|||
import net.osmand.plus.download.ui.LocalIndexesFragment.LocalIndexOperationTask;
|
||||
import net.osmand.plus.helpers.FileNameTranslationHelper;
|
||||
import net.osmand.plus.srtmplugin.SRTMPlugin;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
import java.io.File;
|
||||
import java.text.DateFormat;
|
||||
|
@ -130,6 +132,10 @@ public class ItemViewHolder {
|
|||
}
|
||||
|
||||
public void bindIndexItem(final IndexItem indexItem) {
|
||||
bindIndexItem(indexItem, null);
|
||||
}
|
||||
|
||||
public void bindIndexItem(final IndexItem indexItem, final String cityName) {
|
||||
initAppStatusVariables();
|
||||
boolean isDownloading = context.getDownloadThread().isDownloading(indexItem);
|
||||
int progress = -1;
|
||||
|
@ -138,11 +144,14 @@ public class ItemViewHolder {
|
|||
}
|
||||
boolean disabled = checkDisabledAndClickAction(indexItem);
|
||||
/// name and left item
|
||||
String name;
|
||||
if(showTypeInName) {
|
||||
nameTextView.setText(indexItem.getType().getString(context));
|
||||
name = indexItem.getType().getString(context);
|
||||
} else {
|
||||
nameTextView.setText(indexItem.getVisibleName(context, context.getMyApplication().getRegions(), showParentRegionName));
|
||||
name = indexItem.getVisibleName(context, context.getMyApplication().getRegions(), showParentRegionName);
|
||||
}
|
||||
String text = (!Algorithms.isEmpty(cityName) && !cityName.equals(name) ? cityName + "\n" : "") + name;
|
||||
nameTextView.setText(text);
|
||||
if(!disabled) {
|
||||
nameTextView.setTextColor(textColorPrimary);
|
||||
} else {
|
||||
|
@ -209,6 +218,17 @@ public class ItemViewHolder {
|
|||
}
|
||||
}
|
||||
|
||||
public void bindIndexItem(final CityItem cityItem) {
|
||||
if (cityItem.getIndexItem() != null) {
|
||||
bindIndexItem(cityItem.getIndexItem(), cityItem.getName());
|
||||
} else {
|
||||
nameTextView.setText(cityItem.getName());
|
||||
nameTextView.setTextColor(textColorPrimary);
|
||||
leftImageView.setImageDrawable(getContentIcon(context, R.drawable.ic_map));
|
||||
descrTextView.setVisibility(View.GONE);
|
||||
progressBar.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
protected void download(IndexItem indexItem, DownloadResourceGroup parentOptional) {
|
||||
boolean handled = false;
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
package net.osmand.plus.download.ui;
|
||||
|
||||
import android.content.res.TypedArray;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.view.ContextThemeWrapper;
|
||||
import android.support.v7.widget.SearchView;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
|
@ -23,11 +25,19 @@ import android.widget.RelativeLayout;
|
|||
import android.widget.RelativeLayout.LayoutParams;
|
||||
|
||||
import net.osmand.Collator;
|
||||
import net.osmand.CollatorStringMatcher;
|
||||
import net.osmand.OsmAndCollator;
|
||||
import net.osmand.ResultMatcher;
|
||||
import net.osmand.binary.BinaryMapDataObject;
|
||||
import net.osmand.binary.BinaryMapIndexReader;
|
||||
import net.osmand.binary.BinaryMapIndexReader.SearchRequest;
|
||||
import net.osmand.data.Amenity;
|
||||
import net.osmand.map.OsmandRegions;
|
||||
import net.osmand.map.WorldRegion;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.OsmandSettings;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.download.CityItem;
|
||||
import net.osmand.plus.download.DownloadActivity;
|
||||
import net.osmand.plus.download.DownloadActivity.BannerAndDownloadFreeVersion;
|
||||
import net.osmand.plus.download.DownloadActivityType;
|
||||
|
@ -36,9 +46,15 @@ import net.osmand.plus.download.DownloadResourceGroup;
|
|||
import net.osmand.plus.download.DownloadResourceGroup.DownloadResourceGroupType;
|
||||
import net.osmand.plus.download.DownloadResources;
|
||||
import net.osmand.plus.download.IndexItem;
|
||||
import net.osmand.search.core.SearchPhrase;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedList;
|
||||
|
@ -196,7 +212,9 @@ public class SearchDialogFragment extends DialogFragment implements DownloadEven
|
|||
|
||||
public void updateSearchText(String searchText) {
|
||||
this.searchText = searchText;
|
||||
listAdapter.getFilter().filter(searchText);
|
||||
SearchListAdapter.SearchIndexFilter filter = (SearchListAdapter.SearchIndexFilter) listAdapter.getFilter();
|
||||
filter.cancelFilter();
|
||||
filter.filter(searchText);
|
||||
}
|
||||
|
||||
private OsmandApplication getMyApplication() {
|
||||
|
@ -234,12 +252,14 @@ public class SearchDialogFragment extends DialogFragment implements DownloadEven
|
|||
private class SearchListAdapter extends BaseAdapter implements Filterable {
|
||||
|
||||
private SearchIndexFilter mFilter;
|
||||
private OsmandRegions osmandRegions;
|
||||
|
||||
private List<Object> items = new LinkedList<>();
|
||||
private DownloadActivity ctx;
|
||||
|
||||
public SearchListAdapter(DownloadActivity ctx) {
|
||||
this.ctx = ctx;
|
||||
this.osmandRegions = ctx.getMyApplication().getRegions();
|
||||
TypedArray ta = ctx.getTheme().obtainStyledAttributes(new int[]{android.R.attr.textColorPrimary});
|
||||
ta.recycle();
|
||||
}
|
||||
|
@ -267,7 +287,7 @@ public class SearchDialogFragment extends DialogFragment implements DownloadEven
|
|||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
Object obj = items.get(position);
|
||||
if (obj instanceof IndexItem) {
|
||||
if (obj instanceof IndexItem || obj instanceof CityItem) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
|
@ -282,9 +302,8 @@ public class SearchDialogFragment extends DialogFragment implements DownloadEven
|
|||
@Override
|
||||
public View getView(final int position, View convertView, ViewGroup parent) {
|
||||
final Object obj = items.get(position);
|
||||
if (obj instanceof IndexItem) {
|
||||
if (obj instanceof IndexItem || obj instanceof CityItem) {
|
||||
|
||||
IndexItem item = (IndexItem) obj;
|
||||
ItemViewHolder viewHolder;
|
||||
if (convertView != null && convertView.getTag() instanceof ItemViewHolder) {
|
||||
viewHolder = (ItemViewHolder) convertView.getTag();
|
||||
|
@ -295,8 +314,17 @@ public class SearchDialogFragment extends DialogFragment implements DownloadEven
|
|||
viewHolder.setShowRemoteDate(true);
|
||||
convertView.setTag(viewHolder);
|
||||
}
|
||||
if (obj instanceof IndexItem) {
|
||||
IndexItem item = (IndexItem) obj;
|
||||
viewHolder.setShowTypeInDesc(true);
|
||||
viewHolder.bindIndexItem(item);
|
||||
} else {
|
||||
CityItem item = (CityItem) obj;
|
||||
viewHolder.bindIndexItem(item);
|
||||
if (item.getIndexItem() == null) {
|
||||
new IndexItemResolverTask(viewHolder, item).execute();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
DownloadResourceGroup group = (DownloadResourceGroup) obj;
|
||||
DownloadGroupViewHolder viewHolder;
|
||||
|
@ -327,14 +355,64 @@ public class SearchDialogFragment extends DialogFragment implements DownloadEven
|
|||
return mFilter;
|
||||
}
|
||||
|
||||
class IndexItemResolverTask extends AsyncTask<Void, Void, IndexItem> {
|
||||
private final WeakReference<ItemViewHolder> viewHolderReference;
|
||||
private final CityItem cityItem;
|
||||
|
||||
public IndexItemResolverTask(ItemViewHolder viewHolder, CityItem cityItem) {
|
||||
this.viewHolderReference = new WeakReference<>(viewHolder);
|
||||
this.cityItem = cityItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IndexItem doInBackground(Void... params) {
|
||||
Amenity amenity = cityItem.getAmenity();
|
||||
BinaryMapDataObject o = osmandRegions.findBinaryMapDataObject(amenity.getLocation());
|
||||
if (o != null) {
|
||||
String selectedFullName = osmandRegions.getFullName(o);
|
||||
WorldRegion downloadRegion = osmandRegions.getRegionData(selectedFullName);
|
||||
List<IndexItem> indexItems = ctx.getDownloadThread().getIndexes().getIndexItems(downloadRegion);
|
||||
for (IndexItem item : indexItems) {
|
||||
if (item.getType() == DownloadActivityType.NORMAL_FILE) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(IndexItem indexItem) {
|
||||
if (isCancelled()) {
|
||||
return;
|
||||
}
|
||||
ItemViewHolder viewHolder = viewHolderReference.get();
|
||||
if (viewHolder != null) {
|
||||
if (indexItem != null) {
|
||||
cityItem.setIndexItem(indexItem);
|
||||
viewHolder.bindIndexItem(indexItem, cityItem.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final class SearchIndexFilter extends Filter {
|
||||
|
||||
private OsmandRegions osmandRegions;
|
||||
private final int searchCityLimit = 10000;
|
||||
private final List<String> citySubTypes = Arrays.asList("city", "town");
|
||||
private SearchRequest<Amenity> searchCityRequest;
|
||||
|
||||
public SearchIndexFilter() {
|
||||
this.osmandRegions = ctx.getMyApplication().getRegions();
|
||||
}
|
||||
|
||||
public void cancelFilter() {
|
||||
if (searchCityRequest != null) {
|
||||
searchCityRequest.setInterrupted(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void processGroup(DownloadResourceGroup group, List<Object> filter, List<List<String>> conds) {
|
||||
String name = null;
|
||||
if (group.getRegion() != null && group.getRegion().getRegionSearchText() != null) {
|
||||
|
@ -387,6 +465,63 @@ public class SearchDialogFragment extends DialogFragment implements DownloadEven
|
|||
}
|
||||
}
|
||||
|
||||
public List<CityItem> searchCities(final OsmandApplication app, final String text) throws IOException {
|
||||
IndexItem worldBaseMapItem = app.getDownloadThread().getIndexes().getWorldBaseMapItem();
|
||||
if (worldBaseMapItem == null || !worldBaseMapItem.isDownloaded()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
File obf = worldBaseMapItem.getTargetFile(app);
|
||||
final BinaryMapIndexReader baseMapReader = new BinaryMapIndexReader(new RandomAccessFile(obf, "r"), obf);
|
||||
final SearchPhrase.NameStringMatcher nm = new SearchPhrase.NameStringMatcher(
|
||||
text, CollatorStringMatcher.StringMatcherMode.CHECK_STARTS_FROM_SPACE);
|
||||
final String lang = app.getSettings().MAP_PREFERRED_LOCALE.get();
|
||||
final boolean translit = app.getSettings().MAP_TRANSLITERATE_NAMES.get();
|
||||
final List<Amenity> amenities = new ArrayList<>();
|
||||
SearchRequest<Amenity> request = BinaryMapIndexReader.buildSearchPoiRequest(
|
||||
0, 0,
|
||||
text,
|
||||
Integer.MIN_VALUE, Integer.MAX_VALUE,
|
||||
Integer.MIN_VALUE, Integer.MAX_VALUE,
|
||||
new ResultMatcher<Amenity>() {
|
||||
int count = 0;
|
||||
|
||||
@Override
|
||||
public boolean publish(Amenity amenity) {
|
||||
if (count++ > searchCityLimit) {
|
||||
return false;
|
||||
}
|
||||
List<String> otherNames = amenity.getAllNames(true);
|
||||
String localeName = amenity.getName(lang, translit);
|
||||
String subType = amenity.getSubType();
|
||||
if (!citySubTypes.contains(subType)
|
||||
|| (!nm.matches(localeName) && !nm.matches(otherNames))) {
|
||||
return false;
|
||||
}
|
||||
amenities.add(amenity);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return count > searchCityLimit;
|
||||
}
|
||||
});
|
||||
|
||||
searchCityRequest = request;
|
||||
baseMapReader.searchPoiByName(request);
|
||||
try {
|
||||
baseMapReader.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
List<CityItem> items = new ArrayList<>();
|
||||
for (Amenity amenity : amenities) {
|
||||
items.add(new CityItem(amenity.getName(), amenity, null));
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FilterResults performFiltering(CharSequence constraint) {
|
||||
DownloadResources root = ctx.getDownloadThread().getIndexes();
|
||||
|
@ -396,6 +531,15 @@ public class SearchDialogFragment extends DialogFragment implements DownloadEven
|
|||
results.values = new ArrayList<>();
|
||||
results.count = 0;
|
||||
} else {
|
||||
List<Object> filter = new ArrayList<>();
|
||||
if (constraint.length() > 3) {
|
||||
try {
|
||||
filter.addAll(searchCities(getMyApplication(), constraint.toString()));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
String[] ors = constraint.toString().split(",");
|
||||
List<List<String>> conds = new ArrayList<>();
|
||||
for (String or : ors) {
|
||||
|
@ -411,7 +555,6 @@ public class SearchDialogFragment extends DialogFragment implements DownloadEven
|
|||
}
|
||||
}
|
||||
|
||||
List<Object> filter = new ArrayList<>();
|
||||
processGroup(root, filter, conds);
|
||||
|
||||
final Collator collator = OsmAndCollator.primaryCollator();
|
||||
|
@ -422,13 +565,27 @@ public class SearchDialogFragment extends DialogFragment implements DownloadEven
|
|||
String str2;
|
||||
if (obj1 instanceof DownloadResourceGroup) {
|
||||
str1 = ((DownloadResourceGroup) obj1).getName(ctx);
|
||||
} else {
|
||||
} else if (obj1 instanceof IndexItem) {
|
||||
str1 = ((IndexItem) obj1).getVisibleName(getMyApplication(), osmandRegions, false);
|
||||
} else {
|
||||
Amenity a = ((CityItem) obj1).getAmenity();
|
||||
if ("city".equals(a.getSubType())) {
|
||||
str1 = "!" + ((CityItem) obj1).getName();
|
||||
} else {
|
||||
str1 = ((CityItem) obj1).getName();
|
||||
}
|
||||
}
|
||||
if (obj2 instanceof DownloadResourceGroup) {
|
||||
str2 = ((DownloadResourceGroup) obj2).getName(ctx);
|
||||
} else {
|
||||
} else if (obj2 instanceof IndexItem) {
|
||||
str2 = ((IndexItem) obj2).getVisibleName(getMyApplication(), osmandRegions, false);
|
||||
} else {
|
||||
Amenity a = ((CityItem) obj2).getAmenity();
|
||||
if ("city".equals(a.getSubType())) {
|
||||
str2 = "!" + ((CityItem) obj2).getName();
|
||||
} else {
|
||||
str2 = ((CityItem) obj2).getName();
|
||||
}
|
||||
}
|
||||
return collator.compare(str1, str2);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue