diff --git a/OsmAnd/res/layout/bottom_sheet_item_with_switch_pad_32.xml b/OsmAnd/res/layout/bottom_sheet_item_with_switch_pad_32.xml new file mode 100644 index 0000000000..4658df14df --- /dev/null +++ b/OsmAnd/res/layout/bottom_sheet_item_with_switch_pad_32.xml @@ -0,0 +1,45 @@ + + + + + + + + + + diff --git a/OsmAnd/res/layout/track_segments_container.xml b/OsmAnd/res/layout/card_container.xml similarity index 100% rename from OsmAnd/res/layout/track_segments_container.xml rename to OsmAnd/res/layout/card_container.xml diff --git a/OsmAnd/res/layout/track_menu.xml b/OsmAnd/res/layout/track_menu.xml index 598372776f..9d33f73e88 100644 --- a/OsmAnd/res/layout/track_menu.xml +++ b/OsmAnd/res/layout/track_menu.xml @@ -54,11 +54,15 @@ android:layout_weight="1" android:orientation="vertical"> - - - - - + \ No newline at end of file diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index e390145312..80ed944fcf 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -12,6 +12,11 @@ --> + Change folder + Rename track + Edit track + Upload to OpenStreetMap + Analyze by intervals (split interval) Empty Select folder or add new one Select folder diff --git a/OsmAnd/src/net/osmand/FileUtils.java b/OsmAnd/src/net/osmand/FileUtils.java index fed5346212..580450df60 100644 --- a/OsmAnd/src/net/osmand/FileUtils.java +++ b/OsmAnd/src/net/osmand/FileUtils.java @@ -8,8 +8,6 @@ import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentManager; -import net.osmand.GPXUtilities.GPXFile; -import net.osmand.GPXUtilities.Metadata; import net.osmand.plus.GpxSelectionHelper; import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile; import net.osmand.plus.OsmandApplication; @@ -107,6 +105,7 @@ public class FileUtils { SelectedGpxFile selected = helper.getSelectedFileByPath(src.getAbsolutePath()); app.getGpxDbHelper().rename(src, dest); if (selected != null && selected.getGpxFile() != null) { + selected.resetSplitProcessed(); selected.getGpxFile().path = dest.getAbsolutePath(); helper.updateSelectedGpxFile(selected); } diff --git a/OsmAnd/src/net/osmand/plus/GPXDatabase.java b/OsmAnd/src/net/osmand/plus/GPXDatabase.java index c010b2964e..74dc02be9c 100644 --- a/OsmAnd/src/net/osmand/plus/GPXDatabase.java +++ b/OsmAnd/src/net/osmand/plus/GPXDatabase.java @@ -465,7 +465,7 @@ public class GPXDatabase { return false; } - public boolean rename(File currentFile, File newFile) { + public boolean rename(@Nullable GpxDataItem item, File currentFile, File newFile) { SQLiteConnection db = openConnection(false); if (db != null){ try { @@ -478,6 +478,9 @@ public class GPXDatabase { GPX_COL_DIR + " = ? " + " WHERE " + GPX_COL_NAME + " = ? AND " + GPX_COL_DIR + " = ?", new Object[] { newFileName, newFileDir, fileName, fileDir }); + if (item != null) { + item.file = newFile; + } } finally { db.close(); } diff --git a/OsmAnd/src/net/osmand/plus/GpxDbHelper.java b/OsmAnd/src/net/osmand/plus/GpxDbHelper.java index d5e05e8db3..c27c74f636 100644 --- a/OsmAnd/src/net/osmand/plus/GpxDbHelper.java +++ b/OsmAnd/src/net/osmand/plus/GpxDbHelper.java @@ -68,9 +68,8 @@ public class GpxDbHelper { } public boolean rename(File currentFile, File newFile) { - boolean res = db.rename(currentFile, newFile); - itemsCache.remove(currentFile); - return res; + GpxDataItem item = itemsCache.get(currentFile); + return db.rename(item, currentFile, newFile); } public boolean updateColor(GpxDataItem item, int color) { diff --git a/OsmAnd/src/net/osmand/plus/GpxSelectionHelper.java b/OsmAnd/src/net/osmand/plus/GpxSelectionHelper.java index cb1ad6b79d..879dad90d1 100644 --- a/OsmAnd/src/net/osmand/plus/GpxSelectionHelper.java +++ b/OsmAnd/src/net/osmand/plus/GpxSelectionHelper.java @@ -861,6 +861,10 @@ public class GpxSelectionHelper { return color; } + public void resetSplitProcessed() { + splitProcessed = false; + } + public List getDisplayGroups(OsmandApplication app) { if (modifiedTime != gpxFile.modifiedTime || !splitProcessed) { update(app); diff --git a/OsmAnd/src/net/osmand/plus/activities/MapActivity.java b/OsmAnd/src/net/osmand/plus/activities/MapActivity.java index e41792225b..4e3cbd2885 100644 --- a/OsmAnd/src/net/osmand/plus/activities/MapActivity.java +++ b/OsmAnd/src/net/osmand/plus/activities/MapActivity.java @@ -67,8 +67,7 @@ import net.osmand.plus.AppInitializer; import net.osmand.plus.AppInitializer.AppInitializeListener; import net.osmand.plus.AppInitializer.InitEvents; import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem; -import net.osmand.plus.mapmarkers.MapMarker; -import net.osmand.plus.mapmarkers.MapMarkersHelper.MapMarkerChangedListener; +import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile; import net.osmand.plus.OnDismissDialogFragmentListener; import net.osmand.plus.OsmAndConstants; import net.osmand.plus.OsmAndLocationSimulation; @@ -80,7 +79,6 @@ import net.osmand.plus.TargetPointsHelper.TargetPoint; import net.osmand.plus.Version; import net.osmand.plus.activities.search.SearchActivity; import net.osmand.plus.base.BaseOsmAndFragment; -import net.osmand.plus.base.ContextMenuFragment; import net.osmand.plus.base.FailSafeFuntions; import net.osmand.plus.base.MapViewTrackingUtilities; import net.osmand.plus.chooseplan.OsmLiveGoneDialog; @@ -108,10 +106,11 @@ import net.osmand.plus.helpers.ScrollHelper.OnScrollEventListener; import net.osmand.plus.importfiles.ImportHelper; import net.osmand.plus.mapcontextmenu.AdditionalActionsBottomSheetDialogFragment; import net.osmand.plus.mapcontextmenu.MapContextMenu; -import net.osmand.plus.mapcontextmenu.MenuController; import net.osmand.plus.mapcontextmenu.builders.cards.dialogs.ContextMenuCardDialogFragment; import net.osmand.plus.mapcontextmenu.other.DestinationReachedMenu; import net.osmand.plus.mapcontextmenu.other.TrackDetailsMenu; +import net.osmand.plus.mapmarkers.MapMarker; +import net.osmand.plus.mapmarkers.MapMarkersHelper.MapMarkerChangedListener; import net.osmand.plus.mapmarkers.PlanRouteFragment; import net.osmand.plus.measurementtool.GpxApproximationFragment; import net.osmand.plus.measurementtool.GpxData; @@ -125,8 +124,8 @@ import net.osmand.plus.routepreparationmenu.ChooseRouteFragment; import net.osmand.plus.routepreparationmenu.MapRouteInfoMenu; import net.osmand.plus.routepreparationmenu.MapRouteInfoMenuFragment; import net.osmand.plus.routing.IRouteInformationListener; -import net.osmand.plus.routing.RoutingHelper; import net.osmand.plus.routing.RouteCalculationProgressCallback; +import net.osmand.plus.routing.RoutingHelper; import net.osmand.plus.routing.TransportRoutingHelper.TransportRouteCalculationProgressCallback; import net.osmand.plus.search.QuickSearchDialogFragment; import net.osmand.plus.search.QuickSearchDialogFragment.QuickSearchTab; @@ -169,8 +168,6 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import static net.osmand.aidlapi.OsmAndCustomizationConstants.DRAWER_SETTINGS_ID; -import static net.osmand.plus.activities.TrackActivity.CURRENT_RECORDING; -import static net.osmand.plus.activities.TrackActivity.TRACK_FILE_NAME; public class MapActivity extends OsmandActionBarActivity implements DownloadEvents, OnRequestPermissionsResultCallback, IRouteInformationListener, AMapPointUpdateListener, @@ -1177,15 +1174,15 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven MapRouteInfoMenu.showLocationOnMap(this, latLonToShow.getLatitude(), latLonToShow.getLongitude()); } else if (toShow instanceof GPXFile) { hideContextAndRouteInfoMenues(); + GPXFile gpxFile = (GPXFile) toShow; + SelectedGpxFile selectedGpxFile; + if (gpxFile.showCurrentTrack) { + selectedGpxFile = app.getSavingTrackHelper().getCurrentTrack(); + } else { + selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(gpxFile.path); + } - Bundle args = new Bundle(); - args.putString(TRACK_FILE_NAME, ((GPXFile) toShow).path); - args.putBoolean(CURRENT_RECORDING, ((GPXFile) toShow).showCurrentTrack); - args.putInt(ContextMenuFragment.MENU_STATE_KEY, MenuController.MenuState.HALF_SCREEN); - - TrackAppearanceFragment fragment = new TrackAppearanceFragment(); - fragment.setArguments(args); - TrackAppearanceFragment.showInstance(this, fragment); + TrackAppearanceFragment.showInstance(this, selectedGpxFile); } else if (toShow instanceof QuadRect) { QuadRect qr = (QuadRect) toShow; mapView.fitRectToMap(qr.left, qr.right, qr.top, qr.bottom, (int) qr.width(), (int) qr.height(), 0); diff --git a/OsmAnd/src/net/osmand/plus/helpers/GpxUiHelper.java b/OsmAnd/src/net/osmand/plus/helpers/GpxUiHelper.java index c2813551e9..3d6c3c15c9 100644 --- a/OsmAnd/src/net/osmand/plus/helpers/GpxUiHelper.java +++ b/OsmAnd/src/net/osmand/plus/helpers/GpxUiHelper.java @@ -99,6 +99,7 @@ import net.osmand.plus.dialogs.GpxAppearanceAdapter.AppearanceListItem; import net.osmand.plus.helpers.enums.MetricsConstants; import net.osmand.plus.helpers.enums.SpeedConstants; import net.osmand.plus.monitoring.OsmandMonitoringPlugin; +import net.osmand.plus.myplaces.SaveCurrentTrackTask; import net.osmand.plus.routing.RouteCalculationResult; import net.osmand.plus.settings.backend.CommonPreference; import net.osmand.plus.settings.backend.OsmandSettings; @@ -2192,6 +2193,23 @@ public class GpxUiHelper { new SaveGpxAsyncTask(file, gpxFile, listener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } + public static void saveAndShareCurrentGpx(@NonNull final OsmandApplication app, @NonNull final GPXFile gpxFile) { + SaveGpxListener saveGpxListener = new SaveGpxListener() { + @Override + public void gpxSavingStarted() { + + } + + @Override + public void gpxSavingFinished(Exception errorMessage) { + if (errorMessage == null) { + GpxUiHelper.shareGpx(app, new File(gpxFile.path)); + } + } + }; + new SaveCurrentTrackTask(app, gpxFile, saveGpxListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + public static void saveAndShareGpxWithAppearance(@NonNull final Context context, @NonNull final GPXFile gpxFile) { OsmandApplication app = (OsmandApplication) context.getApplicationContext(); GpxDataItem dataItem = getDataItem(app, gpxFile); diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/SelectedGpxMenuController.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/SelectedGpxMenuController.java index af83eff49a..8a86fbe134 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/SelectedGpxMenuController.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/SelectedGpxMenuController.java @@ -23,9 +23,7 @@ import net.osmand.plus.activities.TrackActivity; import net.osmand.plus.helpers.GpxUiHelper; import net.osmand.plus.mapcontextmenu.MenuController; import net.osmand.plus.mapcontextmenu.builders.SelectedGpxMenuBuilder; -import net.osmand.plus.myplaces.SaveCurrentTrackTask; import net.osmand.plus.settings.backend.OsmandSettings; -import net.osmand.plus.track.SaveGpxAsyncTask.SaveGpxListener; import net.osmand.plus.track.TrackMenuFragment; import net.osmand.util.Algorithms; @@ -77,7 +75,7 @@ public class SelectedGpxMenuController extends MenuController { rightTitleButtonController.startIconId = R.drawable.ic_action_analyze_intervals; } - private static class OpenGpxDetailsTask extends AsyncTask { + public static class OpenGpxDetailsTask extends AsyncTask { private OsmandApplication app; @@ -87,7 +85,7 @@ public class SelectedGpxMenuController extends MenuController { private ProgressDialog progressDialog; private WeakReference activityRef; - OpenGpxDetailsTask(SelectedGpxFile selectedGpxFile, WptPt selectedPoint, MapActivity mapActivity) { + public OpenGpxDetailsTask(SelectedGpxFile selectedGpxFile, WptPt selectedPoint, MapActivity mapActivity) { app = mapActivity.getMyApplication(); this.activityRef = new WeakReference<>(mapActivity); this.selectedGpxFile = selectedGpxFile; @@ -217,7 +215,7 @@ public class SelectedGpxMenuController extends MenuController { if (gpxFile != null) { OsmandApplication app = mapActivity.getMyApplication(); if (Algorithms.isEmpty(gpxFile.path)) { - saveAndShareCurrentGpx(app, gpxFile); + GpxUiHelper.saveAndShareCurrentGpx(app, gpxFile); } else { GpxUiHelper.saveAndShareGpxWithAppearance(app, gpxFile); } @@ -227,23 +225,6 @@ public class SelectedGpxMenuController extends MenuController { } } - public void saveAndShareCurrentGpx(@NonNull final OsmandApplication app, @NonNull final GPXFile gpxFile) { - SaveGpxListener saveGpxListener = new SaveGpxListener() { - @Override - public void gpxSavingStarted() { - - } - - @Override - public void gpxSavingFinished(Exception errorMessage) { - if (errorMessage == null) { - GpxUiHelper.shareGpx(app, new File(gpxFile.path)); - } - } - }; - new SaveCurrentTrackTask(app, gpxFile, saveGpxListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); - } - public static class SelectedGpxPoint { private final WptPt selectedPoint; diff --git a/OsmAnd/src/net/osmand/plus/myplaces/GPXItemPagerAdapter.java b/OsmAnd/src/net/osmand/plus/myplaces/GPXItemPagerAdapter.java index 465f85b617..81d9ee9d72 100644 --- a/OsmAnd/src/net/osmand/plus/myplaces/GPXItemPagerAdapter.java +++ b/OsmAnd/src/net/osmand/plus/myplaces/GPXItemPagerAdapter.java @@ -254,6 +254,7 @@ public class GPXItemPagerAdapter extends PagerAdapter implements CustomTabProvid @Override public void onClick(View v) { if (displayHelper.setJoinSegments(!displayHelper.isJoinSegments())) { + actionsListener.updateContent(); for (int i = 0; i < getCount(); i++) { View view = getViewAtPosition(i); updateJoinGapsInfo(view, i); @@ -337,6 +338,7 @@ public class GPXItemPagerAdapter extends PagerAdapter implements CustomTabProvid @Override public void onClick(View v) { if (displayHelper.setJoinSegments(!displayHelper.isJoinSegments())) { + actionsListener.updateContent(); for (int i = 0; i < getCount(); i++) { View view = getViewAtPosition(i); updateJoinGapsInfo(view, i); @@ -461,7 +463,7 @@ public class GPXItemPagerAdapter extends PagerAdapter implements CustomTabProvid if (!chartClicked) { chartClicked = true; if (selectedWpt != null) { - actionsListener.onPointSelected(selectedWpt.lat, selectedWpt.lon); + actionsListener.onPointSelected(segment, selectedWpt.lat, selectedWpt.lon); } } } @@ -496,7 +498,7 @@ public class GPXItemPagerAdapter extends PagerAdapter implements CustomTabProvid WptPt wpt = getPoint(chart, h.getX()); selectedWpt = wpt; if (chartClicked && wpt != null) { - actionsListener.onPointSelected(wpt.lat, wpt.lon); + actionsListener.onPointSelected(segment, wpt.lat, wpt.lon); } } @@ -565,7 +567,7 @@ public class GPXItemPagerAdapter extends PagerAdapter implements CustomTabProvid chart.highlightValue(h); WptPt wpt = getPoint(chart, h.getX()); if (wpt != null) { - actionsListener.onPointSelected(wpt.lat, wpt.lon); + actionsListener.onPointSelected(segment, wpt.lat, wpt.lon); } } } diff --git a/OsmAnd/src/net/osmand/plus/myplaces/SegmentActionsListener.java b/OsmAnd/src/net/osmand/plus/myplaces/SegmentActionsListener.java index d5ebc2235f..4033dedd7a 100644 --- a/OsmAnd/src/net/osmand/plus/myplaces/SegmentActionsListener.java +++ b/OsmAnd/src/net/osmand/plus/myplaces/SegmentActionsListener.java @@ -17,7 +17,7 @@ public interface SegmentActionsListener { void scrollBy(int px); - void onPointSelected(double lat, double lon); + void onPointSelected(TrkSegment segment, double lat, double lon); void openSplitInterval(GpxDisplayItem gpxItem, TrkSegment trkSegment); diff --git a/OsmAnd/src/net/osmand/plus/myplaces/TrackSegmentFragment.java b/OsmAnd/src/net/osmand/plus/myplaces/TrackSegmentFragment.java index 4a66e09d99..c10fa883ad 100644 --- a/OsmAnd/src/net/osmand/plus/myplaces/TrackSegmentFragment.java +++ b/OsmAnd/src/net/osmand/plus/myplaces/TrackSegmentFragment.java @@ -284,7 +284,7 @@ public class TrackSegmentFragment extends OsmAndListFragment implements TrackBit } @Override - public void onPointSelected(double lat, double lon) { + public void onPointSelected(TrkSegment segment, double lat, double lon) { if (fragmentAdapter != null) { fragmentAdapter.updateSelectedPoint(lat, lon); } diff --git a/OsmAnd/src/net/osmand/plus/osmedit/OsmEditingPlugin.java b/OsmAnd/src/net/osmand/plus/osmedit/OsmEditingPlugin.java index a9a3262216..f734b1c718 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/OsmEditingPlugin.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/OsmEditingPlugin.java @@ -456,7 +456,7 @@ public class OsmEditingPlugin extends OsmandPlugin { } } - public boolean sendGPXFiles(final FragmentActivity activity, AvailableGPXFragment fragment, final GpxInfo... info) { + public boolean sendGPXFiles(final FragmentActivity activity, Fragment fragment, final GpxInfo... info) { String name = settings.USER_NAME.get(); String pwd = settings.USER_PASSWORD.get(); String authToken = settings.USER_ACCESS_TOKEN.get(); diff --git a/OsmAnd/src/net/osmand/plus/track/OptionsCard.java b/OsmAnd/src/net/osmand/plus/track/OptionsCard.java new file mode 100644 index 0000000000..1ed533922c --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/track/OptionsCard.java @@ -0,0 +1,355 @@ +package net.osmand.plus.track; + +import android.graphics.Typeface; +import android.graphics.drawable.Drawable; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; + +import net.osmand.AndroidUtils; +import net.osmand.GPXUtilities.GPXFile; +import net.osmand.plus.OsmandPlugin; +import net.osmand.plus.R; +import net.osmand.plus.UiUtilities; +import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem; +import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithCompoundButton; +import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithDescriptionDifHeight; +import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem; +import net.osmand.plus.base.bottomsheetmenu.simpleitems.DividerItem; +import net.osmand.plus.base.bottomsheetmenu.simpleitems.DividerSpaceItem; +import net.osmand.plus.helpers.FontCache; +import net.osmand.plus.osmedit.OsmEditingPlugin; +import net.osmand.plus.routepreparationmenu.cards.BaseCard; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import static net.osmand.plus.myplaces.TrackActivityFragmentAdapter.isGpxFileSelected; +import static net.osmand.util.Algorithms.capitalizeFirstLetter; + +public class OptionsCard extends BaseCard { + + public static final int SHOW_ON_MAP_BUTTON_INDEX = 0; + public static final int APPEARANCE_BUTTON_INDEX = 1; + public static final int DIRECTIONS_BUTTON_INDEX = 2; + public static final int JOIN_GAPS_BUTTON_INDEX = 3; + public static final int ANALYZE_ON_MAP_BUTTON_INDEX = 4; + public static final int ANALYZE_BY_INTERVALS_BUTTON_INDEX = 5; + public static final int SHARE_BUTTON_INDEX = 6; + public static final int UPLOAD_OSM_BUTTON_INDEX = 7; + public static final int EDIT_BUTTON_INDEX = 8; + public static final int RENAME_BUTTON_INDEX = 9; + public static final int CHANGE_FOLDER_BUTTON_INDEX = 10; + public static final int DELETE_BUTTON_INDEX = 11; + + private TrackDisplayHelper displayHelper; + private GPXFile gpxFile; + private List items = new ArrayList<>(); + + public OptionsCard(@NonNull MapActivity mapActivity, TrackDisplayHelper displayHelper) { + super(mapActivity); + this.displayHelper = displayHelper; + this.gpxFile = displayHelper.getGpx(); + } + + @Override + public int getCardLayoutId() { + return R.layout.card_container; + } + + @Override + protected void updateContent() { + ViewGroup itemsContainer = (ViewGroup) view; + itemsContainer.removeAllViews(); + items.clear(); + + boolean fileAvailable = gpxFile.path != null && !gpxFile.showCurrentTrack; + items.add(createShowOnMapItem()); + items.add(createAppearanceItem()); + if (fileAvailable) { + items.add(createDirectionsItem()); + } + items.add(createDividerItem()); + items.add(createJoinGapsItem()); + items.add(createAnalyzeOnMapItem()); + items.add(createAnalyzeByIntervalsItem()); + + items.add(createDividerItem()); + items.add(createShareItem()); + + if (fileAvailable) { + items.add(createUploadOsmItem()); + items.add(createDividerItem()); + items.add(createEditItem()); + items.add(createRenameItem()); + items.add(createChangeFolderItem()); + items.add(createDividerItem()); + items.add(createDeleteItem()); + } + items.add(new DividerSpaceItem(mapActivity, AndroidUtils.dpToPx(app, 6))); + + inflateItems(); + } + + private BaseBottomSheetItem createDividerItem() { + DividerItem dividerItem = new DividerItem(mapActivity); + int start = app.getResources().getDimensionPixelSize(R.dimen.measurement_tool_options_divider_margin_start); + int verticalMargin = AndroidUtils.dpToPx(app, 6); + dividerItem.setMargins(start, verticalMargin, 0, verticalMargin); + + return dividerItem; + } + + private BaseBottomSheetItem createShowOnMapItem() { + + final Drawable showIcon = getActiveIcon(R.drawable.ic_action_view); + final Drawable hideIcon = getContentIcon(R.drawable.ic_action_hide); + boolean gpxFileSelected = isGpxFileSelected(app, gpxFile); + + final BottomSheetItemWithCompoundButton[] showOnMapItem = new BottomSheetItemWithCompoundButton[1]; + showOnMapItem[0] = (BottomSheetItemWithCompoundButton) new BottomSheetItemWithCompoundButton.Builder() + .setChecked(gpxFileSelected) + .setIcon(gpxFileSelected ? showIcon : hideIcon) + .setTitle(app.getString(R.string.shared_string_show_on_map)) + .setLayoutId(R.layout.bottom_sheet_item_with_switch_pad_32) + .setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + boolean checked = !showOnMapItem[0].isChecked(); + showOnMapItem[0].setChecked(checked); + showOnMapItem[0].setIcon(checked ? showIcon : hideIcon); + + CardListener listener = getListener(); + if (listener != null) { + listener.onCardButtonPressed(OptionsCard.this, SHOW_ON_MAP_BUTTON_INDEX); + } + } + }) + .create(); + return showOnMapItem[0]; + } + + private BaseBottomSheetItem createAppearanceItem() { + return new SimpleBottomSheetItem.Builder() + .setIcon(getActiveIcon(R.drawable.ic_action_appearance)) + .setTitle(app.getString(R.string.shared_string_appearance)) + .setLayoutId(R.layout.bottom_sheet_item_simple_pad_32dp) + .setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + CardListener listener = getListener(); + if (listener != null) { + listener.onCardButtonPressed(OptionsCard.this, APPEARANCE_BUTTON_INDEX); + } + } + }) + .create(); + } + + private BaseBottomSheetItem createDirectionsItem() { + return new SimpleBottomSheetItem.Builder() + .setIcon(getActiveIcon(R.drawable.ic_action_gdirections_dark)) + .setTitle(app.getString(R.string.get_directions)) + .setLayoutId(R.layout.bottom_sheet_item_simple_pad_32dp) + .setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + CardListener listener = getListener(); + if (listener != null) { + listener.onCardButtonPressed(OptionsCard.this, DIRECTIONS_BUTTON_INDEX); + } + } + }) + .create(); + } + + private BaseBottomSheetItem createJoinGapsItem() { + final Drawable joinGapsEnabledIcon = getActiveIcon(R.drawable.ic_action_join_segments); + final Drawable joinGapsDisabledIcon = getContentIcon(R.drawable.ic_action_join_segments); + boolean joinSegments = displayHelper.isJoinSegments(); + + final BottomSheetItemWithCompoundButton[] joinGapsItem = new BottomSheetItemWithCompoundButton[1]; + joinGapsItem[0] = (BottomSheetItemWithCompoundButton) new BottomSheetItemWithCompoundButton.Builder() + .setChecked(joinSegments) + .setIcon(joinSegments ? joinGapsEnabledIcon : joinGapsDisabledIcon) + .setTitle(app.getString(R.string.gpx_join_gaps)) + .setLayoutId(R.layout.bottom_sheet_item_with_switch_pad_32) + .setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + boolean checked = !joinGapsItem[0].isChecked(); + joinGapsItem[0].setChecked(checked); + joinGapsItem[0].setIcon(checked ? joinGapsEnabledIcon : joinGapsDisabledIcon); + + CardListener listener = getListener(); + if (listener != null) { + listener.onCardButtonPressed(OptionsCard.this, JOIN_GAPS_BUTTON_INDEX); + } + } + }) + .create(); + return joinGapsItem[0]; + } + + private BaseBottomSheetItem createAnalyzeOnMapItem() { + return new SimpleBottomSheetItem.Builder() + .setIcon(getActiveIcon(R.drawable.ic_action_analyze_intervals)) + .setTitle(app.getString(R.string.analyze_on_map)) + .setLayoutId(R.layout.bottom_sheet_item_simple_pad_32dp) + .setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + CardListener listener = getListener(); + if (listener != null) { + listener.onCardButtonPressed(OptionsCard.this, ANALYZE_ON_MAP_BUTTON_INDEX); + } + } + }) + .create(); + } + + private BaseBottomSheetItem createAnalyzeByIntervalsItem() { + return new SimpleBottomSheetItem.Builder() + .setIcon(getActiveIcon(R.drawable.ic_action_analyze_intervals)) + .setTitle(app.getString(R.string.analyze_by_intervals)) + .setLayoutId(R.layout.bottom_sheet_item_simple_pad_32dp) + .setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + CardListener listener = getListener(); + if (listener != null) { + listener.onCardButtonPressed(OptionsCard.this, ANALYZE_BY_INTERVALS_BUTTON_INDEX); + } + } + }) + .create(); + } + + private BaseBottomSheetItem createShareItem() { + Drawable shareIcon = getActiveIcon(R.drawable.ic_action_gshare_dark); + return new SimpleBottomSheetItem.Builder() + .setIcon(AndroidUtils.getDrawableForDirection(app, shareIcon)) + .setTitle(app.getString(R.string.shared_string_share)) + .setLayoutId(R.layout.bottom_sheet_item_simple_pad_32dp) + .setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + CardListener listener = getListener(); + if (listener != null) { + listener.onCardButtonPressed(OptionsCard.this, SHARE_BUTTON_INDEX); + } + } + }) + .create(); + } + + private BaseBottomSheetItem createUploadOsmItem() { + OsmEditingPlugin osmEditingPlugin = OsmandPlugin.getEnabledPlugin(OsmEditingPlugin.class); + if (osmEditingPlugin != null) { + return new SimpleBottomSheetItem.Builder() + .setIcon(getActiveIcon(R.drawable.ic_action_export)) + .setTitle(app.getString(R.string.upload_to_openstreetmap)) + .setLayoutId(R.layout.bottom_sheet_item_simple_pad_32dp) + .setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + CardListener listener = getListener(); + if (listener != null) { + listener.onCardButtonPressed(OptionsCard.this, UPLOAD_OSM_BUTTON_INDEX); + } + } + }) + .create(); + } + return null; + } + + private BaseBottomSheetItem createEditItem() { + Drawable editIcon = getActiveIcon(R.drawable.ic_action_edit_dark); + return new SimpleBottomSheetItem.Builder() + .setIcon(AndroidUtils.getDrawableForDirection(app, editIcon)) + .setTitle(app.getString(R.string.edit_track)) + .setLayoutId(R.layout.bottom_sheet_item_simple_pad_32dp) + .setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + CardListener listener = getListener(); + if (listener != null) { + listener.onCardButtonPressed(OptionsCard.this, EDIT_BUTTON_INDEX); + } + } + }) + .create(); + } + + private BaseBottomSheetItem createRenameItem() { + Drawable renameIcon = getActiveIcon(R.drawable.ic_action_name_field); + return new SimpleBottomSheetItem.Builder() + .setIcon(AndroidUtils.getDrawableForDirection(app, renameIcon)) + .setTitle(app.getString(R.string.rename_track)) + .setLayoutId(R.layout.bottom_sheet_item_simple_pad_32dp) + .setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + CardListener listener = getListener(); + if (listener != null) { + listener.onCardButtonPressed(OptionsCard.this, RENAME_BUTTON_INDEX); + } + } + }) + .create(); + } + + private BaseBottomSheetItem createChangeFolderItem() { + String folder = new File(gpxFile.path).getParentFile().getName(); + Drawable changeFolderIcon = getActiveIcon(R.drawable.ic_action_folder_move); + + return new BottomSheetItemWithDescriptionDifHeight.Builder() + .setMinHeight(app.getResources().getDimensionPixelSize(R.dimen.setting_list_item_group_height)) + .setDescriptionColorId(nightMode ? R.color.text_color_secondary_dark : R.color.text_color_secondary_light) + .setDescription(capitalizeFirstLetter(folder)) + .setIcon(AndroidUtils.getDrawableForDirection(app, changeFolderIcon)) + .setTitle(app.getString(R.string.change_folder)) + .setLayoutId(R.layout.bottom_sheet_item_with_descr_pad_32dp) + .setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + CardListener listener = getListener(); + if (listener != null) { + listener.onCardButtonPressed(OptionsCard.this, CHANGE_FOLDER_BUTTON_INDEX); + } + } + }) + .create(); + } + + private BaseBottomSheetItem createDeleteItem() { + String delete = app.getString(R.string.shared_string_delete); + Typeface typeface = FontCache.getRobotoMedium(app); + return new SimpleBottomSheetItem.Builder() + .setTitleColorId(R.color.color_osm_edit_delete) + .setIcon(getColoredIcon(R.drawable.ic_action_delete_dark, R.color.color_osm_edit_delete)) + .setTitle(UiUtilities.createCustomFontSpannable(typeface, delete, delete)) + .setLayoutId(R.layout.bottom_sheet_item_simple_pad_32dp) + .setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + CardListener listener = getListener(); + if (listener != null) { + listener.onCardButtonPressed(OptionsCard.this, DELETE_BUTTON_INDEX); + } + } + }) + .create(); + } + + private void inflateItems() { + for (BaseBottomSheetItem item : items) { + item.inflate(mapActivity, (ViewGroup) view, nightMode); + } + } +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/track/SegmentsCard.java b/OsmAnd/src/net/osmand/plus/track/SegmentsCard.java index 3a6fce7271..b3921a6889 100644 --- a/OsmAnd/src/net/osmand/plus/track/SegmentsCard.java +++ b/OsmAnd/src/net/osmand/plus/track/SegmentsCard.java @@ -34,7 +34,7 @@ public class SegmentsCard extends BaseCard { @Override public int getCardLayoutId() { - return R.layout.track_segments_container; + return R.layout.card_container; } @Override diff --git a/OsmAnd/src/net/osmand/plus/track/TrackAppearanceFragment.java b/OsmAnd/src/net/osmand/plus/track/TrackAppearanceFragment.java index 66b2a5f5a2..43642bfe9c 100644 --- a/OsmAnd/src/net/osmand/plus/track/TrackAppearanceFragment.java +++ b/OsmAnd/src/net/osmand/plus/track/TrackAppearanceFragment.java @@ -56,8 +56,6 @@ import java.io.File; import java.util.ArrayList; import java.util.List; -import static net.osmand.plus.activities.TrackActivity.CURRENT_RECORDING; -import static net.osmand.plus.activities.TrackActivity.TRACK_FILE_NAME; import static net.osmand.plus.dialogs.ConfigureMapMenu.CURRENT_TRACK_COLOR_ATTR; import static net.osmand.plus.dialogs.GpxAppearanceAdapter.TRACK_WIDTH_BOLD; import static net.osmand.plus.dialogs.GpxAppearanceAdapter.TRACK_WIDTH_MEDIUM; @@ -121,6 +119,10 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement return trackDrawInfo; } + public void setSelectedGpxFile(SelectedGpxFile selectedGpxFile) { + this.selectedGpxFile = selectedGpxFile; + } + @Override public int getSupportedMenuStatesPortrait() { return MenuState.HEADER_ONLY | MenuState.HALF_SCREEN | MenuState.FULL_SCREEN; @@ -132,40 +134,25 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement app = requireMyApplication(); gpxDbHelper = app.getGpxDbHelper(); - Bundle arguments = getArguments(); if (savedInstanceState != null) { trackDrawInfo = new TrackDrawInfo(savedInstanceState); - if (trackDrawInfo.isCurrentRecording()) { - selectedGpxFile = app.getSavingTrackHelper().getCurrentTrack(); - } else { - selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(trackDrawInfo.getFilePath()); - } if (!selectedGpxFile.isShowCurrentTrack()) { gpxDataItem = gpxDbHelper.getItem(new File(trackDrawInfo.getFilePath())); } showStartFinishIconsInitialValue = savedInstanceState.getBoolean(SHOW_START_FINISH_ICONS_INITIAL_VALUE_KEY, app.getSettings().SHOW_START_FINISH_ICONS.get()); - } else if (arguments != null) { - String gpxFilePath = arguments.getString(TRACK_FILE_NAME); - boolean currentRecording = arguments.getBoolean(CURRENT_RECORDING, false); + } else { showStartFinishIconsInitialValue = app.getSettings().SHOW_START_FINISH_ICONS.get(); - if (gpxFilePath == null && !currentRecording) { - log.error("Required extra '" + TRACK_FILE_NAME + "' is missing"); - dismiss(); - return; - } - if (currentRecording) { + if (selectedGpxFile.isShowCurrentTrack()) { trackDrawInfo = new TrackDrawInfo(true); trackDrawInfo.setColor(app.getSettings().CURRENT_TRACK_COLOR.get()); trackDrawInfo.setWidth(app.getSettings().CURRENT_TRACK_WIDTH.get()); trackDrawInfo.setShowArrows(app.getSettings().CURRENT_TRACK_SHOW_ARROWS.get()); trackDrawInfo.setShowStartFinish(app.getSettings().CURRENT_TRACK_SHOW_START_FINISH.get()); - selectedGpxFile = app.getSavingTrackHelper().getCurrentTrack(); } else { - gpxDataItem = gpxDbHelper.getItem(new File(gpxFilePath)); + gpxDataItem = gpxDbHelper.getItem(new File(selectedGpxFile.getGpxFile().path)); trackDrawInfo = new TrackDrawInfo(app, gpxDataItem, false); - selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(gpxFilePath); } updateTrackColor(); } @@ -726,8 +713,12 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement return totalScreenHeight - frameTotalHeight; } - public static boolean showInstance(@NonNull MapActivity mapActivity, TrackAppearanceFragment fragment) { + public static boolean showInstance(@NonNull MapActivity mapActivity, @NonNull SelectedGpxFile selectedGpxFile) { try { + TrackAppearanceFragment fragment = new TrackAppearanceFragment(); + fragment.setSelectedGpxFile(selectedGpxFile); + fragment.setRetainInstance(true); + mapActivity.getSupportFragmentManager() .beginTransaction() .replace(R.id.fragmentContainer, fragment, fragment.getFragmentTag()) diff --git a/OsmAnd/src/net/osmand/plus/track/TrackDisplayHelper.java b/OsmAnd/src/net/osmand/plus/track/TrackDisplayHelper.java index 5ab0a6740f..39ce84eedf 100644 --- a/OsmAnd/src/net/osmand/plus/track/TrackDisplayHelper.java +++ b/OsmAnd/src/net/osmand/plus/track/TrackDisplayHelper.java @@ -101,19 +101,7 @@ public class TrackDisplayHelper { return new ArrayList<>(); } if (gpxFile.modifiedTime != modifiedTime) { - modifiedTime = gpxFile.modifiedTime; - GpxSelectionHelper selectedGpxHelper = app.getSelectedGpxHelper(); - displayGroups = selectedGpxHelper.collectDisplayGroups(gpxFile); - originalGroups.clear(); - for (GpxSelectionHelper.GpxDisplayGroup g : displayGroups) { - originalGroups.add(g.cloneInstance()); - } - if (file != null) { - SelectedGpxFile sf = selectedGpxHelper.getSelectedFileByPath(gpxFile.path); - if (sf != null && file != null && sf.getDisplayGroups(app) != null) { - displayGroups = sf.getDisplayGroups(app); - } - } + updateDisplayGroups(); } if (useDisplayGroups) { return displayGroups; @@ -122,6 +110,22 @@ public class TrackDisplayHelper { } } + public void updateDisplayGroups() { + modifiedTime = gpxFile.modifiedTime; + GpxSelectionHelper selectedGpxHelper = app.getSelectedGpxHelper(); + displayGroups = selectedGpxHelper.collectDisplayGroups(gpxFile); + originalGroups.clear(); + for (GpxDisplayGroup g : displayGroups) { + originalGroups.add(g.cloneInstance()); + } + if (file != null) { + SelectedGpxFile sf = selectedGpxHelper.getSelectedFileByPath(gpxFile.path); + if (sf != null && file != null && sf.getDisplayGroups(app) != null) { + displayGroups = sf.getDisplayGroups(app); + } + } + } + @NonNull public List getOriginalGroups(GpxDisplayItemType[] filterTypes) { return filterGroups(false, filterTypes); diff --git a/OsmAnd/src/net/osmand/plus/track/TrackMenuFragment.java b/OsmAnd/src/net/osmand/plus/track/TrackMenuFragment.java index 595c456858..794011f51e 100644 --- a/OsmAnd/src/net/osmand/plus/track/TrackMenuFragment.java +++ b/OsmAnd/src/net/osmand/plus/track/TrackMenuFragment.java @@ -5,12 +5,14 @@ import android.content.res.ColorStateList; import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; +import android.view.Gravity; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; +import android.widget.ImageView; import android.widget.TextView; import androidx.annotation.DrawableRes; @@ -25,36 +27,47 @@ import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.google.android.material.bottomnavigation.BottomNavigationView; import net.osmand.AndroidUtils; +import net.osmand.FileUtils; +import net.osmand.FileUtils.RenameCallback; import net.osmand.GPXUtilities.GPXFile; import net.osmand.GPXUtilities.Track; import net.osmand.GPXUtilities.TrkSegment; import net.osmand.GPXUtilities.WptPt; import net.osmand.PlatformUtil; +import net.osmand.data.LatLon; import net.osmand.data.QuadRect; import net.osmand.data.RotatedTileBox; -import net.osmand.plus.GPXDatabase.GpxDataItem; import net.osmand.plus.GpxDbHelper; import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup; import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem; import net.osmand.plus.GpxSelectionHelper.GpxDisplayItemType; import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile; import net.osmand.plus.OsmandApplication; +import net.osmand.plus.OsmandPlugin; import net.osmand.plus.R; +import net.osmand.plus.UiUtilities; import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.activities.MapActivityActions; import net.osmand.plus.base.ContextMenuFragment; import net.osmand.plus.base.ContextMenuScrollFragment; import net.osmand.plus.helpers.AndroidUiHelper; import net.osmand.plus.helpers.GpxUiHelper; import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetType; import net.osmand.plus.helpers.GpxUiHelper.OrderedLineDataSet; +import net.osmand.plus.mapcontextmenu.controllers.SelectedGpxMenuController.OpenGpxDetailsTask; +import net.osmand.plus.mapcontextmenu.other.TrackChartPoints; import net.osmand.plus.mapcontextmenu.other.TrackDetailsMenu; import net.osmand.plus.measurementtool.GpxData; import net.osmand.plus.measurementtool.MeasurementEditingContext; import net.osmand.plus.measurementtool.MeasurementToolFragment; +import net.osmand.plus.myplaces.AvailableGPXFragment.GpxInfo; import net.osmand.plus.myplaces.GPXTabItemType; +import net.osmand.plus.myplaces.MoveGpxFileBottomSheet; +import net.osmand.plus.myplaces.MoveGpxFileBottomSheet.OnTrackFileMoveListener; import net.osmand.plus.myplaces.SegmentActionsListener; import net.osmand.plus.myplaces.SplitSegmentDialogFragment; import net.osmand.plus.myplaces.TrackActivityFragmentAdapter; +import net.osmand.plus.osmedit.OsmEditingPlugin; import net.osmand.plus.routepreparationmenu.cards.BaseCard; import net.osmand.plus.routepreparationmenu.cards.BaseCard.CardListener; import net.osmand.plus.track.SaveGpxAsyncTask.SaveGpxListener; @@ -68,28 +81,46 @@ import java.util.List; import static net.osmand.plus.activities.TrackActivity.CURRENT_RECORDING; import static net.osmand.plus.activities.TrackActivity.TRACK_FILE_NAME; +import static net.osmand.plus.myplaces.TrackActivityFragmentAdapter.isGpxFileSelected; +import static net.osmand.plus.track.OptionsCard.ANALYZE_BY_INTERVALS_BUTTON_INDEX; +import static net.osmand.plus.track.OptionsCard.ANALYZE_ON_MAP_BUTTON_INDEX; +import static net.osmand.plus.track.OptionsCard.APPEARANCE_BUTTON_INDEX; +import static net.osmand.plus.track.OptionsCard.CHANGE_FOLDER_BUTTON_INDEX; +import static net.osmand.plus.track.OptionsCard.DELETE_BUTTON_INDEX; +import static net.osmand.plus.track.OptionsCard.DIRECTIONS_BUTTON_INDEX; +import static net.osmand.plus.track.OptionsCard.EDIT_BUTTON_INDEX; +import static net.osmand.plus.track.OptionsCard.JOIN_GAPS_BUTTON_INDEX; +import static net.osmand.plus.track.OptionsCard.RENAME_BUTTON_INDEX; +import static net.osmand.plus.track.OptionsCard.SHARE_BUTTON_INDEX; +import static net.osmand.plus.track.OptionsCard.SHOW_ON_MAP_BUTTON_INDEX; +import static net.osmand.plus.track.OptionsCard.UPLOAD_OSM_BUTTON_INDEX; -public class TrackMenuFragment extends ContextMenuScrollFragment implements CardListener, SegmentActionsListener { +public class TrackMenuFragment extends ContextMenuScrollFragment implements CardListener, + SegmentActionsListener, RenameCallback, OnTrackFileMoveListener { public static final String TAG = TrackMenuFragment.class.getName(); private static final Log log = PlatformUtil.getLog(TrackMenuFragment.class); private OsmandApplication app; private TrackDisplayHelper displayHelper; - - private GpxDataItem gpxDataItem; private SelectedGpxFile selectedGpxFile; private View routeMenuTopShadowAll; + private TextView headerTitle; + private ImageView headerIcon; private BottomNavigationView bottomNav; private TrackMenuType menuType = TrackMenuType.TRACK; private SegmentsCard segmentsCard; + private OptionsCard optionsCard; + + private TrackChartPoints trackChartPoints; private int menuTitleHeight; public enum TrackMenuType { TRACK(R.id.action_track, R.string.shared_string_gpx_tracks), - POINTS(R.id.action_points, R.string.shared_string_gpx_points); + POINTS(R.id.action_points, R.string.shared_string_gpx_points), + OPTIONS(R.id.action_options, R.string.shared_string_options); TrackMenuType(@DrawableRes int iconId, @StringRes int titleId) { this.iconId = iconId; @@ -140,26 +171,20 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card GpxDbHelper gpxDbHelper = app.getGpxDbHelper(); displayHelper = new TrackDisplayHelper(app); - String gpxFilePath = ""; - boolean currentRecording = false; Bundle arguments = getArguments(); - if (savedInstanceState != null) { - gpxFilePath = savedInstanceState.getString(TRACK_FILE_NAME); - currentRecording = savedInstanceState.getBoolean(CURRENT_RECORDING, false); - } else if (arguments != null) { - gpxFilePath = arguments.getString(TRACK_FILE_NAME); - currentRecording = arguments.getBoolean(CURRENT_RECORDING, false); + if (arguments != null) { + String gpxFilePath = arguments.getString(TRACK_FILE_NAME); + boolean currentRecording = arguments.getBoolean(CURRENT_RECORDING, false); + if (currentRecording) { + selectedGpxFile = app.getSavingTrackHelper().getCurrentTrack(); + } else { + File file = new File(gpxFilePath); + displayHelper.setFile(file); + displayHelper.setGpxDataItem(gpxDbHelper.getItem(file)); + selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(gpxFilePath); + } + displayHelper.setGpx(selectedGpxFile.getGpxFile()); } - if (currentRecording) { - selectedGpxFile = app.getSavingTrackHelper().getCurrentTrack(); - } else { - File file = new File(gpxFilePath); - displayHelper.setFile(file); - gpxDataItem = gpxDbHelper.getItem(file); - selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(gpxFilePath); - } - displayHelper.setGpxDataItem(gpxDataItem); - displayHelper.setGpx(selectedGpxFile.getGpxFile()); } public GPXFile getGpx() { @@ -172,14 +197,19 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card if (view != null) { bottomNav = view.findViewById(R.id.bottom_navigation); routeMenuTopShadowAll = view.findViewById(R.id.route_menu_top_shadow_all); - TextView title = view.findViewById(R.id.title); - String fileName = Algorithms.getFileWithoutDirs(getGpx().path); - title.setText(GpxUiHelper.getGpxTitle(fileName)); + headerTitle = view.findViewById(R.id.title); + headerIcon = view.findViewById(R.id.icon_view); if (isPortrait()) { updateCardsLayout(); + } else { + int widthNoShadow = getLandscapeNoShadowWidth(); + FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(widthNoShadow, ViewGroup.LayoutParams.WRAP_CONTENT); + params.gravity = Gravity.BOTTOM | Gravity.START; + bottomNav.setLayoutParams(params); } setupCards(); + updateHeader(); setupButtons(view); enterTrackAppearanceMode(); runLayoutListener(); @@ -187,18 +217,46 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card return view; } + private void updateHeader() { + if (menuType == TrackMenuType.OPTIONS) { + headerTitle.setText(menuType.titleId); + AndroidUiHelper.updateVisibility(headerIcon, false); + } else { + String fileName = Algorithms.getFileWithoutDirs(getGpx().path); + headerTitle.setText(GpxUiHelper.getGpxTitle(fileName)); + AndroidUiHelper.updateVisibility(headerIcon, true); + } + } + private void setupCards() { MapActivity mapActivity = getMapActivity(); if (mapActivity != null) { ViewGroup cardsContainer = getCardsContainer(); cardsContainer.removeAllViews(); if (menuType == TrackMenuType.TRACK) { - if (segmentsCard != null) { + if (segmentsCard != null && segmentsCard.getView() != null) { + ViewGroup parent = (ViewGroup) segmentsCard.getView().getParent(); + if (parent != null) { + parent.removeAllViews(); + } cardsContainer.addView(segmentsCard.getView()); } else { segmentsCard = new SegmentsCard(mapActivity, displayHelper, this); + segmentsCard.setListener(this); cardsContainer.addView(segmentsCard.build(mapActivity)); } + } else if (menuType == TrackMenuType.OPTIONS) { + if (optionsCard != null && optionsCard.getView() != null) { + ViewGroup parent = (ViewGroup) optionsCard.getView().getParent(); + if (parent != null) { + parent.removeAllViews(); + } + cardsContainer.addView(optionsCard.getView()); + } else { + optionsCard = new OptionsCard(mapActivity, displayHelper); + optionsCard.setListener(this); + cardsContainer.addView(optionsCard.build(mapActivity)); + } } } } @@ -239,6 +297,46 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card exitTrackAppearanceMode(); } + @Override + public void onResume() { + super.onResume(); + MapActivity mapActivity = getMapActivity(); + if (mapActivity != null && trackChartPoints != null) { + mapActivity.getMapLayers().getGpxLayer().setTrackChartPoints(trackChartPoints); + } + } + + @Override + public void onPause() { + super.onPause(); + MapActivity mapActivity = getMapActivity(); + if (mapActivity != null) { + mapActivity.getMapLayers().getGpxLayer().setTrackChartPoints(null); + } + } + + @Override + public void renamedTo(File file) { + updateFile(file); + } + + @Override + public void onFileMove(@NonNull File src, @NonNull File dest) { + File file = FileUtils.renameGpxFile(app, src, dest); + if (file != null) { + updateFile(file); + } else { + app.showToastMessage(R.string.file_can_not_be_renamed); + } + } + + private void updateFile(File file) { + displayHelper.setFile(file); + displayHelper.updateDisplayGroups(); + updateHeader(); + updateContent(); + } + private void enterTrackAppearanceMode() { MapActivity mapActivity = getMapActivity(); if (mapActivity != null) { @@ -311,7 +409,104 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card @Override public void onCardButtonPressed(@NonNull BaseCard card, int buttonIndex) { + MapActivity mapActivity = getMapActivity(); + if (mapActivity == null) { + return; + } + if (card instanceof OptionsCard) { + final GPXFile gpxFile = getGpx(); + if (buttonIndex == SHOW_ON_MAP_BUTTON_INDEX) { + boolean gpxFileSelected = !isGpxFileSelected(app, gpxFile); + app.getSelectedGpxHelper().selectGpxFile(gpxFile, gpxFileSelected, false); + mapActivity.refreshMap(); + } else if (buttonIndex == APPEARANCE_BUTTON_INDEX) { + TrackAppearanceFragment.showInstance(mapActivity, selectedGpxFile); + } else if (buttonIndex == DIRECTIONS_BUTTON_INDEX) { + MapActivityActions mapActions = mapActivity.getMapActions(); + if (app.getRoutingHelper().isFollowingMode()) { + mapActions.stopNavigationActionConfirm(null, new Runnable() { + @Override + public void run() { + MapActivity mapActivity = getMapActivity(); + if (mapActivity != null) { + mapActivity.getMapActions().enterRoutePlanningModeGivenGpx(gpxFile, null, + null, null, true, true, MenuState.HEADER_ONLY); + } + } + }); + } else { + mapActions.stopNavigationWithoutConfirm(); + mapActions.enterRoutePlanningModeGivenGpx(gpxFile, null, null, + null, true, true, MenuState.HEADER_ONLY); + } + dismiss(); + } + if (buttonIndex == JOIN_GAPS_BUTTON_INDEX) { + displayHelper.setJoinSegments(!displayHelper.isJoinSegments()); + mapActivity.refreshMap(); + if (segmentsCard != null) { + segmentsCard.updateContent(); + } + } else if (buttonIndex == ANALYZE_ON_MAP_BUTTON_INDEX) { + new OpenGpxDetailsTask(selectedGpxFile, null, mapActivity).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + dismiss(); + } else if (buttonIndex == ANALYZE_BY_INTERVALS_BUTTON_INDEX) { + FragmentManager fragmentManager = mapActivity.getSupportFragmentManager(); + TrkSegment segment = gpxFile.getGeneralSegment(); + if (segment == null) { + List segments = gpxFile.getNonEmptyTrkSegments(false); + if (!Algorithms.isEmpty(segments)) { + segment = segments.get(0); + } + } + GpxDisplayItemType[] filterTypes = new GpxDisplayItemType[] {GpxDisplayItemType.TRACK_SEGMENT}; + List items = TrackDisplayHelper.flatten(displayHelper.getOriginalGroups(filterTypes)); + if (segment != null && !Algorithms.isEmpty(items)) { + SplitSegmentDialogFragment.showInstance(fragmentManager, displayHelper, items.get(0), segment); + } + } else if (buttonIndex == SHARE_BUTTON_INDEX) { + OsmandApplication app = mapActivity.getMyApplication(); + if (gpxFile.showCurrentTrack) { + GpxUiHelper.saveAndShareCurrentGpx(app, gpxFile); + } else if (!Algorithms.isEmpty(gpxFile.path)) { + GpxUiHelper.saveAndShareGpxWithAppearance(app, gpxFile); + } + } else if (buttonIndex == UPLOAD_OSM_BUTTON_INDEX) { + OsmEditingPlugin osmEditingPlugin = OsmandPlugin.getEnabledPlugin(OsmEditingPlugin.class); + if (osmEditingPlugin != null) { + GpxInfo gpxInfo = new GpxInfo(); + gpxInfo.gpx = gpxFile; + gpxInfo.file = new File(gpxFile.path); + osmEditingPlugin.sendGPXFiles(mapActivity, this, gpxInfo); + } + } else if (buttonIndex == EDIT_BUTTON_INDEX) { + String fileName = Algorithms.getFileWithoutDirs(gpxFile.path); + MeasurementToolFragment.showInstance(mapActivity.getSupportFragmentManager(), fileName); + dismiss(); + } else if (buttonIndex == RENAME_BUTTON_INDEX) { + FileUtils.renameFile(mapActivity, new File(gpxFile.path), this, true); + } else if (buttonIndex == CHANGE_FOLDER_BUTTON_INDEX) { + FragmentManager fragmentManager = mapActivity.getSupportFragmentManager(); + MoveGpxFileBottomSheet.showInstance(fragmentManager, this, gpxFile.path, true); + } else if (buttonIndex == DELETE_BUTTON_INDEX) { + String fileName = Algorithms.getFileWithoutDirs(gpxFile.path); + + AlertDialog.Builder builder = new AlertDialog.Builder(UiUtilities.getThemedContext(mapActivity, isNightMode())); + builder.setTitle(getString(R.string.delete_confirmation_msg, fileName)); + builder.setMessage(R.string.are_you_sure); + builder.setNegativeButton(R.string.shared_string_cancel, null).setPositiveButton( + R.string.shared_string_ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + if (FileUtils.removeGpxFile(app, new File((gpxFile.path)))) { + dismiss(); + } + } + }); + builder.show(); + } + } } @Override @@ -378,6 +573,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card if (type.iconId == item.getItemId()) { menuType = type; setupCards(); + updateHeader(); break; } } @@ -391,6 +587,9 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card if (segmentsCard != null) { segmentsCard.updateContent(); } + if (optionsCard != null) { + optionsCard.updateContent(); + } setupCards(); } @@ -405,8 +604,19 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card } @Override - public void onPointSelected(double lat, double lon) { - + public void onPointSelected(TrkSegment segment, double lat, double lon) { + if (trackChartPoints == null) { + trackChartPoints = new TrackChartPoints(); + trackChartPoints.setGpx(getGpx()); + } + MapActivity mapActivity = getMapActivity(); + if (mapActivity != null) { + int segmentColor = segment != null ? segment.getColor(0) : 0; + trackChartPoints.setSegmentColor(segmentColor); + trackChartPoints.setHighlightedPoint(new LatLon(lat, lon)); + mapActivity.getMapLayers().getGpxLayer().setTrackChartPoints(trackChartPoints); + mapActivity.refreshMap(); + } } @Override @@ -551,10 +761,8 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card public void gpxSavingFinished(Exception errorMessage) { if (selectedGpxFile != null) { List groups = displayHelper.getDisplayGroups(new GpxDisplayItemType[] {GpxDisplayItemType.TRACK_SEGMENT}); - if (groups != null) { - selectedGpxFile.setDisplayGroups(groups, app); - selectedGpxFile.processPoints(app); - } + selectedGpxFile.setDisplayGroups(groups, app); + selectedGpxFile.processPoints(app); } updateContent(); } @@ -582,6 +790,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card TrackMenuFragment fragment = new TrackMenuFragment(); fragment.setArguments(args); + fragment.setRetainInstance(true); mapActivity.getSupportFragmentManager() .beginTransaction()