Merge pull request #9274 from osmandapp/gpx_context_menu
Gpx context menu UI second part
This commit is contained in:
commit
85ae2fad00
7 changed files with 377 additions and 63 deletions
|
@ -11,6 +11,7 @@
|
||||||
Thx - Hardy
|
Thx - Hardy
|
||||||
|
|
||||||
-->
|
-->
|
||||||
|
<string name="shared_string_bearing">Bearing</string>
|
||||||
<string name="quick_action_showhide_mapillary_descr">A toggle to show or hide the Mapillary layer on the map.</string>
|
<string name="quick_action_showhide_mapillary_descr">A toggle to show or hide the Mapillary layer on the map.</string>
|
||||||
<string name="quick_action_mapillary_show">Show Mapillary</string>
|
<string name="quick_action_mapillary_show">Show Mapillary</string>
|
||||||
<string name="quick_action_mapillary_hide">Hide Mapillary</string>
|
<string name="quick_action_mapillary_hide">Hide Mapillary</string>
|
||||||
|
|
|
@ -754,6 +754,10 @@ public class MenuBuilder {
|
||||||
return iconsCache.getIcon(iconId, light ? R.color.ctx_menu_bottom_view_icon_light : R.color.ctx_menu_bottom_view_icon_dark);
|
return iconsCache.getIcon(iconId, light ? R.color.ctx_menu_bottom_view_icon_light : R.color.ctx_menu_bottom_view_icon_dark);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Drawable getThemedIcon(int iconId) {
|
||||||
|
return app.getUIUtilities().getThemedIcon(iconId);
|
||||||
|
}
|
||||||
|
|
||||||
public Drawable getRowIcon(Context ctx, String fileName) {
|
public Drawable getRowIcon(Context ctx, String fileName) {
|
||||||
Drawable d = RenderingIcons.getBigIcon(ctx, fileName);
|
Drawable d = RenderingIcons.getBigIcon(ctx, fileName);
|
||||||
if (d != null) {
|
if (d != null) {
|
||||||
|
|
|
@ -32,7 +32,6 @@ import net.osmand.data.TransportStop;
|
||||||
import net.osmand.map.OsmandRegions;
|
import net.osmand.map.OsmandRegions;
|
||||||
import net.osmand.map.WorldRegion;
|
import net.osmand.map.WorldRegion;
|
||||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
|
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
|
||||||
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
|
|
||||||
import net.osmand.plus.MapMarkersHelper.MapMarker;
|
import net.osmand.plus.MapMarkersHelper.MapMarker;
|
||||||
import net.osmand.plus.OsmAndFormatter;
|
import net.osmand.plus.OsmAndFormatter;
|
||||||
import net.osmand.plus.OsmandApplication;
|
import net.osmand.plus.OsmandApplication;
|
||||||
|
@ -61,6 +60,7 @@ import net.osmand.plus.mapcontextmenu.controllers.MyLocationMenuController;
|
||||||
import net.osmand.plus.mapcontextmenu.controllers.PointDescriptionMenuController;
|
import net.osmand.plus.mapcontextmenu.controllers.PointDescriptionMenuController;
|
||||||
import net.osmand.plus.mapcontextmenu.controllers.RenderedObjectMenuController;
|
import net.osmand.plus.mapcontextmenu.controllers.RenderedObjectMenuController;
|
||||||
import net.osmand.plus.mapcontextmenu.controllers.SelectedGpxMenuController;
|
import net.osmand.plus.mapcontextmenu.controllers.SelectedGpxMenuController;
|
||||||
|
import net.osmand.plus.mapcontextmenu.controllers.SelectedGpxMenuController.SelectedGpxPoint;
|
||||||
import net.osmand.plus.mapcontextmenu.controllers.TargetPointMenuController;
|
import net.osmand.plus.mapcontextmenu.controllers.TargetPointMenuController;
|
||||||
import net.osmand.plus.mapcontextmenu.controllers.TransportRouteController;
|
import net.osmand.plus.mapcontextmenu.controllers.TransportRouteController;
|
||||||
import net.osmand.plus.mapcontextmenu.controllers.TransportStopController;
|
import net.osmand.plus.mapcontextmenu.controllers.TransportStopController;
|
||||||
|
@ -229,8 +229,8 @@ public abstract class MenuController extends BaseMenuController implements Colla
|
||||||
menuController = new RenderedObjectMenuController(mapActivity, pointDescription, (RenderedObject) object);
|
menuController = new RenderedObjectMenuController(mapActivity, pointDescription, (RenderedObject) object);
|
||||||
} else if (object instanceof MapillaryImage) {
|
} else if (object instanceof MapillaryImage) {
|
||||||
menuController = new MapillaryMenuController(mapActivity, pointDescription, (MapillaryImage) object);
|
menuController = new MapillaryMenuController(mapActivity, pointDescription, (MapillaryImage) object);
|
||||||
} else if (object instanceof SelectedGpxFile) {
|
} else if (object instanceof SelectedGpxPoint) {
|
||||||
menuController = new SelectedGpxMenuController(mapActivity, pointDescription, (SelectedGpxFile) object);
|
menuController = new SelectedGpxMenuController(mapActivity, pointDescription, (SelectedGpxPoint) object);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (menuController == null) {
|
if (menuController == null) {
|
||||||
|
|
|
@ -0,0 +1,214 @@
|
||||||
|
package net.osmand.plus.mapcontextmenu.builders;
|
||||||
|
|
||||||
|
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 androidx.annotation.NonNull;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
|
||||||
|
import net.osmand.AndroidUtils;
|
||||||
|
import net.osmand.GPXUtilities.GPXTrackAnalysis;
|
||||||
|
import net.osmand.GPXUtilities.WptPt;
|
||||||
|
import net.osmand.plus.OsmAndFormatter;
|
||||||
|
import net.osmand.plus.R;
|
||||||
|
import net.osmand.plus.UiUtilities;
|
||||||
|
import net.osmand.plus.activities.MapActivity;
|
||||||
|
import net.osmand.plus.helpers.AndroidUiHelper;
|
||||||
|
import net.osmand.plus.mapcontextmenu.MenuBuilder;
|
||||||
|
import net.osmand.plus.mapcontextmenu.controllers.SelectedGpxMenuController.SelectedGpxPoint;
|
||||||
|
import net.osmand.util.Algorithms;
|
||||||
|
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
|
||||||
|
public class SelectedGpxMenuBuilder extends MenuBuilder {
|
||||||
|
|
||||||
|
private SelectedGpxPoint selectedGpxPoint;
|
||||||
|
private GPXTrackAnalysis analysis;
|
||||||
|
private WptPt selectedPoint;
|
||||||
|
|
||||||
|
public SelectedGpxMenuBuilder(@NonNull MapActivity mapActivity, @NonNull SelectedGpxPoint selectedGpxPoint) {
|
||||||
|
super(mapActivity);
|
||||||
|
this.selectedGpxPoint = selectedGpxPoint;
|
||||||
|
selectedPoint = selectedGpxPoint.getSelectedPoint();
|
||||||
|
analysis = selectedGpxPoint.getSelectedGpxFile().getTrackAnalysis(mapActivity.getMyApplication());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean needBuildPlainMenuItems() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean needBuildCoordinatesRow() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void buildInternal(View view) {
|
||||||
|
buildOverviewRows(view);
|
||||||
|
buildElevationRows(view);
|
||||||
|
buildSpeedRows(view);
|
||||||
|
buildPointRows(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void buildOverviewRows(View view) {
|
||||||
|
buildCategoryView(view, app.getString(R.string.shared_string_overview));
|
||||||
|
|
||||||
|
buildRow(view, getThemedIcon(R.drawable.ic_action_polygom_dark), null, app.getString(R.string.distance),
|
||||||
|
OsmAndFormatter.getFormattedDistance(analysis.totalDistance, app), 0, null,
|
||||||
|
false, null, false, 0, false, false, false, null, false);
|
||||||
|
|
||||||
|
String timeSpan = Algorithms.formatDuration((int) (analysis.timeSpan / 1000), app.accessibilityEnabled());
|
||||||
|
String timeMoving = Algorithms.formatDuration((int) (analysis.timeMoving / 1000), app.accessibilityEnabled());
|
||||||
|
String title = app.getString(R.string.shared_string_time_span) + " / " + app.getString(R.string.shared_string_time_moving);
|
||||||
|
buildRow(view, getThemedIcon(R.drawable.ic_action_time_span), null, title,
|
||||||
|
timeSpan + " / " + timeMoving, 0, null,
|
||||||
|
false, null, false, 0, false, false, false, null, false);
|
||||||
|
|
||||||
|
Date start = new Date(analysis.startTime);
|
||||||
|
Date end = new Date(analysis.endTime);
|
||||||
|
DateFormat format = SimpleDateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
|
||||||
|
buildRow(view, getThemedIcon(R.drawable.ic_action_time_start), null, app.getString(R.string.shared_string_start_time),
|
||||||
|
format.format(start) + " / " + format.format(end), 0, null,
|
||||||
|
false, null, false, 0, false, false, false, null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void buildElevationRows(View view) {
|
||||||
|
if (analysis.isElevationSpecified()) {
|
||||||
|
buildCategoryView(view, app.getString(R.string.altitude));
|
||||||
|
|
||||||
|
buildRow(view, getThemedIcon(R.drawable.ic_action_altitude_average), null, app.getString(R.string.average_altitude),
|
||||||
|
OsmAndFormatter.getFormattedAlt(analysis.avgElevation, app), 0, null,
|
||||||
|
false, null, false, 0, false, false, false, null, false);
|
||||||
|
|
||||||
|
String min = OsmAndFormatter.getFormattedAlt(analysis.minElevation, app);
|
||||||
|
String max = OsmAndFormatter.getFormattedAlt(analysis.maxElevation, app);
|
||||||
|
buildRow(view, getThemedIcon(R.drawable.ic_action_altitude_range_16), null, app.getString(R.string.altitude_range),
|
||||||
|
min + " - " + max, 0, null,
|
||||||
|
false, null, false, 0, false, false, false, null, false);
|
||||||
|
|
||||||
|
String asc = OsmAndFormatter.getFormattedAlt(analysis.diffElevationUp, app);
|
||||||
|
String desc = OsmAndFormatter.getFormattedAlt(analysis.diffElevationDown, app);
|
||||||
|
buildRow(view, getThemedIcon(R.drawable.ic_action_altitude_descent), null, app.getString(R.string.ascent_descent),
|
||||||
|
asc + " / " + desc, 0, null,
|
||||||
|
false, null, false, 0, false, false, false, null, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void buildSpeedRows(View view) {
|
||||||
|
if (analysis.isSpeedSpecified()) {
|
||||||
|
buildCategoryView(view, app.getString(R.string.map_widget_speed));
|
||||||
|
|
||||||
|
buildRow(view, getThemedIcon(R.drawable.ic_action_speed), null, app.getString(R.string.average_speed),
|
||||||
|
OsmAndFormatter.getFormattedSpeed(analysis.avgSpeed, app), 0, null,
|
||||||
|
false, null, false, 0, false, false, false, null, false);
|
||||||
|
|
||||||
|
buildRow(view, getThemedIcon(R.drawable.ic_action_max_speed), null, app.getString(R.string.max_speed),
|
||||||
|
OsmAndFormatter.getFormattedSpeed(analysis.maxSpeed, app), 0, null,
|
||||||
|
false, null, false, 0, false, false, false, null, false);
|
||||||
|
|
||||||
|
buildRow(view, getThemedIcon(R.drawable.ic_action_altitude_descent), null, app.getString(R.string.distance_moving),
|
||||||
|
OsmAndFormatter.getFormattedDistance(analysis.totalDistanceMoving, app), 0, null,
|
||||||
|
false, null, false, 0, false, false, false, null, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void buildPointRows(View view) {
|
||||||
|
buildCategoryView(view, app.getString(R.string.plugin_distance_point));
|
||||||
|
|
||||||
|
buildRow(view, getThemedIcon(R.drawable.ic_action_polygom_dark), null, app.getString(R.string.distance),
|
||||||
|
OsmAndFormatter.getFormattedDistance((float) selectedPoint.distance, app), 0, null,
|
||||||
|
false, null, false, 0, false, false, false, null, false);
|
||||||
|
|
||||||
|
if (selectedPoint.time != 0) {
|
||||||
|
DateFormat format = SimpleDateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
|
||||||
|
buildRow(view, getThemedIcon(R.drawable.ic_action_time_start), null, app.getString(R.string.shared_string_time),
|
||||||
|
format.format(selectedPoint.time), 0, null,
|
||||||
|
false, null, false, 0, false, false, false, null, true);
|
||||||
|
}
|
||||||
|
if (!Double.isNaN(selectedPoint.ele)) {
|
||||||
|
buildRow(view, getThemedIcon(R.drawable.ic_action_altitude), null, app.getString(R.string.altitude),
|
||||||
|
OsmAndFormatter.getFormattedAlt(selectedPoint.ele, app), 0, null,
|
||||||
|
false, null, false, 0, false, false, false, null, false);
|
||||||
|
}
|
||||||
|
if (!Double.isNaN(selectedPoint.speed)) {
|
||||||
|
buildRow(view, getThemedIcon(R.drawable.ic_action_speed), null, app.getString(R.string.average_speed),
|
||||||
|
OsmAndFormatter.getFormattedSpeed((float) selectedPoint.speed, app), 0, null,
|
||||||
|
false, null, false, 0, false, false, false, null, false);
|
||||||
|
}
|
||||||
|
if (selectedGpxPoint.getPointLocation().hasBearing()) {
|
||||||
|
buildRow(view, getThemedIcon(R.drawable.ic_action_relative_bearing), null, app.getString(R.string.shared_string_bearing),
|
||||||
|
OsmAndFormatter.getFormattedAzimuth(selectedGpxPoint.getPointLocation().getBearing(), app), 0, null,
|
||||||
|
false, null, false, 0, false, false, false, null, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void buildCategoryView(View view, String name) {
|
||||||
|
if (!isFirstRow()) {
|
||||||
|
buildRowDivider(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
View categoryView = UiUtilities.getInflater(view.getContext(), !light).inflate(R.layout.preference_category_with_descr, (ViewGroup) view, false);
|
||||||
|
|
||||||
|
AndroidUiHelper.updateVisibility(categoryView.findViewById(android.R.id.icon), false);
|
||||||
|
AndroidUiHelper.updateVisibility(categoryView.findViewById(android.R.id.summary), false);
|
||||||
|
|
||||||
|
TextView title = categoryView.findViewById(android.R.id.title);
|
||||||
|
title.setText(name);
|
||||||
|
|
||||||
|
((LinearLayout) view).addView(categoryView);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasCustomAddressLine() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void buildCustomAddressLine(LinearLayout ll) {
|
||||||
|
int gpxSmallIconMargin = (int) ll.getResources().getDimension(R.dimen.gpx_small_icon_margin);
|
||||||
|
int gpxSmallTextMargin = (int) ll.getResources().getDimension(R.dimen.gpx_small_text_margin);
|
||||||
|
float gpxTextSize = ll.getResources().getDimension(R.dimen.default_desc_text_size);
|
||||||
|
|
||||||
|
int textColor = ContextCompat.getColor(ll.getContext(), light ? R.color.text_color_primary_light : R.color.text_color_primary_dark);
|
||||||
|
|
||||||
|
buildIcon(ll, gpxSmallIconMargin, R.drawable.ic_action_distance_16);
|
||||||
|
buildTextView(ll, gpxSmallTextMargin, gpxTextSize, textColor,
|
||||||
|
OsmAndFormatter.getFormattedDistance(analysis.totalDistance, app));
|
||||||
|
|
||||||
|
buildIcon(ll, gpxSmallIconMargin, R.drawable.ic_action_waypoint_16);
|
||||||
|
buildTextView(ll, gpxSmallTextMargin, gpxTextSize, textColor, "" + analysis.wptPoints);
|
||||||
|
|
||||||
|
buildIcon(ll, gpxSmallIconMargin, R.drawable.ic_action_time_16);
|
||||||
|
buildTextView(ll, gpxSmallTextMargin, gpxTextSize, textColor,
|
||||||
|
Algorithms.formatDuration((int) (analysis.timeSpan / 1000), app.accessibilityEnabled()) + "");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void buildIcon(LinearLayout ll, int gpxSmallIconMargin, int iconId) {
|
||||||
|
ImageView icon = new ImageView(ll.getContext());
|
||||||
|
LinearLayout.LayoutParams llIconParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||||
|
AndroidUtils.setMargins(llIconParams, 0, 0, gpxSmallIconMargin, 0);
|
||||||
|
llIconParams.gravity = Gravity.CENTER_VERTICAL;
|
||||||
|
icon.setLayoutParams(llIconParams);
|
||||||
|
icon.setImageDrawable(app.getUIUtilities().getThemedIcon(iconId));
|
||||||
|
ll.addView(icon);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void buildTextView(LinearLayout ll, int gpxSmallTextMargin, float gpxTextSize, int textColor, String text) {
|
||||||
|
TextView textView = new TextView(ll.getContext());
|
||||||
|
LinearLayout.LayoutParams llTextParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||||
|
AndroidUtils.setMargins(llTextParams, 0, 0, gpxSmallTextMargin, 0);
|
||||||
|
textView.setLayoutParams(llTextParams);
|
||||||
|
textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, gpxTextSize);
|
||||||
|
textView.setTextColor(textColor);
|
||||||
|
textView.setText(text);
|
||||||
|
ll.addView(textView);
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,7 +7,10 @@ import android.os.AsyncTask;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import net.osmand.AndroidUtils;
|
||||||
import net.osmand.GPXUtilities;
|
import net.osmand.GPXUtilities;
|
||||||
|
import net.osmand.GPXUtilities.WptPt;
|
||||||
|
import net.osmand.Location;
|
||||||
import net.osmand.data.PointDescription;
|
import net.osmand.data.PointDescription;
|
||||||
import net.osmand.plus.GpxSelectionHelper;
|
import net.osmand.plus.GpxSelectionHelper;
|
||||||
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
|
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
|
||||||
|
@ -16,27 +19,30 @@ import net.osmand.plus.R;
|
||||||
import net.osmand.plus.activities.MapActivity;
|
import net.osmand.plus.activities.MapActivity;
|
||||||
import net.osmand.plus.activities.TrackActivity;
|
import net.osmand.plus.activities.TrackActivity;
|
||||||
import net.osmand.plus.helpers.GpxUiHelper;
|
import net.osmand.plus.helpers.GpxUiHelper;
|
||||||
import net.osmand.plus.mapcontextmenu.MenuBuilder;
|
|
||||||
import net.osmand.plus.mapcontextmenu.MenuController;
|
import net.osmand.plus.mapcontextmenu.MenuController;
|
||||||
|
import net.osmand.plus.mapcontextmenu.builders.SelectedGpxMenuBuilder;
|
||||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class SelectedGpxMenuController extends MenuController {
|
public class SelectedGpxMenuController extends MenuController {
|
||||||
|
|
||||||
private SelectedGpxFile item;
|
private SelectedGpxPoint selectedGpxPoint;
|
||||||
|
|
||||||
public SelectedGpxMenuController(@NonNull final MapActivity mapActivity, @NonNull PointDescription pointDescription, @NonNull final SelectedGpxFile item) {
|
public SelectedGpxMenuController(@NonNull final MapActivity mapActivity, @NonNull PointDescription pointDescription,
|
||||||
super(new MenuBuilder(mapActivity), pointDescription, mapActivity);
|
@NonNull final SelectedGpxPoint selectedGpxPoint) {
|
||||||
this.item = item;
|
super(new SelectedGpxMenuBuilder(mapActivity, selectedGpxPoint), pointDescription, mapActivity);
|
||||||
|
this.selectedGpxPoint = selectedGpxPoint;
|
||||||
|
builder.setShowOnlinePhotos(false);
|
||||||
|
|
||||||
leftTitleButtonController = new TitleButtonController() {
|
leftTitleButtonController = new TitleButtonController() {
|
||||||
@Override
|
@Override
|
||||||
public void buttonPressed() {
|
public void buttonPressed() {
|
||||||
Intent intent = new Intent(mapActivity, mapActivity.getMyApplication().getAppCustomization().getTrackActivity());
|
Intent intent = new Intent(mapActivity, mapActivity.getMyApplication().getAppCustomization().getTrackActivity());
|
||||||
intent.putExtra(TrackActivity.TRACK_FILE_NAME, item.getGpxFile().path);
|
intent.putExtra(TrackActivity.TRACK_FILE_NAME, selectedGpxPoint.getSelectedGpxFile().getGpxFile().path);
|
||||||
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
|
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
|
||||||
mapActivity.startActivity(intent);
|
mapActivity.startActivity(intent);
|
||||||
}
|
}
|
||||||
|
@ -47,30 +53,41 @@ public class SelectedGpxMenuController extends MenuController {
|
||||||
rightTitleButtonController = new TitleButtonController() {
|
rightTitleButtonController = new TitleButtonController() {
|
||||||
@Override
|
@Override
|
||||||
public void buttonPressed() {
|
public void buttonPressed() {
|
||||||
new OpenGpxDetailsTask(item).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
new OpenGpxDetailsTask(selectedGpxPoint.getSelectedGpxFile(), selectedGpxPoint.getSelectedPoint(), mapActivity).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
rightTitleButtonController.caption = mapActivity.getString(R.string.analyze_on_map);
|
rightTitleButtonController.caption = mapActivity.getString(R.string.analyze_on_map);
|
||||||
rightTitleButtonController.startIconId = R.drawable.ic_action_track_16;
|
rightTitleButtonController.startIconId = R.drawable.ic_action_track_16;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class OpenGpxDetailsTask extends AsyncTask<Void, Void, GpxSelectionHelper.GpxDisplayItem> {
|
private static class OpenGpxDetailsTask extends AsyncTask<Void, Void, GpxSelectionHelper.GpxDisplayItem> {
|
||||||
|
|
||||||
private SelectedGpxFile item;
|
private OsmandApplication app;
|
||||||
ProgressDialog progressDialog;
|
|
||||||
|
|
||||||
OpenGpxDetailsTask(SelectedGpxFile item) {
|
private WptPt selectedPoint;
|
||||||
this.item = item;
|
private SelectedGpxFile selectedGpxFile;
|
||||||
|
|
||||||
|
private ProgressDialog progressDialog;
|
||||||
|
private WeakReference<MapActivity> activityRef;
|
||||||
|
|
||||||
|
OpenGpxDetailsTask(SelectedGpxFile selectedGpxFile, WptPt selectedPoint, MapActivity mapActivity) {
|
||||||
|
app = mapActivity.getMyApplication();
|
||||||
|
this.activityRef = new WeakReference<>(mapActivity);
|
||||||
|
this.selectedGpxFile = selectedGpxFile;
|
||||||
|
this.selectedPoint = selectedPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPreExecute() {
|
protected void onPreExecute() {
|
||||||
if (item.getGpxFile().path != null) {
|
MapActivity activity = activityRef.get();
|
||||||
progressDialog = new ProgressDialog(getMapActivity());
|
if (activity != null && AndroidUtils.isActivityNotDestroyed(activity)) {
|
||||||
progressDialog.setTitle("");
|
if (selectedGpxFile.getGpxFile().path != null) {
|
||||||
progressDialog.setMessage(getMapActivity().getResources().getString(R.string.loading_data));
|
progressDialog = new ProgressDialog(activity);
|
||||||
progressDialog.setCancelable(false);
|
progressDialog.setTitle("");
|
||||||
progressDialog.show();
|
progressDialog.setMessage(app.getString(R.string.loading_data));
|
||||||
|
progressDialog.setCancelable(false);
|
||||||
|
progressDialog.show();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,13 +96,12 @@ public class SelectedGpxMenuController extends MenuController {
|
||||||
GpxSelectionHelper.GpxDisplayGroup gpxDisplayGroup = null;
|
GpxSelectionHelper.GpxDisplayGroup gpxDisplayGroup = null;
|
||||||
GPXUtilities.GPXFile gpxFile = null;
|
GPXUtilities.GPXFile gpxFile = null;
|
||||||
GPXUtilities.Track generalTrack = null;
|
GPXUtilities.Track generalTrack = null;
|
||||||
if (item.getGpxFile().path != null) {
|
if (selectedGpxFile.getGpxFile().path != null) {
|
||||||
gpxFile = GPXUtilities.loadGPXFile(new File(item.getGpxFile().path));
|
gpxFile = GPXUtilities.loadGPXFile(new File(selectedGpxFile.getGpxFile().path));
|
||||||
}
|
}
|
||||||
if (gpxFile != null) {
|
if (gpxFile != null) {
|
||||||
generalTrack = gpxFile.getGeneralTrack();
|
generalTrack = gpxFile.getGeneralTrack();
|
||||||
}
|
}
|
||||||
OsmandApplication app = getMapActivity().getMyApplication();
|
|
||||||
if (generalTrack != null) {
|
if (generalTrack != null) {
|
||||||
gpxFile.addGeneralTrack();
|
gpxFile.addGeneralTrack();
|
||||||
gpxDisplayGroup = app.getSelectedGpxHelper().buildGeneralGpxDisplayGroup(gpxFile, generalTrack);
|
gpxDisplayGroup = app.getSelectedGpxHelper().buildGeneralGpxDisplayGroup(gpxFile, generalTrack);
|
||||||
|
@ -104,47 +120,48 @@ public class SelectedGpxMenuController extends MenuController {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPostExecute(GpxSelectionHelper.GpxDisplayItem gpxItem) {
|
protected void onPostExecute(GpxSelectionHelper.GpxDisplayItem gpxItem) {
|
||||||
if (progressDialog != null) {
|
MapActivity activity = activityRef.get();
|
||||||
progressDialog.dismiss();
|
if (activity != null) {
|
||||||
}
|
if (progressDialog != null && AndroidUtils.isActivityNotDestroyed(activity)) {
|
||||||
if (gpxItem != null && gpxItem.analysis != null) {
|
progressDialog.dismiss();
|
||||||
ArrayList<GpxUiHelper.GPXDataSetType> list = new ArrayList<>();
|
|
||||||
if (gpxItem.analysis.hasElevationData) {
|
|
||||||
list.add(GpxUiHelper.GPXDataSetType.ALTITUDE);
|
|
||||||
}
|
}
|
||||||
if (gpxItem.analysis.hasSpeedData) {
|
if (gpxItem != null && gpxItem.analysis != null) {
|
||||||
list.add(GpxUiHelper.GPXDataSetType.SPEED);
|
ArrayList<GpxUiHelper.GPXDataSetType> list = new ArrayList<>();
|
||||||
} else if (gpxItem.analysis.hasElevationData) {
|
if (gpxItem.analysis.hasElevationData) {
|
||||||
list.add(GpxUiHelper.GPXDataSetType.SLOPE);
|
list.add(GpxUiHelper.GPXDataSetType.ALTITUDE);
|
||||||
|
}
|
||||||
|
if (gpxItem.analysis.hasSpeedData) {
|
||||||
|
list.add(GpxUiHelper.GPXDataSetType.SPEED);
|
||||||
|
} else if (gpxItem.analysis.hasElevationData) {
|
||||||
|
list.add(GpxUiHelper.GPXDataSetType.SLOPE);
|
||||||
|
}
|
||||||
|
if (list.size() > 0) {
|
||||||
|
gpxItem.chartTypes = list.toArray(new GpxUiHelper.GPXDataSetType[0]);
|
||||||
|
}
|
||||||
|
gpxItem.locationOnMap = selectedPoint;
|
||||||
|
OsmandSettings settings = app.getSettings();
|
||||||
|
settings.setMapLocationToShow(gpxItem.locationStart.lat, gpxItem.locationStart.lon,
|
||||||
|
settings.getLastKnownMapZoom(),
|
||||||
|
new PointDescription(PointDescription.POINT_TYPE_WPT, gpxItem.name),
|
||||||
|
false,
|
||||||
|
gpxItem);
|
||||||
|
activity.getContextMenu().hide();
|
||||||
|
MapActivity.launchMapActivityMoveToTop(activity);
|
||||||
}
|
}
|
||||||
if (list.size() > 0) {
|
|
||||||
gpxItem.chartTypes = list.toArray(new GpxUiHelper.GPXDataSetType[list.size()]);
|
|
||||||
}
|
|
||||||
|
|
||||||
MapActivity mapActivity = getMapActivity();
|
|
||||||
OsmandApplication app = mapActivity.getMyApplication();
|
|
||||||
final OsmandSettings settings = app.getSettings();
|
|
||||||
settings.setMapLocationToShow(gpxItem.locationStart.lat, gpxItem.locationStart.lon,
|
|
||||||
settings.getLastKnownMapZoom(),
|
|
||||||
new PointDescription(PointDescription.POINT_TYPE_WPT, gpxItem.name),
|
|
||||||
false,
|
|
||||||
gpxItem);
|
|
||||||
mapActivity.getContextMenu().hide();
|
|
||||||
MapActivity.launchMapActivityMoveToTop(mapActivity);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void setObject(Object object) {
|
protected void setObject(Object object) {
|
||||||
if (object instanceof SelectedGpxFile) {
|
if (object instanceof SelectedGpxPoint) {
|
||||||
this.item = (SelectedGpxFile) object;
|
this.selectedGpxPoint = (SelectedGpxPoint) object;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Object getObject() {
|
protected Object getObject() {
|
||||||
return item;
|
return selectedGpxPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
|
@ -174,4 +191,29 @@ public class SelectedGpxMenuController extends MenuController {
|
||||||
int color = isLight() ? R.color.active_color_primary_light : R.color.active_color_primary_dark;
|
int color = isLight() ? R.color.active_color_primary_light : R.color.active_color_primary_dark;
|
||||||
return getIcon(R.drawable.ic_action_polygom_dark, color);
|
return getIcon(R.drawable.ic_action_polygom_dark, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class SelectedGpxPoint {
|
||||||
|
|
||||||
|
private final WptPt selectedPoint;
|
||||||
|
private final SelectedGpxFile selectedGpxFile;
|
||||||
|
private final Location pointLocation;
|
||||||
|
|
||||||
|
public SelectedGpxPoint(SelectedGpxFile selectedGpxFile, WptPt selectedPoint, Location pointLocation) {
|
||||||
|
this.selectedPoint = selectedPoint;
|
||||||
|
this.selectedGpxFile = selectedGpxFile;
|
||||||
|
this.pointLocation = pointLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WptPt getSelectedPoint() {
|
||||||
|
return selectedPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SelectedGpxFile getSelectedGpxFile() {
|
||||||
|
return selectedGpxFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Location getPointLocation() {
|
||||||
|
return pointLocation;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -737,6 +737,14 @@ public class TrackDetailsMenu {
|
||||||
}
|
}
|
||||||
if (gpxItem.chartHighlightPos != -1) {
|
if (gpxItem.chartHighlightPos != -1) {
|
||||||
chart.highlightValue(gpxItem.chartHighlightPos, 0);
|
chart.highlightValue(gpxItem.chartHighlightPos, 0);
|
||||||
|
} else if (gpxItem.locationOnMap != null) {
|
||||||
|
LineData lineData = chart.getLineData();
|
||||||
|
List<ILineDataSet> ds = lineData != null ? lineData.getDataSets() : null;
|
||||||
|
if (ds != null && ds.size() > 0) {
|
||||||
|
OrderedLineDataSet dataSet = (OrderedLineDataSet) ds.get(0);
|
||||||
|
gpxItem.chartHighlightPos = (float) (gpxItem.locationOnMap.distance / dataSet.getDivX());
|
||||||
|
chart.highlightValue(gpxItem.chartHighlightPos, 0);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
chart.highlightValue(null);
|
chart.highlightValue(null);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ import net.osmand.GPXUtilities;
|
||||||
import net.osmand.GPXUtilities.GPXFile;
|
import net.osmand.GPXUtilities.GPXFile;
|
||||||
import net.osmand.GPXUtilities.TrkSegment;
|
import net.osmand.GPXUtilities.TrkSegment;
|
||||||
import net.osmand.GPXUtilities.WptPt;
|
import net.osmand.GPXUtilities.WptPt;
|
||||||
|
import net.osmand.Location;
|
||||||
import net.osmand.data.LatLon;
|
import net.osmand.data.LatLon;
|
||||||
import net.osmand.data.PointDescription;
|
import net.osmand.data.PointDescription;
|
||||||
import net.osmand.data.QuadRect;
|
import net.osmand.data.QuadRect;
|
||||||
|
@ -43,6 +44,7 @@ import net.osmand.plus.MapMarkersHelper.MapMarkersGroup;
|
||||||
import net.osmand.plus.OsmandApplication;
|
import net.osmand.plus.OsmandApplication;
|
||||||
import net.osmand.plus.R;
|
import net.osmand.plus.R;
|
||||||
import net.osmand.plus.base.FavoriteImageDrawable;
|
import net.osmand.plus.base.FavoriteImageDrawable;
|
||||||
|
import net.osmand.plus.mapcontextmenu.controllers.SelectedGpxMenuController.SelectedGpxPoint;
|
||||||
import net.osmand.plus.mapcontextmenu.other.TrackDetailsMenu.TrackChartPoints;
|
import net.osmand.plus.mapcontextmenu.other.TrackDetailsMenu.TrackChartPoints;
|
||||||
import net.osmand.plus.render.OsmandRenderer;
|
import net.osmand.plus.render.OsmandRenderer;
|
||||||
import net.osmand.plus.render.OsmandRenderer.RenderingContext;
|
import net.osmand.plus.render.OsmandRenderer.RenderingContext;
|
||||||
|
@ -54,6 +56,7 @@ import net.osmand.render.RenderingRuleProperty;
|
||||||
import net.osmand.render.RenderingRuleSearchRequest;
|
import net.osmand.render.RenderingRuleSearchRequest;
|
||||||
import net.osmand.render.RenderingRulesStorage;
|
import net.osmand.render.RenderingRulesStorage;
|
||||||
import net.osmand.util.Algorithms;
|
import net.osmand.util.Algorithms;
|
||||||
|
import net.osmand.util.MapUtils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -605,15 +608,18 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
|
||||||
List<TrkSegment> segments = selectedGpxFile.getPointsToDisplay();
|
List<TrkSegment> segments = selectedGpxFile.getPointsToDisplay();
|
||||||
for (TrkSegment segment : segments) {
|
for (TrkSegment segment : segments) {
|
||||||
QuadRect trackBounds = GPXUtilities.calculateBounds(segment.points);
|
QuadRect trackBounds = GPXUtilities.calculateBounds(segment.points);
|
||||||
if (QuadRect.trivialOverlap(tb.getLatLonBounds(), trackBounds) && isPointNearSegment(tb, segment.points, r, mx, my)) {
|
if (QuadRect.trivialOverlap(tb.getLatLonBounds(), trackBounds)) {
|
||||||
res.add(selectedGpxFile);
|
SelectedGpxPoint selectedGpxPoint = findPointNearSegment(tb, selectedGpxFile, segment.points, r, mx, my);
|
||||||
break;
|
if (selectedGpxPoint != null) {
|
||||||
|
res.add(selectedGpxPoint);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isPointNearSegment(RotatedTileBox tb, List<WptPt> points, int r, int mx, int my) {
|
private SelectedGpxPoint findPointNearSegment(RotatedTileBox tb, SelectedGpxFile selectedGpxFile, List<WptPt> points, int r, int mx, int my) {
|
||||||
WptPt firstPoint = points.get(0);
|
WptPt firstPoint = points.get(0);
|
||||||
int ppx = (int) tb.getPixXFromLatLon(firstPoint.lat, firstPoint.lon);
|
int ppx = (int) tb.getPixXFromLatLon(firstPoint.lat, firstPoint.lon);
|
||||||
int ppy = (int) tb.getPixYFromLatLon(firstPoint.lat, firstPoint.lon);
|
int ppy = (int) tb.getPixYFromLatLon(firstPoint.lat, firstPoint.lon);
|
||||||
|
@ -625,7 +631,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
|
||||||
int py = (int) tb.getPixYFromLatLon(point.lat, point.lon);
|
int py = (int) tb.getPixYFromLatLon(point.lat, point.lon);
|
||||||
int cross = placeInBbox(px, py, mx, my, r, r);
|
int cross = placeInBbox(px, py, mx, my, r, r);
|
||||||
if (cross == 0) {
|
if (cross == 0) {
|
||||||
return true;
|
return createProjectionPoint(selectedGpxFile, points.get(i - 1), point, tb.getLatLonFromPixel(mx, my));
|
||||||
}
|
}
|
||||||
if ((pcross & cross) == 0) {
|
if ((pcross & cross) == 0) {
|
||||||
int mpx = px;
|
int mpx = px;
|
||||||
|
@ -636,7 +642,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
|
||||||
int mpynew = mpy / 2 + ppy / 2;
|
int mpynew = mpy / 2 + ppy / 2;
|
||||||
int mcrossnew = placeInBbox(mpxnew, mpynew, mx, my, r, r);
|
int mcrossnew = placeInBbox(mpxnew, mpynew, mx, my, r, r);
|
||||||
if (mcrossnew == 0) {
|
if (mcrossnew == 0) {
|
||||||
return true;
|
return createProjectionPoint(selectedGpxFile, points.get(i - 1), point, tb.getLatLonFromPixel(mx, my));
|
||||||
}
|
}
|
||||||
if ((mcrossnew & mcross) != 0) {
|
if ((mcrossnew & mcross) != 0) {
|
||||||
mpx = mpxnew;
|
mpx = mpxnew;
|
||||||
|
@ -656,7 +662,38 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
|
||||||
ppx = px;
|
ppx = px;
|
||||||
ppy = py;
|
ppy = py;
|
||||||
}
|
}
|
||||||
return false;
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SelectedGpxPoint createProjectionPoint(SelectedGpxFile selectedGpxFile, WptPt prevPoint, WptPt nextPoint, LatLon latLon) {
|
||||||
|
LatLon projection = MapUtils.getProjection(latLon.getLatitude(), latLon.getLongitude(), prevPoint.lat, prevPoint.lon, nextPoint.lat, nextPoint.lon);
|
||||||
|
|
||||||
|
WptPt projectionPoint = new WptPt();
|
||||||
|
projectionPoint.lat = projection.getLatitude();
|
||||||
|
projectionPoint.lon = projection.getLongitude();
|
||||||
|
projectionPoint.heading = prevPoint.heading;
|
||||||
|
projectionPoint.distance = prevPoint.distance + MapUtils.getDistance(projection, prevPoint.lat, prevPoint.lon);
|
||||||
|
projectionPoint.ele = getValueByDistInterpolation(projectionPoint.distance, prevPoint.distance, prevPoint.ele, nextPoint.distance, nextPoint.ele);
|
||||||
|
projectionPoint.speed = getValueByDistInterpolation(projectionPoint.distance, prevPoint.distance, prevPoint.speed, nextPoint.distance, nextPoint.speed);
|
||||||
|
if (prevPoint.time != 0 && nextPoint.time != 0) {
|
||||||
|
projectionPoint.time = (long) getValueByDistInterpolation(projectionPoint.distance, prevPoint.distance, prevPoint.time, nextPoint.distance, nextPoint.time);
|
||||||
|
}
|
||||||
|
|
||||||
|
Location projectionLocation = new Location("");
|
||||||
|
projectionLocation.setLatitude(projectionPoint.lat);
|
||||||
|
projectionLocation.setLongitude(projectionPoint.lon);
|
||||||
|
|
||||||
|
Location nextPointLocation = new Location("");
|
||||||
|
nextPointLocation.setLatitude(nextPoint.lat);
|
||||||
|
nextPointLocation.setLongitude(nextPoint.lon);
|
||||||
|
|
||||||
|
projectionLocation.setBearing(projectionLocation.bearingTo(nextPointLocation));
|
||||||
|
|
||||||
|
return new SelectedGpxPoint(selectedGpxFile, projectionPoint, projectionLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
private double getValueByDistInterpolation(double projectionDist, double prevDist, double prevVal, double nextDist, double nextVal) {
|
||||||
|
return prevVal + (projectionDist - prevDist) * ((nextVal - prevVal) / (nextDist - prevDist));
|
||||||
}
|
}
|
||||||
|
|
||||||
int placeInBbox(int x, int y, int mx, int my, int halfw, int halfh) {
|
int placeInBbox(int x, int y, int mx, int my, int halfw, int halfh) {
|
||||||
|
@ -672,9 +709,14 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
|
||||||
public PointDescription getObjectName(Object o) {
|
public PointDescription getObjectName(Object o) {
|
||||||
if (o instanceof WptPt) {
|
if (o instanceof WptPt) {
|
||||||
return new PointDescription(PointDescription.POINT_TYPE_WPT, ((WptPt) o).name);
|
return new PointDescription(PointDescription.POINT_TYPE_WPT, ((WptPt) o).name);
|
||||||
} else if (o instanceof SelectedGpxFile) {
|
} else if (o instanceof SelectedGpxPoint) {
|
||||||
SelectedGpxFile selectedGpxFile = (SelectedGpxFile) o;
|
SelectedGpxFile selectedGpxFile = ((SelectedGpxPoint) o).getSelectedGpxFile();
|
||||||
String name = formatName(Algorithms.getFileWithoutDirs(selectedGpxFile.getGpxFile().path));
|
String name;
|
||||||
|
if (selectedGpxFile.isShowCurrentTrack()) {
|
||||||
|
name = view.getContext().getString(R.string.shared_string_currently_recording_track);
|
||||||
|
} else {
|
||||||
|
name = formatName(Algorithms.getFileWithoutDirs(selectedGpxFile.getGpxFile().path));
|
||||||
|
}
|
||||||
return new PointDescription(PointDescription.POINT_TYPE_GPX, name);
|
return new PointDescription(PointDescription.POINT_TYPE_GPX, name);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -720,6 +762,9 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
|
||||||
public LatLon getObjectLocation(Object o) {
|
public LatLon getObjectLocation(Object o) {
|
||||||
if (o instanceof WptPt) {
|
if (o instanceof WptPt) {
|
||||||
return new LatLon(((WptPt) o).lat, ((WptPt) o).lon);
|
return new LatLon(((WptPt) o).lat, ((WptPt) o).lon);
|
||||||
|
} else if (o instanceof SelectedGpxPoint) {
|
||||||
|
WptPt point = ((SelectedGpxPoint) o).getSelectedPoint();
|
||||||
|
return new LatLon(point.lat, point.lon);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue