diff --git a/OsmAnd/res/layout/arrange_poi_list_item.xml b/OsmAnd/res/layout/arrange_poi_list_item.xml
new file mode 100644
index 0000000000..f1d493e094
--- /dev/null
+++ b/OsmAnd/res/layout/arrange_poi_list_item.xml
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OsmAnd/res/layout/edit_profiles_list_fragment.xml b/OsmAnd/res/layout/edit_arrangement_list_fragment.xml
similarity index 100%
rename from OsmAnd/res/layout/edit_profiles_list_fragment.xml
rename to OsmAnd/res/layout/edit_arrangement_list_fragment.xml
diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml
index 8635f82a6e..a72672bc93 100644
--- a/OsmAnd/res/values/strings.xml
+++ b/OsmAnd/res/values/strings.xml
@@ -11,6 +11,12 @@
Thx - Hardy
-->
+ Rearrange categories
+ 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.
+ You can add a new custom category by selecting one or a few needed categories.
+ Reset to default will delete or custom categories and reset sort order to the default state after installation.
+ Available
+ Add custom category
Permission is required to use this option.
Check and share detailed logs of the application
No routing rules in \'%1$s\'. Please choose another file.
diff --git a/OsmAnd/src/net/osmand/plus/OsmandSettings.java b/OsmAnd/src/net/osmand/plus/OsmandSettings.java
index bde5832a5c..df44ddeaa7 100644
--- a/OsmAnd/src/net/osmand/plus/OsmandSettings.java
+++ b/OsmAnd/src/net/osmand/plus/OsmandSettings.java
@@ -3056,6 +3056,10 @@ public class OsmandSettings {
public void setSelectedPoiFilters(final Set poiFilters) {
SELECTED_POI_FILTER_FOR_MAP.set(android.text.TextUtils.join(",", poiFilters));
}
+
+ public final OsmandPreference ARRANGE_POI_FILTERS_BY_DEFAULT = new BooleanPreference("arrange_poi_filters_by_default", false).makeProfile().cache();
+
+ public final OsmandPreference POI_FILTERS_ARRANGEMENT = new StringPreference("poi_filters_arrangement", null).makeProfile().cache();
public static final String VOICE_PROVIDER_NOT_USE = "VOICE_PROVIDER_NOT_USE";
diff --git a/OsmAnd/src/net/osmand/plus/activities/MapActivityLayers.java b/OsmAnd/src/net/osmand/plus/activities/MapActivityLayers.java
index c20a4cc6bd..3dbee524b2 100644
--- a/OsmAnd/src/net/osmand/plus/activities/MapActivityLayers.java
+++ b/OsmAnd/src/net/osmand/plus/activities/MapActivityLayers.java
@@ -276,10 +276,7 @@ public class MapActivityLayers {
final PoiFiltersHelper poiFilters = app.getPoiFilters();
final ContextMenuAdapter adapter = new ContextMenuAdapter();
final List list = new ArrayList<>();
- for (PoiUIFilter f : poiFilters.getTopDefinedPoiFilters()) {
- addFilterToList(adapter, list, f, true);
- }
- for (PoiUIFilter f : poiFilters.getSearchPoiFilters()) {
+ for (PoiUIFilter f : poiFilters.getProfileDependentPoiUIFilters(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 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.getProfileDependentPoiUIFilters(true)) {
addFilterToList(adapter, list, f, false);
}
diff --git a/OsmAnd/src/net/osmand/plus/poi/PoiFiltersHelper.java b/OsmAnd/src/net/osmand/plus/poi/PoiFiltersHelper.java
index 5356fedfa2..fda6d03134 100644
--- a/OsmAnd/src/net/osmand/plus/poi/PoiFiltersHelper.java
+++ b/OsmAnd/src/net/osmand/plus/poi/PoiFiltersHelper.java
@@ -2,6 +2,11 @@ package net.osmand.plus.poi;
import android.support.annotation.NonNull;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.annotations.Expose;
+import com.google.gson.reflect.TypeToken;
+
import net.osmand.osm.AbstractPoiType;
import net.osmand.osm.MapPoiTypes;
import net.osmand.osm.PoiCategory;
@@ -13,9 +18,12 @@ import net.osmand.plus.api.SQLiteAPI.SQLiteCursor;
import net.osmand.plus.api.SQLiteAPI.SQLiteStatement;
import net.osmand.util.Algorithms;
+import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
@@ -25,6 +33,9 @@ import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
+import static net.osmand.plus.poi.PoiFiltersHelper.PoiFilterType.SEARCH;
+import static net.osmand.plus.poi.PoiFiltersHelper.PoiFilterType.TOP_DEFINED;
+
public class PoiFiltersHelper {
private final OsmandApplication application;
@@ -54,6 +65,25 @@ 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 static final Comparator ORDER_COMPARATOR = new Comparator() {
+ @Override
+ public int compare(PoiUIFilter o1, PoiUIFilter o2) {
+ return (o1.getOrder() < o2.getOrder()) ? -1 : ((o1.getOrder() == o2.getOrder()) ? 0 : 1);
+ }
+ };
+
+ public static final Comparator ALPHABET_COMPARATOR = new Comparator() {
+ @Override
+ public int compare(PoiUIFilter o1, PoiUIFilter o2) {
+ return o1.compareTo(o2);
+ }
+ };
+
+ public enum PoiFilterType {
+ TOP_DEFINED,
+ SEARCH
+ }
public PoiFiltersHelper(OsmandApplication application) {
this.application = application;
@@ -248,6 +278,149 @@ public class PoiFiltersHelper {
return result;
}
+ public List getProfileDependentPoiUIFilters(boolean onlyActive) {
+ return getProfileDependentPoiUIFilters(onlyActive, new PoiFilterType[]{TOP_DEFINED, SEARCH});
+ }
+
+ public List getProfileDependentPoiUIFilters(boolean onlyActive, PoiFilterType[] filterTypes) {
+ initPoiUIFiltersArrangementAndActivation();
+ List result = new ArrayList<>();
+ for (PoiFilterType type : filterTypes) {
+ List filterList = new ArrayList<>();
+ switch (type) {
+ case TOP_DEFINED:
+ filterList = getTopDefinedPoiFilters();
+ break;
+ case SEARCH:
+ filterList = getSearchPoiFilters();
+ break;
+ }
+ if (onlyActive) {
+ for (PoiUIFilter f : filterList) {
+ if (f.isActive) {
+ result.add(f);
+ }
+ }
+ } else {
+ result.addAll(filterList);
+ }
+ }
+ Collections.sort(result, ORDER_COMPARATOR);
+ return result;
+ }
+
+ private void initPoiUIFiltersArrangementAndActivation() {
+ List allFilters = new ArrayList<>();
+ allFilters.addAll(getTopDefinedPoiFilters());
+ allFilters.addAll(getSearchPoiFilters());
+
+ List poiBeans = getPoiFiltersBeans();
+ Map activation = null;
+ Map arrangement = null;
+ if (poiBeans != null) {
+ activation = new HashMap<>();
+ arrangement = new HashMap<>();
+ for (PoiFilterBean filterBean : poiBeans) {
+ activation.put(filterBean.getFilterId(), filterBean.isActive);
+ arrangement.put(filterBean.getFilterId(), filterBean.getOrder());
+ }
+ }
+ reorderPoiFilters(allFilters, arrangement);
+ refreshPoiFiltersActivation(allFilters, activation);
+
+ //set up the biggest order to custom filter
+ PoiUIFilter customFilter = getCustomPOIFilter();
+ customFilter.setActive(true);
+ customFilter.setOrder(allFilters.size());
+ }
+
+ private void reorderPoiFilters(List filters, Map arrangement) {
+ boolean defaultArrangement = application.getSettings().ARRANGE_POI_FILTERS_BY_DEFAULT.get();
+ if (arrangement == null || defaultArrangement) {
+ //arrangement by default
+ Collections.sort(filters, ALPHABET_COMPARATOR);
+ for (int i = 0; i < filters.size(); i++) {
+ PoiUIFilter poiFilter = filters.get(i);
+ poiFilter.setOrder(i);
+ }
+ } else {
+ for (PoiUIFilter filter : filters) {
+ String filterId = filter.getFilterId();
+ if (arrangement.containsKey(filterId)) {
+ filter.setOrder(arrangement.get(filterId));
+ }
+ }
+ }
+ }
+
+ private void refreshPoiFiltersActivation(List allFilters, Map activation) {
+ if (activation == null) {
+ //activation by default
+ for (PoiUIFilter filter : allFilters) {
+ filter.setActive(true);
+ }
+ } else {
+ for (PoiUIFilter filter : allFilters) {
+ String filterId = filter.getFilterId();
+ if (activation.containsKey(filterId)) {
+ filter.setActive(activation.get(filterId));
+ }
+ }
+ }
+ }
+
+ public static class PoiFilterBean {
+ @Expose
+ String filterId;
+ @Expose
+ int order;
+ @Expose
+ boolean isActive;
+
+ public PoiFilterBean(String filterId, int order, boolean isActive) {
+ this.filterId = filterId;
+ this.order = order;
+ this.isActive = isActive;
+ }
+
+ public String getFilterId() {
+ return filterId;
+ }
+
+ public int getOrder() {
+ return order;
+ }
+
+ public boolean isActive() {
+ return isActive;
+ }
+
+ public void setFilterId(String filterId) {
+ this.filterId = filterId;
+ }
+
+ public void setOrder(int order) {
+ this.order = order;
+ }
+
+ public void setActive(boolean active) {
+ isActive = active;
+ }
+ }
+
+ public void savePoiFiltersBeans(List list) {
+ Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
+ String defaultProfiles = gson.toJson(list);
+ application.getSettings().POI_FILTERS_ARRANGEMENT.set(defaultProfiles);
+ }
+
+ public List getPoiFiltersBeans() {
+ Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
+ Type t = new TypeToken>() {
+ }.getType();
+ return gson.fromJson(application.getSettings().POI_FILTERS_ARRANGEMENT.get(), t);
+ }
+
private PoiFilterDbHelper openDbHelperNoPois() {
return new PoiFilterDbHelper(null, application);
}
diff --git a/OsmAnd/src/net/osmand/plus/poi/PoiUIFilter.java b/OsmAnd/src/net/osmand/plus/poi/PoiUIFilter.java
index 75bfa98d39..4c7a3a7f66 100644
--- a/OsmAnd/src/net/osmand/plus/poi/PoiUIFilter.java
+++ b/OsmAnd/src/net/osmand/plus/poi/PoiUIFilter.java
@@ -52,6 +52,8 @@ public class PoiUIFilter implements SearchPoiTypeFilter, Comparable
protected String standardIconId = "";
protected String name;
protected boolean isStandardFilter;
+ protected int order;
+ protected boolean isActive = true;
protected final OsmandApplication app;
@@ -743,6 +745,22 @@ public class PoiUIFilter implements SearchPoiTypeFilter, Comparable
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;
}
diff --git a/OsmAnd/src/net/osmand/plus/poi/RearrangePoiFiltersFragment.java b/OsmAnd/src/net/osmand/plus/poi/RearrangePoiFiltersFragment.java
new file mode 100644
index 0000000000..1dcab35f4c
--- /dev/null
+++ b/OsmAnd/src/net/osmand/plus/poi/RearrangePoiFiltersFragment.java
@@ -0,0 +1,664 @@
+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.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.search.QuickSearchCustomPoiFragment;
+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.PoiFiltersHelper.PoiFilterBean;
+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 List items = new ArrayList<>();
+ private EditPoiFiltersAdapter adapter;
+ private boolean isChanged = false;
+ private boolean orderModified = false;
+ private boolean isResetToDefault = false;
+
+ private HashMap poiFiltersOrders = new HashMap<>();
+ private List 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().ARRANGE_POI_FILTERS_BY_DEFAULT.get();
+
+ 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;
+ isResetToDefault = false;
+ 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) {
+ List savingData = new ArrayList<>();
+ for (PoiUIFilter filter : getProfileDependentPoiUiFilters(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);
+ savingData.add(new PoiFilterBean(filterId, order, isActive));
+ }
+ app.getPoiFilters().savePoiFiltersBeans(savingData);
+ app.getSettings().ARRANGE_POI_FILTERS_BY_DEFAULT.set(!orderModified);
+ } else if (isResetToDefault) {
+ app.getPoiFilters().savePoiFiltersBeans(null);
+ app.getSettings().ARRANGE_POI_FILTERS_BY_DEFAULT.set(true);
+ }
+ dismiss();
+ }
+ });
+
+ return mainView;
+ }
+
+ private void initFiltersOrders(OsmandApplication app, boolean arrangementByDefault) {
+ poiFiltersOrders.clear();
+ availableFiltersKeys.clear();
+ List filters = getProfileDependentPoiUiFilters(app);
+ if (arrangementByDefault) {
+ Collections.sort(filters);
+ for (int i = 0; i < filters.size(); i++) {
+ PoiUIFilter filter = filters.get(i);
+ poiFiltersOrders.put(filter.getFilterId(), i);
+ }
+ } else {
+ for (PoiUIFilter filter : filters) {
+ poiFiltersOrders.put(filter.getFilterId(), filter.getOrder());
+ if (!filter.isActive) {
+ availableFiltersKeys.add(filter.getFilterId());
+ }
+ }
+ }
+ updateItems();
+ }
+
+ private void updateItems() {
+ final OsmandApplication app = requireMyApplication();
+ List active = getPoiFilters(true);
+ List 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 = false;
+ orderModified = false;
+ isResetToDefault = true;
+ 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) {
+ try {
+ RearrangePoiFiltersFragment fragment = new RearrangePoiFiltersFragment();
+ fragment.setUsedOnMap(usedOnMap);
+ fragment.show(parentFragment.getChildFragmentManager(), RearrangePoiFiltersFragment.TAG);
+ } catch (RuntimeException e) {
+ LOG.error("showInstance", e);
+ }
+ }
+
+ public List getPoiFilters(boolean isActive) {
+ OsmandApplication app = requireMyApplication();
+ List result = new ArrayList<>();
+ for (PoiUIFilter f : getProfileDependentPoiUiFilters(app)) {
+ addFilterToList(result, f, isActive);
+ }
+ Collections.sort(result, new Comparator() {
+ @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 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 getProfileDependentPoiUiFilters(@NonNull OsmandApplication app) {
+ List filters = app.getPoiFilters().getProfileDependentPoiUIFilters(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;
+ }
+
+ @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;
+ }
+
+ public ListItem(ItemType type) {
+ this.type = type;
+ }
+ }
+
+ private class EditPoiFiltersAdapter extends RecyclerView.Adapter
+ implements ReorderItemTouchHelperCallback.OnItemMoveCallback {
+
+ private OsmandApplication app;
+ private UiUtilities uiUtilities;
+
+ private List 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.arrange_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 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;
+ isResetToDefault = false;
+ 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);
+ }
+}
diff --git a/OsmAnd/src/net/osmand/plus/profiles/EditProfilesFragment.java b/OsmAnd/src/net/osmand/plus/profiles/EditProfilesFragment.java
index a49f174653..51680d99b0 100644
--- a/OsmAnd/src/net/osmand/plus/profiles/EditProfilesFragment.java
+++ b/OsmAnd/src/net/osmand/plus/profiles/EditProfilesFragment.java
@@ -65,7 +65,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() {
diff --git a/OsmAnd/src/net/osmand/plus/quickaction/actions/ShowHidePoiAction.java b/OsmAnd/src/net/osmand/plus/quickaction/actions/ShowHidePoiAction.java
index 389c3a099c..9ec10fbf68 100644
--- a/OsmAnd/src/net/osmand/plus/quickaction/actions/ShowHidePoiAction.java
+++ b/OsmAnd/src/net/osmand/plus/quickaction/actions/ShowHidePoiAction.java
@@ -283,10 +283,7 @@ public class ShowHidePoiAction extends QuickAction {
final List list = new ArrayList<>();
- for (PoiUIFilter f : poiFilters.getTopDefinedPoiFilters()) {
- addFilterToList(adapter, list, f);
- }
- for (PoiUIFilter f : poiFilters.getSearchPoiFilters()) {
+ for (PoiUIFilter f : poiFilters.getProfileDependentPoiUIFilters(true)) {
addFilterToList(adapter, list, f);
}
diff --git a/OsmAnd/src/net/osmand/plus/search/QuickSearchDialogFragment.java b/OsmAnd/src/net/osmand/plus/search/QuickSearchDialogFragment.java
index 7262a9fa2f..4f95f50054 100644
--- a/OsmAnd/src/net/osmand/plus/search/QuickSearchDialogFragment.java
+++ b/OsmAnd/src/net/osmand/plus/search/QuickSearchDialogFragment.java
@@ -76,6 +76,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 +1225,13 @@ 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);
+ }
+ }));
if (categoriesSearchFragment != null) {
categoriesSearchFragment.updateListAdapter(rows, false);
}