From 68250e6ed72eed3c5f939e7c7c77b3e75aebd075 Mon Sep 17 00:00:00 2001 From: Korusn Oleksandr Date: Wed, 4 Jan 2017 14:56:31 +0200 Subject: [PATCH] add poi action --- .../layout/quick_action_add_poi_layout.xml | 40 ++++ .../plus/osmedit/AdvancedEditPoiFragment.java | 2 +- .../plus/osmedit/EditPoiDialogFragment.java | 78 ++++--- .../plus/quickaction/QuickActionFactory.java | 205 ++++++++++++++++-- 4 files changed, 279 insertions(+), 46 deletions(-) create mode 100644 OsmAnd/res/layout/quick_action_add_poi_layout.xml diff --git a/OsmAnd/res/layout/quick_action_add_poi_layout.xml b/OsmAnd/res/layout/quick_action_add_poi_layout.xml new file mode 100644 index 0000000000..071a3e2101 --- /dev/null +++ b/OsmAnd/res/layout/quick_action_add_poi_layout.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + diff --git a/OsmAnd/src/net/osmand/plus/osmedit/AdvancedEditPoiFragment.java b/OsmAnd/src/net/osmand/plus/osmedit/AdvancedEditPoiFragment.java index d0071abef2..a7d3e853a7 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/AdvancedEditPoiFragment.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/AdvancedEditPoiFragment.java @@ -267,7 +267,7 @@ public class AdvancedEditPoiFragment extends BaseOsmAndFragment }); } - private static void addPoiToStringSet(AbstractPoiType abstractPoiType, Set stringSet, + public static void addPoiToStringSet(AbstractPoiType abstractPoiType, Set stringSet, Set values) { if (abstractPoiType instanceof PoiType) { PoiType poiType = (PoiType) abstractPoiType; diff --git a/OsmAnd/src/net/osmand/plus/osmedit/EditPoiDialogFragment.java b/OsmAnd/src/net/osmand/plus/osmedit/EditPoiDialogFragment.java index fdcea6781b..186ae49e01 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/EditPoiDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/EditPoiDialogFragment.java @@ -1,33 +1,5 @@ package net.osmand.plus.osmedit; -import java.io.Serializable; -import java.util.Comparator; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import net.osmand.CallbackWithObject; -import net.osmand.PlatformUtil; -import net.osmand.data.Amenity; -import net.osmand.data.LatLon; -import net.osmand.osm.PoiCategory; -import net.osmand.osm.PoiType; -import net.osmand.osm.edit.EntityInfo; -import net.osmand.osm.edit.Node; -import net.osmand.osm.edit.OSMSettings; -import net.osmand.plus.OsmandApplication; -import net.osmand.plus.OsmandPlugin; -import net.osmand.plus.OsmandSettings; -import net.osmand.plus.R; -import net.osmand.plus.activities.MapActivity; -import net.osmand.plus.base.BaseOsmAndDialogFragment; -import net.osmand.plus.osmedit.dialogs.PoiSubTypeDialogFragment; -import net.osmand.plus.osmedit.dialogs.PoiTypeDialogFragment; -import net.osmand.util.Algorithms; - -import org.apache.commons.logging.Log; - import android.app.Activity; import android.app.Dialog; import android.app.ProgressDialog; @@ -74,6 +46,35 @@ import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; +import net.osmand.CallbackWithObject; +import net.osmand.PlatformUtil; +import net.osmand.data.Amenity; +import net.osmand.data.LatLon; +import net.osmand.osm.PoiCategory; +import net.osmand.osm.PoiType; +import net.osmand.osm.edit.EntityInfo; +import net.osmand.osm.edit.Node; +import net.osmand.osm.edit.OSMSettings; +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.OsmandPlugin; +import net.osmand.plus.OsmandSettings; +import net.osmand.plus.R; +import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.base.BaseOsmAndDialogFragment; +import net.osmand.plus.osmedit.dialogs.PoiSubTypeDialogFragment; +import net.osmand.plus.osmedit.dialogs.PoiTypeDialogFragment; +import net.osmand.util.Algorithms; + +import org.apache.commons.logging.Log; + +import java.io.Serializable; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + public class EditPoiDialogFragment extends BaseOsmAndDialogFragment { public static final String TAG = "EditPoiDialogFragment"; private static final Log LOG = PlatformUtil.getLog(EditPoiDialogFragment.class); @@ -82,7 +83,7 @@ public class EditPoiDialogFragment extends BaseOsmAndDialogFragment { private static final String TAGS_LIST = "tags_list"; private static final String IS_ADDING_POI = "is_adding_poi"; - private static final HashSet BASIC_TAGS = new HashSet() { + public static final HashSet BASIC_TAGS = new HashSet() { { add(OSMSettings.OSMTagKey.NAME.getValue()); add(OSMSettings.OSMTagKey.ADDR_STREET.getValue()); @@ -114,6 +115,15 @@ public class EditPoiDialogFragment extends BaseOsmAndDialogFragment { Node node = (Node) getArguments().getSerializable(KEY_AMENITY_NODE); editPoiData = new EditPoiData(node, getMyApplication()); + + if (getArguments().getSerializable(TAGS_LIST) != null && view == null) { + for (Map.Entry tag : ((Map) getArguments().getSerializable(TAGS_LIST)).entrySet()) + editPoiData.putTag(tag.getKey(), tag.getValue()); + } +// if (getArguments().getSerializable(TAGS_LIST) != null && editPoiData.getTagValues().isEmpty()) { +// //noinspection unchecked +// editPoiData.updateTags((Map) getArguments().getSerializable(TAGS_LIST)); +// } } @Override @@ -574,6 +584,16 @@ public class EditPoiDialogFragment extends BaseOsmAndDialogFragment { return editPoiDialogFragment; } + public static EditPoiDialogFragment createInstance(Node node, boolean isAddingPoi, Map tagList) { + EditPoiDialogFragment editPoiDialogFragment = new EditPoiDialogFragment(); + Bundle args = new Bundle(); + args.putSerializable(KEY_AMENITY_NODE, node); + args.putBoolean(IS_ADDING_POI, isAddingPoi); + args.putSerializable(TAGS_LIST, (Serializable) Collections.unmodifiableMap(tagList)); + editPoiDialogFragment.setArguments(args); + return editPoiDialogFragment; + } + public static void showEditInstance(final Amenity amenity, final AppCompatActivity activity) { final OsmandSettings settings = ((OsmandApplication) activity.getApplication()) diff --git a/OsmAnd/src/net/osmand/plus/quickaction/QuickActionFactory.java b/OsmAnd/src/net/osmand/plus/quickaction/QuickActionFactory.java index 6d136dfba6..8fbae8aa65 100644 --- a/OsmAnd/src/net/osmand/plus/quickaction/QuickActionFactory.java +++ b/OsmAnd/src/net/osmand/plus/quickaction/QuickActionFactory.java @@ -4,24 +4,24 @@ package net.osmand.plus.quickaction; import android.app.Dialog; import android.app.ProgressDialog; import android.content.DialogInterface; -import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.support.v4.view.MotionEventCompat; import android.support.v7.app.AlertDialog; -import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.SwitchCompat; import android.support.v7.widget.helper.ItemTouchHelper; +import android.text.Editable; import android.text.TextUtils; -import android.util.Log; -import android.util.TypedValue; +import android.text.TextWatcher; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; +import android.widget.AutoCompleteTextView; import android.widget.Button; import android.widget.EditText; +import android.widget.ImageButton; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; @@ -32,7 +32,11 @@ import com.google.gson.reflect.TypeToken; import net.osmand.data.LatLon; import net.osmand.data.PointDescription; -import net.osmand.osm.PoiFilter; +import net.osmand.osm.AbstractPoiType; +import net.osmand.osm.MapPoiTypes; +import net.osmand.osm.PoiType; +import net.osmand.osm.edit.Node; +import net.osmand.osm.edit.OSMSettings; import net.osmand.plus.ContextMenuAdapter; import net.osmand.plus.ContextMenuItem; import net.osmand.plus.FavouritesDbHelper; @@ -41,12 +45,12 @@ import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandPlugin; import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; -import net.osmand.plus.activities.MapActivityLayers; import net.osmand.plus.audionotes.AudioVideoNotesPlugin; import net.osmand.plus.dialogs.ConfigureMapMenu; import net.osmand.plus.mapcontextmenu.editors.EditCategoryDialogFragment; import net.osmand.plus.mapcontextmenu.editors.SelectCategoryDialogFragment; import net.osmand.plus.openseamapsplugin.NauticalMapsPlugin; +import net.osmand.plus.osmedit.EditPoiData; import net.osmand.plus.osmedit.EditPoiDialogFragment; import net.osmand.plus.osmedit.OsmEditingPlugin; import net.osmand.plus.parkingpoint.ParkingPositionPlugin; @@ -57,18 +61,18 @@ import net.osmand.plus.render.RenderingIcons; import net.osmand.plus.views.OsmandMapTileView; import net.osmand.plus.widgets.AutoCompleteTextViewEx; import net.osmand.render.RenderingRulesStorage; -import net.osmand.search.core.CustomSearchPoiFilter; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; -import java.util.LinkedHashSet; +import java.util.LinkedHashMap; import java.util.List; -import java.util.Set; +import java.util.Map; +import java.util.Map.Entry; -import static android.util.TypedValue.COMPLEX_UNIT_DIP; +import static net.osmand.plus.osmedit.AdvancedEditPoiFragment.addPoiToStringSet; public class QuickActionFactory { @@ -1201,6 +1205,7 @@ public class QuickActionFactory { public static class AddPOIAction extends QuickAction { public static final int TYPE = 13; + public static final String KEY_TAG = "key_tag"; protected AddPOIAction() { id = System.currentTimeMillis(); @@ -1223,8 +1228,9 @@ public class QuickActionFactory { OsmEditingPlugin plugin = OsmandPlugin.getPlugin(OsmEditingPlugin.class); if (plugin != null) { EditPoiDialogFragment editPoiDialogFragment = - EditPoiDialogFragment.createAddPoiInstance(latLon.getLatitude(), latLon.getLongitude(), - activity.getMyApplication()); +// EditPoiDialogFragment.createAddPoiInstance(latLon.getLatitude(), latLon.getLongitude(), +// activity.getMyApplication()); + EditPoiDialogFragment.createInstance(new Node(latLon.getLatitude(), latLon.getLongitude(), -1), true, getTagsFromParams()); editPoiDialogFragment.show(activity.getSupportFragmentManager(), EditPoiDialogFragment.TAG); } @@ -1232,15 +1238,182 @@ public class QuickActionFactory { @Override public void drawUI(ViewGroup parent, MapActivity activity) { + final View view = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.quick_action_add_poi_layout, parent, false); - View view = LayoutInflater.from(parent.getContext()) - .inflate(R.layout.quick_action_with_text, parent, false); + OsmandApplication application = activity.getMyApplication(); + Drawable deleteDrawable = application.getIconsCache().getPaintedIcon(R.drawable.ic_action_remove_dark, + activity.getResources().getColor(R.color.dash_search_icon_dark)); - ((TextView) view.findViewById(R.id.text)).setText( - R.string.quick_action_add_poi_discr); + LinearLayout editTagsLineaLayout = + (LinearLayout) view.findViewById(R.id.editTagsList); + + final MapPoiTypes mapPoiTypes = application.getPoiTypes(); + final TagAdapterLinearLayoutHack mAdapter = new TagAdapterLinearLayoutHack(editTagsLineaLayout, getTagsFromParams(), deleteDrawable); + // It is possible to not restart initialization every time, and probably move initialization to appInit + Map translatedTypes = mapPoiTypes.getAllTranslatedNames(true); + HashSet tagKeys = new HashSet<>(); + HashSet valueKeys = new HashSet<>(); + for (AbstractPoiType abstractPoiType : translatedTypes.values()) { + addPoiToStringSet(abstractPoiType, tagKeys, valueKeys); + } + addPoiToStringSet(mapPoiTypes.getOtherMapCategory(), tagKeys, valueKeys); +// tagKeys.addAll(EditPoiDialogFragment.BASIC_TAGS); //TODO: ask for basic + 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("", ""); + } + }); + + mAdapter.updateViews(); parent.addView(view); } + + private class TagAdapterLinearLayoutHack { + private final LinearLayout linearLayout; + private final Map tagsData; + private final ArrayAdapter tagAdapter; + private final ArrayAdapter valueAdapter; + private final Drawable deleteDrawable; + + public TagAdapterLinearLayoutHack(LinearLayout linearLayout, + Map tagsData, + Drawable deleteDrawable) { + this.linearLayout = linearLayout; + this.tagsData = tagsData; + this.deleteDrawable = deleteDrawable; + + tagAdapter = new ArrayAdapter<>(linearLayout.getContext(), R.layout.list_textview); + valueAdapter = new ArrayAdapter<>(linearLayout.getContext(), R.layout.list_textview); + } + + public void updateViews() { + linearLayout.removeAllViews(); + List> entries = new ArrayList<>(tagsData.entrySet()); + for (Entry tag : entries) { + if (tag.getKey().equals(EditPoiData.POI_TYPE_TAG) + || tag.getKey().equals(OSMSettings.OSMTagKey.NAME.getValue())) + continue; + addTagView(tag.getKey(), tag.getValue()); + } + } + + 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()); + tagsData.remove(tagEditText.getText().toString()); + setTagsIntoParams(tagsData); + } + }); + final AutoCompleteTextView valueEditText = + (AutoCompleteTextView) convertView.findViewById(R.id.valueEditText); + tagEditText.setText(tg); + tagEditText.setAdapter(tagAdapter); + tagEditText.setThreshold(1); + tagEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() { + @Override + public void onFocusChange(View v, boolean hasFocus) { + if (!hasFocus) { + String s = tagEditText.getText().toString(); + tagsData.remove(previousTag[0]); + tagsData.put(s.toString(), valueEditText.getText().toString()); + previousTag[0] = s.toString(); + setTagsIntoParams(tagsData); + } 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) { + tagsData.put(tagEditText.getText().toString(), s.toString()); + setTagsIntoParams(tagsData); + } + }); + + 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 adapter) { + + textView.setOnFocusChangeListener(new View.OnFocusChangeListener() { + @Override + public void onFocusChange(View v, boolean hasFocus) { + if (hasFocus) { + adapter.getFilter().filter(textView.getText()); + } + } + }); + } + + @Override + public boolean fillParams(View root, MapActivity activity) { + return !getParams().isEmpty() && (getParams().get(KEY_TAG) != null || !getTagsFromParams().isEmpty()); + } + + private Map getTagsFromParams() { + Map quickActions = null; + if (getParams().get(KEY_TAG) != null) { + String json = getParams().get(KEY_TAG); + Type type = new TypeToken>() { + }.getType(); + quickActions = new Gson().fromJson(json, type); + } + return quickActions != null ? quickActions : new LinkedHashMap(); + } + + private void setTagsIntoParams(Map tags) { + getParams().put(KEY_TAG, new Gson().toJson(tags)); + } } public static class MapStyleAction extends QuickAction {