Add POI multiselection

This commit is contained in:
Roman Inflianskas 2016-04-20 20:03:11 +03:00
parent cd8afc8f9b
commit cf0f5e1121
9 changed files with 190 additions and 123 deletions

View file

@ -38,7 +38,9 @@ import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
@ -48,6 +50,7 @@ import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeSet;
public class OsmandSettings {
@ -2319,9 +2322,21 @@ public class OsmandSettings {
return settingsAPI.edit(globalPreferences).putString(LAST_SEARCHED_INTERSECTED_STREET, street).commit();
}
// Avoid using this property, probably you need to use PoiFiltersHelper.getSelectedPoiFilters()
public final OsmandPreference<String> SELECTED_POI_FILTER_FOR_MAP = new StringPreference("selected_poi_filter_for_map", null).makeGlobal().cache();
public Set<String> getSelectedPoiFilters() {
Set<String> result = new LinkedHashSet<>();
String filtersId = SELECTED_POI_FILTER_FOR_MAP.get();
if (filtersId != null)
Collections.addAll(result, filtersId.split(","));
return result;
}
public void setSelectedPoiFilters(final Set<String> poiFilters) {
SELECTED_POI_FILTER_FOR_MAP.set(android.text.TextUtils.join(",", poiFilters));
}
public static final String VOICE_PROVIDER_NOT_USE = "VOICE_PROVIDER_NOT_USE";
public static final String[] TTS_AVAILABLE_VOICES = new String[]{

View file

@ -4,6 +4,7 @@ package net.osmand.plus.activities;
import android.content.DialogInterface;
import android.content.Intent;
import android.support.v7.app.AlertDialog;
import android.widget.ArrayAdapter;
import android.widget.ListAdapter;
import android.widget.Toast;
@ -53,6 +54,7 @@ import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
/**
* Object is responsible to maintain layers using by map activity
@ -257,7 +259,7 @@ public class MapActivityLayers {
}
public AlertDialog selectPOIFilterLayer(final OsmandMapTileView mapView, final PoiUIFilter[] selected) {
public AlertDialog selectPOIFilterLayer(final OsmandMapTileView mapView) {
OsmandApplication app = getApplication();
final PoiFiltersHelper poiFilters = app.getPoiFilters();
final ContextMenuAdapter adapter = new ContextMenuAdapter();
@ -274,36 +276,43 @@ public class MapActivityLayers {
ListAdapter listAdapter = adapter.createListAdapter(activity, app.getSettings().isLightContent());
builder.setAdapter(listAdapter, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
PoiUIFilter pf = list.get(which);
public void onClick(DialogInterface dialog, int position) {
PoiUIFilter pf = list.get(position);
String filterId = pf.getFilterId();
if (filterId.equals(PoiUIFilter.CUSTOM_FILTER_ID)) {
Intent search = new Intent(activity, SearchActivity.class);
search.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
activity.getMyApplication().getSettings().SEARCH_TAB.set(SearchActivity.POI_TAB_INDEX);
activity.startActivity(search);
} else {
pf = poiFilters.getFilterById(filterId);
if (pf != null) {
pf.setFilterByName(pf.getSavedFilterByName());
}
getApplication().getSettings().SELECTED_POI_FILTER_FOR_MAP.set(filterId);
mapView.refreshMap();
if (selected != null && selected.length > 0) {
selected[0] = pf;
}
}
}
});
builder.setNegativeButton(R.string.shared_string_cancel, null);
builder.setTitle(R.string.show_poi_over_map)
.setPositiveButton(R.string.shared_string_ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
mapView.refreshMap();
}
})
.setNegativeButton(R.string.shared_string_cancel, null);
return builder.show();
}
private void addFilterToList(final ContextMenuAdapter adapter, final List<PoiUIFilter> list, PoiUIFilter f) {
private void addFilterToList(final ContextMenuAdapter adapter, final List<PoiUIFilter> list, final PoiUIFilter f) {
list.add(f);
ContextMenuItem.ItemBuilder builder = new ContextMenuItem.ItemBuilder();
builder.setListener(new ContextMenuAdapter.ItemClickListener() {
@Override
public boolean onContextMenuClick(ArrayAdapter<ContextMenuItem> adapter, int itemId, int position, boolean isChecked) {
if (isChecked)
getApplication().getPoiFilters().addSelectedPoiFilter(f);
else
getApplication().getPoiFilters().removeSelectedPoiFilter(f);
return true;
}
});
builder.setTitle(f.getName());
builder.setSelected(getApplication().getPoiFilters().isPoiFilterSelected(f));
if (RenderingIcons.containsBigIcon(f.getIconId())) {
builder.setIcon(RenderingIcons.getBigIconResourceId(f.getIconId()));
} else {

View file

@ -157,7 +157,7 @@ public class SearchPOIActivity extends OsmandListActivity implements OsmAndCompa
public boolean onMenuItemClick(MenuItem item) {
OsmandSettings settings = app.getSettings();
filter.setFilterByName(searchFilter.getText().toString().trim());
settings.SELECTED_POI_FILTER_FOR_MAP.set(filter.getFilterId());
app.getPoiFilters().addSelectedPoiFilter(filter);
if (location != null) {
settings.setMapLocationToShow(location.getLatitude(), location.getLongitude(), 15);
}

View file

@ -28,6 +28,7 @@ import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.activities.PluginActivity;
import net.osmand.plus.activities.SettingsActivity;
import net.osmand.plus.activities.TransportRouteHelper;
import net.osmand.plus.poi.PoiFiltersHelper;
import net.osmand.plus.poi.PoiUIFilter;
import net.osmand.plus.rastermaps.OsmandRasterMapsPlugin;
import net.osmand.plus.render.RendererRegistry;
@ -125,17 +126,18 @@ public class ConfigureMapMenu {
@Override
public boolean onContextMenuClick(final ArrayAdapter<ContextMenuItem> adapter, int itemId, final int pos, boolean isChecked) {
final OsmandSettings settings = ma.getMyApplication().getSettings();
final PoiFiltersHelper pfh = ma.getMyApplication().getPoiFilters();
final ContextMenuItem item = cm.getItem(pos);
if (item.getSelected() != null) {
item.setColorRes(isChecked ? R.color.osmand_orange : ContextMenuItem.INVALID_ID);
adapter.notifyDataSetChanged();
}
if (itemId == R.string.layer_poi) {
settings.SELECTED_POI_FILTER_FOR_MAP.set(null);
pfh.clearSelectedPoiFilters();
if (isChecked) {
selectPOILayer(adapter, adapter.getItem(pos));
} else {
adapter.getItem(pos).setDescription(POIMapLayer.getSelectedPoiName(ma.getMyApplication()));
adapter.getItem(pos).setDescription(pfh.getSelectedPoiFiltersName());
}
} else if (itemId == R.string.layer_amenity_label) {
settings.SHOW_POI_LABEL.set(isChecked);
@ -184,17 +186,15 @@ public class ConfigureMapMenu {
protected void selectPOILayer(final ArrayAdapter<ContextMenuItem> adapter,
final ContextMenuItem item) {
final PoiUIFilter[] selected = new PoiUIFilter[1];
AlertDialog dlg = ma.getMapLayers().selectPOIFilterLayer(ma.getMapView(), selected);
AlertDialog dlg = ma.getMapLayers().selectPOIFilterLayer(ma.getMapView());
dlg.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
OsmandApplication myApplication = ma.getMyApplication();
boolean selected = myApplication.getSettings()
.SELECTED_POI_FILTER_FOR_MAP.get() != null;
PoiFiltersHelper pf = ma.getMyApplication().getPoiFilters();
boolean selected = pf.isShowingAnyPoi();
item.setSelected(selected);
item.setDescription(POIMapLayer.getSelectedPoiName(myApplication));
item.setDescription(pf.getSelectedPoiFiltersName());
item.setColorRes(selected ? R.color.osmand_orange : ContextMenuItem.INVALID_ID);
adapter.notifyDataSetChanged();
}
@ -217,11 +217,11 @@ public class ConfigureMapMenu {
.setColor(selected ? R.color.osmand_orange : ContextMenuItem.INVALID_ID)
.setIcon(R.drawable.ic_action_fav_dark)
.setListener(l).createItem());
selected = settings.SELECTED_POI_FILTER_FOR_MAP.get() != null;
selected = app.getPoiFilters().isShowingAnyPoi();
adapter.addItem(new ContextMenuItem.ItemBuilder()
.setTitleId(R.string.layer_poi, activity)
.setSelected(settings.SELECTED_POI_FILTER_FOR_MAP.get() != null)
.setDescription(POIMapLayer.getSelectedPoiName(app))
.setSelected(selected)
.setDescription(app.getPoiFilters().getSelectedPoiFiltersName())
.setColor(selected ? R.color.osmand_orange : ContextMenuItem.INVALID_ID)
.setIcon(R.drawable.ic_action_info_dark)
.setSecondaryIcon(R.drawable.ic_action_additional_option)

View file

@ -603,8 +603,7 @@ public class WaypointDialogHelper {
if (type == WaypointHelper.POI) {
v = ctx.getLayoutInflater().inflate(R.layout.drawer_list_radius_ex, null);
AndroidUtils.setTextPrimaryColor(mapActivity, (TextView) v.findViewById(R.id.titleEx), nightMode);
String descEx = waypointHelper.getPoiFilter() == null ? ctx.getString(R.string.poi) : waypointHelper
.getPoiFilter().getName();
String descEx = app.getPoiFilters().isShowingAnyPoi() ? ctx.getString(R.string.poi) : app.getPoiFilters().getSelectedPoiFiltersName();
((TextView) v.findViewById(R.id.title)).setText(ctx.getString(R.string.search_radius_proximity) + ":");
((TextView) v.findViewById(R.id.titleEx)).setText(ctx.getString(R.string.shared_string_type) + ":");
final TextView radiusEx = (TextView) v.findViewById(R.id.descriptionEx);
@ -615,8 +614,7 @@ public class WaypointDialogHelper {
running[0] = position;
thisAdapter.notifyDataSetInvalidated();
MapActivity map = (MapActivity) ctx;
final PoiUIFilter[] selected = new PoiUIFilter[1];
AlertDialog dlg = map.getMapLayers().selectPOIFilterLayer(map.getMapView(), selected);
AlertDialog dlg = map.getMapLayers().selectPOIFilterLayer(map.getMapView());
dlg.setOnDismissListener(new OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
@ -688,15 +686,14 @@ public class WaypointDialogHelper {
private void selectPoi(final int[] running, final ArrayAdapter<Object> listAdapter, final int type,
final boolean enable, Activity ctx) {
if (ctx instanceof MapActivity &&
!PoiUIFilter.CUSTOM_FILTER_ID.equals(app.getSettings().SELECTED_POI_FILTER_FOR_MAP.get())) {
!app.getPoiFilters().isPoiFilterSelected(PoiUIFilter.CUSTOM_FILTER_ID)) {
MapActivity map = (MapActivity) ctx;
final PoiUIFilter[] selected = new PoiUIFilter[1];
AlertDialog dlg = map.getMapLayers().selectPOIFilterLayer(map.getMapView(), selected);
AlertDialog dlg = map.getMapLayers().selectPOIFilterLayer(map.getMapView());
dlg.setOnDismissListener(new OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
if (selected != null) {
if (app.getPoiFilters().isShowingAnyPoi()) {
enableType(running, listAdapter, type, enable);
}
}

View file

@ -8,6 +8,7 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import net.osmand.FloatMath;
@ -538,10 +539,11 @@ public class WaypointHelper {
protected void calculatePoi(RouteCalculationResult route, List<LocationPointWrapper> locationPoints) {
PoiUIFilter pf = getPoiFilter();
if (pf != null) {
if (app.getPoiFilters().isShowingAnyPoi()) {
final List<Location> locs = route.getImmutableAllLocations();
List<Amenity> amenities = pf.searchAmenitiesOnThePath(locs, poiSearchDeviationRadius);
List<Amenity> amenities = new ArrayList<>();
for (PoiUIFilter pf : app.getPoiFilters().getSelectedPoiFilters())
amenities.addAll(pf.searchAmenitiesOnThePath(locs, poiSearchDeviationRadius));
for (Amenity a : amenities) {
AmenityRoutePoint rp = a.getRoutePoint();
int i = locs.indexOf(rp.pointA);
@ -607,8 +609,8 @@ public class WaypointHelper {
///
public PoiUIFilter getPoiFilter() {
return app.getPoiFilters().getFilterById(app.getSettings().SELECTED_POI_FILTER_FOR_MAP.get());
public Set<PoiUIFilter> getPoiFilters() {
return app.getPoiFilters().getSelectedPoiFilters();
}
public boolean showPOI() {

View file

@ -1,30 +1,33 @@
package net.osmand.plus.poi;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import net.osmand.access.AccessibilityPlugin;
import net.osmand.osm.AbstractPoiType;
import net.osmand.osm.MapPoiTypes;
import net.osmand.osm.PoiCategory;
import net.osmand.osm.PoiFilter;
import net.osmand.osm.PoiType;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.R;
import net.osmand.plus.api.SQLiteAPI.SQLiteConnection;
import net.osmand.plus.api.SQLiteAPI.SQLiteCursor;
import net.osmand.plus.api.SQLiteAPI.SQLiteStatement;
import net.osmand.util.Algorithms;
import android.support.annotation.NonNull;
import android.util.ArraySet;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
public class PoiFiltersHelper {
private final OsmandApplication application;
@ -36,6 +39,7 @@ public class PoiFiltersHelper {
private PoiUIFilter showAllPOIFilter;
private PoiUIFilter localWikiPoiFilter;
private List<PoiUIFilter> cacheTopStandardFilters;
private Set<PoiUIFilter> selectedPoiFilters = new TreeSet<>();
private static final String UDF_CAR_AID = "car_aid";
private static final String UDF_FOR_TOURISTS = "for_tourists";
@ -80,8 +84,6 @@ public class PoiFiltersHelper {
return searchByNamePOIFilter;
}
public PoiUIFilter getCustomPOIFilter() {
if (customPOIFilter == null){
PoiUIFilter filter = new PoiUIFilter(application.getString(R.string.poi_filter_custom_filter),
@ -163,6 +165,13 @@ public class PoiFiltersHelper {
return null;
}
public List<PoiUIFilter> getFiltersById(String filtersId) {
List<PoiUIFilter> result = new ArrayList<PoiUIFilter>();
for (String filterId : filtersId.split(","))
result.add(getFilterById(filterId));
return result;
}
public void reloadAllPoiFilters() {
showAllPOIFilter = null;
@ -206,7 +215,8 @@ public class PoiFiltersHelper {
// default
MapPoiTypes poiTypes = application.getPoiTypes();
for (PoiFilter t : poiTypes.getTopVisibleFilters()) {
top.add(new PoiUIFilter(t, application, ""));
PoiUIFilter f = new PoiUIFilter(t, application, "");
top.add(f);
}
sortListOfFilters(top);
cacheTopStandardFilters = top;
@ -283,6 +293,52 @@ public class PoiFiltersHelper {
return false;
}
@NonNull
public Set<PoiUIFilter> getSelectedPoiFilters() { return selectedPoiFilters; }
public void addSelectedPoiFilter(PoiUIFilter filter) {
selectedPoiFilters.add(filter);
}
public void addSelectedPoiFilter(String filterId) {
selectedPoiFilters.add(getFilterById(filterId));
}
public void removeSelectedPoiFilter(PoiUIFilter filter) {
selectedPoiFilters.remove(filter);
}
public boolean isShowingAnyPoi() { return !selectedPoiFilters.isEmpty(); }
public void clearSelectedPoiFilters() { selectedPoiFilters.clear(); }
public String getSelectedPoiFiltersName() {
if (!isShowingAnyPoi()) {
return application.getResources().getString(R.string.shared_string_none);
}
List<String> names = new ArrayList<String>();
for (PoiUIFilter filter : selectedPoiFilters)
names.add(filter.getName());
return android.text.TextUtils.join(", ", names);
}
public boolean isPoiFilterSelected(PoiUIFilter filter) {
return selectedPoiFilters.contains(filter);
}
public boolean isPoiFilterSelected(String filterId) {
for (PoiUIFilter filter: selectedPoiFilters)
if (filter.filterId.equals(filterId))
return true;
return false;
}
private void saveCurrentSelections() {
Set<String> filters = new HashSet<>();
for (PoiUIFilter f: selectedPoiFilters)
filters.add(f.filterId);
application.getSettings().setSelectedPoiFilters(filters);
}
public class PoiFilterDbHelper {

View file

@ -33,8 +33,9 @@ import net.osmand.util.MapUtils;
import net.osmand.util.OpeningHoursParser;
import net.osmand.util.OpeningHoursParser.OpeningHours;
import android.content.Context;
import android.support.annotation.NonNull;
public class PoiUIFilter implements SearchPoiTypeFilter {
public class PoiUIFilter implements SearchPoiTypeFilter, Comparable<PoiUIFilter> {
public final static String STD_PREFIX = "std_"; //$NON-NLS-1$
public final static String USER_PREFIX = "user_"; //$NON-NLS-1$
@ -451,7 +452,6 @@ public class PoiUIFilter implements SearchPoiTypeFilter {
return false;
}
public void updateTypesToAccept(AbstractPoiType pt) {
pt.putTypes(acceptedTypes);
if (pt instanceof PoiType && ((PoiType) pt).isAdditional() && ((PoiType) pt).getParentType() != null) {
@ -568,6 +568,13 @@ public class PoiUIFilter implements SearchPoiTypeFilter {
return acceptedTypes.isEmpty();
}
@Override
public int compareTo(@NonNull PoiUIFilter another) {
if (another.filterId.equals(this.filterId))
return 0;
else
return this.name.compareTo(another.name);
}
public interface AmenityNameFilter {

View file

@ -83,24 +83,20 @@ public class POIMapLayer extends OsmandMapLayer implements ContextMenuLayer.ICon
private OsmandMapTileView view;
private final static int MAXIMUM_SHOW_AMENITIES = 5;
private ResourceManager resourceManager;
private RoutingHelper routingHelper;
private PoiUIFilter filter;
private Set<PoiUIFilter> filters = new TreeSet<>();
private MapTextLayer mapTextLayer;
/// cache for displayed POI
// Work with cache (for map copied from AmenityIndexRepositoryOdb)
private MapLayerData<List<Amenity>> data;
private OsmandSettings settings;
private OsmandApplication app;
public POIMapLayer(final MapActivity activity) {
routingHelper = activity.getRoutingHelper();
routingHelper.addListener(this);
settings = activity.getMyApplication().getSettings();
app = activity.getMyApplication();
data = new OsmandMapLayer.MapLayerData<List<Amenity>>() {
{
@ -120,12 +116,14 @@ public class POIMapLayer extends OsmandMapLayer implements ContextMenuLayer.ICon
@Override
protected List<Amenity> calculateResult(RotatedTileBox tileBox) {
QuadRect latLonBounds = tileBox.getLatLonBounds();
if (filter == null || latLonBounds == null) {
if (filters.isEmpty() || latLonBounds == null) {
return new ArrayList<>();
}
int z = (int) Math.floor(tileBox.getZoom() + Math.log(view.getSettings().MAP_DENSITY.get()) / Math.log(2));
List<Amenity> res = filter.searchAmenities(latLonBounds.top, latLonBounds.left,
List<Amenity> res = new ArrayList<>();
for (PoiUIFilter filter : filters)
res.addAll(filter.searchAmenities(latLonBounds.top, latLonBounds.left,
latLonBounds.bottom, latLonBounds.right, z, new ResultMatcher<Amenity>() {
@Override
@ -137,7 +135,7 @@ public class POIMapLayer extends OsmandMapLayer implements ContextMenuLayer.ICon
public boolean isCancelled() {
return isInterrupted();
}
});
}));
Collections.sort(res, new Comparator<Amenity>() {
@Override
@ -197,7 +195,6 @@ public class POIMapLayer extends OsmandMapLayer implements ContextMenuLayer.ICon
poiBackground = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_white_orange_poi_shield);
poiBackgroundSmall = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_white_orange_poi_shield_small);
resourceManager = view.getApplication().getResourceManager();
mapTextLayer = view.getLayerByClass(MapTextLayer.class);
}
@ -221,14 +218,9 @@ public class POIMapLayer extends OsmandMapLayer implements ContextMenuLayer.ICon
@Override
public void onPrepareBufferImage(Canvas canvas, RotatedTileBox tileBox, DrawSettings settings) {
if (!Algorithms.objectEquals(this.settings.SELECTED_POI_FILTER_FOR_MAP.get(),
filter == null ? null : filter.getFilterId())) {
if (this.settings.SELECTED_POI_FILTER_FOR_MAP.get() == null) {
this.filter = null;
} else {
PoiFiltersHelper pfh = app.getPoiFilters();
this.filter = pfh.getFilterById(this.settings.SELECTED_POI_FILTER_FOR_MAP.get());
}
Set<PoiUIFilter> selectedPoiFilters = app.getPoiFilters().getSelectedPoiFilters();
if (!this.filters.equals(selectedPoiFilters)) {
this.filters = new TreeSet<>(selectedPoiFilters);
data.clearCache();
}
@ -236,7 +228,7 @@ public class POIMapLayer extends OsmandMapLayer implements ContextMenuLayer.ICon
List<Amenity> fullObjects = new ArrayList<>();
List<LatLon> fullObjectsLatLon = new ArrayList<>();
List<LatLon> smallObjectsLatLon = new ArrayList<>();
if (filter != null) {
if (!filters.isEmpty()) {
if (tileBox.getZoom() >= startZoom) {
data.queryNewData(tileBox);
objects = data.getResults();
@ -315,16 +307,6 @@ public class POIMapLayer extends OsmandMapLayer implements ContextMenuLayer.ICon
showText(ctx, app, text, title);
}
public static String getSelectedPoiName(OsmandApplication app) {
PoiFiltersHelper pfh = app.getPoiFilters();
String filterId = app.getSettings().SELECTED_POI_FILTER_FOR_MAP.get();
if (filterId == null) {
return app.getResources().getString(R.string.shared_string_none);
}
PoiUIFilter filter = pfh.getFilterById(filterId);
return filter.getName();
}
static int getResIdFromAttribute(final Context ctx, final int attr) {
if (attr == 0)
return 0;
@ -491,7 +473,6 @@ public class POIMapLayer extends OsmandMapLayer implements ContextMenuLayer.ICon
}
@Override
public String getObjectDescription(Object o) {
if (o instanceof Amenity) {