package net.osmand.plus.search; import android.content.Context; import android.content.DialogInterface; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.v4.app.DialogFragment; import android.support.v7.app.AlertDialog; import android.support.v7.widget.AppCompatButton; import android.support.v7.widget.PopupMenu; import android.support.v7.widget.SwitchCompat; import android.support.v7.widget.Toolbar; import android.text.Editable; import android.text.TextWatcher; import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.EditText; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; import net.osmand.AndroidUtils; import net.osmand.osm.AbstractPoiType; import net.osmand.osm.MapPoiTypes; import net.osmand.osm.PoiCategory; import net.osmand.osm.PoiFilter; import net.osmand.osm.PoiType; import net.osmand.plus.IconsCache; import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandSettings; import net.osmand.plus.R; import net.osmand.plus.dialogs.DirectionsDialogs; import net.osmand.plus.poi.PoiUIFilter; import net.osmand.plus.render.RenderingIcons; import net.osmand.plus.widgets.TextViewEx; import net.osmand.util.Algorithms; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; public class QuickSearchPoiFilterFragment extends DialogFragment { public static final String TAG = "QuickSearchPoiFilterFragment"; private static final String QUICK_SEARCH_POI_FILTER_ID_KEY = "quick_search_poi_filter_id_key"; private static final String QUICK_SEARCH_POI_FILTER_BY_NAME_KEY = "quick_search_poi_filter_by_name_key"; private static final String QUICK_SEARCH_POI_FILTER_SELECTED_ADDITIONALS = "quick_search_poi_filter_selected_additionals"; private static final String QUICK_SEARCH_POI_FILTER_COLLAPSED_CATEGORIES = "quick_search_poi_filter_collapsed_categories"; private static final String QUICK_SEARCH_POI_FILTER_SHOW_ALL_CATEGORIES = "quick_search_poi_filter_show_all_categories"; private View view; private ListView listView; private PoiFilterListAdapter adapter; private PoiUIFilter filter; private String filterId; private String nameFilterText = ""; private String nameFilterTextOrig = ""; private EditText editText; private TextView applyFilterButton; private View applyFilterButtonShadow; private Set<String> selectedPoiAdditionals = new TreeSet<>(); private Set<String> selectedPoiAdditionalsOrig = new TreeSet<>(); private ArrayList<String> collapsedCategories = new ArrayList<>(); private ArrayList<String> showAllCategories = new ArrayList<>(); private Map<PoiType, String> poiAdditionalsTranslations = new HashMap<>(); public QuickSearchPoiFilterFragment() { } private OsmandApplication getMyApplication() { return (OsmandApplication) getActivity().getApplication(); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); boolean isLightTheme = getMyApplication().getSettings().OSMAND_THEME.get() == OsmandSettings.OSMAND_LIGHT_THEME; int themeId = isLightTheme ? R.style.OsmandLightTheme : R.style.OsmandDarkTheme; setStyle(STYLE_NO_FRAME, themeId); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { final OsmandApplication app = getMyApplication(); if (getArguments() != null) { filterId = getArguments().getString(QUICK_SEARCH_POI_FILTER_ID_KEY); nameFilterText = getArguments().getString(QUICK_SEARCH_POI_FILTER_BY_NAME_KEY); } else if (savedInstanceState != null) { filterId = savedInstanceState.getString(QUICK_SEARCH_POI_FILTER_ID_KEY); nameFilterText = savedInstanceState.getString(QUICK_SEARCH_POI_FILTER_BY_NAME_KEY); ArrayList<String> selectedList = savedInstanceState.getStringArrayList(QUICK_SEARCH_POI_FILTER_SELECTED_ADDITIONALS); if (selectedList != null) { selectedPoiAdditionals.addAll(selectedList); } ArrayList<String> collapsedList = savedInstanceState.getStringArrayList(QUICK_SEARCH_POI_FILTER_COLLAPSED_CATEGORIES); if (collapsedList != null) { collapsedCategories.addAll(collapsedList); } ArrayList<String> showAllList = savedInstanceState.getStringArrayList(QUICK_SEARCH_POI_FILTER_SHOW_ALL_CATEGORIES); if (showAllList != null) { showAllCategories.addAll(showAllList); } } nameFilterTextOrig = "" + nameFilterText; if (filterId != null) { filter = app.getPoiFilters().getFilterById(filterId); } if (filter == null) { filter = app.getPoiFilters().getCustomPOIFilter(); filter.clearFilter(); } if (selectedPoiAdditionals.size() == 0) { processFilterFields(); initListItems(); } selectedPoiAdditionalsOrig = new TreeSet<>(selectedPoiAdditionals); view = inflater.inflate(R.layout.search_poi_filter, container, false); TextView description = (TextView) view.findViewById(R.id.description); description.setText(filter.getName()); Toolbar toolbar = (Toolbar) view.findViewById(R.id.toolbar); toolbar.setNavigationIcon(app.getIconsCache().getIcon(R.drawable.ic_action_remove_dark)); toolbar.setNavigationContentDescription(R.string.shared_string_close); toolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { dismiss(); } }); ImageButton moreButton = (ImageButton) view.findViewById(R.id.moreButton); moreButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { IconsCache iconsCache = app.getIconsCache(); final PopupMenu optionsMenu = new PopupMenu(getContext(), v); DirectionsDialogs.setupPopUpMenuIcon(optionsMenu); MenuItem item; if (!filter.isStandardFilter()) { item = optionsMenu.getMenu().add(R.string.edit_filter).setIcon( iconsCache.getThemedIcon(R.drawable.ic_action_edit_dark)); item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { editFilter(); return true; } }); } if (!filter.isStandardFilter()) { item = optionsMenu.getMenu().add(R.string.edit_filter_save_as_menu_item).setIcon( iconsCache.getThemedIcon(R.drawable.ic_action_save)); } else { item = optionsMenu.getMenu().add(R.string.save_filter).setIcon( iconsCache.getThemedIcon(R.drawable.ic_action_save)); } item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { saveFilter(); return true; } }); if (!filter.isStandardFilter()) { item = optionsMenu.getMenu().add(R.string.delete_filter) .setIcon(iconsCache.getThemedIcon(R.drawable.ic_action_delete_dark)); item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { deleteFilter(); return true; } }); } optionsMenu.show(); } }); listView = (ListView) view.findViewById(android.R.id.list); listView.setBackgroundColor(getResources().getColor( app.getSettings().isLightContent() ? R.color.ctx_menu_info_view_bg_light : R.color.ctx_menu_info_view_bg_dark)); View editTextView = inflater.inflate(R.layout.poi_filter_list_item, listView, false); editText = (EditText) editTextView.findViewById(R.id.editText); editTextView.findViewById(R.id.divider).setVisibility(View.GONE); editText.setText(nameFilterText); editText.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override public void afterTextChanged(Editable s) { nameFilterText = s.toString(); updateApplyButton(); } }); editText.setVisibility(View.VISIBLE); final ImageView textEditIcon = (ImageView) editTextView.findViewById(R.id.icon); textEditIcon.setImageDrawable(app.getIconsCache().getThemedIcon(R.drawable.ic_action_search_dark)); textEditIcon.setVisibility(View.VISIBLE); editTextView.findViewById(R.id.titleBold).setVisibility(View.GONE); editTextView.findViewById(R.id.titleButton).setVisibility(View.GONE); editTextView.findViewById(R.id.expandItem).setVisibility(View.GONE); editTextView.findViewById(R.id.titleRegular).setVisibility(View.GONE); editTextView.findViewById(R.id.switchItem).setVisibility(View.GONE); editTextView.findViewById(R.id.checkboxItem).setVisibility(View.GONE); listView.addHeaderView(editTextView); View bottomShadowView = inflater.inflate(R.layout.list_shadow_footer, listView, false); listView.addFooterView(bottomShadowView, null, false); adapter = new PoiFilterListAdapter(app, getListItems()); listView.setAdapter(adapter); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { PoiFilterListItem item = adapter.getItem(position - listView.getHeaderViewsCount()); if (item != null) { switch (item.type) { case GROUP_HEADER: if (item.category != null) { if (collapsedCategories.contains(item.category)) { collapsedCategories.remove(item.category); } else { collapsedCategories.add(item.category); } updateListView(); } break; case CHECKBOX_ITEM: CheckBox checkBox = (CheckBox) view.findViewById(R.id.checkboxItem); adapter.toggleCheckbox(item, checkBox, !checkBox.isChecked()); break; case BUTTON_ITEM: if (item.category != null) { showAllCategories.add(item.category); updateListView(); } break; } } } }); applyFilterButtonShadow = view.findViewById(R.id.bottomButtonShadow); applyFilterButton = (TextView) view.findViewById(R.id.bottomButton); applyFilterButton.setText(app.getString(R.string.apply_filters)); applyFilterButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { applyFilterFields(); if (!filter.isStandardFilter()) { filter.setSavedFilterByName(filter.getFilterByName()); if (app.getPoiFilters().editPoiFilter(filter)) { app.getSearchUICore().refreshCustomPoiFilters(); ((QuickSearchDialogFragment) getParentFragment()).replaceQueryWithUiFilter(filter, ""); ((QuickSearchDialogFragment) getParentFragment()).reloadCategories(); dismiss(); } } else { ((QuickSearchDialogFragment) getParentFragment()).replaceQueryWithUiFilter(filter, nameFilterText.trim()); dismiss(); } } }); updateApplyButton(); return view; } private void updateApplyButton() { boolean hasChanges = !nameFilterText.equals(nameFilterTextOrig) || !selectedPoiAdditionals.equals(selectedPoiAdditionalsOrig); applyFilterButton.setVisibility(hasChanges ? View.VISIBLE : View.GONE); applyFilterButtonShadow.setVisibility(hasChanges ? View.VISIBLE : View.GONE); } private void deleteFilter() { final OsmandApplication app = getMyApplication(); AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); builder.setMessage(R.string.edit_filter_delete_dialog_title); builder.setNegativeButton(R.string.shared_string_no, null); builder.setPositiveButton(R.string.shared_string_yes, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { if (app.getPoiFilters().removePoiFilter(filter)) { Toast.makeText(getContext(), MessageFormat.format(getContext().getText(R.string.edit_filter_delete_message).toString(), filter.getName()), Toast.LENGTH_SHORT).show(); app.getSearchUICore().refreshCustomPoiFilters(); QuickSearchDialogFragment quickSearchDialogFragment = (QuickSearchDialogFragment) getParentFragment(); quickSearchDialogFragment.reloadCategories(); quickSearchDialogFragment.clearLastWord(); QuickSearchPoiFilterFragment.this.dismiss(); } } }); builder.create().show(); } private void editFilter() { QuickSearchCustomPoiFragment.showDialog(this, filter.getFilterId()); } private void saveFilter() { final OsmandApplication app = getMyApplication(); AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); builder.setTitle(R.string.access_hint_enter_name); final EditText editText = new EditText(getContext()); editText.setHint(R.string.new_filter); editText.setText(filter.getName()); final TextView textView = new TextView(getContext()); textView.setText(app.getString(R.string.new_filter_desc)); textView.setTextAppearance(getContext(), R.style.TextAppearance_ContextMenuSubtitle); LinearLayout ll = new LinearLayout(getContext()); ll.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)); ll.setOrientation(LinearLayout.VERTICAL); ll.setPadding(AndroidUtils.dpToPx(getContext(), 20f), AndroidUtils.dpToPx(getContext(), 12f), AndroidUtils.dpToPx(getContext(), 20f), AndroidUtils.dpToPx(getContext(), 12f)); ll.addView(editText, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)); textView.setPadding(AndroidUtils.dpToPx(getContext(), 4f), AndroidUtils.dpToPx(getContext(), 6f), AndroidUtils.dpToPx(getContext(), 4f), AndroidUtils.dpToPx(getContext(), 4f)); ll.addView(textView, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)); builder.setView(ll); builder.setNegativeButton(R.string.shared_string_cancel, null); builder.setPositiveButton(R.string.shared_string_save, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { PoiUIFilter nFilter = new PoiUIFilter(editText.getText().toString(), null, filter.getAcceptedTypes(), app); applyFilterFields(); if (!Algorithms.isEmpty(filter.getFilterByName())) { nFilter.setSavedFilterByName(filter.getFilterByName()); } if (app.getPoiFilters().createPoiFilter(nFilter)) { Toast.makeText(getContext(), MessageFormat.format(getContext().getText(R.string.edit_filter_create_message).toString(), editText.getText().toString()), Toast.LENGTH_SHORT).show(); app.getSearchUICore().refreshCustomPoiFilters(); ((QuickSearchDialogFragment) getParentFragment()).replaceQueryWithUiFilter(nFilter, ""); ((QuickSearchDialogFragment) getParentFragment()).reloadCategories(); QuickSearchPoiFilterFragment.this.dismiss(); } } }); builder.create().show(); } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putString(QUICK_SEARCH_POI_FILTER_ID_KEY, filterId); outState.putString(QUICK_SEARCH_POI_FILTER_BY_NAME_KEY, nameFilterText); outState.putStringArrayList(QUICK_SEARCH_POI_FILTER_SELECTED_ADDITIONALS, new ArrayList<>(selectedPoiAdditionals)); outState.putStringArrayList(QUICK_SEARCH_POI_FILTER_COLLAPSED_CATEGORIES, collapsedCategories); outState.putStringArrayList(QUICK_SEARCH_POI_FILTER_SHOW_ALL_CATEGORIES, showAllCategories); } @Override public void onDismiss(DialogInterface dialog) { hideKeyboard(); super.onDismiss(dialog); } private void hideKeyboard() { if (editText.hasFocus()) { AndroidUtils.hideSoftKeyboard(getActivity(), editText); } } private void updateListView() { adapter.setListItems(getListItems()); } private void applyFilterFields() { StringBuilder sb = new StringBuilder(); if (!Algorithms.isEmpty(nameFilterText)) { sb.append(nameFilterText); } for (String param : selectedPoiAdditionals) { if (sb.length() > 0) { sb.append(" "); } sb.append(param); } filter.setFilterByName(sb.toString()); } private void processFilterFields() { OsmandApplication app = getMyApplication(); String filterByName = filter.getFilterByName(); if (!Algorithms.isEmpty(filterByName)) { int index; MapPoiTypes poiTypes = app.getPoiTypes(); Map<String, PoiType> poiAdditionals = filter.getPoiAdditionals(); Set<String> excludedPoiAdditionalCategories = getExcludedPoiAdditionalCategories(); List<PoiType> otherAdditionalCategories = poiTypes.getOtherMapCategory().getPoiAdditionalsCategorized(); if (!excludedPoiAdditionalCategories.contains("opening_hours")) { String keyNameOpen = app.getString(R.string.shared_string_is_open).replace(' ', '_').toLowerCase(); String keyNameOpen24 = app.getString(R.string.shared_string_is_open_24_7).replace(' ', '_').toLowerCase(); index = filterByName.indexOf(keyNameOpen24); if (index != -1) { selectedPoiAdditionals.add(keyNameOpen24); filterByName = filterByName.replaceAll(keyNameOpen24, ""); } index = filterByName.indexOf(keyNameOpen); if (index != -1) { selectedPoiAdditionals.add(keyNameOpen); filterByName = filterByName.replaceAll(keyNameOpen, ""); } } if (poiAdditionals != null) { Map<String, List<PoiType>> additionalsMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); extractPoiAdditionals(poiAdditionals.values(), additionalsMap, excludedPoiAdditionalCategories, true); extractPoiAdditionals(otherAdditionalCategories, additionalsMap, excludedPoiAdditionalCategories, true); if (additionalsMap.size() > 0) { for (Entry<String, List<PoiType>> entry : additionalsMap.entrySet()) { for (PoiType poiType : entry.getValue()) { String keyName = poiType.getKeyName().replace('_', ':').toLowerCase(); index = filterByName.indexOf(keyName); if (index != -1) { selectedPoiAdditionals.add(keyName); filterByName = filterByName.replaceAll(keyName, ""); } } } } } if (filterByName.trim().length() > 0 && Algorithms.isEmpty(nameFilterText)) { nameFilterText = filterByName.trim(); } } } @NonNull private Set<String> getExcludedPoiAdditionalCategories() { Set<String> excludedPoiAdditionalCategories = new LinkedHashSet<>(); if (filter.getAcceptedTypes().size() == 0) { return excludedPoiAdditionalCategories; } MapPoiTypes poiTypes = getMyApplication().getPoiTypes(); PoiCategory topCategory = null; for (Entry<PoiCategory, LinkedHashSet<String>> entry : filter.getAcceptedTypes().entrySet()) { if (topCategory == null) { topCategory = entry.getKey(); } if (entry.getValue() != null) { Set<String> excluded = new LinkedHashSet<>(); for (String keyName : entry.getValue()) { PoiType poiType = poiTypes.getPoiTypeByKeyInCategory(topCategory, keyName); if (poiType != null) { collectExcludedPoiAdditionalCategories(poiType, excluded); if (!poiType.isReference()) { PoiFilter poiFilter = poiType.getFilter(); if (poiFilter != null) { collectExcludedPoiAdditionalCategories(poiFilter, excluded); } PoiCategory poiCategory = poiType.getCategory(); if (poiCategory != null) { collectExcludedPoiAdditionalCategories(poiCategory, excluded); } } } if (excludedPoiAdditionalCategories.size() == 0) { excludedPoiAdditionalCategories.addAll(excluded); } else { excludedPoiAdditionalCategories.retainAll(excluded); } excluded.clear(); } } } if (topCategory != null && topCategory.getExcludedPoiAdditionalCategories() != null) { excludedPoiAdditionalCategories.addAll(topCategory.getExcludedPoiAdditionalCategories()); } return excludedPoiAdditionalCategories; } private void collectExcludedPoiAdditionalCategories(AbstractPoiType abstractPoiType, Set<String> excludedPoiAdditionalCategories) { List<String> categories = abstractPoiType.getExcludedPoiAdditionalCategories(); if (categories != null) { excludedPoiAdditionalCategories.addAll(categories); } } private List<PoiFilterListItem> getListItems() { OsmandApplication app = getMyApplication(); MapPoiTypes poiTypes = app.getPoiTypes(); int groupId = 0; List<PoiFilterListItem> items = new ArrayList<>(); Map<String, PoiType> poiAdditionals = filter.getPoiAdditionals(); Set<String> excludedPoiAdditionalCategories = getExcludedPoiAdditionalCategories(); List<PoiType> otherAdditionalCategories = poiTypes.getOtherMapCategory().getPoiAdditionalsCategorized(); if (!excludedPoiAdditionalCategories.contains("opening_hours")) { items.add(new PoiFilterListItem(PoiFilterListItemType.DIVIDER, 0, null, -1, false, false, false, null, null)); String keyNameOpen = app.getString(R.string.shared_string_is_open).replace(' ', '_').toLowerCase(); items.add(new PoiFilterListItem(PoiFilterListItemType.SWITCH_ITEM, R.drawable.ic_action_time, app.getString(R.string.shared_string_is_open), ++groupId, false, false, selectedPoiAdditionals.contains(keyNameOpen), null, keyNameOpen)); String keyNameOpen24 = app.getString(R.string.shared_string_is_open_24_7).replace(' ', '_').toLowerCase(); items.add(new PoiFilterListItem(PoiFilterListItemType.SWITCH_ITEM, 0, app.getString(R.string.shared_string_is_open_24_7), groupId, false, false, selectedPoiAdditionals.contains(keyNameOpen24), null, keyNameOpen24)); } if (poiAdditionals != null) { Map<String, List<PoiType>> additionalsMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); extractPoiAdditionals(poiAdditionals.values(), additionalsMap, excludedPoiAdditionalCategories, false); extractPoiAdditionals(otherAdditionalCategories, additionalsMap, excludedPoiAdditionalCategories, false); if (additionalsMap.size() > 0) { for (Entry<String, List<PoiType>> entry : additionalsMap.entrySet()) { String category = entry.getKey(); String categoryLocalizedName = poiTypes.getPoiTranslation(category); boolean expanded = !collapsedCategories.contains(category); boolean showAll = showAllCategories.contains(category); items.add(new PoiFilterListItem(PoiFilterListItemType.DIVIDER, 0, null, -1, false, false, false, null, null)); String categoryIconStr = poiTypes.getPoiAdditionalCategoryIcon(category); int categoryIconId = 0; if (!Algorithms.isEmpty(categoryIconStr)) { categoryIconId = RenderingIcons.getBigIconResourceId(categoryIconStr); } if (categoryIconId == 0) { categoryIconId = getResources().getIdentifier("mx_" + category, "drawable", app.getPackageName()); } if (categoryIconId == 0) { categoryIconId = R.drawable.ic_action_folder_stroke; } items.add(new PoiFilterListItem(PoiFilterListItemType.GROUP_HEADER, categoryIconId, categoryLocalizedName, ++groupId, true, expanded, false, category, null)); List<PoiType> categoryPoiAdditionals = new ArrayList<>(entry.getValue()); Collections.sort(categoryPoiAdditionals, new Comparator<PoiType>() { @Override public int compare(PoiType p1, PoiType p2) { String firstPoiTypeTranslation = poiAdditionalsTranslations.get(p1); String secondPoiTypeTranslation = poiAdditionalsTranslations.get(p2); if (firstPoiTypeTranslation != null && secondPoiTypeTranslation != null) { return firstPoiTypeTranslation.compareTo(secondPoiTypeTranslation); } else { return 0; } } }); for (PoiType poiType : categoryPoiAdditionals) { String keyName = poiType.getKeyName().replace('_', ':').toLowerCase(); String translation = poiAdditionalsTranslations.get(poiType); items.add(new PoiFilterListItem(PoiFilterListItemType.CHECKBOX_ITEM, 0, translation, groupId, false, false, selectedPoiAdditionals.contains(keyName), category, keyName)); } if (!showAll && categoryPoiAdditionals.size() > 0) { items.add(new PoiFilterListItem(PoiFilterListItemType.BUTTON_ITEM, 0, app.getString(R.string.shared_string_show_all).toUpperCase(), groupId, false, false, false, category, null)); } } } } return items; } private void extractPoiAdditionals(Collection<PoiType> poiAdditionals, Map<String, List<PoiType>> additionalsMap, Set<String> excludedPoiAdditionalCategories, boolean extractAll) { for (PoiType poiType : poiAdditionals) { String category = poiType.getPoiAdditionalCategory(); if (category == null) { category = ""; } if (excludedPoiAdditionalCategories != null && excludedPoiAdditionalCategories.contains(category)) { continue; } if (collapsedCategories.contains(category) && !extractAll) { if (!additionalsMap.containsKey(category)) { additionalsMap.put(category, new ArrayList<PoiType>()); } continue; } boolean showAll = showAllCategories.contains(category) || extractAll; String keyName = poiType.getKeyName().replace('_', ':').toLowerCase(); if (!poiAdditionalsTranslations.containsKey(poiType)) { poiAdditionalsTranslations.put(poiType, poiType.getTranslation()); } if (showAll || poiType.isTopVisible() || selectedPoiAdditionals.contains(keyName.replace(' ', ':'))) { List<PoiType> adds = additionalsMap.get(category); if (adds == null) { adds = new ArrayList<>(); additionalsMap.put(category, adds); } if (!adds.contains(poiType)) { adds.add(poiType); } } } } private void initListItems() { Map<String, PoiType> poiAdditionals = filter.getPoiAdditionals(); Set<String> excludedPoiAdditionalCategories = getExcludedPoiAdditionalCategories(); List<PoiType> otherAdditionalCategories = getMyApplication().getPoiTypes().getOtherMapCategory().getPoiAdditionalsCategorized(); if (poiAdditionals != null) { initPoiAdditionals(poiAdditionals.values(), excludedPoiAdditionalCategories); initPoiAdditionals(otherAdditionalCategories, excludedPoiAdditionalCategories); } } private void initPoiAdditionals(Collection<PoiType> poiAdditionals, Set<String> excludedPoiAdditionalCategories) { Set<String> selectedCategories = new LinkedHashSet<>(); Set<String> topTrueOnlyCategories = new LinkedHashSet<>(); Set<String> topFalseOnlyCategories = new LinkedHashSet<>(); for (PoiType poiType : poiAdditionals) { String category = poiType.getPoiAdditionalCategory(); if (category != null) { topTrueOnlyCategories.add(category); topFalseOnlyCategories.add(category); } } for (PoiType poiType : poiAdditionals) { String category = poiType.getPoiAdditionalCategory(); if (category == null) { category = ""; } if (excludedPoiAdditionalCategories != null && excludedPoiAdditionalCategories.contains(category)) { topTrueOnlyCategories.remove(category); topFalseOnlyCategories.remove(category); continue; } if (!poiType.isTopVisible()) { topTrueOnlyCategories.remove(category); } else { topFalseOnlyCategories.remove(category); } String keyName = poiType.getKeyName().replace('_', ':').replace(' ', ':').toLowerCase(); if (selectedPoiAdditionals.contains(keyName)) { selectedCategories.add(category); } } for (String category : topTrueOnlyCategories) { if (!showAllCategories.contains(category)) { showAllCategories.add(category); } } for (String category : topFalseOnlyCategories) { if (!collapsedCategories.contains(category) && !showAllCategories.contains(category)) { if (!selectedCategories.contains(category)) { collapsedCategories.add(category); } showAllCategories.add(category); } } } public static void showDialog(DialogFragment parentFragment, String filterByName, String filterId) { Bundle bundle = new Bundle(); if (filterByName != null) { bundle.putString(QUICK_SEARCH_POI_FILTER_BY_NAME_KEY, filterByName); } if (filterId != null) { bundle.putString(QUICK_SEARCH_POI_FILTER_ID_KEY, filterId); } QuickSearchPoiFilterFragment fragment = new QuickSearchPoiFilterFragment(); fragment.setArguments(bundle); fragment.show(parentFragment.getChildFragmentManager(), TAG); } private class PoiFilterListAdapter extends ArrayAdapter<PoiFilterListItem> { private OsmandApplication app; PoiFilterListAdapter(OsmandApplication app, List<PoiFilterListItem> items) { super(app, R.layout.poi_filter_list_item, items); this.app = app; } public void setListItems(List<PoiFilterListItem> items) { setNotifyOnChange(false); clear(); for (PoiFilterListItem item : items) { add(item); } setNotifyOnChange(true); notifyDataSetChanged(); } @Override public int getItemViewType(int position) { PoiFilterListItem item = getItem(position); return item != null && item.type == PoiFilterListItemType.DIVIDER ? 1 : 0; } @Override public int getViewTypeCount() { return 2; } public void toggleSwitch(PoiFilterListItem item, boolean isChecked) { item.checked = isChecked; if (item.checked) { selectedPoiAdditionals.add(item.keyName); } else { selectedPoiAdditionals.remove(item.keyName); } updateApplyButton(); } public void toggleCheckbox(PoiFilterListItem item, CheckBox checkBox, boolean isChecked) { if (checkBox != null) { checkBox.setChecked(isChecked); } item.checked = isChecked; if (item.checked) { selectedPoiAdditionals.add(item.keyName); } else { selectedPoiAdditionals.remove(item.keyName); } updateApplyButton(); } @NonNull @Override public View getView(final int position, View convertView, ViewGroup parent) { final PoiFilterListItem item = getItem(position); final PoiFilterListItem nextItem = position < getCount() - 1 ? getItem(position + 1) : null; int viewType = getItemViewType(position); View view; if (convertView == null) { LayoutInflater inflater = (LayoutInflater) app.getSystemService(Context.LAYOUT_INFLATER_SERVICE); if (viewType == 0) { view = inflater.inflate(R.layout.poi_filter_list_item, null); } else { view = inflater.inflate(R.layout.list_item_divider, null); view.setOnClickListener(null); } } else { view = convertView; } if (viewType == 1) { return view; } final ImageView icon = (ImageView) view.findViewById(R.id.icon); final TextViewEx titleRegular = (TextViewEx) view.findViewById(R.id.titleRegular); final TextViewEx titleBold = (TextViewEx) view.findViewById(R.id.titleBold); final TextViewEx titleButton = (TextViewEx) view.findViewById(R.id.titleButton); final SwitchCompat switchItem = (SwitchCompat) view.findViewById(R.id.switchItem); final CheckBox checkBoxItem = (CheckBox) view.findViewById(R.id.checkboxItem); final ImageView expandItem = (ImageView) view.findViewById(R.id.expandItem); final View divider = view.findViewById(R.id.divider); if (item != null) { if (nextItem != null && nextItem.groupIndex == item.groupIndex) { divider.setVisibility(View.VISIBLE); } else { divider.setVisibility(View.GONE); } if (item.iconId != 0) { icon.setImageDrawable(app.getIconsCache().getIcon(item.iconId, app.getSettings().isLightContent() ? R.color.icon_color : R.color.color_white)); icon.setVisibility(View.VISIBLE); } else { icon.setVisibility(View.GONE); } switchItem.setOnCheckedChangeListener(null); checkBoxItem.setOnCheckedChangeListener(null); switch (item.type) { case GROUP_HEADER: titleBold.setText(item.text); if (item.expandable) { expandItem.setImageDrawable(item.expanded ? app.getIconsCache().getThemedIcon(R.drawable.ic_action_arrow_up) : app.getIconsCache().getThemedIcon(R.drawable.ic_action_arrow_down)); expandItem.setVisibility(View.VISIBLE); } else { expandItem.setVisibility(View.GONE); } titleBold.setVisibility(View.VISIBLE); titleButton.setVisibility(View.GONE); titleRegular.setVisibility(View.GONE); switchItem.setVisibility(View.GONE); checkBoxItem.setVisibility(View.GONE); break; case SWITCH_ITEM: titleRegular.setText(item.text); titleRegular.setVisibility(View.VISIBLE); switchItem.setVisibility(View.VISIBLE); switchItem.setChecked(item.checked); switchItem.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { toggleSwitch(item, isChecked); } }); titleBold.setVisibility(View.GONE); titleButton.setVisibility(View.GONE); expandItem.setVisibility(View.GONE); checkBoxItem.setVisibility(View.GONE); break; case CHECKBOX_ITEM: titleRegular.setText(item.text); titleRegular.setVisibility(View.VISIBLE); checkBoxItem.setVisibility(View.VISIBLE); checkBoxItem.setChecked(item.checked); checkBoxItem.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { toggleCheckbox(item, checkBoxItem, isChecked); } }); switchItem.setVisibility(View.GONE); titleBold.setVisibility(View.GONE); titleButton.setVisibility(View.GONE); expandItem.setVisibility(View.GONE); break; case BUTTON_ITEM: titleButton.setText(item.text); titleButton.setVisibility(View.VISIBLE); checkBoxItem.setVisibility(View.GONE); switchItem.setVisibility(View.GONE); titleBold.setVisibility(View.GONE); titleRegular.setVisibility(View.GONE); expandItem.setVisibility(View.GONE); break; } } return view; } } public enum PoiFilterListItemType { DIVIDER, GROUP_HEADER, SWITCH_ITEM, CHECKBOX_ITEM, BUTTON_ITEM } public static class PoiFilterListItem { private PoiFilterListItemType type; private int iconId; private String text; private int groupIndex; private boolean expandable; private boolean expanded; private boolean checked; private String category; private String keyName; public PoiFilterListItem(PoiFilterListItemType type, int iconId, String text, int groupIndex, boolean expandable, boolean expanded, boolean checked, String category, String keyName) { this.type = type; this.iconId = iconId; this.text = text; this.groupIndex = groupIndex; this.expandable = expandable; this.expanded = expanded; this.checked = checked; this.category = category; this.keyName = keyName; } } }