Merge pull request #8352 from osmandapp/ArrangePoiFilters
Arrange POI Filters
This commit is contained in:
commit
4c21a80c78
17 changed files with 1076 additions and 71 deletions
|
@ -39,6 +39,7 @@ import java.util.HashSet;
|
|||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
|
@ -344,6 +345,14 @@ public class SearchUICore {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setFilterOrders(Map<String, Integer> filterOrders) {
|
||||
for (SearchCoreAPI capi : apis) {
|
||||
if (capi instanceof SearchAmenityTypesAPI) {
|
||||
((SearchAmenityTypesAPI) capi).setFilterOrders(filterOrders);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void registerAPI(SearchCoreAPI api) {
|
||||
apis.add(api);
|
||||
|
|
|
@ -6,10 +6,12 @@ import net.osmand.data.Amenity;
|
|||
|
||||
public interface CustomSearchPoiFilter extends SearchPoiTypeFilter {
|
||||
|
||||
public String getFilterId();
|
||||
|
||||
public String getName();
|
||||
|
||||
|
||||
public Object getIconResource();
|
||||
|
||||
|
||||
public ResultMatcher<Amenity> wrapResultMatcher(final ResultMatcher<Amenity> matcher);
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -633,12 +633,15 @@ public class SearchCoreFactory {
|
|||
|
||||
public static class SearchAmenityTypesAPI extends SearchBaseAPI {
|
||||
|
||||
public final static String STD_POI_FILTER_PREFIX = "std_";
|
||||
|
||||
private Map<String, PoiType> translatedNames = new LinkedHashMap<>();
|
||||
private List<AbstractPoiType> topVisibleFilters;
|
||||
private List<PoiCategory> categories;
|
||||
private List<CustomSearchPoiFilter> customPoiFilters = new ArrayList<>();
|
||||
private TIntArrayList customPoiFiltersPriorites = new TIntArrayList();
|
||||
private MapPoiTypes types;
|
||||
private Map<String, Integer> filterOrders = new HashMap<>();
|
||||
|
||||
public SearchAmenityTypesAPI(MapPoiTypes types) {
|
||||
super(ObjectType.POI_TYPE);
|
||||
|
@ -655,6 +658,10 @@ public class SearchCoreFactory {
|
|||
this.customPoiFiltersPriorites.add(priority);
|
||||
}
|
||||
|
||||
public void setFilterOrders(Map<String, Integer> filterOrders) {
|
||||
this.filterOrders = filterOrders;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean search(SearchPhrase phrase, SearchResultMatcher resultMatcher) throws IOException {
|
||||
if (translatedNames.isEmpty()) {
|
||||
|
@ -666,13 +673,14 @@ public class SearchCoreFactory {
|
|||
List<AbstractPoiType> searchWordTypes = new ArrayList<AbstractPoiType>();
|
||||
NameStringMatcher nm;
|
||||
String unknownSearchPhrase = phrase.getUnknownSearchPhrase();
|
||||
boolean showTopFiltersOnly = !phrase.isUnknownSearchWordPresent();
|
||||
if (phrase.getUnknownSearchWord().length() < unknownSearchPhrase.length()) {
|
||||
nm = new NameStringMatcher(unknownSearchPhrase, StringMatcherMode.CHECK_ONLY_STARTS_WITH_TRIM);
|
||||
} else {
|
||||
nm = new NameStringMatcher(unknownSearchPhrase, StringMatcherMode.CHECK_STARTS_FROM_SPACE);
|
||||
}
|
||||
for (AbstractPoiType pf : topVisibleFilters) {
|
||||
if (!phrase.isUnknownSearchWordPresent()
|
||||
if (showTopFiltersOnly
|
||||
|| nm.matches(pf.getTranslation())
|
||||
|| nm.matches(pf.getEnTranslation())
|
||||
|| nm.matches(pf.getSynonyms())) {
|
||||
|
@ -680,7 +688,7 @@ public class SearchCoreFactory {
|
|||
searchWordTypes.add(pf);
|
||||
}
|
||||
}
|
||||
if (phrase.isUnknownSearchWordPresent()) {
|
||||
if (!showTopFiltersOnly) {
|
||||
for (PoiCategory c : categories) {
|
||||
if (!results.contains(c)
|
||||
&& (nm.matches(c.getTranslation())
|
||||
|
@ -726,28 +734,46 @@ public class SearchCoreFactory {
|
|||
SearchResult res = new SearchResult(phrase);
|
||||
res.localeName = pt.getTranslation();
|
||||
res.object = pt;
|
||||
res.priority = SEARCH_AMENITY_TYPE_PRIORITY;
|
||||
res.priorityDistance = 0;
|
||||
res.objectType = ObjectType.POI_TYPE;
|
||||
res.firstUnknownWordMatches = startMatch.matches(res.localeName);
|
||||
resultMatcher.publish(res);
|
||||
if (showTopFiltersOnly) {
|
||||
String stdFilterId = getStandardFilterId(pt);
|
||||
if (filterOrders.containsKey(stdFilterId)) {
|
||||
res.priority = SEARCH_AMENITY_TYPE_PRIORITY + filterOrders.get(stdFilterId);
|
||||
resultMatcher.publish(res);
|
||||
}
|
||||
} else {
|
||||
res.priority = SEARCH_AMENITY_TYPE_PRIORITY;
|
||||
resultMatcher.publish(res);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < customPoiFilters.size(); i++) {
|
||||
CustomSearchPoiFilter csf = customPoiFilters.get(i);
|
||||
int p = customPoiFiltersPriorites.get(i);
|
||||
if (!phrase.isUnknownSearchWordPresent() || nm.matches(csf.getName())) {
|
||||
SearchResult res = new SearchResult(phrase);
|
||||
res.localeName = csf.getName();
|
||||
res.object = csf;
|
||||
res.priority = SEARCH_AMENITY_TYPE_PRIORITY + p;
|
||||
res.objectType = ObjectType.POI_TYPE;
|
||||
resultMatcher.publish(res);
|
||||
if (showTopFiltersOnly) {
|
||||
if (filterOrders.containsKey(csf.getFilterId())) {
|
||||
res.priority = SEARCH_AMENITY_TYPE_PRIORITY + filterOrders.get(csf.getFilterId());
|
||||
resultMatcher.publish(res);
|
||||
}
|
||||
} else {
|
||||
res.priority = SEARCH_AMENITY_TYPE_PRIORITY + customPoiFiltersPriorites.get(i);
|
||||
resultMatcher.publish(res);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getStandardFilterId(AbstractPoiType poi) {
|
||||
return STD_POI_FILTER_PREFIX + poi.getKeyName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSearchMoreAvailable(SearchPhrase phrase) {
|
||||
return false;
|
||||
|
|
68
OsmAnd/res/layout/order_poi_list_item.xml
Normal file
68
OsmAnd/res/layout/order_poi_list_item.xml
Normal file
|
@ -0,0 +1,68 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:osmand="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="@dimen/bottom_sheet_list_item_height"
|
||||
android:background="?attr/list_background_color"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/selectable_list_item"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="@dimen/content_padding_half"
|
||||
android:paddingBottom="@dimen/content_padding_half"
|
||||
android:orientation="horizontal"
|
||||
tools:background="?android:attr/selectableItemBackground">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/action_icon"
|
||||
style="@style/Widget.AppCompat.ActionButton"
|
||||
android:layout_width="@dimen/standard_icon_size"
|
||||
android:layout_height="@dimen/standard_icon_size"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginLeft="@dimen/content_padding"
|
||||
android:layout_marginRight="@dimen/content_padding"
|
||||
tools:src="@drawable/ic_action_remove"
|
||||
tools:tint="@color/icon_color_default_light" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="@dimen/standard_icon_size"
|
||||
android:layout_height="@dimen/standard_icon_size"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginLeft="@dimen/content_padding"
|
||||
android:layout_marginRight="@dimen/content_padding"
|
||||
tools:src="@drawable/mm_air_transport"
|
||||
tools:tint="@color/poi_background" />
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_weight="1"
|
||||
android:ellipsize="marquee"
|
||||
android:paddingLeft="@dimen/content_padding"
|
||||
android:paddingRight="@dimen/content_padding"
|
||||
android:singleLine="true"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="@dimen/default_list_text_size"
|
||||
osmand:typeface="@string/font_roboto_regular"
|
||||
tools:text="@string/poi_aerialway_transport" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/move_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:paddingLeft="@dimen/content_padding"
|
||||
android:paddingRight="@dimen/content_padding"
|
||||
android:src="@drawable/ic_action_item_move"
|
||||
android:tint="?attr/secondary_icon_color" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
|
@ -9,33 +9,43 @@
|
|||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="26dp"
|
||||
android:paddingRight="16dp"
|
||||
android:paddingTop="18dp"
|
||||
android:paddingBottom="16dp"
|
||||
android:paddingTop="@dimen/content_padding"
|
||||
android:orientation="vertical">
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="@dimen/dialog_header_text_size"
|
||||
osmand:typeface="@string/font_roboto_medium"
|
||||
tools:text="Food"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="@dimen/default_desc_text_size"
|
||||
android:text="@string/subcategories"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:paddingLeft="@dimen/card_content_padding_large"
|
||||
android:paddingRight="@dimen/content_padding"
|
||||
android:orientation="vertical">
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="@dimen/dialog_header_text_size"
|
||||
osmand:typeface="@string/font_roboto_medium"
|
||||
tools:text="Food"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="@dimen/default_desc_text_size"
|
||||
android:text="@string/subcategories"/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/buttonContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="@dimen/card_content_padding_large"
|
||||
android:paddingRight="@dimen/content_padding"
|
||||
android:paddingTop="@dimen/content_padding_half"
|
||||
android:paddingBottom="@dimen/content_padding_half"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
|
|
|
@ -11,6 +11,12 @@
|
|||
Thx - Hardy
|
||||
|
||||
-->
|
||||
<string name="rearrange_categories">Rearrange categories</string>
|
||||
<string name="create_custom_categories_list_promo">You can add custom categories hide categories that you don’t find necessary and change the sort order of the list. The list can be imported and exported with profiles.</string>
|
||||
<string name="add_new_custom_category_button_promo">You can add a new custom category by selecting one or a few needed categories.</string>
|
||||
<string name="reset_to_default_category_button_promo">Reset to default will delete or custom categories and reset sort order to the default state after installation.</string>
|
||||
<string name="shared_string_available">Available</string>
|
||||
<string name="add_custom_category">Add custom category</string>
|
||||
<string name="rendering_attr_streetLightingNight_name">Show only at night</string>
|
||||
<string name="plugin_prefs_reset_successful">All plugin settings restored to default state.</string>
|
||||
<string name="profile_prefs_reset_successful">All profile settings restored to default state.</string>
|
||||
|
|
|
@ -1051,6 +1051,31 @@ public class OsmandSettings {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public List<String> getStringsList() {
|
||||
final String listAsString = get();
|
||||
if (listAsString != null) {
|
||||
if (listAsString.contains(delimiter)) {
|
||||
return Arrays.asList(listAsString.split(delimiter));
|
||||
} else {
|
||||
return new ArrayList<String>() {
|
||||
{add(listAsString);}
|
||||
};
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setStringsList(List<String> values) {
|
||||
if (values == null || values.size() == 0) {
|
||||
set(null);
|
||||
return;
|
||||
}
|
||||
clearAll();
|
||||
for (String value : values) {
|
||||
addValue(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class EnumIntPreference<E extends Enum<E>> extends CommonPreference<E> {
|
||||
|
@ -3160,6 +3185,12 @@ public class OsmandSettings {
|
|||
public void setSelectedPoiFilters(final Set<String> poiFilters) {
|
||||
SELECTED_POI_FILTER_FOR_MAP.set(android.text.TextUtils.join(",", poiFilters));
|
||||
}
|
||||
|
||||
public final ListStringPreference POI_FILTERS_ORDER = (ListStringPreference)
|
||||
new ListStringPreference("poi_filters_order", null, ",,").makeProfile().cache();
|
||||
|
||||
public final ListStringPreference INACTIVE_POI_FILTERS = (ListStringPreference)
|
||||
new ListStringPreference("inactive_poi_filters", null, ",,").makeProfile().cache();
|
||||
|
||||
public static final String VOICE_PROVIDER_NOT_USE = "VOICE_PROVIDER_NOT_USE";
|
||||
|
||||
|
|
|
@ -276,10 +276,7 @@ public class MapActivityLayers {
|
|||
final PoiFiltersHelper poiFilters = app.getPoiFilters();
|
||||
final ContextMenuAdapter adapter = new ContextMenuAdapter();
|
||||
final List<PoiUIFilter> list = new ArrayList<>();
|
||||
for (PoiUIFilter f : poiFilters.getTopDefinedPoiFilters()) {
|
||||
addFilterToList(adapter, list, f, true);
|
||||
}
|
||||
for (PoiUIFilter f : poiFilters.getSearchPoiFilters()) {
|
||||
for (PoiUIFilter f : poiFilters.getSortedPoiFilters(true)) {
|
||||
addFilterToList(adapter, list, f, true);
|
||||
}
|
||||
list.add(poiFilters.getCustomPOIFilter());
|
||||
|
@ -357,10 +354,7 @@ public class MapActivityLayers {
|
|||
.setIcon(R.drawable.ic_action_search_dark).createItem());
|
||||
final List<PoiUIFilter> list = new ArrayList<>();
|
||||
list.add(poiFilters.getCustomPOIFilter());
|
||||
for (PoiUIFilter f : poiFilters.getTopDefinedPoiFilters()) {
|
||||
addFilterToList(adapter, list, f, false);
|
||||
}
|
||||
for (PoiUIFilter f : poiFilters.getSearchPoiFilters()) {
|
||||
for (PoiUIFilter f : poiFilters.getSortedPoiFilters(true)) {
|
||||
addFilterToList(adapter, list, f, false);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ import net.osmand.util.Algorithms;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
|
@ -54,7 +55,7 @@ public class PoiFiltersHelper {
|
|||
UDF_CAR_AID, UDF_FOR_TOURISTS, UDF_FOOD_SHOP, UDF_FUEL, UDF_SIGHTSEEING, UDF_EMERGENCY,
|
||||
UDF_PUBLIC_TRANSPORT, UDF_ACCOMMODATION, UDF_RESTAURANTS, UDF_PARKING
|
||||
};
|
||||
|
||||
|
||||
public PoiFiltersHelper(OsmandApplication application) {
|
||||
this.application = application;
|
||||
PoiFilterDbHelper helper = openDbHelperNoPois();
|
||||
|
@ -170,7 +171,6 @@ public class PoiFiltersHelper {
|
|||
PoiUIFilter lf = new PoiUIFilter(tp, application, "");
|
||||
ArrayList<PoiUIFilter> copy = new ArrayList<>(cacheTopStandardFilters);
|
||||
copy.add(lf);
|
||||
Collections.sort(copy);
|
||||
cacheTopStandardFilters = copy;
|
||||
return lf;
|
||||
}
|
||||
|
@ -179,7 +179,6 @@ public class PoiFiltersHelper {
|
|||
PoiUIFilter lf = new PoiUIFilter(lt, application, "");
|
||||
ArrayList<PoiUIFilter> copy = new ArrayList<>(cacheTopStandardFilters);
|
||||
copy.add(lf);
|
||||
Collections.sort(copy);
|
||||
cacheTopStandardFilters = copy;
|
||||
return lf;
|
||||
}
|
||||
|
@ -235,7 +234,6 @@ public class PoiFiltersHelper {
|
|||
PoiUIFilter f = new PoiUIFilter(t, application, "");
|
||||
top.add(f);
|
||||
}
|
||||
Collections.sort(top);
|
||||
cacheTopStandardFilters = top;
|
||||
}
|
||||
List<PoiUIFilter> result = new ArrayList<>();
|
||||
|
@ -248,6 +246,118 @@ public class PoiFiltersHelper {
|
|||
return result;
|
||||
}
|
||||
|
||||
public Map<String, Integer> getPoiFilterOrders(boolean onlyActive) {
|
||||
Map<String, Integer> filterOrders = new HashMap<>();
|
||||
List<PoiUIFilter> sortedFilters = getSortedPoiFilters(onlyActive);
|
||||
for (PoiUIFilter filter : sortedFilters) {
|
||||
filterOrders.put(filter.getFilterId(), filter.getOrder());
|
||||
}
|
||||
return filterOrders;
|
||||
}
|
||||
|
||||
public List<PoiUIFilter> getSortedPoiFilters(boolean onlyActive) {
|
||||
initPoiUIFiltersState();
|
||||
List<PoiUIFilter> allFilters = new ArrayList<>();
|
||||
allFilters.addAll(getTopDefinedPoiFilters());
|
||||
allFilters.addAll(getSearchPoiFilters());
|
||||
Collections.sort(allFilters);
|
||||
if (onlyActive) {
|
||||
List<PoiUIFilter> onlyActiveFilters = new ArrayList<>();
|
||||
for (PoiUIFilter f : allFilters) {
|
||||
if (f.isActive()) {
|
||||
onlyActiveFilters.add(f);
|
||||
}
|
||||
}
|
||||
return onlyActiveFilters;
|
||||
} else {
|
||||
return allFilters;
|
||||
}
|
||||
}
|
||||
|
||||
private void initPoiUIFiltersState() {
|
||||
List<PoiUIFilter> allFilters = new ArrayList<>();
|
||||
allFilters.addAll(getTopDefinedPoiFilters());
|
||||
allFilters.addAll(getSearchPoiFilters());
|
||||
|
||||
refreshPoiFiltersActivation(allFilters);
|
||||
refreshPoiFiltersOrder(allFilters);
|
||||
|
||||
//set up the biggest order to custom filter
|
||||
PoiUIFilter customFilter = getCustomPOIFilter();
|
||||
customFilter.setActive(true);
|
||||
customFilter.setOrder(allFilters.size());
|
||||
}
|
||||
|
||||
private void refreshPoiFiltersOrder(List<PoiUIFilter> filters) {
|
||||
Map<String, Integer> orders = getPoiFiltersOrder();
|
||||
List<PoiUIFilter> existedFilters = new ArrayList<>();
|
||||
List<PoiUIFilter> newFilters = new ArrayList<>();
|
||||
if (orders != null) {
|
||||
//set up orders from settings
|
||||
for (PoiUIFilter filter : filters) {
|
||||
Integer order = orders.get(filter.getFilterId());
|
||||
if (order != null) {
|
||||
filter.setOrder(order);
|
||||
existedFilters.add(filter);
|
||||
} else {
|
||||
newFilters.add(filter);
|
||||
}
|
||||
}
|
||||
//make order values without spaces
|
||||
Collections.sort(existedFilters);
|
||||
for (int i = 0; i < existedFilters.size(); i++) {
|
||||
existedFilters.get(i).setOrder(i);
|
||||
}
|
||||
//set up maximum orders for new poi filters
|
||||
Collections.sort(newFilters);
|
||||
for (PoiUIFilter filter : newFilters) {
|
||||
filter.setOrder(existedFilters.size());
|
||||
existedFilters.add(filter);
|
||||
}
|
||||
} else {
|
||||
for (PoiUIFilter filter : filters) {
|
||||
filter.setOrder(PoiUIFilter.INVALID_ORDER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void refreshPoiFiltersActivation(List<PoiUIFilter> filters) {
|
||||
List<String> inactiveFiltersIds = getInactivePoiFiltersIds();
|
||||
if (inactiveFiltersIds != null) {
|
||||
for (PoiUIFilter filter : filters) {
|
||||
filter.setActive(!inactiveFiltersIds.contains(filter.getFilterId()));
|
||||
}
|
||||
} else {
|
||||
for (PoiUIFilter filter : filters) {
|
||||
filter.setActive(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void saveFiltersOrder(List<String> filterIds) {
|
||||
application.getSettings().POI_FILTERS_ORDER.setStringsList(filterIds);
|
||||
}
|
||||
|
||||
public void saveInactiveFilters(List<String> filterIds) {
|
||||
application.getSettings().INACTIVE_POI_FILTERS.setStringsList(filterIds);
|
||||
}
|
||||
|
||||
public Map<String, Integer> getPoiFiltersOrder() {
|
||||
List<String> ids = application.getSettings().POI_FILTERS_ORDER.getStringsList();
|
||||
if (ids == null) {
|
||||
return null;
|
||||
}
|
||||
Map<String, Integer> result = new HashMap<>();
|
||||
for (int i = 0; i < ids.size(); i++) {
|
||||
result.put(ids.get(i), i);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<String> getInactivePoiFiltersIds() {
|
||||
return application.getSettings().INACTIVE_POI_FILTERS.getStringsList();
|
||||
}
|
||||
|
||||
private PoiFilterDbHelper openDbHelperNoPois() {
|
||||
return new PoiFilterDbHelper(null, application);
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ public class PoiUIFilter implements SearchPoiTypeFilter, Comparable<PoiUIFilter>
|
|||
public final static String USER_PREFIX = "user_"; //$NON-NLS-1$
|
||||
public final static String CUSTOM_FILTER_ID = USER_PREFIX + "custom_id"; //$NON-NLS-1$
|
||||
public final static String BY_NAME_FILTER_ID = USER_PREFIX + "by_name"; //$NON-NLS-1$
|
||||
public final static int INVALID_ORDER = -1;
|
||||
|
||||
private Map<PoiCategory, LinkedHashSet<String>> acceptedTypes = new LinkedHashMap<>();
|
||||
private Map<String, PoiType> poiAdditionals = new HashMap<>();
|
||||
|
@ -52,6 +53,8 @@ public class PoiUIFilter implements SearchPoiTypeFilter, Comparable<PoiUIFilter>
|
|||
protected String standardIconId = "";
|
||||
protected String name;
|
||||
protected boolean isStandardFilter;
|
||||
protected int order = INVALID_ORDER;
|
||||
protected boolean isActive = true;
|
||||
|
||||
protected final OsmandApplication app;
|
||||
|
||||
|
@ -718,6 +721,7 @@ public class PoiUIFilter implements SearchPoiTypeFilter, Comparable<PoiUIFilter>
|
|||
updatePoiAdditionals();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFilterId() {
|
||||
return filterId;
|
||||
}
|
||||
|
@ -743,6 +747,22 @@ public class PoiUIFilter implements SearchPoiTypeFilter, Comparable<PoiUIFilter>
|
|||
this.isStandardFilter = isStandardFilter;
|
||||
}
|
||||
|
||||
public int getOrder() {
|
||||
return order;
|
||||
}
|
||||
|
||||
public void setOrder(int order) {
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return isActive;
|
||||
}
|
||||
|
||||
public void setActive(boolean active) {
|
||||
isActive = active;
|
||||
}
|
||||
|
||||
public Context getApplication() {
|
||||
return app;
|
||||
}
|
||||
|
@ -773,7 +793,9 @@ public class PoiUIFilter implements SearchPoiTypeFilter, Comparable<PoiUIFilter>
|
|||
|
||||
@Override
|
||||
public int compareTo(@NonNull PoiUIFilter another) {
|
||||
if (another.filterId.equals(this.filterId)) {
|
||||
if (this.order != INVALID_ORDER && another.order != INVALID_ORDER) {
|
||||
return (this.order < another.order) ? -1 : ((this.order == another.order) ? 0 : 1);
|
||||
} else if (another.filterId.equals(this.filterId)) {
|
||||
String thisFilterByName = this.filterByName == null ? "" : this.filterByName;
|
||||
String anotherFilterByName = another.filterByName == null ? "" : another.filterByName;
|
||||
return thisFilterByName.compareToIgnoreCase(anotherFilterByName);
|
||||
|
|
695
OsmAnd/src/net/osmand/plus/poi/RearrangePoiFiltersFragment.java
Normal file
695
OsmAnd/src/net/osmand/plus/poi/RearrangePoiFiltersFragment.java
Normal file
|
@ -0,0 +1,695 @@
|
|||
package net.osmand.plus.poi;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v4.view.MotionEventCompat;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.support.v7.widget.helper.ItemTouchHelper;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.CallbackWithObject;
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.UiUtilities;
|
||||
import net.osmand.plus.render.RenderingIcons;
|
||||
import net.osmand.plus.views.controls.ReorderItemTouchHelperCallback;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import static net.osmand.plus.poi.PoiUIFilter.CUSTOM_FILTER_ID;
|
||||
import static net.osmand.plus.poi.RearrangePoiFiltersFragment.ItemType.DESCRIPTION;
|
||||
import static net.osmand.plus.poi.RearrangePoiFiltersFragment.ItemType.POI;
|
||||
import static net.osmand.plus.poi.RearrangePoiFiltersFragment.ItemType.SPACE;
|
||||
|
||||
public class RearrangePoiFiltersFragment extends DialogFragment {
|
||||
|
||||
public static final String TAG = "RearrangePoiFiltersFragment";
|
||||
|
||||
private static final Log LOG = PlatformUtil.getLog(RearrangePoiFiltersFragment.class);
|
||||
|
||||
private boolean usedOnMap;
|
||||
private CallbackWithObject<Boolean> resultCallback;
|
||||
|
||||
private List<ListItem> items = new ArrayList<>();
|
||||
private EditPoiFiltersAdapter adapter;
|
||||
private boolean orderModified;
|
||||
private boolean activationModified;
|
||||
private boolean wasReset = false;
|
||||
private boolean isChanged = false;
|
||||
|
||||
private HashMap<String, Integer> poiFiltersOrders = new HashMap<>();
|
||||
private List<String> availableFiltersKeys = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
boolean nightMode = isNightMode(requireMyApplication(), usedOnMap);
|
||||
int themeId = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme;
|
||||
setStyle(STYLE_NO_FRAME, themeId);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
final OsmandApplication app = requireMyApplication();
|
||||
|
||||
boolean nightMode = isNightMode(app, usedOnMap);
|
||||
|
||||
View mainView = UiUtilities.getInflater(app, nightMode).inflate(R.layout.edit_arrangement_list_fragment, container, false);
|
||||
ImageButton closeButton = mainView.findViewById(R.id.close_button);
|
||||
closeButton.setImageResource(R.drawable.ic_action_remove_dark);
|
||||
closeButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
dismiss();
|
||||
}
|
||||
});
|
||||
|
||||
TextView toolbarTitle = mainView.findViewById(R.id.toolbar_title);
|
||||
toolbarTitle.setText(R.string.rearrange_categories);
|
||||
|
||||
RecyclerView recyclerView = mainView.findViewById(R.id.profiles_list);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(app));
|
||||
|
||||
adapter = new EditPoiFiltersAdapter(app, nightMode);
|
||||
initFiltersOrders(app, false);
|
||||
|
||||
final ItemTouchHelper touchHelper = new ItemTouchHelper(new ReorderItemTouchHelperCallback(adapter));
|
||||
touchHelper.attachToRecyclerView(recyclerView);
|
||||
|
||||
orderModified = app.getSettings().POI_FILTERS_ORDER.get() != null;
|
||||
activationModified = app.getSettings().INACTIVE_POI_FILTERS.get() != null;
|
||||
|
||||
adapter.setListener(new PoiAdapterListener() {
|
||||
|
||||
private int fromPosition;
|
||||
private int toPosition;
|
||||
|
||||
@Override
|
||||
public void onDragStarted(RecyclerView.ViewHolder holder) {
|
||||
fromPosition = holder.getAdapterPosition();
|
||||
touchHelper.startDrag(holder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDragOrSwipeEnded(RecyclerView.ViewHolder holder) {
|
||||
toPosition = holder.getAdapterPosition();
|
||||
if (toPosition >= 0 && fromPosition >= 0 && toPosition != fromPosition) {
|
||||
adapter.notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onButtonClicked(int pos) {
|
||||
ListItem item = items.get(pos);
|
||||
if (item.value instanceof PoiUIFilterDataObject) {
|
||||
isChanged = true;
|
||||
activationModified = true;
|
||||
PoiUIFilterDataObject poiInfo = (PoiUIFilterDataObject) item.value;
|
||||
poiInfo.toggleActive();
|
||||
if (!poiInfo.isActive) {
|
||||
availableFiltersKeys.add(poiInfo.filterId);
|
||||
} else {
|
||||
availableFiltersKeys.remove(poiInfo.filterId);
|
||||
}
|
||||
updateItems();
|
||||
}
|
||||
}
|
||||
});
|
||||
recyclerView.setAdapter(adapter);
|
||||
|
||||
View cancelButton = mainView.findViewById(R.id.dismiss_button);
|
||||
UiUtilities.setupDialogButton(nightMode, cancelButton, UiUtilities.DialogButtonType.SECONDARY, R.string.shared_string_cancel);
|
||||
cancelButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
dismiss();
|
||||
}
|
||||
});
|
||||
|
||||
mainView.findViewById(R.id.buttons_divider).setVisibility(View.VISIBLE);
|
||||
|
||||
View applyButton = mainView.findViewById(R.id.right_bottom_button);
|
||||
UiUtilities.setupDialogButton(nightMode, applyButton, UiUtilities.DialogButtonType.PRIMARY, R.string.shared_string_apply);
|
||||
applyButton.setVisibility(View.VISIBLE);
|
||||
applyButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (isChanged) {
|
||||
if (activationModified) {
|
||||
app.getPoiFilters().saveInactiveFilters(availableFiltersKeys);
|
||||
} else if (wasReset) {
|
||||
app.getPoiFilters().saveInactiveFilters(null);
|
||||
}
|
||||
if (orderModified) {
|
||||
List<PoiUIFilter> dataToSave = new ArrayList<>();
|
||||
for (PoiUIFilter filter : getSortedPoiUiFilters(app)) {
|
||||
String filterId = filter.getFilterId();
|
||||
Integer order = poiFiltersOrders.get(filterId);
|
||||
if (order == null) {
|
||||
order = filter.getOrder();
|
||||
}
|
||||
boolean isActive = !availableFiltersKeys.contains(filterId);
|
||||
filter.setActive(isActive);
|
||||
filter.setOrder(order);
|
||||
if (isActive) {
|
||||
dataToSave.add(filter);
|
||||
}
|
||||
}
|
||||
Collections.sort(dataToSave);
|
||||
List<String> filterIds = new ArrayList<>();
|
||||
for (PoiUIFilter filter : dataToSave) {
|
||||
filterIds.add(filter.getFilterId());
|
||||
}
|
||||
app.getPoiFilters().saveFiltersOrder(filterIds);
|
||||
} else if (wasReset) {
|
||||
app.getPoiFilters().saveFiltersOrder(null);
|
||||
}
|
||||
}
|
||||
if (resultCallback != null) {
|
||||
resultCallback.processResult(isChanged);
|
||||
}
|
||||
dismiss();
|
||||
}
|
||||
});
|
||||
|
||||
return mainView;
|
||||
}
|
||||
|
||||
private void initFiltersOrders(OsmandApplication app, boolean arrangementByDefault) {
|
||||
poiFiltersOrders.clear();
|
||||
availableFiltersKeys.clear();
|
||||
List<PoiUIFilter> filters = getSortedPoiUiFilters(app);
|
||||
if (arrangementByDefault) {
|
||||
Collections.sort(filters, new Comparator<PoiUIFilter>() {
|
||||
@Override
|
||||
public int compare(PoiUIFilter o1, PoiUIFilter o2) {
|
||||
if (o1.filterId.equals(o2.filterId)) {
|
||||
String filterByName1 = o1.filterByName == null ? "" : o1.filterByName;
|
||||
String filterByName2 = o2.filterByName == null ? "" : o2.filterByName;
|
||||
return filterByName1.compareToIgnoreCase(filterByName2);
|
||||
} else {
|
||||
return o1.name.compareTo(o2.name);
|
||||
}
|
||||
}
|
||||
});
|
||||
for (int i = 0; i < filters.size(); i++) {
|
||||
PoiUIFilter filter = filters.get(i);
|
||||
poiFiltersOrders.put(filter.getFilterId(), i);
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < filters.size(); i++) {
|
||||
PoiUIFilter filter = filters.get(i);
|
||||
poiFiltersOrders.put(filter.getFilterId(), i);
|
||||
if (!filter.isActive) {
|
||||
availableFiltersKeys.add(filter.getFilterId());
|
||||
}
|
||||
}
|
||||
}
|
||||
updateItems();
|
||||
}
|
||||
|
||||
private void updateItems() {
|
||||
final OsmandApplication app = requireMyApplication();
|
||||
List<ListItem> active = getPoiFilters(true);
|
||||
List<ListItem> available = getPoiFilters(false);
|
||||
items.clear();
|
||||
items.add(new ListItem(DESCRIPTION, app.getString(R.string.create_custom_categories_list_promo)));
|
||||
items.add(new ListItem(ItemType.SPACE, app.getResources().getDimension(R.dimen.content_padding)));
|
||||
items.addAll(active);
|
||||
items.add(new ListItem(ItemType.DIVIDER, 0));
|
||||
if (availableFiltersKeys != null && availableFiltersKeys.size() > 0) {
|
||||
items.add(new ListItem(ItemType.HEADER, app.getString(R.string.shared_string_available)));
|
||||
items.addAll(available);
|
||||
items.add(new ListItem(ItemType.DIVIDER, 1));
|
||||
}
|
||||
/*items.add(new ListItem(ItemType.BUTTON, new ControlButton(app.getString(R.string.add_custom_category),
|
||||
R.drawable.ic_action_plus, new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
QuickSearchCustomPoiFragment.showDialog(RearrangePoiFiltersFragment.this, app.getPoiFilters().getCustomPOIFilter().getFilterId());
|
||||
}
|
||||
})));*/
|
||||
items.add(new ListItem(ItemType.BUTTON, new ControlButton(app.getString(R.string.reset_to_default),
|
||||
R.drawable.ic_action_reset_to_default_dark, new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
isChanged = true;
|
||||
wasReset = true;
|
||||
activationModified = false;
|
||||
orderModified = false;
|
||||
initFiltersOrders(app, true);
|
||||
}
|
||||
})));
|
||||
items.add(new ListItem(DESCRIPTION,
|
||||
// app.getString(R.string.add_new_custom_category_button_promo) + '\n' +
|
||||
app.getString(R.string.reset_to_default_category_button_promo)));
|
||||
|
||||
adapter.setItems(items);
|
||||
}
|
||||
|
||||
public static void showInstance(@NonNull DialogFragment parentFragment, boolean usedOnMap, CallbackWithObject<Boolean> callback) {
|
||||
try {
|
||||
RearrangePoiFiltersFragment fragment = new RearrangePoiFiltersFragment();
|
||||
fragment.setUsedOnMap(usedOnMap);
|
||||
fragment.setResultCallback(callback);
|
||||
fragment.show(parentFragment.getChildFragmentManager(), RearrangePoiFiltersFragment.TAG);
|
||||
} catch (RuntimeException e) {
|
||||
LOG.error("showInstance", e);
|
||||
}
|
||||
}
|
||||
|
||||
public List<ListItem> getPoiFilters(boolean isActive) {
|
||||
OsmandApplication app = requireMyApplication();
|
||||
List<ListItem> result = new ArrayList<>();
|
||||
for (PoiUIFilter f : getSortedPoiUiFilters(app)) {
|
||||
addFilterToList(result, f, isActive);
|
||||
}
|
||||
Collections.sort(result, new Comparator<ListItem>() {
|
||||
@Override
|
||||
public int compare(ListItem o1, ListItem o2) {
|
||||
int order1 = ((PoiUIFilterDataObject) o1.value).order;
|
||||
int order2 = ((PoiUIFilterDataObject) o2.value).order;
|
||||
return (order1 < order2) ? -1 : ((order1 == order2) ? 0 : 1);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
private void addFilterToList(List<ListItem> list, PoiUIFilter f, boolean isActive) {
|
||||
String filterId = f.getFilterId();
|
||||
if (!isActive && availableFiltersKeys.contains(filterId) || isActive && !availableFiltersKeys.contains(filterId)) {
|
||||
Integer order = poiFiltersOrders.get(filterId);
|
||||
if (order == null) {
|
||||
order = f.getOrder();
|
||||
}
|
||||
PoiUIFilterDataObject poiInfo = new PoiUIFilterDataObject();
|
||||
poiInfo.filterId = filterId;
|
||||
poiInfo.name = f.getName();
|
||||
poiInfo.order = order;
|
||||
String iconRes = f.getIconId();
|
||||
if (iconRes != null && RenderingIcons.containsBigIcon(iconRes)) {
|
||||
poiInfo.iconRes = RenderingIcons.getBigIconResourceId(iconRes);
|
||||
} else {
|
||||
poiInfo.iconRes = R.drawable.mx_user_defined;
|
||||
}
|
||||
poiInfo.isActive = !availableFiltersKeys.contains(filterId);
|
||||
list.add(new ListItem(POI, poiInfo));
|
||||
}
|
||||
}
|
||||
|
||||
private static List<PoiUIFilter> getSortedPoiUiFilters(@NonNull OsmandApplication app) {
|
||||
List<PoiUIFilter> filters = app.getPoiFilters().getSortedPoiFilters(false);
|
||||
//remove custom filter
|
||||
for (int i = filters.size() - 1; i >= 0; i--) {
|
||||
PoiUIFilter filter = filters.get(i);
|
||||
if (filter.getFilterId().equals(CUSTOM_FILTER_ID)) {
|
||||
filters.remove(filter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return filters;
|
||||
}
|
||||
|
||||
public void setUsedOnMap(boolean usedOnMap) {
|
||||
this.usedOnMap = usedOnMap;
|
||||
}
|
||||
|
||||
public void setResultCallback(CallbackWithObject<Boolean> resultCallback) {
|
||||
this.resultCallback = resultCallback;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
protected OsmandApplication requireMyApplication() {
|
||||
FragmentActivity activity = requireActivity();
|
||||
return (OsmandApplication) activity.getApplication();
|
||||
}
|
||||
|
||||
public static boolean isNightMode(OsmandApplication app, boolean usedOnMap) {
|
||||
if (app != null) {
|
||||
return usedOnMap ? app.getDaynightHelper().isNightModeForMapControls() : !app.getSettings().isLightContent();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public class PoiUIFilterDataObject {
|
||||
String filterId;
|
||||
String name;
|
||||
int iconRes;
|
||||
int order;
|
||||
boolean isActive;
|
||||
|
||||
public void toggleActive() {
|
||||
isActive = !isActive;
|
||||
}
|
||||
}
|
||||
|
||||
protected class ControlButton {
|
||||
private String title;
|
||||
private int iconRes;
|
||||
private View.OnClickListener listener;
|
||||
|
||||
public ControlButton(String title, int iconRes, View.OnClickListener listener) {
|
||||
this.title = title;
|
||||
this.iconRes = iconRes;
|
||||
this.listener = listener;
|
||||
}
|
||||
}
|
||||
|
||||
protected enum ItemType {
|
||||
DESCRIPTION,
|
||||
POI,
|
||||
HEADER,
|
||||
DIVIDER,
|
||||
SPACE,
|
||||
BUTTON
|
||||
}
|
||||
|
||||
private class ListItem {
|
||||
ItemType type;
|
||||
Object value;
|
||||
|
||||
public ListItem(ItemType type, Object value) {
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
private class EditPoiFiltersAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
|
||||
implements ReorderItemTouchHelperCallback.OnItemMoveCallback {
|
||||
|
||||
private OsmandApplication app;
|
||||
private UiUtilities uiUtilities;
|
||||
|
||||
private List<ListItem> items = new ArrayList<>();
|
||||
private boolean nightMode;
|
||||
private PoiAdapterListener listener;
|
||||
|
||||
public EditPoiFiltersAdapter(OsmandApplication app, boolean nightMode) {
|
||||
setHasStableIds(true);
|
||||
this.app = app;
|
||||
this.uiUtilities = app.getUIUtilities();
|
||||
this.nightMode = nightMode;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewTypeId) {
|
||||
Context ctx = parent.getContext();
|
||||
LayoutInflater inflater = UiUtilities.getInflater(ctx, nightMode);
|
||||
ItemType type = viewTypeId < ItemType.values().length ? ItemType.values()[viewTypeId] : SPACE;
|
||||
View itemView;
|
||||
switch (type) {
|
||||
case POI:
|
||||
itemView = inflater.inflate(R.layout.order_poi_list_item, parent, false);
|
||||
return new PoiViewHolder(itemView);
|
||||
case SPACE:
|
||||
itemView = new View(ctx);
|
||||
return new SpaceViewHolder(itemView);
|
||||
case BUTTON:
|
||||
itemView = inflater.inflate(R.layout.preference_button, parent, false);
|
||||
return new ButtonViewHolder(itemView);
|
||||
case HEADER:
|
||||
itemView = inflater.inflate(R.layout.preference_category_with_descr, parent, false);
|
||||
return new HeaderViewHolder(itemView);
|
||||
case DIVIDER:
|
||||
itemView = inflater.inflate(R.layout.divider, parent, false);
|
||||
return new DividerViewHolder(itemView);
|
||||
case DESCRIPTION:
|
||||
itemView = inflater.inflate(R.layout.bottom_sheet_item_description_long, parent, false);
|
||||
return new DescriptionViewHolder(itemView);
|
||||
default:
|
||||
throw new IllegalArgumentException("Unsupported view type");
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
@Override
|
||||
public void onBindViewHolder(final @NonNull RecyclerView.ViewHolder holder, int position) {
|
||||
ListItem item = items.get(position);
|
||||
boolean nightMode = isNightMode(app, usedOnMap);
|
||||
int activeColorResId = nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light;
|
||||
if (holder instanceof PoiViewHolder) {
|
||||
PoiViewHolder h = (PoiViewHolder) holder;
|
||||
PoiUIFilterDataObject poiInfo = (PoiUIFilterDataObject) item.value;
|
||||
int osmandOrangeColorResId = nightMode ? R.color.osmand_orange_dark : R.color.osmand_orange;
|
||||
h.title.setText(poiInfo.name);
|
||||
h.icon.setImageDrawable(uiUtilities.getIcon(poiInfo.iconRes, osmandOrangeColorResId));
|
||||
h.moveIcon.setVisibility(poiInfo.isActive ? View.VISIBLE : View.GONE);
|
||||
h.actionIcon.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
int pos = holder.getAdapterPosition();
|
||||
if (listener != null && pos != RecyclerView.NO_POSITION) {
|
||||
listener.onButtonClicked(pos);
|
||||
}
|
||||
}
|
||||
});
|
||||
if (poiInfo.isActive) {
|
||||
h.actionIcon.setImageDrawable(uiUtilities.getIcon(R.drawable.ic_action_remove, R.color.color_osm_edit_delete));
|
||||
h.moveIcon.setOnTouchListener(new View.OnTouchListener() {
|
||||
@Override
|
||||
public boolean onTouch(View view, MotionEvent event) {
|
||||
if (MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_DOWN) {
|
||||
listener.onDragStarted(holder);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
h.actionIcon.setImageDrawable(uiUtilities.getIcon(R.drawable.ic_action_add, R.color.color_osm_edit_create));
|
||||
}
|
||||
} else if (holder instanceof SpaceViewHolder) {
|
||||
float space = (float) item.value;
|
||||
((SpaceViewHolder) holder).setSpace((int) space);
|
||||
} else if (holder instanceof ButtonViewHolder) {
|
||||
ControlButton buttonInfo = (ControlButton) item.value;
|
||||
ButtonViewHolder h = (ButtonViewHolder) holder;
|
||||
h.buttonView.setOnClickListener(buttonInfo.listener);
|
||||
h.icon.setImageDrawable(uiUtilities.getIcon(buttonInfo.iconRes, activeColorResId));
|
||||
h.title.setText(buttonInfo.title);
|
||||
Drawable drawable = UiUtilities.getColoredSelectableDrawable(app, ContextCompat.getColor(app, activeColorResId), 0.3f);
|
||||
AndroidUtils.setBackground(h.buttonView, drawable);
|
||||
} else if (holder instanceof HeaderViewHolder) {
|
||||
String header = (String) item.value;
|
||||
((HeaderViewHolder) holder).tvTitle.setText(header);
|
||||
} else if (holder instanceof DescriptionViewHolder) {
|
||||
String description = (String) item.value;
|
||||
((DescriptionViewHolder) holder).tvDescription.setText(description);
|
||||
}
|
||||
}
|
||||
|
||||
public void setListener(PoiAdapterListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
public void setItems(List<ListItem> items) {
|
||||
this.items = items;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return items.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
ListItem item = items.get(position);
|
||||
return item.type.ordinal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onItemMove(int from, int to) {
|
||||
Object itemFrom = items.get(from).value;
|
||||
Object itemTo = items.get(to).value;
|
||||
if (itemFrom instanceof PoiUIFilterDataObject && itemTo instanceof PoiUIFilterDataObject) {
|
||||
isChanged = true;
|
||||
orderModified = true;
|
||||
PoiUIFilterDataObject poiFrom = (PoiUIFilterDataObject) itemFrom;
|
||||
PoiUIFilterDataObject poiTo = (PoiUIFilterDataObject) itemTo;
|
||||
|
||||
int orderFrom = poiFrom.order;
|
||||
int orderTo = poiTo.order;
|
||||
|
||||
poiFrom.order = orderTo;
|
||||
poiTo.order = orderFrom;
|
||||
|
||||
poiFiltersOrders.put(poiFrom.filterId, orderTo);
|
||||
poiFiltersOrders.put(poiTo.filterId, orderFrom);
|
||||
|
||||
Collections.swap(items, from, to);
|
||||
notifyItemMoved(from, to);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
ListItem item = items.get(position);
|
||||
if (item.value instanceof PoiUIFilterDataObject) {
|
||||
return ((PoiUIFilterDataObject) item.value).filterId.hashCode();
|
||||
} else if (item.value instanceof ControlButton) {
|
||||
return ((ControlButton) item.value).title.hashCode();
|
||||
} else if (item.value != null) {
|
||||
return item.value.hashCode();
|
||||
}
|
||||
return item.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemDismiss(RecyclerView.ViewHolder holder) {
|
||||
listener.onDragOrSwipeEnded(holder);
|
||||
}
|
||||
|
||||
private class DividerViewHolder extends RecyclerView.ViewHolder implements ReorderItemTouchHelperCallback.UnmovableItem {
|
||||
View divider;
|
||||
|
||||
public DividerViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
divider = itemView.findViewById(R.id.divider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMovingDisabled() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private class HeaderViewHolder extends RecyclerView.ViewHolder implements ReorderItemTouchHelperCallback.UnmovableItem {
|
||||
private TextView tvTitle;
|
||||
private TextView tvDescription;
|
||||
|
||||
public HeaderViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
tvTitle = itemView.findViewById(android.R.id.title);
|
||||
tvDescription = itemView.findViewById(android.R.id.summary);
|
||||
tvDescription.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMovingDisabled() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private class ButtonViewHolder extends RecyclerView.ViewHolder implements ReorderItemTouchHelperCallback.UnmovableItem {
|
||||
|
||||
private View buttonView;
|
||||
private ImageView icon;
|
||||
private TextView title;
|
||||
|
||||
public ButtonViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
buttonView = itemView;
|
||||
icon = itemView.findViewById(android.R.id.icon);
|
||||
title = itemView.findViewById(android.R.id.title);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMovingDisabled() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private class SpaceViewHolder extends RecyclerView.ViewHolder implements ReorderItemTouchHelperCallback.UnmovableItem {
|
||||
|
||||
View space;
|
||||
|
||||
public SpaceViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
space = itemView;
|
||||
}
|
||||
|
||||
public void setSpace(int hSpace) {
|
||||
ViewGroup.LayoutParams lp = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, hSpace);
|
||||
space.setLayoutParams(lp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMovingDisabled() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private class PoiViewHolder extends RecyclerView.ViewHolder implements ReorderItemTouchHelperCallback.UnmovableItem {
|
||||
|
||||
private TextView title;
|
||||
private TextView description;
|
||||
private ImageView icon;
|
||||
private ImageButton actionIcon;
|
||||
private ImageView moveIcon;
|
||||
private View itemsContainer;
|
||||
|
||||
public PoiViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
title = itemView.findViewById(R.id.title);
|
||||
actionIcon = itemView.findViewById(R.id.action_icon);
|
||||
icon = itemView.findViewById(R.id.icon);
|
||||
moveIcon = itemView.findViewById(R.id.move_icon);
|
||||
itemsContainer = itemView.findViewById(R.id.selectable_list_item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMovingDisabled() {
|
||||
int position = getAdapterPosition();
|
||||
if (position != RecyclerView.NO_POSITION) {
|
||||
ListItem item = items.get(position);
|
||||
if (item.value instanceof PoiUIFilterDataObject) {
|
||||
PoiUIFilterDataObject pdo = (PoiUIFilterDataObject) item.value;
|
||||
return !pdo.isActive;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private class DescriptionViewHolder extends RecyclerView.ViewHolder implements ReorderItemTouchHelperCallback.UnmovableItem {
|
||||
|
||||
private TextView tvDescription;
|
||||
|
||||
public DescriptionViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
tvDescription = itemView.findViewById(R.id.description);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMovingDisabled() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface PoiAdapterListener {
|
||||
|
||||
void onDragStarted(RecyclerView.ViewHolder holder);
|
||||
|
||||
void onDragOrSwipeEnded(RecyclerView.ViewHolder holder);
|
||||
|
||||
void onButtonClicked(int view);
|
||||
}
|
||||
}
|
|
@ -64,7 +64,7 @@ public class EditProfilesFragment extends BaseOsmAndFragment {
|
|||
}
|
||||
nightMode = !app.getSettings().isLightContent();
|
||||
|
||||
View mainView = UiUtilities.getInflater(getContext(), nightMode).inflate(R.layout.edit_profiles_list_fragment, container, false);
|
||||
View mainView = UiUtilities.getInflater(getContext(), nightMode).inflate(R.layout.edit_arrangement_list_fragment, container, false);
|
||||
ImageButton closeButton = mainView.findViewById(R.id.close_button);
|
||||
closeButton.setImageResource(R.drawable.ic_action_remove_dark);
|
||||
closeButton.setOnClickListener(new View.OnClickListener() {
|
||||
|
|
|
@ -283,10 +283,7 @@ public class ShowHidePoiAction extends QuickAction {
|
|||
|
||||
final List<PoiUIFilter> list = new ArrayList<>();
|
||||
|
||||
for (PoiUIFilter f : poiFilters.getTopDefinedPoiFilters()) {
|
||||
addFilterToList(adapter, list, f);
|
||||
}
|
||||
for (PoiUIFilter f : poiFilters.getSearchPoiFilters()) {
|
||||
for (PoiUIFilter f : poiFilters.getSortedPoiFilters(true)) {
|
||||
addFilterToList(adapter, list, f);
|
||||
}
|
||||
|
||||
|
|
|
@ -23,9 +23,9 @@ import android.widget.CompoundButton.OnCheckedChangeListener;
|
|||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import net.osmand.osm.PoiCategory;
|
||||
import net.osmand.osm.PoiType;
|
||||
import net.osmand.plus.DialogListItemAdapter;
|
||||
import net.osmand.plus.UiUtilities;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.OsmandSettings;
|
||||
|
@ -59,8 +59,7 @@ public class QuickSearchCustomPoiFragment extends DialogFragment {
|
|||
private TextView barTitle;
|
||||
private TextView barButton;
|
||||
private boolean editMode;
|
||||
private boolean isLightTheme;
|
||||
|
||||
private boolean nightMode;
|
||||
|
||||
public QuickSearchCustomPoiFragment() {
|
||||
}
|
||||
|
@ -72,10 +71,8 @@ public class QuickSearchCustomPoiFragment extends DialogFragment {
|
|||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
isLightTheme =
|
||||
getMyApplication().getSettings().OSMAND_THEME.get() == OsmandSettings.OSMAND_LIGHT_THEME;
|
||||
int themeId = isLightTheme ? R.style.OsmandLightTheme : R.style.OsmandDarkTheme;
|
||||
setStyle(STYLE_NO_FRAME, themeId);
|
||||
this.nightMode = getMyApplication().getSettings().OSMAND_THEME.get() == OsmandSettings.OSMAND_DARK_THEME;
|
||||
setStyle(STYLE_NO_FRAME, nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -101,7 +98,7 @@ public class QuickSearchCustomPoiFragment extends DialogFragment {
|
|||
|
||||
Toolbar toolbar = (Toolbar) view.findViewById(R.id.toolbar);
|
||||
Drawable icClose = app.getUIUtilities().getIcon(R.drawable.ic_action_remove_dark,
|
||||
isLightTheme ? R.color.active_buttons_and_links_text_light : R.color.active_buttons_and_links_text_dark);
|
||||
nightMode ? R.color.active_buttons_and_links_text_dark : R.color.active_buttons_and_links_text_light);
|
||||
toolbar.setNavigationIcon(icClose);
|
||||
toolbar.setNavigationContentDescription(R.string.shared_string_close);
|
||||
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
|
||||
|
@ -110,8 +107,8 @@ public class QuickSearchCustomPoiFragment extends DialogFragment {
|
|||
dismiss();
|
||||
}
|
||||
});
|
||||
toolbar.setBackgroundColor(ContextCompat.getColor(app, isLightTheme ? R.color.app_bar_color_light : R.color.app_bar_color_dark));
|
||||
toolbar.setTitleTextColor(ContextCompat.getColor(app, isLightTheme ? R.color.active_buttons_and_links_text_light : R.color.active_buttons_and_links_text_dark));
|
||||
toolbar.setBackgroundColor(ContextCompat.getColor(app, nightMode ? R.color.app_bar_color_dark : R.color.app_bar_color_light));
|
||||
toolbar.setTitleTextColor(ContextCompat.getColor(app, nightMode ? R.color.active_buttons_and_links_text_dark : R.color.active_buttons_and_links_text_light));
|
||||
|
||||
TextView title = (TextView) view.findViewById(R.id.title);
|
||||
if (editMode) {
|
||||
|
@ -254,6 +251,7 @@ public class QuickSearchCustomPoiFragment extends DialogFragment {
|
|||
AppCompatTextView titleView = (AppCompatTextView) row.findViewById(R.id.title);
|
||||
AppCompatTextView descView = (AppCompatTextView) row.findViewById(R.id.description);
|
||||
SwitchCompat check = (SwitchCompat) row.findViewById(R.id.toggle_item);
|
||||
UiUtilities.setupCompoundButton(check, nightMode, UiUtilities.CompoundButtonType.GLOBAL);
|
||||
|
||||
boolean categorySelected = filter.isTypeAccepted(category);
|
||||
UiUtilities ic = app.getUIUtilities();
|
||||
|
@ -268,8 +266,8 @@ public class QuickSearchCustomPoiFragment extends DialogFragment {
|
|||
iconView.setImageDrawable(null);
|
||||
}
|
||||
secondaryIconView.setImageDrawable(
|
||||
ic.getIcon(R.drawable.ic_action_additional_option,
|
||||
app.getSettings().isLightContent() ? R.color.icon_color_default_dark : 0));
|
||||
ic.getIcon(R.drawable.ic_action_additional_option, nightMode
|
||||
? R.color.icon_color_default_dark : R.color.icon_color_default_light));
|
||||
check.setOnCheckedChangeListener(null);
|
||||
check.setChecked(filter.isTypeAccepted(category));
|
||||
String textString = category.getTranslation();
|
||||
|
@ -388,8 +386,16 @@ public class QuickSearchCustomPoiFragment extends DialogFragment {
|
|||
.inflate(R.layout.subcategories_dialog_title, null);
|
||||
TextView titleTextView = (TextView) titleView.findViewById(R.id.title);
|
||||
titleTextView.setText(poiCategory.getTranslation());
|
||||
SwitchCompat check = (SwitchCompat) titleView.findViewById(R.id.check);
|
||||
check.setChecked(allSelected);
|
||||
View toggleButtonContainer = titleView.findViewById(R.id.buttonContainer);
|
||||
final CompoundButton selectAllToggle = (CompoundButton) toggleButtonContainer.findViewById(R.id.check);
|
||||
UiUtilities.setupCompoundButton(selectAllToggle, nightMode, UiUtilities.CompoundButtonType.GLOBAL);
|
||||
toggleButtonContainer.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
selectAllToggle.setChecked(!selectAllToggle.isChecked());
|
||||
}
|
||||
});
|
||||
selectAllToggle.setChecked(allSelected);
|
||||
builder.setCustomTitle(titleView);
|
||||
|
||||
builder.setCancelable(true);
|
||||
|
@ -424,17 +430,20 @@ public class QuickSearchCustomPoiFragment extends DialogFragment {
|
|||
listView.setSelectionFromTop(index, top);
|
||||
}
|
||||
});
|
||||
|
||||
builder.setMultiChoiceItems(visibleNames, selected,
|
||||
new DialogInterface.OnMultiChoiceClickListener() {
|
||||
|
||||
int activeColor = ContextCompat.getColor(getMyApplication(), nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light);
|
||||
int themeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme;
|
||||
final DialogListItemAdapter adapter = DialogListItemAdapter.createMultiChoiceAdapter(visibleNames,
|
||||
nightMode, selected, getMyApplication(), activeColor, themeRes, new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int item, boolean isChecked) {
|
||||
selected[item] = isChecked;
|
||||
public void onClick(View v) {
|
||||
int which = (int) v.getTag();
|
||||
selected[which] = !selected[which];
|
||||
}
|
||||
});
|
||||
builder.setAdapter(adapter, null);
|
||||
final AlertDialog dialog = builder.show();
|
||||
check.setOnCheckedChangeListener(new OnCheckedChangeListener() {
|
||||
adapter.setDialog(dialog);
|
||||
selectAllToggle.setOnCheckedChangeListener(new OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
if (isChecked) {
|
||||
|
@ -445,6 +454,7 @@ public class QuickSearchCustomPoiFragment extends DialogFragment {
|
|||
for (int i = 0; i < selected.length; i++) {
|
||||
dialog.getListView().setItemChecked(i, selected[i]);
|
||||
}
|
||||
adapter.notifyDataSetChanged();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ import android.widget.TextView;
|
|||
import android.widget.Toast;
|
||||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.CallbackWithObject;
|
||||
import net.osmand.Location;
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.ResultMatcher;
|
||||
|
@ -76,6 +77,7 @@ import net.osmand.plus.activities.MapActivity.ShowQuickSearchMode;
|
|||
import net.osmand.plus.helpers.SearchHistoryHelper;
|
||||
import net.osmand.plus.helpers.SearchHistoryHelper.HistoryEntry;
|
||||
import net.osmand.plus.poi.PoiUIFilter;
|
||||
import net.osmand.plus.poi.RearrangePoiFiltersFragment;
|
||||
import net.osmand.plus.resources.RegionAddressRepository;
|
||||
import net.osmand.plus.search.QuickSearchHelper.SearchHistoryAPI;
|
||||
import net.osmand.plus.search.listitems.QuickSearchButtonListItem;
|
||||
|
@ -1224,6 +1226,23 @@ public class QuickSearchDialogFragment extends DialogFragment implements OsmAndC
|
|||
QuickSearchDialogFragment.this, filter.getFilterId());
|
||||
}
|
||||
}));
|
||||
rows.add(new QuickSearchButtonListItem(app, R.drawable.ic_action_item_move,
|
||||
app.getString(R.string.rearrange_categories), new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
RearrangePoiFiltersFragment.showInstance(QuickSearchDialogFragment.this, false, new CallbackWithObject<Boolean>() {
|
||||
|
||||
@Override
|
||||
public boolean processResult(Boolean changed) {
|
||||
if (changed) {
|
||||
searchHelper.refreshFilterOrders();
|
||||
reloadCategoriesInternal();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}));
|
||||
if (categoriesSearchFragment != null) {
|
||||
categoriesSearchFragment.updateListAdapter(rows, false);
|
||||
}
|
||||
|
|
|
@ -102,6 +102,7 @@ public class QuickSearchHelper implements ResourceListener {
|
|||
core.registerAPI(new SearchOnlineApi(app));
|
||||
|
||||
refreshCustomPoiFilters();
|
||||
refreshFilterOrders();
|
||||
}
|
||||
|
||||
public void refreshCustomPoiFilters() {
|
||||
|
@ -117,6 +118,11 @@ public class QuickSearchHelper implements ResourceListener {
|
|||
core.addCustomSearchPoiFilter(poiFilters.getShowAllPOIFilter(), 1);
|
||||
}
|
||||
|
||||
public void refreshFilterOrders() {
|
||||
PoiFiltersHelper filtersHelper = app.getPoiFilters();
|
||||
core.setFilterOrders(filtersHelper.getPoiFilterOrders(true));
|
||||
}
|
||||
|
||||
public void setRepositoriesForSearchUICore(final OsmandApplication app) {
|
||||
BinaryMapIndexReader[] binaryMapIndexReaderArray = app.getResourceManager().getQuickSearchFiles();
|
||||
core.getSearchSettings().setOfflineIndexes(Arrays.asList(binaryMapIndexReaderArray));
|
||||
|
|
Loading…
Reference in a new issue