diff --git a/OsmAnd/res/layout/bottom_sheet_select_segment.xml b/OsmAnd/res/layout/bottom_sheet_select_segment.xml index ddfa37f927..ee4dfec006 100644 --- a/OsmAnd/res/layout/bottom_sheet_select_segment.xml +++ b/OsmAnd/res/layout/bottom_sheet_select_segment.xml @@ -45,7 +45,6 @@ android:textSize="@dimen/default_desc_text_size" osmand:typeface="@string/font_roboto_regular" /> - - ps = params.getPoints(settings.getContext()); mapActivity.getRoutingHelper().setGpxParams(params); settings.FOLLOW_THE_GPX_ROUTE.set(result.path); diff --git a/OsmAnd/src/net/osmand/plus/base/FailSafeFuntions.java b/OsmAnd/src/net/osmand/plus/base/FailSafeFuntions.java index d898505b76..46708ce5ae 100644 --- a/OsmAnd/src/net/osmand/plus/base/FailSafeFuntions.java +++ b/OsmAnd/src/net/osmand/plus/base/FailSafeFuntions.java @@ -134,6 +134,9 @@ public class FailSafeFuntions { if(settings.GPX_ROUTE_CALC.get()) { gpxRoute.setCalculateOsmAndRoute(true); } + if (settings.GPX_ROUTE_SEGMENT.get() != -1) { + gpxRoute.setSelectedSegment(settings.GPX_ROUTE_SEGMENT.get()); + } } else { gpxRoute = null; } diff --git a/OsmAnd/src/net/osmand/plus/helpers/TrackSelectSegmentAdapter.java b/OsmAnd/src/net/osmand/plus/helpers/TrackSelectSegmentAdapter.java index 96ceefed24..4f621b9161 100644 --- a/OsmAnd/src/net/osmand/plus/helpers/TrackSelectSegmentAdapter.java +++ b/OsmAnd/src/net/osmand/plus/helpers/TrackSelectSegmentAdapter.java @@ -16,16 +16,18 @@ import net.osmand.plus.OsmAndFormatter; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.UiUtilities; +import net.osmand.plus.helpers.TrackSelectSegmentAdapter.TrackViewHolder; import net.osmand.util.MapUtils; import java.util.List; -public class TrackSelectSegmentAdapter extends RecyclerView.Adapter { +public class TrackSelectSegmentAdapter extends RecyclerView.Adapter { + private final OsmandApplication app; private final LayoutInflater themedInflater; private final UiUtilities iconsCache; private final List segments; - private GpxTrackAdapter.OnItemClickListener onItemClickListener; + private OnItemClickListener onItemClickListener; public TrackSelectSegmentAdapter(Context ctx, List segments) { app = (OsmandApplication) ctx.getApplicationContext(); @@ -36,17 +38,17 @@ public class TrackSelectSegmentAdapter extends RecyclerView.Adapter 1; String fileName = null; File file = null; if (!Algorithms.isEmpty(gpxFile.path)) { file = new File(gpxFile.path); - if (isTrackContainsMultiSegment) { - fileName = Algorithms.getFileNameWithoutExtension(file.getName()); - } else { - fileName = Algorithms.getFileNameWithoutExtension(file.getName()); - } + fileName = Algorithms.getFileNameWithoutExtension(file.getName()); } else if (!Algorithms.isEmpty(gpxFile.tracks)) { fileName = gpxFile.tracks.get(0).name; } if (Algorithms.isEmpty(fileName)) { fileName = app.getString(R.string.shared_string_gpx_track); } + GPXRouteParamsBuilder routeParams = app.getRoutingHelper().getCurrentGPXRoute(); + if (gpxFile.getNonEmptySegmentsCount() > 1 && routeParams != null && routeParams.getSelectedSegment() != -1) { + fileName = fileName + " segment " + (routeParams.getSelectedSegment() + 1); + } sortButton.setVisibility(View.GONE); GPXInfo gpxInfo = new GPXInfo(fileName, file != null ? file.lastModified() : 0, file != null ? file.length() : 0); TrackEditCard importTrackCard = new TrackEditCard(mapActivity, gpxInfo); @@ -497,10 +498,10 @@ public class FollowTrackFragment extends ContextMenuScrollFragment implements Ca if (selectedGpxFile != null) { GPXFile gpxFile = selectedGpxFile.getGpxFile(); if (gpxFile.getNonEmptySegmentsCount() > 1) { - TrackSelectSegmentBottomSheet.showInstance(mapActivity.getSupportFragmentManager(), gpxFile); + TrackSelectSegmentBottomSheet.showInstance(mapActivity.getSupportFragmentManager(), gpxFile, this); } else { - updateSelectionMode(false); selectTrackToFollow(gpxFile); + updateSelectionMode(false); } } else { CallbackWithObject callback = new CallbackWithObject() { @@ -509,10 +510,10 @@ public class FollowTrackFragment extends ContextMenuScrollFragment implements Ca MapActivity mapActivity = getMapActivity(); if (mapActivity != null) { if (result[0].getNonEmptySegmentsCount() > 1) { - TrackSelectSegmentBottomSheet.showInstance(mapActivity.getSupportFragmentManager(), result[0]); + TrackSelectSegmentBottomSheet.showInstance(mapActivity.getSupportFragmentManager(), result[0], FollowTrackFragment.this); } else { - updateSelectionMode(false); selectTrackToFollow(result[0]); + updateSelectionMode(false); } } return true; @@ -536,7 +537,7 @@ public class FollowTrackFragment extends ContextMenuScrollFragment implements Ca app.initVoiceCommandPlayer(mapActivity, mode, true, null, false, false, true); } } - mapActivity.getMapActions().setGPXRouteParams(gpxFile, 1); + mapActivity.getMapActions().setGPXRouteParams(gpxFile); app.getTargetPointsHelper().updateRouteAndRefresh(true); app.getRoutingHelper().onSettingsChanged(true); } @@ -719,7 +720,6 @@ public class FollowTrackFragment extends ContextMenuScrollFragment implements Ca } } - @Override public void routeWasCancelled() { @@ -734,4 +734,18 @@ public class FollowTrackFragment extends ContextMenuScrollFragment implements Ca protected String getThemeInfoProviderTag() { return TAG; } + + @Override + public void onSegmentSelect(GPXFile gpxFile, int selectedSegment) { + selectTrackToFollow(gpxFile); + if (selectedSegment != -1) { + GPXRouteParamsBuilder paramsBuilder = app.getRoutingHelper().getCurrentGPXRoute(); + if (paramsBuilder != null) { + paramsBuilder.setSelectedSegment(selectedSegment); + app.getSettings().GPX_ROUTE_SEGMENT.set(selectedSegment); + app.getRoutingHelper().onSettingsChanged(true); + } + } + updateSelectionMode(false); + } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java b/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java index b3b2a11ab6..051a5218fa 100644 --- a/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java +++ b/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java @@ -8,7 +8,6 @@ import android.util.Base64; import net.osmand.GPXUtilities; import net.osmand.GPXUtilities.GPXFile; import net.osmand.GPXUtilities.Route; -import net.osmand.GPXUtilities.Track; import net.osmand.GPXUtilities.TrkSegment; import net.osmand.GPXUtilities.WptPt; import net.osmand.Location; @@ -20,15 +19,15 @@ import net.osmand.data.LatLon; import net.osmand.data.LocationPoint; import net.osmand.data.WptLocationPoint; import net.osmand.plus.OsmandApplication; -import net.osmand.plus.onlinerouting.OnlineRoutingHelper; -import net.osmand.plus.onlinerouting.engine.OnlineRoutingEngine.OnlineRoutingResponse; -import net.osmand.plus.settings.backend.OsmandSettings; -import net.osmand.plus.settings.backend.CommonPreference; import net.osmand.plus.R; import net.osmand.plus.TargetPointsHelper; import net.osmand.plus.TargetPointsHelper.TargetPoint; +import net.osmand.plus.onlinerouting.OnlineRoutingHelper; +import net.osmand.plus.onlinerouting.engine.OnlineRoutingEngine.OnlineRoutingResponse; import net.osmand.plus.render.NativeOsmandLibrary; import net.osmand.plus.settings.backend.ApplicationMode; +import net.osmand.plus.settings.backend.CommonPreference; +import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.router.GeneralRouter; import net.osmand.router.GeneralRouter.RoutingParameter; import net.osmand.router.GeneralRouter.RoutingParameterType; @@ -161,6 +160,7 @@ public class RouteProvider { private boolean leftSide; private boolean passWholeRoute; private boolean calculateOsmAndRouteParts; + private int selectedSegment = -1; public GPXRouteParamsBuilder(GPXFile file, OsmandSettings settings) { leftSide = settings.DRIVING_REGION.get().leftHandDriving; @@ -191,6 +191,14 @@ public class RouteProvider { this.calculateOsmAndRoute = calculateOsmAndRoute; } + public int getSelectedSegment() { + return selectedSegment; + } + + public void setSelectedSegment(int selectedSegment) { + this.selectedSegment = selectedSegment; + } + public void setPassWholeRoute(boolean passWholeRoute) { this.passWholeRoute = passWholeRoute; } @@ -278,8 +286,9 @@ public class RouteProvider { wpt.add(new WptLocationPoint(w)); } } + int selectedSegment = builder.getSelectedSegment(); if (OSMAND_ROUTER_V2.equals(file.author)) { - route = parseOsmAndGPXRoute(points, file); + route = parseOsmAndGPXRoute(points, file, selectedSegment); routePoints = file.getRoutePoints(); if (reverse) { Collections.reverse(points); @@ -287,7 +296,7 @@ public class RouteProvider { } addMissingTurns = route != null && route.isEmpty(); } else if (file.isCloudmadeRouteFile() || OSMAND_ROUTER.equals(file.author)) { - directions = parseOsmAndGPXRoute(points, file, OSMAND_ROUTER.equals(file.author), builder.leftSide, 10); + directions = parseOsmAndGPXRoute(points, file, OSMAND_ROUTER.equals(file.author), builder.leftSide, 10, selectedSegment); if (OSMAND_ROUTER.equals(file.author) && file.hasRtePt()) { // For files generated by OSMAND_ROUTER use directions contained unaltered addMissingTurns = false; @@ -301,12 +310,16 @@ public class RouteProvider { } else { // first of all check tracks if (!useIntermediatePointsRTE) { - for (Track tr : file.tracks) { - if (!tr.generalTrack) { - for (TrkSegment tkSeg : tr.segments) { - for (WptPt pt : tkSeg.points) { - points.add(createLocation(pt)); - } + List segments = file.getNonEmptyTrkSegments(false); + if (selectedSegment != -1 && segments.size() > selectedSegment) { + TrkSegment segment = segments.get(selectedSegment); + for (WptPt p : segment.points) { + points.add(createLocation(p)); + } + } else { + for (TrkSegment tkSeg : segments) { + for (WptPt p : tkSeg.points) { + points.add(createLocation(p)); } } } @@ -998,35 +1011,49 @@ public class RouteProvider { return new RouteCalculationResult("Empty result"); } - private static List parseOsmAndGPXRoute(List points, GPXFile gpxFile) { - for (Track tr : gpxFile.tracks) { - for (TrkSegment ts : tr.segments) { + private static List parseOsmAndGPXRoute(List points, GPXFile gpxFile, int selectedSegment) { + List segments = gpxFile.getNonEmptyTrkSegments(false); + if (selectedSegment != -1 && segments.size() > selectedSegment) { + TrkSegment segment = segments.get(selectedSegment); + for (WptPt p : segment.points) { + points.add(createLocation(p)); + } + RouteImporter routeImporter = new RouteImporter(segment); + return routeImporter.importRoute(); + } else { + for (TrkSegment ts : segments) { for (WptPt p : ts.points) { points.add(createLocation(p)); } } + RouteImporter routeImporter = new RouteImporter(gpxFile); + return routeImporter.importRoute(); } - RouteImporter routeImporter = new RouteImporter(gpxFile); - return routeImporter.importRoute(); } private static List parseOsmAndGPXRoute(List points, GPXFile gpxFile, boolean osmandRouter, - boolean leftSide, float defSpeed) { + boolean leftSide, float defSpeed, int selectedSegment) { List directions = null; if (!osmandRouter) { for (WptPt pt : gpxFile.getPoints()) { points.add(createLocation(pt)); } } else { - for (Track tr : gpxFile.tracks) { - for (TrkSegment ts : tr.segments) { + List segments = gpxFile.getNonEmptyTrkSegments(false); + if (selectedSegment != -1 && segments.size() > selectedSegment) { + TrkSegment segment = segments.get(selectedSegment); + for (WptPt p : segment.points) { + points.add(createLocation(p)); + } + } else { + for (TrkSegment ts : segments) { for (WptPt p : ts.points) { points.add(createLocation(p)); } } } } - float[] distanceToEnd = new float[points.size()]; + float[] distanceToEnd = new float[points.size()]; for (int i = points.size() - 2; i >= 0; i--) { distanceToEnd[i] = distanceToEnd[i + 1] + points.get(i).distanceTo(points.get(i + 1)); } @@ -1307,7 +1334,7 @@ public class RouteProvider { GPXFile gpxFile = GPXUtilities.loadGPXFile(gpxStream); - dir = parseOsmAndGPXRoute(res, gpxFile, true, params.leftSide, params.mode.getDefaultSpeed()); + dir = parseOsmAndGPXRoute(res, gpxFile, true, params.leftSide, params.mode.getDefaultSpeed(), -1); if (dir != null) { addMissingTurns = false; diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java b/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java index 45cefd2723..9652fc3bad 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java @@ -45,10 +45,8 @@ import net.osmand.plus.helpers.enums.DrivingRegion; import net.osmand.plus.helpers.enums.MetricsConstants; import net.osmand.plus.helpers.enums.SpeedConstants; import net.osmand.plus.helpers.enums.TracksSortByMode; -import net.osmand.plus.mapillary.MapillaryPlugin; import net.osmand.plus.mapmarkers.CoordinateInputFormats.Format; import net.osmand.plus.mapmarkers.MapMarkersMode; -import net.osmand.plus.openplacereviews.OpenPlaceReviewsPlugin; import net.osmand.plus.profiles.LocationIcon; import net.osmand.plus.profiles.NavigationIcon; import net.osmand.plus.profiles.ProfileIconColors; @@ -1389,6 +1387,7 @@ public class OsmandSettings { public final OsmandPreference GPX_ROUTE_CALC_OSMAND_PARTS = new BooleanPreference(this, "gpx_routing_calculate_osmand_route", true).makeGlobal().makeShared().cache(); public final OsmandPreference GPX_CALCULATE_RTEPT = new BooleanPreference(this, "gpx_routing_calculate_rtept", true).makeGlobal().makeShared().cache(); public final OsmandPreference GPX_ROUTE_CALC = new BooleanPreference(this, "calc_gpx_route", false).makeGlobal().makeShared().cache(); + public final OsmandPreference GPX_ROUTE_SEGMENT = new IntPreference(this, "gpx_route_segment", -1).makeGlobal().makeShared().cache(); public final OsmandPreference SHOW_START_FINISH_ICONS = new BooleanPreference(this, "show_start_finish_icons", true).makeGlobal().makeShared().cache(); public final OsmandPreference AVOID_TOLL_ROADS = new BooleanPreference(this, "avoid_toll_roads", false).makeProfile().cache(); @@ -2594,7 +2593,7 @@ public class OsmandSettings { public static final String VOICE_PROVIDER_NOT_USE = "VOICE_PROVIDER_NOT_USE"; - public static final String[] TTS_AVAILABLE_VOICES = new String[]{ + public static final String[] TTS_AVAILABLE_VOICES = new String[] { "de", "en", "es", "fr", "it", "ja", "nl", "pl", "pt", "ru", "zh" }; // this value string is synchronized with settings_pref.xml preference name diff --git a/OsmAnd/src/net/osmand/plus/track/TrackSelectSegmentBottomSheet.java b/OsmAnd/src/net/osmand/plus/track/TrackSelectSegmentBottomSheet.java index 319605dd98..b49c2eb898 100644 --- a/OsmAnd/src/net/osmand/plus/track/TrackSelectSegmentBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/track/TrackSelectSegmentBottomSheet.java @@ -9,31 +9,30 @@ import android.text.style.ForegroundColorSpan; import android.util.TypedValue; import android.view.LayoutInflater; import android.view.View; +import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import androidx.annotation.NonNull; -import androidx.appcompat.widget.AppCompatImageView; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import net.osmand.AndroidUtils; import net.osmand.GPXUtilities; +import net.osmand.GPXUtilities.GPXFile; import net.osmand.GPXUtilities.TrkSegment; import net.osmand.plus.OsmAndFormatter; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; -import net.osmand.plus.TargetPointsHelper; import net.osmand.plus.UiUtilities; -import net.osmand.plus.activities.MapActivity; import net.osmand.plus.base.MenuBottomSheetDialogFragment; import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem; import net.osmand.plus.helpers.FontCache; -import net.osmand.plus.helpers.GpxTrackAdapter; import net.osmand.plus.helpers.TrackSelectSegmentAdapter; -import net.osmand.plus.routing.RoutingHelper; -import net.osmand.plus.settings.backend.ApplicationMode; +import net.osmand.plus.helpers.TrackSelectSegmentAdapter.OnItemClickListener; import net.osmand.plus.widgets.style.CustomTypefaceSpan; import net.osmand.util.Algorithms; @@ -42,33 +41,18 @@ import java.util.List; public class TrackSelectSegmentBottomSheet extends MenuBottomSheetDialogFragment { public static final String TAG = TrackSelectSegmentBottomSheet.class.getSimpleName(); - protected TrackSelectSegmentAdapter adapterSegments; - private MapActivity mapActivity; - private GPXUtilities.GPXFile gpxFile; - private OsmandApplication app; - public static void showInstance(@NonNull FragmentManager fragmentManager, @NonNull GPXUtilities.GPXFile gpxFile) { - if (!fragmentManager.isStateSaved()) { - TrackSelectSegmentBottomSheet fragment = new TrackSelectSegmentBottomSheet(); - fragment.setRetainInstance(true); - fragment.gpxFile = gpxFile; - fragment.show(fragmentManager, TAG); - } - } + private OsmandApplication app; + private GPXFile gpxFile; @Override public void createMenuItems(Bundle savedInstanceState) { + app = requiredMyApplication(); Context context = requireContext(); LayoutInflater inflater = UiUtilities.getInflater(context, nightMode); View itemView = inflater.inflate(R.layout.bottom_sheet_select_segment, null, false); - app = getMyApplication(); - if (app == null) { - return; - } - - mapActivity = (MapActivity) getActivity(); String titleGpxTrack = Algorithms.getFileWithoutDirs(gpxFile.path); Typeface typeface = FontCache.getRobotoMedium(app); String selectSegmentDescription = getString(R.string.select_segments_description, titleGpxTrack); @@ -86,9 +70,9 @@ public class TrackSelectSegmentBottomSheet extends MenuBottomSheetDialogFragment LinearLayout gpxTrackContainer = itemView.findViewById(R.id.gpx_track_container); GPXUtilities.GPXTrackAnalysis analysis = gpxFile.getAnalysis(0); - AppCompatImageView icon = gpxTrackContainer.findViewById(R.id.icon); - int sidePadding = AndroidUtils.dpToPx(mapActivity, 16f); - int bottomTopPadding = AndroidUtils.dpToPx(mapActivity, 2f); + ImageView icon = gpxTrackContainer.findViewById(R.id.icon); + int sidePadding = AndroidUtils.dpToPx(context, 16f); + int bottomTopPadding = AndroidUtils.dpToPx(context, 2f); LinearLayout readContainer = gpxTrackContainer.findViewById(R.id.read_section); readContainer.setPadding(0, bottomTopPadding, 0, bottomTopPadding); @@ -111,15 +95,19 @@ public class TrackSelectSegmentBottomSheet extends MenuBottomSheetDialogFragment time.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14); time.setText(analysis.isTimeSpecified() ? Algorithms.formatDuration((int) (analysis.timeSpan / 1000), app.accessibilityEnabled()) : ""); - final RecyclerView recyclerView = itemView.findViewById(R.id.gpx_segment_list); + RecyclerView recyclerView = itemView.findViewById(R.id.gpx_segment_list); recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); recyclerView.setNestedScrollingEnabled(false); - final List segments = gpxFile.getNonEmptyTrkSegments(true); - adapterSegments = new TrackSelectSegmentAdapter(requireContext(), segments); - adapterSegments.setAdapterListener(new GpxTrackAdapter.OnItemClickListener() { + + List segments = gpxFile.getNonEmptyTrkSegments(false); + TrackSelectSegmentAdapter adapterSegments = new TrackSelectSegmentAdapter(context, segments); + adapterSegments.setAdapterListener(new OnItemClickListener() { @Override public void onItemClick(int position) { - //select segment + Fragment fragment = getTargetFragment(); + if (fragment instanceof OnSegmentSelectedListener) { + ((OnSegmentSelectedListener) fragment).onSegmentSelect(gpxFile, position); + } dismiss(); } }); @@ -128,30 +116,27 @@ public class TrackSelectSegmentBottomSheet extends MenuBottomSheetDialogFragment gpxTrackContainer.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - selectSegmentToFollow(gpxFile); + Fragment fragment = getTargetFragment(); + if (fragment instanceof OnSegmentSelectedListener) { + ((OnSegmentSelectedListener) fragment).onSegmentSelect(gpxFile, -1); + } dismiss(); } }); } - private void selectSegmentToFollow(GPXUtilities.GPXFile gpxFile) { - if (mapActivity != null) { - this.gpxFile = gpxFile; - TargetPointsHelper targetPointsHelper = app.getTargetPointsHelper(); - RoutingHelper routingHelper = app.getRoutingHelper(); - List points = gpxFile.getRoutePoints(); - if (!points.isEmpty()) { - ApplicationMode mode = ApplicationMode.valueOfStringKey(points.get(0).getProfileType(), null); - if (mode != null) { - routingHelper.setAppMode(mode); - app.initVoiceCommandPlayer(mapActivity, mode, true, null, false, false, true); - } - } - mapActivity.getMapActions().setGPXRouteParams(gpxFile); - targetPointsHelper.updateRouteAndRefresh(true); - routingHelper.onSettingsChanged(true); + public interface OnSegmentSelectedListener { + void onSegmentSelect(GPXFile gpxFile, int selectedSegment); + } + + public static void showInstance(@NonNull FragmentManager fragmentManager, @NonNull GPXFile gpxFile, @Nullable Fragment target) { + if (!fragmentManager.isStateSaved()) { + TrackSelectSegmentBottomSheet fragment = new TrackSelectSegmentBottomSheet(); + fragment.setRetainInstance(true); + fragment.setTargetFragment(target, 0); + fragment.gpxFile = gpxFile; + fragment.show(fragmentManager, TAG); } } -} - +} \ No newline at end of file