diff --git a/OsmAnd-java/src/main/java/net/osmand/util/Algorithms.java b/OsmAnd-java/src/main/java/net/osmand/util/Algorithms.java index 7dd69b9be4..21e7fbd58c 100644 --- a/OsmAnd-java/src/main/java/net/osmand/util/Algorithms.java +++ b/OsmAnd-java/src/main/java/net/osmand/util/Algorithms.java @@ -26,6 +26,7 @@ import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Map.Entry; @@ -139,6 +140,26 @@ public class Algorithms { return name; } + public static List collectDirs(File parentDir, List dirs) { + return collectDirs(parentDir, dirs, null); + } + + public static List collectDirs(File parentDir, List dirs, File exclDir) { + File[] listFiles = parentDir.listFiles(); + if (listFiles != null) { + Arrays.sort(listFiles); + for (File f : listFiles) { + if (f.isDirectory()) { + if (!f.equals(exclDir)) { + dirs.add(f); + } + Algorithms.collectDirs(f, dirs); + } + } + } + return dirs; + } + public static File[] getSortedFilesVersions(File dir) { File[] listFiles = dir.listFiles(); if (listFiles != null) { diff --git a/OsmAnd/res/layout/bottom_sheet_item_with_switch_and_descr.xml b/OsmAnd/res/layout/bottom_sheet_item_with_switch_and_descr.xml new file mode 100644 index 0000000000..6c3ad9cefe --- /dev/null +++ b/OsmAnd/res/layout/bottom_sheet_item_with_switch_and_descr.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/markers_track_name_text_field_box.xml b/OsmAnd/res/layout/markers_track_name_text_field_box.xml deleted file mode 100644 index 17cd56c10a..0000000000 --- a/OsmAnd/res/layout/markers_track_name_text_field_box.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/OsmAnd/res/layout/measure_track_is_saved.xml b/OsmAnd/res/layout/measure_track_is_saved.xml new file mode 100644 index 0000000000..39a05764e5 --- /dev/null +++ b/OsmAnd/res/layout/measure_track_is_saved.xml @@ -0,0 +1,40 @@ + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/markers_track_name_edit_text.xml b/OsmAnd/res/layout/track_name_edit_text.xml similarity index 80% rename from OsmAnd/res/layout/markers_track_name_edit_text.xml rename to OsmAnd/res/layout/track_name_edit_text.xml index b2b4f6da29..545b7c42a0 100644 --- a/OsmAnd/res/layout/markers_track_name_edit_text.xml +++ b/OsmAnd/res/layout/track_name_edit_text.xml @@ -1,14 +1,14 @@ + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical"> + android:focusableInTouchMode="true" /> + android:layout_height="wrap_content" /> diff --git a/OsmAnd/res/values/sizes.xml b/OsmAnd/res/values/sizes.xml index beba6fe553..8d403a7133 100644 --- a/OsmAnd/res/values/sizes.xml +++ b/OsmAnd/res/values/sizes.xml @@ -262,6 +262,8 @@ 6dp 14dp 16dp + 100dp + 60dp 8dp 8dp 10dp diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index 04996c9fa1..48444fd8c4 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -11,6 +11,8 @@ Thx - Hardy --> + is saved + Open saved track All previous segments will be recalculated using selected profile. All next segments will be recalculated using selected profile. Only selected segment will be recalculated using selected profile. @@ -24,6 +26,9 @@ Will pause track logging when the app is killed (via recent apps). (OsmAnd background indication disappears from the Android notification bar.) REC %s track files selected + File name + Only the route line will be saved, the waypoints will be deleted. + Simplified track Change route type after Change route type before Trim after diff --git a/OsmAnd/src/net/osmand/plus/base/bottomsheetmenu/BottomSheetItemWithDescription.java b/OsmAnd/src/net/osmand/plus/base/bottomsheetmenu/BottomSheetItemWithDescription.java index 0593f6c519..b138bee19f 100644 --- a/OsmAnd/src/net/osmand/plus/base/bottomsheetmenu/BottomSheetItemWithDescription.java +++ b/OsmAnd/src/net/osmand/plus/base/bottomsheetmenu/BottomSheetItemWithDescription.java @@ -12,6 +12,7 @@ import androidx.annotation.LayoutRes; import androidx.core.content.ContextCompat; import net.osmand.plus.R; +import net.osmand.util.Algorithms; public class BottomSheetItemWithDescription extends SimpleBottomSheetItem { @@ -73,8 +74,13 @@ public class BottomSheetItemWithDescription extends SimpleBottomSheetItem { @Override public void inflate(Context context, ViewGroup container, boolean nightMode) { super.inflate(context, container, nightMode); - descriptionTv = (TextView) view.findViewById(R.id.description); + descriptionTv = view.findViewById(R.id.description); if (descriptionTv != null) { + if (Algorithms.isEmpty(description)) { + descriptionTv.setVisibility(View.GONE); + } else { + descriptionTv.setVisibility(View.VISIBLE); + } descriptionTv.setText(description); if (descriptionColorId != INVALID_ID) { descriptionTv.setTextColor(ContextCompat.getColor(context, descriptionColorId)); diff --git a/OsmAnd/src/net/osmand/plus/base/bottomsheetmenu/BottomSheetItemWithDescriptionDifHeight.java b/OsmAnd/src/net/osmand/plus/base/bottomsheetmenu/BottomSheetItemWithDescriptionDifHeight.java index 4ec0060f02..1fe76373ec 100644 --- a/OsmAnd/src/net/osmand/plus/base/bottomsheetmenu/BottomSheetItemWithDescriptionDifHeight.java +++ b/OsmAnd/src/net/osmand/plus/base/bottomsheetmenu/BottomSheetItemWithDescriptionDifHeight.java @@ -8,7 +8,8 @@ import android.widget.LinearLayout; import androidx.annotation.ColorRes; import androidx.annotation.LayoutRes; -import androidx.core.view.ViewCompat; + +import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; public class BottomSheetItemWithDescriptionDifHeight extends BottomSheetItemWithDescription { @@ -50,22 +51,19 @@ public class BottomSheetItemWithDescriptionDifHeight extends BottomSheetItemWith } - @Override public void inflate(Context context, ViewGroup container, boolean nightMode) { super.inflate(context, container, nightMode); - if (minHeight == 0) { - minHeight = ViewCompat.getMinimumHeight(view); + if (minHeight != INVALID_VALUE) { + LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) view.getLayoutParams(); + params.height = WRAP_CONTENT; + view.setMinimumHeight(minHeight); } - LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) view.getLayoutParams(); - params.height = minHeight; - view.setMinimumHeight(minHeight); - } public static class Builder extends BottomSheetItemWithDescription.Builder { - int minHeight; + int minHeight = INVALID_VALUE; public Builder setMinHeight(int minHeight) { this.minHeight = minHeight; diff --git a/OsmAnd/src/net/osmand/plus/mapmarkers/SaveAsTrackBottomSheetDialogFragment.java b/OsmAnd/src/net/osmand/plus/mapmarkers/SaveAsTrackBottomSheetDialogFragment.java index 5cdb3571c2..f176437ebd 100644 --- a/OsmAnd/src/net/osmand/plus/mapmarkers/SaveAsTrackBottomSheetDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/mapmarkers/SaveAsTrackBottomSheetDialogFragment.java @@ -1,6 +1,5 @@ package net.osmand.plus.mapmarkers; -import android.os.Build; import android.os.Bundle; import android.text.format.DateFormat; import android.view.ContextThemeWrapper; @@ -70,14 +69,10 @@ public class SaveAsTrackBottomSheetDialogFragment extends BottomSheetDialogFragm titleTv.setText(openFromCoordinateInput ? R.string.coord_input_save_as_track : R.string.marker_save_as_track); titleTv.setTextColor(ContextCompat.getColor(getContext(), textPrimaryColor)); TextView descriptionTv = (TextView) mainView.findViewById(R.id.save_as_track_description); - descriptionTv.setText(openFromCoordinateInput ? getString(R.string.coord_input_save_as_track_descr, number) : getString(R.string.marker_save_as_track_descr)); - int layoutRes; - if (Build.VERSION.SDK_INT > Build.VERSION_CODES.ICE_CREAM_SANDWICH) { - layoutRes = R.layout.markers_track_name_text_field_box; - } else { - layoutRes = R.layout.markers_track_name_edit_text; - } - contentLayout.addView(getLayoutInflater().inflate(layoutRes, contentLayout, false), 2); + descriptionTv.setText(openFromCoordinateInput + ? getString(R.string.coord_input_save_as_track_descr, String.valueOf(number)) + : getString(R.string.marker_save_as_track_descr)); + contentLayout.addView(getLayoutInflater().inflate(R.layout.track_name_edit_text, contentLayout, false), 2); if (portrait) { AndroidUtils.setBackground(getActivity(), mainView, nightMode, R.drawable.bg_bottom_menu_light, R.drawable.bg_bottom_menu_dark); } diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java index db1aa41bd8..771eab8b74 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java @@ -66,7 +66,6 @@ import net.osmand.plus.measurementtool.OptionsBottomSheetDialogFragment.OptionsF 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; import net.osmand.plus.measurementtool.adapter.MeasurementToolAdapter; import net.osmand.plus.measurementtool.adapter.MeasurementToolAdapter.MeasurementAdapterListener; @@ -100,6 +99,7 @@ import java.util.Locale; import static net.osmand.IndexConstants.GPX_FILE_EXT; import static net.osmand.plus.measurementtool.MeasurementEditingContext.CalculationMode; import static net.osmand.plus.measurementtool.MeasurementEditingContext.SnapToRoadProgressListener; +import static net.osmand.plus.measurementtool.SaveAsNewTrackBottomSheetDialogFragment.*; import static net.osmand.plus.measurementtool.SelectFileBottomSheet.Mode.ADD_TO_TRACK; import static net.osmand.plus.measurementtool.SelectFileBottomSheet.Mode.OPEN_TRACK; import static net.osmand.plus.measurementtool.SelectFileBottomSheet.SelectFileListener; @@ -110,7 +110,8 @@ import static net.osmand.plus.measurementtool.command.ClearPointsCommand.ClearCo import static net.osmand.plus.measurementtool.command.ClearPointsCommand.ClearCommandMode.BEFORE; public class MeasurementToolFragment extends BaseOsmAndFragment implements RouteBetweenPointsFragmentListener, - OptionsFragmentListener, GpxApproximationFragmentListener, SelectedPointFragmentListener { + OptionsFragmentListener, GpxApproximationFragmentListener, SelectedPointFragmentListener, + SaveAsNewTrackFragmentListener { public static final String TAG = MeasurementToolFragment.class.getSimpleName(); @@ -132,6 +133,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route private ImageView redoBtn; private ImageView mainIcon; private Snackbar snackbar; + private String fileName; private boolean wasCollapseButtonVisible; private boolean progressBarVisible; @@ -150,6 +152,12 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route LINE } + private enum SaveAction { + SHOW_SNACK_BAR_AND_CLOSE, + SHOW_TOAST, + SHOW_IS_SAVED_FRAGMENT + } + private void setEditingCtx(MeasurementEditingContext editingCtx) { this.editingCtx = editingCtx; } @@ -199,11 +207,6 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route measurementLayer.setEditingCtx(editingCtx); - // Handling screen rotation - Fragment saveAsNewTrackFragment = mapActivity.getSupportFragmentManager().findFragmentByTag(SaveAsNewTrackBottomSheetDialogFragment.TAG); - if (saveAsNewTrackFragment != null) { - ((SaveAsNewTrackBottomSheetDialogFragment) saveAsNewTrackFragment).setListener(createSaveAsNewTrackFragmentListener()); - } // If rotate the screen from landscape to portrait when the list of points is displayed then // the RecyclerViewFragment will exist without view. This is necessary to remove it. if (!portrait) { @@ -399,7 +402,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route toolBarController.setOnSaveViewClickListener(new OnClickListener() { @Override public void onClick(View v) { - saveChanges(true); + saveChanges(SaveAction.SHOW_SNACK_BAR_AND_CLOSE); } }); updateToolbar(); @@ -431,7 +434,9 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route initMeasurementMode(gpxData); if (savedInstanceState == null) { - if (editingCtx.isNewData() && planRouteMode) { + if (fileName != null) { + addNewGpxData(getGpxFile(fileName)); + } else if (editingCtx.isNewData() && planRouteMode && initialPoint == null) { StartPlanRouteBottomSheet.showInstance(mapActivity.getSupportFragmentManager(), createStartPlanRouteListener()); } else if (!editingCtx.isNewData() && !editingCtx.hasRoutePoints() && !editingCtx.hasRoute() && editingCtx.getPointsCount() > 1) { @@ -446,6 +451,10 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route return !planRouteMode && !editingCtx.isNewData(); } + public void setFileName(String fileName) { + this.fileName = fileName; + } + private void updateUndoRedoCommonStuff() { hidePointsListIfNoPoints(); if (editingCtx.getPointsCount() > 0) { @@ -589,17 +598,17 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route } } - public void saveChanges(boolean close) { + public void saveChanges(SaveAction saveAction) { MapActivity mapActivity = getMapActivity(); if (mapActivity != null) { if (editingCtx.getPointsCount() > 0) { GpxData gpxData = editingCtx.getGpxData(); if (editingCtx.isNewData()) { - saveAsGpx(SaveType.ROUTE_POINT, close); + saveAsGpx(SaveType.ROUTE_POINT, saveAction); } else if (isInEditMode() && gpxData.getActionType() == ActionType.EDIT_SEGMENT) { openSaveAsNewTrackMenu(mapActivity); } else { - addToGpx(mapActivity, close); + addToGpx(mapActivity, saveAction); } } else { Toast.makeText(mapActivity, getString(R.string.none_point_error), Toast.LENGTH_SHORT).show(); @@ -660,7 +669,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route @Override public void saveChangesOnClick() { - saveChanges(false); + saveChanges(SaveAction.SHOW_TOAST); } @Override @@ -899,11 +908,17 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route @Override public void selectFileOnCLick(String gpxFileName) { if (mapActivity != null) { - GPXFile gpxFile = getGpxFile(gpxFileName); + GPXFile gpxFile; + if (gpxFileName == null) { + gpxFile = mapActivity.getMyApplication().getSavingTrackHelper().getCurrentGpx(); + } else { + gpxFile = getGpxFile(gpxFileName); + } SelectedGpxFile selectedGpxFile = mapActivity.getMyApplication().getSelectedGpxHelper() .getSelectedFileByPath(gpxFile.path); boolean showOnMap = selectedGpxFile != null; - saveExistingGpx(gpxFile, showOnMap, ActionType.ADD_SEGMENT, editingCtx.hasRoute() ? SaveType.ROUTE_POINT : SaveType.LINE, false); + saveExistingGpx(gpxFile, showOnMap, ActionType.ADD_SEGMENT, + editingCtx.hasRoute() ? SaveType.ROUTE_POINT : SaveType.LINE, SaveAction.SHOW_TOAST); } } @@ -939,18 +954,15 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route } } - private SaveAsNewTrackFragmentListener createSaveAsNewTrackFragmentListener() { - return new SaveAsNewTrackFragmentListener() { - @Override - public void saveAsRoutePointOnClick() { - saveAsGpx(SaveType.ROUTE_POINT, false); - } - - @Override - public void saveAsLineOnClick() { - saveAsGpx(SaveType.LINE, false); - } - }; + @Override + public void onSaveAsNewTrack(String folderName, String fileName, boolean showOnMap, boolean simplifiedTrack) { + File dir = getMyApplication().getAppPath(IndexConstants.GPX_INDEX_DIR); + if (folderName != null) { + dir = new File(dir, folderName); + } + fileName = fileName + GPX_FILE_EXT; + SaveType saveType = simplifiedTrack ? SaveType.LINE : SaveType.ROUTE_POINT; + saveNewGpx(dir, fileName, showOnMap, saveType, SaveAction.SHOW_IS_SAVED_FRAGMENT); } private MeasurementAdapterListener createMeasurementAdapterListener(final ItemTouchHelper touchHelper) { @@ -1076,10 +1088,8 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route private void openSaveAsNewTrackMenu(MapActivity mapActivity) { if (mapActivity != null) { if (editingCtx.getPointsCount() > 0) { - SaveAsNewTrackBottomSheetDialogFragment fragment = new SaveAsNewTrackBottomSheetDialogFragment(); - fragment.setUsedOnMap(true); - fragment.setListener(createSaveAsNewTrackFragmentListener()); - fragment.show(mapActivity.getSupportFragmentManager(), SaveAsNewTrackBottomSheetDialogFragment.TAG); + SaveAsNewTrackBottomSheetDialogFragment.showInstance(mapActivity.getSupportFragmentManager(), + this, getSuggestedFileName()); } else { Toast.makeText(mapActivity, getString(R.string.none_point_error), Toast.LENGTH_SHORT).show(); } @@ -1346,18 +1356,19 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route } } - private void addToGpx(MapActivity mapActivity, boolean close) { + private void addToGpx(MapActivity mapActivity, SaveAction saveAction) { GpxData gpxData = editingCtx.getGpxData(); GPXFile gpx = gpxData != null ? gpxData.getGpxFile() : null; if (gpx != null) { SelectedGpxFile selectedGpxFile = mapActivity.getMyApplication().getSelectedGpxHelper().getSelectedFileByPath(gpx.path); boolean showOnMap = selectedGpxFile != null; - saveExistingGpx(gpx, showOnMap, gpxData.getActionType(), editingCtx.hasRoute() ? SaveType.ROUTE_POINT : SaveType.LINE, close); + saveExistingGpx(gpx, showOnMap, gpxData.getActionType(), + editingCtx.hasRoute() ? SaveType.ROUTE_POINT : SaveType.LINE, saveAction); } } - private void saveAsGpx(final SaveType saveType, final boolean close) { + private void saveAsGpx(final SaveType saveType, final SaveAction saveAction) { MapActivity mapActivity = getMapActivity(); if (mapActivity != null) { final File dir = mapActivity.getMyApplication().getAppPath(IndexConstants.GPX_INDEX_DIR); @@ -1375,7 +1386,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route }); showOnMapToggle.setChecked(true); - String displayedName = getSuggestedFileName(dir); + String displayedName = getSuggestedFileName(); nameEt.setText(displayedName); nameEt.setSelection(displayedName.length()); final boolean[] textChanged = new boolean[1]; @@ -1396,7 +1407,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route fout = new File(dir, fileName); } } - saveNewGpx(dir, fileName, showOnMapToggle.isChecked(), saveType, close); + saveNewGpx(dir, fileName, showOnMapToggle.isChecked(), saveType, saveAction); } }) .setNegativeButton(R.string.shared_string_cancel, null); @@ -1434,17 +1445,21 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route } } - private String getSuggestedFileName(File dir) { + private String getSuggestedFileName() { GpxData gpxData = editingCtx.getGpxData(); String displayedName; if (gpxData == null) { final String suggestedName = new SimpleDateFormat("EEE dd MMM yyyy", Locale.US).format(new Date()); displayedName = suggestedName; - File fout = new File(dir, suggestedName + GPX_FILE_EXT); - int ind = 0; - while (fout.exists()) { - displayedName = suggestedName + "_" + (++ind); - fout = new File(dir, displayedName + GPX_FILE_EXT); + OsmandApplication app = getMyApplication(); + if (app != null) { + File dir = app.getAppPath(IndexConstants.GPX_INDEX_DIR); + File fout = new File(dir, suggestedName + GPX_FILE_EXT); + int ind = 0; + while (fout.exists()) { + displayedName = suggestedName + "_" + (++ind); + fout = new File(dir, displayedName + GPX_FILE_EXT); + } } } else { displayedName = AndroidUtils.trimExtension(new File(gpxData.getGpxFile().path).getName()); @@ -1452,12 +1467,13 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route return displayedName; } - private void saveNewGpx(File dir, String fileName, boolean showOnMap, SaveType saveType, boolean close) { - saveGpx(dir, fileName, showOnMap, null, null, saveType, close); + private void saveNewGpx(File dir, String fileName, boolean showOnMap, SaveType saveType, SaveAction saveAction) { + saveGpx(dir, fileName, showOnMap, null, null, saveType, saveAction); } - private void saveExistingGpx(GPXFile gpx, boolean showOnMap, ActionType actionType, SaveType saveType, boolean close) { - saveGpx(null, null, showOnMap, gpx, actionType, saveType, close); + private void saveExistingGpx(GPXFile gpx, boolean showOnMap, ActionType actionType, SaveType saveType, + SaveAction saveAction) { + saveGpx(null, null, showOnMap, gpx, actionType, saveType, saveAction); } @SuppressLint("StaticFieldLeak") @@ -1467,7 +1483,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route final GPXFile gpxFile, final ActionType actionType, final SaveType saveType, - final boolean close) { + final SaveAction saveAction) { new AsyncTask() { @@ -1595,7 +1611,10 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route gpx.addRoutePoints(points); } } - Exception res = GPXUtilities.writeGpxFile(toSave, gpx); + Exception res = null; + if (!gpx.showCurrentTrack) { + res = GPXUtilities.writeGpxFile(toSave, gpx); + } savedGpxFile = gpx; if (showOnMap) { SelectedGpxFile sf = app.getSelectedGpxHelper().selectGpxFile(gpx, true, false); @@ -1635,34 +1654,42 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route if (isInEditMode()) { dismiss(mapActivity); } else { - if (close) { - final WeakReference mapActivityRef = new WeakReference<>(mapActivity); - snackbar = Snackbar.make(mapActivity.getLayout(), - MessageFormat.format(getString(R.string.gpx_saved_sucessfully), toSave.getName()), - Snackbar.LENGTH_LONG) - .setAction(R.string.shared_string_rename, new OnClickListener() { - @Override - public void onClick(View view) { - MapActivity mapActivity = mapActivityRef.get(); - if (AndroidUtils.isActivityNotDestroyed(mapActivity)) { - FileUtils.renameFile(mapActivity, toSave, new FileUtils.RenameCallback() { - @Override - public void renamedTo(File file) { - - } - }); + switch (saveAction) { + case SHOW_SNACK_BAR_AND_CLOSE: + final WeakReference mapActivityRef = new WeakReference<>(mapActivity); + snackbar = Snackbar.make(mapActivity.getLayout(), + MessageFormat.format(getString(R.string.gpx_saved_sucessfully), toSave.getName()), + Snackbar.LENGTH_LONG) + .setAction(R.string.shared_string_rename, new OnClickListener() { + @Override + public void onClick(View view) { + MapActivity mapActivity = mapActivityRef.get(); + if (AndroidUtils.isActivityNotDestroyed(mapActivity)) { + FileUtils.renameFile(mapActivity, toSave, new FileUtils.RenameCallback() { + @Override + public void renamedTo(File file) { + } + }); + } } - } - }); - snackbar.getView().findViewById(com.google.android.material.R.id.snackbar_action) - .setAllCaps(false); - UiUtilities.setupSnackbar(snackbar, nightMode); - snackbar.show(); - dismiss(mapActivity); - } else { - Toast.makeText(mapActivity, - MessageFormat.format(getString(R.string.gpx_saved_sucessfully), toSave.getAbsolutePath()), - Toast.LENGTH_LONG).show(); + }); + snackbar.getView().findViewById(com.google.android.material.R.id.snackbar_action) + .setAllCaps(false); + UiUtilities.setupSnackbar(snackbar, nightMode); + snackbar.show(); + dismiss(mapActivity); + break; + case SHOW_IS_SAVED_FRAGMENT: + SavedTrackBottomSheetDialogFragment.showInstance(mapActivity.getSupportFragmentManager(), + toSave.getName()); + dismiss(mapActivity); + break; + case SHOW_TOAST: + if (!savedGpxFile.showCurrentTrack) { + Toast.makeText(mapActivity, + MessageFormat.format(getString(R.string.gpx_saved_sucessfully), toSave.getAbsolutePath()), + Toast.LENGTH_LONG).show(); + } } } } else { @@ -1708,7 +1735,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route return; } final GpxData gpxData = editingCtx.getGpxData(); - String fileName = getSuggestedFileName(mapActivity.getMyApplication().getAppPath(IndexConstants.GPX_INDEX_DIR)); + String fileName = getSuggestedFileName(); String actionStr = getString(R.string.plan_route); boolean editMode = isInEditMode(); if (editMode) { @@ -1853,6 +1880,14 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route public static boolean showInstance(FragmentManager fragmentManager, LatLon initialPoint) { MeasurementToolFragment fragment = new MeasurementToolFragment(); fragment.setInitialPoint(initialPoint); + fragment.setPlanRouteMode(true); + return showFragment(fragment, fragmentManager); + } + + public static boolean showInstance(FragmentManager fragmentManager, String fileName) { + MeasurementToolFragment fragment = new MeasurementToolFragment(); + fragment.setFileName(fileName); + fragment.setPlanRouteMode(true); return showFragment(fragment, fragmentManager); } diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/SaveAsNewTrackBottomSheetDialogFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/SaveAsNewTrackBottomSheetDialogFragment.java index a3a1741192..5d9273118e 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/SaveAsNewTrackBottomSheetDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/SaveAsNewTrackBottomSheetDialogFragment.java @@ -1,31 +1,51 @@ package net.osmand.plus.measurementtool; -import android.graphics.drawable.Drawable; -import android.os.Build; +import android.content.res.ColorStateList; +import android.graphics.Color; +import android.graphics.drawable.GradientDrawable; import android.os.Bundle; -import android.view.ContextThemeWrapper; -import android.view.MotionEvent; +import android.text.Editable; +import android.text.TextWatcher; import android.view.View; -import android.widget.ImageView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.content.res.AppCompatResources; +import androidx.core.content.ContextCompat; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; + +import com.google.android.material.textfield.TextInputEditText; +import com.google.android.material.textfield.TextInputLayout; import net.osmand.AndroidUtils; +import net.osmand.PlatformUtil; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; +import net.osmand.plus.UiUtilities; import net.osmand.plus.base.MenuBottomSheetDialogFragment; import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem; -import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem; -import net.osmand.plus.base.bottomsheetmenu.simpleitems.ShortDescriptionItem; +import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithCompoundButton; +import net.osmand.plus.base.bottomsheetmenu.HorizontalRecyclerBottomSheetItem; +import net.osmand.plus.base.bottomsheetmenu.simpleitems.DividerSpaceItem; import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem; +import net.osmand.plus.measurementtool.adapter.FolderListAdapter; + +import org.apache.commons.logging.Log; public class SaveAsNewTrackBottomSheetDialogFragment extends MenuBottomSheetDialogFragment { - public final static String TAG = "SaveAsNewTrackBottomSheetDialogFragment"; + public static final String TAG = SaveAsNewTrackBottomSheetDialogFragment.class.getSimpleName(); + private static final Log LOG = PlatformUtil.getLog(SaveAsNewTrackBottomSheetDialogFragment.class); + public static final String SHOW_ON_MAP_KEY = "show_on_map_key"; + public static final String SIMPLIFIED_TRACK_KEY = "simplified_track_key"; + public static final String FOLDER_NAME_KEY = "folder_name_key"; - private SaveAsNewTrackFragmentListener listener; - - public void setListener(SaveAsNewTrackFragmentListener listener) { - this.listener = listener; - } + boolean showOnMap; + boolean simplifiedTrack; + String fileName; + String folderName; + boolean rightButtonEnabled = true; @Override public void createMenuItems(Bundle savedInstanceState) { @@ -33,84 +53,183 @@ public class SaveAsNewTrackBottomSheetDialogFragment extends MenuBottomSheetDial if (app == null) { return; } + if (savedInstanceState != null) { + showOnMap = savedInstanceState.getBoolean(SHOW_ON_MAP_KEY); + simplifiedTrack = savedInstanceState.getBoolean(SIMPLIFIED_TRACK_KEY); + folderName = savedInstanceState.getString(FOLDER_NAME_KEY); + } items.add(new TitleItem(getString(R.string.shared_string_save_as_gpx))); - items.add(new ShortDescriptionItem(getString(R.string.measurement_tool_save_as_new_track_descr))); - - if (Build.VERSION.SDK_INT >= 18) { - final int themeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme; - View imagesRow = View.inflate(new ContextThemeWrapper(getContext(), themeRes), - R.layout.fragment_save_as_new_track_images_row, null); - - final ImageView routePointImage = (ImageView) imagesRow.findViewById(R.id.route_point_image); - final ImageView lineImage = (ImageView) imagesRow.findViewById(R.id.line_image); - Drawable routePointDrawable = app.getUIUtilities().getIcon(nightMode - ? R.drawable.img_help_trip_route_points_night - : R.drawable.img_help_trip_route_points_day); - Drawable lineDrawable = app.getUIUtilities().getIcon(nightMode - ? R.drawable.img_help_trip_track_night - : R.drawable.img_help_trip_track_day); - if (routePointDrawable != null && lineDrawable != null) { - routePointImage.setImageDrawable(AndroidUtils.getDrawableForDirection(app, routePointDrawable)); - lineImage.setImageDrawable(AndroidUtils.getDrawableForDirection(app, lineDrawable)); + View editNameView = View.inflate(UiUtilities.getThemedContext(app, nightMode), + R.layout.track_name_edit_text, null); + final TextInputLayout nameTextBox = editNameView.findViewById(R.id.name_text_box); + nameTextBox.setBoxBackgroundColorResource(R.color.material_text_input_layout_bg); + nameTextBox.setHint(app.getString(R.string.ltr_or_rtl_combine_via_colon, + app.getString(R.string.shared_string_file_name), "").trim()); + ColorStateList colorStateList = ColorStateList.valueOf(ContextCompat + .getColor(app, nightMode ? R.color.text_color_secondary_dark : R.color.text_color_secondary_light)); + nameTextBox.setDefaultHintTextColor(colorStateList); + TextInputEditText nameText = editNameView.findViewById(R.id.name_edit_text); + nameText.setText(fileName); + nameText.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { } - routePointImage.setOnClickListener(saveAsRoutePointOnClickListener); - lineImage.setOnClickListener(saveAsLineOnClickListener); - View.OnTouchListener textOnTouchListener = new View.OnTouchListener() { - @Override - public boolean onTouch(View v, MotionEvent event) { - return false; - } - }; - imagesRow.findViewById(R.id.line_text).setOnTouchListener(textOnTouchListener); - imagesRow.findViewById(R.id.route_point_text).setOnTouchListener(textOnTouchListener); + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } - items.add(new BaseBottomSheetItem.Builder().setCustomView(imagesRow).create()); + @Override + public void afterTextChanged(Editable s) { + checkEmptyName(s, nameTextBox); + } + }); + BaseBottomSheetItem editFileName = new BaseBottomSheetItem.Builder() + .setCustomView(editNameView) + .create(); + this.items.add(editFileName); + + int contentPaddingSmall = app.getResources().getDimensionPixelSize(R.dimen.content_padding_small); + int contentPaddingHalf = app.getResources().getDimensionPixelSize(R.dimen.content_padding_half); + + items.add(new DividerSpaceItem(app, contentPaddingSmall)); + + FolderListAdapter adapter = new FolderListAdapter(app, nightMode, folderName); + if (adapter.getItemCount() > 0) { + adapter.setListener(createFolderSelectListener()); + View view = View.inflate(UiUtilities.getThemedContext(app, nightMode), R.layout.bottom_sheet_item_recyclerview, + null); + View recyclerView = view.findViewById(R.id.recycler_view); + recyclerView.setPadding(contentPaddingHalf, 0, contentPaddingHalf, 0); + BaseBottomSheetItem scrollItem = new HorizontalRecyclerBottomSheetItem.Builder() + .setAdapter(adapter) + .setCustomView(view) + .create(); + this.items.add(scrollItem); + + items.add(new DividerSpaceItem(app, app.getResources().getDimensionPixelSize(R.dimen.dialog_content_margin))); } - - BaseBottomSheetItem saveAsRoutePointsItem = new SimpleBottomSheetItem.Builder() - .setIcon(getContentIcon(R.drawable.ic_action_route_points)) - .setTitle(getString(R.string.save_as_route_point)) - .setLayoutId(R.layout.bottom_sheet_item_simple) - .setOnClickListener(saveAsRoutePointOnClickListener) + int activeColorRes = nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light; + int backgroundColor = AndroidUtils.getColorFromAttr(UiUtilities.getThemedContext(app, nightMode), + R.attr.activity_background_color); + GradientDrawable background = (GradientDrawable) AppCompatResources.getDrawable(app, + R.drawable.bg_select_group_button_outline); + if (background != null) { + background = (GradientDrawable) background.mutate(); + background.setStroke(0, Color.TRANSPARENT); + background.setColor(backgroundColor); + } + final BottomSheetItemWithCompoundButton[] simplifiedTrackItem = new BottomSheetItemWithCompoundButton[1]; + simplifiedTrackItem[0] = (BottomSheetItemWithCompoundButton) new BottomSheetItemWithCompoundButton.Builder() + .setChecked(simplifiedTrack) + .setCompoundButtonColorId(activeColorRes) + .setDescription(getString(R.string.simplified_track_description)) + .setBackground(background) + .setTitle(getString(R.string.simplified_track)) + .setLayoutId(R.layout.bottom_sheet_item_with_switch_and_descr) + .setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + simplifiedTrack = !simplifiedTrack; + simplifiedTrackItem[0].setChecked(simplifiedTrack); + } + }) .create(); - items.add(saveAsRoutePointsItem); + items.add(simplifiedTrackItem[0]); - BaseBottomSheetItem saveAsLineItem = new SimpleBottomSheetItem.Builder() - .setIcon(getContentIcon(R.drawable.ic_action_split_interval)) - .setTitle(getString(R.string.save_as_line)) - .setLayoutId(R.layout.bottom_sheet_item_simple) - .setOnClickListener(saveAsLineOnClickListener) + items.add(new DividerSpaceItem(app, app.getResources().getDimensionPixelSize(R.dimen.content_padding))); + + background = (GradientDrawable) AppCompatResources.getDrawable(app, R.drawable.bg_select_group_button_outline); + if (background != null) { + background = (GradientDrawable) background.mutate(); + background.setStroke(app.getResources().getDimensionPixelSize(R.dimen.map_button_stroke), backgroundColor); + } + final BottomSheetItemWithCompoundButton[] showOnMapItem = new BottomSheetItemWithCompoundButton[1]; + showOnMapItem[0] = (BottomSheetItemWithCompoundButton) new BottomSheetItemWithCompoundButton.Builder() + .setCompoundButtonColorId(activeColorRes) + .setChecked(showOnMap) + .setBackground(background) + .setTitle(getString(R.string.shared_string_show_on_map)) + .setLayoutId(R.layout.bottom_sheet_item_with_switch_and_descr) + .setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + showOnMap = !showOnMap; + showOnMapItem[0].setChecked(showOnMap); + } + }) .create(); - items.add(saveAsLineItem); + items.add(showOnMapItem[0]); + + items.add(new DividerSpaceItem(app, contentPaddingSmall)); } - private View.OnClickListener saveAsLineOnClickListener = new View.OnClickListener() { - @Override - public void onClick(View view) { - if (listener != null) { - listener.saveAsLineOnClick(); + private FolderListAdapter.FolderListAdapterListener createFolderSelectListener() { + return new FolderListAdapter.FolderListAdapterListener() { + @Override + public void onItemSelected(String item) { + folderName = item; } - dismiss(); - } - }; + }; + } - private View.OnClickListener saveAsRoutePointOnClickListener = new View.OnClickListener() { - @Override - public void onClick(View view) { - if (listener != null) { - listener.saveAsRoutePointOnClick(); + @Override + public void onSaveInstanceState(Bundle outState) { + outState.putBoolean(SHOW_ON_MAP_KEY, showOnMap); + outState.putBoolean(SIMPLIFIED_TRACK_KEY, simplifiedTrack); + outState.putString(FOLDER_NAME_KEY, folderName); + super.onSaveInstanceState(outState); + } + + public static void showInstance(@NonNull FragmentManager fm, @Nullable Fragment targetFragment, String fileName) { + try { + if (!fm.isStateSaved()) { + SaveAsNewTrackBottomSheetDialogFragment fragment = new SaveAsNewTrackBottomSheetDialogFragment(); + fragment.setTargetFragment(targetFragment, 0); + fragment.fileName = fileName; + fragment.show(fm, TAG); } - dismiss(); + } catch (RuntimeException e) { + LOG.error("showInstance", e); } - }; + } + + @Override + protected int getRightBottomButtonTextId() { + return R.string.shared_string_save; + } + + @Override + protected void onRightBottomButtonClick() { + Fragment targetFragment = getTargetFragment(); + if (targetFragment instanceof SaveAsNewTrackFragmentListener) { + ((SaveAsNewTrackFragmentListener) targetFragment).onSaveAsNewTrack(folderName, fileName, showOnMap, + simplifiedTrack); + } + dismiss(); + } + + @Override + protected boolean isRightBottomButtonEnabled() { + return rightButtonEnabled; + } + + private void checkEmptyName(Editable name, TextInputLayout nameCaption) { + if (name.toString().trim().isEmpty()) { + nameCaption.setError(getString(R.string.empty_filename)); + rightButtonEnabled = false; + } else { + nameCaption.setError(null); + rightButtonEnabled = true; + } + updateBottomButtons(); + } interface SaveAsNewTrackFragmentListener { - void saveAsRoutePointOnClick(); + void onSaveAsNewTrack(String folderName, String fileName, boolean showOnMap, boolean simplifiedTrack); - void saveAsLineOnClick(); } } diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/SavedTrackBottomSheetDialogFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/SavedTrackBottomSheetDialogFragment.java new file mode 100644 index 0000000000..12f2be4cc8 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/measurementtool/SavedTrackBottomSheetDialogFragment.java @@ -0,0 +1,104 @@ +package net.osmand.plus.measurementtool; + +import android.app.Activity; +import android.os.Bundle; +import android.view.View; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.fragment.app.FragmentManager; + +import net.osmand.plus.R; +import net.osmand.plus.UiUtilities; +import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.base.MenuBottomSheetDialogFragment; +import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemButton; +import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem; +import net.osmand.plus.base.bottomsheetmenu.simpleitems.DividerItem; +import net.osmand.plus.base.bottomsheetmenu.simpleitems.DividerSpaceItem; + +public class SavedTrackBottomSheetDialogFragment extends MenuBottomSheetDialogFragment { + + public static final String TAG = SavedTrackBottomSheetDialogFragment.class.getSimpleName(); + public static final String FILE_NAME_KEY = "file_name_key"; + + String fileName; + + @Override + public void createMenuItems(Bundle savedInstanceState) { + + if (savedInstanceState != null) { + fileName = savedInstanceState.getString(FILE_NAME_KEY); + } + + View mainView = View.inflate(UiUtilities.getThemedContext(getMyApplication(), nightMode), + R.layout.measure_track_is_saved, null); + TextView fileNameView = mainView.findViewById(R.id.file_name); + fileNameView.setText(fileName); + items.add(new SimpleBottomSheetItem.Builder() + .setCustomView(mainView) + .create()); + + DividerItem divider = new DividerItem(getContext()); + int contextPadding = getResources().getDimensionPixelSize(R.dimen.content_padding); + int contextPaddingSmall = getResources().getDimensionPixelSize(R.dimen.content_padding_small); + divider.setMargins(contextPadding, contextPadding, contextPadding, contextPaddingSmall); + items.add(divider); + + items.add(new BottomSheetItemButton.Builder() + .setTitle(getString(R.string.open_saved_track)) + .setLayoutId(R.layout.bottom_sheet_button) + .setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Activity activity = getActivity(); + if (activity instanceof MapActivity) { + MeasurementToolFragment.showInstance(((MapActivity) activity).getSupportFragmentManager(), + fileName); + } + dismiss(); + } + }) + .create()); + + items.add(new DividerSpaceItem(getContext(), contextPaddingSmall)); + + items.add(new BottomSheetItemButton.Builder() + .setButtonType(UiUtilities.DialogButtonType.SECONDARY) + .setTitle(getString(R.string.plan_route_create_new_route)) + .setLayoutId(R.layout.bottom_sheet_button) + .setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Activity activity = getActivity(); + if (activity instanceof MapActivity) { + MeasurementToolFragment.showInstance(((MapActivity) activity).getSupportFragmentManager(), + ((MapActivity) activity).getMapLocation()); + } + dismiss(); + } + }) + .create()); + + items.add(new DividerSpaceItem(getContext(), contextPaddingSmall)); + } + + @Override + protected int getDismissButtonTextId() { + return R.string.shared_string_exit; + } + + @Override + public void onSaveInstanceState(Bundle outState) { + outState.putString(FILE_NAME_KEY, fileName); + super.onSaveInstanceState(outState); + } + + public static void showInstance(@NonNull FragmentManager fragmentManager, String fileName) { + if (!fragmentManager.isStateSaved()) { + SavedTrackBottomSheetDialogFragment fragment = new SavedTrackBottomSheetDialogFragment(); + fragment.fileName = fileName; + fragment.show(fragmentManager, TAG); + } + } +} diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/SelectFileBottomSheet.java b/OsmAnd/src/net/osmand/plus/measurementtool/SelectFileBottomSheet.java index 60565b7839..d9619de9d1 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/SelectFileBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/SelectFileBottomSheet.java @@ -25,12 +25,12 @@ import net.osmand.plus.mapcontextmenu.other.HorizontalSelectionAdapter.Horizonta 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; +import static net.osmand.util.Algorithms.collectDirs; public class SelectFileBottomSheet extends MenuBottomSheetDialogFragment { @@ -63,6 +63,7 @@ public class SelectFileBottomSheet extends MenuBottomSheetDialogFragment { private SelectFileListener listener; private Map> gpxInfoMap; private Mode fragmentMode; + private String selectedFolder; public void setFragmentMode(Mode fragmentMode) { this.fragmentMode = fragmentMode; @@ -90,13 +91,19 @@ public class SelectFileBottomSheet extends MenuBottomSheetDialogFragment { final File gpxDir = app.getAppPath(IndexConstants.GPX_INDEX_DIR); collectDirs(gpxDir, dirs); List dirItems = new ArrayList<>(); + String allFilesFolder = context.getString(R.string.shared_string_all); + if (savedInstanceState == null) { + selectedFolder = allFilesFolder; + } + dirItems.add(allFilesFolder); 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); + if (isShowCurrentGpx()) { + allGpxList.add(0, new GPXInfo(getString(R.string.shared_string_currently_recording_track), 0, 0)); + } gpxInfoMap = new HashMap<>(); gpxInfoMap.put(allFilesFolder, allGpxList); for (GPXInfo gpxInfo : allGpxList) { @@ -108,12 +115,18 @@ public class SelectFileBottomSheet extends MenuBottomSheetDialogFragment { } gpxList.add(gpxInfo); } - adapter = new GpxTrackAdapter(requireContext(), allGpxList, false); + + adapter = new GpxTrackAdapter(requireContext(), allGpxList, isShowCurrentGpx()); adapter.setAdapterListener(new OnItemClickListener() { @Override public void onItemClick(int position) { if (position != RecyclerView.NO_POSITION && position < allGpxList.size()) { - String fileName = allGpxList.get(position).getFileName(); + String fileName; + if (isShowCurrentGpx() && position == 0) { + fileName = null; + } else { + fileName = allGpxList.get(position).getFileName(); + } if (listener != null) { listener.selectFileOnCLick(fileName); } @@ -128,18 +141,28 @@ public class SelectFileBottomSheet extends MenuBottomSheetDialogFragment { RecyclerView.HORIZONTAL, false)); final HorizontalSelectionAdapter folderAdapter = new HorizontalSelectionAdapter(app, nightMode); folderAdapter.setItems(dirItems); - folderAdapter.setSelectedItem(allFilesFolder); + folderAdapter.setSelectedItem(selectedFolder); 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(); + selectedFolder = item; + updateFileList(item, folderAdapter); } }); items.add(new BaseBottomSheetItem.Builder().setCustomView(mainView).create()); + updateFileList(selectedFolder, folderAdapter); + } + + private void updateFileList(String folderName, HorizontalSelectionAdapter folderAdapter) { + List gpxInfoList = gpxInfoMap.get(folderName); + adapter.setGpxInfoList(gpxInfoList != null ? gpxInfoList : new ArrayList()); + adapter.notifyDataSetChanged(); + folderAdapter.notifyDataSetChanged(); + } + + private boolean isShowCurrentGpx() { + return fragmentMode == Mode.ADD_TO_TRACK; } private String getFolderName(GPXInfo gpxInfo) { @@ -149,19 +172,6 @@ public class SelectFileBottomSheet extends MenuBottomSheetDialogFragment { : 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); @@ -170,7 +180,6 @@ public class SelectFileBottomSheet extends MenuBottomSheetDialogFragment { public static void showInstance(FragmentManager fragmentManager, SelectFileListener listener, Mode mode) { if (!fragmentManager.isStateSaved()) { SelectFileBottomSheet fragment = new SelectFileBottomSheet(); - fragment.setUsedOnMap(true); fragment.setRetainInstance(true); fragment.setListener(listener); fragment.setFragmentMode(mode); diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/adapter/FolderListAdapter.java b/OsmAnd/src/net/osmand/plus/measurementtool/adapter/FolderListAdapter.java new file mode 100644 index 0000000000..b207d7aac5 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/measurementtool/adapter/FolderListAdapter.java @@ -0,0 +1,150 @@ +package net.osmand.plus.measurementtool.adapter; + +import android.graphics.drawable.GradientDrawable; +import android.os.Build; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.appcompat.content.res.AppCompatResources; +import androidx.core.content.ContextCompat; +import androidx.recyclerview.widget.RecyclerView; + +import net.osmand.AndroidUtils; +import net.osmand.IndexConstants; +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.R; +import net.osmand.util.Algorithms; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class FolderListAdapter extends RecyclerView.Adapter { + + List items = new ArrayList<>(); + + String selectedItemName; + OsmandApplication app; + boolean nightMode; + FolderListAdapterListener listener; + + public FolderListAdapter(OsmandApplication app, boolean nightMode, String folderName) { + this.app = app; + this.nightMode = nightMode; + selectedItemName = folderName; + fillGroups(); + } + + private void fillGroups() { + items.clear(); + items.addAll(getFolders()); + } + + private Collection getFolders() { + List dirs = new ArrayList<>(); + final File gpxDir = app.getAppPath(IndexConstants.GPX_INDEX_DIR); + Algorithms.collectDirs(gpxDir, dirs); + List dirItems = new ArrayList<>(); + for (File dir : dirs) { + dirItems.add(dir.getName()); + } + return dirItems; + } + + @NonNull + @Override + public GroupsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + int activeColorRes = nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light; + View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.point_editor_group_select_item, + parent, false); + ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) view.getLayoutParams(); + params.width = app.getResources().getDimensionPixelSize(R.dimen.measurement_tool_folder_select_width); + params.height = app.getResources().getDimensionPixelSize(R.dimen.measurement_tool_folder_select_height); + TextView groupName = view.findViewById(R.id.groupName); + groupName.setMaxLines(1); + groupName.setEllipsize(TextUtils.TruncateAt.END); + groupName.setTextColor(ContextCompat.getColor(app, activeColorRes)); + return new FolderListAdapter.GroupsViewHolder(view); + } + + @Override + public void onBindViewHolder(@NonNull final GroupsViewHolder holder, int position) { + + holder.groupButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + int previousSelectedPosition = getItemPosition(selectedItemName); + selectedItemName = items.get(holder.getAdapterPosition()); + notifyItemChanged(holder.getAdapterPosition()); + notifyItemChanged(previousSelectedPosition); + if (listener != null) { + listener.onItemSelected(selectedItemName); + } + } + }); + final String group = Algorithms.capitalizeFirstLetter(items.get(position)); + holder.groupName.setText(group); + int activeColorRes = nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light; + int strokeColor; + int strokeWidth; + if (selectedItemName != null && selectedItemName.equals(items.get(position))) { + strokeColor = activeColorRes; + strokeWidth = 2; + } else { + strokeColor = nightMode ? R.color.stroked_buttons_and_links_outline_dark + : R.color.stroked_buttons_and_links_outline_light; + strokeWidth = 1; + } + GradientDrawable rectContourDrawable = (GradientDrawable) AppCompatResources.getDrawable(app, + R.drawable.bg_select_group_button_outline); + if (rectContourDrawable != null) { + rectContourDrawable.setStroke(AndroidUtils.dpToPx(app, strokeWidth), ContextCompat.getColor(app, strokeColor)); + holder.groupButton.setImageDrawable(rectContourDrawable); + } + int iconID; + iconID = R.drawable.ic_action_folder; + holder.groupIcon.setImageDrawable(app.getUIUtilities().getIcon(iconID, activeColorRes)); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + AndroidUtils.setBackground(app, holder.groupButton, nightMode, R.drawable.ripple_solid_light_6dp, + R.drawable.ripple_solid_dark_6dp); + } + } + + @Override + public int getItemCount() { + return items == null ? 0 : items.size(); + } + + int getItemPosition(String name) { + return items.indexOf(name); + } + + public void setListener(FolderListAdapterListener listener) { + this.listener = listener; + } + + static class GroupsViewHolder extends RecyclerView.ViewHolder { + + final TextView groupName; + final ImageView groupIcon; + final ImageView groupButton; + + GroupsViewHolder(View itemView) { + super(itemView); + groupName = itemView.findViewById(R.id.groupName); + groupIcon = itemView.findViewById(R.id.groupIcon); + groupButton = itemView.findViewById(R.id.outlineRect); + } + } + + public interface FolderListAdapterListener { + + void onItemSelected(String item); + } +} diff --git a/OsmAnd/src/net/osmand/plus/myplaces/AvailableGPXFragment.java b/OsmAnd/src/net/osmand/plus/myplaces/AvailableGPXFragment.java index 761996059e..6e862b5d4b 100644 --- a/OsmAnd/src/net/osmand/plus/myplaces/AvailableGPXFragment.java +++ b/OsmAnd/src/net/osmand/plus/myplaces/AvailableGPXFragment.java @@ -81,7 +81,6 @@ import net.osmand.plus.mapmarkers.CoordinateInputDialogFragment; import net.osmand.plus.monitoring.OsmandMonitoringPlugin; import net.osmand.plus.osmedit.OsmEditingPlugin; import net.osmand.plus.settings.backend.OsmandSettings; -import net.osmand.util.Algorithms; import java.io.File; import java.text.Collator; @@ -103,6 +102,7 @@ import java.util.regex.Pattern; import static net.osmand.plus.GpxSelectionHelper.CURRENT_TRACK; import static net.osmand.plus.myplaces.FavoritesActivity.GPX_TAB; import static net.osmand.plus.myplaces.FavoritesActivity.TAB_ID; +import static net.osmand.util.Algorithms.*; public class AvailableGPXFragment extends OsmandExpandableListFragment implements FavoritesFragmentStateHolder { @@ -742,20 +742,6 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment implement } } - private void collectDirs(File dir, List dirs, File exclDir) { - File[] listFiles = dir.listFiles(); - if (listFiles != null) { - for (File f : listFiles) { - if (f.isDirectory()) { - if (!exclDir.equals(f)) { - dirs.add(f); - } - collectDirs(f, dirs, exclDir); - } - } - } - } - private void moveGpx(final GpxInfo info) { final ContextMenuAdapter menuAdapter = new ContextMenuAdapter(app); @@ -777,7 +763,7 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment implement dirName = dirName.substring(gpxDir.length() + 1); } } - menuAdapter.addItem(itemBuilder.setTitle(Algorithms.capitalizeFirstLetter(dirName)) + menuAdapter.addItem(itemBuilder.setTitle(capitalizeFirstLetter(dirName)) .setIcon(R.drawable.ic_action_folder_stroke).setTag(i).createItem()); i++; } @@ -1111,7 +1097,7 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment implement // search from end for (int i = category.size() - 1; i >= 0; i--) { String cat = category.get(i); - if (Algorithms.objectEquals(catName, cat)) { + if (objectEquals(catName, cat)) { found = i; break; } @@ -1249,14 +1235,14 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment implement if (groupName.length() == 0) { groupName = getString(R.string.shared_string_tracks); } - t.append(Algorithms.capitalizeFirstLetter(groupName)); + t.append(capitalizeFirstLetter(groupName)); boolean light = app.getSettings().isLightContent(); if (selectionMode) { final CheckBox ch = (CheckBox) v.findViewById(R.id.toggle_item); // Issue 6187: No selection box for Visible group header //ch.setVisibility(View.VISIBLE); - ch.setVisibility((selectionMode && !(groupPosition == 0 && isShowingSelection()))? View.VISIBLE : View.GONE); + ch.setVisibility((selectionMode && !(groupPosition == 0 && isShowingSelection())) ? View.VISIBLE : View.GONE); ch.setChecked(selectedGroups.contains(groupPosition)); ch.setOnClickListener(new View.OnClickListener() { @@ -1361,7 +1347,7 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment implement // local_indexes_cat_gpx now obsolete in new UI screen which shows only GPX data // if (Algorithms.objectEquals(getActivity().getString(R.string.local_indexes_cat_gpx) + " " + // g.subfolder, cat)) { - if (Algorithms.objectEquals("" + g.subfolder, cat)) { + if (objectEquals("" + g.subfolder, cat)) { found = i; break; } @@ -1586,7 +1572,7 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment implement for (GpxInfo info : params) { if (!isCancelled() && (info.gpx == null || !info.gpx.showCurrentTrack)) { boolean successfull; - successfull = Algorithms.removeAllFiles(info.file); + successfull = removeAllFiles(info.file); app.getGpxDbHelper().remove(info.file); total++; if (successfull) { @@ -1849,7 +1835,7 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment implement // if (analysis.isTimeMoving()) { // time.setText(Algorithms.formatDuration((int) (analysis.timeMoving / 1000)) + ""); // } else { - time.setText(Algorithms.formatDuration((int) (analysis.timeSpan / 1000), app.accessibilityEnabled()) + ""); + time.setText(formatDuration((int) (analysis.timeSpan / 1000), app.accessibilityEnabled()) + ""); // } } else { time.setText("");