Merge pull request #7262 from osmandapp/contextMenuForTravelPoints

WptPt context menu upgrade
This commit is contained in:
Alexey 2019-07-16 11:43:42 +03:00 committed by GitHub
commit b0996dc825
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 263 additions and 51 deletions

View file

@ -2,6 +2,7 @@ package net.osmand.plus.mapcontextmenu;
import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.ColorStateList;
import android.graphics.Color;
@ -14,6 +15,7 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.support.v4.graphics.drawable.DrawableCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.view.ContextThemeWrapper;
import android.text.ClipboardManager;
import android.text.SpannableStringBuilder;
@ -500,9 +502,23 @@ public class MenuBuilder {
needLinks, textLinesLimit, isUrl, onClickListener, matchWidthDivider);
}
public View buildRow(final View view, Drawable icon, final String buttonText, final String text, int textColor, String secondaryText,
boolean collapsable, final CollapsableView collapsableView, boolean needLinks,
int textLinesLimit, boolean isUrl, OnClickListener onClickListener, boolean matchWidthDivider) {
return buildRow(view, icon, buttonText, text, textColor, secondaryText, collapsable, collapsableView,
needLinks, textLinesLimit, isUrl, false, false, onClickListener, matchWidthDivider);
}
public View buildRow(View view, int iconId, String buttonText, String text, int textColor,
boolean collapsable, final CollapsableView collapsableView,
boolean needLinks, int textLinesLimit, boolean isUrl, boolean isNumber, boolean isEmail, OnClickListener onClickListener, boolean matchWidthDivider) {
return buildRow(view, iconId == 0 ? null : getRowIcon(iconId), buttonText, text, textColor, null, collapsable, collapsableView,
needLinks, textLinesLimit, isUrl, isNumber, isEmail, onClickListener, matchWidthDivider);
}
public View buildRow(final View view, Drawable icon, final String buttonText, final String text, int textColor, String secondaryText,
boolean collapsable, final CollapsableView collapsableView, boolean needLinks,
int textLinesLimit, boolean isUrl, OnClickListener onClickListener, boolean matchWidthDivider) {
int textLinesLimit, boolean isUrl, boolean isNumber, boolean isEmail, OnClickListener onClickListener, boolean matchWidthDivider) {
if (!isFirstRow()) {
buildRowDivider(view);
@ -567,7 +583,7 @@ public class MenuBuilder {
int linkTextColor = ContextCompat.getColor(view.getContext(), light ? R.color.ctx_menu_bottom_view_url_color_light : R.color.ctx_menu_bottom_view_url_color_dark);
if (isUrl) {
if (isUrl || isNumber || isEmail) {
textView.setTextColor(linkTextColor);
} else if (needLinks) {
Linkify.addLinks(textView, Linkify.ALL);
@ -664,6 +680,22 @@ public class MenuBuilder {
v.getContext().startActivity(intent);
}
});
} else if (isNumber) {
ll.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View v) {
showDialog(text, Intent.ACTION_DIAL, "tel:", v);
}
});
} else if (isEmail) {
ll.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_SENDTO);
intent.setData(Uri.parse("mailto:" + text));
v.getContext().startActivity(intent);
}
});
}
((LinearLayout) view).addView(baseView);
@ -674,6 +706,29 @@ public class MenuBuilder {
return ll;
}
protected void showDialog(String text, final String actionType, final String dataPrefix, final View v) {
final String[] items = text.split("[,;]");
final Intent intent = new Intent(actionType);
if (items.length > 1) {
for (int i = 0; i < items.length; i++) {
items[i] = items[i].trim();
}
AlertDialog.Builder dlg = new AlertDialog.Builder(v.getContext());
dlg.setNegativeButton(R.string.shared_string_cancel, null);
dlg.setItems(items, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
intent.setData(Uri.parse(dataPrefix + items[which]));
v.getContext().startActivity(intent);
}
});
dlg.show();
} else {
intent.setData(Uri.parse(dataPrefix + text));
v.getContext().startActivity(intent);
}
}
protected void setDividerWidth(boolean matchWidthDivider) {
this.matchWidthDivider = matchWidthDivider;

View file

@ -198,7 +198,7 @@ public abstract class MenuController extends BaseMenuController implements Colla
} else if (object instanceof OsmPoint) {
menuController = new EditPOIMenuController(mapActivity, pointDescription, (OsmPoint) object);
} else if (object instanceof WptPt) {
menuController = new WptPtMenuController(mapActivity, pointDescription, (WptPt) object);
menuController = WptPtMenuController.getInstance(mapActivity, pointDescription, (WptPt) object);
} else if (object instanceof DownloadMapObject) {
menuController = new MapDataMenuController(mapActivity, pointDescription, (DownloadMapObject) object);
} else if (object instanceof OpenStreetNote) {

View file

@ -282,24 +282,7 @@ public class AmenityMenuBuilder extends MenuBuilder {
ll.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View v) {
final String[] phones = text.split(",|;");
if (phones.length > 1) {
AlertDialog.Builder dlg = new AlertDialog.Builder(v.getContext());
dlg.setNegativeButton(R.string.shared_string_cancel, null);
dlg.setItems(phones, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:" + phones[which]));
v.getContext().startActivity(intent);
}
});
dlg.show();
} else {
Intent intent = new Intent(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:" + text));
v.getContext().startActivity(intent);
}
showDialog(text, Intent.ACTION_DIAL, "tel:", v);
}
});
} else if (isUrl) {

View file

@ -30,7 +30,6 @@ import java.util.Date;
import java.util.List;
public class WptPtMenuBuilder extends MenuBuilder {
private final WptPt wpt;
public WptPtMenuBuilder(@NonNull MapActivity mapActivity, final @NonNull WptPt wpt) {
@ -72,16 +71,11 @@ public class WptPtMenuBuilder extends MenuBuilder {
null, Algorithms.capitalizeFirstLetterAndLowercase(app.getString(R.string.plugin_distance_point_hdop)) + ": " + (int)wpt.hdop, 0,
false, null, false, 0, false, null, false);
}
if (!Algorithms.isEmpty(wpt.desc)) {
final View row = buildRow(view, R.drawable.ic_action_note_dark, null, wpt.desc, 0, false, null, true, 10, false, null, false);
row.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
POIMapLayer.showDescriptionDialog(row.getContext(), app, wpt.desc,
row.getResources().getString(R.string.shared_string_description));
}
});
prepareDescription(wpt, view);
}
if (!Algorithms.isEmpty(wpt.comment)) {
final View rowc = buildRow(view, R.drawable.ic_action_note_dark, null, wpt.comment, 0,
false, null, true, 10, false, null, false);
@ -96,6 +90,19 @@ public class WptPtMenuBuilder extends MenuBuilder {
buildPlainMenuItems(view);
}
protected void prepareDescription(final WptPt wpt, View view) {
if (!Algorithms.isEmpty(wpt.desc)) {
final View row = buildRow(view, R.drawable.ic_action_note_dark, null, wpt.desc, 0, false, null, true, 10, false, null, false);
row.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
POIMapLayer.showDescriptionDialog(row.getContext(), app, wpt.desc,
row.getResources().getString(R.string.shared_string_description));
}
});
}
}
private void buildWaypointsView(View view) {
GpxSelectionHelper gpxSelectionHelper = app.getSelectedGpxHelper();
@ -138,24 +145,32 @@ public class WptPtMenuBuilder extends MenuBuilder {
LinearLayout view = (LinearLayout) buildCollapsableContentView(context, collapsed, true);
List<WptPt> points = gpxFile.getPoints();
for (int i = 0; i < points.size() && i < 10; i++) {
final WptPt point = points.get(i);
boolean selected = selectedPoint != null && selectedPoint.equals(point);
TextViewEx button = buildButtonInCollapsableView(context, selected, false);
button.setText(point.name);
String selectedCategory = selectedPoint != null && selectedPoint.category != null ? selectedPoint.category : "";
int showCount = 0;
for (final WptPt point : points) {
String currentCategory = point != null ? point.category : null;
if (selectedCategory.equals(currentCategory)) {
showCount++;
boolean selected = selectedPoint != null && selectedPoint.equals(point);
TextViewEx button = buildButtonInCollapsableView(context, selected, false);
button.setText(point.name);
if (!selected) {
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
LatLon latLon = new LatLon(point.getLatitude(), point.getLongitude());
PointDescription pointDescription = new PointDescription(PointDescription.POINT_TYPE_WPT, point.name);
mapActivity.getContextMenu().setCenterMarker(true);
mapActivity.getContextMenu().show(latLon, pointDescription, point);
}
});
if (!selected) {
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
LatLon latLon = new LatLon(point.getLatitude(), point.getLongitude());
PointDescription pointDescription = new PointDescription(PointDescription.POINT_TYPE_WPT, point.name);
mapActivity.getContextMenu().setCenterMarker(true);
mapActivity.getContextMenu().show(latLon, pointDescription, point);
}
});
}
view.addView(button);
}
if (showCount >= 10) {
break;
}
view.addView(button);
}
if (points.size() > 10) {

View file

@ -3,7 +3,9 @@ package net.osmand.plus.mapcontextmenu.controllers;
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import net.osmand.GPXUtilities;
import net.osmand.data.LatLon;
import net.osmand.data.PointDescription;
import net.osmand.GPXUtilities.WptPt;
@ -14,27 +16,32 @@ import net.osmand.plus.MapMarkersHelper.MapMarker;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.base.FavoriteImageDrawable;
import net.osmand.plus.mapcontextmenu.MenuBuilder;
import net.osmand.plus.mapcontextmenu.MenuController;
import net.osmand.plus.mapcontextmenu.builders.WptPtMenuBuilder;
import net.osmand.plus.wikivoyage.menu.WikivoyageWptPtMenuBuilder;
import net.osmand.plus.wikivoyage.menu.WikivoyageWptPtMenuController;
import net.osmand.util.Algorithms;
import java.io.File;
import java.util.Map;
public class WptPtMenuController extends MenuController {
private WptPt wpt;
private MapMarker mapMarker;
private MapActivity mapActivity;
public WptPtMenuController(@NonNull MapActivity mapActivity, @NonNull PointDescription pointDescription, @NonNull WptPt wpt) {
super(new WptPtMenuBuilder(mapActivity, wpt), pointDescription, mapActivity);
public WptPtMenuController(@NonNull MenuBuilder menuBuilder, @NonNull MapActivity mapActivity, @NonNull PointDescription pointDescription, @NonNull final WptPt wpt) {
super(menuBuilder, pointDescription, mapActivity);
this.wpt = wpt;
this.mapActivity = mapActivity;
final MapMarkersHelper markersHelper = mapActivity.getMyApplication().getMapMarkersHelper();
mapMarker = markersHelper.getMapMarker(wpt);
if (mapMarker == null) {
mapMarker = markersHelper.getMapMarker(new LatLon(wpt.lat, wpt.lon));
}
if (mapMarker != null) {
} else {
MapMarkerMenuController markerMenuController =
new MapMarkerMenuController(mapActivity, mapMarker.getPointDescription(mapActivity), mapMarker);
leftTitleButtonController = markerMenuController.getLeftTitleButtonController();
@ -138,4 +145,16 @@ public class WptPtMenuController extends MenuController {
return "";
}
}
}
public static WptPtMenuController getInstance(@NonNull MapActivity mapActivity, @NonNull PointDescription pointDescription, @NonNull final WptPt wpt) {
SelectedGpxFile selectedGpxFile = mapActivity.getMyApplication().getSelectedGpxHelper().getSelectedGPXFile(wpt);
GPXUtilities.GPXFile gpxFile = selectedGpxFile != null ? selectedGpxFile.getGpxFile() : null;
GPXUtilities.Metadata metadata = gpxFile != null ? gpxFile.metadata : null;
Map<String, String> extensions = metadata != null ? metadata.getExtensionsToRead() : null;
String metadataDesc = extensions != null ? metadata.getExtensionsToRead().get("desc") : null;
if (metadataDesc != null && metadataDesc.contains("wikivoyage.org/")) {
return new WikivoyageWptPtMenuController(new WikivoyageWptPtMenuBuilder(mapActivity, wpt), mapActivity, pointDescription, wpt, gpxFile);
}
return new WptPtMenuController(new WptPtMenuBuilder(mapActivity, wpt), mapActivity, pointDescription, wpt);
}
}

View file

@ -0,0 +1,98 @@
package net.osmand.plus.wikivoyage.menu;
import android.support.annotation.NonNull;
import android.view.View;
import net.osmand.GPXUtilities;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.mapcontextmenu.builders.WptPtMenuBuilder;
import net.osmand.util.Algorithms;
import java.util.HashMap;
public class WikivoyageWptPtMenuBuilder extends WptPtMenuBuilder {
final String KEY_PHONE = "Phone: ";
final String KEY_EMAIL = "Email: ";
final String KEY_WORKING_HOURS = "Working hours: ";
final String KEY_PRICE = "Price: ";
final String KEY_DIRECTIONS = "Directions: ";
final String KEY_OTHER_DESCRIPTION = "Other description";
public WikivoyageWptPtMenuBuilder(@NonNull MapActivity mapActivity, @NonNull GPXUtilities.WptPt wpt) {
super(mapActivity, wpt);
}
@Override
protected void prepareDescription(final GPXUtilities.WptPt wpt, View view) {
String description = wpt.desc;
if (!description.contains("\n")) {
super.prepareDescription(wpt, view);
return;
}
HashMap<String, String> descTokens = getDescriptionTokens(description, KEY_PHONE, KEY_EMAIL, KEY_WORKING_HOURS, KEY_PRICE, KEY_DIRECTIONS);
String phones = descTokens.get(KEY_PHONE);
String emails = descTokens.get(KEY_EMAIL);
String workingHours = descTokens.get(KEY_WORKING_HOURS);
String price = descTokens.get(KEY_PRICE);
String direction = descTokens.get(KEY_DIRECTIONS);
final String desc = descTokens.get(KEY_OTHER_DESCRIPTION);
if (!Algorithms.isEmpty(desc)) {
buildRow(view, R.drawable.ic_action_note_dark, null, desc, 0, false, null, true, 10, false, null, false);
}
if (!Algorithms.isEmpty(phones)) {
buildRow(view, R.drawable.ic_action_call_dark,
null, phones, 0,
false, null, false, 0, false, true, false, null, false);
}
if (!Algorithms.isEmpty(wpt.link)) {
buildRow(view, R.drawable.ic_world_globe_dark,
null, wpt.link, 0,
false, null, false, 0, true, null, false);
}
if (!Algorithms.isEmpty(emails)) {
buildRow(view, R.drawable.ic_action_message,
null, emails, 0,
false, null, false, 0, false, false, true, null, false);
}
if (!Algorithms.isEmpty(workingHours)) {
buildRow(view, R.drawable.ic_action_time,
null, workingHours, 0,
false, null, false, 0, false, null, false);
}
if (!Algorithms.isEmpty(direction)) {
buildRow(view, R.drawable.ic_action_gdirections_dark,
null, direction, 0,
false, null, false, 0, false, null, false);
}
if (!Algorithms.isEmpty(price)) {
buildRow(view, R.drawable.ic_action_price_tag,
null, price, 0,
false, null, false, 0, false, null, false);
}
}
private HashMap<String, String> getDescriptionTokens(String desc, String ... allowedKeys) {
String[] tokens = desc.split("\n");
HashMap<String, String> mTokens = new HashMap<>();
for (String token : tokens) {
boolean matched = false;
for (String key : allowedKeys) {
if (token.startsWith(key)) {
matched = true;
String value = token.substring(key.length()).trim();
mTokens.put(key, value);
}
}
if (!matched) {
String s = mTokens.get(KEY_OTHER_DESCRIPTION);
mTokens.put(KEY_OTHER_DESCRIPTION, s != null ? s + "\n" + token : token);
}
}
return mTokens;
}
}

View file

@ -0,0 +1,42 @@
package net.osmand.plus.wikivoyage.menu;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import net.osmand.GPXUtilities;
import net.osmand.data.PointDescription;
import net.osmand.plus.GpxSelectionHelper;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.mapcontextmenu.MenuBuilder;
import net.osmand.plus.mapcontextmenu.controllers.WptPtMenuController;
import net.osmand.plus.wikivoyage.article.WikivoyageArticleDialogFragment;
import net.osmand.plus.wikivoyage.data.TravelArticle;
public class WikivoyageWptPtMenuController extends WptPtMenuController {
public WikivoyageWptPtMenuController(@NonNull MenuBuilder menuBuilder, @NonNull final MapActivity mapActivity, @NonNull PointDescription pointDescription, @NonNull GPXUtilities.WptPt wpt, GPXUtilities.GPXFile gpxFile) {
super(menuBuilder, mapActivity, pointDescription, wpt);
GPXUtilities.Metadata metadata = gpxFile != null ? gpxFile.metadata : null;
final TravelArticle article = metadata != null ? getTravelArticle(metadata) : null;
if (article != null) {
leftTitleButtonController = new TitleButtonController() {
@Override
public void buttonPressed() {
WikivoyageArticleDialogFragment.showInstance(mapActivity.getMyApplication(), mapActivity.getSupportFragmentManager(), article.getTripId(), article.getLang());
}
};
leftTitleButtonController.caption = mapActivity.getString(R.string.context_menu_read_article);
leftTitleButtonController.leftIconId = R.drawable.ic_action_read_text;
}
}
private TravelArticle getTravelArticle(@NonNull GPXUtilities.Metadata metadata) {
String title = metadata.getArticleTitle();
String lang = metadata.getArticleLang();
if (!TextUtils.isEmpty(title) && !TextUtils.isEmpty(lang)) {
return getMapActivity().getMyApplication().getTravelDbHelper().getArticle(title, lang);
}
return null;
}
}