diff --git a/OsmAnd-api/src/net/osmand/aidlapi/IOsmAndAidlInterface.aidl b/OsmAnd-api/src/net/osmand/aidlapi/IOsmAndAidlInterface.aidl index e25e4338de..770cc32418 100644 --- a/OsmAnd-api/src/net/osmand/aidlapi/IOsmAndAidlInterface.aidl +++ b/OsmAnd-api/src/net/osmand/aidlapi/IOsmAndAidlInterface.aidl @@ -77,6 +77,7 @@ import net.osmand.aidlapi.customization.OsmandSettingsInfoParams; import net.osmand.aidlapi.customization.CustomizationInfoParams; import net.osmand.aidlapi.customization.ProfileSettingsParams; import net.osmand.aidlapi.customization.MapMarginsParams; +import net.osmand.aidlapi.customization.CustomPluginParams; import net.osmand.aidlapi.gpx.AGpxFile; import net.osmand.aidlapi.gpx.AGpxFileDetails; @@ -883,4 +884,6 @@ interface IOsmAndAidlInterface { * Is contect menu open. */ boolean isMenuOpen(); + + int getPluginVersion(in CustomPluginParams params); } \ No newline at end of file diff --git a/OsmAnd-api/src/net/osmand/aidlapi/customization/CustomPluginParams.aidl b/OsmAnd-api/src/net/osmand/aidlapi/customization/CustomPluginParams.aidl new file mode 100644 index 0000000000..9eeaa2e013 --- /dev/null +++ b/OsmAnd-api/src/net/osmand/aidlapi/customization/CustomPluginParams.aidl @@ -0,0 +1,3 @@ +package net.osmand.aidlapi.customization; + +parcelable CustomPluginParams; \ No newline at end of file diff --git a/OsmAnd-api/src/net/osmand/aidlapi/customization/CustomPluginParams.java b/OsmAnd-api/src/net/osmand/aidlapi/customization/CustomPluginParams.java new file mode 100644 index 0000000000..a3b35a7dd4 --- /dev/null +++ b/OsmAnd-api/src/net/osmand/aidlapi/customization/CustomPluginParams.java @@ -0,0 +1,48 @@ +package net.osmand.aidlapi.customization; + +import android.os.Bundle; +import android.os.Parcel; + +import net.osmand.aidlapi.AidlParams; + + +public class CustomPluginParams extends AidlParams { + + public static final String PLUGIN_ID_KEY = "plugin_id"; + + private String pluginId; + + public CustomPluginParams(String pluginId) { + this.pluginId = pluginId; + } + + public CustomPluginParams(Parcel in) { + readFromParcel(in); + } + + public static final Creator CREATOR = new Creator() { + @Override + public CustomPluginParams createFromParcel(Parcel in) { + return new CustomPluginParams(in); + } + + @Override + public CustomPluginParams[] newArray(int size) { + return new CustomPluginParams[size]; + } + }; + + public String getPluginId() { + return pluginId; + } + + @Override + public void writeToBundle(Bundle bundle) { + bundle.putString(PLUGIN_ID_KEY, pluginId); + } + + @Override + protected void readFromBundle(Bundle bundle) { + pluginId = bundle.getString(PLUGIN_ID_KEY); + } +} \ No newline at end of file diff --git a/OsmAnd-java/src/main/java/net/osmand/router/RouteSegmentResult.java b/OsmAnd-java/src/main/java/net/osmand/router/RouteSegmentResult.java index 6f8de67353..c57fdc8f1c 100644 --- a/OsmAnd-java/src/main/java/net/osmand/router/RouteSegmentResult.java +++ b/OsmAnd-java/src/main/java/net/osmand/router/RouteSegmentResult.java @@ -315,7 +315,7 @@ public class RouteSegmentResult implements StringExternalizable int[] turnLanes = TurnType.lanesFromString(bundle.getString("turnLanes", null)); turnType.setLanes(turnLanes); } - object.id = bundle.getLong("id", object.id); + object.id = bundle.getLong("id", object.id) << 6; object.types = bundle.getIntArray("types", null); object.pointTypes = bundle.getIntIntArray("pointTypes", null); object.nameIds = bundle.getIntArray("names", null); diff --git a/OsmAnd/res/drawable/bg_round_btn_dark.xml b/OsmAnd/res/drawable/bg_round_btn_dark.xml new file mode 100644 index 0000000000..e73b696dd0 --- /dev/null +++ b/OsmAnd/res/drawable/bg_round_btn_dark.xml @@ -0,0 +1,10 @@ + + + + + + diff --git a/OsmAnd/res/drawable/bg_round_btn_light.xml b/OsmAnd/res/drawable/bg_round_btn_light.xml new file mode 100644 index 0000000000..b6a1875aa5 --- /dev/null +++ b/OsmAnd/res/drawable/bg_round_btn_light.xml @@ -0,0 +1,10 @@ + + + + + + diff --git a/OsmAnd/res/drawable/btn_circle_night_no_shadow.xml b/OsmAnd/res/drawable/btn_circle_night_no_shadow.xml new file mode 100644 index 0000000000..f3b4395849 --- /dev/null +++ b/OsmAnd/res/drawable/btn_circle_night_no_shadow.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/drawable/btn_circle_no_shadow.xml b/OsmAnd/res/drawable/btn_circle_no_shadow.xml new file mode 100644 index 0000000000..6ba74f9ec9 --- /dev/null +++ b/OsmAnd/res/drawable/btn_circle_no_shadow.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/drawable/ic_action_join_segments.xml b/OsmAnd/res/drawable/ic_action_join_segments.xml new file mode 100644 index 0000000000..20b82f7a73 --- /dev/null +++ b/OsmAnd/res/drawable/ic_action_join_segments.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/OsmAnd/res/drawable/ic_action_new_segment.xml b/OsmAnd/res/drawable/ic_action_new_segment.xml new file mode 100644 index 0000000000..1bcf405766 --- /dev/null +++ b/OsmAnd/res/drawable/ic_action_new_segment.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + diff --git a/OsmAnd/res/layout-land/map_hud_bottom.xml b/OsmAnd/res/layout-land/map_hud_bottom.xml index c591d05eda..ec9b4e0c4a 100644 --- a/OsmAnd/res/layout-land/map_hud_bottom.xml +++ b/OsmAnd/res/layout-land/map_hud_bottom.xml @@ -110,16 +110,31 @@ android:layout_marginStart="@dimen/map_button_spacing_land" android:background="@drawable/btn_round" android:contentDescription="@string/layer_route" - tools:src="@drawable/ic_action_remove_dark"/> + tools:src="@drawable/ic_action_remove_dark" /> + + + + + + + - diff --git a/OsmAnd/res/layout/bottom_sheet_item_with_switch_and_dialog.xml b/OsmAnd/res/layout/bottom_sheet_item_with_switch_and_dialog.xml new file mode 100644 index 0000000000..bb6ae1a943 --- /dev/null +++ b/OsmAnd/res/layout/bottom_sheet_item_with_switch_and_dialog.xml @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/map_hud_bottom.xml b/OsmAnd/res/layout/map_hud_bottom.xml index dc4be05d64..629f9350a1 100644 --- a/OsmAnd/res/layout/map_hud_bottom.xml +++ b/OsmAnd/res/layout/map_hud_bottom.xml @@ -106,15 +106,28 @@ android:contentDescription="@string/layer_route" tools:src="@drawable/ic_action_remove_dark"/> - + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/fragment_on_save_current_track.xml b/OsmAnd/res/layout/save_gpx_fragment.xml similarity index 73% rename from OsmAnd/res/layout/fragment_on_save_current_track.xml rename to OsmAnd/res/layout/save_gpx_fragment.xml index bc333b7c7a..b2f953a6f0 100644 --- a/OsmAnd/res/layout/fragment_on_save_current_track.xml +++ b/OsmAnd/res/layout/save_gpx_fragment.xml @@ -59,31 +59,4 @@ android:padding="@dimen/content_padding" /> - - - - - - - - - - - \ No newline at end of file diff --git a/OsmAnd/res/values/attrs.xml b/OsmAnd/res/values/attrs.xml index ae88075cb7..fbcfe713fb 100644 --- a/OsmAnd/res/values/attrs.xml +++ b/OsmAnd/res/values/attrs.xml @@ -23,6 +23,7 @@ + diff --git a/OsmAnd/res/values/phrases.xml b/OsmAnd/res/values/phrases.xml index c38d838285..1af4077125 100644 --- a/OsmAnd/res/values/phrases.xml +++ b/OsmAnd/res/values/phrases.xml @@ -3998,7 +3998,7 @@ Vehicle access: delivery Vehicle access: forestry - Motorcar access: + Motorcar access: yes Motorcar access: private Motorcar access: no Motorcar access: destination @@ -4306,4 +4306,6 @@ Siren + Lifeguard base + diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index 7414ecc26f..22a74625cc 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -11,6 +11,16 @@ Thx - Hardy --> + + • Added option to export and import all data including settings, resources, my places\n\n + • Plan Route: graphs for segments with the route, added the ability to create and edit multiply segment tracks\n\n + • Added OAuth authentication method for OpenStreetMap, improved UI of OSM dialogs \n\n + • Custom colors for favorites and tracks waypoints\n\n + + Add new segment + Split after + Split before + Join segments Light aircraft You can use Elevation data for consideration of Ascent / Descent for your trip %1$s * %2$s diff --git a/OsmAnd/res/values/styles.xml b/OsmAnd/res/values/styles.xml index 50432d35a9..330dda3311 100644 --- a/OsmAnd/res/values/styles.xml +++ b/OsmAnd/res/values/styles.xml @@ -96,6 +96,7 @@ @drawable/btn_round_light @drawable/btn_round_border_light @drawable/btn_round_border_light_2 + @drawable/bg_round_btn_light @drawable/bg_card_light @drawable/context_menu_card_light @drawable/bg_map_context_menu_light @@ -400,6 +401,7 @@ @drawable/btn_round_dark @drawable/btn_round_border_dark @drawable/btn_round_border_dark_2 + @drawable/bg_round_btn_dark @drawable/bg_card_dark @drawable/context_menu_card_dark @drawable/bg_map_context_menu_dark diff --git a/OsmAnd/src/net/osmand/AndroidUtils.java b/OsmAnd/src/net/osmand/AndroidUtils.java index a3ca6b066b..545e7b7391 100644 --- a/OsmAnd/src/net/osmand/AndroidUtils.java +++ b/OsmAnd/src/net/osmand/AndroidUtils.java @@ -10,7 +10,6 @@ import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Canvas; -import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.PointF; diff --git a/OsmAnd/src/net/osmand/aidl/OsmandAidlApi.java b/OsmAnd/src/net/osmand/aidl/OsmandAidlApi.java index 467ad76a0f..969e5bd135 100644 --- a/OsmAnd/src/net/osmand/aidl/OsmandAidlApi.java +++ b/OsmAnd/src/net/osmand/aidl/OsmandAidlApi.java @@ -50,6 +50,7 @@ import net.osmand.plus.AppInitializer.AppInitializeListener; import net.osmand.plus.AppInitializer.InitEvents; import net.osmand.plus.ContextMenuAdapter; import net.osmand.plus.ContextMenuItem; +import net.osmand.plus.CustomOsmandPlugin; import net.osmand.plus.FavouritesDbHelper; import net.osmand.plus.GPXDatabase.GpxDataItem; import net.osmand.plus.GpxSelectionHelper; @@ -125,6 +126,7 @@ import static net.osmand.aidl.ConnectedApp.AIDL_OBJECT_ID; import static net.osmand.aidl.ConnectedApp.AIDL_PACKAGE_NAME; import static net.osmand.aidl.ConnectedApp.AIDL_REMOVE_MAP_LAYER; import static net.osmand.aidl.ConnectedApp.AIDL_REMOVE_MAP_WIDGET; +import static net.osmand.aidlapi.OsmandAidlConstants.CANNOT_ACCESS_API_ERROR; import static net.osmand.aidlapi.OsmandAidlConstants.COPY_FILE_IO_ERROR; import static net.osmand.aidlapi.OsmandAidlConstants.COPY_FILE_MAX_LOCK_TIME_MS; import static net.osmand.aidlapi.OsmandAidlConstants.COPY_FILE_PARAMS_ERROR; @@ -140,6 +142,7 @@ import static net.osmand.plus.helpers.ExternalApiHelper.PARAM_NT_DIRECTION_TURN; import static net.osmand.plus.helpers.ExternalApiHelper.PARAM_NT_DISTANCE; import static net.osmand.plus.helpers.ExternalApiHelper.PARAM_NT_IMMINENT; import static net.osmand.plus.settings.backend.backup.SettingsHelper.REPLACE_KEY; +import static net.osmand.plus.settings.backend.backup.SettingsHelper.SILENT_IMPORT_KEY; public class OsmandAidlApi { @@ -2233,11 +2236,12 @@ public class OsmandAidlApi { } public boolean importProfileV2(final Uri profileUri, ArrayList settingsTypeKeys, boolean replace, - String latestChanges, int version) { + String latestChanges, int version) { if (profileUri != null) { Bundle bundle = new Bundle(); bundle.putStringArrayList(SettingsHelper.SETTINGS_TYPE_LIST_KEY, settingsTypeKeys); bundle.putBoolean(REPLACE_KEY, replace); + bundle.putBoolean(SILENT_IMPORT_KEY, true); bundle.putString(SettingsHelper.SETTINGS_LATEST_CHANGES_KEY, latestChanges); bundle.putInt(SettingsHelper.SETTINGS_VERSION_KEY, version); @@ -2309,7 +2313,7 @@ public class OsmandAidlApi { File exportDir = app.getSettings().getExternalStorageDirectory(); String fileName = appMode.toHumanString(); SettingsHelper settingsHelper = app.getSettingsHelper(); - settingsItems.addAll(settingsHelper.getFilteredSettingsItems(settingsTypes, false)); + settingsItems.addAll(settingsHelper.getFilteredSettingsItems(settingsTypes, false, true)); settingsHelper.exportSettings(exportDir, fileName, null, settingsItems, true); return true; } @@ -2324,6 +2328,15 @@ public class OsmandAidlApi { return mapActivity.getContextMenu().isVisible(); } + public int getPluginVersion(String pluginName) { + OsmandPlugin plugin = OsmandPlugin.getPlugin(pluginName); + if (plugin instanceof CustomOsmandPlugin) { + CustomOsmandPlugin customPlugin = (CustomOsmandPlugin) plugin; + return customPlugin.getVersion(); + } + return CANNOT_ACCESS_API_ERROR; + } + private static class FileCopyInfo { long startTime; long lastAccessTime; diff --git a/OsmAnd/src/net/osmand/aidl/OsmandAidlServiceV2.java b/OsmAnd/src/net/osmand/aidl/OsmandAidlServiceV2.java index 78e7875d24..cac1426664 100644 --- a/OsmAnd/src/net/osmand/aidl/OsmandAidlServiceV2.java +++ b/OsmAnd/src/net/osmand/aidl/OsmandAidlServiceV2.java @@ -22,9 +22,9 @@ import net.osmand.aidlapi.contextmenu.ContextMenuButtonsParams; import net.osmand.aidlapi.contextmenu.RemoveContextMenuButtonsParams; import net.osmand.aidlapi.contextmenu.UpdateContextMenuButtonsParams; import net.osmand.aidlapi.copyfile.CopyFileParams; -import net.osmand.aidlapi.customization.MapMarginsParams; -import net.osmand.aidlapi.info.AppInfoParams; +import net.osmand.aidlapi.customization.CustomPluginParams; import net.osmand.aidlapi.customization.CustomizationInfoParams; +import net.osmand.aidlapi.customization.MapMarginsParams; import net.osmand.aidlapi.customization.OsmandSettingsInfoParams; import net.osmand.aidlapi.customization.OsmandSettingsParams; import net.osmand.aidlapi.customization.ProfileSettingsParams; @@ -48,6 +48,7 @@ import net.osmand.aidlapi.gpx.RemoveGpxParams; import net.osmand.aidlapi.gpx.ShowGpxParams; import net.osmand.aidlapi.gpx.StartGpxRecordingParams; import net.osmand.aidlapi.gpx.StopGpxRecordingParams; +import net.osmand.aidlapi.info.AppInfoParams; import net.osmand.aidlapi.lock.SetLockStateParams; import net.osmand.aidlapi.map.ALatLon; import net.osmand.aidlapi.map.SetMapLocationParams; @@ -1122,6 +1123,7 @@ public class OsmandAidlServiceV2 extends Service implements AidlCallbackListener return UNKNOWN_API_ERROR; } } + @Override public long registerForKeyEvents(AKeyEventsParams params, final IOsmAndAidlCallback callback) { try { @@ -1356,6 +1358,20 @@ public class OsmandAidlServiceV2 extends Service implements AidlCallbackListener return false; } } + + @Override + public int getPluginVersion(CustomPluginParams params) { + try { + OsmandAidlApi api = getApi("getPluginVersion"); + if (api != null) { + return api.getPluginVersion(params.getPluginId()); + } + } catch (Exception e) { + handleException(e); + return UNKNOWN_API_ERROR; + } + return CANNOT_ACCESS_API_ERROR; + } }; private void setCustomization(OsmandAidlApi api, CustomizationInfoParams params) { diff --git a/OsmAnd/src/net/osmand/plus/AppInitializer.java b/OsmAnd/src/net/osmand/plus/AppInitializer.java index 8f13681d69..e6271f4509 100644 --- a/OsmAnd/src/net/osmand/plus/AppInitializer.java +++ b/OsmAnd/src/net/osmand/plus/AppInitializer.java @@ -107,7 +107,7 @@ public class AppInitializer implements IProgress { private static final String VECTOR_INDEXES_CHECK = "VECTOR_INDEXES_CHECK"; //$NON-NLS-1$ private static final String EXCEPTION_FILE_SIZE = "EXCEPTION_FS"; //$NON-NLS-1$ - public static final String LATEST_CHANGES_URL = "https://osmand.net/blog/osmand-3-8-released"; + public static final String LATEST_CHANGES_URL = "https://osmand.net/blog/osmand-3-9-released"; // public static final String LATEST_CHANGES_URL = null; // not enough to read public static final int APP_EXIT_CODE = 4; public static final String APP_EXIT_KEY = "APP_EXIT_KEY"; diff --git a/OsmAnd/src/net/osmand/plus/CustomOsmandPlugin.java b/OsmAnd/src/net/osmand/plus/CustomOsmandPlugin.java index 9127fa0aef..9f3003e925 100644 --- a/OsmAnd/src/net/osmand/plus/CustomOsmandPlugin.java +++ b/OsmAnd/src/net/osmand/plus/CustomOsmandPlugin.java @@ -17,16 +17,6 @@ import net.osmand.PlatformUtil; import net.osmand.data.LatLon; import net.osmand.map.ITileSource; import net.osmand.map.WorldRegion; -import net.osmand.plus.settings.backend.ApplicationMode; -import net.osmand.plus.settings.backend.backup.SettingsHelper; -import net.osmand.plus.settings.backend.backup.AvoidRoadsSettingsItem; -import net.osmand.plus.settings.backend.backup.MapSourcesSettingsItem; -import net.osmand.plus.settings.backend.backup.PluginSettingsItem; -import net.osmand.plus.settings.backend.backup.PoiUiFiltersSettingsItem; -import net.osmand.plus.settings.backend.backup.ProfileSettingsItem; -import net.osmand.plus.settings.backend.backup.QuickActionsSettingsItem; -import net.osmand.plus.settings.backend.backup.SettingsHelper.SettingsCollectListener; -import net.osmand.plus.settings.backend.backup.SettingsItem; import net.osmand.plus.download.DownloadActivityType; import net.osmand.plus.download.DownloadIndexesThread; import net.osmand.plus.download.DownloadResources; @@ -35,6 +25,16 @@ import net.osmand.plus.helpers.AvoidSpecificRoads; import net.osmand.plus.poi.PoiUIFilter; import net.osmand.plus.quickaction.QuickAction; import net.osmand.plus.quickaction.QuickActionRegistry; +import net.osmand.plus.settings.backend.ApplicationMode; +import net.osmand.plus.settings.backend.backup.AvoidRoadsSettingsItem; +import net.osmand.plus.settings.backend.backup.MapSourcesSettingsItem; +import net.osmand.plus.settings.backend.backup.PluginSettingsItem; +import net.osmand.plus.settings.backend.backup.PoiUiFiltersSettingsItem; +import net.osmand.plus.settings.backend.backup.ProfileSettingsItem; +import net.osmand.plus.settings.backend.backup.QuickActionsSettingsItem; +import net.osmand.plus.settings.backend.backup.SettingsHelper; +import net.osmand.plus.settings.backend.backup.SettingsHelper.SettingsCollectListener; +import net.osmand.plus.settings.backend.backup.SettingsItem; import net.osmand.util.Algorithms; import org.apache.commons.logging.Log; @@ -73,9 +73,12 @@ public class CustomOsmandPlugin extends OsmandPlugin { private List suggestedDownloadItems = new ArrayList<>(); private List customRegions = new ArrayList<>(); + private int version; + public CustomOsmandPlugin(@NonNull OsmandApplication app, @NonNull JSONObject json) throws JSONException { super(app); pluginId = json.getString("pluginId"); + version = json.optInt("version", -1); readAdditionalDataFromJson(json); readDependentFilesFromJson(json); loadResources(); @@ -86,6 +89,11 @@ public class CustomOsmandPlugin extends OsmandPlugin { return pluginId; } + @Override + public int getVersion() { + return version; + } + @Override public String getName() { return JsonUtils.getLocalizedResFromMap(app, names, app.getString(R.string.custom_osmand_plugin)); diff --git a/OsmAnd/src/net/osmand/plus/GpxSelectionHelper.java b/OsmAnd/src/net/osmand/plus/GpxSelectionHelper.java index 026987d13b..cb1ad6b79d 100644 --- a/OsmAnd/src/net/osmand/plus/GpxSelectionHelper.java +++ b/OsmAnd/src/net/osmand/plus/GpxSelectionHelper.java @@ -23,16 +23,15 @@ import net.osmand.PlatformUtil; import net.osmand.StateChangedListener; import net.osmand.data.LatLon; import net.osmand.plus.GPXDatabase.GpxDataItem; -import net.osmand.plus.mapmarkers.MapMarkersHelper; -import net.osmand.plus.mapmarkers.MapMarkersGroup; import net.osmand.plus.activities.SavingTrackHelper; import net.osmand.plus.helpers.GpxUiHelper; import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetAxisType; import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetType; -import net.osmand.plus.routing.RouteProvider; import net.osmand.plus.helpers.enums.MetricsConstants; +import net.osmand.plus.mapmarkers.MapMarkersGroup; +import net.osmand.plus.mapmarkers.MapMarkersHelper; +import net.osmand.plus.routing.RouteProvider; import net.osmand.plus.track.GpxSplitType; -import net.osmand.plus.track.GradientScaleType; import net.osmand.util.Algorithms; import org.apache.commons.logging.Log; @@ -60,17 +59,13 @@ public class GpxSelectionHelper { private static final String BACKUP = "backup"; private static final String BACKUPMODIFIEDTIME = "backupTime"; private static final String COLOR = "color"; - private static final String WIDTH = "width"; private static final String SELECTED_BY_USER = "selected_by_user"; - private static final String SHOW_ARROWS = "show_arrows"; - private static final String GRADIENT_SCALE_TYPE = "gradient_scale_type"; - private static final String SHOW_START_FINISH = "show_start_finish"; private OsmandApplication app; + private SavingTrackHelper savingTrackHelper; @NonNull private List selectedGPXFiles = new ArrayList<>(); private Map selectedGpxFilesBackUp = new HashMap<>(); - private SavingTrackHelper savingTrackHelper; private SelectGpxTask selectGpxTask; private SelectedGpxFile trackToFollow; private StateChangedListener followTrackListener; @@ -231,22 +226,20 @@ public class GpxSelectionHelper { List groups = app.getSelectedGpxHelper().collectDisplayGroups(gpxFile); GpxSplitType splitType = GpxSplitType.getSplitTypeByTypeId(dataItem.getSplitType()); - if (splitType != null) { - if (splitType == GpxSplitType.NO_SPLIT) { - for (GpxDisplayGroup model : groups) { - model.noSplit(app); - } - } else if (splitType == GpxSplitType.DISTANCE) { - for (GpxDisplayGroup model : groups) { - model.splitByDistance(app, dataItem.getSplitInterval(), dataItem.isJoinSegments()); - } - } else if (splitType == GpxSplitType.TIME) { - for (GpxDisplayGroup model : groups) { - model.splitByTime(app, (int) dataItem.getSplitInterval(), dataItem.isJoinSegments()); - } + if (splitType == GpxSplitType.NO_SPLIT) { + for (GpxDisplayGroup model : groups) { + model.noSplit(app); + } + } else if (splitType == GpxSplitType.DISTANCE) { + for (GpxDisplayGroup model : groups) { + model.splitByDistance(app, dataItem.getSplitInterval(), dataItem.isJoinSegments()); + } + } else if (splitType == GpxSplitType.TIME) { + for (GpxDisplayGroup model : groups) { + model.splitByTime(app, (int) dataItem.getSplitInterval(), dataItem.isJoinSegments()); } - selectedGpxFile.setDisplayGroups(groups, app); } + selectedGpxFile.setDisplayGroups(groups, app); } } return true; @@ -579,24 +572,6 @@ public class GpxSelectionHelper { int clr = parseColor(obj.getString(COLOR)); gpx.setColor(clr); } - for (GradientScaleType scaleType : GradientScaleType.values()) { - if (obj.has(scaleType.getColorTypeName())) { - int clr = parseColor(obj.getString(scaleType.getColorTypeName())); - gpx.setGradientScaleColor(scaleType.getColorTypeName(), clr); - } - } - if (obj.has(SHOW_ARROWS)) { - gpx.setShowArrows(obj.optBoolean(SHOW_ARROWS, false)); - } - if (obj.has(GRADIENT_SCALE_TYPE)) { - gpx.setGradientScaleType(obj.optString(GRADIENT_SCALE_TYPE)); - } - if (obj.has(SHOW_START_FINISH)) { - gpx.setShowStartFinish(obj.optBoolean(SHOW_START_FINISH, true)); - } - if (obj.has(WIDTH)) { - gpx.setWidth(obj.getString(WIDTH)); - } if (gpx.error != null) { save = true; } else if (obj.has(BACKUP)) { @@ -644,20 +619,6 @@ public class GpxSelectionHelper { if (s.gpxFile.getColor(0) != 0) { obj.put(COLOR, Algorithms.colorToString(s.gpxFile.getColor(0))); } - if (s.gpxFile.getWidth(null) != null) { - obj.put(WIDTH, s.gpxFile.getWidth(null)); - } - if (s.gpxFile.getGradientScaleType() != null) { - obj.put(GRADIENT_SCALE_TYPE, s.gpxFile.getGradientScaleType()); - } - obj.put(SHOW_ARROWS, s.gpxFile.isShowArrows()); - obj.put(SHOW_START_FINISH, s.gpxFile.isShowStartFinish()); - for (GradientScaleType scaleType : GradientScaleType.values()) { - int gradientScaleColor = s.gpxFile.getGradientScaleColor(scaleType.getColorTypeName(), 0); - if (gradientScaleColor != 0) { - obj.put(scaleType.getColorTypeName(), Algorithms.colorToString(gradientScaleColor)); - } - } } obj.put(SELECTED_BY_USER, s.selectedByUser); } catch (JSONException e) { @@ -710,23 +671,6 @@ public class GpxSelectionHelper { if (dataItem.getColor() != 0) { gpx.setColor(dataItem.getColor()); } - if (dataItem.getGradientSpeedColor() != 0) { - gpx.setGradientScaleColor(GradientScaleType.SPEED.getColorTypeName(), dataItem.getGradientSpeedColor()); - } - if (dataItem.getGradientAltitudeColor() != 0) { - gpx.setGradientScaleColor(GradientScaleType.ALTITUDE.getColorTypeName(), dataItem.getGradientAltitudeColor()); - } - if (dataItem.getGradientSlopeColor() != 0) { - gpx.setGradientScaleColor(GradientScaleType.SLOPE.getColorTypeName(), dataItem.getGradientSlopeColor()); - } - if (dataItem.getGradientScaleType() != null) { - gpx.setGradientScaleType(dataItem.getGradientScaleType().getTypeName()); - } - if (dataItem.getWidth() != null) { - gpx.setWidth(dataItem.getWidth()); - } - gpx.setShowArrows(dataItem.isShowArrows()); - gpx.setShowStartFinish(dataItem.isShowStartFinish()); sf.setJoinSegments(dataItem.isJoinSegments()); } sf.setGpxFile(gpx, app); diff --git a/OsmAnd/src/net/osmand/plus/OsmAndFormatter.java b/OsmAnd/src/net/osmand/plus/OsmAndFormatter.java index 3fd1aa1adc..11267b0286 100644 --- a/OsmAnd/src/net/osmand/plus/OsmAndFormatter.java +++ b/OsmAnd/src/net/osmand/plus/OsmAndFormatter.java @@ -519,7 +519,11 @@ public class OsmAndFormatter { result.append(r); } else if (outputFormat == MGRS_FORMAT) { MGRSPoint pnt = new MGRSPoint(new LatLonPoint(lat, lon)); - result.append(pnt.toFlavoredString(5)); + try { + result.append(pnt.toFlavoredString(5)); + } catch (java.lang.Error e) { + e.printStackTrace(); + } } return result.toString(); } @@ -573,4 +577,4 @@ public class OsmAndFormatter { coordinate *= 60.0; return coordinate; } -} \ No newline at end of file +} diff --git a/OsmAnd/src/net/osmand/plus/OsmandPlugin.java b/OsmAnd/src/net/osmand/plus/OsmandPlugin.java index 54f45b7425..01203b6f72 100644 --- a/OsmAnd/src/net/osmand/plus/OsmandPlugin.java +++ b/OsmAnd/src/net/osmand/plus/OsmandPlugin.java @@ -123,8 +123,8 @@ public abstract class OsmandPlugin { return null; } - public String getVersion() { - return ""; + public int getVersion() { + return -1; } /** @@ -340,6 +340,7 @@ public abstract class OsmandPlugin { try { JSONObject json = new JSONObject(); json.put("pluginId", plugin.getId()); + json.put("version", plugin.getVersion()); plugin.writeAdditionalDataToJson(json); plugin.writeDependentFilesJson(json); itemsJson.put(json); diff --git a/OsmAnd/src/net/osmand/plus/activities/PluginsFragment.java b/OsmAnd/src/net/osmand/plus/activities/PluginsFragment.java index 783e7791c5..e29139db23 100644 --- a/OsmAnd/src/net/osmand/plus/activities/PluginsFragment.java +++ b/OsmAnd/src/net/osmand/plus/activities/PluginsFragment.java @@ -42,6 +42,8 @@ import net.osmand.plus.settings.fragments.BaseSettingsFragment.SettingsScreenTyp import org.apache.commons.logging.Log; import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; public class PluginsFragment extends BaseOsmAndFragment implements PluginStateListener { @@ -138,6 +140,10 @@ public class PluginsFragment extends BaseOsmAndFragment implements PluginStateLi private void switchEnabled(@NonNull ConnectedApp connectedApp) { app.getAidlApi().switchEnabled(connectedApp); + OsmandPlugin plugin = OsmandPlugin.getPlugin(connectedApp.getPack()); + if (plugin != null) { + OsmandPlugin.enablePlugin(getActivity(), app, plugin, connectedApp.isEnabled()); + } adapter.notifyDataSetChanged(); } @@ -150,8 +156,26 @@ public class PluginsFragment extends BaseOsmAndFragment implements PluginStateLi PluginsListAdapter(Context context) { super(context, R.layout.plugins_list_item, new ArrayList<>()); - addAll(app.getAidlApi().getConnectedApps()); - addAll(OsmandPlugin.getVisiblePlugins()); + addAll(getFilteredPluginsAndApps()); + } + + private List getFilteredPluginsAndApps() { + List connectedApps = app.getAidlApi().getConnectedApps(); + List visiblePlugins = OsmandPlugin.getVisiblePlugins(); + + for (Iterator iterator = visiblePlugins.iterator(); iterator.hasNext(); ) { + OsmandPlugin plugin = iterator.next(); + for (ConnectedApp app : connectedApps) { + if (plugin.getId().equals(app.getPack())) { + iterator.remove(); + } + } + } + List list = new ArrayList<>(); + list.addAll(connectedApps); + list.addAll(visiblePlugins); + + return list; } @NonNull diff --git a/OsmAnd/src/net/osmand/plus/base/MenuBottomSheetDialogFragment.java b/OsmAnd/src/net/osmand/plus/base/MenuBottomSheetDialogFragment.java index 05dbd85340..2af2d9673b 100644 --- a/OsmAnd/src/net/osmand/plus/base/MenuBottomSheetDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/base/MenuBottomSheetDialogFragment.java @@ -16,6 +16,7 @@ import android.view.ViewTreeObserver.OnScrollChangedListener; import android.view.Window; import android.view.WindowManager; import android.widget.LinearLayout; +import android.widget.ScrollView; import androidx.annotation.ColorInt; import androidx.annotation.ColorRes; @@ -192,6 +193,15 @@ public abstract class MenuBottomSheetDialogFragment extends BottomSheetDialogFra }); } + protected ViewTreeObserver.OnGlobalLayoutListener getShadowLayoutListener(){ + return new ViewTreeObserver.OnGlobalLayoutListener() { + @Override + public void onGlobalLayout() { + setShadowOnScrollableView(); + } + }; + } + protected void drawTopShadow(boolean showTopShadow) { final Activity activity = getActivity(); View mainView = getView(); @@ -478,4 +488,15 @@ public abstract class MenuBottomSheetDialogFragment extends BottomSheetDialogFra } }); } + + protected void setShadowOnScrollableView() { + ScrollView scrollView = getView().findViewById(R.id.scroll_view); + boolean isScrollable = scrollView.getChildAt(0).getHeight() >= scrollView.getHeight();; + if (isScrollable) { + drawTopShadow(false); + scrollView.getChildAt(0).setPadding(0,8,0,0); + } else { + drawTopShadow(true); + } + } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/dialogs/WhatsNewDialogFragment.java b/OsmAnd/src/net/osmand/plus/dialogs/WhatsNewDialogFragment.java index 523fdb6416..6225bea95d 100644 --- a/OsmAnd/src/net/osmand/plus/dialogs/WhatsNewDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/dialogs/WhatsNewDialogFragment.java @@ -30,7 +30,7 @@ public class WhatsNewDialogFragment extends DialogFragment { final OsmandApplication osmandApplication = (OsmandApplication) getActivity().getApplication(); final String appVersion = Version.getAppVersion(osmandApplication); builder.setTitle(getString(R.string.whats_new) + " " + appVersion) - .setMessage(getString(R.string.release_3_8)) + .setMessage(getString(R.string.release_3_9)) .setNegativeButton(R.string.shared_string_close, null); if (AppInitializer.LATEST_CHANGES_URL != null) { builder.setPositiveButton(R.string.read_more, new DialogInterface.OnClickListener() { diff --git a/OsmAnd/src/net/osmand/plus/helpers/ExternalApiHelper.java b/OsmAnd/src/net/osmand/plus/helpers/ExternalApiHelper.java index c92438e850..57d6039145 100644 --- a/OsmAnd/src/net/osmand/plus/helpers/ExternalApiHelper.java +++ b/OsmAnd/src/net/osmand/plus/helpers/ExternalApiHelper.java @@ -644,7 +644,7 @@ public class ExternalApiHelper { gpxFile.path = destFile.getAbsolutePath(); } - new SaveGpxAsyncTask(gpxFile, new SaveGpxListener() { + new SaveGpxAsyncTask(new File(gpxFile.path), gpxFile, new SaveGpxListener() { @Override public void gpxSavingStarted() { diff --git a/OsmAnd/src/net/osmand/plus/helpers/GpxUiHelper.java b/OsmAnd/src/net/osmand/plus/helpers/GpxUiHelper.java index 2b91e0a6b7..c2813551e9 100644 --- a/OsmAnd/src/net/osmand/plus/helpers/GpxUiHelper.java +++ b/OsmAnd/src/net/osmand/plus/helpers/GpxUiHelper.java @@ -12,6 +12,7 @@ import android.content.Intent; import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.net.Uri; +import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; import android.text.SpannableString; @@ -63,6 +64,7 @@ import com.github.mikephil.charting.utils.MPPointF; import net.osmand.AndroidUtils; import net.osmand.CallbackWithObject; +import net.osmand.FileUtils; import net.osmand.GPXUtilities; import net.osmand.GPXUtilities.Elevation; import net.osmand.GPXUtilities.GPXFile; @@ -75,30 +77,35 @@ import net.osmand.PlatformUtil; import net.osmand.plus.ContextMenuAdapter; import net.osmand.plus.ContextMenuItem; import net.osmand.plus.GPXDatabase.GpxDataItem; +import net.osmand.plus.GpxDbHelper; import net.osmand.plus.GpxDbHelper.GpxDataItemCallback; -import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem; import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup; +import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem; import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile; import net.osmand.plus.OsmAndConstants; import net.osmand.plus.OsmAndFormatter; import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandPlugin; -import net.osmand.plus.activities.PluginsFragment; -import net.osmand.plus.helpers.enums.MetricsConstants; -import net.osmand.plus.helpers.enums.SpeedConstants; -import net.osmand.plus.settings.backend.CommonPreference; -import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.R; import net.osmand.plus.UiUtilities; import net.osmand.plus.Version; import net.osmand.plus.activities.ActivityResultListener; import net.osmand.plus.activities.ActivityResultListener.OnActivityResultListener; import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.activities.PluginsFragment; import net.osmand.plus.dialogs.ConfigureMapMenu; import net.osmand.plus.dialogs.GpxAppearanceAdapter; 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.routing.RouteCalculationResult; +import net.osmand.plus.settings.backend.CommonPreference; +import net.osmand.plus.settings.backend.OsmandSettings; +import net.osmand.plus.track.GpxSplitType; +import net.osmand.plus.track.GradientScaleType; +import net.osmand.plus.track.SaveGpxAsyncTask; +import net.osmand.plus.track.SaveGpxAsyncTask.SaveGpxListener; import net.osmand.render.RenderingRuleProperty; import net.osmand.render.RenderingRulesStorage; import net.osmand.router.RouteStatisticsHelper; @@ -245,7 +252,7 @@ public class GpxUiHelper { } public static AlertDialog selectGPXFile(final Activity activity, - final boolean showCurrentGpx, final boolean multipleChoice, + final boolean showCurrentGpx, final boolean multipleChoice, final CallbackWithObject callbackWithObject, boolean nightMode) { int dialogThemeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme; OsmandApplication app = (OsmandApplication) activity.getApplication(); @@ -597,15 +604,16 @@ public class GpxUiHelper { if (app != null && showCurrentGpx && adapter.getItem(0).getSelected()) { currentGPX = app.getSavingTrackHelper().getCurrentGpx(); } - List s = new ArrayList<>(); + List fileNames = new ArrayList<>(); for (int i = (showCurrentGpx ? 1 : 0); i < adapter.length(); i++) { if (adapter.getItem(i).getSelected()) { - s.add(list.get(i).getFileName()); + fileNames.add(list.get(i).getFileName()); } } dialog.dismiss(); + updateSelectedTracksAppearance(app, fileNames); loadGPXFileInDifferentThread(activity, callbackWithObject, dir, currentGPX, - s.toArray(new String[0])); + fileNames.toArray(new String[0])); } }); builder.setNegativeButton(R.string.shared_string_cancel, null); @@ -710,6 +718,38 @@ public class GpxUiHelper { return dlg; } + private static void updateSelectedTracksAppearance(OsmandApplication app, List fileNames) { + final GpxDbHelper gpxDbHelper = app.getGpxDbHelper(); + final boolean showStartFinish = app.getSettings().SHOW_START_FINISH_ICONS.get(); + final String savedWidth = app.getSettings().getCustomRenderProperty(CURRENT_TRACK_WIDTH_ATTR).get(); + String savedColor = app.getSettings().getCustomRenderProperty(CURRENT_TRACK_COLOR_ATTR).get(); + final int color = GpxAppearanceAdapter.parseTrackColor(app.getRendererRegistry().getCurrentSelectedRenderer(), savedColor); + + GpxDataItemCallback callback = new GpxDataItemCallback() { + @Override + public boolean isCancelled() { + return false; + } + + @Override + public void onGpxDataItemReady(GpxDataItem item) { + updateTrackAppearance(gpxDbHelper, item, savedWidth, color, showStartFinish); + } + }; + for (String name : fileNames) { + GpxDataItem item = gpxDbHelper.getItem(new File(app.getAppPath(IndexConstants.GPX_INDEX_DIR), name), callback); + if (item != null) { + updateTrackAppearance(gpxDbHelper, item, savedWidth, color, showStartFinish); + } + } + } + + private static void updateTrackAppearance(GpxDbHelper gpxDbHelper, GpxDataItem item, String width, int color, boolean showStartFinish) { + gpxDbHelper.updateColor(item, color); + gpxDbHelper.updateWidth(item, width); + gpxDbHelper.updateShowStartFinish(item, showStartFinish); + } + public static void updateGpxInfoView(View v, String itemTitle, GPXInfo info, GpxDataItem dataItem, boolean currentlyRecordingTrack, OsmandApplication app) { TextView viewName = ((TextView) v.findViewById(R.id.name)); viewName.setText(itemTitle.replace("/", " • ").trim()); @@ -808,11 +848,9 @@ public class GpxUiHelper { View apprTitleView, String prefWidthValue, String prefColorValue) { - TextView widthTextView = (TextView) apprTitleView.findViewById(R.id.widthTitle); - ImageView colorImageView = (ImageView) apprTitleView.findViewById(R.id.colorImage); - if (Algorithms.isEmpty(prefWidthValue)) { - widthTextView.setText(AndroidUtils.getRenderingStringPropertyValue(activity, trackWidthProp.getDefaultValueDescription())); - } else { + TextView widthTextView = apprTitleView.findViewById(R.id.widthTitle); + ImageView colorImageView = apprTitleView.findViewById(R.id.colorImage); + if (!Algorithms.isEmpty(prefWidthValue)) { widthTextView.setText(AndroidUtils.getRenderingStringPropertyValue(activity, prefWidthValue)); } int color = GpxAppearanceAdapter.parseTrackColor(renderer, prefColorValue); @@ -2133,6 +2171,90 @@ public class GpxUiHelper { return gpxItem; } + public static void saveAndShareGpx(@NonNull final Context context, @NonNull final GPXFile gpxFile) { + OsmandApplication app = (OsmandApplication) context.getApplicationContext(); + File tempDir = FileUtils.getTempDir(app); + String fileName = Algorithms.getFileWithoutDirs(gpxFile.path); + final File file = new File(tempDir, fileName); + SaveGpxListener listener = new SaveGpxListener() { + @Override + public void gpxSavingStarted() { + + } + + @Override + public void gpxSavingFinished(Exception errorMessage) { + if (errorMessage == null) { + shareGpx(context, file); + } + } + }; + new SaveGpxAsyncTask(file, gpxFile, listener).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); + if (dataItem != null) { + addAppearanceToGpx(gpxFile, dataItem); + saveAndShareGpx(app, gpxFile); + } + } + + private static GpxDataItem getDataItem(@NonNull final OsmandApplication app, @NonNull final GPXFile gpxFile) { + GpxDataItemCallback itemCallback = new GpxDataItemCallback() { + @Override + public boolean isCancelled() { + return false; + } + + @Override + public void onGpxDataItemReady(GpxDataItem item) { + addAppearanceToGpx(gpxFile, item); + saveAndShareGpx(app, gpxFile); + } + }; + return app.getGpxDbHelper().getItem(new File(gpxFile.path), itemCallback); + } + + private static void addAppearanceToGpx(@NonNull GPXFile gpxFile, @NonNull GpxDataItem dataItem) { + gpxFile.setShowArrows(dataItem.isShowArrows()); + gpxFile.setShowStartFinish(dataItem.isShowStartFinish()); + gpxFile.setSplitInterval(dataItem.getSplitInterval()); + gpxFile.setSplitType(GpxSplitType.getSplitTypeByTypeId(dataItem.getSplitType()).getTypeName()); + if (dataItem.getColor() != 0) { + gpxFile.setColor(dataItem.getColor()); + } + if (dataItem.getWidth() != null) { + gpxFile.setWidth(dataItem.getWidth()); + } + if (dataItem.getGradientSpeedColor() != 0) { + gpxFile.setGradientScaleColor(GradientScaleType.SPEED.getColorTypeName(), dataItem.getGradientSpeedColor()); + } + if (dataItem.getGradientSlopeColor() != 0) { + gpxFile.setGradientScaleColor(GradientScaleType.SLOPE.getColorTypeName(), dataItem.getGradientSlopeColor()); + } + if (dataItem.getGradientAltitudeColor() != 0) { + gpxFile.setGradientScaleColor(GradientScaleType.ALTITUDE.getColorTypeName(), dataItem.getGradientAltitudeColor()); + } + if (dataItem.getGradientScaleType() != null) { + gpxFile.setGradientScaleType(dataItem.getGradientScaleType().name()); + } + } + + public static void shareGpx(@NonNull Context context, @NonNull File file) { + Uri fileUri = AndroidUtils.getUriForFile(context, file); + Intent sendIntent = new Intent(Intent.ACTION_SEND); + sendIntent.putExtra(Intent.EXTRA_STREAM, fileUri); + sendIntent.setType("application/gpx+xml"); + sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + if (context instanceof OsmandApplication) { + sendIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + } + if (AndroidUtils.isIntentSafe(context, sendIntent)) { + context.startActivity(sendIntent); + } + } public static class GPXInfo { private String fileName; diff --git a/OsmAnd/src/net/osmand/plus/importfiles/ImportHelper.java b/OsmAnd/src/net/osmand/plus/importfiles/ImportHelper.java index c7cad00b0c..a46ae659b8 100644 --- a/OsmAnd/src/net/osmand/plus/importfiles/ImportHelper.java +++ b/OsmAnd/src/net/osmand/plus/importfiles/ImportHelper.java @@ -70,6 +70,7 @@ import static net.osmand.plus.myplaces.FavoritesActivity.GPX_TAB; import static net.osmand.plus.myplaces.FavoritesActivity.TAB_ID; import static net.osmand.plus.settings.backend.backup.SettingsHelper.REPLACE_KEY; import static net.osmand.plus.settings.backend.backup.SettingsHelper.SETTINGS_TYPE_LIST_KEY; +import static net.osmand.plus.settings.backend.backup.SettingsHelper.SILENT_IMPORT_KEY; /** * @author Koen Rabaey @@ -210,7 +211,7 @@ public class ImportHelper { public static String getNameFromContentUri(OsmandApplication app, Uri contentUri) { try { String name; - Cursor returnCursor = app.getContentResolver().query(contentUri, new String[]{OpenableColumns.DISPLAY_NAME}, null, null, null); + Cursor returnCursor = app.getContentResolver().query(contentUri, new String[] {OpenableColumns.DISPLAY_NAME}, null, null, null); if (returnCursor != null && returnCursor.moveToFirst()) { int columnIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME); if (columnIndex != -1) { @@ -267,6 +268,7 @@ public class ImportHelper { int version = extras.getInt(SettingsHelper.SETTINGS_VERSION_KEY, -1); String latestChanges = extras.getString(SettingsHelper.SETTINGS_LATEST_CHANGES_KEY); boolean replace = extras.getBoolean(REPLACE_KEY); + boolean silentImport = extras.getBoolean(SILENT_IMPORT_KEY); ArrayList settingsTypeKeys = extras.getStringArrayList(SETTINGS_TYPE_LIST_KEY); List settingsTypes = null; if (settingsTypeKeys != null) { @@ -275,18 +277,18 @@ public class ImportHelper { settingsTypes.add(ExportSettingsType.valueOf(key)); } } - handleOsmAndSettingsImport(intentUri, fileName, settingsTypes, replace, latestChanges, version, callback); + handleOsmAndSettingsImport(intentUri, fileName, settingsTypes, replace, silentImport, latestChanges, version, callback); } else { - handleOsmAndSettingsImport(intentUri, fileName, null, false, null, -1, + handleOsmAndSettingsImport(intentUri, fileName, null, false, false, null, -1, callback); } } protected void handleOsmAndSettingsImport(Uri uri, String name, final List settingsTypes, - final boolean replace, String latestChanges, int version, - CallbackWithObject> callback) { - executeImportTask(new SettingsImportTask(activity, uri, name, settingsTypes, replace, latestChanges, version, - callback)); + final boolean replace, boolean silentImport, String latestChanges, int version, + CallbackWithObject> callback) { + executeImportTask(new SettingsImportTask(activity, uri, name, settingsTypes, replace, silentImport, + latestChanges, version, callback)); } protected void handleXmlFileImport(Uri intentUri, String fileName, CallbackWithObject routingCallback) { diff --git a/OsmAnd/src/net/osmand/plus/importfiles/SettingsImportTask.java b/OsmAnd/src/net/osmand/plus/importfiles/SettingsImportTask.java index 75c8d55015..34119b0bb5 100644 --- a/OsmAnd/src/net/osmand/plus/importfiles/SettingsImportTask.java +++ b/OsmAnd/src/net/osmand/plus/importfiles/SettingsImportTask.java @@ -17,10 +17,9 @@ import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.base.BaseLoadAsyncTask; import net.osmand.plus.settings.backend.ExportSettingsType; +import net.osmand.plus.settings.backend.backup.PluginSettingsItem; import net.osmand.plus.settings.backend.backup.SettingsHelper; import net.osmand.plus.settings.backend.backup.SettingsHelper.CheckDuplicatesListener; -import net.osmand.plus.settings.backend.backup.PluginSettingsItem; -import net.osmand.plus.settings.backend.backup.ProfileSettingsItem; import net.osmand.plus.settings.backend.backup.SettingsHelper.SettingsCollectListener; import net.osmand.plus.settings.backend.backup.SettingsHelper.SettingsImportListener; import net.osmand.plus.settings.backend.backup.SettingsItem; @@ -42,19 +41,21 @@ class SettingsImportTask extends BaseLoadAsyncTask { private String name; private List settingsTypes; private boolean replace; + private boolean silentImport; private String latestChanges; private int version; private CallbackWithObject> callback; public SettingsImportTask(@NonNull FragmentActivity activity, @NonNull Uri uri, - @NonNull String name, List settingsTypes, - boolean replace, String latestChanges, int version, - CallbackWithObject> callback) { + @NonNull String name, List settingsTypes, + boolean replace, boolean silentImport, String latestChanges, int version, + CallbackWithObject> callback) { super(activity); this.uri = uri; this.name = name; this.settingsTypes = settingsTypes; this.replace = replace; + this.silentImport = silentImport; this.latestChanges = latestChanges; this.version = version; this.callback = callback; @@ -93,13 +94,13 @@ class SettingsImportTask extends BaseLoadAsyncTask { if (!pluginIndependentItems.isEmpty()) { if (settingsTypes == null) { FragmentActivity activity = activityRef.get(); - if (activity != null) { + if (!silentImport && activity != null) { FragmentManager fragmentManager = activity.getSupportFragmentManager(); ImportSettingsFragment.showInstance(fragmentManager, pluginIndependentItems, file); } } else { Map> allSettingsMap = getSettingsToOperate(pluginIndependentItems, false); - List settingsList = settingsHelper.getFilteredSettingsItems(allSettingsMap, settingsTypes); + List settingsList = settingsHelper.getFilteredSettingsItems(allSettingsMap, settingsTypes, false); settingsHelper.checkDuplicates(file, settingsList, settingsList, getDuplicatesListener(file, replace)); } } @@ -141,7 +142,7 @@ class SettingsImportTask extends BaseLoadAsyncTask { ((MapActivity) activity).getMapLayers().getMapWidgetRegistry().updateVisibleWidgets(); ((MapActivity) activity).updateApplicationModeSettings(); } - if (file != null && activity != null) { + if (!silentImport && file != null && activity != null) { FragmentManager fm = activity.getSupportFragmentManager(); ImportCompleteFragment.showInstance(fm, items, file.getName()); } @@ -174,11 +175,6 @@ class SettingsImportTask extends BaseLoadAsyncTask { CustomOsmandPlugin plugin = pluginItem.getPlugin(); plugin.loadResources(); - for (SettingsItem item : items) { - if (item instanceof ProfileSettingsItem) { - ((ProfileSettingsItem) item).applyAdditionalPrefs(); - } - } if (!Algorithms.isEmpty(plugin.getDownloadMaps())) { app.getDownloadThread().runReloadIndexFilesSilent(); } @@ -188,11 +184,14 @@ class SettingsImportTask extends BaseLoadAsyncTask { if (!Algorithms.isEmpty(plugin.getRouterNames())) { loadRoutingFiles(app, null); } - if (activity != null) { + if (!silentImport && activity != null) { plugin.onInstall(app, activity); } String pluginId = pluginItem.getPluginId(); - File pluginDir = new File(app.getAppPath(null), IndexConstants.PLUGINS_DIR + pluginId); + File pluginDir = app.getAppPath(IndexConstants.PLUGINS_DIR + pluginId); + if (!pluginDir.exists()) { + pluginDir.mkdirs(); + } app.getSettingsHelper().exportSettings(pluginDir, "items", null, items, false); } }; diff --git a/OsmAnd/src/net/osmand/plus/importfiles/ZipImportTask.java b/OsmAnd/src/net/osmand/plus/importfiles/ZipImportTask.java index afdb7a32f2..a086db3e6b 100644 --- a/OsmAnd/src/net/osmand/plus/importfiles/ZipImportTask.java +++ b/OsmAnd/src/net/osmand/plus/importfiles/ZipImportTask.java @@ -86,7 +86,7 @@ public class ZipImportTask extends BaseLoadAsyncTask { } else if (importType == ImportType.SETTINGS) { String name = createUniqueFileName(app, "settings", TEMP_DIR, OSMAND_SETTINGS_FILE_EXT); importHelper.handleOsmAndSettingsImport(uri, name + OSMAND_SETTINGS_FILE_EXT, - null, false, null, -1, null); + null, false, false, null, -1, null); } } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuBuilder.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuBuilder.java index 503e52ecf0..3a34e262fc 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuBuilder.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuBuilder.java @@ -412,7 +412,7 @@ public class MenuBuilder { } }); //TODO This feature is under development - if (!OsmandPlugin.isDevelopment()) { + if (!Version.isDeveloperVersion(app)) { view.setVisibility(View.GONE); } photoButton = view; diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/SelectedGpxMenuController.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/SelectedGpxMenuController.java index 26e2a136c8..f2895d6c10 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/SelectedGpxMenuController.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/SelectedGpxMenuController.java @@ -1,10 +1,8 @@ package net.osmand.plus.mapcontextmenu.controllers; import android.app.ProgressDialog; -import android.content.Context; import android.content.Intent; import android.graphics.drawable.Drawable; -import android.net.Uri; import android.os.AsyncTask; import androidx.annotation.NonNull; @@ -39,7 +37,7 @@ public class SelectedGpxMenuController extends MenuController { private SelectedGpxPoint selectedGpxPoint; public SelectedGpxMenuController(@NonNull final MapActivity mapActivity, @NonNull PointDescription pointDescription, - @NonNull final SelectedGpxPoint selectedGpxPoint) { + @NonNull final SelectedGpxPoint selectedGpxPoint) { super(new SelectedGpxMenuBuilder(mapActivity, selectedGpxPoint), pointDescription, mapActivity); this.selectedGpxPoint = selectedGpxPoint; builder.setShowOnlinePhotos(false); @@ -209,24 +207,11 @@ public class SelectedGpxMenuController extends MenuController { if (mapActivity != null && selectedGpxPoint != null) { final GPXFile gpxFile = selectedGpxPoint.getSelectedGpxFile().getGpxFile(); if (gpxFile != null) { + OsmandApplication app = mapActivity.getMyApplication(); if (Algorithms.isEmpty(gpxFile.path)) { - SaveGpxListener saveGpxListener = new SaveGpxListener() { - @Override - public void gpxSavingStarted() { - - } - - @Override - public void gpxSavingFinished(Exception errorMessage) { - MapActivity mapActivity = getMapActivity(); - if (mapActivity != null) { - shareGpx(mapActivity, gpxFile.path); - } - } - }; - new SaveCurrentTrackTask(mapActivity.getMyApplication(), gpxFile, saveGpxListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + saveAndShareCurrentGpx(app, gpxFile); } else { - shareGpx(mapActivity, gpxFile.path); + GpxUiHelper.saveAndShareGpxWithAppearance(app, gpxFile); } } } else { @@ -234,15 +219,21 @@ public class SelectedGpxMenuController extends MenuController { } } - private void shareGpx(@NonNull Context context, @NonNull String path) { - final Uri fileUri = AndroidUtils.getUriForFile(context, new File(path)); - final Intent sendIntent = new Intent(Intent.ACTION_SEND); - sendIntent.putExtra(Intent.EXTRA_STREAM, fileUri); - sendIntent.setType("application/gpx+xml"); - sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - if (AndroidUtils.isIntentSafe(context, sendIntent)) { - context.startActivity(sendIntent); - } + 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 { diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/WptPtEditorFragment.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/WptPtEditorFragment.java index eaf3cc994b..f5ef3033c8 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/WptPtEditorFragment.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/WptPtEditorFragment.java @@ -30,6 +30,7 @@ import net.osmand.plus.track.SaveGpxAsyncTask; import net.osmand.plus.track.SaveGpxAsyncTask.SaveGpxListener; import net.osmand.util.Algorithms; +import java.io.File; import java.util.Map; public class WptPtEditorFragment extends PointEditorFragment { @@ -379,7 +380,7 @@ public class WptPtEditorFragment extends PointEditorFragment { } private void saveGpx(final OsmandApplication app, final GPXFile gpxFile, final boolean gpxSelected) { - new SaveGpxAsyncTask(gpxFile, new SaveGpxListener() { + new SaveGpxAsyncTask(new File(gpxFile.path), gpxFile, new SaveGpxListener() { @Override public void gpxSavingStarted() { diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/WptPtEditorFragmentNew.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/WptPtEditorFragmentNew.java index c973009798..c948b5414e 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/WptPtEditorFragmentNew.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/WptPtEditorFragmentNew.java @@ -34,6 +34,7 @@ import net.osmand.plus.track.SaveGpxAsyncTask; import net.osmand.plus.track.SaveGpxAsyncTask.SaveGpxListener; import net.osmand.util.Algorithms; +import java.io.File; import java.util.List; import java.util.Map; import java.util.Set; @@ -482,7 +483,7 @@ public class WptPtEditorFragmentNew extends PointEditorFragmentNew { } private void saveGpx(final OsmandApplication app, final GPXFile gpxFile, final boolean gpxSelected) { - new SaveGpxAsyncTask(gpxFile, new SaveGpxListener() { + new SaveGpxAsyncTask(new File(gpxFile.path), gpxFile, new SaveGpxListener() { @Override public void gpxSavingStarted() { diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/other/TrackDetailsMenu.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/other/TrackDetailsMenu.java index f1be5a9fad..94811ff241 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/other/TrackDetailsMenu.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/other/TrackDetailsMenu.java @@ -473,6 +473,10 @@ public class TrackDetailsMenu { } public void refreshChart(LineChart chart, boolean forceFit) { + refreshChart(chart, true, forceFit); + } + + public void refreshChart(LineChart chart, boolean fitTrackOnMap, boolean forceFit) { MapActivity mapActivity = getMapActivity(); GpxDisplayItem gpxItem = getGpxItem(); if (mapActivity == null || gpxItem == null) { @@ -529,7 +533,9 @@ public class TrackDetailsMenu { if (location != null) { mapActivity.refreshMap(); } - fitTrackOnMap(chart, location, forceFit); + if (fitTrackOnMap) { + fitTrackOnMap(chart, location, forceFit); + } } public boolean shouldShowXAxisPoints () { diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/GraphsCard.java b/OsmAnd/src/net/osmand/plus/measurementtool/GraphsCard.java index ef376f48fd..deb636420a 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/GraphsCard.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/GraphsCard.java @@ -311,7 +311,7 @@ public class GraphsCard extends BaseCard implements OnUpdateInfoListener { private void updateChartOnMap() { if (hasVisibleGraph()) { trackDetailsMenu.reset(); - refreshMapCallback.refreshMap(false); + refreshMapCallback.refreshMap(false, false); } } diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementEditingContext.java b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementEditingContext.java index 6c3411b004..9ce68686de 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementEditingContext.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementEditingContext.java @@ -296,29 +296,8 @@ public class MeasurementEditingContext { return !newData && hasDefaultPointsOnly && getPoints().size() > 2; } - public boolean isSelectionNeedApproximation() { - boolean hasDefaultPointsOnly = false; - boolean newData = isNewData(); - if (!newData && selectedPointPosition != -1) { - WptPt selectedPoint = getPoints().get(selectedPointPosition); - List segments = getBeforeSegments(); - List points = null; - for (TrkSegment segment : segments) { - if (segment.points.contains(selectedPoint)) { - points = segment.points; - } - } - if (!Algorithms.isEmpty(points)) { - hasDefaultPointsOnly = true; - for (WptPt point : points) { - if (point.hasProfile()) { - hasDefaultPointsOnly = false; - break; - } - } - } - } - return !newData && hasDefaultPointsOnly && getPoints().size() > 2; + public boolean isAddNewSegmentAllowed() { + return beforeSegments.size() > 0 && beforeSegments.get(beforeSegments.size() - 1).points.size() >= 2; } public void clearSnappedToRoadPoints() { @@ -430,13 +409,19 @@ public class MeasurementEditingContext { if (position > 0 && position <= points.size()) { WptPt prevPt = points.get(position - 1); if (prevPt.isGap()) { - point.setGap(); - if (position > 1) { - WptPt pt = points.get(position - 2); - if (pt.hasProfile()) { - prevPt.setProfileType(pt.getProfileType()); - } else { - prevPt.removeProfileType(); + if (position == points.size() && getAfterPoints().size() == 0) { + if (appMode != MeasurementEditingContext.DEFAULT_APP_MODE) { + point.setProfileType(appMode.getStringKey()); + } + } else { + point.setGap(); + if (position > 1) { + WptPt pt = points.get(position - 2); + if (pt.hasProfile()) { + prevPt.setProfileType(pt.getProfileType()); + } else { + prevPt.removeProfileType(); + } } } } else if (prevPt.hasProfile()) { @@ -540,6 +525,45 @@ public class MeasurementEditingContext { clearAfterSegments(); } + public void splitPoints(int selectedPointPosition, boolean after) { + int pointIndex = after ? selectedPointPosition : selectedPointPosition - 1; + if (pointIndex >= 0 && pointIndex < before.points.size()) { + WptPt point = before.points.get(pointIndex); + WptPt nextPoint = before.points.size() > pointIndex + 1 ? before.points.get(pointIndex + 1) : null; + WptPt newPoint = new WptPt(point); + newPoint.copyExtensions(point); + newPoint.setGap(); + before.points.remove(pointIndex); + before.points.add(pointIndex, newPoint); + if (newPoint != null) { + roadSegmentData.remove(new Pair<>(point, nextPoint)); + } + updateSegmentsForSnap(false); + } + } + + public void joinPoints(int selectedPointPosition) { + WptPt gapPoint = null; + int gapIndex = -1; + if (isFirstPointSelected(selectedPointPosition, false)) { + if (selectedPointPosition - 1 >= 0) { + gapPoint = before.points.get(selectedPointPosition - 1); + gapIndex = selectedPointPosition - 1; + } + } else if (isLastPointSelected(selectedPointPosition, false)) { + gapPoint = before.points.get(selectedPointPosition); + gapIndex = selectedPointPosition; + } + if (gapPoint != null) { + WptPt newPoint = new WptPt(gapPoint); + newPoint.copyExtensions(gapPoint); + newPoint.removeProfileType(); + before.points.remove(gapIndex); + before.points.add(gapIndex, newPoint); + updateSegmentsForSnap(false); + } + } + public void clearSegments() { clearBeforeSegments(); clearAfterSegments(); @@ -560,15 +584,43 @@ public class MeasurementEditingContext { } } - public boolean isFirstPointSelected() { - return isBorderPointSelected(true); + public boolean canSplit(boolean after) { + WptPt selectedPoint = getPoints().get(selectedPointPosition); + List segments = getBeforeSegments(); + for (TrkSegment segment : segments) { + int i = segment.points.indexOf(selectedPoint); + if (i != -1) { + return after ? i < segment.points.size() - 2 : i > 1; + } + } + return false; } - public boolean isLastPointSelected() { - return isBorderPointSelected(false); + public boolean isFirstPointSelected(boolean outer) { + return isFirstPointSelected(selectedPointPosition, outer); } - private boolean isBorderPointSelected(boolean first) { + public boolean isFirstPointSelected(int selectedPointPosition, boolean outer) { + if (outer) { + return selectedPointPosition == 0; + } else { + return isBorderPointSelected(selectedPointPosition, true); + } + } + + public boolean isLastPointSelected(boolean outer) { + return isLastPointSelected(selectedPointPosition, outer); + } + + public boolean isLastPointSelected(int selectedPointPosition, boolean outer) { + if (outer) { + return selectedPointPosition == getPoints().size() - 1; + } else { + return isBorderPointSelected(selectedPointPosition, false); + } + } + + private boolean isBorderPointSelected(int selectedPointPosition, boolean first) { WptPt selectedPoint = getPoints().get(selectedPointPosition); List segments = getBeforeSegments(); int count = 0; @@ -738,7 +790,7 @@ public class MeasurementEditingContext { pairPoints.add(points.get(j)); prevPointIndex = j; } - if (points.size() > prevPointIndex + 1) { + if (points.size() > prevPointIndex + 1 && i == routePoints.size() - 2) { pairPoints.add(points.get(prevPointIndex + 1)); } Iterator it = routeSegments.iterator(); diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java index db5a66cdce..f56eab9797 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java @@ -22,6 +22,7 @@ import androidx.activity.OnBackPressedCallback; import androidx.annotation.DrawableRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.appcompat.content.res.AppCompatResources; import androidx.core.content.ContextCompat; import androidx.core.widget.TextViewCompat; import androidx.fragment.app.FragmentManager; @@ -64,10 +65,13 @@ import net.osmand.plus.measurementtool.command.ApplyGpxApproximationCommand; import net.osmand.plus.measurementtool.command.ChangeRouteModeCommand; import net.osmand.plus.measurementtool.command.ChangeRouteModeCommand.ChangeRouteType; import net.osmand.plus.measurementtool.command.ClearPointsCommand; +import net.osmand.plus.measurementtool.command.JoinPointsCommand; import net.osmand.plus.measurementtool.command.MovePointCommand; import net.osmand.plus.measurementtool.command.RemovePointCommand; import net.osmand.plus.measurementtool.command.ReorderPointCommand; import net.osmand.plus.measurementtool.command.ReversePointsCommand; +import net.osmand.plus.routepreparationmenu.RouteOptionsBottomSheet; +import net.osmand.plus.measurementtool.command.SplitPointsCommand; import net.osmand.plus.routepreparationmenu.cards.BaseCard; import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.settings.backend.OsmandSettings; @@ -76,8 +80,8 @@ import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarControll import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarControllerType; import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarView; import net.osmand.plus.widgets.MultiStateToggleButton; -import net.osmand.plus.widgets.MultiStateToggleButton.RadioItem; import net.osmand.plus.widgets.MultiStateToggleButton.OnRadioItemClickListener; +import net.osmand.plus.widgets.MultiStateToggleButton.RadioItem; import net.osmand.router.RoutePlannerFrontEnd.GpxRouteApproximation; import net.osmand.util.Algorithms; @@ -230,7 +234,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route return null; } final MeasurementToolLayer measurementLayer = mapActivity.getMapLayers().getMeasurementToolLayer(); - OsmandApplication app = mapActivity.getMyApplication(); + final OsmandApplication app = mapActivity.getMyApplication(); editingCtx.setApplication(mapActivity.getMyApplication()); editingCtx.setProgressListener(new SnapToRoadProgressListener() { @@ -368,9 +372,10 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route @Override public void onClick(View view) { boolean trackSnappedToRoad = !editingCtx.isApproximationNeeded(); + boolean addNewSegmentAllowed = editingCtx.isAddNewSegmentAllowed(); OptionsBottomSheetDialogFragment.showInstance(mapActivity.getSupportFragmentManager(), MeasurementToolFragment.this, - trackSnappedToRoad, + trackSnappedToRoad, addNewSegmentAllowed, editingCtx.getAppMode().getStringKey() ); } @@ -432,7 +437,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route @Override public void onMeasure(float distance, float bearing) { String distStr = OsmAndFormatter.getFormattedDistance(distance, mapActivity.getMyApplication()); - String azimuthStr = OsmAndFormatter.getFormattedAzimuth(bearing, getMyApplication()); + String azimuthStr = OsmAndFormatter.getFormattedAzimuth(bearing, app); distanceToCenterTv.setText(String.format("%1$s • %2$s", distStr, azimuthStr)); TextViewCompat.setAutoSizeTextTypeUniformWithConfiguration( distanceToCenterTv, 14, 18, 2, @@ -496,7 +501,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route final GpxData gpxData = editingCtx.getGpxData(); - ImageButton snapToRoadBtn = (ImageButton) mapActivity.findViewById(R.id.snap_to_road_image_button); + ImageButton snapToRoadBtn = mapActivity.findViewById(R.id.snap_to_road_image_button); snapToRoadBtn.setBackgroundResource(nightMode ? R.drawable.btn_circle_night : R.drawable.btn_circle); snapToRoadBtn.setOnClickListener(new OnClickListener() { @Override @@ -505,6 +510,31 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route } }); snapToRoadBtn.setVisibility(View.VISIBLE); + LinearLayout profileWithConfig = mapActivity.findViewById(R.id.profile_with_config_btn); + + View background = profileWithConfig.findViewById(R.id.btn_background); + AndroidUtils.setBackground(background, AppCompatResources.getDrawable(view.getContext(), + AndroidUtils.resolveAttribute(view.getContext(), R.attr.bg_round_btn))); + View divider = profileWithConfig.findViewById(R.id.divider); + divider.setBackgroundResource(AndroidUtils.resolveAttribute(view.getContext(), R.attr.divider_color)); + ImageButton profileBtn = profileWithConfig.findViewById(R.id.profile); + profileBtn.setBackgroundResource(nightMode ? R.drawable.btn_circle_night_no_shadow : R.drawable.btn_circle_no_shadow); + profileBtn.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View view) { + startSnapToRoad(false); + } + }); + ImageButton configBtn = profileWithConfig.findViewById(R.id.profile_config); + configBtn.setBackgroundResource(nightMode ? R.drawable.btn_circle_night_no_shadow : R.drawable.btn_circle_no_shadow); + configBtn.setImageDrawable(getContentIcon(R.drawable.ic_action_settings)); + configBtn.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + RouteOptionsBottomSheet.showInstance(mapActivity.getSupportFragmentManager(), + editingCtx.getAppMode().getStringKey()); + } + }); initMeasurementMode(gpxData, savedInstanceState == null); @@ -829,6 +859,11 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route startSnapToRoad(true); } + @Override + public void addNewSegmentOnClick() { + onSplitPointsAfter(); + } + @Override public void directionsOnClick() { MapActivity mapActivity = getMapActivity(); @@ -1012,6 +1047,39 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route trimRoute(AFTER); } + @Override + public void onSplitPointsAfter() { + MeasurementToolLayer measurementLayer = getMeasurementLayer(); + editingCtx.getCommandManager().execute(new SplitPointsCommand(measurementLayer, true)); + collapseInfoViewIfExpanded(); + editingCtx.setSelectedPointPosition(-1); + updateUndoRedoButton(false, redoBtn); + updateUndoRedoButton(true, undoBtn); + updateDistancePointsText(); + } + + @Override + public void onSplitPointsBefore() { + MeasurementToolLayer measurementLayer = getMeasurementLayer(); + editingCtx.getCommandManager().execute(new SplitPointsCommand(measurementLayer, false)); + collapseInfoViewIfExpanded(); + editingCtx.setSelectedPointPosition(-1); + updateUndoRedoButton(false, redoBtn); + updateUndoRedoButton(true, undoBtn); + updateDistancePointsText(); + } + + @Override + public void onJoinPoints() { + MeasurementToolLayer measurementLayer = getMeasurementLayer(); + editingCtx.getCommandManager().execute(new JoinPointsCommand(measurementLayer)); + collapseInfoViewIfExpanded(); + editingCtx.setSelectedPointPosition(-1); + updateUndoRedoButton(false, redoBtn); + updateUndoRedoButton(true, undoBtn); + updateDistancePointsText(); + } + private void trimRoute(ClearCommandMode before) { MeasurementToolLayer measurementLayer = getMeasurementLayer(); editingCtx.getCommandManager().execute(new ClearPointsCommand(measurementLayer, before)); @@ -1251,17 +1319,24 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route final ApplicationMode appMode = editingCtx.getAppMode(); if (mapActivity != null) { Drawable icon; + ImageButton snapToRoadBtn = mapActivity.findViewById(R.id.snap_to_road_image_button); + LinearLayout profileWithConfig = mapActivity.findViewById(R.id.profile_with_config_btn); + ImageButton configBtn = profileWithConfig.findViewById(R.id.profile); if (isTrackReadyToCalculate()) { if (appMode == MeasurementEditingContext.DEFAULT_APP_MODE) { icon = getActiveIcon(R.drawable.ic_action_split_interval); + snapToRoadBtn.setVisibility(View.VISIBLE); + profileWithConfig.setVisibility(View.GONE); } else { icon = getIcon(appMode.getIconRes(), appMode.getIconColorInfo().getColor(nightMode)); + snapToRoadBtn.setVisibility(View.GONE); + profileWithConfig.setVisibility(View.VISIBLE); } } else { icon = getContentIcon(R.drawable.ic_action_help); } - ImageButton snapToRoadBtn = (ImageButton) mapActivity.findViewById(R.id.snap_to_road_image_button); snapToRoadBtn.setImageDrawable(icon); + configBtn.setImageDrawable(icon); mapActivity.refreshMap(); } } @@ -1274,6 +1349,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route MapActivity mapActivity = getMapActivity(); if (mapActivity != null) { mapActivity.findViewById(R.id.snap_to_road_image_button).setVisibility(View.GONE); + mapActivity.findViewById(R.id.profile_with_config_btn).setVisibility(View.GONE); } } diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolLayer.java b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolLayer.java index cad4985d38..3c6bcf6c89 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolLayer.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolLayer.java @@ -328,7 +328,7 @@ public class MeasurementToolLayer extends OsmandMapLayer implements ContextMenuL hasPointsBefore = true; WptPt pt = segment.points.get(segment.points.size() - 1); hasGapBefore = pt.isGap(); - if (!pt.isGap() || !editingCtx.isInAddPointBeforeMode()) { + if (!pt.isGap() || (editingCtx.isInAddPointMode() && !editingCtx.isInAddPointBeforeMode())) { float locX = tb.getPixXFromLatLon(pt.lat, pt.lon); float locY = tb.getPixYFromLatLon(pt.lat, pt.lon); tx.add(locX); @@ -345,7 +345,7 @@ public class MeasurementToolLayer extends OsmandMapLayer implements ContextMenuL tx.add((float) tb.getCenterPixelX()); ty.add((float) tb.getCenterPixelY()); } - if (!hasGapBefore || editingCtx.isInAddPointBeforeMode()) { + if (!hasGapBefore || (editingCtx.isInAddPointMode() && editingCtx.isInAddPointBeforeMode())) { WptPt pt = segment.points.get(0); float locX = tb.getPixXFromLatLon(pt.lat, pt.lon); float locY = tb.getPixYFromLatLon(pt.lat, pt.lon); diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/OptionsBottomSheetDialogFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/OptionsBottomSheetDialogFragment.java index 0a9c690a1e..f286a814b3 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/OptionsBottomSheetDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/OptionsBottomSheetDialogFragment.java @@ -15,6 +15,7 @@ import net.osmand.PlatformUtil; import net.osmand.plus.R; import net.osmand.plus.base.MenuBottomSheetDialogFragment; import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem; +import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithDescription; import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithDescriptionDifHeight; import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem; import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem; @@ -29,6 +30,7 @@ public class OptionsBottomSheetDialogFragment extends MenuBottomSheetDialogFragm public static final String TRACK_SNAPPED_TO_ROAD_KEY = "track_snapped_to_road"; public static final String SNAP_TO_ROAD_APP_MODE_KEY = "snap_to_road_app_mode"; + public static final String ADD_NEW_SEGMENT_ALLOWED_KEY = "add_new_segment_allowed"; private ApplicationMode routeAppMode; @@ -36,8 +38,10 @@ public class OptionsBottomSheetDialogFragment extends MenuBottomSheetDialogFragm public void createMenuItems(Bundle savedInstanceState) { Bundle args = getArguments(); boolean trackSnappedToRoad = false; + boolean addNewSegmentAllowed = false; if (args != null) { trackSnappedToRoad = args.getBoolean(TRACK_SNAPPED_TO_ROAD_KEY); + addNewSegmentAllowed = args.getBoolean(ADD_NEW_SEGMENT_ALLOWED_KEY); routeAppMode = ApplicationMode.valueOfStringKey(args.getString(SNAP_TO_ROAD_APP_MODE_KEY), null); } @@ -78,6 +82,25 @@ public class OptionsBottomSheetDialogFragment extends MenuBottomSheetDialogFragm items.add(snapToRoadItem); + if (addNewSegmentAllowed) { + BaseBottomSheetItem addNewSegment = new BottomSheetItemWithDescription.Builder() + //.setIcon(getContentIcon(R.drawable.ic_action_trim_right)) + .setTitle(getString(R.string.plan_route_add_new_segment)) + .setLayoutId(R.layout.bottom_sheet_item_with_descr_pad_32dp) + .setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Fragment fragment = getTargetFragment(); + if (fragment instanceof OptionsFragmentListener) { + ((OptionsFragmentListener) fragment).addNewSegmentOnClick(); + } + dismiss(); + } + }) + .create(); + items.add(addNewSegment); + } + items.add(new OptionsDividerItem(getContext())); BaseBottomSheetItem saveAsNewSegmentItem = new SimpleBottomSheetItem.Builder() @@ -200,12 +223,13 @@ public class OptionsBottomSheetDialogFragment extends MenuBottomSheetDialogFragm } public static void showInstance(@NonNull FragmentManager fm, Fragment targetFragment, - boolean trackSnappedToRoad, String routeAppModeStringKey) { + boolean trackSnappedToRoad, boolean addNewSegmentAllowed, String routeAppModeStringKey) { try { if (!fm.isStateSaved()) { OptionsBottomSheetDialogFragment fragment = new OptionsBottomSheetDialogFragment(); Bundle args = new Bundle(); args.putBoolean(TRACK_SNAPPED_TO_ROAD_KEY, trackSnappedToRoad); + args.putBoolean(ADD_NEW_SEGMENT_ALLOWED_KEY, addNewSegmentAllowed); args.putString(SNAP_TO_ROAD_APP_MODE_KEY, routeAppModeStringKey); fragment.setArguments(args); fragment.setTargetFragment(targetFragment,0); @@ -225,6 +249,8 @@ public class OptionsBottomSheetDialogFragment extends MenuBottomSheetDialogFragm void snapToRoadOnCLick(); + void addNewSegmentOnClick(); + void saveChangesOnClick(); void saveAsNewTrackOnClick(); diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/SavedTrackBottomSheetDialogFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/SavedTrackBottomSheetDialogFragment.java index 7cec05b764..fc4f5aeece 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/SavedTrackBottomSheetDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/SavedTrackBottomSheetDialogFragment.java @@ -2,7 +2,6 @@ package net.osmand.plus.measurementtool; import android.app.Activity; import android.content.Intent; -import android.net.Uri; import android.os.Bundle; import android.view.View; import android.widget.TextView; @@ -11,7 +10,6 @@ import androidx.annotation.NonNull; import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentManager; -import net.osmand.AndroidUtils; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.UiUtilities; @@ -21,6 +19,7 @@ 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.helpers.GpxUiHelper; import net.osmand.util.Algorithms; import java.io.File; @@ -80,13 +79,10 @@ public class SavedTrackBottomSheetDialogFragment extends MenuBottomSheetDialogFr @Override protected void onThirdBottomButtonClick() { - final Intent sendIntent = new Intent(); - sendIntent.setAction(Intent.ACTION_SEND); - final Uri fileUri = AndroidUtils.getUriForFile(getMyApplication(), new File(fileName)); - sendIntent.putExtra(Intent.EXTRA_STREAM, fileUri); - sendIntent.setType("application/gpx+xml"); - sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - startActivity(sendIntent); + FragmentActivity activity = getActivity(); + if (activity != null) { + GpxUiHelper.shareGpx(activity, new File(fileName)); + } dismiss(); } diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/SelectFileBottomSheet.java b/OsmAnd/src/net/osmand/plus/measurementtool/SelectFileBottomSheet.java index b89cbda954..43037f1398 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/SelectFileBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/SelectFileBottomSheet.java @@ -9,6 +9,7 @@ import android.widget.TextView; import androidx.annotation.StringRes; import androidx.appcompat.view.ContextThemeWrapper; +import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentManager; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -20,7 +21,7 @@ import net.osmand.OsmAndCollator; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.UiUtilities; -import net.osmand.plus.base.BottomSheetBehaviourDialogFragment; +import net.osmand.plus.base.MenuBottomSheetDialogFragment; import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem; import net.osmand.plus.helpers.GpxTrackAdapter; import net.osmand.plus.helpers.GpxTrackAdapter.OnItemClickListener; @@ -38,11 +39,11 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import static net.osmand.plus.SimplePopUpMenuItemAdapter.*; +import static net.osmand.plus.SimplePopUpMenuItemAdapter.SimplePopUpMenuItem; import static net.osmand.plus.helpers.GpxUiHelper.getSortedGPXFilesInfo; import static net.osmand.util.Algorithms.collectDirs; -public class SelectFileBottomSheet extends BottomSheetBehaviourDialogFragment { +public class SelectFileBottomSheet extends MenuBottomSheetDialogFragment { private List folders; private HorizontalSelectionAdapter folderAdapter; @@ -301,8 +302,27 @@ public class SelectFileBottomSheet extends BottomSheetBehaviourDialogFragment { } @Override - protected int getPeekHeight() { - return AndroidUtils.dpToPx(getContext(), BOTTOM_SHEET_HEIGHT_DP); + protected boolean useScrollableItemsContainer() { + return false; + } + + @Override + protected boolean useExpandableList() { + return true; + } + + @Override + protected int getCustomHeight() { + FragmentActivity activity = getActivity(); + if (activity != null) { + int screenHeight = AndroidUtils.getScreenHeight(activity); + int statusBarHeight = AndroidUtils.getStatusBarHeight(activity); + int navBarHeight = AndroidUtils.getNavBarHeight(activity); + int buttonsHeight = getResources().getDimensionPixelSize(R.dimen.dialog_button_ex_height); + + return screenHeight - statusBarHeight - buttonsHeight - navBarHeight - getResources().getDimensionPixelSize(R.dimen.toolbar_height); + } + return super.getCustomHeight(); } public static void showInstance(FragmentManager fragmentManager, SelectFileListener listener, Mode mode) { diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/SelectedPointBottomSheetDialogFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/SelectedPointBottomSheetDialogFragment.java index e6cccff706..99dba59e1d 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/SelectedPointBottomSheetDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/SelectedPointBottomSheetDialogFragment.java @@ -133,7 +133,7 @@ public class SelectedPointBottomSheetDialogFragment extends MenuBottomSheetDialo dismiss(); } }) - .setDisabled(editingCtx.isFirstPointSelected()) + .setDisabled(editingCtx.isFirstPointSelected(false)) .create(); items.add(trimRouteBefore); @@ -152,10 +152,93 @@ public class SelectedPointBottomSheetDialogFragment extends MenuBottomSheetDialo dismiss(); } }) - .setDisabled(editingCtx.isLastPointSelected()) + .setDisabled(editingCtx.isLastPointSelected(false)) .create(); items.add(trimRouteAfter); + if (editingCtx.isFirstPointSelected(true)) { + // skip + } else if (editingCtx.isLastPointSelected(true)) { + items.add(new OptionsDividerItem(getContext())); + + // new segment + BaseBottomSheetItem addNewSegment = new BottomSheetItemWithDescription.Builder() + //.setIcon(getContentIcon(R.drawable.ic_action_trim_right)) + .setTitle(getString(R.string.plan_route_add_new_segment)) + .setLayoutId(R.layout.bottom_sheet_item_with_descr_pad_32dp) + .setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Fragment targetFragment = getTargetFragment(); + if (targetFragment instanceof SelectedPointFragmentListener) { + ((SelectedPointFragmentListener) targetFragment).onSplitPointsAfter(); + } + dismiss(); + } + }) + .create(); + items.add(addNewSegment); + } else if (editingCtx.isFirstPointSelected(false) || editingCtx.isLastPointSelected(false)) { + items.add(new OptionsDividerItem(getContext())); + + // join + BaseBottomSheetItem joinSegments = new BottomSheetItemWithDescription.Builder() + //.setIcon(getContentIcon(R.drawable.ic_action_trim_right)) + .setTitle(getString(R.string.plan_route_join_segments)) + .setLayoutId(R.layout.bottom_sheet_item_with_descr_pad_32dp) + .setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Fragment targetFragment = getTargetFragment(); + if (targetFragment instanceof SelectedPointFragmentListener) { + ((SelectedPointFragmentListener) targetFragment).onJoinPoints(); + } + dismiss(); + } + }) + .create(); + items.add(joinSegments); + } else { + items.add(new OptionsDividerItem(getContext())); + + // split + BaseBottomSheetItem splitAfter = new BottomSheetItemWithDescription.Builder() + //.setIcon(getContentIcon(R.drawable.ic_action_trim_right)) + .setTitle(getString(R.string.plan_route_split_after)) + .setLayoutId(R.layout.bottom_sheet_item_with_descr_pad_32dp) + .setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Fragment targetFragment = getTargetFragment(); + if (targetFragment instanceof SelectedPointFragmentListener) { + ((SelectedPointFragmentListener) targetFragment).onSplitPointsAfter(); + } + dismiss(); + } + }) + .setDisabled(!editingCtx.canSplit(true)) + .create(); + items.add(splitAfter); + + BaseBottomSheetItem splitBefore = new BottomSheetItemWithDescription.Builder() + //.setIcon(getContentIcon(R.drawable.ic_action_trim_right)) + .setTitle(getString(R.string.plan_route_split_before)) + .setLayoutId(R.layout.bottom_sheet_item_with_descr_pad_32dp) + .setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Fragment targetFragment = getTargetFragment(); + if (targetFragment instanceof SelectedPointFragmentListener) { + ((SelectedPointFragmentListener) targetFragment).onSplitPointsBefore(); + } + dismiss(); + } + }) + .setDisabled(!editingCtx.canSplit(false)) + .create(); + items.add(splitBefore); + } + items.add(new OptionsDividerItem(getContext())); BaseBottomSheetItem changeRouteTypeBefore = new BottomSheetItemWithDescription.Builder() @@ -172,7 +255,7 @@ public class SelectedPointBottomSheetDialogFragment extends MenuBottomSheetDialo dismiss(); } }) - .setDisabled(editingCtx.isFirstPointSelected() || editingCtx.isSelectionNeedApproximation()) + .setDisabled(editingCtx.isFirstPointSelected(false) || editingCtx.isApproximationNeeded()) .create(); items.add(changeRouteTypeBefore); @@ -190,7 +273,7 @@ public class SelectedPointBottomSheetDialogFragment extends MenuBottomSheetDialo dismiss(); } }) - .setDisabled(editingCtx.isLastPointSelected() || editingCtx.isSelectionNeedApproximation()) + .setDisabled(editingCtx.isLastPointSelected(false) || editingCtx.isApproximationNeeded()) .create(); items.add(changeRouteTypeAfter); @@ -352,6 +435,12 @@ public class SelectedPointBottomSheetDialogFragment extends MenuBottomSheetDialo void onTrimRouteAfter(); + void onSplitPointsAfter(); + + void onSplitPointsBefore(); + + void onJoinPoints(); + void onChangeRouteTypeBefore(); void onChangeRouteTypeAfter(); diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/command/JoinPointsCommand.java b/OsmAnd/src/net/osmand/plus/measurementtool/command/JoinPointsCommand.java new file mode 100644 index 0000000000..95a311a9d3 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/measurementtool/command/JoinPointsCommand.java @@ -0,0 +1,58 @@ +package net.osmand.plus.measurementtool.command; + +import android.util.Pair; + +import net.osmand.GPXUtilities.WptPt; +import net.osmand.plus.measurementtool.MeasurementEditingContext; +import net.osmand.plus.measurementtool.MeasurementEditingContext.RoadSegmentData; +import net.osmand.plus.measurementtool.MeasurementToolLayer; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class JoinPointsCommand extends MeasurementModeCommand { + + private List points; + private Map, RoadSegmentData> roadSegmentData; + private int pointPosition; + + public JoinPointsCommand(MeasurementToolLayer measurementLayer) { + super(measurementLayer); + } + + @Override + public boolean execute() { + pointPosition = getEditingCtx().getSelectedPointPosition(); + executeCommand(); + return true; + } + + private void executeCommand() { + MeasurementEditingContext ctx = getEditingCtx(); + List pts = ctx.getPoints(); + points = new ArrayList<>(pts); + roadSegmentData = ctx.getRoadSegmentData(); + ctx.joinPoints(pointPosition); + refreshMap(); + } + + @Override + public void undo() { + MeasurementEditingContext ctx = getEditingCtx(); + ctx.clearSegments(); + ctx.setRoadSegmentData(roadSegmentData); + ctx.addPoints(points); + refreshMap(); + } + + @Override + public void redo() { + executeCommand(); + } + + @Override + public MeasurementCommandType getType() { + return MeasurementCommandType.JOIN_POINTS; + } +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/command/MeasurementModeCommand.java b/OsmAnd/src/net/osmand/plus/measurementtool/command/MeasurementModeCommand.java index 32fa3ee7cd..3a77d0cb6a 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/command/MeasurementModeCommand.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/command/MeasurementModeCommand.java @@ -41,6 +41,8 @@ public abstract class MeasurementModeCommand implements Command { SNAP_TO_ROAD, CHANGE_ROUTE_MODE, APPROXIMATE_POINTS, - REVERSE_POINTS + REVERSE_POINTS, + SPLIT_POINTS, + JOIN_POINTS } } diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/command/SplitPointsCommand.java b/OsmAnd/src/net/osmand/plus/measurementtool/command/SplitPointsCommand.java new file mode 100644 index 0000000000..6bfb75d682 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/measurementtool/command/SplitPointsCommand.java @@ -0,0 +1,67 @@ +package net.osmand.plus.measurementtool.command; + +import android.util.Pair; + +import net.osmand.GPXUtilities; +import net.osmand.GPXUtilities.TrkSegment; +import net.osmand.GPXUtilities.WptPt; +import net.osmand.plus.measurementtool.MeasurementEditingContext; +import net.osmand.plus.measurementtool.MeasurementEditingContext.RoadSegmentData; +import net.osmand.plus.measurementtool.MeasurementToolLayer; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class SplitPointsCommand extends MeasurementModeCommand { + + private boolean after; + private List points; + private Map, RoadSegmentData> roadSegmentData; + private int pointPosition; + + public SplitPointsCommand(MeasurementToolLayer measurementLayer, boolean after) { + super(measurementLayer); + this.after = after; + MeasurementEditingContext editingCtx = getEditingCtx(); + this.pointPosition = editingCtx.getSelectedPointPosition(); + if (this.pointPosition == -1) { + this.after = true; + this.pointPosition = editingCtx.getPoints().size() - 1; + } + } + + @Override + public boolean execute() { + executeCommand(); + return true; + } + + private void executeCommand() { + MeasurementEditingContext ctx = getEditingCtx(); + List pts = ctx.getPoints(); + points = new ArrayList<>(pts); + roadSegmentData = ctx.getRoadSegmentData(); + ctx.splitPoints(pointPosition, after); + refreshMap(); + } + + @Override + public void undo() { + MeasurementEditingContext ctx = getEditingCtx(); + ctx.clearSegments(); + ctx.setRoadSegmentData(roadSegmentData); + ctx.addPoints(points); + refreshMap(); + } + + @Override + public void redo() { + executeCommand(); + } + + @Override + public MeasurementCommandType getType() { + return MeasurementCommandType.SPLIT_POINTS; + } +} diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/graph/CustomGraphAdapter.java b/OsmAnd/src/net/osmand/plus/measurementtool/graph/CustomGraphAdapter.java index 1bc763b165..32a1f6a654 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/graph/CustomGraphAdapter.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/graph/CustomGraphAdapter.java @@ -61,11 +61,14 @@ public class CustomGraphAdapter extends BaseGraphAdapter elems = getStatistics().elements; + List elems = getStatistics().elements; int i = h.getStackIndex(); if (i >= 0 && elems.size() > i) { selectedPropertyName = elems.get(i).getPropertyName(); updateLegend(); + } else if (LegendViewType.ONE_ELEMENT == legendViewType && elems.size() == 1) { + selectedPropertyName = elems.get(0).getPropertyName(); + updateLegend(); } } @@ -116,19 +119,20 @@ public class CustomGraphAdapter extends BaseGraphAdapter attributes = getSegmentsList(); + if (attributes == null) return; switch (legendViewType) { case ONE_ELEMENT: - for (RouteSegmentAttribute segment : getSegmentsList()) { - if (segment.getPropertyName().equals(selectedPropertyName)) { - attachLegend(Collections.singletonList(segment), null); + for (RouteSegmentAttribute attribute : attributes) { + if (attribute.getPropertyName().equals(selectedPropertyName)) { + attachLegend(Collections.singletonList(attribute), null); break; } } break; case ALL_AS_LIST: - attachLegend(getSegmentsList(), selectedPropertyName); + attachLegend(attributes, selectedPropertyName); break; } } @@ -137,7 +141,7 @@ public class CustomGraphAdapter extends BaseGraphAdapter(filenames)); f.setArguments(b); @@ -234,3 +231,4 @@ public class OnSaveCurrentTrackFragment extends BottomSheetDialogFragment { } } } + diff --git a/OsmAnd/src/net/osmand/plus/myplaces/TrackPointFragment.java b/OsmAnd/src/net/osmand/plus/myplaces/TrackPointFragment.java index 95b05e2d18..10f36953c6 100644 --- a/OsmAnd/src/net/osmand/plus/myplaces/TrackPointFragment.java +++ b/OsmAnd/src/net/osmand/plus/myplaces/TrackPointFragment.java @@ -4,7 +4,6 @@ import android.app.Activity; import android.content.DialogInterface; import android.content.Intent; import android.graphics.Bitmap; -import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; @@ -54,8 +53,6 @@ import net.osmand.plus.GPXDatabase.GpxDataItem; import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup; import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem; import net.osmand.plus.GpxSelectionHelper.GpxDisplayItemType; -import net.osmand.plus.mapmarkers.MapMarkersHelper; -import net.osmand.plus.mapmarkers.MapMarkersGroup; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.UiUtilities; @@ -66,7 +63,10 @@ import net.osmand.plus.activities.SavingTrackHelper; import net.osmand.plus.activities.TrackActivity; import net.osmand.plus.base.OsmandExpandableListFragment; import net.osmand.plus.base.PointImageDrawable; +import net.osmand.plus.helpers.GpxUiHelper; import net.osmand.plus.mapmarkers.CoordinateInputDialogFragment; +import net.osmand.plus.mapmarkers.MapMarkersGroup; +import net.osmand.plus.mapmarkers.MapMarkersHelper; import net.osmand.plus.myplaces.TrackBitmapDrawer.TrackBitmapDrawerListener; import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.track.SaveGpxAsyncTask.SaveGpxListener; @@ -303,7 +303,8 @@ public class TrackPointFragment extends OsmandExpandableListFragment implements private void shareItems() { final GPXFile gpxFile = getGpx(); - if (gpxFile != null && getTrackActivity() != null) { + FragmentActivity activity = getActivity(); + if (gpxFile != null && activity != null) { if (Algorithms.isEmpty(gpxFile.path)) { SaveGpxListener saveGpxListener = new SaveGpxListener() { @Override @@ -315,26 +316,20 @@ public class TrackPointFragment extends OsmandExpandableListFragment implements public void gpxSavingFinished(Exception errorMessage) { if (isResumed()) { hideProgressBar(); - shareGpx(gpxFile.path); + FragmentActivity activity = getActivity(); + if (activity != null) { + GpxUiHelper.shareGpx(activity, new File(gpxFile.path)); + } } } }; new SaveCurrentTrackTask(app, gpxFile, saveGpxListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } else { - shareGpx(gpxFile.path); + GpxUiHelper.saveAndShareGpxWithAppearance(activity, gpxFile); } } } - private void shareGpx(String path) { - final Uri fileUri = AndroidUtils.getUriForFile(getMyApplication(), new File(path)); - final Intent sendIntent = new Intent(Intent.ACTION_SEND); - sendIntent.putExtra(Intent.EXTRA_STREAM, fileUri); - sendIntent.setType("application/gpx+xml"); - sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - startActivity(sendIntent); - } - private void openCoordinatesInput() { FragmentManager fm = getFragmentManager(); if (fm != null) { @@ -412,7 +407,7 @@ public class TrackPointFragment extends OsmandExpandableListFragment implements final MapMarkersHelper markersHelper = app.getMapMarkersHelper(); final boolean synced = markersHelper.getMarkersGroup(getGpx()) != null; createMenuItem(menu, SELECT_MAP_MARKERS_ID, synced ? R.string.remove_from_map_markers - : R.string.shared_string_add_to_map_markers, R.drawable.ic_action_flag, MenuItem.SHOW_AS_ACTION_NEVER); + : R.string.shared_string_add_to_map_markers, R.drawable.ic_action_flag, MenuItem.SHOW_AS_ACTION_NEVER); } createMenuItem(menu, SELECT_FAVORITES_ID, R.string.shared_string_add_to_favorites, R.drawable.ic_action_favorite, MenuItem.SHOW_AS_ACTION_NEVER); createMenuItem(menu, DELETE_ID, R.string.shared_string_delete, R.drawable.ic_action_delete_dark, MenuItem.SHOW_AS_ACTION_NEVER); diff --git a/OsmAnd/src/net/osmand/plus/myplaces/TrackSegmentFragment.java b/OsmAnd/src/net/osmand/plus/myplaces/TrackSegmentFragment.java index 08c68ac3e8..e686c08f5b 100644 --- a/OsmAnd/src/net/osmand/plus/myplaces/TrackSegmentFragment.java +++ b/OsmAnd/src/net/osmand/plus/myplaces/TrackSegmentFragment.java @@ -3,11 +3,9 @@ package net.osmand.plus.myplaces; import android.annotation.SuppressLint; import android.content.Context; import android.content.DialogInterface; -import android.content.Intent; import android.graphics.Bitmap; import android.graphics.Matrix; import android.graphics.drawable.Drawable; -import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.util.SparseArray; @@ -28,6 +26,7 @@ import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.widget.SwitchCompat; import androidx.core.content.ContextCompat; +import androidx.fragment.app.FragmentActivity; import androidx.viewpager.widget.PagerAdapter; import com.github.mikephil.charting.charts.LineChart; @@ -62,9 +61,9 @@ import net.osmand.plus.activities.TrackActivity; import net.osmand.plus.base.OsmAndListFragment; import net.osmand.plus.helpers.AndroidUiHelper; import net.osmand.plus.helpers.GpxUiHelper; -import net.osmand.plus.helpers.GpxUiHelper.LineGraphType; import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetAxisType; import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetType; +import net.osmand.plus.helpers.GpxUiHelper.LineGraphType; import net.osmand.plus.helpers.GpxUiHelper.OrderedLineDataSet; import net.osmand.plus.myplaces.TrackBitmapDrawer.TrackBitmapDrawerListener; import net.osmand.plus.settings.backend.OsmandSettings; @@ -163,12 +162,11 @@ public class TrackSegmentFragment extends OsmAndListFragment implements TrackBit .setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { - final Uri fileUri = AndroidUtils.getUriForFile(getMyApplication(), new File(getGpx().path)); - final Intent sendIntent = new Intent(Intent.ACTION_SEND); - sendIntent.putExtra(Intent.EXTRA_STREAM, fileUri); - sendIntent.setType("application/gpx+xml"); - sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - startActivity(sendIntent); + GPXFile gpx = getGpx(); + FragmentActivity activity = getActivity(); + if (activity != null && gpx != null) { + GpxUiHelper.shareGpx(activity, new File(gpx.path)); + } return true; } }); @@ -1209,7 +1207,7 @@ public class TrackSegmentFragment extends OsmAndListFragment implements TrackBit } private void saveGpx(final SelectedGpxFile selectedGpxFile, GPXFile gpxFile) { - new SaveGpxAsyncTask(gpxFile, new SaveGpxListener() { + new SaveGpxAsyncTask(new File(gpxFile.path), gpxFile, new SaveGpxListener() { @Override public void gpxSavingStarted() { TrackActivity activity = getTrackActivity(); diff --git a/OsmAnd/src/net/osmand/plus/osmedit/OpenstreetmapRemoteUtil.java b/OsmAnd/src/net/osmand/plus/osmedit/OpenstreetmapRemoteUtil.java index 98256d0635..8cefebd9ad 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/OpenstreetmapRemoteUtil.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/OpenstreetmapRemoteUtil.java @@ -417,8 +417,9 @@ public class OpenstreetmapRemoteUtil implements OpenstreetmapUtil { } } } - } else if (MapUtils.getDistance(n.getLatLon(), entity.getLatLon()) < 10) { - // avoid shifting due to round error + } else if (MapUtils.getDistance(n.getLatLon(), entity.getLatLon()) < 10 || + MapUtils.getDistance(n.getLatLon(), entity.getLatLon()) > 10000) { + // avoid shifting due to round error and avoid moving to more than 10 km n.setLatitude(entity.getLatitude()); n.setLongitude(entity.getLongitude()); } diff --git a/OsmAnd/src/net/osmand/plus/osmedit/dialogs/BugBottomSheetDialog.java b/OsmAnd/src/net/osmand/plus/osmedit/dialogs/BugBottomSheetDialog.java index 38bb8da5fe..7b4067c2f7 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/dialogs/BugBottomSheetDialog.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/dialogs/BugBottomSheetDialog.java @@ -56,6 +56,7 @@ public class BugBottomSheetDialog extends MenuBottomSheetDialogFragment { View osmNoteView = View.inflate(UiUtilities.getThemedContext(app, nightMode), R.layout.open_osm_note_text, null); + osmNoteView.getViewTreeObserver().addOnGlobalLayoutListener(getShadowLayoutListener()); TextInputLayout textBox = osmNoteView.findViewById(R.id.name_text_box); textBox.setHint(AndroidUtils.addColon(app, R.string.osn_bug_name)); ColorStateList colorStateList = ColorStateList.valueOf(ContextCompat @@ -85,9 +86,9 @@ public class BugBottomSheetDialog extends MenuBottomSheetDialogFragment { } public static void showInstance(@NonNull FragmentManager fm, OsmBugsUtil osmBugsUtil, OsmBugsUtil local, - String text, int titleTextId, int posButtonTextId, final OsmPoint.Action action, - final OsmBugsLayer.OpenStreetNote bug, final OsmNotesPoint point, - HandleOsmNoteAsyncTask.HandleBugListener handleBugListener) { + String text, int titleTextId, int posButtonTextId, final OsmPoint.Action action, + final OsmBugsLayer.OpenStreetNote bug, final OsmNotesPoint point, + HandleOsmNoteAsyncTask.HandleBugListener handleBugListener) { try { if (!fm.isStateSaved()) { BugBottomSheetDialog fragment = new BugBottomSheetDialog(); diff --git a/OsmAnd/src/net/osmand/plus/osmedit/dialogs/SendGpxBottomSheetFragment.java b/OsmAnd/src/net/osmand/plus/osmedit/dialogs/SendGpxBottomSheetFragment.java index 759f924d10..cc1fab7554 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/dialogs/SendGpxBottomSheetFragment.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/dialogs/SendGpxBottomSheetFragment.java @@ -1,14 +1,11 @@ package net.osmand.plus.osmedit.dialogs; -import android.graphics.Rect; import android.os.AsyncTask; import android.os.Bundle; import android.text.Editable; import android.view.LayoutInflater; import android.view.View; -import android.view.ViewTreeObserver; import android.widget.LinearLayout; -import android.widget.ScrollView; import android.widget.TextView; import androidx.annotation.NonNull; @@ -54,10 +51,6 @@ public class SendGpxBottomSheetFragment extends MenuBottomSheetDialogFragment { private TextInputEditText tagsField; private TextInputEditText messageField; - private int contentHeightPrevious = 0; - private int buttonsHeight; - private int shadowHeight; - private ScrollView scrollView; public void setGpxInfos(GpxInfo[] gpxInfos) { this.gpxInfos = gpxInfos; @@ -69,13 +62,13 @@ public class SendGpxBottomSheetFragment extends MenuBottomSheetDialogFragment { OsmandSettings settings = app.getSettings(); LayoutInflater themedInflater = UiUtilities.getInflater(app, nightMode); - View sendOsmPoiView = themedInflater.inflate(R.layout.send_gpx_fragment, null); - sendOsmPoiView.getViewTreeObserver().addOnGlobalLayoutListener(getOnGlobalLayoutListener()); + View sendGpxView = themedInflater.inflate(R.layout.send_gpx_fragment, null); + sendGpxView.getViewTreeObserver().addOnGlobalLayoutListener(getShadowLayoutListener()); - tagsField = sendOsmPoiView.findViewById(R.id.tags_field); - messageField = sendOsmPoiView.findViewById(R.id.message_field); + tagsField = sendGpxView.findViewById(R.id.tags_field); + messageField = sendGpxView.findViewById(R.id.message_field); - TextView accountName = sendOsmPoiView.findViewById(R.id.user_name); + TextView accountName = sendGpxView.findViewById(R.id.user_name); if (!Algorithms.isEmpty(settings.USER_DISPLAY_NAME.get())) { accountName.setText(settings.USER_DISPLAY_NAME.get()); } else { @@ -86,8 +79,8 @@ public class SendGpxBottomSheetFragment extends MenuBottomSheetDialogFragment { messageField.setText(Algorithms.getFileNameWithoutExtension(fileName)); messageField.setSelection(messageField.getText().length()); - final TextView visibilityName = sendOsmPoiView.findViewById(R.id.visibility_name); - final TextView visibilityDescription = sendOsmPoiView.findViewById(R.id.visibility_description); + final TextView visibilityName = sendGpxView.findViewById(R.id.visibility_name); + final TextView visibilityDescription = sendGpxView.findViewById(R.id.visibility_description); visibilityName.setText(selectedUploadVisibility.getTitleId()); visibilityDescription.setText(selectedUploadVisibility.getDescriptionId()); @@ -110,7 +103,7 @@ public class SendGpxBottomSheetFragment extends MenuBottomSheetDialogFragment { horizontalSelectionAdapter.notifyDataSetChanged(); } }); - LinearLayout account = sendOsmPoiView.findViewById(R.id.account_container); + LinearLayout account = sendGpxView.findViewById(R.id.account_container); account.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -121,39 +114,17 @@ public class SendGpxBottomSheetFragment extends MenuBottomSheetDialogFragment { dismiss(); } }); - RecyclerView iconCategoriesRecyclerView = sendOsmPoiView.findViewById(R.id.description_view); + RecyclerView iconCategoriesRecyclerView = sendGpxView.findViewById(R.id.description_view); iconCategoriesRecyclerView.setAdapter(horizontalSelectionAdapter); iconCategoriesRecyclerView.setLayoutManager(new LinearLayoutManager(app, RecyclerView.HORIZONTAL, false)); horizontalSelectionAdapter.notifyDataSetChanged(); SimpleBottomSheetItem titleItem = (SimpleBottomSheetItem) new SimpleBottomSheetItem.Builder() - .setCustomView(sendOsmPoiView) + .setCustomView(sendGpxView) .create(); items.add(titleItem); } - private ViewTreeObserver.OnGlobalLayoutListener getOnGlobalLayoutListener() { - return new ViewTreeObserver.OnGlobalLayoutListener() { - @Override - public void onGlobalLayout() { - Rect visibleDisplayFrame = new Rect(); - buttonsHeight = getResources().getDimensionPixelSize(R.dimen.dialog_button_ex_max_width); - shadowHeight = getResources().getDimensionPixelSize(R.dimen.bottom_sheet_top_shadow_height); - scrollView = getView().findViewById(R.id.scroll_view); - scrollView.getWindowVisibleDisplayFrame(visibleDisplayFrame); - int viewHeight = scrollView.getHeight(); - int contentHeight = visibleDisplayFrame.bottom - visibleDisplayFrame.top - buttonsHeight; - if (contentHeightPrevious != contentHeight) { - boolean showTopShadow; - showTopShadow = viewHeight + shadowHeight < contentHeight; - scrollView.requestLayout(); - contentHeightPrevious = contentHeight; - drawTopShadow(showTopShadow); - } - } - }; - } - protected static void showOpenStreetMapScreen(@NonNull FragmentActivity activity) { if (activity instanceof MapActivity) { BaseSettingsFragment.showInstance(activity, OPEN_STREET_MAP_EDITING); diff --git a/OsmAnd/src/net/osmand/plus/osmedit/dialogs/SendOsmNoteBottomSheetFragment.java b/OsmAnd/src/net/osmand/plus/osmedit/dialogs/SendOsmNoteBottomSheetFragment.java index 7ab3d9149b..f4f657c099 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/dialogs/SendOsmNoteBottomSheetFragment.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/dialogs/SendOsmNoteBottomSheetFragment.java @@ -77,6 +77,7 @@ public class SendOsmNoteBottomSheetFragment extends MenuBottomSheetDialogFragmen final View sendOsmNoteView = View.inflate(new ContextThemeWrapper(getContext(), themeRes), R.layout.send_osm_note_fragment, null); + sendOsmNoteView.getViewTreeObserver().addOnGlobalLayoutListener(getShadowLayoutListener()); noteText = sendOsmNoteView.findViewById(R.id.note_text); noteText.setText(((OsmNotesPoint) poi[0]).getText()); diff --git a/OsmAnd/src/net/osmand/plus/osmedit/dialogs/SendPoiBottomSheetFragment.java b/OsmAnd/src/net/osmand/plus/osmedit/dialogs/SendPoiBottomSheetFragment.java index 35a998e1bb..a715c33354 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/dialogs/SendPoiBottomSheetFragment.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/dialogs/SendPoiBottomSheetFragment.java @@ -37,221 +37,222 @@ import static net.osmand.plus.osmedit.dialogs.SendGpxBottomSheetFragment.showOpe public class SendPoiBottomSheetFragment extends MenuBottomSheetDialogFragment { - public static final String TAG = SendPoiBottomSheetFragment.class.getSimpleName(); - private static final Log LOG = PlatformUtil.getLog(SendPoiBottomSheetFragment.class); - public static final String OPENSTREETMAP_POINT = "openstreetmap_point"; - private OsmPoint[] poi; + public static final String TAG = SendPoiBottomSheetFragment.class.getSimpleName(); + private static final Log LOG = PlatformUtil.getLog(SendPoiBottomSheetFragment.class); + public static final String OPENSTREETMAP_POINT = "openstreetmap_point"; + private OsmPoint[] poi; - private SwitchCompat closeChangeSet; - private EditText messageEditText; + private SwitchCompat closeChangeSet; + private EditText messageEditText; - private boolean isLoginOAuth(OsmandSettings settings) { - return !Algorithms.isEmpty(settings.USER_DISPLAY_NAME.get()); - } + private boolean isLoginOAuth(OsmandSettings settings) { + return !Algorithms.isEmpty(settings.USER_DISPLAY_NAME.get()); + } - @Override - public void createMenuItems(Bundle savedInstanceState) { - OsmandApplication app = getMyApplication(); - if (app == null) { - return; - } - poi = (OsmPoint[]) getArguments().getSerializable(OPENSTREETMAP_POINT); - final boolean isNightMode = app.getDaynightHelper().isNightModeForMapControls(); - final View sendOsmPoiView = View.inflate(new ContextThemeWrapper(getContext(), themeRes), - R.layout.send_poi_fragment, null); - closeChangeSet = sendOsmPoiView.findViewById(R.id.close_change_set_checkbox); - messageEditText = sendOsmPoiView.findViewById(R.id.message_field); - String defaultChangeSet = createDefaultChangeSet(app); - messageEditText.setText(defaultChangeSet); - messageEditText.setSelection(messageEditText.getText().length()); - final TextView accountName = sendOsmPoiView.findViewById(R.id.user_name); - OsmandSettings settings = app.getSettings(); - String userNameOAuth = settings.USER_DISPLAY_NAME.get(); - String userNameOpenID = settings.USER_NAME.get(); - String userName = isLoginOAuth(settings) ? userNameOAuth : userNameOpenID; - accountName.setText(userName); - closeChangeSet.setBackgroundResource(isNightMode ? R.drawable.layout_bg_dark : R.drawable.layout_bg); - final int paddingSmall = app.getResources().getDimensionPixelSize(R.dimen.content_padding_small); - closeChangeSet.setPadding(paddingSmall, 0, paddingSmall, 0); - closeChangeSet.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - if (isNightMode) { - closeChangeSet.setBackgroundResource( - isChecked ? R.drawable.layout_bg_dark_solid : R.drawable.layout_bg_dark); - } else { - closeChangeSet.setBackgroundResource( - isChecked ? R.drawable.layout_bg_solid : R.drawable.layout_bg); - } - closeChangeSet.setPadding(paddingSmall, 0, paddingSmall, 0); - } - }); - LinearLayout account = sendOsmPoiView.findViewById(R.id.account_container); - account.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - FragmentActivity activity = getActivity(); - if (activity != null) { - showOpenStreetMapScreen(activity); - } - dismiss(); - } - }); - final SimpleBottomSheetItem titleItem = (SimpleBottomSheetItem) new SimpleBottomSheetItem.Builder() - .setCustomView(sendOsmPoiView) - .create(); - items.add(titleItem); - } + @Override + public void createMenuItems(Bundle savedInstanceState) { + OsmandApplication app = getMyApplication(); + if (app == null) { + return; + } + poi = (OsmPoint[]) getArguments().getSerializable(OPENSTREETMAP_POINT); + final boolean isNightMode = app.getDaynightHelper().isNightModeForMapControls(); + final View sendOsmPoiView = View.inflate(new ContextThemeWrapper(getContext(), themeRes), + R.layout.send_poi_fragment, null); + sendOsmPoiView.getViewTreeObserver().addOnGlobalLayoutListener(getShadowLayoutListener()); + closeChangeSet = sendOsmPoiView.findViewById(R.id.close_change_set_checkbox); + messageEditText = sendOsmPoiView.findViewById(R.id.message_field); + String defaultChangeSet = createDefaultChangeSet(app); + messageEditText.setText(defaultChangeSet); + messageEditText.setSelection(messageEditText.getText().length()); + final TextView accountName = sendOsmPoiView.findViewById(R.id.user_name); + OsmandSettings settings = app.getSettings(); + String userNameOAuth = settings.USER_DISPLAY_NAME.get(); + String userNameOpenID = settings.USER_NAME.get(); + String userName = isLoginOAuth(settings) ? userNameOAuth : userNameOpenID; + accountName.setText(userName); + closeChangeSet.setBackgroundResource(isNightMode ? R.drawable.layout_bg_dark : R.drawable.layout_bg); + final int paddingSmall = app.getResources().getDimensionPixelSize(R.dimen.content_padding_small); + closeChangeSet.setPadding(paddingSmall, 0, paddingSmall, 0); + closeChangeSet.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (isNightMode) { + closeChangeSet.setBackgroundResource( + isChecked ? R.drawable.layout_bg_dark_solid : R.drawable.layout_bg_dark); + } else { + closeChangeSet.setBackgroundResource( + isChecked ? R.drawable.layout_bg_solid : R.drawable.layout_bg); + } + closeChangeSet.setPadding(paddingSmall, 0, paddingSmall, 0); + } + }); + LinearLayout account = sendOsmPoiView.findViewById(R.id.account_container); + account.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + FragmentActivity activity = getActivity(); + if (activity != null) { + showOpenStreetMapScreen(activity); + } + dismiss(); + } + }); + final SimpleBottomSheetItem titleItem = (SimpleBottomSheetItem) new SimpleBottomSheetItem.Builder() + .setCustomView(sendOsmPoiView) + .create(); + items.add(titleItem); + } - public static void showInstance(@NonNull FragmentManager fm, @NonNull OsmPoint[] points) { - try { - if (!fm.isStateSaved()) { - SendPoiBottomSheetFragment fragment = new SendPoiBottomSheetFragment(); - Bundle bundle = new Bundle(); - bundle.putSerializable(OPENSTREETMAP_POINT, points); - fragment.setArguments(bundle); - fragment.show(fm, TAG); - } - } catch (RuntimeException e) { - LOG.error("showInstance", e); - } - } + public static void showInstance(@NonNull FragmentManager fm, @NonNull OsmPoint[] points) { + try { + if (!fm.isStateSaved()) { + SendPoiBottomSheetFragment fragment = new SendPoiBottomSheetFragment(); + Bundle bundle = new Bundle(); + bundle.putSerializable(OPENSTREETMAP_POINT, points); + fragment.setArguments(bundle); + fragment.show(fm, TAG); + } + } catch (RuntimeException e) { + LOG.error("showInstance", e); + } + } - @Override - protected UiUtilities.DialogButtonType getRightBottomButtonType() { - return (UiUtilities.DialogButtonType.PRIMARY); - } + @Override + protected UiUtilities.DialogButtonType getRightBottomButtonType() { + return (UiUtilities.DialogButtonType.PRIMARY); + } - @Override - protected void onRightBottomButtonClick() { - ProgressDialogPoiUploader progressDialogPoiUploader = null; - Activity activity = getActivity(); - if (activity instanceof MapActivity) { - progressDialogPoiUploader = new SimpleProgressDialogPoiUploader((MapActivity) activity); - } else if (getParentFragment() instanceof ProgressDialogPoiUploader) { - progressDialogPoiUploader = (ProgressDialogPoiUploader) getParentFragment(); - } - if (progressDialogPoiUploader != null) { - String comment = messageEditText.getText().toString(); - if (comment.length() > 0) { - for (OsmPoint osmPoint : poi) { - if (osmPoint.getGroup() == OsmPoint.Group.POI) { - ((OpenstreetmapPoint) osmPoint).setComment(comment); - break; - } - } - } - progressDialogPoiUploader.showProgressDialog(poi, closeChangeSet.isChecked(), false); - } - dismiss(); - } + @Override + protected void onRightBottomButtonClick() { + ProgressDialogPoiUploader progressDialogPoiUploader = null; + Activity activity = getActivity(); + if (activity instanceof MapActivity) { + progressDialogPoiUploader = new SimpleProgressDialogPoiUploader((MapActivity) activity); + } else if (getParentFragment() instanceof ProgressDialogPoiUploader) { + progressDialogPoiUploader = (ProgressDialogPoiUploader) getParentFragment(); + } + if (progressDialogPoiUploader != null) { + String comment = messageEditText.getText().toString(); + if (comment.length() > 0) { + for (OsmPoint osmPoint : poi) { + if (osmPoint.getGroup() == OsmPoint.Group.POI) { + ((OpenstreetmapPoint) osmPoint).setComment(comment); + break; + } + } + } + progressDialogPoiUploader.showProgressDialog(poi, closeChangeSet.isChecked(), false); + } + dismiss(); + } - @Override - protected int getRightBottomButtonTextId() { - return R.string.shared_string_upload; - } + @Override + protected int getRightBottomButtonTextId() { + return R.string.shared_string_upload; + } - private String createDefaultChangeSet(OsmandApplication app) { - Map allTranslatedSubTypes = app.getPoiTypes().getAllTranslatedNames(true); - if (allTranslatedSubTypes == null) { - return ""; - } - Map addGroup = new HashMap<>(); - Map editGroup = new HashMap<>(); - Map deleteGroup = new HashMap<>(); - Map reopenGroup = new HashMap<>(); - String comment = ""; - for (OsmPoint p : poi) { - if (p.getGroup() == OsmPoint.Group.POI) { - OsmPoint.Action action = p.getAction(); - String type = ((OpenstreetmapPoint) p).getEntity().getTag(Entity.POI_TYPE_TAG); - if (type == null) { - continue; - } - PoiType localizedPoiType = allTranslatedSubTypes.get(type.toLowerCase().trim()); - if (localizedPoiType != null) { - type = Algorithms.capitalizeFirstLetter(localizedPoiType.getKeyName().replace('_', ' ')); - } - if (action == OsmPoint.Action.CREATE) { - if (!addGroup.containsKey(type)) { - addGroup.put(type, 1); - } else { - addGroup.put(type, addGroup.get(type) + 1); - } - } else if (action == OsmPoint.Action.MODIFY) { - if (!editGroup.containsKey(type)) { - editGroup.put(type, 1); - } else { - editGroup.put(type, editGroup.get(type) + 1); - } - } else if (action == OsmPoint.Action.DELETE) { - if (!deleteGroup.containsKey(type)) { - deleteGroup.put(type, 1); - } else { - deleteGroup.put(type, deleteGroup.get(type) + 1); - } - } else if (action == OsmPoint.Action.REOPEN) { - if (!reopenGroup.containsKey(type)) { - reopenGroup.put(type, 1); - } else { - reopenGroup.put(type, reopenGroup.get(type) + 1); - } - } - } - } - int modifiedItemsOutOfLimit = 0; - for (int i = 0; i < 4; i++) { - String action; - Map group; - switch (i) { - case 0: - action = getString(R.string.default_changeset_add); - group = addGroup; - break; - case 1: - action = getString(R.string.default_changeset_edit); - group = editGroup; - break; - case 2: - action = getString(R.string.default_changeset_delete); - group = deleteGroup; - break; - case 3: - action = getString(R.string.default_changeset_reopen); - group = reopenGroup; - break; - default: - action = ""; - group = new HashMap<>(); - } + private String createDefaultChangeSet(OsmandApplication app) { + Map allTranslatedSubTypes = app.getPoiTypes().getAllTranslatedNames(true); + if (allTranslatedSubTypes == null) { + return ""; + } + Map addGroup = new HashMap<>(); + Map editGroup = new HashMap<>(); + Map deleteGroup = new HashMap<>(); + Map reopenGroup = new HashMap<>(); + String comment = ""; + for (OsmPoint p : poi) { + if (p.getGroup() == OsmPoint.Group.POI) { + OsmPoint.Action action = p.getAction(); + String type = ((OpenstreetmapPoint) p).getEntity().getTag(Entity.POI_TYPE_TAG); + if (type == null) { + continue; + } + PoiType localizedPoiType = allTranslatedSubTypes.get(type.toLowerCase().trim()); + if (localizedPoiType != null) { + type = Algorithms.capitalizeFirstLetter(localizedPoiType.getKeyName().replace('_', ' ')); + } + if (action == OsmPoint.Action.CREATE) { + if (!addGroup.containsKey(type)) { + addGroup.put(type, 1); + } else { + addGroup.put(type, addGroup.get(type) + 1); + } + } else if (action == OsmPoint.Action.MODIFY) { + if (!editGroup.containsKey(type)) { + editGroup.put(type, 1); + } else { + editGroup.put(type, editGroup.get(type) + 1); + } + } else if (action == OsmPoint.Action.DELETE) { + if (!deleteGroup.containsKey(type)) { + deleteGroup.put(type, 1); + } else { + deleteGroup.put(type, deleteGroup.get(type) + 1); + } + } else if (action == OsmPoint.Action.REOPEN) { + if (!reopenGroup.containsKey(type)) { + reopenGroup.put(type, 1); + } else { + reopenGroup.put(type, reopenGroup.get(type) + 1); + } + } + } + } + int modifiedItemsOutOfLimit = 0; + for (int i = 0; i < 4; i++) { + String action; + Map group; + switch (i) { + case 0: + action = getString(R.string.default_changeset_add); + group = addGroup; + break; + case 1: + action = getString(R.string.default_changeset_edit); + group = editGroup; + break; + case 2: + action = getString(R.string.default_changeset_delete); + group = deleteGroup; + break; + case 3: + action = getString(R.string.default_changeset_reopen); + group = reopenGroup; + break; + default: + action = ""; + group = new HashMap<>(); + } - if (!group.isEmpty()) { - int pos = 0; - for (Map.Entry entry : group.entrySet()) { - String type = entry.getKey(); - int quantity = entry.getValue(); - if (comment.length() > 200) { - modifiedItemsOutOfLimit += quantity; - } else { - if (pos == 0) { - comment = comment.concat(comment.length() == 0 ? "" : "; ").concat(action).concat(" ") - .concat(quantity == 1 ? "" : quantity + " ").concat(type); - } else { - comment = comment.concat(", ").concat(quantity == 1 ? "" : quantity + " ").concat(type); - } - } - pos++; - } - } - } - if (modifiedItemsOutOfLimit != 0) { - comment = comment.concat("; ").concat(modifiedItemsOutOfLimit + " ") - .concat(getString(R.string.items_modified)).concat("."); - } else if (!comment.isEmpty()) { - comment = comment.concat("."); - } - return comment; - } + if (!group.isEmpty()) { + int pos = 0; + for (Map.Entry entry : group.entrySet()) { + String type = entry.getKey(); + int quantity = entry.getValue(); + if (comment.length() > 200) { + modifiedItemsOutOfLimit += quantity; + } else { + if (pos == 0) { + comment = comment.concat(comment.length() == 0 ? "" : "; ").concat(action).concat(" ") + .concat(quantity == 1 ? "" : quantity + " ").concat(type); + } else { + comment = comment.concat(", ").concat(quantity == 1 ? "" : quantity + " ").concat(type); + } + } + pos++; + } + } + } + if (modifiedItemsOutOfLimit != 0) { + comment = comment.concat("; ").concat(modifiedItemsOutOfLimit + " ") + .concat(getString(R.string.items_modified)).concat("."); + } else if (!comment.isEmpty()) { + comment = comment.concat("."); + } + return comment; + } } diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteDetailsFragment.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteDetailsFragment.java index 0747c650c5..ba8e6133c3 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteDetailsFragment.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteDetailsFragment.java @@ -369,7 +369,7 @@ public class RouteDetailsFragment extends ContextMenuFragment super.calculateLayout(view, initLayout); if (!initLayout && getCurrentMenuState() != MenuState.FULL_SCREEN) { if (refreshMapCallback != null) { - refreshMapCallback.refreshMap(false); + refreshMapCallback.refreshMap(false, false); } } } diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteOptionsBottomSheet.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteOptionsBottomSheet.java index 4c54fa47b0..cc983c9f77 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteOptionsBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteOptionsBottomSheet.java @@ -1,6 +1,7 @@ package net.osmand.plus.routepreparationmenu; import android.app.Activity; +import android.content.DialogInterface; import android.content.Intent; import android.graphics.drawable.Drawable; import android.os.Build; @@ -12,11 +13,15 @@ import android.widget.LinearLayout; import android.widget.TextView; import androidx.annotation.ColorRes; +import androidx.annotation.NonNull; +import androidx.appcompat.widget.SwitchCompat; import androidx.core.content.ContextCompat; +import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import net.osmand.AndroidUtils; import net.osmand.GPXUtilities.GPXFile; +import net.osmand.PlatformUtil; import net.osmand.StateChangedListener; import net.osmand.plus.OsmAndLocationSimulation; import net.osmand.plus.OsmandApplication; @@ -31,6 +36,7 @@ import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithDescription; import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem; import net.osmand.plus.base.bottomsheetmenu.simpleitems.DividerStartItem; import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem; +import net.osmand.plus.measurementtool.MeasurementToolFragment; import net.osmand.plus.routepreparationmenu.RoutingOptionsHelper.AvoidPTTypesRoutingParameter; import net.osmand.plus.routepreparationmenu.RoutingOptionsHelper.AvoidRoadsRoutingParameter; import net.osmand.plus.routepreparationmenu.RoutingOptionsHelper.DividerItem; @@ -53,18 +59,28 @@ import net.osmand.router.GeneralRouter; import net.osmand.router.GeneralRouter.RoutingParameter; import net.osmand.util.Algorithms; +import org.apache.commons.logging.Log; + import java.io.File; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; +import static net.osmand.plus.measurementtool.RouteBetweenPointsBottomSheetDialogFragment.RouteBetweenPointsDialogMode.ALL; +import static net.osmand.plus.measurementtool.RouteBetweenPointsBottomSheetDialogFragment.RouteBetweenPointsDialogType.WHOLE_ROUTE_CALCULATION; import static net.osmand.plus.routepreparationmenu.RoutingOptionsHelper.DRIVING_STYLE; import static net.osmand.plus.settings.fragments.RouteParametersFragment.RELIEF_SMOOTHNESS_FACTOR; +import static net.osmand.plus.settings.fragments.RouteParametersFragment.getRoutingParameterTitle; +import static net.osmand.plus.settings.fragments.RouteParametersFragment.isRoutingParameterSelected; import static net.osmand.router.GeneralRouter.USE_HEIGHT_OBSTACLES; public class RouteOptionsBottomSheet extends MenuBottomSheetDialogFragment { - public static final String TAG = "RouteOptionsBottomSheet"; + public static final String TAG = RouteOptionsBottomSheet.class.getSimpleName(); + private static final Log LOG = PlatformUtil.getLog(RouteOptionsBottomSheet.class); + public static final String APP_MODE_KEY = "APP_MODE_KEY"; + public static final String PLANE_ROUTE = "PLANE_ROUTE"; private OsmandApplication app; private OsmandSettings settings; @@ -79,16 +95,28 @@ public class RouteOptionsBottomSheet extends MenuBottomSheetDialogFragment { private CommonPreference useHeightPref; private StateChangedListener voiceMuteChangeListener; private StateChangedListener useHeightChangeListener; + private boolean planRouteMode; + private List reliefParameters = new ArrayList<>(); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + Bundle args = getArguments(); + if (args != null) { + String appMode = args.getString(APP_MODE_KEY, null); + if (appMode != null) { + applicationMode = ApplicationMode.valueOfStringKey(appMode, null); + planRouteMode = true; + } + } app = requiredMyApplication(); settings = app.getSettings(); routingHelper = app.getRoutingHelper(); routingOptionsHelper = app.getRoutingOptionsHelper(); mapActivity = getMapActivity(); - applicationMode = routingHelper.getAppMode(); + if (applicationMode == null) { + applicationMode = routingHelper.getAppMode(); + } selectedModeColorId = applicationMode.getIconColorInfo().getColor(nightMode); voiceMuteChangeListener = new StateChangedListener() { @Override @@ -103,6 +131,7 @@ public class RouteOptionsBottomSheet extends MenuBottomSheetDialogFragment { } }; useHeightPref = settings.getCustomRoutingBooleanProperty(USE_HEIGHT_OBSTACLES, false); + reliefParameters = getReliefParameters(); } @Override @@ -115,21 +144,29 @@ public class RouteOptionsBottomSheet extends MenuBottomSheetDialogFragment { if (optionsItem instanceof DividerItem) { items.add(new DividerStartItem(app)); } else if (optionsItem instanceof MuteSoundRoutingParameter) { - items.add(createMuteSoundItem(optionsItem)); + if (!planRouteMode) { + items.add(createMuteSoundItem(optionsItem)); + } } else if (optionsItem instanceof ShowAlongTheRouteItem) { items.add(createShowAlongTheRouteItem(optionsItem)); } else if (optionsItem instanceof RouteSimulationItem) { - items.add(createRouteSimulationItem(optionsItem)); + if (!planRouteMode) { + items.add(createRouteSimulationItem(optionsItem)); + } } else if (optionsItem instanceof AvoidPTTypesRoutingParameter) { items.add(createAvoidPTTypesItem(optionsItem)); } else if (optionsItem instanceof AvoidRoadsRoutingParameter) { items.add(createAvoidRoadsItem(optionsItem)); } else if (optionsItem instanceof GpxLocalRoutingParameter) { - items.add(createGpxRoutingItem(optionsItem)); + if (!planRouteMode) { + items.add(createGpxRoutingItem(optionsItem)); + } } else if (optionsItem instanceof TimeConditionalRoutingItem) { items.add(createTimeConditionalRoutingItem(optionsItem)); } else if (optionsItem instanceof OtherSettingsRoutingParameter) { items.add(createOtherSettingsRoutingItem(optionsItem)); + } else if (USE_HEIGHT_OBSTACLES.equals(optionsItem.getKey()) && hasReliefParameters()) { + items.add(inflateElevationParameter(optionsItem)); } else { inflateRoutingParameter(optionsItem); } @@ -256,6 +293,62 @@ public class RouteOptionsBottomSheet extends MenuBottomSheetDialogFragment { .create(); } + private BaseBottomSheetItem inflateElevationParameter(final LocalRoutingParameter parameter) { + final BottomSheetItemWithCompoundButton[] item = new BottomSheetItemWithCompoundButton[1]; + final boolean active = !useHeightPref.getModeValue(applicationMode); + final View itemView = UiUtilities.getInflater(app, nightMode).inflate( + R.layout.bottom_sheet_item_with_switch_and_dialog, null, false); + final SwitchCompat switchButton = itemView.findViewById(R.id.compound_button); + View itemsContainer = itemView.findViewById(R.id.selectable_list_item); + itemsContainer.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (USE_HEIGHT_OBSTACLES.equals(parameter.getKey()) && hasReliefParameters()) { + FragmentManager fm = getFragmentManager(); + if (fm != null) { + ElevationDateBottomSheet.showInstance(fm, applicationMode, RouteOptionsBottomSheet.this, false); + } + } + } + }); + + switchButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + applyParameter(item[0], parameter); + item[0].setDescription(getElevationDescription(parameter)); + switchButton.setChecked(parameter.isSelected(settings)); + } + }); + + item[0] = (BottomSheetItemWithCompoundButton) new BottomSheetItemWithCompoundButton.Builder() + .setChecked(!active) + .setCompoundButtonColorId(selectedModeColorId) + .setDescription(getElevationDescription(parameter)) + .setIcon(getContentIcon(active ? parameter.getActiveIconId() : parameter.getDisabledIconId())) + .setTitle(getString(R.string.routing_attr_height_obstacles_name)) + .setCustomView(itemView) + .create(); + + return item[0]; + } + + private String getElevationDescription(LocalRoutingParameter parameter) { + String description; + if (parameter.isSelected(settings)) { + description = getString(R.string.shared_string_enabled); + for (RoutingParameter routingParameter : reliefParameters) { + if (isRoutingParameterSelected(settings, applicationMode, routingParameter)) { + description = getString(R.string.ltr_or_rtl_combine_via_comma, description, + getRoutingParameterTitle(app, routingParameter)); + } + } + } else { + description = getString(R.string.shared_string_disabled); + } + return description; + } + private BaseBottomSheetItem createTimeConditionalRoutingItem(final LocalRoutingParameter optionsItem) { final BottomSheetItemWithCompoundButton[] timeConditionalRoutingItem = new BottomSheetItemWithCompoundButton[1]; timeConditionalRoutingItem[0] = (BottomSheetItemWithCompoundButton) new BottomSheetItemWithCompoundButton.Builder() @@ -415,8 +508,10 @@ public class RouteOptionsBottomSheet extends MenuBottomSheetDialogFragment { @Override public void onClick(View view) { dismiss(); + Bundle args = new Bundle(); + args.putBoolean(PLANE_ROUTE, planRouteMode); BaseSettingsFragment.showInstance(mapActivity, BaseSettingsFragment.SettingsScreenType.NAVIGATION, - mapActivity.getRoutingHelper().getAppMode()); + applicationMode, args); } }) .create(); @@ -468,14 +563,7 @@ public class RouteOptionsBottomSheet extends MenuBottomSheetDialogFragment { builder.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - if (USE_HEIGHT_OBSTACLES.equals(parameter.getKey()) && hasReliefParameters()) { - FragmentManager fm = getFragmentManager(); - if (fm != null) { - ElevationDateBottomSheet.showInstance(fm, applicationMode, RouteOptionsBottomSheet.this, false); - } - } else { - applyParameter(item[0], parameter); - } + applyParameter(item[0], parameter); } }); } @@ -488,14 +576,19 @@ public class RouteOptionsBottomSheet extends MenuBottomSheetDialogFragment { } private boolean hasReliefParameters() { + return !Algorithms.isEmpty(reliefParameters); + } + + private List getReliefParameters() { + List reliefFactorParameters = new ArrayList<>(); Map parameters = app.getRouter(applicationMode).getParameters(); - for (Map.Entry e : parameters.entrySet()) { - RoutingParameter routingParameter = e.getValue(); + for (Map.Entry entry : parameters.entrySet()) { + RoutingParameter routingParameter = entry.getValue(); if (RELIEF_SMOOTHNESS_FACTOR.equals(routingParameter.getGroup())) { - return true; + reliefFactorParameters.add(routingParameter); } } - return false; + return reliefFactorParameters; } private void applyParameter(BottomSheetItemWithCompoundButton bottomSheetItem, LocalRoutingParameter parameter) { @@ -515,6 +608,23 @@ public class RouteOptionsBottomSheet extends MenuBottomSheetDialogFragment { if (mapActivity != null) { mapActivity.getMapRouteInfoMenu().updateMenu(); } + + } + + @Override + public void onDismiss(@NonNull DialogInterface dialog) { + super.onDismiss(dialog); + updatePlanRoute(); + } + + private void updatePlanRoute() { + MapActivity mapActivity = getMapActivity(); + if (mapActivity != null) { + Fragment fragment = mapActivity.getSupportFragmentManager().findFragmentByTag(MeasurementToolFragment.TAG); + if (fragment != null) { + ((MeasurementToolFragment) fragment).onChangeApplicationMode(applicationMode, WHOLE_ROUTE_CALCULATION, ALL); + } + } } private List getRoutingParameters(ApplicationMode applicationMode) { @@ -549,8 +659,21 @@ public class RouteOptionsBottomSheet extends MenuBottomSheetDialogFragment { } public static void showInstance(FragmentManager fragmentManager) { - RouteOptionsBottomSheet f = new RouteOptionsBottomSheet(); - f.show(fragmentManager, RouteOptionsBottomSheet.TAG); + showInstance(fragmentManager, null); + } + + public static void showInstance(FragmentManager fm, String appModeKey) { + try { + if (!fm.isStateSaved()) { + RouteOptionsBottomSheet fragment = new RouteOptionsBottomSheet(); + Bundle args = new Bundle(); + args.putString(APP_MODE_KEY, appModeKey); + fragment.setArguments(args); + fragment.show(fm, TAG); + } + } catch (RuntimeException e) { + LOG.error("showInstance", e); + } } public void updateParameters() { diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/FileSettingsItem.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/FileSettingsItem.java index 493e49fa07..88c72beddc 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/FileSettingsItem.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/FileSettingsItem.java @@ -129,6 +129,7 @@ public class FileSettingsItem extends StreamSettingsItem { } protected File file; + protected File savedFile; private final File appPath; protected FileSubtype subtype; private long size; @@ -280,18 +281,18 @@ public class FileSettingsItem extends StreamSettingsItem { @Override public void readFromStream(@NonNull InputStream inputStream, String entryName) throws IOException, IllegalArgumentException { OutputStream output; - File dest = FileSettingsItem.this.getFile(); - if (dest.isDirectory()) { - dest = new File(dest, entryName.substring(fileName.length())); + savedFile = FileSettingsItem.this.getFile(); + if (savedFile.isDirectory()) { + savedFile = new File(savedFile, entryName.substring(fileName.length())); } - if (dest.exists() && !shouldReplace) { - dest = renameFile(dest); + if (savedFile.exists() && !shouldReplace) { + savedFile = renameFile(savedFile); } - if (dest.getParentFile() != null && !dest.getParentFile().exists()) { + if (savedFile.getParentFile() != null && !savedFile.getParentFile().exists()) { //noinspection ResultOfMethodCallIgnored - dest.getParentFile().mkdirs(); + savedFile.getParentFile().mkdirs(); } - output = new FileOutputStream(dest); + output = new FileOutputStream(savedFile); byte[] buffer = new byte[SettingsHelper.BUFFER]; int count; try { @@ -303,7 +304,7 @@ public class FileSettingsItem extends StreamSettingsItem { Algorithms.closeStream(output); } if (lastModified != -1) { - dest.setLastModified(lastModified); + savedFile.setLastModified(lastModified); } } }; diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/GpxAppearanceInfo.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/GpxAppearanceInfo.java new file mode 100644 index 0000000000..157d5ecb0a --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/GpxAppearanceInfo.java @@ -0,0 +1,125 @@ +package net.osmand.plus.settings.backend.backup; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import net.osmand.GPXUtilities.GPXTrackAnalysis; +import net.osmand.plus.GPXDatabase.GpxDataItem; +import net.osmand.plus.track.GpxSplitType; +import net.osmand.plus.track.GradientScaleType; +import net.osmand.util.Algorithms; + +import org.json.JSONException; +import org.json.JSONObject; + +public class GpxAppearanceInfo { + + public String width; + public GradientScaleType scaleType; + public int color; + public int gradientSpeedColor; + public int gradientAltitudeColor; + public int gradientSlopeColor; + public int splitType; + public double splitInterval; + public boolean showArrows; + public boolean showStartFinish; + + public long timeSpan; + public int wptPoints; + public float totalDistance; + + public GpxAppearanceInfo() { + + } + + public GpxAppearanceInfo(@NonNull GpxDataItem dataItem) { + color = dataItem.getColor(); + width = dataItem.getWidth(); + showArrows = dataItem.isShowArrows(); + showStartFinish = dataItem.isShowStartFinish(); + splitType = dataItem.getSplitType(); + splitInterval = dataItem.getSplitInterval(); + scaleType = dataItem.getGradientScaleType(); + gradientSpeedColor = dataItem.getGradientSpeedColor(); + gradientSlopeColor = dataItem.getGradientSlopeColor(); + gradientAltitudeColor = dataItem.getGradientAltitudeColor(); + + GPXTrackAnalysis analysis = dataItem.getAnalysis(); + if (analysis != null) { + timeSpan = analysis.timeSpan; + wptPoints = analysis.wptPoints; + totalDistance = analysis.totalDistance; + } + } + + public void toJson(@NonNull JSONObject json) throws JSONException { + writeParam(json, "color", color); + writeParam(json, "width", width); + writeParam(json, "show_arrows", showArrows); + writeParam(json, "show_start_finish", showStartFinish); + writeParam(json, "split_type", GpxSplitType.getSplitTypeByTypeId(splitType).getTypeName()); + writeParam(json, "split_interval", splitInterval); + writeParam(json, "gradient_scale_type", scaleType); + writeParam(json, GradientScaleType.SPEED.getColorTypeName(), gradientSpeedColor); + writeParam(json, GradientScaleType.SLOPE.getColorTypeName(), gradientSlopeColor); + writeParam(json, GradientScaleType.ALTITUDE.getColorTypeName(), gradientAltitudeColor); + + writeParam(json, "time_span", timeSpan); + writeParam(json, "wpt_points", wptPoints); + writeParam(json, "total_distance", totalDistance); + } + + public static GpxAppearanceInfo fromJson(@NonNull JSONObject json) { + GpxAppearanceInfo gpxAppearanceInfo = new GpxAppearanceInfo(); + gpxAppearanceInfo.color = json.optInt("color"); + gpxAppearanceInfo.width = json.optString("width"); + gpxAppearanceInfo.showArrows = json.optBoolean("show_arrows"); + gpxAppearanceInfo.showStartFinish = json.optBoolean("show_start_finish"); + gpxAppearanceInfo.splitType = GpxSplitType.getSplitTypeByName(json.optString("split_type")).getType(); + gpxAppearanceInfo.splitInterval = json.optDouble("split_interval"); + gpxAppearanceInfo.scaleType = getScaleType(json.optString("gradient_scale_type")); + gpxAppearanceInfo.gradientSpeedColor = json.optInt(GradientScaleType.SPEED.getColorTypeName()); + gpxAppearanceInfo.gradientSlopeColor = json.optInt(GradientScaleType.SLOPE.getColorTypeName()); + gpxAppearanceInfo.gradientAltitudeColor = json.optInt(GradientScaleType.ALTITUDE.getColorTypeName()); + + gpxAppearanceInfo.timeSpan = json.optLong("time_span"); + gpxAppearanceInfo.wptPoints = json.optInt("wpt_points"); + gpxAppearanceInfo.totalDistance = (float) json.optDouble("total_distance"); + + return gpxAppearanceInfo; + } + + private static GradientScaleType getScaleType(String name) { + if (!Algorithms.isEmpty(name)) { + try { + return GradientScaleType.valueOf(name); + } catch (IllegalStateException e) { + SettingsHelper.LOG.error("Failed to read gradientScaleType", e); + } + } + return null; + } + + private static void writeParam(@NonNull JSONObject json, @NonNull String name, @Nullable Object value) throws JSONException { + if (value instanceof Integer) { + if ((Integer) value != 0) { + json.putOpt(name, value); + } + } else if (value instanceof Long) { + if ((Long) value != 0) { + json.putOpt(name, value); + } + } else if (value instanceof Double) { + if ((Double) value != 0.0 && !Double.isNaN((Double) value)) { + json.putOpt(name, value); + } + } else if (value instanceof String) { + if (!Algorithms.isEmpty((String) value)) { + json.putOpt(name, value); + } + } else if (value != null) { + json.putOpt(name, value); + } + } +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/GpxSettingsItem.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/GpxSettingsItem.java new file mode 100644 index 0000000000..b9c39026a9 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/GpxSettingsItem.java @@ -0,0 +1,104 @@ +package net.osmand.plus.settings.backend.backup; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import net.osmand.plus.GPXDatabase; +import net.osmand.plus.GPXDatabase.GpxDataItem; +import net.osmand.plus.GpxDbHelper; +import net.osmand.plus.GpxDbHelper.GpxDataItemCallback; +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.track.GpxSplitType; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.File; + +public class GpxSettingsItem extends FileSettingsItem { + + private GpxAppearanceInfo appearanceInfo; + + public GpxSettingsItem(@NonNull OsmandApplication app, @NonNull File file) throws IllegalArgumentException { + super(app, file); + createGpxAppearanceInfo(); + } + + GpxSettingsItem(@NonNull OsmandApplication app, @NonNull JSONObject json) throws JSONException { + super(app, json); + } + + @Nullable + public GpxAppearanceInfo getAppearanceInfo() { + return appearanceInfo; + } + + @NonNull + @Override + public SettingsItemType getType() { + return SettingsItemType.GPX; + } + + @Override + void readFromJson(@NonNull JSONObject json) throws JSONException { + subtype = FileSubtype.GPX; + super.readFromJson(json); + appearanceInfo = GpxAppearanceInfo.fromJson(json); + } + + @Override + void writeToJson(@NonNull JSONObject json) throws JSONException { + super.writeToJson(json); + if (appearanceInfo != null) { + appearanceInfo.toJson(json); + } + } + + @Override + public void applyAdditionalParams() { + if (appearanceInfo != null) { + GpxDataItem dataItem = app.getGpxDbHelper().getItem(savedFile, new GpxDataItemCallback() { + @Override + public boolean isCancelled() { + return false; + } + + @Override + public void onGpxDataItemReady(GpxDataItem item) { + updateGpxParams(item); + } + }); + if (dataItem != null) { + updateGpxParams(dataItem); + } + } + } + + private void updateGpxParams(@NonNull GPXDatabase.GpxDataItem dataItem) { + GpxDbHelper gpxDbHelper = app.getGpxDbHelper(); + GpxSplitType splitType = GpxSplitType.getSplitTypeByTypeId(appearanceInfo.splitType); + gpxDbHelper.updateColor(dataItem, appearanceInfo.color); + gpxDbHelper.updateWidth(dataItem, appearanceInfo.width); + gpxDbHelper.updateShowArrows(dataItem, appearanceInfo.showArrows); + gpxDbHelper.updateShowStartFinish(dataItem, appearanceInfo.showStartFinish); + gpxDbHelper.updateSplit(dataItem, splitType, appearanceInfo.splitInterval); + gpxDbHelper.updateGradientScaleType(dataItem, appearanceInfo.scaleType); + } + + private void createGpxAppearanceInfo() { + GpxDataItem dataItem = app.getGpxDbHelper().getItem(file, new GpxDataItemCallback() { + @Override + public boolean isCancelled() { + return false; + } + + @Override + public void onGpxDataItemReady(GPXDatabase.GpxDataItem item) { + appearanceInfo = new GpxAppearanceInfo(item); + } + }); + if (dataItem != null) { + appearanceInfo = new GpxAppearanceInfo(dataItem); + } + } +} diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/PluginSettingsItem.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/PluginSettingsItem.java index 32d6a04e22..203ea37661 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/PluginSettingsItem.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/PluginSettingsItem.java @@ -99,6 +99,7 @@ public class PluginSettingsItem extends SettingsItem { @Override void writeToJson(@NonNull JSONObject json) throws JSONException { super.writeToJson(json); + json.put("version", plugin.getVersion()); plugin.writeAdditionalDataToJson(json); } diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/ProfileSettingsItem.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/ProfileSettingsItem.java index 4ddb04daab..b0bfd5be61 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/ProfileSettingsItem.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/ProfileSettingsItem.java @@ -176,7 +176,7 @@ public class ProfileSettingsItem extends OsmandSettingsItem { ApplicationMode.changeProfileAvailability(appMode, true, app); } - public void applyAdditionalPrefs() { + public void applyAdditionalParams() { if (additionalPrefsJson != null) { updatePluginResPrefs(); diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsHelper.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsHelper.java index 6c3cf25178..44b1f44bf4 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsHelper.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsHelper.java @@ -95,6 +95,7 @@ public class SettingsHelper { public static final String SETTINGS_TYPE_LIST_KEY = "settings_type_list_key"; public static final String REPLACE_KEY = "replace"; + public static final String SILENT_IMPORT_KEY = "silent_import"; public static final String SETTINGS_LATEST_CHANGES_KEY = "settings_latest_changes"; public static final String SETTINGS_VERSION_KEY = "settings_version"; @@ -472,31 +473,31 @@ public class SettingsHelper { exportSettings(fileDir, fileName, listener, new ArrayList<>(Arrays.asList(items)), exportItemsFiles); } - public List getFilteredSettingsItems(List settingsTypes, boolean globalExport) { + public List getFilteredSettingsItems(List settingsTypes, boolean addProfiles, boolean export) { Map> typesMap = new HashMap<>(); - typesMap.putAll(getSettingsItems(globalExport)); + typesMap.putAll(getSettingsItems(addProfiles)); typesMap.putAll(getMyPlacesItems()); typesMap.putAll(getResourcesItems()); - return getFilteredSettingsItems(typesMap, settingsTypes); + return getFilteredSettingsItems(typesMap, settingsTypes, export); } public List getFilteredSettingsItems(Map> allSettingsMap, - List settingsTypes) { + List settingsTypes, boolean export) { List settingsItems = new ArrayList<>(); for (ExportSettingsType settingsType : settingsTypes) { List settingsDataObjects = allSettingsMap.get(settingsType); if (settingsDataObjects != null) { - settingsItems.addAll(prepareSettingsItems(new ArrayList<>(settingsDataObjects))); + settingsItems.addAll(prepareSettingsItems(settingsDataObjects, export)); } } return settingsItems; } - public Map getSettingsByCategory(boolean globalExport) { + public Map getSettingsByCategory(boolean addProfiles) { Map dataList = new LinkedHashMap<>(); - Map> settingsItems = getSettingsItems(globalExport); + Map> settingsItems = getSettingsItems(addProfiles); Map> myPlacesItems = getMyPlacesItems(); Map> resourcesItems = getResourcesItems(); @@ -513,10 +514,10 @@ public class SettingsHelper { return dataList; } - private Map> getSettingsItems(boolean globalExport) { + private Map> getSettingsItems(boolean addProfiles) { Map> settingsItems = new LinkedHashMap<>(); - if (globalExport) { + if (addProfiles) { List appModeBeans = new ArrayList<>(); for (ApplicationMode mode : ApplicationMode.allPossibleValues()) { appModeBeans.add(mode.toModeBean()); @@ -687,7 +688,7 @@ public class SettingsHelper { return files; } - public List prepareSettingsItems(List data) { + public List prepareSettingsItems(List data, boolean export) { List settingsItems = new ArrayList<>(); List quickActions = new ArrayList<>(); List poiUIFilters = new ArrayList<>(); @@ -710,7 +711,12 @@ public class SettingsHelper { tileSourceTemplates.add((ITileSource) object); } else if (object instanceof File) { try { - settingsItems.add(new FileSettingsItem(app, (File) object)); + File file = (File) object; + if (file.getName().endsWith(IndexConstants.GPX_FILE_EXT)) { + settingsItems.add(new GpxSettingsItem(app, file)); + } else { + settingsItems.add(new FileSettingsItem(app, file)); + } } catch (IllegalArgumentException e) { LOG.warn("Trying to export unsuported file type", e); } @@ -749,7 +755,14 @@ public class SettingsHelper { } if (!appModeBeans.isEmpty()) { for (ApplicationModeBean modeBean : appModeBeans) { - settingsItems.add(new ProfileSettingsItem(app, null, modeBean)); + if (export) { + ApplicationMode mode = ApplicationMode.valueOfStringKey(modeBean.stringKey, null); + if (mode != null) { + settingsItems.add(new ProfileSettingsItem(app, mode)); + } + } else { + settingsItems.add(new ProfileSettingsItem(app, null, modeBean)); + } } } if (!osmNotesPointList.isEmpty()) { @@ -924,6 +937,9 @@ public class SettingsHelper { SearchHistorySettingsItem searchHistorySettingsItem = (SearchHistorySettingsItem) item; historyEntries.addAll(searchHistorySettingsItem.getItems()); break; + case GPX: + tracksFilesList.add((GpxSettingsItem) item); + break; default: break; } diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsImporter.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsImporter.java index 66c40d03cc..77cadcdf1e 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsImporter.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsImporter.java @@ -128,6 +128,7 @@ class SettingsImporter { if (reader != null) { reader.readFromStream(ois, fileName); } + item.applyAdditionalParams(); } catch (IllegalArgumentException e) { item.warnings.add(app.getString(R.string.settings_item_read_error, item.getName())); SettingsHelper.LOG.error("Error reading item data: " + item.getName(), e); diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItem.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItem.java index 8b6736bf1d..6903a6bc43 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItem.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItem.java @@ -123,6 +123,10 @@ public abstract class SettingsItem { // non implemented } + public void applyAdditionalParams() { + // non implemented + } + void readFromJson(@NonNull JSONObject json) throws JSONException { pluginId = json.has("pluginId") ? json.getString("pluginId") : null; if (json.has("name")) { diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItemType.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItemType.java index 6664da22cc..9af8424ffc 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItemType.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItemType.java @@ -7,6 +7,7 @@ public enum SettingsItemType { DATA, FILE, RESOURCES, + GPX, QUICK_ACTIONS, POI_UI_FILTERS, MAP_SOURCES, diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItemsFactory.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItemsFactory.java index b19e95388c..39846f1826 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItemsFactory.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItemsFactory.java @@ -143,6 +143,9 @@ class SettingsItemsFactory { case SEARCH_HISTORY: item = new SearchHistorySettingsItem(app, json); break; + case GPX: + item = new GpxSettingsItem(app, json); + break; } return item; } diff --git a/OsmAnd/src/net/osmand/plus/settings/bottomsheets/BooleanPreferenceBottomSheet.java b/OsmAnd/src/net/osmand/plus/settings/bottomsheets/BooleanPreferenceBottomSheet.java index 98c4397327..21cd184cd4 100644 --- a/OsmAnd/src/net/osmand/plus/settings/bottomsheets/BooleanPreferenceBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/settings/bottomsheets/BooleanPreferenceBottomSheet.java @@ -119,7 +119,7 @@ public class BooleanPreferenceBottomSheet extends BasePreferenceBottomSheet { @Override protected int getDismissButtonTextId() { - return R.string.shared_string_cancel; + return R.string.shared_string_close; } protected static View getCustomButtonView(OsmandApplication app, ApplicationMode mode, boolean checked, boolean nightMode) { diff --git a/OsmAnd/src/net/osmand/plus/settings/bottomsheets/ElevationDateBottomSheet.java b/OsmAnd/src/net/osmand/plus/settings/bottomsheets/ElevationDateBottomSheet.java index 10f8c283f9..0d5d990eaf 100644 --- a/OsmAnd/src/net/osmand/plus/settings/bottomsheets/ElevationDateBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/settings/bottomsheets/ElevationDateBottomSheet.java @@ -2,6 +2,7 @@ package net.osmand.plus.settings.bottomsheets; import android.content.Context; import android.os.Bundle; +import android.os.Handler; import android.view.View; import android.widget.TextView; @@ -20,6 +21,7 @@ import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithCompoundButton; import net.osmand.plus.base.bottomsheetmenu.simpleitems.DividerSpaceItem; import net.osmand.plus.base.bottomsheetmenu.simpleitems.LongDescriptionItem; import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem; +import net.osmand.plus.routepreparationmenu.RouteOptionsBottomSheet; import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.settings.backend.CommonPreference; import net.osmand.plus.settings.fragments.ApplyQueryType; @@ -89,12 +91,17 @@ public class ElevationDateBottomSheet extends MenuBottomSheetDialogFragment { } } + @Override + protected int getDismissButtonTextId() { + return R.string.shared_string_close; + } + @Override public void createMenuItems(Bundle savedInstanceState) { Context themedCtx = UiUtilities.getThemedContext(requireContext(), nightMode); - on = getString(R.string.shared_string_enable); - off = getString(R.string.shared_string_disable); + on = getString(R.string.shared_string_enabled); + off = getString(R.string.shared_string_disabled); appModeColor = appMode.getIconColorInfo().getColor(nightMode); activeColor = AndroidUtils.resolveAttribute(themedCtx, R.attr.active_color_basic); disabledColor = AndroidUtils.resolveAttribute(themedCtx, android.R.attr.textColorSecondary); @@ -171,7 +178,20 @@ public class ElevationDateBottomSheet extends MenuBottomSheetDialogFragment { RoutingParameter parameter = parameters.get(selectedEntryIndex); updateSelectedParameters(app, appMode, parameters, parameter.getId()); } + Fragment target = getTargetFragment(); + if (target instanceof BaseSettingsFragment) { + ((BaseSettingsFragment) target).updateSetting(useHeightPref.getId()); + } + if (target instanceof RouteOptionsBottomSheet) { + ((RouteOptionsBottomSheet) target).updateParameters(); + } updateReliefButtons(); + app.runInUIThread(new Runnable() { + @Override + public void run() { + dismiss(); + } + }, 500); } }).create(); items.add(preferenceItem[0]); diff --git a/OsmAnd/src/net/osmand/plus/settings/bottomsheets/OsmLoginDataBottomSheet.java b/OsmAnd/src/net/osmand/plus/settings/bottomsheets/OsmLoginDataBottomSheet.java index 622fc11977..384f5457da 100644 --- a/OsmAnd/src/net/osmand/plus/settings/bottomsheets/OsmLoginDataBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/settings/bottomsheets/OsmLoginDataBottomSheet.java @@ -6,10 +6,10 @@ import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.widget.EditText; +import android.widget.ScrollView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.appcompat.content.res.AppCompatResources; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; @@ -44,6 +44,7 @@ public class OsmLoginDataBottomSheet extends BasePreferenceBottomSheet { LayoutInflater themedInflater = UiUtilities.getInflater(requireContext(), nightMode); View view = themedInflater.inflate(R.layout.osm_login_data, null); + view.getViewTreeObserver().addOnGlobalLayoutListener(getShadowLayoutListener()); userNameEditText = view.findViewById(R.id.name_edit_text); passwordEditText = view.findViewById(R.id.password_edit_text); @@ -73,6 +74,7 @@ public class OsmLoginDataBottomSheet extends BasePreferenceBottomSheet { items.add(titleItem); } + @Override public void onSaveInstanceState(@NonNull Bundle outState) { super.onSaveInstanceState(outState); @@ -107,7 +109,7 @@ public class OsmLoginDataBottomSheet extends BasePreferenceBottomSheet { } public static boolean showInstance(@NonNull FragmentManager fragmentManager, String key, Fragment target, - boolean usedOnMap, @Nullable ApplicationMode appMode) { + boolean usedOnMap, @Nullable ApplicationMode appMode) { try { Bundle args = new Bundle(); args.putString(PREFERENCE_ID, key); diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportItemsBottomSheet.java b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportItemsBottomSheet.java index f5d52366fe..f7d8c6ad6f 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportItemsBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportItemsBottomSheet.java @@ -54,6 +54,8 @@ import net.osmand.plus.settings.backend.ExportSettingsType; import net.osmand.plus.settings.backend.backup.FileSettingsItem; import net.osmand.plus.settings.backend.backup.FileSettingsItem.FileSubtype; import net.osmand.plus.settings.backend.backup.GlobalSettingsItem; +import net.osmand.plus.settings.backend.backup.GpxAppearanceInfo; +import net.osmand.plus.settings.backend.backup.GpxSettingsItem; import net.osmand.plus.settings.fragments.ExportSettingsAdapter.OnItemSelectedListener; import net.osmand.util.Algorithms; import net.osmand.view.ThreeStateCheckbox; @@ -313,11 +315,13 @@ public class ExportItemsBottomSheet extends MenuBottomSheetDialogFragment { builder.setTitle(tileSource.getName()); builder.setIcon(uiUtilities.getIcon(R.drawable.ic_map, activeColorRes)); } else if (object instanceof File) { - File file = (File) object; - setupBottomSheetItemForFile(builder, file, file.lastModified(), file.length()); + setupBottomSheetItemForFile(builder, (File) object); + } else if (object instanceof GpxSettingsItem) { + GpxSettingsItem item = (GpxSettingsItem) object; + setupBottomSheetItemForGpx(builder, item.getFile(), item.getAppearanceInfo()); } else if (object instanceof FileSettingsItem) { FileSettingsItem item = (FileSettingsItem) object; - setupBottomSheetItemForFile(builder, item.getFile(), item.getLastModified(), item.getSize()); + setupBottomSheetItemForFile(builder, item.getFile()); } else if (object instanceof AvoidRoadInfo) { AvoidRoadInfo avoidRoadInfo = (AvoidRoadInfo) object; builder.setTitle(avoidRoadInfo.name); @@ -361,7 +365,7 @@ public class ExportItemsBottomSheet extends MenuBottomSheetDialogFragment { } } - private void setupBottomSheetItemForFile(Builder builder, File file, long lastModified, long size) { + private void setupBottomSheetItemForFile(Builder builder, File file) { FileSubtype fileSubtype = FileSubtype.getSubtypeByPath(app, file.getPath()); builder.setTitle(file.getName()); if (file.getAbsolutePath().contains(IndexConstants.RENDERERS_DIR)) { @@ -369,17 +373,14 @@ public class ExportItemsBottomSheet extends MenuBottomSheetDialogFragment { } else if (file.getAbsolutePath().contains(IndexConstants.ROUTING_PROFILES_DIR)) { builder.setIcon(uiUtilities.getIcon(R.drawable.ic_action_route_distance, activeColorRes)); } else if (file.getAbsolutePath().contains(IndexConstants.GPX_INDEX_DIR)) { - builder.setTitle(GpxUiHelper.getGpxTitle(file.getName())); - builder.setTag(file); - builder.setDescription(getTrackDescr(file, lastModified, size)); - builder.setIcon(uiUtilities.getIcon(R.drawable.ic_action_route_distance, activeColorRes)); + setupBottomSheetItemForGpx(builder, file, null); } else if (file.getAbsolutePath().contains(IndexConstants.AV_INDEX_DIR)) { int iconId = AudioVideoNotesPlugin.getIconIdForRecordingFile(file); if (iconId == -1) { iconId = R.drawable.ic_action_photo_dark; } builder.setIcon(uiUtilities.getIcon(iconId, activeColorRes)); - builder.setDescription(AndroidUtils.formatSize(app, size)); + builder.setDescription(AndroidUtils.formatSize(app, file.length())); } else if (fileSubtype.isMap() || fileSubtype == FileSettingsItem.FileSubtype.TTS_VOICE || fileSubtype == FileSettingsItem.FileSubtype.VOICE) { @@ -388,7 +389,7 @@ public class ExportItemsBottomSheet extends MenuBottomSheetDialogFragment { if (fileSubtype.isMap()) { String mapDescription = getMapDescription(file); - String formattedSize = AndroidUtils.formatSize(app, size); + String formattedSize = AndroidUtils.formatSize(app, file.length()); if (mapDescription != null) { builder.setDescription(getString(R.string.ltr_or_rtl_combine_via_bold_point, mapDescription, formattedSize)); } else { @@ -398,6 +399,12 @@ public class ExportItemsBottomSheet extends MenuBottomSheetDialogFragment { } } + private void setupBottomSheetItemForGpx(Builder builder, File file, @Nullable GpxAppearanceInfo appearanceInfo) { + builder.setTitle(GpxUiHelper.getGpxTitle(file.getName())); + builder.setDescription(getTrackDescr(file, file.lastModified(), file.length(), appearanceInfo)); + builder.setIcon(uiUtilities.getIcon(R.drawable.ic_action_route_distance, activeColorRes)); + } + private final GpxDataItemCallback gpxDataItemCallback = new GpxDataItemCallback() { @Override public boolean isCancelled() { @@ -407,15 +414,18 @@ public class ExportItemsBottomSheet extends MenuBottomSheetDialogFragment { @Override public void onGpxDataItemReady(GpxDataItem item) { for (BaseBottomSheetItem bottomSheetItem : items) { - if (Algorithms.objectEquals(item.getFile(), bottomSheetItem.getTag())) { - ((BottomSheetItemWithDescription) bottomSheetItem).setDescription(getTrackDescrForDataItem(item)); - break; + Object tag = bottomSheetItem.getTag(); + if (tag instanceof FileSettingsItem) { + if (Algorithms.objectEquals(item.getFile(), ((FileSettingsItem) tag).getFile())) { + ((BottomSheetItemWithDescription) bottomSheetItem).setDescription(getTrackDescrForDataItem(item)); + break; + } } } } }; - private String getTrackDescr(@NonNull File file, long lastModified, long size) { + private String getTrackDescr(@NonNull File file, long lastModified, long size, GpxAppearanceInfo appearanceInfo) { String folder = ""; File parent = file.getParentFile(); if (parent != null) { @@ -426,6 +436,11 @@ public class ExportItemsBottomSheet extends MenuBottomSheetDialogFragment { if (dataItem != null) { return getTrackDescrForDataItem(dataItem); } + } else if (appearanceInfo != null) { + String dist = OsmAndFormatter.getFormattedDistance(appearanceInfo.totalDistance, app); + String points = appearanceInfo.wptPoints + " " + getString(R.string.shared_string_gpx_points).toLowerCase(); + String descr = getString(R.string.ltr_or_rtl_combine_via_bold_point, folder, dist); + return getString(R.string.ltr_or_rtl_combine_via_comma, descr, points); } else { String date = OsmAndFormatter.getFormattedDate(app, lastModified); String formattedSize = AndroidUtils.formatSize(app, size); diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportSettingsFragment.java b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportSettingsFragment.java index ad4e23aa11..586b6f0db3 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportSettingsFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportSettingsFragment.java @@ -24,14 +24,18 @@ import net.osmand.IndexConstants; import net.osmand.PlatformUtil; import net.osmand.plus.R; import net.osmand.plus.settings.backend.ApplicationMode; +import net.osmand.plus.settings.backend.ApplicationMode.ApplicationModeBean; +import net.osmand.plus.settings.backend.ExportSettingsType; import net.osmand.plus.settings.backend.backup.FileSettingsItem; import net.osmand.plus.settings.backend.backup.SettingsHelper.SettingsExportListener; import net.osmand.plus.settings.backend.backup.SettingsItem; +import net.osmand.util.Algorithms; import org.apache.commons.logging.Log; import java.io.File; import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Locale; @@ -73,7 +77,10 @@ public class ExportSettingsFragment extends BaseSettingsListFragment { progressValue = savedInstanceState.getInt(PROGRESS_VALUE_KEY); } exportMode = true; - dataList = app.getSettingsHelper().getSettingsByCategory(globalExport); + dataList = app.getSettingsHelper().getSettingsByCategory(true); + if (!globalExport && savedInstanceState == null) { + updateSelectedProfile(); + } } @Nullable @@ -122,6 +129,20 @@ public class ExportSettingsFragment extends BaseSettingsListFragment { } } + private void updateSelectedProfile() { + List profileItems = getItemsForType(ExportSettingsType.PROFILE); + if (!Algorithms.isEmpty(profileItems)) { + for (Object item : profileItems) { + if (item instanceof ApplicationModeBean && appMode.getStringKey().equals(((ApplicationModeBean) item).stringKey)) { + List selectedProfiles = new ArrayList<>(); + selectedProfiles.add(item); + selectedItemsMap.put(ExportSettingsType.PROFILE, selectedProfiles); + break; + } + } + } + } + private void prepareFile() { if (app != null) { exportingStarted = true; @@ -129,7 +150,7 @@ public class ExportSettingsFragment extends BaseSettingsListFragment { showExportProgressDialog(); File tempDir = FileUtils.getTempDir(app); String fileName = getFileName(); - List items = app.getSettingsHelper().prepareSettingsItems(adapter.getData()); + List items = app.getSettingsHelper().prepareSettingsItems(adapter.getData(), true); progress.setMax(getMaxProgress(items)); app.getSettingsHelper().exportSettings(tempDir, fileName, getSettingsExportListener(), items, true); } diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/ImportSettingsFragment.java b/OsmAnd/src/net/osmand/plus/settings/fragments/ImportSettingsFragment.java index 18e4f3cec5..b3039831a3 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/ImportSettingsFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/ImportSettingsFragment.java @@ -18,6 +18,7 @@ import androidx.fragment.app.FragmentManager; import com.google.android.material.appbar.CollapsingToolbarLayout; +import net.osmand.IndexConstants; import net.osmand.PlatformUtil; import net.osmand.map.ITileSource; import net.osmand.map.TileSourceManager.TileSourceTemplate; @@ -43,6 +44,7 @@ import net.osmand.plus.settings.backend.backup.AvoidRoadsSettingsItem; import net.osmand.plus.settings.backend.backup.FavoritesSettingsItem; import net.osmand.plus.settings.backend.backup.FileSettingsItem; import net.osmand.plus.settings.backend.backup.GlobalSettingsItem; +import net.osmand.plus.settings.backend.backup.GpxSettingsItem; import net.osmand.plus.settings.backend.backup.HistoryMarkersSettingsItem; import net.osmand.plus.settings.backend.backup.MapSourcesSettingsItem; import net.osmand.plus.settings.backend.backup.MarkersSettingsItem; @@ -349,7 +351,12 @@ public class ImportSettingsFragment extends BaseSettingsListFragment { } else if (object instanceof TileSourceTemplate || object instanceof SQLiteTileSource) { tileSourceTemplates.add((ITileSource) object); } else if (object instanceof File) { - settingsItems.add(new FileSettingsItem(app, (File) object)); + File file = (File) object; + if (file.getName().endsWith(IndexConstants.GPX_FILE_EXT)) { + settingsItems.add(new GpxSettingsItem(app, file)); + } else { + settingsItems.add(new FileSettingsItem(app, file)); + } } else if (object instanceof FileSettingsItem) { settingsItems.add((FileSettingsItem) object); } else if (object instanceof AvoidRoadInfo) { diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/NavigationFragment.java b/OsmAnd/src/net/osmand/plus/settings/fragments/NavigationFragment.java index cb9aba42dd..08ea81a092 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/NavigationFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/NavigationFragment.java @@ -3,9 +3,11 @@ package net.osmand.plus.settings.fragments; import android.graphics.drawable.Drawable; import android.os.Bundle; +import androidx.activity.OnBackPressedCallback; import androidx.preference.Preference; import androidx.preference.SwitchPreferenceCompat; +import net.osmand.plus.routepreparationmenu.RouteOptionsBottomSheet; import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandPlugin; @@ -33,6 +35,7 @@ import static net.osmand.plus.profiles.SelectProfileBottomSheetDialogFragment.IS import static net.osmand.plus.profiles.SelectProfileBottomSheetDialogFragment.PROFILE_KEY_ARG; import static net.osmand.plus.profiles.SelectProfileBottomSheetDialogFragment.SELECTED_KEY; import static net.osmand.plus.profiles.SelectProfileBottomSheetDialogFragment.TYPE_NAV_PROFILE; +import static net.osmand.plus.routepreparationmenu.RouteOptionsBottomSheet.PLANE_ROUTE; public class NavigationFragment extends BaseSettingsFragment { @@ -48,6 +51,16 @@ public class NavigationFragment extends BaseSettingsFragment { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); routingProfileDataObjects = getRoutingProfiles(app); + requireMyActivity().getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) { + public void handleOnBackPressed() { + Bundle args = getArguments(); + if (args != null && args.getBoolean(PLANE_ROUTE, false)) { + RouteOptionsBottomSheet.showInstance(getMapActivity().getSupportFragmentManager(), + getSelectedAppMode().getStringKey()); + } + dismiss(); + } + }); } @Override diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/RouteParametersFragment.java b/OsmAnd/src/net/osmand/plus/settings/fragments/RouteParametersFragment.java index f763d99896..00f0960dfe 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/RouteParametersFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/RouteParametersFragment.java @@ -285,12 +285,12 @@ public class RouteParametersFragment extends BaseSettingsFragment implements OnP if (p.getType() == RoutingParameterType.BOOLEAN) { OsmandPreference pref = settings.getCustomRoutingBooleanProperty(p.getId(), p.getDefaultBoolean()); - SwitchPreferenceEx switchPreferenceEx = (SwitchPreferenceEx) createSwitchPreferenceEx(pref.getId(), title, description, R.layout.preference_with_descr_dialog_and_switch); + SwitchPreferenceEx switchPreferenceEx = createSwitchPreferenceEx(pref.getId(), title, description, R.layout.preference_with_descr_dialog_and_switch); switchPreferenceEx.setDescription(description); switchPreferenceEx.setIcon(getRoutingPrefIcon(p.getId())); - switchPreferenceEx.setSummaryOn(R.string.shared_string_on); - switchPreferenceEx.setSummaryOff(R.string.shared_string_off); screen.addPreference(switchPreferenceEx); + + setupOtherBooleanParameterSummary(am, p, switchPreferenceEx); } else { Object[] vls = p.getPossibleValues(); String[] svlss = new String[vls.length]; @@ -340,6 +340,22 @@ public class RouteParametersFragment extends BaseSettingsFragment implements OnP setupFastRecalculationPref(); } + private void setupOtherBooleanParameterSummary(ApplicationMode am, RoutingParameter p, SwitchPreferenceEx switchPreferenceEx) { + if (USE_HEIGHT_OBSTACLES.equals(p.getId()) && !Algorithms.isEmpty(reliefFactorParameters)) { + String summaryOn = getString(R.string.shared_string_enabled); + for (RoutingParameter parameter : reliefFactorParameters) { + if (isRoutingParameterSelected(settings, am, parameter)) { + summaryOn = getString(R.string.ltr_or_rtl_combine_via_comma, summaryOn, getRoutingParameterTitle(app, parameter)); + } + } + switchPreferenceEx.setSummaryOn(summaryOn); + switchPreferenceEx.setSummaryOff(R.string.shared_string_disabled); + } else { + switchPreferenceEx.setSummaryOn(R.string.shared_string_on); + switchPreferenceEx.setSummaryOff(R.string.shared_string_off); + } + } + private void addDivider(PreferenceScreen screen) { Preference divider = new Preference(requireContext()); divider.setLayoutResource(R.layout.simple_divider_item); @@ -403,7 +419,7 @@ public class RouteParametersFragment extends BaseSettingsFragment implements OnP return; } final OsmandApplication app = (OsmandApplication) activity.getApplication(); - final float[] angleValue = new float[] {mode.getStrAngle()}; + final float[] angleValue = new float[]{mode.getStrAngle()}; boolean nightMode = !app.getSettings().isLightContentForMode(mode); Context themedContext = UiUtilities.getThemedContext(activity, nightMode); AlertDialog.Builder builder = new AlertDialog.Builder(themedContext); diff --git a/OsmAnd/src/net/osmand/plus/track/GpxSplitType.java b/OsmAnd/src/net/osmand/plus/track/GpxSplitType.java index ee539b8302..d10cd1e505 100644 --- a/OsmAnd/src/net/osmand/plus/track/GpxSplitType.java +++ b/OsmAnd/src/net/osmand/plus/track/GpxSplitType.java @@ -3,6 +3,7 @@ package net.osmand.plus.track; import android.content.Context; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.annotation.StringRes; import net.osmand.plus.R; @@ -36,21 +37,23 @@ public enum GpxSplitType { return ctx.getString(resId); } - public static GpxSplitType getSplitTypeByName(@NonNull String name) { + @NonNull + public static GpxSplitType getSplitTypeByName(@Nullable String name) { for (GpxSplitType splitType : GpxSplitType.values()) { if (splitType.name().equalsIgnoreCase(name)) { return splitType; } } - return null; + return NO_SPLIT; } + @NonNull public static GpxSplitType getSplitTypeByTypeId(int typeId) { for (GpxSplitType splitType : GpxSplitType.values()) { if (splitType.getType() == typeId) { return splitType; } } - return null; + return NO_SPLIT; } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/track/SaveGpxAsyncTask.java b/OsmAnd/src/net/osmand/plus/track/SaveGpxAsyncTask.java index 3b613e82c7..0f9ce671d3 100644 --- a/OsmAnd/src/net/osmand/plus/track/SaveGpxAsyncTask.java +++ b/OsmAnd/src/net/osmand/plus/track/SaveGpxAsyncTask.java @@ -12,12 +12,14 @@ import java.io.File; public class SaveGpxAsyncTask extends AsyncTask { + private final File file; private final GPXFile gpx; private final SaveGpxListener saveGpxListener; - public SaveGpxAsyncTask(@NonNull GPXFile gpx, - @Nullable SaveGpxListener saveGpxListener) { + public SaveGpxAsyncTask(@NonNull File file, @NonNull GPXFile gpx, + @Nullable SaveGpxListener saveGpxListener) { this.gpx = gpx; + this.file = file; this.saveGpxListener = saveGpxListener; } @@ -30,7 +32,7 @@ public class SaveGpxAsyncTask extends AsyncTask { @Override protected Exception doInBackground(Void... params) { - return GPXUtilities.writeGpxFile(new File(gpx.path), gpx); + return GPXUtilities.writeGpxFile(file, gpx); } @Override diff --git a/OsmAnd/src/net/osmand/plus/track/TrackAppearanceFragment.java b/OsmAnd/src/net/osmand/plus/track/TrackAppearanceFragment.java index f8a9ebbfc3..66b2a5f5a2 100644 --- a/OsmAnd/src/net/osmand/plus/track/TrackAppearanceFragment.java +++ b/OsmAnd/src/net/osmand/plus/track/TrackAppearanceFragment.java @@ -28,6 +28,7 @@ import net.osmand.PlatformUtil; 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.GpxDisplayItemType; import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile; @@ -70,6 +71,7 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement private static final String SHOW_START_FINISH_ICONS_INITIAL_VALUE_KEY = "showStartFinishIconsInitialValueKey"; private OsmandApplication app; + private GpxDbHelper gpxDbHelper; @Nullable private GpxDataItem gpxDataItem; @@ -128,6 +130,7 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); app = requireMyApplication(); + gpxDbHelper = app.getGpxDbHelper(); Bundle arguments = getArguments(); if (savedInstanceState != null) { @@ -138,7 +141,7 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(trackDrawInfo.getFilePath()); } if (!selectedGpxFile.isShowCurrentTrack()) { - gpxDataItem = app.getGpxDbHelper().getItem(new File(trackDrawInfo.getFilePath())); + gpxDataItem = gpxDbHelper.getItem(new File(trackDrawInfo.getFilePath())); } showStartFinishIconsInitialValue = savedInstanceState.getBoolean(SHOW_START_FINISH_ICONS_INITIAL_VALUE_KEY, app.getSettings().SHOW_START_FINISH_ICONS.get()); @@ -160,7 +163,7 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement trackDrawInfo.setShowStartFinish(app.getSettings().CURRENT_TRACK_SHOW_START_FINISH.get()); selectedGpxFile = app.getSavingTrackHelper().getCurrentTrack(); } else { - gpxDataItem = app.getGpxDbHelper().getItem(new File(gpxFilePath)); + gpxDataItem = gpxDbHelper.getItem(new File(gpxFilePath)); trackDrawInfo = new TrackDrawInfo(app, gpxDataItem, false); selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(gpxFilePath); } @@ -527,10 +530,10 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement } private void saveCustomColorsToTracks(int prevColor, int newColor) { - List gpxDataItems = app.getGpxDbHelper().getItems(); + List gpxDataItems = gpxDbHelper.getItems(); for (GpxDataItem dataItem : gpxDataItems) { if (prevColor == dataItem.getColor()) { - app.getGpxDbHelper().updateColor(dataItem, newColor); + gpxDbHelper.updateColor(dataItem, newColor); } } List files = app.getSelectedGpxHelper().getSelectedGPXFiles(); @@ -554,36 +557,19 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement private void saveTrackInfo() { GPXFile gpxFile = selectedGpxFile.getGpxFile(); - - gpxFile.setWidth(trackDrawInfo.getWidth()); - if (trackDrawInfo.getGradientScaleType() != null) { - gpxFile.setGradientScaleType(trackDrawInfo.getGradientScaleType().name()); - } else { - gpxFile.removeGradientScaleType(); - } - gpxFile.setColor(trackDrawInfo.getColor()); - - GpxSplitType splitType = GpxSplitType.getSplitTypeByTypeId(trackDrawInfo.getSplitType()); - if (splitType != null) { - gpxFile.setSplitType(splitType.getTypeName()); - } - - gpxFile.setSplitInterval(trackDrawInfo.getSplitInterval()); - gpxFile.setShowArrows(trackDrawInfo.isShowArrows()); - //gpxFile.setShowStartFinish(trackDrawInfo.isShowStartFinish()); - if (gpxFile.showCurrentTrack) { app.getSettings().CURRENT_TRACK_COLOR.set(trackDrawInfo.getColor()); app.getSettings().CURRENT_TRACK_WIDTH.set(trackDrawInfo.getWidth()); app.getSettings().CURRENT_TRACK_SHOW_ARROWS.set(trackDrawInfo.isShowArrows()); app.getSettings().CURRENT_TRACK_SHOW_START_FINISH.set(trackDrawInfo.isShowStartFinish()); - } else { - if (gpxDataItem != null) { - gpxDataItem = new GpxDataItem(new File(gpxFile.path), gpxFile); - app.getGpxDbHelper().add(gpxDataItem); - } - app.getSelectedGpxHelper().updateSelectedGpxFile(selectedGpxFile); - saveGpx(gpxFile); + } else if (gpxDataItem != null) { + GpxSplitType splitType = GpxSplitType.getSplitTypeByTypeId(trackDrawInfo.getSplitType()); + gpxDbHelper.updateColor(gpxDataItem, trackDrawInfo.getColor()); + gpxDbHelper.updateWidth(gpxDataItem, trackDrawInfo.getWidth()); + gpxDbHelper.updateShowArrows(gpxDataItem, trackDrawInfo.isShowArrows()); +// gpxDbHelper.updateShowStartFinish(gpxDataItem, trackDrawInfo.isShowStartFinish()); + gpxDbHelper.updateSplit(gpxDataItem, splitType, trackDrawInfo.getSplitInterval()); + gpxDbHelper.updateGradientScaleType(gpxDataItem, trackDrawInfo.getGradientScaleType()); } } @@ -594,9 +580,6 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement double distanceSplit = gpxDataItem.getSplitInterval(); GpxSplitType splitType = GpxSplitType.getSplitTypeByTypeId(gpxDataItem.getSplitType()); - if (splitType == null) { - splitType = GpxSplitType.NO_SPLIT; - } applySplit(splitType, timeSplit, distanceSplit); } } @@ -633,10 +616,6 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement timeSplit, distanceSplit).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } - private void saveGpx(final GPXFile gpxFile) { - new SaveGpxAsyncTask(gpxFile, null).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); - } - private void setupCards() { MapActivity mapActivity = getMapActivity(); if (mapActivity != null) { diff --git a/OsmAnd/src/net/osmand/plus/views/layers/GPXLayer.java b/OsmAnd/src/net/osmand/plus/views/layers/GPXLayer.java index 117c2a4777..688d114d03 100644 --- a/OsmAnd/src/net/osmand/plus/views/layers/GPXLayer.java +++ b/OsmAnd/src/net/osmand/plus/views/layers/GPXLayer.java @@ -33,6 +33,8 @@ import net.osmand.data.PointDescription; import net.osmand.data.QuadRect; import net.osmand.data.QuadTree; import net.osmand.data.RotatedTileBox; +import net.osmand.plus.GPXDatabase.GpxDataItem; +import net.osmand.plus.GpxDbHelper; import net.osmand.plus.GpxSelectionHelper; import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup; import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem; @@ -69,6 +71,7 @@ import net.osmand.util.MapUtils; import org.apache.commons.logging.Log; +import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -106,8 +109,10 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM private TrackDrawInfo trackDrawInfo; private TrackChartPoints trackChartPoints; - private GpxSelectionHelper selectedGpxHelper; + private GpxDbHelper gpxDbHelper; private MapMarkersHelper mapMarkersHelper; + private GpxSelectionHelper selectedGpxHelper; + private List cache = new ArrayList<>(); private Map pointFileMap = new HashMap<>(); private MapTextLayer textLayer; @@ -144,6 +149,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM @Override public void initLayer(OsmandMapTileView view) { this.view = view; + gpxDbHelper = view.getApplication().getGpxDbHelper(); selectedGpxHelper = view.getApplication().getSelectedGpxHelper(); mapMarkersHelper = view.getApplication().getMapMarkersHelper(); osmandRenderer = view.getApplication().getResourceManager().getRenderer().getRenderer(); @@ -303,6 +309,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM RenderingContext rc = new OsmandRenderer.RenderingContext(view.getContext()); rc.setDensityValue((float) tileBox.getMapDensity()); cachedColor = req.getIntPropertyValue(rrs.PROPS.R_COLOR); + defaultTrackWidth = rc.getComplexValue(req, req.ALL.R_STROKE_WIDTH); osmandRenderer.updatePaint(req, paint, 0, false, rc); if (req.isSpecified(rrs.PROPS.R_SHADOW_RADIUS)) { @@ -428,7 +435,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM boolean showArrows = isShowArrowsForTrack(selectedGpxFile.getGpxFile()); if (showArrows) { QuadRect correctedQuadRect = getCorrectedQuadRect(tileBox.getLatLonBounds()); - String width = getTrackWidthName(selectedGpxFile.getGpxFile(), ""); + String width = getTrackWidthName(selectedGpxFile.getGpxFile(), defaultTrackWidthPref.get()); float trackWidth = getTrackWidth(width, defaultTrackWidth); int trackColor = getTrackColor(selectedGpxFile.getGpxFile(), cachedColor); int arrowColor = UiUtilities.getContrastColor(view.getApplication(), trackColor, false); @@ -637,7 +644,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM List selectedGPXFiles, DrawSettings settings) { SelectedGpxFile currentTrack = null; for (SelectedGpxFile selectedGpxFile : selectedGPXFiles) { - String width = getTrackWidthName(selectedGpxFile.getGpxFile(), ""); + String width = getTrackWidthName(selectedGpxFile.getGpxFile(), defaultTrackWidthPref.get()); if (!cachedTrackWidth.containsKey(width)) { cachedTrackWidth.put(width, null); } @@ -656,7 +663,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM RotatedTileBox tileBox, DrawSettings settings) { List segments = selectedGpxFile.getPointsToDisplay(); for (TrkSegment ts : segments) { - String width = getTrackWidthName(selectedGpxFile.getGpxFile(), ""); + String width = getTrackWidthName(selectedGpxFile.getGpxFile(), defaultTrackWidthPref.get()); int color = getTrackColor(selectedGpxFile.getGpxFile(), ts.getColor(cachedColor)); if (ts.renderer == null && !ts.points.isEmpty()) { Renderable.RenderableSegment renderer; @@ -681,25 +688,31 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM } private int getTrackColor(GPXFile gpxFile, int defaultColor) { - int color; + int color = 0; if (hasTrackDrawInfoForTrack(gpxFile)) { color = trackDrawInfo.getColor(); } else if (gpxFile.showCurrentTrack) { color = currentTrackColorPref.get(); } else { - color = gpxFile.getColor(defaultColor); + GpxDataItem dataItem = gpxDbHelper.getItem(new File(gpxFile.path)); + if (dataItem != null) { + color = dataItem.getColor(); + } } return color != 0 ? color : defaultColor; } private String getTrackWidthName(GPXFile gpxFile, String defaultWidth) { - String width; + String width = null; if (hasTrackDrawInfoForTrack(gpxFile)) { width = trackDrawInfo.getWidth(); } else if (gpxFile.showCurrentTrack) { width = currentTrackWidthPref.get(); } else { - width = gpxFile.getWidth(defaultWidth); + GpxDataItem dataItem = gpxDbHelper.getItem(new File(gpxFile.path)); + if (dataItem != null) { + width = dataItem.getWidth(); + } } return width != null ? width : defaultWidth; } @@ -710,7 +723,11 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM } else if (gpxFile.showCurrentTrack) { return currentTrackShowArrowsPref.get(); } else { - return gpxFile.isShowArrows(); + GpxDataItem dataItem = gpxDbHelper.getItem(new File(gpxFile.path)); + if (dataItem != null) { + return dataItem.isShowArrows(); + } + return false; } } @@ -1027,7 +1044,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM callback.onApplyMovedObject(true, objectInMotion); } } else { - new SaveGpxAsyncTask(gpxFile, new SaveGpxAsyncTask.SaveGpxListener() { + new SaveGpxAsyncTask(new File(gpxFile.path), gpxFile, new SaveGpxAsyncTask.SaveGpxListener() { @Override public void gpxSavingStarted() {