diff --git a/OsmAnd/res/layout/bottom_sheet_item_simple_pad_32dp.xml b/OsmAnd/res/layout/bottom_sheet_item_simple_pad_32dp.xml
new file mode 100644
index 0000000000..f7600c2bff
--- /dev/null
+++ b/OsmAnd/res/layout/bottom_sheet_item_simple_pad_32dp.xml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
diff --git a/OsmAnd/res/layout/bottom_sheet_plan_route_select_file.xml b/OsmAnd/res/layout/bottom_sheet_plan_route_select_file.xml
new file mode 100644
index 0000000000..cd6f08e0fe
--- /dev/null
+++ b/OsmAnd/res/layout/bottom_sheet_plan_route_select_file.xml
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OsmAnd/res/layout/bottom_sheet_plan_route_start.xml b/OsmAnd/res/layout/bottom_sheet_plan_route_start.xml
new file mode 100644
index 0000000000..fcc2753f32
--- /dev/null
+++ b/OsmAnd/res/layout/bottom_sheet_plan_route_start.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OsmAnd/res/layout/fragment_measurement_tool.xml b/OsmAnd/res/layout/fragment_measurement_tool.xml
index e126e58a29..12ab48d201 100644
--- a/OsmAnd/res/layout/fragment_measurement_tool.xml
+++ b/OsmAnd/res/layout/fragment_measurement_tool.xml
@@ -71,7 +71,7 @@
android:layout_marginStart="@dimen/measurement_tool_text_button_padding"
android:layout_toEndOf="@id/main_icon"
android:layout_toRightOf="@id/main_icon"
- android:textAppearance="@style/TextAppearance.ListItemTitle"
+ android:textAppearance="@style/TextAppearance.ListItemCategoryTitle"
tools:text="724 m,"/>
@@ -221,8 +220,8 @@
android:text="@string/shared_string_add"
android:textColor="@color/color_white"
android:textAllCaps="false"
- android:paddingEnd="@dimen/measurement_tool_button_padding"
- android:paddingStart="@dimen/measurement_tool_button_padding" />
+ android:paddingEnd="@dimen/measurement_tool_button_padding"
+ android:paddingStart="@dimen/measurement_tool_button_padding" />
@@ -251,8 +250,8 @@
android:text="@string/shared_string_apply"
android:textColor="@color/color_white"
android:textAllCaps="false"
- android:paddingEnd="@dimen/measurement_tool_button_padding"
- android:paddingStart="@dimen/measurement_tool_button_padding" />
+ android:paddingEnd="@dimen/measurement_tool_button_padding"
+ android:paddingStart="@dimen/measurement_tool_button_padding" />
+ android:paddingEnd="@dimen/measurement_tool_button_padding"
+ android:paddingStart="@dimen/measurement_tool_button_padding" />
+ android:paddingEnd="@dimen/measurement_tool_button_padding"
+ android:paddingStart="@dimen/measurement_tool_button_padding" />
diff --git a/OsmAnd/res/layout/gpx_track_select_item.xml b/OsmAnd/res/layout/gpx_track_select_item.xml
index 1a530a7aab..9d0b905eba 100644
--- a/OsmAnd/res/layout/gpx_track_select_item.xml
+++ b/OsmAnd/res/layout/gpx_track_select_item.xml
@@ -1,10 +1,10 @@
@@ -29,9 +29,8 @@
android:layout_marginEnd="@dimen/list_content_padding"
android:layout_marginRight="@dimen/list_content_padding"
android:layout_weight="1"
- android:orientation="vertical"
- android:paddingTop="@dimen/content_padding_small"
- android:paddingBottom="@dimen/content_padding_small">
+ android:layout_gravity="center_vertical"
+ android:orientation="vertical">
48dp
64dp
24dp
+ 10dp
+ 6dp
+ 32dp
7dp
8dp
64dp
diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml
index 1de9329e5e..6ca8722b5e 100644
--- a/OsmAnd/res/values/strings.xml
+++ b/OsmAnd/res/values/strings.xml
@@ -11,6 +11,12 @@
Thx - Hardy
-->
+ Done
+ Select a track file for open.
+ Create new route
+ Open existing track
+ Import track
+ Last edited
Solid
Direction arrows
Custom
diff --git a/OsmAnd/src/net/osmand/plus/UiUtilities.java b/OsmAnd/src/net/osmand/plus/UiUtilities.java
index c60117f58c..2da7cbaac2 100644
--- a/OsmAnd/src/net/osmand/plus/UiUtilities.java
+++ b/OsmAnd/src/net/osmand/plus/UiUtilities.java
@@ -41,8 +41,8 @@ import androidx.core.view.ViewCompat;
import androidx.core.widget.TintableCompoundButton;
import com.google.android.material.slider.RangeSlider;
-import com.google.android.material.snackbar.BaseTransientBottomBar;
import com.google.android.material.slider.Slider;
+import com.google.android.material.snackbar.BaseTransientBottomBar;
import com.google.android.material.snackbar.Snackbar;
import com.google.android.material.snackbar.SnackbarContentLayout;
@@ -60,7 +60,6 @@ import org.apache.commons.logging.Log;
import java.util.ArrayList;
import java.util.List;
-
import gnu.trove.map.hash.TLongObjectHashMap;
import static net.osmand.plus.SimplePopUpMenuItemAdapter.SimplePopUpMenuItem;
@@ -184,7 +183,7 @@ public class UiUtilities {
return tintDrawable(AppCompatResources.getDrawable(context, resId), color);
}
- public static Drawable tintDrawable(Drawable drawable, int color) {
+ public static Drawable tintDrawable(Drawable drawable, @ColorInt int color) {
Drawable coloredDrawable = null;
if (drawable != null) {
coloredDrawable = DrawableCompat.wrap(drawable);
diff --git a/OsmAnd/src/net/osmand/plus/helpers/GpxTrackAdapter.java b/OsmAnd/src/net/osmand/plus/helpers/GpxTrackAdapter.java
index ab52559b28..06717dc85d 100644
--- a/OsmAnd/src/net/osmand/plus/helpers/GpxTrackAdapter.java
+++ b/OsmAnd/src/net/osmand/plus/helpers/GpxTrackAdapter.java
@@ -15,11 +15,13 @@ import net.osmand.AndroidUtils;
import net.osmand.GPXUtilities;
import net.osmand.IndexConstants;
import net.osmand.plus.GPXDatabase;
+import net.osmand.plus.GPXDatabase.GpxDataItem;
import net.osmand.plus.GpxDbHelper;
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.GpxUiHelper.GPXInfo;
import net.osmand.util.Algorithms;
import java.io.File;
@@ -29,20 +31,27 @@ import java.util.List;
public class GpxTrackAdapter extends RecyclerView.Adapter {
- private LayoutInflater themedInflater;
- private List gpxInfoList;
private OsmandApplication app;
+ private LayoutInflater themedInflater;
+ private UiUtilities iconsCache;
+ private List gpxInfoList;
private boolean showCurrentGpx;
private OnItemClickListener onItemClickListener;
- private UiUtilities iconsCache;
- GpxTrackAdapter(Context ctx, List gpxInfoList, boolean showCurrentGpx) {
- this.showCurrentGpx = showCurrentGpx;
+ public GpxTrackAdapter(Context ctx, List gpxInfoList, boolean showCurrentGpx) {
app = (OsmandApplication) ctx.getApplicationContext();
- boolean nightMode = app.getDaynightHelper().isNightModeForMapControls();
- themedInflater = UiUtilities.getInflater(ctx, nightMode);
- this.gpxInfoList = gpxInfoList;
+ themedInflater = UiUtilities.getInflater(ctx, app.getDaynightHelper().isNightModeForMapControls());
iconsCache = app.getUIUtilities();
+ this.gpxInfoList = gpxInfoList;
+ this.showCurrentGpx = showCurrentGpx;
+ }
+
+ public void setGpxInfoList(List gpxInfoList) {
+ this.gpxInfoList = gpxInfoList;
+ }
+
+ public void setShowCurrentGpx(boolean showCurrentGpx) {
+ this.showCurrentGpx = showCurrentGpx;
}
@NonNull
@@ -67,14 +76,16 @@ public class GpxTrackAdapter extends RecyclerView.Adapter() {
ProgressDialog progress = null;
@@ -264,7 +270,7 @@ public class ImportHelper {
if (AndroidUtils.isActivityNotDestroyed(activity)) {
progress.dismiss();
}
- handleResult(result, fileName, save, useImportDir, false);
+ handleResult(result, fileName, save, useImportDir, false, showInDetailsActivity);
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
@@ -941,8 +947,13 @@ public class ImportHelper {
executeImportTask(renderingImportTask);
}
+ private void handleResult(GPXFile result, String name, boolean save,
+ boolean useImportDir, boolean forceImportFavourites) {
+ handleResult(result, name, save, useImportDir, forceImportFavourites, true);
+ }
+
private void handleResult(final GPXFile result, final String name, final boolean save,
- final boolean useImportDir, boolean forceImportFavourites) {
+ final boolean useImportDir, boolean forceImportFavourites, boolean showInDetailsActivity) {
if (result != null) {
if (result.error != null) {
Toast.makeText(activity, result.error.getMessage(), Toast.LENGTH_LONG).show();
@@ -951,8 +962,9 @@ public class ImportHelper {
}
} else {
if (save) {
- new SaveAsyncTask(result, name, useImportDir).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
- } else {
+ new SaveAsyncTask(result, name, useImportDir, showInDetailsActivity)
+ .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ } else if (showInDetailsActivity) {
showGpxInDetailsActivity(result);
}
if (gpxImportCompleteListener != null) {
@@ -1057,11 +1069,13 @@ public class ImportHelper {
private final GPXFile result;
private final String name;
private final boolean useImportDir;
+ private boolean showInDetailsActivity;
- private SaveAsyncTask(GPXFile result, final String name, boolean useImportDir) {
+ private SaveAsyncTask(GPXFile result, final String name, boolean useImportDir, boolean showInDetailsActivity) {
this.result = result;
this.name = name;
this.useImportDir = useImportDir;
+ this.showInDetailsActivity = showInDetailsActivity;
}
@Override
@@ -1071,12 +1085,24 @@ public class ImportHelper {
@Override
protected void onPostExecute(final String warning) {
- if(Algorithms.isEmpty(warning)) {
- showGpxInDetailsActivity(result);
+ if (Algorithms.isEmpty(warning)) {
+ if (showInDetailsActivity) {
+ showGpxInDetailsActivity(result);
+ } else {
+ showPlanRouteFragment();
+ }
} else {
Toast.makeText(activity, warning, Toast.LENGTH_LONG).show();
}
}
+
+ private void showPlanRouteFragment() {
+ MeasurementToolFragment fragment = (MeasurementToolFragment) activity.getSupportFragmentManager()
+ .findFragmentByTag(MeasurementToolFragment.TAG);
+ if (fragment != null && !fragment.isDetached() && !fragment.isRemoving()) {
+ fragment.addNewGpxData(result);
+ }
+ }
}
private MapActivity getMapActivity() {
diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java
index cb4492c4f4..003297cb87 100644
--- a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java
+++ b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java
@@ -50,6 +50,7 @@ import net.osmand.GPXUtilities.TrkSegment;
import net.osmand.GPXUtilities.WptPt;
import net.osmand.IndexConstants;
import net.osmand.data.LatLon;
+import net.osmand.data.QuadRect;
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
import net.osmand.plus.OsmAndFormatter;
import net.osmand.plus.OsmandApplication;
@@ -79,6 +80,8 @@ import net.osmand.plus.views.MapControlsLayer;
import net.osmand.plus.views.controls.ReorderItemTouchHelperCallback;
import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory;
import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarController;
+import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarControllerType;
+import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarView;
import java.io.File;
import java.text.MessageFormat;
@@ -89,6 +92,8 @@ import java.util.List;
import java.util.Locale;
import static net.osmand.IndexConstants.GPX_FILE_EXT;
+import static net.osmand.plus.measurementtool.SelectFileBottomSheet.SelectFileListener;
+import static net.osmand.plus.measurementtool.StartPlanRouteBottomSheet.StartPlanRouteListener;
public class MeasurementToolFragment extends BaseOsmAndFragment {
@@ -117,6 +122,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment {
private boolean wasCollapseButtonVisible;
private boolean progressBarVisible;
private boolean pointsListOpened;
+ private boolean planRouteMode = false;
private Boolean saved;
private boolean portrait;
private boolean nightMode;
@@ -140,6 +146,10 @@ public class MeasurementToolFragment extends BaseOsmAndFragment {
this.initialPoint = initialPoint;
}
+ public void setPlanRouteMode(boolean planRouteMode) {
+ this.planRouteMode = planRouteMode;
+ }
+
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
@@ -198,7 +208,6 @@ public class MeasurementToolFragment extends BaseOsmAndFragment {
hidePointsListFragment();
}
- editingCtx.getCommandManager().resetMeasurementLayer(measurementLayer);
nightMode = mapActivity.getMyApplication().getDaynightHelper().isNightModeForMapControls();
portrait = AndroidUiHelper.isOrientationPortrait(mapActivity);
@@ -318,17 +327,13 @@ public class MeasurementToolFragment extends BaseOsmAndFragment {
@Override
public void onClick(View view) {
editingCtx.getCommandManager().undo();
- if (editingCtx.getCommandManager().canUndo()) {
- enable(undoBtn);
- } else {
- disable(undoBtn);
- }
+ updateUndoRedoButton(editingCtx.getCommandManager().canUndo(), undoBtn);
hidePointsListIfNoPoints();
if (editingCtx.getPointsCount() > 0) {
enable(upDownBtn);
}
adapter.notifyDataSetChanged();
- enable(redoBtn);
+ updateUndoRedoButton(true, redoBtn);
updateText();
}
});
@@ -339,17 +344,13 @@ public class MeasurementToolFragment extends BaseOsmAndFragment {
@Override
public void onClick(View view) {
editingCtx.getCommandManager().redo();
- if (editingCtx.getCommandManager().canRedo()) {
- enable(redoBtn);
- } else {
- disable(redoBtn);
- }
+ updateUndoRedoButton(editingCtx.getCommandManager().canRedo(), redoBtn);
hidePointsListIfNoPoints();
if (editingCtx.getPointsCount() > 0) {
enable(upDownBtn);
}
adapter.notifyDataSetChanged();
- enable(undoBtn);
+ updateUndoRedoButton(true, undoBtn);
updateText();
}
});
@@ -385,8 +386,8 @@ public class MeasurementToolFragment extends BaseOsmAndFragment {
String azimuthStr = OsmAndFormatter.getFormattedAzimuth(bearing, getMyApplication());
distanceToCenterTv.setText(String.format("%1$s • %2$s", distStr, azimuthStr));
TextViewCompat.setAutoSizeTextTypeUniformWithConfiguration(
- distanceToCenterTv, 12, 18, 2, TypedValue.COMPLEX_UNIT_SP
- );
+ distanceToCenterTv, 14, 18, 2,
+ TypedValue.COMPLEX_UNIT_SP);
}
});
@@ -401,16 +402,16 @@ public class MeasurementToolFragment extends BaseOsmAndFragment {
});
if (!editingCtx.getCommandManager().canUndo()) {
- disable(undoBtn);
+ updateUndoRedoButton(false, undoBtn);
}
if (!editingCtx.getCommandManager().canRedo()) {
- disable(redoBtn);
+ updateUndoRedoButton(false, redoBtn);
}
if (editingCtx.getPointsCount() < 1) {
disable(upDownBtn);
}
- toolBarController = new MeasurementToolBarController(newGpxData);
+ toolBarController = new MeasurementToolBarController();
if (editingCtx.getSelectedPointPosition() != -1) {
int navigationIconResId = AndroidUtils.getNavigationIconResId(mapActivity);
toolBarController.setBackBtnIconIds(navigationIconResId, navigationIconResId);
@@ -427,7 +428,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment {
toolBarController.setTitle(getString(R.string.edit_line));
}
} else {
- toolBarController.setTitle(getString(R.string.measurement_tool_action_bar));
+ toolBarController.setTitle(getString(R.string.plan_route));
}
toolBarController.setOnBackButtonClickListener(new View.OnClickListener() {
@Override
@@ -451,7 +452,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment {
} else {
if (newGpxData == null) {
final File dir = mapActivity.getMyApplication().getAppPath(IndexConstants.GPX_INDEX_DIR);
- String fileName = getSuggestedName(dir);
+ String fileName = getSuggestedName(dir) + GPX_FILE_EXT;
saveNewGpx(dir, fileName, true, SaveType.ROUTE_POINT, true);
} else {
addToGpx(mapActivity);
@@ -485,6 +486,17 @@ public class MeasurementToolFragment extends BaseOsmAndFragment {
pointsRv.setLayoutManager(new LinearLayoutManager(getContext()));
pointsRv.setAdapter(adapter);
+ initMeasurementMode(newGpxData);
+
+ if (planRouteMode) {
+ StartPlanRouteBottomSheet.showInstance(mapActivity.getSupportFragmentManager(),
+ createStartPlanRouteListener());
+ }
+ return view;
+ }
+
+ private void initMeasurementMode(NewGpxData newGpxData) {
+ editingCtx.getCommandManager().resetMeasurementLayer(getMapActivity().getMapLayers().getMeasurementToolLayer());
enterMeasurementMode();
showSnapToRoadControls();
@@ -503,8 +515,6 @@ public class MeasurementToolFragment extends BaseOsmAndFragment {
if (saved == null) {
saved = newGpxData != null && (newGpxData.getActionType() == ActionType.ADD_ROUTE_POINTS || newGpxData.getActionType() == ActionType.EDIT_SEGMENT);
}
-
- return view;
}
@Override
@@ -675,7 +685,8 @@ public class MeasurementToolFragment extends BaseOsmAndFragment {
if (pointsListOpened) {
hidePointsList();
}
- disable(redoBtn, upDownBtn);
+ updateUndoRedoButton(false, redoBtn);
+ disable(upDownBtn);
updateText();
saved = false;
}
@@ -765,11 +776,77 @@ public class MeasurementToolFragment extends BaseOsmAndFragment {
};
}
+ private StartPlanRouteListener createStartPlanRouteListener() {
+ return new StartPlanRouteListener() {
+ @Override
+ public void openExistingTrackOnClick() {
+ MapActivity mapActivity = getMapActivity();
+ if (mapActivity != null) {
+ SelectFileBottomSheet.showInstance(mapActivity.getSupportFragmentManager(),
+ createSelectFileListener());
+ }
+ }
+
+ @Override
+ public void openLastEditTrackOnClick(GPXFile gpxFile) {
+ addNewGpxData(gpxFile);
+ }
+
+ @Override
+ public void dismissButtonOnClick() {
+ quit(true);
+ }
+ };
+ }
+
+ private SelectFileListener createSelectFileListener() {
+ return new SelectFileListener() {
+ @Override
+ public void selectFileOnCLick(GPXFile gpxFile) {
+ addNewGpxData(gpxFile);
+ }
+
+ @Override
+ public void dismissButtonOnClick() {
+ MapActivity mapActivity = getMapActivity();
+ if (mapActivity != null) {
+ StartPlanRouteBottomSheet.showInstance(mapActivity.getSupportFragmentManager(),
+ createStartPlanRouteListener());
+ }
+ }
+ };
+ }
+
+ public void addNewGpxData(GPXFile gpxFile) {
+ QuadRect rect = gpxFile.getRect();
+ TrkSegment segment = getTrkSegment(gpxFile);
+ NewGpxData newGpxData = new NewGpxData(gpxFile, rect, ActionType.EDIT_SEGMENT, segment);
+ editingCtx.setNewGpxData(newGpxData);
+ initMeasurementMode(newGpxData);
+ QuadRect qr = newGpxData.getRect();
+ MapActivity mapActivity = getMapActivity();
+ if (mapActivity != null) {
+ mapActivity.getMapView().fitRectToMap(qr.left, qr.right, qr.top, qr.bottom,
+ (int) qr.width(), (int) qr.height(), 0);
+ }
+ }
+
+ private TrkSegment getTrkSegment(GPXFile gpxFile) {
+ for (GPXUtilities.Track t : gpxFile.tracks) {
+ for (TrkSegment s : t.segments) {
+ if (s.points.size() > 0) {
+ return s;
+ }
+ }
+ }
+ return null;
+ }
+
private void removePoint(MeasurementToolLayer layer, int position) {
editingCtx.getCommandManager().execute(new RemovePointCommand(layer, position));
adapter.notifyDataSetChanged();
- enable(undoBtn);
- disable(redoBtn);
+ updateUndoRedoButton(true, undoBtn);
+ updateUndoRedoButton(false, redoBtn);
updateText();
saved = false;
hidePointsListIfNoPoints();
@@ -831,7 +908,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment {
if (toPosition >= 0 && fromPosition >= 0 && toPosition != fromPosition) {
editingCtx.getCommandManager().execute(new ReorderPointCommand(measurementLayer, fromPosition, toPosition));
adapter.notifyDataSetChanged();
- disable(redoBtn);
+ updateUndoRedoButton(false, redoBtn);
updateText();
mapActivity.refreshMap();
saved = false;
@@ -1114,8 +1191,9 @@ public class MeasurementToolFragment extends BaseOsmAndFragment {
}
private void doAddOrMovePointCommonStuff() {
- enable(undoBtn, upDownBtn);
- disable(redoBtn);
+ enable(upDownBtn);
+ updateUndoRedoButton(true, undoBtn);
+ updateUndoRedoButton(false, redoBtn);
updateText();
adapter.notifyDataSetChanged();
saved = false;
@@ -1486,6 +1564,8 @@ public class MeasurementToolFragment extends BaseOsmAndFragment {
}
}
});
+ snackbar.getView().findViewById(com.google.android.material.R.id.snackbar_action)
+ .setAllCaps(false);
UiUtilities.setupSnackbar(snackbar, nightMode);
snackbar.show();
dismiss(mapActivity);
@@ -1502,18 +1582,24 @@ public class MeasurementToolFragment extends BaseOsmAndFragment {
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
- private void enable(View... views) {
- for (View view : views) {
- view.setEnabled(true);
- view.setAlpha(1);
- }
+ private void updateUndoRedoButton(boolean enable, View view) {
+ view.setEnabled(enable);
+ int color = enable
+ ? nightMode ? R.color.icon_color_active_dark : R.color.icon_color_active_light
+ : nightMode ? R.color.icon_color_secondary_dark : R.color.icon_color_secondary_light;
+ ImageView imageView = ((ImageView) view);
+ imageView.setImageDrawable(UiUtilities.tintDrawable(imageView.getDrawable(),
+ ContextCompat.getColor(view.getContext(), color)));
}
- private void disable(View... views) {
- for (View view : views) {
- view.setEnabled(false);
- view.setAlpha(.5f);
- }
+ private void enable(View view) {
+ view.setEnabled(true);
+ view.setAlpha(1);
+ }
+
+ private void disable(View view) {
+ view.setEnabled(false);
+ view.setAlpha(.5f);
}
private void updateText() {
@@ -1534,11 +1620,9 @@ public class MeasurementToolFragment extends BaseOsmAndFragment {
final File dir = mapActivity.getMyApplication().getAppPath(IndexConstants.GPX_INDEX_DIR);
toolBarController.setTitle(getSuggestedName(dir));
toolBarController.setDescription(getString(R.string.plan_route));
- toolBarController.setSaveViewVisible(true);
} else {
- toolBarController.setTitle(getString(R.string.measurement_tool_action_bar));
+ toolBarController.setTitle(getString(R.string.plan_route));
toolBarController.setDescription(null);
- toolBarController.setSaveViewVisible(false);
}
mapActivity.showTopToolbar(toolBarController);
}
@@ -1699,7 +1783,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment {
} else {
visibleSnapToRoadIcon(false);
}
- if (editingCtx.getNewGpxData() != null) {
+ if (editingCtx.getNewGpxData() != null && !planRouteMode) {
GPXFile gpx = editingCtx.getNewGpxData().getGpxFile();
Intent newIntent = new Intent(mapActivity, mapActivity.getMyApplication().getAppCustomization().getTrackActivity());
newIntent.putExtra(TrackActivity.TRACK_FILE_NAME, gpx.path);
@@ -1726,7 +1810,9 @@ public class MeasurementToolFragment extends BaseOsmAndFragment {
}
public static boolean showInstance(FragmentManager fragmentManager) {
- return showFragment(new MeasurementToolFragment(), fragmentManager);
+ MeasurementToolFragment fragment = new MeasurementToolFragment();
+ fragment.setPlanRouteMode(true);
+ return showFragment(fragment, fragmentManager);
}
private static boolean showFragment(MeasurementToolFragment fragment, FragmentManager fragmentManager) {
@@ -1743,29 +1829,44 @@ public class MeasurementToolFragment extends BaseOsmAndFragment {
private class MeasurementToolBarController extends TopToolbarController {
- MeasurementToolBarController(NewGpxData newGpxData) {
- super(MapInfoWidgetsFactory.TopToolbarControllerType.MEASUREMENT_TOOL);
+ MeasurementToolBarController() {
+ super(TopToolbarControllerType.MEASUREMENT_TOOL);
setBackBtnIconClrIds(0, 0);
setTitleTextClrIds(R.color.text_color_tab_active_light, R.color.text_color_tab_active_dark);
setDescrTextClrIds(R.color.text_color_tab_active_light, R.color.text_color_tab_active_dark);
setBgIds(R.drawable.gradient_toolbar, R.drawable.gradient_toolbar,
R.drawable.gradient_toolbar, R.drawable.gradient_toolbar);
setCloseBtnVisible(false);
- if (newGpxData != null) {
- setSaveViewVisible(true);
- }
+ setSaveViewVisible(true);
setSingleLineTitle(false);
+ setSaveViewTextId(R.string.shared_string_done);
}
@Override
- public void updateToolbar(MapInfoWidgetsFactory.TopToolbarView view) {
+ public void updateToolbar(TopToolbarView view) {
super.updateToolbar(view);
+ setupDoneButton(view);
View shadow = view.getShadowView();
if (shadow != null) {
shadow.setVisibility(View.GONE);
}
}
+ private void setupDoneButton(TopToolbarView view) {
+ TextView done = view.getSaveView();
+ Context ctx = done.getContext();
+ done.setAllCaps(false);
+ ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) done.getLayoutParams();
+ layoutParams.height = ctx.getResources().getDimensionPixelSize(R.dimen.measurement_tool_button_height);
+ layoutParams.leftMargin = ctx.getResources().getDimensionPixelSize(R.dimen.context_menu_padding_margin_large);
+ layoutParams.rightMargin = ctx.getResources().getDimensionPixelSize(R.dimen.context_menu_padding_margin_large);
+ int paddingH = ctx.getResources().getDimensionPixelSize(R.dimen.context_menu_padding_margin_large);
+ int paddingV = ctx.getResources().getDimensionPixelSize(R.dimen.context_menu_padding_margin_small);
+ done.setPadding(paddingH, paddingV, paddingH, paddingV);
+ AndroidUtils.setBackground(ctx, done, nightMode, R.drawable.dlg_btn_stroked_light,
+ R.drawable.dlg_btn_stroked_dark);
+ }
+
@Override
public int getStatusBarColor(Context context, boolean night) {
return NO_COLOR;
diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/SelectFileBottomSheet.java b/OsmAnd/src/net/osmand/plus/measurementtool/SelectFileBottomSheet.java
new file mode 100644
index 0000000000..4e1a46c162
--- /dev/null
+++ b/OsmAnd/src/net/osmand/plus/measurementtool/SelectFileBottomSheet.java
@@ -0,0 +1,171 @@
+package net.osmand.plus.measurementtool;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.view.View;
+
+import androidx.appcompat.view.ContextThemeWrapper;
+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.IndexConstants;
+import net.osmand.plus.OsmandApplication;
+import net.osmand.plus.R;
+import net.osmand.plus.base.MenuBottomSheetDialogFragment;
+import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem;
+import net.osmand.plus.helpers.GpxTrackAdapter;
+import net.osmand.plus.helpers.GpxTrackAdapter.OnItemClickListener;
+import net.osmand.plus.helpers.GpxUiHelper.GPXInfo;
+import net.osmand.plus.mapcontextmenu.other.HorizontalSelectionAdapter;
+import net.osmand.plus.mapcontextmenu.other.HorizontalSelectionAdapter.HorizontalSelectionAdapterListener;
+import net.osmand.util.Algorithms;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static net.osmand.plus.helpers.GpxUiHelper.getSortedGPXFilesInfo;
+
+public class SelectFileBottomSheet extends MenuBottomSheetDialogFragment {
+
+ public static final String TAG = SelectFileBottomSheet.class.getSimpleName();
+ public static final int BOTTOM_SHEET_HEIGHT_DP = 427;
+
+ protected View mainView;
+ protected GpxTrackAdapter adapter;
+ private SelectFileListener listener;
+ private Map> gpxInfoMap;
+
+ public void setListener(SelectFileListener listener) {
+ this.listener = listener;
+ }
+
+ @Override
+ public void createMenuItems(Bundle savedInstanceState) {
+ final int themeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme;
+ Context context = requireContext();
+ OsmandApplication app = requiredMyApplication();
+ mainView = View.inflate(new ContextThemeWrapper(context, themeRes),
+ R.layout.bottom_sheet_plan_route_select_file, null);
+ final RecyclerView filesRecyclerView = mainView.findViewById(R.id.gpx_track_list);
+ filesRecyclerView.setLayoutManager(new LinearLayoutManager(context));
+
+ List dirs = new ArrayList<>();
+ final File gpxDir = app.getAppPath(IndexConstants.GPX_INDEX_DIR);
+ collectDirs(gpxDir, dirs);
+ List dirItems = new ArrayList<>();
+ for (File dir : dirs) {
+ dirItems.add(dir.getName());
+ }
+ String allFilesFolder = context.getString(R.string.shared_string_all);
+ dirItems.add(0, allFilesFolder);
+
+ final List allGpxList = getSortedGPXFilesInfo(gpxDir, null, false);
+ gpxInfoMap = new HashMap<>();
+ gpxInfoMap.put(allFilesFolder, allGpxList);
+ for (GPXInfo gpxInfo : allGpxList) {
+ String folderName = getFolderName(gpxInfo);
+ List gpxList = gpxInfoMap.get(folderName);
+ if (gpxList == null) {
+ gpxList = new ArrayList<>();
+ gpxInfoMap.put(folderName, gpxList);
+ }
+ gpxList.add(gpxInfo);
+ }
+ adapter = new GpxTrackAdapter(requireContext(), allGpxList, false);
+ adapter.setAdapterListener(new OnItemClickListener() {
+ @Override
+ public void onItemClick(int position) {
+ if (position != RecyclerView.NO_POSITION && position < allGpxList.size()) {
+ String fileName = allGpxList.get(position).getFileName();
+ GPXFile gpxFile = GPXUtilities.loadGPXFile(new File(gpxDir, fileName));
+ if (listener != null) {
+ listener.selectFileOnCLick(gpxFile);
+ }
+ }
+ dismiss();
+ }
+ });
+ filesRecyclerView.setAdapter(adapter);
+
+ final RecyclerView foldersRecyclerView = mainView.findViewById(R.id.folder_list);
+ foldersRecyclerView.setLayoutManager(new LinearLayoutManager(context,
+ RecyclerView.HORIZONTAL, false));
+ final HorizontalSelectionAdapter folderAdapter = new HorizontalSelectionAdapter(app, nightMode);
+ folderAdapter.setItems(dirItems);
+ folderAdapter.setSelectedItem(allFilesFolder);
+ foldersRecyclerView.setAdapter(folderAdapter);
+ folderAdapter.setListener(new HorizontalSelectionAdapterListener() {
+ @Override
+ public void onItemSelected(String item) {
+ List gpxInfoList = gpxInfoMap.get(item);
+ adapter.setGpxInfoList(gpxInfoList != null ? gpxInfoList : new ArrayList());
+ adapter.notifyDataSetChanged();
+ folderAdapter.notifyDataSetChanged();
+ }
+ });
+ items.add(new BaseBottomSheetItem.Builder().setCustomView(mainView).create());
+ }
+
+ private String getFolderName(GPXInfo gpxInfo) {
+ int fileNameStartIndex = gpxInfo.getFileName().lastIndexOf(File.separator);
+ return fileNameStartIndex != -1
+ ? gpxInfo.getFileName().substring(0, fileNameStartIndex)
+ : IndexConstants.GPX_INDEX_DIR.substring(0, IndexConstants.GPX_INDEX_DIR.length() - 1);
+ }
+
+ private void collectDirs(File dir, List dirs) {
+ File[] listFiles = dir.listFiles();
+ if (listFiles != null) {
+ Arrays.sort(listFiles);
+ for (File f : listFiles) {
+ if (f.isDirectory()) {
+ dirs.add(f);
+ collectDirs(f, dirs);
+ }
+ }
+ }
+ }
+
+ @Override
+ protected int getCustomHeight() {
+ return AndroidUtils.dpToPx(mainView.getContext(), BOTTOM_SHEET_HEIGHT_DP);
+ }
+
+ public static void showInstance(FragmentManager fragmentManager, SelectFileListener listener) {
+ if (!fragmentManager.isStateSaved()) {
+ SelectFileBottomSheet fragment = new SelectFileBottomSheet();
+ fragment.setUsedOnMap(true);
+ fragment.setRetainInstance(true);
+ fragment.setListener(listener);
+ fragment.show(fragmentManager, SelectFileBottomSheet.TAG);
+ }
+ }
+
+ @Override
+ protected int getDismissButtonTextId() {
+ return R.string.shared_string_cancel;
+ }
+
+ @Override
+ protected void onDismissButtonClickAction() {
+ if (listener != null) {
+ listener.dismissButtonOnClick();
+ }
+ }
+
+ interface SelectFileListener {
+
+ void selectFileOnCLick(GPXFile gpxFile);
+
+ void dismissButtonOnClick();
+
+ }
+}
diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/StartPlanRouteBottomSheet.java b/OsmAnd/src/net/osmand/plus/measurementtool/StartPlanRouteBottomSheet.java
new file mode 100644
index 0000000000..52f8b64b25
--- /dev/null
+++ b/OsmAnd/src/net/osmand/plus/measurementtool/StartPlanRouteBottomSheet.java
@@ -0,0 +1,229 @@
+package net.osmand.plus.measurementtool;
+
+import android.app.Activity;
+import android.content.ActivityNotFoundException;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.view.View;
+
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.view.ContextThemeWrapper;
+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.IndexConstants;
+import net.osmand.PlatformUtil;
+import net.osmand.plus.OsmandApplication;
+import net.osmand.plus.R;
+import net.osmand.plus.base.MenuBottomSheetDialogFragment;
+import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem;
+import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithDescription;
+import net.osmand.plus.base.bottomsheetmenu.simpleitems.DividerHalfItem;
+import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem;
+import net.osmand.plus.helpers.GpxTrackAdapter;
+import net.osmand.plus.helpers.GpxUiHelper.GPXInfo;
+import net.osmand.plus.helpers.ImportHelper;
+
+import org.apache.commons.logging.Log;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import static net.osmand.plus.helpers.GpxUiHelper.getSortedGPXFilesInfo;
+
+public class StartPlanRouteBottomSheet extends MenuBottomSheetDialogFragment {
+
+ public static final String TAG = StartPlanRouteBottomSheet.class.getSimpleName();
+ private static final Log LOG = PlatformUtil.getLog(StartPlanRouteBottomSheet.class);
+ public static final int BOTTOM_SHEET_HEIGHT_DP = 427;
+ private static final int OPEN_GPX_DOCUMENT_REQUEST = 1001;
+
+ protected View mainView;
+ protected GpxTrackAdapter adapter;
+ private StartPlanRouteListener listener;
+ private ImportHelper importHelper;
+
+ public void setListener(StartPlanRouteListener listener) {
+ this.listener = listener;
+ }
+
+ @Override
+ public void createMenuItems(Bundle savedInstanceState) {
+ importHelper = new ImportHelper((AppCompatActivity) getActivity(), getMyApplication(), null);
+ final int themeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme;
+ mainView = View.inflate(new ContextThemeWrapper(getContext(), themeRes),
+ R.layout.bottom_sheet_plan_route_start, null);
+
+ items.add(new TitleItem(getString(R.string.plan_route)));
+
+ BaseBottomSheetItem createNewRouteItem = new BottomSheetItemWithDescription.Builder()
+ .setIcon(getContentIcon(R.drawable.ic_notification_track))
+ .setTitle(getString(R.string.plan_route_create_new_route))
+ .setLayoutId(R.layout.bottom_sheet_item_simple_pad_32dp)
+ .setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ dismiss();
+ }
+ })
+ .create();
+ items.add(createNewRouteItem);
+
+ BaseBottomSheetItem openExistingTrackItem = new BottomSheetItemWithDescription.Builder()
+ .setIcon(getContentIcon(R.drawable.ic_action_folder))
+ .setTitle(getString(R.string.plan_route_open_existing_track))
+ .setLayoutId(R.layout.bottom_sheet_item_simple_pad_32dp)
+ .setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (listener != null) {
+ listener.openExistingTrackOnClick();
+ }
+ dismiss();
+ }
+ })
+ .create();
+ items.add(openExistingTrackItem);
+
+ BaseBottomSheetItem importTrackItem = new BottomSheetItemWithDescription.Builder()
+ .setIcon(getContentIcon(R.drawable.ic_action_phone))
+ .setTitle(getString(R.string.plan_route_import_track))
+ .setLayoutId(R.layout.bottom_sheet_item_simple_pad_32dp)
+ .setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ importTrack();
+ }
+ })
+ .create();
+ items.add(importTrackItem);
+
+ items.add(new DividerHalfItem(getContext()));
+
+ final RecyclerView recyclerView = mainView.findViewById(R.id.gpx_track_list);
+ recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
+ OsmandApplication app = getMyApplication();
+ if (app == null) {
+ return;
+ }
+
+ File gpxDir = app.getAppPath(IndexConstants.GPX_INDEX_DIR);
+ List gpxList = getSortedGPXFilesInfo(gpxDir, null, false);
+ Collections.sort(gpxList, new Comparator() {
+ @Override
+ public int compare(GPXInfo lhs, GPXInfo rhs) {
+ return lhs.getLastModified() > rhs.getLastModified()
+ ? -1 : (lhs.getLastModified() == rhs.getLastModified() ? 0 : 1);
+ }
+ });
+ final List gpxTopList = gpxList.subList(0, Math.min(5, gpxList.size()));
+ adapter = new GpxTrackAdapter(requireContext(), gpxList, false);
+ adapter.setAdapterListener(new GpxTrackAdapter.OnItemClickListener() {
+ @Override
+ public void onItemClick(int position) {
+ StartPlanRouteBottomSheet.this.onItemClick(position, gpxTopList);
+ }
+ });
+ recyclerView.setAdapter(adapter);
+ items.add(new BaseBottomSheetItem.Builder().setCustomView(mainView).create());
+ }
+
+ @Override
+ protected int getCustomHeight() {
+ return AndroidUtils.dpToPx(mainView.getContext(), BOTTOM_SHEET_HEIGHT_DP);
+ }
+
+ private void onItemClick(int position, List gpxInfoList) {
+ if (position != RecyclerView.NO_POSITION && position < gpxInfoList.size()) {
+ OsmandApplication app = requiredMyApplication();
+ String fileName = gpxInfoList.get(position).getFileName();
+ GPXFile gpxFile = GPXUtilities.loadGPXFile(new File(app.getAppPath(IndexConstants.GPX_INDEX_DIR), fileName));
+ if (listener != null) {
+ listener.openLastEditTrackOnClick(gpxFile);
+ }
+ }
+ dismiss();
+ }
+
+ private void importTrack() {
+ Intent intent = new Intent();
+ String action;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+ action = Intent.ACTION_OPEN_DOCUMENT;
+ } else {
+ action = Intent.ACTION_GET_CONTENT;
+ }
+ intent.setAction(action);
+ intent.setType("*/*");
+ try {
+ startActivityForResult(intent, OPEN_GPX_DOCUMENT_REQUEST);
+ } catch (ActivityNotFoundException e) {
+ LOG.error(e.getMessage(), e);
+ }
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (requestCode == OPEN_GPX_DOCUMENT_REQUEST && resultCode == Activity.RESULT_OK) {
+ if (data != null) {
+ Uri uri = data.getData();
+ importHelper.setGpxImportCompleteListener(new ImportHelper.OnGpxImportCompleteListener() {
+ @Override
+ public void onComplete(boolean success) {
+ finishImport(success);
+ importHelper.setGpxImportCompleteListener(null);
+ }
+ });
+ importHelper.handleGpxImport(uri, false, false);
+ }
+ } else {
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+ }
+
+ void finishImport(boolean success) {
+ if (success) {
+ dismiss();
+ }
+ }
+
+ public static void showInstance(FragmentManager fragmentManager, StartPlanRouteListener listener) {
+ if (!fragmentManager.isStateSaved()) {
+ StartPlanRouteBottomSheet fragment = new StartPlanRouteBottomSheet();
+ fragment.setUsedOnMap(true);
+ fragment.setRetainInstance(true);
+ fragment.setListener(listener);
+ fragment.show(fragmentManager, StartPlanRouteBottomSheet.TAG);
+ }
+ }
+
+ @Override
+ protected int getDismissButtonTextId() {
+ return R.string.shared_string_cancel;
+ }
+
+ @Override
+ protected void onDismissButtonClickAction() {
+ if (listener != null) {
+ listener.dismissButtonOnClick();
+ }
+ }
+
+ interface StartPlanRouteListener {
+
+ void openExistingTrackOnClick();
+
+ void openLastEditTrackOnClick(GPXFile gpxFile);
+
+ void dismissButtonOnClick();
+
+ }
+}