Fix plan route recalculation after app mode settings change

This commit is contained in:
max-klaus 2020-12-23 16:13:44 +03:00
parent 75e93d6ec7
commit b2b6775105
22 changed files with 365 additions and 261 deletions

View file

@ -64,6 +64,7 @@ import net.osmand.plus.helpers.enums.MetricsConstants;
import net.osmand.plus.inapp.InAppPurchaseHelper;
import net.osmand.plus.mapmarkers.MapMarkersDbHelper;
import net.osmand.plus.mapmarkers.MapMarkersHelper;
import net.osmand.plus.measurementtool.MeasurementEditingContext;
import net.osmand.plus.monitoring.LiveMonitoringHelper;
import net.osmand.plus.osmedit.oauth.OsmOAuthHelper;
import net.osmand.plus.poi.PoiFiltersHelper;
@ -156,6 +157,7 @@ public class OsmandApplication extends MultiDexApplication {
GpxDbHelper gpxDbHelper;
QuickActionRegistry quickActionRegistry;
OsmOAuthHelper osmOAuthHelper;
MeasurementEditingContext measurementEditingContext;
private Resources localizedResources;
private Map<String, Builder> customRoutingConfigs = new ConcurrentHashMap<>();
@ -465,6 +467,14 @@ public class OsmandApplication extends MultiDexApplication {
return routingHelper;
}
public MeasurementEditingContext getMeasurementEditingContext() {
return measurementEditingContext;
}
public void setMeasurementEditingContext(MeasurementEditingContext context) {
this.measurementEditingContext = context;
}
public TransportRoutingHelper getTransportRoutingHelper() {
return transportRoutingHelper;
}

View file

@ -553,7 +553,7 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven
allowPrivate.setModeValue(mode, true);
}
}
getRoutingHelper().onSettingsChanged(true);
getRoutingHelper().onSettingsChanged(null, true);
}
});
dlg.setNegativeButton(R.string.shared_string_no, null);

View file

@ -119,7 +119,7 @@ public class AvoidSpecificRoads {
remove(item);
removeImpassableRoad(item);
notifyDataSetChanged();
recalculateRoute();
recalculateRoute(item != null ? item.appModeKey : null);
}
});
return v;
@ -163,8 +163,9 @@ public class AvoidSpecificRoads {
return app.getString(R.string.shared_string_road);
}
private void recalculateRoute() {
app.getRoutingHelper().onSettingsChanged();
private void recalculateRoute(@Nullable String appModeKey) {
ApplicationMode mode = ApplicationMode.valueOfStringKey(appModeKey, null);
app.getRoutingHelper().onSettingsChanged(mode);
}
public void removeImpassableRoad(LatLon latLon) {
@ -181,7 +182,7 @@ public class AvoidSpecificRoads {
removeImpassableRoad(getLocation(obj));
}
public void showDialog(@NonNull final MapActivity mapActivity) {
public void showDialog(@NonNull final MapActivity mapActivity, final @Nullable ApplicationMode mode) {
boolean nightMode = app.getDaynightHelper().isNightModeForMapControls();
Context themedContext = UiUtilities.getThemedContext(mapActivity, nightMode);
@ -206,14 +207,14 @@ public class AvoidSpecificRoads {
bld.setPositiveButton(R.string.shared_string_select_on_map, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
selectFromMap(mapActivity);
selectFromMap(mapActivity, mode);
}
});
bld.setNegativeButton(R.string.shared_string_close, null);
bld.show();
}
public void selectFromMap(final MapActivity mapActivity) {
public void selectFromMap(@NonNull final MapActivity mapActivity) {
ContextMenuLayer cm = mapActivity.getMapLayers().getContextMenuLayer();
cm.setSelectOnMap(new CallbackWithObject<LatLon>() {
@Override
@ -224,6 +225,17 @@ public class AvoidSpecificRoads {
});
}
public void selectFromMap(@NonNull final MapActivity mapActivity, @Nullable final ApplicationMode mode) {
ContextMenuLayer cm = mapActivity.getMapLayers().getContextMenuLayer();
cm.setSelectOnMap(new CallbackWithObject<LatLon>() {
@Override
public boolean processResult(LatLon result) {
addImpassableRoad(mapActivity, result, true, false, mode != null ? mode.getStringKey() : null);
return true;
}
});
}
public void addImpassableRoad(@Nullable final MapActivity mapActivity,
@NonNull final LatLon loc,
final boolean showDialog,
@ -236,7 +248,9 @@ public class AvoidSpecificRoads {
ApplicationMode defaultAppMode = app.getRoutingHelper().getAppMode();
final ApplicationMode appMode = appModeKey != null ? ApplicationMode.valueOfStringKey(appModeKey, defaultAppMode) : defaultAppMode;
List<RouteSegmentResult> roads = app.getRoutingHelper().getRoute().getOriginalRoute();
List<RouteSegmentResult> roads = app.getMeasurementEditingContext() != null
? app.getMeasurementEditingContext().getRoadSegmentData(appMode)
: app.getRoutingHelper().getRoute().getOriginalRoute();
if (mapActivity != null && roads != null) {
RotatedTileBox tb = mapActivity.getMapView().getCurrentRotatedTileBox().copy();
float maxDistPx = MAX_AVOID_ROUTE_SEARCH_RADIUS_DP * tb.getDensity();
@ -346,10 +360,10 @@ public class AvoidSpecificRoads {
app.getSettings().removeImpassableRoad(location);
}
}
recalculateRoute();
recalculateRoute(avoidRoadInfo.appModeKey);
if (activity != null) {
if (showDialog) {
showDialog(activity);
showDialog(activity, ApplicationMode.valueOfStringKey(avoidRoadInfo.appModeKey, null));
}
MapContextMenu menu = activity.getContextMenu();
if (menu.isActive()) {

View file

@ -135,12 +135,12 @@ public class GraphsCard extends BaseCard implements OnUpdateInfoListener {
}
private void updateMenu() {
if (!editingCtx.isPointsEnoughToCalculateRoute()) {
graphTypesMenu.setVisibility(View.GONE);
} else {
if (editingCtx.isPointsEnoughToCalculateRoute()) {
graphTypesMenu.setVisibility(View.VISIBLE);
graphTypesMenu.removeAllViews();
fillInMenu();
} else {
graphTypesMenu.setVisibility(View.GONE);
}
}
@ -349,7 +349,7 @@ public class GraphsCard extends BaseCard implements OnUpdateInfoListener {
private List<RouteStatistics> calculateRouteStatistics() {
OsmandApplication app = getMyApplication();
List<RouteSegmentResult> route = editingCtx.getAllRouteSegments();
List<RouteSegmentResult> route = editingCtx.getOrderedRoadSegmentData();
if (route != null && app != null) {
return RouteDetailsFragment.calculateRouteStatistics(app, route, nightMode);
}

View file

@ -16,11 +16,12 @@ import net.osmand.plus.OsmandApplication;
import net.osmand.plus.measurementtool.command.ApplyGpxApproximationCommand;
import net.osmand.plus.measurementtool.command.MeasurementCommandManager;
import net.osmand.plus.measurementtool.command.MeasurementModeCommand;
import net.osmand.plus.routing.IRouteSettingsListener;
import net.osmand.plus.routing.RouteCalculationParams;
import net.osmand.plus.routing.RouteCalculationParams.RouteCalculationResultListener;
import net.osmand.plus.routing.RouteCalculationProgressCallback;
import net.osmand.plus.routing.RouteCalculationResult;
import net.osmand.plus.routing.RoutingHelper;
import net.osmand.plus.routing.RouteCalculationProgressCallback;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.router.RouteCalculationProgress;
import net.osmand.router.RouteExporter;
@ -40,12 +41,13 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import static net.osmand.plus.measurementtool.MeasurementEditingContext.CalculationMode.WHOLE_TRACK;
import static net.osmand.plus.measurementtool.command.MeasurementModeCommand.MeasurementCommandType.APPROXIMATE_POINTS;
public class MeasurementEditingContext {
public class MeasurementEditingContext implements IRouteSettingsListener {
public final static ApplicationMode DEFAULT_APP_MODE = ApplicationMode.DEFAULT;
@ -70,9 +72,11 @@ public class MeasurementEditingContext {
private int calculatedPairs;
private int pointsToCalculateSize;
private CalculationMode lastCalculationMode = WHOLE_TRACK;
private SnapToRoadProgressListener progressListener;
private ApplicationMode appMode = DEFAULT_APP_MODE;
private SnapToRoadProgressListener progressListener;
private RouteCalculationProgress calculationProgress;
private Map<Pair<WptPt, WptPt>, RoadSegmentData> roadSegmentData = new ConcurrentHashMap<>();
public enum CalculationMode {
@ -86,66 +90,22 @@ public class MeasurementEditingContext {
ADD_BEFORE,
}
public static class RoadSegmentData {
private final ApplicationMode appMode;
private final WptPt start;
private final WptPt end;
private final List<WptPt> points;
private final List<RouteSegmentResult> segments;
private final double distance;
public RoadSegmentData(@NonNull ApplicationMode appMode, @NonNull WptPt start, @NonNull WptPt end,
@Nullable List<WptPt> points, @Nullable List<RouteSegmentResult> segments) {
this.appMode = appMode;
this.start = start;
this.end = end;
this.points = points;
this.segments = segments;
double distance = 0;
if (points != null && points.size() > 1) {
for (int i = 1; i < points.size(); i++) {
distance += MapUtils.getDistance(points.get(i - 1).lat, points.get(i - 1).lon,
points.get(i).lat, points.get(i).lon);
}
} else if (segments != null) {
for (RouteSegmentResult segment : segments) {
distance += segment.getDistance();
}
}
this.distance = distance;
}
public ApplicationMode getAppMode() {
return appMode;
}
public WptPt getStart() {
return start;
}
public WptPt getEnd() {
return end;
}
@Nullable
public List<WptPt> getPoints() {
return points != null ? Collections.unmodifiableList(points) : null;
}
@Nullable
public List<RouteSegmentResult> getSegments() {
return segments != null ? Collections.unmodifiableList(segments) : null;
}
public double getDistance() {
return distance;
}
}
public void setApplication(OsmandApplication application) {
this.application = application;
}
public void setupRouteSettingsListener() {
if (application != null) {
application.getRoutingHelper().addRouteSettingsListener(this);
}
}
public void resetRouteSettingsListener() {
if (application != null) {
application.getRoutingHelper().removeRouteSettingsListener(this);
}
}
MeasurementCommandManager getCommandManager() {
return commandManager;
}
@ -371,7 +331,7 @@ public class MeasurementEditingContext {
return getPointsCount() >= 2;
}
public List<RouteSegmentResult> getAllRouteSegments() {
public List<RouteSegmentResult> getOrderedRoadSegmentData() {
List<RouteSegmentResult> allSegments = new ArrayList<>();
for (Pair<WptPt, WptPt> key : getOrderedRoadSegmentDataKeys()) {
RoadSegmentData data = roadSegmentData.get(key);
@ -385,21 +345,50 @@ public class MeasurementEditingContext {
return allSegments.size() > 0 ? allSegments : null;
}
public void recalculateRouteSegmentsForAppMode() {
clearRouteSegmentsByAppMode();
updateSegmentsForSnap();
@NonNull
public List<RouteSegmentResult> getRoadSegmentData(@Nullable ApplicationMode mode) {
List<RouteSegmentResult> res = new ArrayList<>();
if (mode == null) {
for (RoadSegmentData data : roadSegmentData.values()) {
List<RouteSegmentResult> segments = data.getSegments();
if (!Algorithms.isEmpty(segments)) {
res.addAll(segments);
}
}
} else {
for (Entry<Pair<WptPt, WptPt>, RoadSegmentData> dataEntry : roadSegmentData.entrySet()) {
WptPt firstPoint = dataEntry.getKey().first;
if (mode.getStringKey().equals(firstPoint.getProfileType())) {
List<RouteSegmentResult> segments = dataEntry.getValue().getSegments();
if (!Algorithms.isEmpty(segments)) {
res.addAll(segments);
}
}
}
}
return res;
}
public void clearRouteSegmentsByAppMode() {
for (Pair<WptPt, WptPt> key : getOrderedRoadSegmentDataKeys()) {
if(key.first.getProfileType().equals(appMode.getStringKey())) {
RoadSegmentData data = roadSegmentData.get(key);
void recalculateRouteSegments(@Nullable ApplicationMode mode) {
boolean changed = false;
if (mode == null) {
roadSegmentData.clear();
changed = true;
} else {
for (Pair<WptPt, WptPt> pair : getOrderedRoadSegmentDataKeys()) {
if (mode.getStringKey().equals(pair.first.getProfileType())) {
RoadSegmentData data = roadSegmentData.get(pair);
if (data != null) {
roadSegmentData.remove(key);
roadSegmentData.remove(pair);
changed = true;
}
}
}
}
if (changed) {
updateSegmentsForSnap(false);
}
}
void splitSegments(int position) {
List<WptPt> points = new ArrayList<>();
@ -794,11 +783,11 @@ public class MeasurementEditingContext {
Pair<WptPt, WptPt> pair = new Pair<>(routePoints.get(i), routePoints.get(i + 1));
int startIndex = pair.first.getTrkPtIndex();
if (startIndex < 0 || startIndex < prevPointIndex || startIndex >= points.size()) {
startIndex = findPointIndex(pair.first, points, prevPointIndex);
startIndex = MeasurementEditingContextUtils.findPointIndex(pair.first, points, prevPointIndex);
}
int endIndex = pair.second.getTrkPtIndex();
if (endIndex < 0 || endIndex < startIndex || endIndex >= points.size()) {
endIndex = findPointIndex(pair.second, points, startIndex);
endIndex = MeasurementEditingContextUtils.findPointIndex(pair.second, points, startIndex);
}
if (startIndex >= 0 && endIndex >= 0) {
List<WptPt> pairPoints = new ArrayList<>();
@ -847,7 +836,7 @@ public class MeasurementEditingContext {
List<GpxPoint> gpxPoints = gpxApproximation.finalPoints;
for (int i = 0; i < gpxPoints.size(); i++) {
GpxPoint gp1 = gpxPoints.get(i);
boolean lastGpxPoint = isLastGpxPoint(gpxPoints, i);
boolean lastGpxPoint = MeasurementEditingContextUtils.isLastGpxPoint(gpxPoints, i);
List<WptPt> points = new ArrayList<>();
List<RouteSegmentResult> segments = new ArrayList<>();
for (int k = 0; k < gp1.routeToTarget.size(); k++) {
@ -858,7 +847,7 @@ public class MeasurementEditingContext {
}
for (int k = 0; k < segments.size(); k++) {
RouteSegmentResult seg = segments.get(k);
fillPointsArray(points, seg, lastGpxPoint && k == segments.size() - 1);
MeasurementEditingContextUtils.fillPointsArray(points, seg, lastGpxPoint && k == segments.size() - 1);
}
if (!points.isEmpty()) {
WptPt wp1 = new WptPt();
@ -893,61 +882,6 @@ public class MeasurementEditingContext {
return routePoints;
}
private boolean isLastGpxPoint(List<GpxPoint> gpxPoints, int index) {
if (index == gpxPoints.size() - 1) {
return true;
} else {
for (int i = index + 1; i < gpxPoints.size(); i++) {
GpxPoint gp = gpxPoints.get(i);
for (int k = 0; k < gp.routeToTarget.size(); k++) {
RouteSegmentResult seg = gp.routeToTarget.get(k);
if (seg.getStartPointIndex() != seg.getEndPointIndex()) {
return false;
}
}
}
}
return true;
}
private void fillPointsArray(List<WptPt> points, RouteSegmentResult seg, boolean includeEndPoint) {
int ind = seg.getStartPointIndex();
boolean plus = seg.isForwardDirection();
float[] heightArray = seg.getObject().calculateHeightArray();
while (ind != seg.getEndPointIndex()) {
addPointToArray(points, seg, ind, heightArray);
ind = plus ? ind + 1 : ind - 1;
}
if (includeEndPoint) {
addPointToArray(points, seg, ind, heightArray);
}
}
private void addPointToArray(List<WptPt> points, RouteSegmentResult seg, int index, float[] heightArray) {
LatLon l = seg.getPoint(index);
WptPt pt = new WptPt();
if (heightArray != null && heightArray.length > index * 2 + 1) {
pt.ele = heightArray[index * 2 + 1];
}
pt.lat = l.getLatitude();
pt.lon = l.getLongitude();
points.add(pt);
}
private int findPointIndex(WptPt point, List<WptPt> points, int firstIndex) {
double minDistance = Double.MAX_VALUE;
int index = 0;
for (int i = Math.max(0, firstIndex); i < points.size(); i++) {
double distance = MapUtils.getDistance(point.lat, point.lon, points.get(i).lat, points.get(i).lon);
if (distance < minDistance) {
minDistance = distance;
index = i;
}
}
return index;
}
private void updateSegmentsForSnap(boolean both) {
recreateSegments(beforeSegments = new ArrayList<>(),
beforeSegmentsForSnap = new ArrayList<>(), before.points, true);
@ -966,7 +900,6 @@ public class MeasurementEditingContext {
}
}
void cancelSnapToRoad() {
progressListener.hideProgressBar();
if (calculationProgress != null) {
@ -1108,8 +1041,10 @@ public class MeasurementEditingContext {
for (int i = startPointIndex; i < endPointIndex; i++) {
Pair<WptPt, WptPt> pair = new Pair<>(before.points.get(i), before.points.get(i + 1));
RoadSegmentData data = this.roadSegmentData.get(pair);
if (data != null && data.points != null && data.segments != null) {
for (WptPt pt : data.points) {
List<WptPt> dataPoints = data != null ? data.getPoints() : null;
List<RouteSegmentResult> dataSegments = data != null ? data.getSegments() : null;
if (dataPoints != null && dataSegments != null) {
for (WptPt pt : dataPoints) {
Location l = new Location("");
l.setLatitude(pt.getLatitude());
l.setLongitude(pt.getLongitude());
@ -1119,7 +1054,7 @@ public class MeasurementEditingContext {
locations.add(l);
}
pair.second.setTrkPtIndex(i + 1 < before.points.size() - 1 ? locations.size() : locations.size() - 1);
route.addAll(data.segments);
route.addAll(dataSegments);
}
}
if (!locations.isEmpty() && !route.isEmpty()) {
@ -1156,14 +1091,8 @@ public class MeasurementEditingContext {
return res;
}
interface SnapToRoadProgressListener {
void showProgressBar();
void updateProgress(int progress);
void hideProgressBar();
void refresh();
@Override
public void onRouteSettingsChanged(@Nullable ApplicationMode mode) {
recalculateRouteSegments(mode);
}
}

View file

@ -0,0 +1,67 @@
package net.osmand.plus.measurementtool;
import net.osmand.GPXUtilities;
import net.osmand.data.LatLon;
import net.osmand.router.RoutePlannerFrontEnd;
import net.osmand.router.RouteSegmentResult;
import net.osmand.util.MapUtils;
import java.util.List;
public class MeasurementEditingContextUtils {
static boolean isLastGpxPoint(List<RoutePlannerFrontEnd.GpxPoint> gpxPoints, int index) {
if (index == gpxPoints.size() - 1) {
return true;
} else {
for (int i = index + 1; i < gpxPoints.size(); i++) {
RoutePlannerFrontEnd.GpxPoint gp = gpxPoints.get(i);
for (int k = 0; k < gp.routeToTarget.size(); k++) {
RouteSegmentResult seg = gp.routeToTarget.get(k);
if (seg.getStartPointIndex() != seg.getEndPointIndex()) {
return false;
}
}
}
}
return true;
}
static int findPointIndex(GPXUtilities.WptPt point, List<GPXUtilities.WptPt> points, int firstIndex) {
double minDistance = Double.MAX_VALUE;
int index = 0;
for (int i = Math.max(0, firstIndex); i < points.size(); i++) {
double distance = MapUtils.getDistance(point.lat, point.lon, points.get(i).lat, points.get(i).lon);
if (distance < minDistance) {
minDistance = distance;
index = i;
}
}
return index;
}
static void addPointToArray(List<GPXUtilities.WptPt> points, RouteSegmentResult seg, int index, float[] heightArray) {
LatLon l = seg.getPoint(index);
GPXUtilities.WptPt pt = new GPXUtilities.WptPt();
if (heightArray != null && heightArray.length > index * 2 + 1) {
pt.ele = heightArray[index * 2 + 1];
}
pt.lat = l.getLatitude();
pt.lon = l.getLongitude();
points.add(pt);
}
static void fillPointsArray(List<GPXUtilities.WptPt> points, RouteSegmentResult seg, boolean includeEndPoint) {
int ind = seg.getStartPointIndex();
boolean plus = seg.isForwardDirection();
float[] heightArray = seg.getObject().calculateHeightArray();
while (ind != seg.getEndPointIndex()) {
addPointToArray(points, seg, ind, heightArray);
ind = plus ? ind + 1 : ind - 1;
}
if (includeEndPoint) {
addPointToArray(points, seg, ind, heightArray);
}
}
}

View file

@ -72,7 +72,6 @@ import net.osmand.plus.measurementtool.command.ReorderPointCommand;
import net.osmand.plus.measurementtool.command.ReversePointsCommand;
import net.osmand.plus.measurementtool.command.SplitPointsCommand;
import net.osmand.plus.routepreparationmenu.RouteOptionsBottomSheet;
import net.osmand.plus.routepreparationmenu.RouteOptionsBottomSheet.OnAppModeConfiguredCallback;
import net.osmand.plus.routepreparationmenu.RouteOptionsBottomSheet.DialogMode;
import net.osmand.plus.routepreparationmenu.cards.BaseCard;
import net.osmand.plus.settings.backend.ApplicationMode;
@ -98,7 +97,6 @@ import java.util.Locale;
import static net.osmand.IndexConstants.GPX_FILE_EXT;
import static net.osmand.IndexConstants.GPX_INDEX_DIR;
import static net.osmand.plus.measurementtool.MeasurementEditingContext.CalculationMode;
import static net.osmand.plus.measurementtool.MeasurementEditingContext.SnapToRoadProgressListener;
import static net.osmand.plus.measurementtool.SaveAsNewTrackBottomSheetDialogFragment.SaveAsNewTrackFragmentListener;
import static net.osmand.plus.measurementtool.SelectFileBottomSheet.Mode.ADD_TO_TRACK;
import static net.osmand.plus.measurementtool.SelectFileBottomSheet.SelectFileListener;
@ -109,8 +107,7 @@ import static net.osmand.plus.measurementtool.command.ClearPointsCommand.ClearCo
public class MeasurementToolFragment extends BaseOsmAndFragment implements RouteBetweenPointsFragmentListener,
OptionsFragmentListener, GpxApproximationFragmentListener, SelectedPointFragmentListener,
SaveAsNewTrackFragmentListener, MapControlsThemeInfoProvider,
OnAppModeConfiguredCallback {
SaveAsNewTrackFragmentListener, MapControlsThemeInfoProvider {
public static final String TAG = MeasurementToolFragment.class.getSimpleName();
public static final String TAPS_DISABLED_KEY = "taps_disabled_key";
@ -241,7 +238,8 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
final MeasurementToolLayer measurementLayer = mapActivity.getMapLayers().getMeasurementToolLayer();
final OsmandApplication app = mapActivity.getMyApplication();
editingCtx.setApplication(mapActivity.getMyApplication());
app.setMeasurementEditingContext(editingCtx);
editingCtx.setApplication(app);
editingCtx.setProgressListener(new SnapToRoadProgressListener() {
@Override
public void showProgressBar() {
@ -267,6 +265,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
updateDistancePointsText();
}
});
editingCtx.setupRouteSettingsListener();
measurementLayer.setEditingCtx(editingCtx);
@ -1102,12 +1101,6 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
updateDistancePointsText();
}
@Override
public void onAppModeConfigured() {
editingCtx.recalculateRouteSegmentsForAppMode();
updateDistancePointsText();
}
@Override
public void onChangeRouteTypeBefore() {
MapActivity mapActivity = getMapActivity();
@ -1910,6 +1903,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
private void dismiss(@NonNull MapActivity mapActivity, boolean clearContext) {
try {
OsmandApplication app = mapActivity.getMyApplication();
if (clearContext) {
editingCtx.clearSegments();
}
@ -1920,13 +1914,15 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
GpxData gpxData = editingCtx.getGpxData();
GPXFile gpx = gpxData != null ? gpxData.getGpxFile() : null;
if (gpx != null) {
Intent newIntent = new Intent(mapActivity, mapActivity.getMyApplication().getAppCustomization().getTrackActivity());
Intent newIntent = new Intent(mapActivity, app.getAppCustomization().getTrackActivity());
newIntent.putExtra(TrackActivity.TRACK_FILE_NAME, gpx.path);
newIntent.putExtra(TrackActivity.OPEN_TRACKS_LIST, true);
newIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(newIntent);
}
}
editingCtx.resetRouteSettingsListener();
app.setMeasurementEditingContext(null);
mapActivity.getSupportFragmentManager().beginTransaction().remove(this).commitAllowingStateLoss();
} catch (Exception e) {
// ignore

View file

@ -0,0 +1,68 @@
package net.osmand.plus.measurementtool;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import net.osmand.GPXUtilities.WptPt;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.router.RouteSegmentResult;
import net.osmand.util.MapUtils;
import java.util.Collections;
import java.util.List;
public class RoadSegmentData {
private final ApplicationMode appMode;
private final WptPt start;
private final WptPt end;
private final List<WptPt> points;
private final List<RouteSegmentResult> segments;
private final double distance;
public RoadSegmentData(@NonNull ApplicationMode appMode, @NonNull WptPt start, @NonNull WptPt end,
@Nullable List<WptPt> points, @Nullable List<RouteSegmentResult> segments) {
this.appMode = appMode;
this.start = start;
this.end = end;
this.points = points;
this.segments = segments;
double distance = 0;
if (points != null && points.size() > 1) {
for (int i = 1; i < points.size(); i++) {
distance += MapUtils.getDistance(points.get(i - 1).lat, points.get(i - 1).lon,
points.get(i).lat, points.get(i).lon);
}
} else if (segments != null) {
for (RouteSegmentResult segment : segments) {
distance += segment.getDistance();
}
}
this.distance = distance;
}
public ApplicationMode getAppMode() {
return appMode;
}
public WptPt getStart() {
return start;
}
public WptPt getEnd() {
return end;
}
@Nullable
public List<WptPt> getPoints() {
return points != null ? Collections.unmodifiableList(points) : null;
}
@Nullable
public List<RouteSegmentResult> getSegments() {
return segments != null ? Collections.unmodifiableList(segments) : null;
}
public double getDistance() {
return distance;
}
}

View file

@ -0,0 +1,12 @@
package net.osmand.plus.measurementtool;
interface SnapToRoadProgressListener {
void showProgressBar();
void updateProgress(int progress);
void hideProgressBar();
void refresh();
}

View file

@ -6,7 +6,7 @@ import androidx.annotation.NonNull;
import net.osmand.GPXUtilities.WptPt;
import net.osmand.plus.measurementtool.MeasurementEditingContext;
import net.osmand.plus.measurementtool.MeasurementEditingContext.RoadSegmentData;
import net.osmand.plus.measurementtool.RoadSegmentData;
import net.osmand.plus.measurementtool.MeasurementToolLayer;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.router.RoutePlannerFrontEnd.GpxRouteApproximation;

View file

@ -4,7 +4,7 @@ import android.util.Pair;
import net.osmand.GPXUtilities.WptPt;
import net.osmand.plus.measurementtool.MeasurementEditingContext;
import net.osmand.plus.measurementtool.MeasurementEditingContext.RoadSegmentData;
import net.osmand.plus.measurementtool.RoadSegmentData;
import net.osmand.plus.measurementtool.MeasurementToolLayer;
import net.osmand.plus.settings.backend.ApplicationMode;

View file

@ -4,7 +4,7 @@ import android.util.Pair;
import net.osmand.GPXUtilities.WptPt;
import net.osmand.plus.measurementtool.MeasurementEditingContext;
import net.osmand.plus.measurementtool.MeasurementEditingContext.RoadSegmentData;
import net.osmand.plus.measurementtool.RoadSegmentData;
import net.osmand.plus.measurementtool.MeasurementToolLayer;
import java.util.ArrayList;

View file

@ -4,7 +4,7 @@ import android.util.Pair;
import net.osmand.GPXUtilities.WptPt;
import net.osmand.plus.measurementtool.MeasurementEditingContext;
import net.osmand.plus.measurementtool.MeasurementEditingContext.RoadSegmentData;
import net.osmand.plus.measurementtool.RoadSegmentData;
import net.osmand.plus.measurementtool.MeasurementToolLayer;
import java.util.ArrayList;

View file

@ -4,12 +4,11 @@ import android.util.Pair;
import net.osmand.GPXUtilities.WptPt;
import net.osmand.plus.measurementtool.MeasurementEditingContext;
import net.osmand.plus.measurementtool.MeasurementEditingContext.RoadSegmentData;
import net.osmand.plus.measurementtool.RoadSegmentData;
import net.osmand.plus.measurementtool.MeasurementToolLayer;
import net.osmand.plus.settings.backend.ApplicationMode;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

View file

@ -2,11 +2,9 @@ package net.osmand.plus.measurementtool.command;
import android.util.Pair;
import net.osmand.GPXUtilities;
import net.osmand.GPXUtilities.TrkSegment;
import net.osmand.GPXUtilities.WptPt;
import net.osmand.plus.measurementtool.MeasurementEditingContext;
import net.osmand.plus.measurementtool.MeasurementEditingContext.RoadSegmentData;
import net.osmand.plus.measurementtool.RoadSegmentData;
import net.osmand.plus.measurementtool.MeasurementToolLayer;
import java.util.ArrayList;

View file

@ -20,6 +20,7 @@ import androidx.fragment.app.Fragment;
import net.osmand.AndroidUtils;
import net.osmand.data.LatLon;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.settings.backend.CommonPreference;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
@ -32,6 +33,7 @@ import net.osmand.plus.base.bottomsheetmenu.simpleitems.SubtitleDividerItem;
import net.osmand.plus.dashboard.DashboardOnMap;
import net.osmand.plus.helpers.AvoidSpecificRoads;
import net.osmand.router.GeneralRouter;
import net.osmand.router.RouteSegmentResult;
import java.io.Serializable;
import java.util.ArrayList;
@ -52,6 +54,7 @@ public class AvoidRoadsBottomSheetDialogFragment extends MenuBottomSheetDialogFr
private static final String AVOID_ROADS_TYPES_KEY = "avoid_roads_types";
private static final String HIDE_IMPASSABLE_ROADS_KEY = "hide_impassable_roads";
private static final String AVOID_ROADS_OBJECTS_KEY = "avoid_roads_objects";
private static final String AVOID_ROADS_APP_MODE_KEY = "avoid_roads_app_mode";
private RoutingOptionsHelper routingOptionsHelper;
@ -63,11 +66,16 @@ public class AvoidRoadsBottomSheetDialogFragment extends MenuBottomSheetDialogFr
private boolean hideImpassableRoads;
@ColorRes
private int compoundButtonColorId = INVALID_ID;
private ApplicationMode appMode;
public void setHideImpassableRoads(boolean hideImpassableRoads) {
this.hideImpassableRoads = hideImpassableRoads;
}
public void setApplicationMode(ApplicationMode appMode) {
this.appMode = appMode;
}
@Override
public void createMenuItems(Bundle savedInstanceState) {
final OsmandApplication app = getMyApplication();
@ -83,6 +91,9 @@ public class AvoidRoadsBottomSheetDialogFragment extends MenuBottomSheetDialogFr
if (savedInstanceState.containsKey(AVOID_ROADS_OBJECTS_KEY)) {
removedImpassableRoads = (List<LatLon>) savedInstanceState.getSerializable(AVOID_ROADS_OBJECTS_KEY);
}
if (savedInstanceState.containsKey(AVOID_ROADS_APP_MODE_KEY)) {
appMode = ApplicationMode.valueOfStringKey(savedInstanceState.getString(AVOID_ROADS_APP_MODE_KEY), null);
}
}
if (routingParametersMap == null) {
routingParametersMap = getRoutingParametersMap(app);
@ -154,7 +165,7 @@ public class AvoidRoadsBottomSheetDialogFragment extends MenuBottomSheetDialogFr
if (mapActivity != null) {
mapActivity.getDashboard().setDashboardVisibility(false, DashboardOnMap.DashboardType.ROUTE_PREFERENCES);
mapActivity.getMapRouteInfoMenu().hide();
app.getAvoidSpecificRoads().selectFromMap(mapActivity);
app.getAvoidSpecificRoads().selectFromMap(mapActivity, appMode);
Fragment fragment = getTargetFragment();
if (fragment != null) {
fragment.onActivityResult(getTargetRequestCode(), OPEN_AVOID_ROADS_DIALOG_REQUEST_CODE, null);
@ -262,6 +273,9 @@ public class AvoidRoadsBottomSheetDialogFragment extends MenuBottomSheetDialogFr
outState.putSerializable(AVOID_ROADS_TYPES_KEY, routingParametersMap);
outState.putSerializable(AVOID_ROADS_OBJECTS_KEY, (Serializable) removedImpassableRoads);
outState.putBoolean(HIDE_IMPASSABLE_ROADS_KEY, hideImpassableRoads);
if (appMode != null) {
outState.putString(AVOID_ROADS_APP_MODE_KEY, appMode.getStringKey());
}
}
@Override

View file

@ -1,7 +1,6 @@
package net.osmand.plus.routepreparationmenu;
import android.app.Activity;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.Build;
@ -13,7 +12,6 @@ import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.ColorRes;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.SwitchCompat;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
@ -400,7 +398,7 @@ public class RouteOptionsBottomSheet extends MenuBottomSheetDialogFragment {
boolean enabled = !settings.ENABLE_TIME_CONDITIONAL_ROUTING.getModeValue(applicationMode);
settings.ENABLE_TIME_CONDITIONAL_ROUTING.setModeValue(applicationMode, enabled);
timeConditionalRoutingItem[0].setChecked(enabled);
app.getRoutingHelper().onSettingsChanged(true);
app.getRoutingHelper().onSettingsChanged(applicationMode, true);
}
})
.create();
@ -473,6 +471,7 @@ public class RouteOptionsBottomSheet extends MenuBottomSheetDialogFragment {
AvoidRoadsBottomSheetDialogFragment avoidRoadsFragment = new AvoidRoadsBottomSheetDialogFragment();
avoidRoadsFragment.setTargetFragment(RouteOptionsBottomSheet.this, AvoidRoadsBottomSheetDialogFragment.REQUEST_CODE);
avoidRoadsFragment.setCompoundButtonColorId(selectedModeColorId);
avoidRoadsFragment.setApplicationMode(applicationMode);
avoidRoadsFragment.show(mapActivity.getSupportFragmentManager(), AvoidRoadsBottomSheetDialogFragment.TAG);
updateMenu();
}
@ -656,19 +655,6 @@ public class RouteOptionsBottomSheet extends MenuBottomSheetDialogFragment {
}
@Override
public void onDismiss(@NonNull DialogInterface dialog) {
super.onDismiss(dialog);
notifyAppModeConfigurationChanged();
}
private void notifyAppModeConfigurationChanged() {
Fragment fragment = getTargetFragment();
if (fragment instanceof OnAppModeConfiguredCallback) {
((OnAppModeConfiguredCallback) fragment).onAppModeConfigured();
}
}
private List<LocalRoutingParameter> getRoutingParameters(ApplicationMode applicationMode) {
List<String> routingParameters;
@ -742,10 +728,6 @@ public class RouteOptionsBottomSheet extends MenuBottomSheetDialogFragment {
}
}
public interface OnAppModeConfiguredCallback {
void onAppModeConfigured();
}
public enum AppModeOptions {
CAR(MuteSoundRoutingParameter.KEY,

View file

@ -113,7 +113,7 @@ public class RoutingOptionsHelper {
public void selectRestrictedRoads(final MapActivity mapActivity) {
mapActivity.getDashboard().setDashboardVisibility(false, DashboardOnMap.DashboardType.ROUTE_PREFERENCES);
mapActivity.getMapRouteInfoMenu().hide();
mapActivity.getMyApplication().getAvoidSpecificRoads().showDialog(mapActivity);
mapActivity.getMyApplication().getAvoidSpecificRoads().showDialog(mapActivity, null);
}
public void selectVoiceGuidance(final MapActivity mapActivity, final CallbackWithObject<String> callback, ApplicationMode applicationMode) {
@ -230,7 +230,7 @@ public class RoutingOptionsHelper {
if (rp instanceof OtherLocalRoutingParameter) {
updateGpxRoutingParameter((OtherLocalRoutingParameter) rp);
}
routingHelper.onSettingsChanged(true);
routingHelper.onSettingsChanged(rp.getApplicationMode(), true);
}
public void updateGpxRoutingParameter(OtherLocalRoutingParameter gpxParam) {

View file

@ -0,0 +1,12 @@
package net.osmand.plus.routing;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import net.osmand.plus.settings.backend.ApplicationMode;
public interface IRouteSettingsListener {
void onRouteSettingsChanged(@Nullable ApplicationMode mode);
}

View file

@ -1,6 +1,7 @@
package net.osmand.plus.routing;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.Location;
@ -28,6 +29,7 @@ import net.osmand.router.RouteExporter;
import net.osmand.router.RoutePlannerFrontEnd.GpxPoint;
import net.osmand.router.RoutePlannerFrontEnd.GpxRouteApproximation;
import net.osmand.router.RouteSegmentResult;
import net.osmand.util.Algorithms;
import net.osmand.util.MapUtils;
import java.io.IOException;
@ -50,6 +52,8 @@ public class RoutingHelper {
private List<WeakReference<IRouteInformationListener>> listeners = new LinkedList<>();
private List<WeakReference<IRoutingDataUpdateListener>> updateListeners = new LinkedList<>();
private List<WeakReference<IRouteSettingsListener>> settingsListeners = new LinkedList<>();
private final OsmandApplication app;
private OsmandSettings settings;
private final RouteProvider provider;
@ -328,59 +332,47 @@ public class RoutingHelper {
return lastFixedLocation;
}
public void addRouteDataListener(IRoutingDataUpdateListener listener) {
updateListeners = updateListenersList(new ArrayList<>(updateListeners), listener, true);
public void addRouteDataListener(@NonNull IRoutingDataUpdateListener listener) {
updateListeners = updateListeners(new ArrayList<>(updateListeners), listener, true);
}
public void removeRouteDataListener(IRoutingDataUpdateListener listener) {
updateListeners = updateListenersList(new ArrayList<>(updateListeners), listener, false);
public void removeRouteDataListener(@NonNull IRoutingDataUpdateListener listener) {
updateListeners = updateListeners(new ArrayList<>(updateListeners), listener, false);
}
private List<WeakReference<IRoutingDataUpdateListener>> updateListenersList(
List<WeakReference<IRoutingDataUpdateListener>> copyList,
IRoutingDataUpdateListener listener, boolean isNewListener) {
Iterator<WeakReference<IRoutingDataUpdateListener>> it = copyList.iterator();
while (it.hasNext()) {
WeakReference<IRoutingDataUpdateListener> ref = it.next();
IRoutingDataUpdateListener l = ref.get();
if (l == null || l == listener) {
it.remove();
}
}
if (isNewListener) {
copyList.add(new WeakReference<>(listener));
}
return copyList;
public void addRouteSettingsListener(@NonNull IRouteSettingsListener listener) {
settingsListeners = updateListeners(new ArrayList<>(settingsListeners), listener, true);
}
public void addListener(IRouteInformationListener l) {
listeners = updateInformationListeners(new ArrayList<>(listeners), l, true);
public void removeRouteSettingsListener(@NonNull IRouteSettingsListener listener) {
settingsListeners = updateListeners(new ArrayList<>(settingsListeners), listener, false);
}
public void addListener(@NonNull IRouteInformationListener l) {
listeners = updateListeners(new ArrayList<>(listeners), l, true);
transportRoutingHelper.addListener(l);
}
public void removeListener(IRouteInformationListener lt) {
listeners = updateInformationListeners(new ArrayList<>(listeners), lt, false);
public void removeListener(@NonNull IRouteInformationListener lt) {
listeners = updateListeners(new ArrayList<>(listeners), lt, false);
}
private List<WeakReference<IRouteInformationListener>> updateInformationListeners(
List<WeakReference<IRouteInformationListener>> copyList,
IRouteInformationListener listener, boolean isNewListener) {
Iterator<WeakReference<IRouteInformationListener>> it = copyList.iterator();
private <T> List<WeakReference<T>> updateListeners(List<WeakReference<T>> copyList,
T listener, boolean isNewListener) {
Iterator<WeakReference<T>> it = copyList.iterator();
while (it.hasNext()) {
WeakReference<IRouteInformationListener> ref = it.next();
IRouteInformationListener l = ref.get();
WeakReference<T> ref = it.next();
T l = ref.get();
if (l == null || l == listener) {
it.remove();
}
}
if (isNewListener) {
copyList.add(new WeakReference<>(listener));
}
return copyList;
}
public void updateLocation(Location currentLocation) {
if (settings.getPointToStart() == null && settings.getMyLocationToStart() == null && currentLocation != null) {
app.getTargetPointsHelper().setMyLocationPoint(
@ -571,15 +563,7 @@ public class RoutingHelper {
route.updateCurrentRoute(newCurrentRoute + 1);
currentRoute = newCurrentRoute + 1;
app.getNotificationHelper().refreshNotification(NotificationType.NAVIGATION);
if (!updateListeners.isEmpty()) {
ArrayList<WeakReference<IRoutingDataUpdateListener>> tmp = new ArrayList<>(updateListeners);
for (WeakReference<IRoutingDataUpdateListener> ref : tmp) {
IRoutingDataUpdateListener l = ref.get();
if (l != null) {
l.onRoutingDataUpdate();
}
}
}
fireRoutingDataUpdateEvent();
} else {
break;
}
@ -688,6 +672,30 @@ public class RoutingHelper {
return false;
}
private void fireRoutingDataUpdateEvent() {
if (!updateListeners.isEmpty()) {
ArrayList<WeakReference<IRoutingDataUpdateListener>> tmp = new ArrayList<>(updateListeners);
for (WeakReference<IRoutingDataUpdateListener> ref : tmp) {
IRoutingDataUpdateListener l = ref.get();
if (l != null) {
l.onRoutingDataUpdate();
}
}
}
}
private void fireRouteSettingsChangedEvent(@Nullable ApplicationMode mode) {
if (!settingsListeners.isEmpty()) {
ArrayList<WeakReference<IRouteSettingsListener>> tmp = new ArrayList<>(settingsListeners);
for (WeakReference<IRouteSettingsListener> ref : tmp) {
IRouteSettingsListener l = ref.get();
if (l != null) {
l.onRouteSettingsChanged(mode);
}
}
}
}
public int getLeftDistance() {
return route.getDistanceToFinish(lastFixedLocation);
}
@ -766,9 +774,19 @@ public class RoutingHelper {
}
public void onSettingsChanged(boolean forceRouteRecalculation) {
if (forceRouteRecalculation || isRouteCalculated() || isRouteBeingCalculated()) {
onSettingsChanged(mode, forceRouteRecalculation);
}
public void onSettingsChanged(@Nullable ApplicationMode mode) {
onSettingsChanged(mode, false);
}
public void onSettingsChanged(@Nullable ApplicationMode mode, boolean forceRouteRecalculation) {
if (forceRouteRecalculation ||
((mode == null || mode.equals(this.mode)) && (isRouteCalculated() || isRouteBeingCalculated()))) {
recalculateRouteDueToSettingsChange();
}
fireRouteSettingsChangedEvent(mode);
}
private void recalculateRouteDueToSettingsChange() {

View file

@ -432,10 +432,7 @@ public class RouteParametersFragment extends BaseSettingsFragment implements OnP
public void onClick(DialogInterface dialog, int which) {
mode.setStrAngle(angleValue[0]);
updateAllSettings();
RoutingHelper routingHelper = app.getRoutingHelper();
if (mode.equals(routingHelper.getAppMode())) {
routingHelper.onSettingsChanged();
}
app.getRoutingHelper().onSettingsChanged(mode);
}
});
builder.setNegativeButton(R.string.shared_string_cancel, null);
@ -643,11 +640,8 @@ public class RouteParametersFragment extends BaseSettingsFragment implements OnP
return multiSelectPref;
}
private static void recalculateRoute(OsmandApplication app, ApplicationMode mode) {
RoutingHelper routingHelper = app.getRoutingHelper();
if (mode.equals(routingHelper.getAppMode())) {
routingHelper.onSettingsChanged();
}
private static void recalculateRoute(@NonNull OsmandApplication app, ApplicationMode mode) {
app.getRoutingHelper().onSettingsChanged(mode);
}
private void clearParameters() {

View file

@ -193,10 +193,7 @@ public class VehicleParametersFragment extends BaseSettingsFragment implements O
}
private void recalculateRoute() {
RoutingHelper routingHelper = app.getRoutingHelper();
if (getSelectedAppMode().equals(routingHelper.getAppMode())) {
routingHelper.onSettingsChanged();
}
app.getRoutingHelper().onSettingsChanged(getSelectedAppMode());
}
private void showSeekbarSettingsDialog(@NonNull Activity activity, final boolean defaultSpeedOnly) {
@ -267,10 +264,7 @@ public class VehicleParametersFragment extends BaseSettingsFragment implements O
mode.setMinSpeed(minValue[0] / ratio[0]);
mode.setMaxSpeed(maxValue[0] / ratio[0]);
}
RoutingHelper routingHelper = app.getRoutingHelper();
if (mode.equals(routingHelper.getAppMode())) {
routingHelper.onSettingsChanged();
}
app.getRoutingHelper().onSettingsChanged(mode);
}
});
builder.setNegativeButton(R.string.shared_string_cancel, null);
@ -282,10 +276,7 @@ public class VehicleParametersFragment extends BaseSettingsFragment implements O
mode.setMinSpeed(0f);
mode.setMaxSpeed(0f);
}
RoutingHelper routingHelper = app.getRoutingHelper();
if (mode.equals(routingHelper.getAppMode())) {
routingHelper.onSettingsChanged();
}
app.getRoutingHelper().onSettingsChanged(mode);
}
});