Multi-profile plan route

This commit is contained in:
max-klaus 2020-08-29 14:45:43 +03:00
parent f628e01a86
commit d5d247dd9a
6 changed files with 308 additions and 73 deletions

View file

@ -11,6 +11,12 @@
Thx - Hardy
-->
<string name="all_previous_segments_will_be_recalc">All previous segments will be recalculated using selected profile.</string>
<string name="all_next_segments_will_be_recalc">All next segments will be recalculated using selected profile.</string>
<string name="only_selected_segment_recalc">Only selected segment will be recalculated using selected profile.</string>
<string name="all_previous_segments">All previous segments</string>
<string name="previous_segment">Previous segment</string>
<string name="all_next_segments">All next segments</string>
<string name="system_default_theme">System Default</string>
<string name="gpx_monitoring_start">Resume trip recording</string>
<string name="gpx_monitoring_stop">Pause trip recording</string>

View file

@ -34,6 +34,7 @@ import net.osmand.util.MapUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@ -61,11 +62,11 @@ public class MeasurementEditingContext {
private boolean inAddPointMode;
private int calculatedPairs;
private int pointsToCalculateSize;
private CalculationMode calculationMode = WHOLE_TRACK;
private CalculationMode lastCalculationMode = WHOLE_TRACK;
private SnapToRoadProgressListener progressListener;
private ApplicationMode appMode = DEFAULT_APP_MODE;
private RouteCalculationProgress calculationProgress;
private final Map<Pair<WptPt, WptPt>, RoadSegmentData> roadSegmentData = new ConcurrentHashMap<>();
private Map<Pair<WptPt, WptPt>, RoadSegmentData> roadSegmentData = new ConcurrentHashMap<>();
public enum CalculationMode {
NEXT_SEGMENT,
@ -195,12 +196,12 @@ public class MeasurementEditingContext {
return gpxData != null && gpxData.getGpxFile() != null && gpxData.getGpxFile().hasRoute();
}
public CalculationMode getCalculationMode() {
return calculationMode;
public CalculationMode getLastCalculationMode() {
return lastCalculationMode;
}
public void setCalculationMode(CalculationMode calculationMode) {
this.calculationMode = calculationMode;
public void setLastCalculationMode(CalculationMode lastCalculationMode) {
this.lastCalculationMode = lastCalculationMode;
}
void setProgressListener(SnapToRoadProgressListener progressListener) {
@ -237,6 +238,14 @@ public class MeasurementEditingContext {
return distance;
}
public Map<Pair<WptPt, WptPt>, RoadSegmentData> getRoadSegmentData() {
return new HashMap<>(roadSegmentData);
}
public void setRoadSegmentData(Map<Pair<WptPt, WptPt>, RoadSegmentData> roadSegmentData) {
this.roadSegmentData = new ConcurrentHashMap<>(roadSegmentData);
}
public boolean hasRoute() {
return !roadSegmentData.isEmpty();
}
@ -350,6 +359,19 @@ public class MeasurementEditingContext {
return selectedPointPosition == getPoints().size() - 1;
}
public ApplicationMode getSelectedPointAppMode() {
return getPointAppMode(selectedPointPosition);
}
public ApplicationMode getBeforeSelectedPointAppMode() {
return getPointAppMode(Math.max(selectedPointPosition - 1, 0));
}
private ApplicationMode getPointAppMode(int pointPosition) {
String profileType = getPoints().get(pointPosition).getProfileType();
return ApplicationMode.valueOfStringKey(profileType, MeasurementEditingContext.DEFAULT_APP_MODE);
}
public void scheduleRouteCalculateIfNotEmpty() {
if (application == null || (before.points.size() == 0 && after.points.size() == 0)) {
return;

View file

@ -63,6 +63,8 @@ import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.measurementtool.GpxApproximationFragment.GpxApproximationFragmentListener;
import net.osmand.plus.measurementtool.GpxData.ActionType;
import net.osmand.plus.measurementtool.OptionsBottomSheetDialogFragment.OptionsFragmentListener;
import net.osmand.plus.measurementtool.RouteBetweenPointsBottomSheetDialogFragment.RouteBetweenPointsDialogMode;
import net.osmand.plus.measurementtool.RouteBetweenPointsBottomSheetDialogFragment.RouteBetweenPointsDialogType;
import net.osmand.plus.measurementtool.RouteBetweenPointsBottomSheetDialogFragment.RouteBetweenPointsFragmentListener;
import net.osmand.plus.measurementtool.SaveAsNewTrackBottomSheetDialogFragment.SaveAsNewTrackFragmentListener;
import net.osmand.plus.measurementtool.SelectedPointBottomSheetDialogFragment.SelectedPointFragmentListener;
@ -71,6 +73,7 @@ import net.osmand.plus.measurementtool.adapter.MeasurementToolAdapter.Measuremen
import net.osmand.plus.measurementtool.command.AddPointCommand;
import net.osmand.plus.measurementtool.command.ApplyGpxApproximationCommand;
import net.osmand.plus.measurementtool.command.ChangeRouteModeCommand;
import net.osmand.plus.measurementtool.command.ChangeRouteModeCommand.ChangeRouteType;
import net.osmand.plus.measurementtool.command.ClearPointsCommand;
import net.osmand.plus.measurementtool.command.MovePointCommand;
import net.osmand.plus.measurementtool.command.RemovePointCommand;
@ -101,8 +104,10 @@ import static net.osmand.plus.measurementtool.SelectFileBottomSheet.Mode.ADD_TO_
import static net.osmand.plus.measurementtool.SelectFileBottomSheet.Mode.OPEN_TRACK;
import static net.osmand.plus.measurementtool.SelectFileBottomSheet.SelectFileListener;
import static net.osmand.plus.measurementtool.StartPlanRouteBottomSheet.StartPlanRouteListener;
import static net.osmand.plus.measurementtool.command.ClearPointsCommand.*;
import static net.osmand.plus.measurementtool.command.ClearPointsCommand.ClearCommandMode.*;
import static net.osmand.plus.measurementtool.command.ClearPointsCommand.ClearCommandMode;
import static net.osmand.plus.measurementtool.command.ClearPointsCommand.ClearCommandMode.AFTER;
import static net.osmand.plus.measurementtool.command.ClearPointsCommand.ClearCommandMode.ALL;
import static net.osmand.plus.measurementtool.command.ClearPointsCommand.ClearCommandMode.BEFORE;
public class MeasurementToolFragment extends BaseOsmAndFragment implements RouteBetweenPointsFragmentListener,
OptionsFragmentListener, GpxApproximationFragmentListener, SelectedPointFragmentListener {
@ -573,7 +578,10 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
if (editingCtx.isNewData() || editingCtx.hasRoutePoints() || editingCtx.hasRoute() || editingCtx.getPointsCount() < 2) {
RouteBetweenPointsBottomSheetDialogFragment.showInstance(mapActivity.getSupportFragmentManager(),
this, editingCtx.getCalculationMode(),
this, RouteBetweenPointsDialogType.WHOLE_ROUTE_CALCULATION,
editingCtx.getLastCalculationMode() == CalculationMode.NEXT_SEGMENT
? RouteBetweenPointsDialogMode.SINGLE
: RouteBetweenPointsDialogMode.ALL,
editingCtx.getAppMode());
} else {
SnapTrackWarningBottomSheet.showInstance(mapActivity.getSupportFragmentManager(), this);
@ -759,12 +767,24 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
@Override
public void onChangeRouteTypeBefore() {
MapActivity mapActivity = getMapActivity();
if (mapActivity != null) {
RouteBetweenPointsBottomSheetDialogFragment.showInstance(mapActivity.getSupportFragmentManager(),
this, RouteBetweenPointsDialogType.PREV_ROUTE_CALCULATION,
RouteBetweenPointsDialogMode.SINGLE,
editingCtx.getBeforeSelectedPointAppMode());
}
}
@Override
public void onChangeRouteTypeAfter() {
MapActivity mapActivity = getMapActivity();
if (mapActivity != null) {
RouteBetweenPointsBottomSheetDialogFragment.showInstance(mapActivity.getSupportFragmentManager(),
this, RouteBetweenPointsDialogType.NEXT_ROUTE_CALCULATION,
RouteBetweenPointsDialogMode.SINGLE,
editingCtx.getSelectedPointAppMode());
}
}
@Override
@ -780,6 +800,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
@Override
public void onCloseRouteDialog() {
toolBarController.setTitle(previousToolBarTitle);
editingCtx.setSelectedPointPosition(-1);
MapActivity mapActivity = getMapActivity();
if (mapActivity != null) {
mapActivity.refreshMap();
@ -787,10 +808,26 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
}
@Override
public void onChangeApplicationMode(ApplicationMode mode, CalculationMode calculationMode) {
public void onChangeApplicationMode(ApplicationMode mode, RouteBetweenPointsDialogType dialogType,
RouteBetweenPointsDialogMode dialogMode) {
MeasurementToolLayer measurementLayer = getMeasurementLayer();
if (measurementLayer != null) {
editingCtx.getCommandManager().execute(new ChangeRouteModeCommand(measurementLayer, mode, calculationMode));
ChangeRouteType changeRouteType = ChangeRouteType.NEXT_SEGMENT;
switch (dialogType) {
case WHOLE_ROUTE_CALCULATION:
changeRouteType = dialogMode == RouteBetweenPointsDialogMode.SINGLE
? ChangeRouteType.LAST_SEGMENT : ChangeRouteType.WHOLE_ROUTE;
break;
case NEXT_ROUTE_CALCULATION:
changeRouteType = dialogMode == RouteBetweenPointsDialogMode.SINGLE
? ChangeRouteType.NEXT_SEGMENT : ChangeRouteType.ALL_NEXT_SEGMENTS;
break;
case PREV_ROUTE_CALCULATION:
changeRouteType = dialogMode == RouteBetweenPointsDialogMode.SINGLE
? ChangeRouteType.PREV_SEGMENT : ChangeRouteType.ALL_PREV_SEGMENTS;
break;
}
editingCtx.getCommandManager().execute(new ChangeRouteModeCommand(measurementLayer, mode, changeRouteType, editingCtx.getSelectedPointPosition()));
updateUndoRedoButton(false, redoBtn);
updateUndoRedoButton(true, undoBtn);
disable(upDownBtn);

View file

@ -26,7 +26,6 @@ import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.base.BottomSheetDialogFragment;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.measurementtool.MeasurementEditingContext.CalculationMode;
import net.osmand.plus.settings.backend.ApplicationMode;
import org.apache.commons.logging.Log;
@ -36,8 +35,6 @@ import java.util.List;
import static net.osmand.plus.UiUtilities.CustomRadioButtonType.LEFT;
import static net.osmand.plus.UiUtilities.CustomRadioButtonType.RIGHT;
import static net.osmand.plus.measurementtool.MeasurementEditingContext.CalculationMode.NEXT_SEGMENT;
import static net.osmand.plus.measurementtool.MeasurementEditingContext.CalculationMode.WHOLE_TRACK;
import static net.osmand.plus.measurementtool.MeasurementEditingContext.DEFAULT_APP_MODE;
public class RouteBetweenPointsBottomSheetDialogFragment extends BottomSheetDialogFragment {
@ -45,27 +42,42 @@ public class RouteBetweenPointsBottomSheetDialogFragment extends BottomSheetDial
private static final Log LOG = PlatformUtil.getLog(RouteBetweenPointsBottomSheetDialogFragment.class);
public static final String TAG = RouteBetweenPointsBottomSheetDialogFragment.class.getSimpleName();
public static final int STRAIGHT_LINE_TAG = -1;
public static final String CALCULATION_MODE_KEY = "calculation_type";
public static final String DIALOG_TYPE_KEY = "dialog_type_key";
public static final String DEFAULT_DIALOG_MODE_KEY = "default_dialog_mode_key";
public static final String ROUTE_APP_MODE_KEY = "route_app_mode";
private boolean nightMode;
private boolean portrait;
private TextView btnDescription;
private CalculationMode calculationMode = WHOLE_TRACK;
private RouteBetweenPointsDialogType dialogType = RouteBetweenPointsDialogType.WHOLE_ROUTE_CALCULATION;
private RouteBetweenPointsDialogMode defaultDialogMode = RouteBetweenPointsDialogMode.SINGLE;
private ApplicationMode appMode;
private LinearLayout customRadioButton;
public enum RouteBetweenPointsDialogType {
WHOLE_ROUTE_CALCULATION,
NEXT_ROUTE_CALCULATION,
PREV_ROUTE_CALCULATION
}
public enum RouteBetweenPointsDialogMode {
SINGLE,
ALL,
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Bundle args = getArguments();
if (args != null) {
appMode = ApplicationMode.valueOfStringKey(args.getString(ROUTE_APP_MODE_KEY), null);
calculationMode = (CalculationMode) args.get(CALCULATION_MODE_KEY);
dialogType = (RouteBetweenPointsDialogType) args.get(DIALOG_TYPE_KEY);
defaultDialogMode = (RouteBetweenPointsDialogMode) args.get(DEFAULT_DIALOG_MODE_KEY);
}
if (savedInstanceState != null) {
calculationMode = (CalculationMode) savedInstanceState.get(CALCULATION_MODE_KEY);
dialogType = (RouteBetweenPointsDialogType) savedInstanceState.get(DIALOG_TYPE_KEY);
defaultDialogMode = (RouteBetweenPointsDialogMode) savedInstanceState.get(DEFAULT_DIALOG_MODE_KEY);
}
OsmandApplication app = requiredMyApplication();
nightMode = app.getDaynightHelper().isNightModeForMapControls();
@ -89,10 +101,10 @@ public class RouteBetweenPointsBottomSheetDialogFragment extends BottomSheetDial
});
customRadioButton = mainView.findViewById(R.id.custom_radio_buttons);
TextView segmentBtn = mainView.findViewById(R.id.left_button);
segmentBtn.setText(R.string.next_segment);
TextView wholeTrackBtn = mainView.findViewById(R.id.right_button);
wholeTrackBtn.setText(R.string.whole_track);
TextView singleModeButton = mainView.findViewById(R.id.left_button);
singleModeButton.setText(getButtonText(RouteBetweenPointsDialogMode.SINGLE));
TextView allModeButton = mainView.findViewById(R.id.right_button);
allModeButton.setText(getButtonText(RouteBetweenPointsDialogMode.ALL));
btnDescription = mainView.findViewById(R.id.button_description);
LinearLayout navigationType = mainView.findViewById(R.id.navigation_types_container);
@ -108,7 +120,7 @@ public class RouteBetweenPointsBottomSheetDialogFragment extends BottomSheetDial
}
Fragment fragment = getTargetFragment();
if (fragment instanceof RouteBetweenPointsFragmentListener) {
((RouteBetweenPointsFragmentListener) fragment).onChangeApplicationMode(mode, calculationMode);
((RouteBetweenPointsFragmentListener) fragment).onChangeApplicationMode(mode, dialogType, defaultDialogMode);
}
dismiss();
}
@ -127,22 +139,82 @@ public class RouteBetweenPointsBottomSheetDialogFragment extends BottomSheetDial
}
}
segmentBtn.setOnClickListener(new View.OnClickListener() {
singleModeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
updateModeButtons(NEXT_SEGMENT);
setDefaultDialogMode(RouteBetweenPointsDialogMode.SINGLE);
}
});
wholeTrackBtn.setOnClickListener(new View.OnClickListener() {
allModeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
updateModeButtons(WHOLE_TRACK);
setDefaultDialogMode(RouteBetweenPointsDialogMode.ALL);
}
});
updateModeButtons(calculationMode);
updateModeButtons();
return mainView;
}
private String getButtonText(RouteBetweenPointsDialogMode dialogMode) {
switch (dialogType) {
case WHOLE_ROUTE_CALCULATION:
switch (dialogMode) {
case SINGLE:
return getString(R.string.next_segment);
case ALL:
return getString(R.string.whole_track);
}
break;
case NEXT_ROUTE_CALCULATION:
switch (dialogMode) {
case SINGLE:
return getString(R.string.next_segment);
case ALL:
return getString(R.string.all_next_segments);
}
break;
case PREV_ROUTE_CALCULATION:
switch (dialogMode) {
case SINGLE:
return getString(R.string.previous_segment);
case ALL:
return getString(R.string.all_previous_segments);
}
break;
}
return "";
}
private String getButtonDescr(RouteBetweenPointsDialogMode dialogMode) {
switch (dialogType) {
case WHOLE_ROUTE_CALCULATION:
switch (dialogMode) {
case SINGLE:
return getString(R.string.rourte_between_points_next_segment_button_desc);
case ALL:
return getString(R.string.rourte_between_points_whole_track_button_desc);
}
break;
case NEXT_ROUTE_CALCULATION:
switch (dialogMode) {
case SINGLE:
return getString(R.string.only_selected_segment_recalc);
case ALL:
return getString(R.string.all_next_segments_will_be_recalc);
}
break;
case PREV_ROUTE_CALCULATION:
switch (dialogMode) {
case SINGLE:
return getString(R.string.only_selected_segment_recalc);
case ALL:
return getString(R.string.all_previous_segments_will_be_recalc);
}
break;
}
return "";
}
private void addDelimiterView(LinearLayout container) {
View row = UiUtilities.getInflater(getContext(), nightMode).inflate(R.layout.divider, container, false);
View divider = row.findViewById(R.id.divider);
@ -152,15 +224,15 @@ public class RouteBetweenPointsBottomSheetDialogFragment extends BottomSheetDial
container.addView(row);
}
private void updateModeButtons(CalculationMode calculationMode) {
if (calculationMode == NEXT_SEGMENT) {
UiUtilities.updateCustomRadioButtons(getMyApplication(), customRadioButton, nightMode, LEFT);
btnDescription.setText(R.string.rourte_between_points_next_segment_button_desc);
} else {
btnDescription.setText(R.string.rourte_between_points_whole_track_button_desc);
UiUtilities.updateCustomRadioButtons(getMyApplication(), customRadioButton, nightMode, RIGHT);
public void setDefaultDialogMode(RouteBetweenPointsDialogMode defaultDialogMode) {
this.defaultDialogMode = defaultDialogMode;
updateModeButtons();
}
setCalculationMode(calculationMode);
public void updateModeButtons() {
UiUtilities.updateCustomRadioButtons(getMyApplication(), customRadioButton, nightMode,
defaultDialogMode == RouteBetweenPointsDialogMode.SINGLE ? LEFT : RIGHT);
btnDescription.setText(getButtonDescr(defaultDialogMode));
}
private void addProfileView(LinearLayout container, View.OnClickListener onClickListener, Object tag,
@ -195,7 +267,8 @@ public class RouteBetweenPointsBottomSheetDialogFragment extends BottomSheetDial
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putSerializable(CALCULATION_MODE_KEY, calculationMode);
outState.putSerializable(DIALOG_TYPE_KEY, dialogType);
outState.putSerializable(DEFAULT_DIALOG_MODE_KEY, defaultDialogMode);
}
@Override
@ -207,18 +280,17 @@ public class RouteBetweenPointsBottomSheetDialogFragment extends BottomSheetDial
super.onDestroyView();
}
public void setCalculationMode(CalculationMode calculationMode) {
this.calculationMode = calculationMode;
}
public static void showInstance(FragmentManager fm, Fragment targetFragment, CalculationMode calculationMode,
public static void showInstance(FragmentManager fm, Fragment targetFragment,
RouteBetweenPointsDialogType dialogType,
RouteBetweenPointsDialogMode defaultDialogMode,
ApplicationMode applicationMode) {
try {
if (!fm.isStateSaved()) {
RouteBetweenPointsBottomSheetDialogFragment fragment = new RouteBetweenPointsBottomSheetDialogFragment();
Bundle args = new Bundle();
args.putString(ROUTE_APP_MODE_KEY, applicationMode != null ? applicationMode.getStringKey() : null);
args.putSerializable(CALCULATION_MODE_KEY, calculationMode);
args.putSerializable(DIALOG_TYPE_KEY, dialogType);
args.putSerializable(DEFAULT_DIALOG_MODE_KEY, defaultDialogMode);
fragment.setArguments(args);
fragment.setTargetFragment(targetFragment, 0);
fragment.show(fm, TAG);
@ -232,7 +304,8 @@ public class RouteBetweenPointsBottomSheetDialogFragment extends BottomSheetDial
void onCloseRouteDialog();
void onChangeApplicationMode(ApplicationMode mode, CalculationMode calculationMode);
void onChangeApplicationMode(ApplicationMode mode, RouteBetweenPointsDialogType dialogType,
RouteBetweenPointsDialogMode dialogMode);
}
}

View file

@ -157,6 +157,46 @@ public class SelectedPointBottomSheetDialogFragment extends MenuBottomSheetDialo
items.add(new OptionsDividerItem(getContext()));
BaseBottomSheetItem changeRouteTypeBefore = new BottomSheetItemWithDescription.Builder()
.setDescription(getDescription(true))
.setIcon(getRouteTypeIcon(true))
.setTitle(getString(R.string.plan_route_change_route_type_before))
.setLayoutId(R.layout.bottom_sheet_item_with_descr_pad_32dp)
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Fragment targetFragment = getTargetFragment();
if (targetFragment instanceof SelectedPointFragmentListener) {
((SelectedPointFragmentListener) targetFragment).onChangeRouteTypeBefore();
}
dismiss();
}
})
.setDisabled(editingCtx.isFirstPointSelected())
.create();
items.add(changeRouteTypeBefore);
BaseBottomSheetItem changeRouteTypeAfter = new BottomSheetItemWithDescription.Builder()
.setDescription(getDescription(false))
.setIcon(getRouteTypeIcon(false))
.setTitle(getString(R.string.plan_route_change_route_type_after))
.setLayoutId(R.layout.bottom_sheet_item_with_descr_pad_32dp)
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Fragment targetFragment = getTargetFragment();
if (targetFragment instanceof SelectedPointFragmentListener) {
((SelectedPointFragmentListener) targetFragment).onChangeRouteTypeAfter();
}
dismiss();
}
})
.setDisabled(editingCtx.isLastPointSelected())
.create();
items.add(changeRouteTypeAfter);
items.add(new OptionsDividerItem(getContext()));
BaseBottomSheetItem deleteItem = new SimpleBottomSheetItem.Builder()
.setIcon(getIcon(R.drawable.ic_action_delete_dark,
nightMode ? R.color.color_osm_edit_delete : R.color.color_osm_edit_delete))
@ -283,12 +323,11 @@ public class SelectedPointBottomSheetDialogFragment extends MenuBottomSheetDialo
@Nullable
private Drawable getRouteTypeIcon(boolean before) {
Drawable icon = getContentIcon(R.drawable.ic_action_split_interval);
int pos = editingCtx.getSelectedPointPosition();
pos = before ? pos : Math.max(pos - 1, 0);
String profileType = editingCtx.getPoints().get(pos).getProfileType();
ApplicationMode routeAppMode = ApplicationMode.valueOfStringKey(profileType, null);
if (routeAppMode != null) {
ApplicationMode routeAppMode = before ? editingCtx.getBeforeSelectedPointAppMode() : editingCtx.getSelectedPointAppMode();
Drawable icon;
if (MeasurementEditingContext.DEFAULT_APP_MODE.equals(routeAppMode)) {
icon = getContentIcon(R.drawable.ic_action_split_interval);
} else {
icon = getIcon(routeAppMode.getIconRes(), routeAppMode.getIconColorInfo().getColor(nightMode));
}
return icon;

View file

@ -1,12 +1,17 @@
package net.osmand.plus.measurementtool.command;
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.MeasurementToolLayer;
import net.osmand.plus.settings.backend.ApplicationMode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static net.osmand.plus.measurementtool.MeasurementEditingContext.CalculationMode;
import static net.osmand.plus.measurementtool.MeasurementEditingContext.DEFAULT_APP_MODE;
@ -15,42 +20,88 @@ public class ChangeRouteModeCommand extends MeasurementModeCommand {
private List<WptPt> oldPoints;
private List<WptPt> newPoints;
private Map<Pair<WptPt, WptPt>, RoadSegmentData> oldRoadSegmentData;
private Map<Pair<WptPt, WptPt>, RoadSegmentData> newRoadSegmentData;
private ApplicationMode oldMode;
private ApplicationMode newMode;
private CalculationMode oldCalculationMode;
private CalculationMode newCalculationMode;
private ChangeRouteType changeRouteType;
private int pointIndex;
public enum ChangeRouteType {
LAST_SEGMENT,
WHOLE_ROUTE,
NEXT_SEGMENT,
ALL_NEXT_SEGMENTS,
PREV_SEGMENT,
ALL_PREV_SEGMENTS
}
public ChangeRouteModeCommand(MeasurementToolLayer measurementLayer, ApplicationMode newMode,
CalculationMode newCalculationMode) {
ChangeRouteType changeRouteType, int pointIndex) {
super(measurementLayer);
this.newMode = newMode;
this.newCalculationMode = newCalculationMode;
MeasurementEditingContext editingCtx = getEditingCtx();
oldMode = editingCtx.getAppMode();
oldCalculationMode = editingCtx.getCalculationMode();
this.changeRouteType = changeRouteType;
this.pointIndex = pointIndex;
this.oldMode = getEditingCtx().getAppMode();
}
@Override
public boolean execute() {
MeasurementEditingContext editingCtx = getEditingCtx();
oldPoints = new ArrayList<>(editingCtx.getPoints());
oldRoadSegmentData = editingCtx.getRoadSegmentData();
newPoints = new ArrayList<>(oldPoints.size());
newRoadSegmentData = new HashMap<>(oldRoadSegmentData);
if (oldPoints.size() > 0) {
for (WptPt pt : oldPoints) {
WptPt point = new WptPt(pt);
point.copyExtensions(pt);
newPoints.add(point);
}
switch (newCalculationMode) {
case NEXT_SEGMENT:
switch (changeRouteType) {
case LAST_SEGMENT: {
updateProfileType(newPoints.get(newPoints.size() - 1));
editingCtx.setLastCalculationMode(CalculationMode.NEXT_SEGMENT);
newRoadSegmentData = null;
break;
case WHOLE_TRACK:
}
case WHOLE_ROUTE: {
for (WptPt pt : newPoints) {
updateProfileType(pt);
}
editingCtx.setLastCalculationMode(CalculationMode.WHOLE_TRACK);
newRoadSegmentData.clear();
break;
}
case NEXT_SEGMENT: {
if (pointIndex >= 0 && pointIndex < newPoints.size()) {
updateProfileType(newPoints.get(pointIndex));
}
newRoadSegmentData.remove(getPairAt(pointIndex));
break;
}
case ALL_NEXT_SEGMENTS: {
for (int i = pointIndex; i >= 0 && i < newPoints.size(); i++) {
updateProfileType(newPoints.get(i));
newRoadSegmentData.remove(getPairAt(i));
}
break;
}
case PREV_SEGMENT: {
if (pointIndex > 0 && pointIndex < newPoints.size()) {
updateProfileType(newPoints.get(pointIndex - 1));
newRoadSegmentData.remove(getPairAt(pointIndex - 1));
}
break;
}
case ALL_PREV_SEGMENTS: {
for (int i = 0; i < pointIndex && i < newPoints.size(); i++) {
updateProfileType(newPoints.get(i));
newRoadSegmentData.remove(getPairAt(i));
}
break;
}
}
}
executeCommand();
return true;
@ -61,11 +112,8 @@ public class ChangeRouteModeCommand extends MeasurementModeCommand {
MeasurementEditingContext editingCtx = getEditingCtx();
editingCtx.getPoints().clear();
editingCtx.addPoints(oldPoints);
editingCtx.setCalculationMode(oldCalculationMode);
editingCtx.setAppMode(oldMode);
if (newCalculationMode == CalculationMode.WHOLE_TRACK) {
editingCtx.clearSnappedToRoadPoints();
}
editingCtx.setRoadSegmentData(oldRoadSegmentData);
editingCtx.updateCacheForSnap();
}
@ -79,14 +127,24 @@ public class ChangeRouteModeCommand extends MeasurementModeCommand {
return MeasurementCommandType.CHANGE_ROUTE_MODE;
}
private Pair<WptPt, WptPt> getPairAt(int pointIndex) {
WptPt first = pointIndex >= 0 && pointIndex < newPoints.size() ? newPoints.get(pointIndex) : null;
WptPt second = pointIndex >= 0 && pointIndex < newPoints.size() - 1 ? newPoints.get(pointIndex + 1) : null;
return new Pair<>(first, second);
}
private void executeCommand() {
MeasurementEditingContext editingCtx = getEditingCtx();
editingCtx.getPoints().clear();
editingCtx.addPoints(newPoints);
editingCtx.setCalculationMode(newCalculationMode);
if (newPoints.isEmpty()) {
editingCtx.setAppMode(newMode);
if (newCalculationMode == CalculationMode.WHOLE_TRACK) {
editingCtx.clearSnappedToRoadPoints();
} else {
WptPt lastPoint = newPoints.get(newPoints.size() - 1);
editingCtx.setAppMode(ApplicationMode.valueOfStringKey(lastPoint.getProfileType(), DEFAULT_APP_MODE));
}
if (newRoadSegmentData != null) {
editingCtx.setRoadSegmentData(newRoadSegmentData);
}
editingCtx.updateCacheForSnap();
}