package net.osmand.plus.osmedit; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.support.annotation.Nullable; import android.text.Editable; import android.text.TextWatcher; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnFocusChangeListener; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.AutoCompleteTextView; import android.widget.Button; import android.widget.ImageButton; import android.widget.LinearLayout; import android.widget.TextView; import net.osmand.PlatformUtil; 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.osm.edit.OSMSettings; import net.osmand.plus.R; import net.osmand.plus.base.BaseOsmAndFragment; import net.osmand.util.Algorithms; import org.apache.commons.logging.Log; import java.util.HashSet; import java.util.Map; import java.util.Map.Entry; import java.util.Set; public class AdvancedEditPoiFragment extends BaseOsmAndFragment implements EditPoiDialogFragment.OnFragmentActivatedListener { private static final String TAG = "AdvancedEditPoiFragment"; private static final Log LOG = PlatformUtil.getLog(AdvancedEditPoiFragment.class); private TagAdapterLinearLayoutHack mAdapter; private EditPoiData.TagsChangedListener mTagsChangedListener; private Drawable deleteDrawable; private TextView nameTextView; private TextView amenityTagTextView; private TextView amenityTextView; @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); } @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { final View view = inflater.inflate(R.layout.fragment_edit_poi_advanced, container, false); deleteDrawable = getPaintedContentIcon(R.drawable.ic_action_remove_dark, getActivity().getResources().getColor(R.color.dash_search_icon_dark)); nameTextView = (TextView) view.findViewById(R.id.nameTextView); amenityTagTextView = (TextView) view.findViewById(R.id.amenityTagTextView); amenityTextView = (TextView) view.findViewById(R.id.amenityTextView); LinearLayout editTagsLineaLayout = (LinearLayout) view.findViewById(R.id.editTagsList); final MapPoiTypes mapPoiTypes = getMyApplication().getPoiTypes(); mAdapter = new TagAdapterLinearLayoutHack(editTagsLineaLayout, getData()); // It is possible to not restart initialization every time, and probably move initialization to appInit Map<String, PoiType> translatedTypes = getData().getAllTranslatedSubTypes(); HashSet<String> tagKeys = new HashSet<>(); HashSet<String> valueKeys = new HashSet<>(); for (AbstractPoiType abstractPoiType : translatedTypes.values()) { addPoiToStringSet(abstractPoiType, tagKeys, valueKeys); } addPoiToStringSet(mapPoiTypes.getOtherMapCategory(), tagKeys, valueKeys); mAdapter.setTagData(tagKeys.toArray(new String[tagKeys.size()])); mAdapter.setValueData(valueKeys.toArray(new String[valueKeys.size()])); Button addTagButton = (Button) view.findViewById(R.id.addTagButton); addTagButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mAdapter.addTagView("", ""); } }); return view; } @Override public void onResume() { super.onResume(); mAdapter.updateViews(); updateName(); updatePoiType(); mTagsChangedListener = new EditPoiData.TagsChangedListener() { @Override public void onTagsChanged(String anyTag) { if (Algorithms.objectEquals(anyTag, OSMSettings.OSMTagKey.NAME.getValue())) { updateName(); } if (Algorithms.objectEquals(anyTag, EditPoiData.POI_TYPE_TAG)) { updatePoiType(); } } }; getData().addListener(mTagsChangedListener); } @Override public void onPause() { super.onPause(); getData().deleteListener(mTagsChangedListener); } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); } private EditPoiDialogFragment getEditPoiFragment() { return (EditPoiDialogFragment) getParentFragment(); } private EditPoiData getData() { return getEditPoiFragment().getEditPoiData(); } @Override public void onFragmentActivated() { if(mAdapter != null) { mAdapter.updateViews(); } } private void updateName() { nameTextView.setText(getData().getTag(OSMSettings.OSMTagKey.NAME.getValue())); } private void updatePoiType() { PoiType pt = getData().getPoiTypeDefined(); if (pt != null) { amenityTagTextView.setText(pt.getOsmTag()); amenityTextView.setText(pt.getOsmValue()); } else { amenityTagTextView.setText(getData().getPoiCategory().getDefaultTag()); amenityTextView.setText(getData().getPoiTypeString()); } } public class TagAdapterLinearLayoutHack { private final LinearLayout linearLayout; private final EditPoiData editPoiData; private final ArrayAdapter<String> tagAdapter; private final ArrayAdapter<String> valueAdapter; public TagAdapterLinearLayoutHack(LinearLayout linearLayout, EditPoiData editPoiData) { this.linearLayout = linearLayout; this.editPoiData = editPoiData; tagAdapter = new ArrayAdapter<>(linearLayout.getContext(), R.layout.list_textview); valueAdapter = new ArrayAdapter<>(linearLayout.getContext(), R.layout.list_textview); } public void updateViews() { linearLayout.removeAllViews(); editPoiData.setIsInEdit(true); for (Entry<String, String> tag : editPoiData.getTagValues().entrySet()) { if (tag.getKey().equals(EditPoiData.POI_TYPE_TAG) || tag.getKey().equals(OSMSettings.OSMTagKey.NAME.getValue()) || tag.getKey().startsWith(EditPoiData.REMOVE_TAG_PREFIX)) continue; addTagView(tag.getKey(), tag.getValue()); } editPoiData.setIsInEdit(false); } public void addTagView(String tg, String vl) { View convertView = LayoutInflater.from(linearLayout.getContext()) .inflate(R.layout.poi_tag_list_item, null, false); final AutoCompleteTextView tagEditText = (AutoCompleteTextView) convertView.findViewById(R.id.tagEditText); ImageButton deleteItemImageButton = (ImageButton) convertView.findViewById(R.id.deleteItemImageButton); deleteItemImageButton.setImageDrawable(deleteDrawable); final String[] previousTag = new String[]{tg}; deleteItemImageButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { linearLayout.removeView((View) v.getParent()); editPoiData.removeTag(tagEditText.getText().toString()); } }); final AutoCompleteTextView valueEditText = (AutoCompleteTextView) convertView.findViewById(R.id.valueEditText); tagEditText.setText(tg); tagEditText.setAdapter(tagAdapter); tagEditText.setThreshold(1); tagEditText.setOnFocusChangeListener(new OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if (!hasFocus) { if (!editPoiData.isInEdit()) { String s = tagEditText.getText().toString(); editPoiData.removeTag(previousTag[0]); editPoiData.putTag(s.toString(), valueEditText.getText().toString()); previousTag[0] = s.toString(); } } else { tagAdapter.getFilter().filter(tagEditText.getText()); } } }); valueEditText.setText(vl); valueEditText.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) { if (!editPoiData.isInEdit()) { editPoiData.putTag(tagEditText.getText().toString(), s.toString()); } } }); initAutocompleteTextView(valueEditText, valueAdapter); linearLayout.addView(convertView); tagEditText.requestFocus(); } public void setTagData(String[] tags) { tagAdapter.clear(); for (String s : tags) { tagAdapter.add(s); } tagAdapter.sort(String.CASE_INSENSITIVE_ORDER); tagAdapter.notifyDataSetChanged(); } public void setValueData(String[] values) { valueAdapter.clear(); for (String s : values) { valueAdapter.add(s); } valueAdapter.sort(String.CASE_INSENSITIVE_ORDER); valueAdapter.notifyDataSetChanged(); } } private static void initAutocompleteTextView(final AutoCompleteTextView textView, final ArrayAdapter<String> adapter) { textView.setOnFocusChangeListener(new View.OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if (hasFocus) { adapter.getFilter().filter(textView.getText()); } } }); } public static void addPoiToStringSet(AbstractPoiType abstractPoiType, Set<String> stringSet, Set<String> values) { if (abstractPoiType instanceof PoiType) { PoiType poiType = (PoiType) abstractPoiType; if (poiType.isNotEditableOsm() || poiType.getBaseLangType() != null) { return; } if (poiType.getOsmTag() != null && !poiType.getOsmTag().equals(OSMSettings.OSMTagKey.NAME.getValue())) { stringSet.add(poiType.getOsmTag()); if (poiType.getOsmTag2() != null) { stringSet.add(poiType.getOsmTag2()); } } if (poiType.getOsmValue() != null) { values.add(poiType.getOsmValue()); } if (poiType.getOsmValue2() != null) { values.add(poiType.getOsmValue2()); } for (PoiType type : poiType.getPoiAdditionals()) { addPoiToStringSet(type, stringSet, values); } } else if (abstractPoiType instanceof PoiCategory) { PoiCategory poiCategory = (PoiCategory) abstractPoiType; for (PoiFilter filter : poiCategory.getPoiFilters()) { addPoiToStringSet(filter, stringSet, values); } for (PoiType poiType : poiCategory.getPoiTypes()) { addPoiToStringSet(poiType, stringSet, values); } for (PoiType poiType : poiCategory.getPoiAdditionals()) { addPoiToStringSet(poiType, stringSet, values); } } else if (abstractPoiType instanceof PoiFilter) { PoiFilter poiFilter = (PoiFilter) abstractPoiType; for (PoiType poiType : poiFilter.getPoiTypes()) { addPoiToStringSet(poiType, stringSet, values); } } else { throw new IllegalArgumentException("abstractPoiType can't be instance of class " + abstractPoiType.getClass()); } } }