This commit is contained in:
Alexey Kulish 2016-11-06 17:34:59 +03:00
parent 700e77c9c5
commit 5f0add31a3
4 changed files with 282 additions and 26 deletions

View file

@ -1,8 +1,18 @@
package net.osmand.map; package net.osmand.map;
import gnu.trove.iterator.TIntObjectIterator; import net.osmand.PlatformUtil;
import gnu.trove.list.array.TIntArrayList; 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.File;
import java.io.IOException; import java.io.IOException;
@ -21,19 +31,8 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.TreeSet; import java.util.TreeSet;
import net.osmand.PlatformUtil; import gnu.trove.iterator.TIntObjectIterator;
import net.osmand.ResultMatcher; import gnu.trove.list.array.TIntArrayList;
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;
public class OsmandRegions { 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;
}
} }

View 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;
}
}

View file

@ -25,6 +25,7 @@ import net.osmand.plus.R;
import net.osmand.plus.Version; import net.osmand.plus.Version;
import net.osmand.plus.activities.LocalIndexHelper.LocalIndexType; import net.osmand.plus.activities.LocalIndexHelper.LocalIndexType;
import net.osmand.plus.activities.LocalIndexInfo; import net.osmand.plus.activities.LocalIndexInfo;
import net.osmand.plus.download.CityItem;
import net.osmand.plus.download.DownloadActivity; import net.osmand.plus.download.DownloadActivity;
import net.osmand.plus.download.DownloadActivityType; import net.osmand.plus.download.DownloadActivityType;
import net.osmand.plus.download.DownloadResourceGroup; 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.download.ui.LocalIndexesFragment.LocalIndexOperationTask;
import net.osmand.plus.helpers.FileNameTranslationHelper; import net.osmand.plus.helpers.FileNameTranslationHelper;
import net.osmand.plus.srtmplugin.SRTMPlugin; import net.osmand.plus.srtmplugin.SRTMPlugin;
import net.osmand.util.Algorithms;
import java.io.File; import java.io.File;
import java.text.DateFormat; import java.text.DateFormat;
@ -130,6 +132,10 @@ public class ItemViewHolder {
} }
public void bindIndexItem(final IndexItem indexItem) { public void bindIndexItem(final IndexItem indexItem) {
bindIndexItem(indexItem, null);
}
public void bindIndexItem(final IndexItem indexItem, final String cityName) {
initAppStatusVariables(); initAppStatusVariables();
boolean isDownloading = context.getDownloadThread().isDownloading(indexItem); boolean isDownloading = context.getDownloadThread().isDownloading(indexItem);
int progress = -1; int progress = -1;
@ -138,11 +144,14 @@ public class ItemViewHolder {
} }
boolean disabled = checkDisabledAndClickAction(indexItem); boolean disabled = checkDisabledAndClickAction(indexItem);
/// name and left item /// name and left item
String name;
if(showTypeInName) { if(showTypeInName) {
nameTextView.setText(indexItem.getType().getString(context)); name = indexItem.getType().getString(context);
} else { } 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) { if(!disabled) {
nameTextView.setTextColor(textColorPrimary); nameTextView.setTextColor(textColorPrimary);
} else { } 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) { protected void download(IndexItem indexItem, DownloadResourceGroup parentOptional) {
boolean handled = false; boolean handled = false;

View file

@ -1,12 +1,14 @@
package net.osmand.plus.download.ui; package net.osmand.plus.download.ui;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.app.DialogFragment; import android.support.v4.app.DialogFragment;
import android.support.v4.content.ContextCompat; import android.support.v4.content.ContextCompat;
import android.support.v7.view.ContextThemeWrapper; import android.support.v7.view.ContextThemeWrapper;
import android.support.v7.widget.SearchView; import android.support.v7.widget.SearchView;
import android.support.v7.widget.Toolbar; import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.util.TypedValue; import android.util.TypedValue;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
@ -23,11 +25,19 @@ import android.widget.RelativeLayout;
import android.widget.RelativeLayout.LayoutParams; import android.widget.RelativeLayout.LayoutParams;
import net.osmand.Collator; import net.osmand.Collator;
import net.osmand.CollatorStringMatcher;
import net.osmand.OsmAndCollator; 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.OsmandRegions;
import net.osmand.map.WorldRegion;
import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandSettings; import net.osmand.plus.OsmandSettings;
import net.osmand.plus.R; import net.osmand.plus.R;
import net.osmand.plus.download.CityItem;
import net.osmand.plus.download.DownloadActivity; import net.osmand.plus.download.DownloadActivity;
import net.osmand.plus.download.DownloadActivity.BannerAndDownloadFreeVersion; import net.osmand.plus.download.DownloadActivity.BannerAndDownloadFreeVersion;
import net.osmand.plus.download.DownloadActivityType; 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.DownloadResourceGroup.DownloadResourceGroupType;
import net.osmand.plus.download.DownloadResources; import net.osmand.plus.download.DownloadResources;
import net.osmand.plus.download.IndexItem; import net.osmand.plus.download.IndexItem;
import net.osmand.search.core.SearchPhrase;
import net.osmand.util.Algorithms; 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.ArrayList;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.LinkedList; import java.util.LinkedList;
@ -196,7 +212,9 @@ public class SearchDialogFragment extends DialogFragment implements DownloadEven
public void updateSearchText(String searchText) { public void updateSearchText(String searchText) {
this.searchText = searchText; this.searchText = searchText;
listAdapter.getFilter().filter(searchText); SearchListAdapter.SearchIndexFilter filter = (SearchListAdapter.SearchIndexFilter) listAdapter.getFilter();
filter.cancelFilter();
filter.filter(searchText);
} }
private OsmandApplication getMyApplication() { private OsmandApplication getMyApplication() {
@ -234,12 +252,14 @@ public class SearchDialogFragment extends DialogFragment implements DownloadEven
private class SearchListAdapter extends BaseAdapter implements Filterable { private class SearchListAdapter extends BaseAdapter implements Filterable {
private SearchIndexFilter mFilter; private SearchIndexFilter mFilter;
private OsmandRegions osmandRegions;
private List<Object> items = new LinkedList<>(); private List<Object> items = new LinkedList<>();
private DownloadActivity ctx; private DownloadActivity ctx;
public SearchListAdapter(DownloadActivity ctx) { public SearchListAdapter(DownloadActivity ctx) {
this.ctx = ctx; this.ctx = ctx;
this.osmandRegions = ctx.getMyApplication().getRegions();
TypedArray ta = ctx.getTheme().obtainStyledAttributes(new int[]{android.R.attr.textColorPrimary}); TypedArray ta = ctx.getTheme().obtainStyledAttributes(new int[]{android.R.attr.textColorPrimary});
ta.recycle(); ta.recycle();
} }
@ -267,7 +287,7 @@ public class SearchDialogFragment extends DialogFragment implements DownloadEven
@Override @Override
public int getItemViewType(int position) { public int getItemViewType(int position) {
Object obj = items.get(position); Object obj = items.get(position);
if (obj instanceof IndexItem) { if (obj instanceof IndexItem || obj instanceof CityItem) {
return 0; return 0;
} else { } else {
return 1; return 1;
@ -282,9 +302,8 @@ public class SearchDialogFragment extends DialogFragment implements DownloadEven
@Override @Override
public View getView(final int position, View convertView, ViewGroup parent) { public View getView(final int position, View convertView, ViewGroup parent) {
final Object obj = items.get(position); final Object obj = items.get(position);
if (obj instanceof IndexItem) { if (obj instanceof IndexItem || obj instanceof CityItem) {
IndexItem item = (IndexItem) obj;
ItemViewHolder viewHolder; ItemViewHolder viewHolder;
if (convertView != null && convertView.getTag() instanceof ItemViewHolder) { if (convertView != null && convertView.getTag() instanceof ItemViewHolder) {
viewHolder = (ItemViewHolder) convertView.getTag(); viewHolder = (ItemViewHolder) convertView.getTag();
@ -295,8 +314,17 @@ public class SearchDialogFragment extends DialogFragment implements DownloadEven
viewHolder.setShowRemoteDate(true); viewHolder.setShowRemoteDate(true);
convertView.setTag(viewHolder); convertView.setTag(viewHolder);
} }
viewHolder.setShowTypeInDesc(true); if (obj instanceof IndexItem) {
viewHolder.bindIndexItem(item); 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 { } else {
DownloadResourceGroup group = (DownloadResourceGroup) obj; DownloadResourceGroup group = (DownloadResourceGroup) obj;
DownloadGroupViewHolder viewHolder; DownloadGroupViewHolder viewHolder;
@ -327,14 +355,64 @@ public class SearchDialogFragment extends DialogFragment implements DownloadEven
return mFilter; 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 final class SearchIndexFilter extends Filter {
private OsmandRegions osmandRegions; private OsmandRegions osmandRegions;
private final int searchCityLimit = 10000;
private final List<String> citySubTypes = Arrays.asList("city", "town");
private SearchRequest<Amenity> searchCityRequest;
public SearchIndexFilter() { public SearchIndexFilter() {
this.osmandRegions = ctx.getMyApplication().getRegions(); 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) { private void processGroup(DownloadResourceGroup group, List<Object> filter, List<List<String>> conds) {
String name = null; String name = null;
if (group.getRegion() != null && group.getRegion().getRegionSearchText() != 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 @Override
protected FilterResults performFiltering(CharSequence constraint) { protected FilterResults performFiltering(CharSequence constraint) {
DownloadResources root = ctx.getDownloadThread().getIndexes(); DownloadResources root = ctx.getDownloadThread().getIndexes();
@ -396,6 +531,15 @@ public class SearchDialogFragment extends DialogFragment implements DownloadEven
results.values = new ArrayList<>(); results.values = new ArrayList<>();
results.count = 0; results.count = 0;
} else { } 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(","); String[] ors = constraint.toString().split(",");
List<List<String>> conds = new ArrayList<>(); List<List<String>> conds = new ArrayList<>();
for (String or : ors) { for (String or : ors) {
@ -411,7 +555,6 @@ public class SearchDialogFragment extends DialogFragment implements DownloadEven
} }
} }
List<Object> filter = new ArrayList<>();
processGroup(root, filter, conds); processGroup(root, filter, conds);
final Collator collator = OsmAndCollator.primaryCollator(); final Collator collator = OsmAndCollator.primaryCollator();
@ -422,13 +565,27 @@ public class SearchDialogFragment extends DialogFragment implements DownloadEven
String str2; String str2;
if (obj1 instanceof DownloadResourceGroup) { if (obj1 instanceof DownloadResourceGroup) {
str1 = ((DownloadResourceGroup) obj1).getName(ctx); str1 = ((DownloadResourceGroup) obj1).getName(ctx);
} else { } else if (obj1 instanceof IndexItem) {
str1 = ((IndexItem) obj1).getVisibleName(getMyApplication(), osmandRegions, false); 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) { if (obj2 instanceof DownloadResourceGroup) {
str2 = ((DownloadResourceGroup) obj2).getName(ctx); str2 = ((DownloadResourceGroup) obj2).getName(ctx);
} else { } else if (obj2 instanceof IndexItem) {
str2 = ((IndexItem) obj2).getVisibleName(getMyApplication(), osmandRegions, false); 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); return collator.compare(str1, str2);
} }