From 73c1664ff8f8cb749d851e0f56845a4721d8fe6c Mon Sep 17 00:00:00 2001 From: Alexey Kulish Date: Tue, 8 Sep 2015 15:32:42 +0300 Subject: [PATCH] Context menu in progress --- .../res/layout/map_context_menu_fragment.xml | 56 ++++-- .../mapcontextmenu/BottomSectionBuilder.java | 27 +++ .../mapcontextmenu/InfoSectionBuilder.java | 166 ++++++++++++++++++ .../plus/mapcontextmenu/MapContextMenu.java | 13 +- .../MapContextMenuFragment.java | 24 +++ .../osmand/plus/views/ContextMenuLayer.java | 88 ++++++---- 6 files changed, 325 insertions(+), 49 deletions(-) create mode 100644 OsmAnd/src/net/osmand/plus/mapcontextmenu/BottomSectionBuilder.java create mode 100644 OsmAnd/src/net/osmand/plus/mapcontextmenu/InfoSectionBuilder.java diff --git a/OsmAnd/res/layout/map_context_menu_fragment.xml b/OsmAnd/res/layout/map_context_menu_fragment.xml index ca495ba479..52c903bf34 100644 --- a/OsmAnd/res/layout/map_context_menu_fragment.xml +++ b/OsmAnd/res/layout/map_context_menu_fragment.xml @@ -53,8 +53,9 @@ @@ -79,25 +80,41 @@ android:layout_marginTop="3dp" android:text="@string/other_location" android:textColor="?android:textColorSecondary" - android:textSize="@dimen/default_list_text_size"/> + android:textSize="@dimen/default_desc_text_size"/> + + + + + + + android:layout_height="1dp" + android:background="?attr/dashboard_divider"/> + android:layout_gravity="bottom"> + android:layout_width="1dp" + android:background="?attr/dashboard_divider"/> + android:layout_width="1dp" + android:background="?attr/dashboard_divider"/> + android:layout_width="1dp" + android:background="?attr/dashboard_divider"/> + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/BottomSectionBuilder.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/BottomSectionBuilder.java new file mode 100644 index 0000000000..bc393679d9 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/BottomSectionBuilder.java @@ -0,0 +1,27 @@ +package net.osmand.plus.mapcontextmenu; + +import android.graphics.drawable.Drawable; +import android.view.View; + +import net.osmand.plus.IconsCache; +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.R; + +public abstract class BottomSectionBuilder { + + protected OsmandApplication app; + + public BottomSectionBuilder(OsmandApplication app) { + this.app = app; + } + + public abstract void buildSection(View view); + + public Drawable getRowIcon(int iconId) { + IconsCache iconsCache = app.getIconsCache(); + boolean light = app.getSettings().isLightContent(); + return iconsCache.getIcon(iconId, + light ? R.color.icon_color : R.color.icon_color_light); + } + +} diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/InfoSectionBuilder.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/InfoSectionBuilder.java new file mode 100644 index 0000000000..1ffd848cc9 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/InfoSectionBuilder.java @@ -0,0 +1,166 @@ +package net.osmand.plus.mapcontextmenu; + +import android.content.res.Resources; +import android.util.AttributeSet; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import net.osmand.data.Amenity; +import net.osmand.osm.AbstractPoiType; +import net.osmand.osm.MapPoiTypes; +import net.osmand.osm.PoiType; +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.R; +import net.osmand.util.Algorithms; + +import java.util.Map; + +import static android.util.TypedValue.COMPLEX_UNIT_DIP; + +public class InfoSectionBuilder extends BottomSectionBuilder { + + private final Amenity amenity; + + public InfoSectionBuilder(OsmandApplication app, final Amenity amenity) { + super(app); + this.amenity = amenity; + } + + private void buildRow(View view, int iconId, String text) { + + /* + + + + + + + + + + + + + + + + + + */ + + + LinearLayout ll = new LinearLayout(view.getContext()); + ll.setOrientation(LinearLayout.HORIZONTAL); + ll.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); + + // Icon + LinearLayout llIcon = new LinearLayout(view.getContext()); + llIcon.setOrientation(LinearLayout.HORIZONTAL); + llIcon.setLayoutParams(new LinearLayout.LayoutParams(dpToPx(42f), ViewGroup.LayoutParams.MATCH_PARENT)); + ll.addView(llIcon); + + ImageView icon = new ImageView(view.getContext()); + ViewGroup.MarginLayoutParams llIconParams = new ViewGroup.MarginLayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + llIconParams.setMargins(dpToPx(12f), 0, 0, 0); + //llIconParams.setGravity(Gravity.CENTER_VERTICAL); + icon.setLayoutParams(llIconParams); + icon.setScaleType(ImageView.ScaleType.CENTER); + icon.setImageDrawable(getRowIcon(iconId)); + llIcon.addView(icon); + + // Text + LinearLayout llText = new LinearLayout(view.getContext()); + llText.setOrientation(LinearLayout.VERTICAL); + ViewGroup.MarginLayoutParams llTextParams = new ViewGroup.MarginLayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); + llTextParams.setMargins(0, dpToPx(4f), 0, dpToPx(4f)); + llText.setLayoutParams(llTextParams); + ll.addView(llText); + + TextView textView = new TextView(view.getContext()); + ViewGroup.MarginLayoutParams llTextViewParams = new ViewGroup.MarginLayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); + llTextViewParams.setMargins(dpToPx(10f), 0, dpToPx(10f), 0); + llText.setLayoutParams(llTextViewParams); + } + + public int dpToPx(float dp) { + Resources r = app.getResources(); + return (int) TypedValue.applyDimension( + COMPLEX_UNIT_DIP, + dp, + r.getDisplayMetrics() + ); + } + + @Override + public void buildSection(View view) { + + MapPoiTypes poiTypes = app.getPoiTypes(); + for(Map.Entry e : amenity.getAdditionalInfo().entrySet()) { + int iconId = 0; + String key = e.getKey(); + String vl = e.getValue(); + if(key.startsWith("name:")) { + continue; + } else if(Amenity.OPENING_HOURS.equals(key)) { + iconId = R.drawable.mm_clock; // todo: change icon + } else if(Amenity.PHONE.equals(key)) { + iconId = R.drawable.mm_amenity_telephone; // todo: change icon + } else if(Amenity.WEBSITE.equals(key)) { + iconId = R.drawable.mm_internet_access; // todo: change icon + } else { + iconId = R.drawable.ic_type_info; // todo: change icon + AbstractPoiType pt = poiTypes.getAnyPoiAdditionalTypeByKey(e.getKey()); + if (pt != null) { + if(pt instanceof PoiType && !((PoiType) pt).isText()) { + vl = pt.getTranslation(); + } else { + vl = /*pt.getTranslation() + ": " + */amenity.unzipContent(e.getValue()); + } + } else { + vl = /*Algorithms.capitalizeFirstLetterAndLowercase(e.getKey()) + + ": " + */amenity.unzipContent(e.getValue()); + } + } + + buildRow(view, iconId, vl); + } + } +} diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/MapContextMenu.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/MapContextMenu.java index 2048005c63..4b0d13c2f1 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/MapContextMenu.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/MapContextMenu.java @@ -134,7 +134,7 @@ public class MapContextMenu { res = typeName; } - return Algorithms.isEmpty(res) ? "Address is unknown yet" : res; + return Algorithms.isEmpty(res) ? "Address is unknown yet" : res; // todo: text constant } public String getLocationStr() { @@ -144,6 +144,17 @@ public class MapContextMenu { return foundStreetName; } + public BottomSectionBuilder getBottomSectionBuilder() { + + if (object != null) { + if (object instanceof Amenity) { + return new InfoSectionBuilder(app, (Amenity)object); + } + } + + return null; + } + public void buttonNavigatePressed() { mapActivity.getMapActions().showNavigationContextMenuPoint(pointDescription.getLat(), pointDescription.getLon()); } diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/MapContextMenuFragment.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/MapContextMenuFragment.java index a98de676c5..f1b0a35ca0 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/MapContextMenuFragment.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/MapContextMenuFragment.java @@ -126,6 +126,7 @@ public class MapContextMenuFragment extends Fragment { } }); + // Left icon IconsCache iconsCache = getMyApplication().getIconsCache(); boolean light = getMyApplication().getSettings().isLightContent(); @@ -140,12 +141,27 @@ public class MapContextMenuFragment extends Fragment { light ? R.color.icon_color : R.color.icon_color_light)); } + // Text line 1 TextView line1 = (TextView) view.findViewById(R.id.context_menu_line1); line1.setText(MapContextMenu.getInstance().getAddressStr()); + // Text line 2 TextView line2 = (TextView) view.findViewById(R.id.context_menu_line2); line2.setText(MapContextMenu.getInstance().getLocationStr()); + // Close button + final ImageView closeButtonView = (ImageView)view.findViewById(R.id.context_menu_close_btn_view); + closeButtonView.setImageDrawable(iconsCache.getIcon(R.drawable.ic_action_remove_dark, + light ? R.color.actionbar_dark_color : R.color.actionbar_light_color)); + closeButtonView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + ((MapActivity)getActivity()).getMapLayers().getContextMenuLayer().hideMapContextMenuMarker(); + dismissMenu(); + } + }); + + // Action buttons final ImageButton buttonNavigate = (ImageButton) view.findViewById(R.id.context_menu_route_button); buttonNavigate.setImageDrawable(iconsCache.getIcon(R.drawable.map_directions, light ? R.color.actionbar_dark_color : R.color.actionbar_light_color)); @@ -186,6 +202,14 @@ public class MapContextMenuFragment extends Fragment { } }); + // Bottom view + BottomSectionBuilder bottomSectionBuilder = MapContextMenu.getInstance().getBottomSectionBuilder(); + if (bottomSectionBuilder != null) { + View bottomView = view.findViewById(R.id.context_menu_bottom_view); + bottomSectionBuilder.buildSection(bottomView); + } + + /* Toolbar toolbar = (Toolbar) view.findViewById(R.id.toolbar); toolbar.setTitle(R.string.poi_create_title); diff --git a/OsmAnd/src/net/osmand/plus/views/ContextMenuLayer.java b/OsmAnd/src/net/osmand/plus/views/ContextMenuLayer.java index 0282f751cb..965f45c573 100644 --- a/OsmAnd/src/net/osmand/plus/views/ContextMenuLayer.java +++ b/OsmAnd/src/net/osmand/plus/views/ContextMenuLayer.java @@ -4,14 +4,9 @@ import android.app.AlertDialog; import android.app.AlertDialog.Builder; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; -import android.graphics.Paint; import android.graphics.PointF; -import android.graphics.PorterDuff; -import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; import android.os.Build; import android.text.Html; @@ -35,6 +30,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; public class ContextMenuLayer extends OsmandMapLayer { @@ -68,6 +64,7 @@ public class ContextMenuLayer extends OsmandMapLayer { private LatLon latLon; private String description; private Map selectedObjects = new ConcurrentHashMap(); + private Object selectedObj; private TextView textView; private ImageView closeButton; @@ -78,10 +75,8 @@ public class ContextMenuLayer extends OsmandMapLayer { private float scaleCoefficient = 1; private CallbackWithObject selectOnMap = null; - private Bitmap mapContextMarker; - private boolean showMapContextMarker; - - private Paint mapMarkerPaintIcon; + private boolean showContextMarker; + private ImageView contextMarker; public ContextMenuLayer(MapActivity activity){ this.activity = activity; @@ -130,11 +125,14 @@ public class ContextMenuLayer extends OsmandMapLayer { closeButton.setImageDrawable(view.getResources().getDrawable(R.drawable.headliner_close)); closeButton.setClickable(true); - showMapContextMarker = false; - mapMarkerPaintIcon = new Paint(); - mapMarkerPaintIcon.setColorFilter(new PorterDuffColorFilter(activity.getResources().getColor(R.color.osmand_orange), PorterDuff.Mode.SRC_IN)); - mapContextMarker = BitmapFactory.decodeResource(view.getResources(), R.drawable.ic_action_marker2); - + showContextMarker = false; + contextMarker = new ImageView(view.getContext()); + contextMarker.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); + contextMarker.setImageDrawable(view.getResources().getDrawable(R.drawable.map_pin_context_menu)); + contextMarker.setClickable(true); + int minw = contextMarker.getDrawable().getMinimumWidth(); + int minh = contextMarker.getDrawable().getMinimumHeight(); + contextMarker.layout(0, 0, minw, minh); if(latLon != null){ setLocation(latLon, description); @@ -153,8 +151,10 @@ public class ContextMenuLayer extends OsmandMapLayer { int x = (int) box.getPixXFromLatLon(latLon.getLatitude(), latLon.getLongitude()); int y = (int) box.getPixYFromLatLon(latLon.getLatitude(), latLon.getLongitude()); - if (showMapContextMarker) - canvas.drawBitmap(mapContextMarker, x - mapContextMarker.getWidth() / 2, y - mapContextMarker.getHeight(), mapMarkerPaintIcon); + if (showContextMarker) { + canvas.translate(x - contextMarker.getWidth() / 2, y - contextMarker.getHeight()); + contextMarker.draw(canvas); + } textView.setTextColor(nightMode != null && nightMode.isNightMode() ? Color.GRAY : Color.WHITE); if (textView.getText().length() > 0) { @@ -201,15 +201,15 @@ public class ContextMenuLayer extends OsmandMapLayer { } public void showMapContextMenuMarker() { - if (!showMapContextMarker) { - showMapContextMarker = true; + if (!showContextMarker) { + showContextMarker = true; view.refreshMap(); } } public void hideMapContextMenuMarker() { - if (showMapContextMarker) { - showMapContextMarker = false; + if (showContextMarker) { + showContextMarker = false; view.refreshMap(); } } @@ -273,11 +273,10 @@ public class ContextMenuLayer extends OsmandMapLayer { if (latLon != null) { if (selectedObjects.size() == 1) { setLocation(null, ""); - Object selectedObj = selectedObjects.keySet().iterator().next(); + selectedObj = selectedObjects.keySet().iterator().next(); showMapContextMenu(selectedObj, latLon); - } else { - String description = getSelectedObjectDescription(); - setLocation(latLon, description); + } else if (selectedObjects.size() > 1) { + showContextMenuForSelectedObjects(latLon); } } else { setLocation(null, ""); @@ -362,7 +361,19 @@ public class ContextMenuLayer extends OsmandMapLayer { } return 0; } - + + public boolean pressedContextMarker(RotatedTileBox tb, float px, float py) { + if (latLon != null && showContextMarker) { + Rect bs = contextMarker.getDrawable().getBounds(); + int dx = (int) (px - tb.getPixXFromLatLon(latLon.getLatitude(), latLon.getLongitude())); + int dy = (int) (py - tb.getPixYFromLatLon(latLon.getLatitude(), latLon.getLongitude())); + int bx = dx + bs.width() / 2; + int by = dy + bs.height(); + return (bs.contains(bx, by)); + } + return false; + } + public String getSelectedObjectName(){ return getSelectedObjectInfo(true); } @@ -412,6 +423,11 @@ public class ContextMenuLayer extends OsmandMapLayer { @Override public boolean onSingleTap(PointF point, RotatedTileBox tileBox) { + if (pressedContextMarker(tileBox, point.x, point.y)) { + showMapContextMenu(selectedObj, latLon); + return true; + } + boolean nativeMode = (Build.VERSION.SDK_INT >= 14) || view.getSettings().SCROLL_MAP_BY_GESTURES.get(); int val = pressedInTextView(tileBox, point.x, point.y); if(selectOnMap != null) { @@ -438,12 +454,10 @@ public class ContextMenuLayer extends OsmandMapLayer { if (latLon != null) { if (selectedObjects.size() == 1) { setLocation(null, ""); - Object selectedObj = selectedObjects.keySet().iterator().next(); + selectedObj = selectedObjects.keySet().iterator().next(); showMapContextMenu(selectedObj, latLon); - } else { - String description = getSelectedObjectDescription(); - setLocation(latLon, description); - view.refreshMap(); + } else if (selectedObjects.size() > 1) { + showContextMenuForSelectedObjects(latLon); return true; } } @@ -467,13 +481,13 @@ public class ContextMenuLayer extends OsmandMapLayer { builder.setItems(d, new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - Object selectedObj = s.get(which); + selectedObj = s.get(which); showMapContextMenu(selectedObj, l); } }); builder.show(); } else { - Object selectedObj = selectedObjects.keySet().iterator().next(); + selectedObj = selectedObjects.keySet().iterator().next(); showMapContextMenu(selectedObj, l); } } @@ -481,13 +495,15 @@ public class ContextMenuLayer extends OsmandMapLayer { private void showMapContextMenu(Object obj, LatLon latLon) { PointDescription pointDescription; if (obj != null) { - pointDescription = selectedObjects.get(obj).getObjectName(obj); - pointDescription.setLat(latLon.getLatitude()); - pointDescription.setLon(latLon.getLongitude()); + IContextMenuProvider typedObj = selectedObjects.get(obj); + pointDescription = typedObj.getObjectName(obj); + LatLon objLocation = typedObj.getObjectLocation(obj); + pointDescription.setLat(objLocation.getLatitude()); + pointDescription.setLon(objLocation.getLongitude()); } else { pointDescription = new PointDescription(latLon.getLatitude(), latLon.getLongitude()); } - this.latLon = latLon; + this.latLon = new LatLon(pointDescription.getLat(), pointDescription.getLon()); showMapContextMenuMarker(); MapContextMenu.getInstance().show(pointDescription, obj);