Merge pull request #10356 from osmandapp/master

update test branch
This commit is contained in:
Hardy 2020-12-07 21:21:01 +01:00 committed by GitHub
commit d745c75bb8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
86 changed files with 2012 additions and 725 deletions

View file

@ -77,6 +77,7 @@ import net.osmand.aidlapi.customization.OsmandSettingsInfoParams;
import net.osmand.aidlapi.customization.CustomizationInfoParams; import net.osmand.aidlapi.customization.CustomizationInfoParams;
import net.osmand.aidlapi.customization.ProfileSettingsParams; import net.osmand.aidlapi.customization.ProfileSettingsParams;
import net.osmand.aidlapi.customization.MapMarginsParams; import net.osmand.aidlapi.customization.MapMarginsParams;
import net.osmand.aidlapi.customization.CustomPluginParams;
import net.osmand.aidlapi.gpx.AGpxFile; import net.osmand.aidlapi.gpx.AGpxFile;
import net.osmand.aidlapi.gpx.AGpxFileDetails; import net.osmand.aidlapi.gpx.AGpxFileDetails;
@ -883,4 +884,6 @@ interface IOsmAndAidlInterface {
* Is contect menu open. * Is contect menu open.
*/ */
boolean isMenuOpen(); boolean isMenuOpen();
int getPluginVersion(in CustomPluginParams params);
} }

View file

@ -0,0 +1,3 @@
package net.osmand.aidlapi.customization;
parcelable CustomPluginParams;

View file

@ -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<CustomPluginParams> CREATOR = new Creator<CustomPluginParams>() {
@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);
}
}

View file

@ -315,7 +315,7 @@ public class RouteSegmentResult implements StringExternalizable<RouteDataBundle>
int[] turnLanes = TurnType.lanesFromString(bundle.getString("turnLanes", null)); int[] turnLanes = TurnType.lanesFromString(bundle.getString("turnLanes", null));
turnType.setLanes(turnLanes); 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.types = bundle.getIntArray("types", null);
object.pointTypes = bundle.getIntIntArray("pointTypes", null); object.pointTypes = bundle.getIntIntArray("pointTypes", null);
object.nameIds = bundle.getIntArray("names", null); object.nameIds = bundle.getIntArray("names", null);

View file

@ -0,0 +1,10 @@
<inset xmlns:android="http://schemas.android.com/apk/res/android"
android:insetLeft="@dimen/map_button_inset_shadow"
android:insetTop="@dimen/map_button_inset_shadow"
android:insetRight="@dimen/map_button_inset_shadow"
android:insetBottom="@dimen/map_button_inset_shadow">
<shape android:shape="rectangle">
<solid android:color="@color/map_widget_dark" />
<corners android:radius="48dp" />
</shape>
</inset>

View file

@ -0,0 +1,10 @@
<inset xmlns:android="http://schemas.android.com/apk/res/android"
android:insetLeft="@dimen/map_button_inset_shadow"
android:insetTop="@dimen/map_button_inset_shadow"
android:insetRight="@dimen/map_button_inset_shadow"
android:insetBottom="@dimen/map_button_inset_shadow">
<shape android:shape="rectangle">
<solid android:color="@color/map_widget_light" />
<corners android:radius="48dp" />
</shape>
</inset>

View file

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape android:shape="oval">
<solid android:color="@color/map_widget_dark_pressed" />
</shape>
</item>
<item>
<shape android:shape="oval">
<solid android:color="@color/color_transparent" />
</shape>
</item>
</selector>

View file

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape android:shape="oval">
<solid android:color="@color/map_widget_light_pressed" />
</shape>
</item>
<item>
<shape android:shape="oval">
<solid android:color="@color/map_widget_light" />
</shape>
</item>
</selector>

View file

@ -0,0 +1,46 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M20,11H23C23.5523,11 24,11.4477 24,12C24,12.5523 23.5523,13 23,13H20V11Z">
<aapt:attr name="android:fillColor">
<gradient
android:startY="12"
android:startX="21"
android:endY="12"
android:endX="24"
android:type="linear">
<item android:offset="0" android:color="#FFFFFFFF"/>
<item android:offset="1" android:color="#00FFFFFF"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="M4,13H1C0.4477,13 0,12.5523 0,12C0,11.4477 0.4477,11 1,11H4V13Z">
<aapt:attr name="android:fillColor">
<gradient
android:startY="12"
android:startX="0"
android:endY="12"
android:endX="3"
android:type="linear">
<item android:offset="0" android:color="#00FFFFFF"/>
<item android:offset="1" android:color="#FFFFFFFF"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="M6,9C4.3432,9 3,10.3431 3,12C3,13.6569 4.3432,15 6,15C7.6568,15 9,13.6569 9,12C9,10.3431 7.6568,9 6,9ZM6,13C6.5523,13 7,12.5523 7,12C7,11.4477 6.5523,11 6,11C5.4477,11 5,11.4477 5,12C5,12.5523 5.4477,13 6,13Z"
android:fillColor="#ffffff"
android:fillType="evenOdd"/>
<path
android:pathData="M18,15C19.6569,15 21,13.6569 21,12C21,10.3431 19.6569,9 18,9C16.3431,9 15,10.3431 15,12C15,13.6569 16.3431,15 18,15ZM18,11C17.4477,11 17,11.4477 17,12C17,12.5523 17.4477,13 18,13C18.5523,13 19,12.5523 19,12C19,11.4477 18.5523,11 18,11Z"
android:fillColor="#ffffff"
android:fillType="evenOdd"/>
<path
android:pathData="M11,11C10.4477,11 10,11.4477 10,12C10,12.5523 10.4477,13 11,13H13C13.5523,13 14,12.5523 14,12C14,11.4477 13.5523,11 13,11H11Z"
android:fillColor="#ffffff"/>
</vector>

View file

@ -0,0 +1,27 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M14.8293,13C14.4175,14.1652 13.3062,15 12,15C10.3431,15 9,13.6569 9,12C9,10.3431 10.3431,9 12,9C13.3062,9 14.4175,9.8348 14.8293,11H21C21.5523,11 22,11.4477 22,12C22,12.5523 21.5523,13 21,13H14.8293ZM11,12C11,11.4477 11.4477,11 12,11C12.5523,11 13,11.4477 13,12C13,12.5523 12.5523,13 12,13C11.4477,13 11,12.5523 11,12Z"
android:fillType="evenOdd">
<aapt:attr name="android:fillColor">
<gradient
android:startY="12"
android:startX="12.25"
android:endY="12"
android:endX="22"
android:type="linear">
<item android:offset="0" android:color="#FFFFFFFF"/>
<item android:offset="1" android:color="#00FFFFFF"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="M2,12C2,11.4477 2.4477,11 3,11H6C6.5523,11 7,11.4477 7,12C7,12.5523 6.5523,13 6,13H3C2.4477,13 2,12.5523 2,12Z"
android:strokeAlpha="0.5"
android:fillColor="#ffffff"
android:fillAlpha="0.5"/>
</vector>

View file

@ -110,16 +110,31 @@
android:layout_marginStart="@dimen/map_button_spacing_land" android:layout_marginStart="@dimen/map_button_spacing_land"
android:background="@drawable/btn_round" android:background="@drawable/btn_round"
android:contentDescription="@string/layer_route" android:contentDescription="@string/layer_route"
tools:src="@drawable/ic_action_remove_dark"/> tools:src="@drawable/ic_action_remove_dark" />
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageButton
android:id="@+id/snap_to_road_image_button"
android:layout_width="@dimen/map_button_size"
android:layout_height="@dimen/map_button_size"
android:layout_gravity="bottom"
android:background="@drawable/btn_circle"
android:visibility="gone"
tools:src="@drawable/ic_action_remove_dark"
android:contentDescription="@string/snap_to_road" />
<include
android:id="@+id/profile_with_config_btn"
android:layout_width="wrap_content"
android:layout_height="@dimen/map_button_size"
android:layout_gravity="bottom"
layout="@layout/profile_with_config_btn_layout"
android:visibility="gone" />
</FrameLayout>
<ImageButton
android:id="@+id/snap_to_road_image_button"
android:layout_width="@dimen/map_button_size"
android:layout_height="@dimen/map_button_size"
android:layout_gravity="bottom"
android:background="@drawable/btn_circle"
android:visibility="gone"
tools:src="@drawable/ic_action_remove_dark"/>
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
</FrameLayout> </FrameLayout>

View file

@ -0,0 +1,81 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:osmand="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/list_background_color"
android:gravity="center_vertical">
<LinearLayout
android:id="@+id/selectable_list_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="@dimen/setting_list_item_large_height"
tools:background="?android:attr/selectableItemBackground">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/icon"
android:layout_width="@dimen/standard_icon_size"
android:layout_height="@dimen/standard_icon_size"
android:layout_gravity="center_vertical"
android:layout_marginStart="@dimen/content_padding"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginTop="@dimen/bottom_sheet_icon_margin"
android:layout_marginEnd="@dimen/bottom_sheet_icon_margin"
android:layout_marginRight="@dimen/bottom_sheet_icon_margin"
android:layout_marginBottom="@dimen/bottom_sheet_icon_margin"
osmand:srcCompat="@drawable/ic_action_altitude_average" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:orientation="vertical">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:fadingEdge="horizontal"
android:letterSpacing="@dimen/text_button_letter_spacing"
android:maxLines="2"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size"
osmand:typeface="@string/font_roboto_regular" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:letterSpacing="@dimen/description_letter_spacing"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_regular" />
</LinearLayout>
<View
android:layout_width="1dp"
android:layout_height="match_parent"
android:layout_marginTop="18dp"
android:layout_marginBottom="18dp"
android:background="?attr/divider_color_basic" />
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/compound_button"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="@null"
android:clickable="false"
android:focusable="false"
android:paddingStart="@dimen/content_padding"
android:paddingLeft="@dimen/content_padding"
android:paddingEnd="@dimen/content_padding"
android:paddingRight="@dimen/content_padding" />
</LinearLayout>
</LinearLayout>

View file

@ -106,15 +106,28 @@
android:contentDescription="@string/layer_route" android:contentDescription="@string/layer_route"
tools:src="@drawable/ic_action_remove_dark"/> tools:src="@drawable/ic_action_remove_dark"/>
<ImageButton <FrameLayout
android:id="@+id/snap_to_road_image_button" android:layout_width="wrap_content"
android:layout_width="@dimen/map_button_size" android:layout_height="wrap_content">
android:layout_height="@dimen/map_button_size"
android:layout_gravity="bottom" <ImageButton
android:background="@drawable/btn_circle" android:id="@+id/snap_to_road_image_button"
android:visibility="gone" android:layout_width="@dimen/map_button_size"
tools:src="@drawable/ic_action_remove_dark" android:layout_height="@dimen/map_button_size"
android:contentDescription="@string/snap_to_road" /> android:layout_gravity="bottom"
android:background="@drawable/btn_circle"
android:visibility="gone"
tools:src="@drawable/ic_action_remove_dark"
android:contentDescription="@string/snap_to_road" />
<include
android:id="@+id/profile_with_config_btn"
android:layout_width="wrap_content"
android:layout_height="@dimen/map_button_size"
android:layout_gravity="bottom"
layout="@layout/profile_with_config_btn_layout"
android:visibility="gone" />
</FrameLayout>
<LinearLayout <LinearLayout
android:id="@+id/map_ruler_container" android:id="@+id/map_ruler_container"

View file

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/btn_background"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:elevation="2dp">
<ImageButton
android:id="@+id/profile"
android:layout_width="@dimen/map_route_buttons_height_land"
android:layout_height="@dimen/map_route_buttons_height_land"
app:srcCompat="@drawable/ic_action_car_dark"
android:background="@color/color_transparent"
android:contentDescription="@string/app_modes_choose"/>
<View
android:id="@+id/divider"
android:layout_width="1dp"
android:layout_height="24dp"
android:background="?attr/divider_color"
android:layout_gravity="center_vertical"/>
<ImageButton
android:id="@+id/profile_config"
android:layout_width="@dimen/map_route_buttons_height_land"
android:layout_height="@dimen/map_route_buttons_height_land"
app:srcCompat="@drawable/ic_action_settings"
android:background="@color/color_transparent"
android:contentDescription="@string/configure_profile" />
</LinearLayout>
</LinearLayout>

View file

@ -59,31 +59,4 @@
android:padding="@dimen/content_padding" /> android:padding="@dimen/content_padding" />
</LinearLayout> </LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingLeft="@dimen/content_padding"
android:paddingTop="@dimen/content_padding_small"
android:paddingRight="@dimen/content_padding"
android:paddingBottom="@dimen/content_padding_small"
android:paddingEnd="@dimen/content_padding"
android:paddingStart="@dimen/content_padding">
<include
android:id="@+id/open_track_button"
layout="@layout/bottom_sheet_dialog_button" />
<View
android:id="@+id/buttons_divider"
android:layout_width="@dimen/content_padding"
android:layout_height="match_parent" />
<include
android:id="@+id/close_button"
layout="@layout/bottom_sheet_dialog_button" />
</LinearLayout>
</LinearLayout> </LinearLayout>

View file

@ -23,6 +23,7 @@
<attr name="btn_round" format="reference" /> <attr name="btn_round" format="reference" />
<attr name="btn_round_border" format="reference" /> <attr name="btn_round_border" format="reference" />
<attr name="btn_round_border_2" format="reference" /> <attr name="btn_round_border_2" format="reference" />
<attr name="bg_round_btn" format="reference" />
<attr name="bg_card" format="reference" /> <attr name="bg_card" format="reference" />
<attr name="context_menu_card" format="reference" /> <attr name="context_menu_card" format="reference" />
<attr name="ctx_menu_card_btn" format="reference" /> <attr name="ctx_menu_card_btn" format="reference" />

View file

@ -3998,7 +3998,7 @@
<string name="poi_vehicle_delivery">Vehicle access: delivery</string> <string name="poi_vehicle_delivery">Vehicle access: delivery</string>
<string name="poi_vehicle_forestry">Vehicle access: forestry</string> <string name="poi_vehicle_forestry">Vehicle access: forestry</string>
<string name="poi_motorcar_yes">Motorcar access: </string> <string name="poi_motorcar_yes">Motorcar access: yes</string>
<string name="poi_motorcar_private">Motorcar access: private</string> <string name="poi_motorcar_private">Motorcar access: private</string>
<string name="poi_motorcar_no">Motorcar access: no</string> <string name="poi_motorcar_no">Motorcar access: no</string>
<string name="poi_motorcar_destination">Motorcar access: destination</string> <string name="poi_motorcar_destination">Motorcar access: destination</string>
@ -4306,4 +4306,6 @@
<string name="poi_siren">Siren</string> <string name="poi_siren">Siren</string>
<string name="poi_lifeguard_base">Lifeguard base</string>
</resources> </resources>

View file

@ -11,6 +11,16 @@
Thx - Hardy Thx - Hardy
--> -->
<string name="release_3_9">
• 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
</string>
<string name="plan_route_add_new_segment">Add new segment</string>
<string name="plan_route_split_after">Split after</string>
<string name="plan_route_split_before">Split before</string>
<string name="plan_route_join_segments">Join segments</string>
<string name="app_mode_light_aircraft">Light aircraft</string> <string name="app_mode_light_aircraft">Light aircraft</string>
<string name="elevation_data">You can use Elevation data for consideration of Ascent / Descent for your trip</string> <string name="elevation_data">You can use Elevation data for consideration of Ascent / Descent for your trip</string>
<string name="ltr_or_rtl_combine_via_star">%1$s * %2$s</string> <string name="ltr_or_rtl_combine_via_star">%1$s * %2$s</string>

View file

@ -96,6 +96,7 @@
<item name="btn_round">@drawable/btn_round_light</item> <item name="btn_round">@drawable/btn_round_light</item>
<item name="btn_round_border">@drawable/btn_round_border_light</item> <item name="btn_round_border">@drawable/btn_round_border_light</item>
<item name="btn_round_border_2">@drawable/btn_round_border_light_2</item> <item name="btn_round_border_2">@drawable/btn_round_border_light_2</item>
<item name="bg_round_btn">@drawable/bg_round_btn_light</item>
<item name="bg_card">@drawable/bg_card_light</item> <item name="bg_card">@drawable/bg_card_light</item>
<item name="context_menu_card">@drawable/context_menu_card_light</item> <item name="context_menu_card">@drawable/context_menu_card_light</item>
<item name="bg_map_context_menu">@drawable/bg_map_context_menu_light</item> <item name="bg_map_context_menu">@drawable/bg_map_context_menu_light</item>
@ -400,6 +401,7 @@
<item name="btn_round">@drawable/btn_round_dark</item> <item name="btn_round">@drawable/btn_round_dark</item>
<item name="btn_round_border">@drawable/btn_round_border_dark</item> <item name="btn_round_border">@drawable/btn_round_border_dark</item>
<item name="btn_round_border_2">@drawable/btn_round_border_dark_2</item> <item name="btn_round_border_2">@drawable/btn_round_border_dark_2</item>
<item name="bg_round_btn">@drawable/bg_round_btn_dark</item>
<item name="bg_card">@drawable/bg_card_dark</item> <item name="bg_card">@drawable/bg_card_dark</item>
<item name="context_menu_card">@drawable/context_menu_card_dark</item> <item name="context_menu_card">@drawable/context_menu_card_dark</item>
<item name="bg_map_context_menu">@drawable/bg_map_context_menu_dark</item> <item name="bg_map_context_menu">@drawable/bg_map_context_menu_dark</item>

View file

@ -10,7 +10,6 @@ import android.content.res.Configuration;
import android.content.res.Resources; import android.content.res.Resources;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix; import android.graphics.Matrix;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.PointF; import android.graphics.PointF;

View file

@ -50,6 +50,7 @@ import net.osmand.plus.AppInitializer.AppInitializeListener;
import net.osmand.plus.AppInitializer.InitEvents; import net.osmand.plus.AppInitializer.InitEvents;
import net.osmand.plus.ContextMenuAdapter; import net.osmand.plus.ContextMenuAdapter;
import net.osmand.plus.ContextMenuItem; import net.osmand.plus.ContextMenuItem;
import net.osmand.plus.CustomOsmandPlugin;
import net.osmand.plus.FavouritesDbHelper; import net.osmand.plus.FavouritesDbHelper;
import net.osmand.plus.GPXDatabase.GpxDataItem; import net.osmand.plus.GPXDatabase.GpxDataItem;
import net.osmand.plus.GpxSelectionHelper; 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_PACKAGE_NAME;
import static net.osmand.aidl.ConnectedApp.AIDL_REMOVE_MAP_LAYER; import static net.osmand.aidl.ConnectedApp.AIDL_REMOVE_MAP_LAYER;
import static net.osmand.aidl.ConnectedApp.AIDL_REMOVE_MAP_WIDGET; 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_IO_ERROR;
import static net.osmand.aidlapi.OsmandAidlConstants.COPY_FILE_MAX_LOCK_TIME_MS; import static net.osmand.aidlapi.OsmandAidlConstants.COPY_FILE_MAX_LOCK_TIME_MS;
import static net.osmand.aidlapi.OsmandAidlConstants.COPY_FILE_PARAMS_ERROR; 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_DISTANCE;
import static net.osmand.plus.helpers.ExternalApiHelper.PARAM_NT_IMMINENT; 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.REPLACE_KEY;
import static net.osmand.plus.settings.backend.backup.SettingsHelper.SILENT_IMPORT_KEY;
public class OsmandAidlApi { public class OsmandAidlApi {
@ -2233,11 +2236,12 @@ public class OsmandAidlApi {
} }
public boolean importProfileV2(final Uri profileUri, ArrayList<String> settingsTypeKeys, boolean replace, public boolean importProfileV2(final Uri profileUri, ArrayList<String> settingsTypeKeys, boolean replace,
String latestChanges, int version) { String latestChanges, int version) {
if (profileUri != null) { if (profileUri != null) {
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putStringArrayList(SettingsHelper.SETTINGS_TYPE_LIST_KEY, settingsTypeKeys); bundle.putStringArrayList(SettingsHelper.SETTINGS_TYPE_LIST_KEY, settingsTypeKeys);
bundle.putBoolean(REPLACE_KEY, replace); bundle.putBoolean(REPLACE_KEY, replace);
bundle.putBoolean(SILENT_IMPORT_KEY, true);
bundle.putString(SettingsHelper.SETTINGS_LATEST_CHANGES_KEY, latestChanges); bundle.putString(SettingsHelper.SETTINGS_LATEST_CHANGES_KEY, latestChanges);
bundle.putInt(SettingsHelper.SETTINGS_VERSION_KEY, version); bundle.putInt(SettingsHelper.SETTINGS_VERSION_KEY, version);
@ -2309,7 +2313,7 @@ public class OsmandAidlApi {
File exportDir = app.getSettings().getExternalStorageDirectory(); File exportDir = app.getSettings().getExternalStorageDirectory();
String fileName = appMode.toHumanString(); String fileName = appMode.toHumanString();
SettingsHelper settingsHelper = app.getSettingsHelper(); SettingsHelper settingsHelper = app.getSettingsHelper();
settingsItems.addAll(settingsHelper.getFilteredSettingsItems(settingsTypes, false)); settingsItems.addAll(settingsHelper.getFilteredSettingsItems(settingsTypes, false, true));
settingsHelper.exportSettings(exportDir, fileName, null, settingsItems, true); settingsHelper.exportSettings(exportDir, fileName, null, settingsItems, true);
return true; return true;
} }
@ -2324,6 +2328,15 @@ public class OsmandAidlApi {
return mapActivity.getContextMenu().isVisible(); 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 { private static class FileCopyInfo {
long startTime; long startTime;
long lastAccessTime; long lastAccessTime;

View file

@ -22,9 +22,9 @@ import net.osmand.aidlapi.contextmenu.ContextMenuButtonsParams;
import net.osmand.aidlapi.contextmenu.RemoveContextMenuButtonsParams; import net.osmand.aidlapi.contextmenu.RemoveContextMenuButtonsParams;
import net.osmand.aidlapi.contextmenu.UpdateContextMenuButtonsParams; import net.osmand.aidlapi.contextmenu.UpdateContextMenuButtonsParams;
import net.osmand.aidlapi.copyfile.CopyFileParams; import net.osmand.aidlapi.copyfile.CopyFileParams;
import net.osmand.aidlapi.customization.MapMarginsParams; import net.osmand.aidlapi.customization.CustomPluginParams;
import net.osmand.aidlapi.info.AppInfoParams;
import net.osmand.aidlapi.customization.CustomizationInfoParams; import net.osmand.aidlapi.customization.CustomizationInfoParams;
import net.osmand.aidlapi.customization.MapMarginsParams;
import net.osmand.aidlapi.customization.OsmandSettingsInfoParams; import net.osmand.aidlapi.customization.OsmandSettingsInfoParams;
import net.osmand.aidlapi.customization.OsmandSettingsParams; import net.osmand.aidlapi.customization.OsmandSettingsParams;
import net.osmand.aidlapi.customization.ProfileSettingsParams; 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.ShowGpxParams;
import net.osmand.aidlapi.gpx.StartGpxRecordingParams; import net.osmand.aidlapi.gpx.StartGpxRecordingParams;
import net.osmand.aidlapi.gpx.StopGpxRecordingParams; import net.osmand.aidlapi.gpx.StopGpxRecordingParams;
import net.osmand.aidlapi.info.AppInfoParams;
import net.osmand.aidlapi.lock.SetLockStateParams; import net.osmand.aidlapi.lock.SetLockStateParams;
import net.osmand.aidlapi.map.ALatLon; import net.osmand.aidlapi.map.ALatLon;
import net.osmand.aidlapi.map.SetMapLocationParams; import net.osmand.aidlapi.map.SetMapLocationParams;
@ -1122,6 +1123,7 @@ public class OsmandAidlServiceV2 extends Service implements AidlCallbackListener
return UNKNOWN_API_ERROR; return UNKNOWN_API_ERROR;
} }
} }
@Override @Override
public long registerForKeyEvents(AKeyEventsParams params, final IOsmAndAidlCallback callback) { public long registerForKeyEvents(AKeyEventsParams params, final IOsmAndAidlCallback callback) {
try { try {
@ -1356,6 +1358,20 @@ public class OsmandAidlServiceV2 extends Service implements AidlCallbackListener
return false; 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) { private void setCustomization(OsmandAidlApi api, CustomizationInfoParams params) {

View file

@ -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 VECTOR_INDEXES_CHECK = "VECTOR_INDEXES_CHECK"; //$NON-NLS-1$
private static final String EXCEPTION_FILE_SIZE = "EXCEPTION_FS"; //$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 String LATEST_CHANGES_URL = null; // not enough to read
public static final int APP_EXIT_CODE = 4; public static final int APP_EXIT_CODE = 4;
public static final String APP_EXIT_KEY = "APP_EXIT_KEY"; public static final String APP_EXIT_KEY = "APP_EXIT_KEY";

View file

@ -17,16 +17,6 @@ import net.osmand.PlatformUtil;
import net.osmand.data.LatLon; import net.osmand.data.LatLon;
import net.osmand.map.ITileSource; import net.osmand.map.ITileSource;
import net.osmand.map.WorldRegion; 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.DownloadActivityType;
import net.osmand.plus.download.DownloadIndexesThread; import net.osmand.plus.download.DownloadIndexesThread;
import net.osmand.plus.download.DownloadResources; 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.poi.PoiUIFilter;
import net.osmand.plus.quickaction.QuickAction; import net.osmand.plus.quickaction.QuickAction;
import net.osmand.plus.quickaction.QuickActionRegistry; 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 net.osmand.util.Algorithms;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
@ -73,9 +73,12 @@ public class CustomOsmandPlugin extends OsmandPlugin {
private List<SuggestedDownloadItem> suggestedDownloadItems = new ArrayList<>(); private List<SuggestedDownloadItem> suggestedDownloadItems = new ArrayList<>();
private List<WorldRegion> customRegions = new ArrayList<>(); private List<WorldRegion> customRegions = new ArrayList<>();
private int version;
public CustomOsmandPlugin(@NonNull OsmandApplication app, @NonNull JSONObject json) throws JSONException { public CustomOsmandPlugin(@NonNull OsmandApplication app, @NonNull JSONObject json) throws JSONException {
super(app); super(app);
pluginId = json.getString("pluginId"); pluginId = json.getString("pluginId");
version = json.optInt("version", -1);
readAdditionalDataFromJson(json); readAdditionalDataFromJson(json);
readDependentFilesFromJson(json); readDependentFilesFromJson(json);
loadResources(); loadResources();
@ -86,6 +89,11 @@ public class CustomOsmandPlugin extends OsmandPlugin {
return pluginId; return pluginId;
} }
@Override
public int getVersion() {
return version;
}
@Override @Override
public String getName() { public String getName() {
return JsonUtils.getLocalizedResFromMap(app, names, app.getString(R.string.custom_osmand_plugin)); return JsonUtils.getLocalizedResFromMap(app, names, app.getString(R.string.custom_osmand_plugin));

View file

@ -23,16 +23,15 @@ import net.osmand.PlatformUtil;
import net.osmand.StateChangedListener; import net.osmand.StateChangedListener;
import net.osmand.data.LatLon; import net.osmand.data.LatLon;
import net.osmand.plus.GPXDatabase.GpxDataItem; 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.activities.SavingTrackHelper;
import net.osmand.plus.helpers.GpxUiHelper; import net.osmand.plus.helpers.GpxUiHelper;
import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetAxisType; import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetAxisType;
import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetType; import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetType;
import net.osmand.plus.routing.RouteProvider;
import net.osmand.plus.helpers.enums.MetricsConstants; 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.GpxSplitType;
import net.osmand.plus.track.GradientScaleType;
import net.osmand.util.Algorithms; import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
@ -60,17 +59,13 @@ public class GpxSelectionHelper {
private static final String BACKUP = "backup"; private static final String BACKUP = "backup";
private static final String BACKUPMODIFIEDTIME = "backupTime"; private static final String BACKUPMODIFIEDTIME = "backupTime";
private static final String COLOR = "color"; 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 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 OsmandApplication app;
private SavingTrackHelper savingTrackHelper;
@NonNull @NonNull
private List<SelectedGpxFile> selectedGPXFiles = new ArrayList<>(); private List<SelectedGpxFile> selectedGPXFiles = new ArrayList<>();
private Map<GPXFile, Long> selectedGpxFilesBackUp = new HashMap<>(); private Map<GPXFile, Long> selectedGpxFilesBackUp = new HashMap<>();
private SavingTrackHelper savingTrackHelper;
private SelectGpxTask selectGpxTask; private SelectGpxTask selectGpxTask;
private SelectedGpxFile trackToFollow; private SelectedGpxFile trackToFollow;
private StateChangedListener<String> followTrackListener; private StateChangedListener<String> followTrackListener;
@ -231,22 +226,20 @@ public class GpxSelectionHelper {
List<GpxDisplayGroup> groups = app.getSelectedGpxHelper().collectDisplayGroups(gpxFile); List<GpxDisplayGroup> groups = app.getSelectedGpxHelper().collectDisplayGroups(gpxFile);
GpxSplitType splitType = GpxSplitType.getSplitTypeByTypeId(dataItem.getSplitType()); GpxSplitType splitType = GpxSplitType.getSplitTypeByTypeId(dataItem.getSplitType());
if (splitType != null) { if (splitType == GpxSplitType.NO_SPLIT) {
if (splitType == GpxSplitType.NO_SPLIT) { for (GpxDisplayGroup model : groups) {
for (GpxDisplayGroup model : groups) { model.noSplit(app);
model.noSplit(app); }
} } else if (splitType == GpxSplitType.DISTANCE) {
} else if (splitType == GpxSplitType.DISTANCE) { for (GpxDisplayGroup model : groups) {
for (GpxDisplayGroup model : groups) { model.splitByDistance(app, dataItem.getSplitInterval(), dataItem.isJoinSegments());
model.splitByDistance(app, dataItem.getSplitInterval(), dataItem.isJoinSegments()); }
} } else if (splitType == GpxSplitType.TIME) {
} else if (splitType == GpxSplitType.TIME) { for (GpxDisplayGroup model : groups) {
for (GpxDisplayGroup model : groups) { model.splitByTime(app, (int) dataItem.getSplitInterval(), dataItem.isJoinSegments());
model.splitByTime(app, (int) dataItem.getSplitInterval(), dataItem.isJoinSegments());
}
} }
selectedGpxFile.setDisplayGroups(groups, app);
} }
selectedGpxFile.setDisplayGroups(groups, app);
} }
} }
return true; return true;
@ -579,24 +572,6 @@ public class GpxSelectionHelper {
int clr = parseColor(obj.getString(COLOR)); int clr = parseColor(obj.getString(COLOR));
gpx.setColor(clr); 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) { if (gpx.error != null) {
save = true; save = true;
} else if (obj.has(BACKUP)) { } else if (obj.has(BACKUP)) {
@ -644,20 +619,6 @@ public class GpxSelectionHelper {
if (s.gpxFile.getColor(0) != 0) { if (s.gpxFile.getColor(0) != 0) {
obj.put(COLOR, Algorithms.colorToString(s.gpxFile.getColor(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); obj.put(SELECTED_BY_USER, s.selectedByUser);
} catch (JSONException e) { } catch (JSONException e) {
@ -710,23 +671,6 @@ public class GpxSelectionHelper {
if (dataItem.getColor() != 0) { if (dataItem.getColor() != 0) {
gpx.setColor(dataItem.getColor()); 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.setJoinSegments(dataItem.isJoinSegments());
} }
sf.setGpxFile(gpx, app); sf.setGpxFile(gpx, app);

View file

@ -519,7 +519,11 @@ public class OsmAndFormatter {
result.append(r); result.append(r);
} else if (outputFormat == MGRS_FORMAT) { } else if (outputFormat == MGRS_FORMAT) {
MGRSPoint pnt = new MGRSPoint(new LatLonPoint(lat, lon)); 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(); return result.toString();
} }
@ -573,4 +577,4 @@ public class OsmAndFormatter {
coordinate *= 60.0; coordinate *= 60.0;
return coordinate; return coordinate;
} }
} }

View file

@ -123,8 +123,8 @@ public abstract class OsmandPlugin {
return null; return null;
} }
public String getVersion() { public int getVersion() {
return ""; return -1;
} }
/** /**
@ -340,6 +340,7 @@ public abstract class OsmandPlugin {
try { try {
JSONObject json = new JSONObject(); JSONObject json = new JSONObject();
json.put("pluginId", plugin.getId()); json.put("pluginId", plugin.getId());
json.put("version", plugin.getVersion());
plugin.writeAdditionalDataToJson(json); plugin.writeAdditionalDataToJson(json);
plugin.writeDependentFilesJson(json); plugin.writeDependentFilesJson(json);
itemsJson.put(json); itemsJson.put(json);

View file

@ -42,6 +42,8 @@ import net.osmand.plus.settings.fragments.BaseSettingsFragment.SettingsScreenTyp
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class PluginsFragment extends BaseOsmAndFragment implements PluginStateListener { public class PluginsFragment extends BaseOsmAndFragment implements PluginStateListener {
@ -138,6 +140,10 @@ public class PluginsFragment extends BaseOsmAndFragment implements PluginStateLi
private void switchEnabled(@NonNull ConnectedApp connectedApp) { private void switchEnabled(@NonNull ConnectedApp connectedApp) {
app.getAidlApi().switchEnabled(connectedApp); app.getAidlApi().switchEnabled(connectedApp);
OsmandPlugin plugin = OsmandPlugin.getPlugin(connectedApp.getPack());
if (plugin != null) {
OsmandPlugin.enablePlugin(getActivity(), app, plugin, connectedApp.isEnabled());
}
adapter.notifyDataSetChanged(); adapter.notifyDataSetChanged();
} }
@ -150,8 +156,26 @@ public class PluginsFragment extends BaseOsmAndFragment implements PluginStateLi
PluginsListAdapter(Context context) { PluginsListAdapter(Context context) {
super(context, R.layout.plugins_list_item, new ArrayList<>()); super(context, R.layout.plugins_list_item, new ArrayList<>());
addAll(app.getAidlApi().getConnectedApps()); addAll(getFilteredPluginsAndApps());
addAll(OsmandPlugin.getVisiblePlugins()); }
private List<Object> getFilteredPluginsAndApps() {
List<ConnectedApp> connectedApps = app.getAidlApi().getConnectedApps();
List<OsmandPlugin> visiblePlugins = OsmandPlugin.getVisiblePlugins();
for (Iterator<OsmandPlugin> iterator = visiblePlugins.iterator(); iterator.hasNext(); ) {
OsmandPlugin plugin = iterator.next();
for (ConnectedApp app : connectedApps) {
if (plugin.getId().equals(app.getPack())) {
iterator.remove();
}
}
}
List<Object> list = new ArrayList<>();
list.addAll(connectedApps);
list.addAll(visiblePlugins);
return list;
} }
@NonNull @NonNull

View file

@ -16,6 +16,7 @@ import android.view.ViewTreeObserver.OnScrollChangedListener;
import android.view.Window; import android.view.Window;
import android.view.WindowManager; import android.view.WindowManager;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.ScrollView;
import androidx.annotation.ColorInt; import androidx.annotation.ColorInt;
import androidx.annotation.ColorRes; 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) { protected void drawTopShadow(boolean showTopShadow) {
final Activity activity = getActivity(); final Activity activity = getActivity();
View mainView = getView(); 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);
}
}
} }

View file

@ -30,7 +30,7 @@ public class WhatsNewDialogFragment extends DialogFragment {
final OsmandApplication osmandApplication = (OsmandApplication) getActivity().getApplication(); final OsmandApplication osmandApplication = (OsmandApplication) getActivity().getApplication();
final String appVersion = Version.getAppVersion(osmandApplication); final String appVersion = Version.getAppVersion(osmandApplication);
builder.setTitle(getString(R.string.whats_new) + " " + appVersion) 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); .setNegativeButton(R.string.shared_string_close, null);
if (AppInitializer.LATEST_CHANGES_URL != null) { if (AppInitializer.LATEST_CHANGES_URL != null) {
builder.setPositiveButton(R.string.read_more, new DialogInterface.OnClickListener() { builder.setPositiveButton(R.string.read_more, new DialogInterface.OnClickListener() {

View file

@ -644,7 +644,7 @@ public class ExternalApiHelper {
gpxFile.path = destFile.getAbsolutePath(); gpxFile.path = destFile.getAbsolutePath();
} }
new SaveGpxAsyncTask(gpxFile, new SaveGpxListener() { new SaveGpxAsyncTask(new File(gpxFile.path), gpxFile, new SaveGpxListener() {
@Override @Override
public void gpxSavingStarted() { public void gpxSavingStarted() {

View file

@ -12,6 +12,7 @@ import android.content.Intent;
import android.graphics.Typeface; import android.graphics.Typeface;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.net.Uri; import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.text.SpannableString; import android.text.SpannableString;
@ -63,6 +64,7 @@ import com.github.mikephil.charting.utils.MPPointF;
import net.osmand.AndroidUtils; import net.osmand.AndroidUtils;
import net.osmand.CallbackWithObject; import net.osmand.CallbackWithObject;
import net.osmand.FileUtils;
import net.osmand.GPXUtilities; import net.osmand.GPXUtilities;
import net.osmand.GPXUtilities.Elevation; import net.osmand.GPXUtilities.Elevation;
import net.osmand.GPXUtilities.GPXFile; import net.osmand.GPXUtilities.GPXFile;
@ -75,30 +77,35 @@ import net.osmand.PlatformUtil;
import net.osmand.plus.ContextMenuAdapter; import net.osmand.plus.ContextMenuAdapter;
import net.osmand.plus.ContextMenuItem; import net.osmand.plus.ContextMenuItem;
import net.osmand.plus.GPXDatabase.GpxDataItem; import net.osmand.plus.GPXDatabase.GpxDataItem;
import net.osmand.plus.GpxDbHelper;
import net.osmand.plus.GpxDbHelper.GpxDataItemCallback; import net.osmand.plus.GpxDbHelper.GpxDataItemCallback;
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup; import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup;
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile; import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
import net.osmand.plus.OsmAndConstants; import net.osmand.plus.OsmAndConstants;
import net.osmand.plus.OsmAndFormatter; import net.osmand.plus.OsmAndFormatter;
import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin; 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.R;
import net.osmand.plus.UiUtilities; import net.osmand.plus.UiUtilities;
import net.osmand.plus.Version; import net.osmand.plus.Version;
import net.osmand.plus.activities.ActivityResultListener; import net.osmand.plus.activities.ActivityResultListener;
import net.osmand.plus.activities.ActivityResultListener.OnActivityResultListener; import net.osmand.plus.activities.ActivityResultListener.OnActivityResultListener;
import net.osmand.plus.activities.MapActivity; import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.activities.PluginsFragment;
import net.osmand.plus.dialogs.ConfigureMapMenu; import net.osmand.plus.dialogs.ConfigureMapMenu;
import net.osmand.plus.dialogs.GpxAppearanceAdapter; import net.osmand.plus.dialogs.GpxAppearanceAdapter;
import net.osmand.plus.dialogs.GpxAppearanceAdapter.AppearanceListItem; 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.monitoring.OsmandMonitoringPlugin;
import net.osmand.plus.routing.RouteCalculationResult; 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.RenderingRuleProperty;
import net.osmand.render.RenderingRulesStorage; import net.osmand.render.RenderingRulesStorage;
import net.osmand.router.RouteStatisticsHelper; import net.osmand.router.RouteStatisticsHelper;
@ -245,7 +252,7 @@ public class GpxUiHelper {
} }
public static AlertDialog selectGPXFile(final Activity activity, public static AlertDialog selectGPXFile(final Activity activity,
final boolean showCurrentGpx, final boolean multipleChoice, final boolean showCurrentGpx, final boolean multipleChoice,
final CallbackWithObject<GPXFile[]> callbackWithObject, boolean nightMode) { final CallbackWithObject<GPXFile[]> callbackWithObject, boolean nightMode) {
int dialogThemeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme; int dialogThemeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme;
OsmandApplication app = (OsmandApplication) activity.getApplication(); OsmandApplication app = (OsmandApplication) activity.getApplication();
@ -597,15 +604,16 @@ public class GpxUiHelper {
if (app != null && showCurrentGpx && adapter.getItem(0).getSelected()) { if (app != null && showCurrentGpx && adapter.getItem(0).getSelected()) {
currentGPX = app.getSavingTrackHelper().getCurrentGpx(); currentGPX = app.getSavingTrackHelper().getCurrentGpx();
} }
List<String> s = new ArrayList<>(); List<String> fileNames = new ArrayList<>();
for (int i = (showCurrentGpx ? 1 : 0); i < adapter.length(); i++) { for (int i = (showCurrentGpx ? 1 : 0); i < adapter.length(); i++) {
if (adapter.getItem(i).getSelected()) { if (adapter.getItem(i).getSelected()) {
s.add(list.get(i).getFileName()); fileNames.add(list.get(i).getFileName());
} }
} }
dialog.dismiss(); dialog.dismiss();
updateSelectedTracksAppearance(app, fileNames);
loadGPXFileInDifferentThread(activity, callbackWithObject, dir, currentGPX, loadGPXFileInDifferentThread(activity, callbackWithObject, dir, currentGPX,
s.toArray(new String[0])); fileNames.toArray(new String[0]));
} }
}); });
builder.setNegativeButton(R.string.shared_string_cancel, null); builder.setNegativeButton(R.string.shared_string_cancel, null);
@ -710,6 +718,38 @@ public class GpxUiHelper {
return dlg; return dlg;
} }
private static void updateSelectedTracksAppearance(OsmandApplication app, List<String> 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) { public static void updateGpxInfoView(View v, String itemTitle, GPXInfo info, GpxDataItem dataItem, boolean currentlyRecordingTrack, OsmandApplication app) {
TextView viewName = ((TextView) v.findViewById(R.id.name)); TextView viewName = ((TextView) v.findViewById(R.id.name));
viewName.setText(itemTitle.replace("/", "").trim()); viewName.setText(itemTitle.replace("/", "").trim());
@ -808,11 +848,9 @@ public class GpxUiHelper {
View apprTitleView, View apprTitleView,
String prefWidthValue, String prefWidthValue,
String prefColorValue) { String prefColorValue) {
TextView widthTextView = (TextView) apprTitleView.findViewById(R.id.widthTitle); TextView widthTextView = apprTitleView.findViewById(R.id.widthTitle);
ImageView colorImageView = (ImageView) apprTitleView.findViewById(R.id.colorImage); ImageView colorImageView = apprTitleView.findViewById(R.id.colorImage);
if (Algorithms.isEmpty(prefWidthValue)) { if (!Algorithms.isEmpty(prefWidthValue)) {
widthTextView.setText(AndroidUtils.getRenderingStringPropertyValue(activity, trackWidthProp.getDefaultValueDescription()));
} else {
widthTextView.setText(AndroidUtils.getRenderingStringPropertyValue(activity, prefWidthValue)); widthTextView.setText(AndroidUtils.getRenderingStringPropertyValue(activity, prefWidthValue));
} }
int color = GpxAppearanceAdapter.parseTrackColor(renderer, prefColorValue); int color = GpxAppearanceAdapter.parseTrackColor(renderer, prefColorValue);
@ -2133,6 +2171,90 @@ public class GpxUiHelper {
return gpxItem; 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 { public static class GPXInfo {
private String fileName; private String fileName;

View file

@ -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.myplaces.FavoritesActivity.TAB_ID;
import static net.osmand.plus.settings.backend.backup.SettingsHelper.REPLACE_KEY; 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.SETTINGS_TYPE_LIST_KEY;
import static net.osmand.plus.settings.backend.backup.SettingsHelper.SILENT_IMPORT_KEY;
/** /**
* @author Koen Rabaey * @author Koen Rabaey
@ -210,7 +211,7 @@ public class ImportHelper {
public static String getNameFromContentUri(OsmandApplication app, Uri contentUri) { public static String getNameFromContentUri(OsmandApplication app, Uri contentUri) {
try { try {
String name; 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()) { if (returnCursor != null && returnCursor.moveToFirst()) {
int columnIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME); int columnIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
if (columnIndex != -1) { if (columnIndex != -1) {
@ -267,6 +268,7 @@ public class ImportHelper {
int version = extras.getInt(SettingsHelper.SETTINGS_VERSION_KEY, -1); int version = extras.getInt(SettingsHelper.SETTINGS_VERSION_KEY, -1);
String latestChanges = extras.getString(SettingsHelper.SETTINGS_LATEST_CHANGES_KEY); String latestChanges = extras.getString(SettingsHelper.SETTINGS_LATEST_CHANGES_KEY);
boolean replace = extras.getBoolean(REPLACE_KEY); boolean replace = extras.getBoolean(REPLACE_KEY);
boolean silentImport = extras.getBoolean(SILENT_IMPORT_KEY);
ArrayList<String> settingsTypeKeys = extras.getStringArrayList(SETTINGS_TYPE_LIST_KEY); ArrayList<String> settingsTypeKeys = extras.getStringArrayList(SETTINGS_TYPE_LIST_KEY);
List<ExportSettingsType> settingsTypes = null; List<ExportSettingsType> settingsTypes = null;
if (settingsTypeKeys != null) { if (settingsTypeKeys != null) {
@ -275,18 +277,18 @@ public class ImportHelper {
settingsTypes.add(ExportSettingsType.valueOf(key)); settingsTypes.add(ExportSettingsType.valueOf(key));
} }
} }
handleOsmAndSettingsImport(intentUri, fileName, settingsTypes, replace, latestChanges, version, callback); handleOsmAndSettingsImport(intentUri, fileName, settingsTypes, replace, silentImport, latestChanges, version, callback);
} else { } else {
handleOsmAndSettingsImport(intentUri, fileName, null, false, null, -1, handleOsmAndSettingsImport(intentUri, fileName, null, false, false, null, -1,
callback); callback);
} }
} }
protected void handleOsmAndSettingsImport(Uri uri, String name, final List<ExportSettingsType> settingsTypes, protected void handleOsmAndSettingsImport(Uri uri, String name, final List<ExportSettingsType> settingsTypes,
final boolean replace, String latestChanges, int version, final boolean replace, boolean silentImport, String latestChanges, int version,
CallbackWithObject<List<SettingsItem>> callback) { CallbackWithObject<List<SettingsItem>> callback) {
executeImportTask(new SettingsImportTask(activity, uri, name, settingsTypes, replace, latestChanges, version, executeImportTask(new SettingsImportTask(activity, uri, name, settingsTypes, replace, silentImport,
callback)); latestChanges, version, callback));
} }
protected void handleXmlFileImport(Uri intentUri, String fileName, CallbackWithObject routingCallback) { protected void handleXmlFileImport(Uri intentUri, String fileName, CallbackWithObject routingCallback) {

View file

@ -17,10 +17,9 @@ import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity; import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.base.BaseLoadAsyncTask; import net.osmand.plus.base.BaseLoadAsyncTask;
import net.osmand.plus.settings.backend.ExportSettingsType; 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;
import net.osmand.plus.settings.backend.backup.SettingsHelper.CheckDuplicatesListener; 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.SettingsCollectListener;
import net.osmand.plus.settings.backend.backup.SettingsHelper.SettingsImportListener; import net.osmand.plus.settings.backend.backup.SettingsHelper.SettingsImportListener;
import net.osmand.plus.settings.backend.backup.SettingsItem; import net.osmand.plus.settings.backend.backup.SettingsItem;
@ -42,19 +41,21 @@ class SettingsImportTask extends BaseLoadAsyncTask<Void, Void, String> {
private String name; private String name;
private List<ExportSettingsType> settingsTypes; private List<ExportSettingsType> settingsTypes;
private boolean replace; private boolean replace;
private boolean silentImport;
private String latestChanges; private String latestChanges;
private int version; private int version;
private CallbackWithObject<List<SettingsItem>> callback; private CallbackWithObject<List<SettingsItem>> callback;
public SettingsImportTask(@NonNull FragmentActivity activity, @NonNull Uri uri, public SettingsImportTask(@NonNull FragmentActivity activity, @NonNull Uri uri,
@NonNull String name, List<ExportSettingsType> settingsTypes, @NonNull String name, List<ExportSettingsType> settingsTypes,
boolean replace, String latestChanges, int version, boolean replace, boolean silentImport, String latestChanges, int version,
CallbackWithObject<List<SettingsItem>> callback) { CallbackWithObject<List<SettingsItem>> callback) {
super(activity); super(activity);
this.uri = uri; this.uri = uri;
this.name = name; this.name = name;
this.settingsTypes = settingsTypes; this.settingsTypes = settingsTypes;
this.replace = replace; this.replace = replace;
this.silentImport = silentImport;
this.latestChanges = latestChanges; this.latestChanges = latestChanges;
this.version = version; this.version = version;
this.callback = callback; this.callback = callback;
@ -93,13 +94,13 @@ class SettingsImportTask extends BaseLoadAsyncTask<Void, Void, String> {
if (!pluginIndependentItems.isEmpty()) { if (!pluginIndependentItems.isEmpty()) {
if (settingsTypes == null) { if (settingsTypes == null) {
FragmentActivity activity = activityRef.get(); FragmentActivity activity = activityRef.get();
if (activity != null) { if (!silentImport && activity != null) {
FragmentManager fragmentManager = activity.getSupportFragmentManager(); FragmentManager fragmentManager = activity.getSupportFragmentManager();
ImportSettingsFragment.showInstance(fragmentManager, pluginIndependentItems, file); ImportSettingsFragment.showInstance(fragmentManager, pluginIndependentItems, file);
} }
} else { } else {
Map<ExportSettingsType, List<?>> allSettingsMap = getSettingsToOperate(pluginIndependentItems, false); Map<ExportSettingsType, List<?>> allSettingsMap = getSettingsToOperate(pluginIndependentItems, false);
List<SettingsItem> settingsList = settingsHelper.getFilteredSettingsItems(allSettingsMap, settingsTypes); List<SettingsItem> settingsList = settingsHelper.getFilteredSettingsItems(allSettingsMap, settingsTypes, false);
settingsHelper.checkDuplicates(file, settingsList, settingsList, getDuplicatesListener(file, replace)); settingsHelper.checkDuplicates(file, settingsList, settingsList, getDuplicatesListener(file, replace));
} }
} }
@ -141,7 +142,7 @@ class SettingsImportTask extends BaseLoadAsyncTask<Void, Void, String> {
((MapActivity) activity).getMapLayers().getMapWidgetRegistry().updateVisibleWidgets(); ((MapActivity) activity).getMapLayers().getMapWidgetRegistry().updateVisibleWidgets();
((MapActivity) activity).updateApplicationModeSettings(); ((MapActivity) activity).updateApplicationModeSettings();
} }
if (file != null && activity != null) { if (!silentImport && file != null && activity != null) {
FragmentManager fm = activity.getSupportFragmentManager(); FragmentManager fm = activity.getSupportFragmentManager();
ImportCompleteFragment.showInstance(fm, items, file.getName()); ImportCompleteFragment.showInstance(fm, items, file.getName());
} }
@ -174,11 +175,6 @@ class SettingsImportTask extends BaseLoadAsyncTask<Void, Void, String> {
CustomOsmandPlugin plugin = pluginItem.getPlugin(); CustomOsmandPlugin plugin = pluginItem.getPlugin();
plugin.loadResources(); plugin.loadResources();
for (SettingsItem item : items) {
if (item instanceof ProfileSettingsItem) {
((ProfileSettingsItem) item).applyAdditionalPrefs();
}
}
if (!Algorithms.isEmpty(plugin.getDownloadMaps())) { if (!Algorithms.isEmpty(plugin.getDownloadMaps())) {
app.getDownloadThread().runReloadIndexFilesSilent(); app.getDownloadThread().runReloadIndexFilesSilent();
} }
@ -188,11 +184,14 @@ class SettingsImportTask extends BaseLoadAsyncTask<Void, Void, String> {
if (!Algorithms.isEmpty(plugin.getRouterNames())) { if (!Algorithms.isEmpty(plugin.getRouterNames())) {
loadRoutingFiles(app, null); loadRoutingFiles(app, null);
} }
if (activity != null) { if (!silentImport && activity != null) {
plugin.onInstall(app, activity); plugin.onInstall(app, activity);
} }
String pluginId = pluginItem.getPluginId(); 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); app.getSettingsHelper().exportSettings(pluginDir, "items", null, items, false);
} }
}; };

View file

@ -86,7 +86,7 @@ public class ZipImportTask extends BaseLoadAsyncTask<Void, Void, ImportType> {
} else if (importType == ImportType.SETTINGS) { } else if (importType == ImportType.SETTINGS) {
String name = createUniqueFileName(app, "settings", TEMP_DIR, OSMAND_SETTINGS_FILE_EXT); String name = createUniqueFileName(app, "settings", TEMP_DIR, OSMAND_SETTINGS_FILE_EXT);
importHelper.handleOsmAndSettingsImport(uri, name + OSMAND_SETTINGS_FILE_EXT, importHelper.handleOsmAndSettingsImport(uri, name + OSMAND_SETTINGS_FILE_EXT,
null, false, null, -1, null); null, false, false, null, -1, null);
} }
} }
} }

View file

@ -412,7 +412,7 @@ public class MenuBuilder {
} }
}); });
//TODO This feature is under development //TODO This feature is under development
if (!OsmandPlugin.isDevelopment()) { if (!Version.isDeveloperVersion(app)) {
view.setVisibility(View.GONE); view.setVisibility(View.GONE);
} }
photoButton = view; photoButton = view;

View file

@ -1,10 +1,8 @@
package net.osmand.plus.mapcontextmenu.controllers; package net.osmand.plus.mapcontextmenu.controllers;
import android.app.ProgressDialog; import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask; import android.os.AsyncTask;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
@ -39,7 +37,7 @@ public class SelectedGpxMenuController extends MenuController {
private SelectedGpxPoint selectedGpxPoint; private SelectedGpxPoint selectedGpxPoint;
public SelectedGpxMenuController(@NonNull final MapActivity mapActivity, @NonNull PointDescription pointDescription, public SelectedGpxMenuController(@NonNull final MapActivity mapActivity, @NonNull PointDescription pointDescription,
@NonNull final SelectedGpxPoint selectedGpxPoint) { @NonNull final SelectedGpxPoint selectedGpxPoint) {
super(new SelectedGpxMenuBuilder(mapActivity, selectedGpxPoint), pointDescription, mapActivity); super(new SelectedGpxMenuBuilder(mapActivity, selectedGpxPoint), pointDescription, mapActivity);
this.selectedGpxPoint = selectedGpxPoint; this.selectedGpxPoint = selectedGpxPoint;
builder.setShowOnlinePhotos(false); builder.setShowOnlinePhotos(false);
@ -209,24 +207,11 @@ public class SelectedGpxMenuController extends MenuController {
if (mapActivity != null && selectedGpxPoint != null) { if (mapActivity != null && selectedGpxPoint != null) {
final GPXFile gpxFile = selectedGpxPoint.getSelectedGpxFile().getGpxFile(); final GPXFile gpxFile = selectedGpxPoint.getSelectedGpxFile().getGpxFile();
if (gpxFile != null) { if (gpxFile != null) {
OsmandApplication app = mapActivity.getMyApplication();
if (Algorithms.isEmpty(gpxFile.path)) { if (Algorithms.isEmpty(gpxFile.path)) {
SaveGpxListener saveGpxListener = new SaveGpxListener() { saveAndShareCurrentGpx(app, gpxFile);
@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);
} else { } else {
shareGpx(mapActivity, gpxFile.path); GpxUiHelper.saveAndShareGpxWithAppearance(app, gpxFile);
} }
} }
} else { } else {
@ -234,15 +219,21 @@ public class SelectedGpxMenuController extends MenuController {
} }
} }
private void shareGpx(@NonNull Context context, @NonNull String path) { public void saveAndShareCurrentGpx(@NonNull final OsmandApplication app, @NonNull final GPXFile gpxFile) {
final Uri fileUri = AndroidUtils.getUriForFile(context, new File(path)); SaveGpxListener saveGpxListener = new SaveGpxListener() {
final Intent sendIntent = new Intent(Intent.ACTION_SEND); @Override
sendIntent.putExtra(Intent.EXTRA_STREAM, fileUri); public void gpxSavingStarted() {
sendIntent.setType("application/gpx+xml");
sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); }
if (AndroidUtils.isIntentSafe(context, sendIntent)) {
context.startActivity(sendIntent); @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 { public static class SelectedGpxPoint {

View file

@ -30,6 +30,7 @@ import net.osmand.plus.track.SaveGpxAsyncTask;
import net.osmand.plus.track.SaveGpxAsyncTask.SaveGpxListener; import net.osmand.plus.track.SaveGpxAsyncTask.SaveGpxListener;
import net.osmand.util.Algorithms; import net.osmand.util.Algorithms;
import java.io.File;
import java.util.Map; import java.util.Map;
public class WptPtEditorFragment extends PointEditorFragment { 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) { 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 @Override
public void gpxSavingStarted() { public void gpxSavingStarted() {

View file

@ -34,6 +34,7 @@ import net.osmand.plus.track.SaveGpxAsyncTask;
import net.osmand.plus.track.SaveGpxAsyncTask.SaveGpxListener; import net.osmand.plus.track.SaveGpxAsyncTask.SaveGpxListener;
import net.osmand.util.Algorithms; import net.osmand.util.Algorithms;
import java.io.File;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; 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) { 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 @Override
public void gpxSavingStarted() { public void gpxSavingStarted() {

View file

@ -473,6 +473,10 @@ public class TrackDetailsMenu {
} }
public void refreshChart(LineChart chart, boolean forceFit) { public void refreshChart(LineChart chart, boolean forceFit) {
refreshChart(chart, true, forceFit);
}
public void refreshChart(LineChart chart, boolean fitTrackOnMap, boolean forceFit) {
MapActivity mapActivity = getMapActivity(); MapActivity mapActivity = getMapActivity();
GpxDisplayItem gpxItem = getGpxItem(); GpxDisplayItem gpxItem = getGpxItem();
if (mapActivity == null || gpxItem == null) { if (mapActivity == null || gpxItem == null) {
@ -529,7 +533,9 @@ public class TrackDetailsMenu {
if (location != null) { if (location != null) {
mapActivity.refreshMap(); mapActivity.refreshMap();
} }
fitTrackOnMap(chart, location, forceFit); if (fitTrackOnMap) {
fitTrackOnMap(chart, location, forceFit);
}
} }
public boolean shouldShowXAxisPoints () { public boolean shouldShowXAxisPoints () {

View file

@ -311,7 +311,7 @@ public class GraphsCard extends BaseCard implements OnUpdateInfoListener {
private void updateChartOnMap() { private void updateChartOnMap() {
if (hasVisibleGraph()) { if (hasVisibleGraph()) {
trackDetailsMenu.reset(); trackDetailsMenu.reset();
refreshMapCallback.refreshMap(false); refreshMapCallback.refreshMap(false, false);
} }
} }

View file

@ -296,29 +296,8 @@ public class MeasurementEditingContext {
return !newData && hasDefaultPointsOnly && getPoints().size() > 2; return !newData && hasDefaultPointsOnly && getPoints().size() > 2;
} }
public boolean isSelectionNeedApproximation() { public boolean isAddNewSegmentAllowed() {
boolean hasDefaultPointsOnly = false; return beforeSegments.size() > 0 && beforeSegments.get(beforeSegments.size() - 1).points.size() >= 2;
boolean newData = isNewData();
if (!newData && selectedPointPosition != -1) {
WptPt selectedPoint = getPoints().get(selectedPointPosition);
List<TrkSegment> segments = getBeforeSegments();
List<WptPt> 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 void clearSnappedToRoadPoints() { public void clearSnappedToRoadPoints() {
@ -430,13 +409,19 @@ public class MeasurementEditingContext {
if (position > 0 && position <= points.size()) { if (position > 0 && position <= points.size()) {
WptPt prevPt = points.get(position - 1); WptPt prevPt = points.get(position - 1);
if (prevPt.isGap()) { if (prevPt.isGap()) {
point.setGap(); if (position == points.size() && getAfterPoints().size() == 0) {
if (position > 1) { if (appMode != MeasurementEditingContext.DEFAULT_APP_MODE) {
WptPt pt = points.get(position - 2); point.setProfileType(appMode.getStringKey());
if (pt.hasProfile()) { }
prevPt.setProfileType(pt.getProfileType()); } else {
} else { point.setGap();
prevPt.removeProfileType(); if (position > 1) {
WptPt pt = points.get(position - 2);
if (pt.hasProfile()) {
prevPt.setProfileType(pt.getProfileType());
} else {
prevPt.removeProfileType();
}
} }
} }
} else if (prevPt.hasProfile()) { } else if (prevPt.hasProfile()) {
@ -540,6 +525,45 @@ public class MeasurementEditingContext {
clearAfterSegments(); 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() { public void clearSegments() {
clearBeforeSegments(); clearBeforeSegments();
clearAfterSegments(); clearAfterSegments();
@ -560,15 +584,43 @@ public class MeasurementEditingContext {
} }
} }
public boolean isFirstPointSelected() { public boolean canSplit(boolean after) {
return isBorderPointSelected(true); WptPt selectedPoint = getPoints().get(selectedPointPosition);
List<TrkSegment> 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() { public boolean isFirstPointSelected(boolean outer) {
return isBorderPointSelected(false); 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); WptPt selectedPoint = getPoints().get(selectedPointPosition);
List<TrkSegment> segments = getBeforeSegments(); List<TrkSegment> segments = getBeforeSegments();
int count = 0; int count = 0;
@ -738,7 +790,7 @@ public class MeasurementEditingContext {
pairPoints.add(points.get(j)); pairPoints.add(points.get(j));
prevPointIndex = j; prevPointIndex = j;
} }
if (points.size() > prevPointIndex + 1) { if (points.size() > prevPointIndex + 1 && i == routePoints.size() - 2) {
pairPoints.add(points.get(prevPointIndex + 1)); pairPoints.add(points.get(prevPointIndex + 1));
} }
Iterator<RouteSegmentResult> it = routeSegments.iterator(); Iterator<RouteSegmentResult> it = routeSegments.iterator();

View file

@ -22,6 +22,7 @@ import androidx.activity.OnBackPressedCallback;
import androidx.annotation.DrawableRes; import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.content.res.AppCompatResources;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.core.widget.TextViewCompat; import androidx.core.widget.TextViewCompat;
import androidx.fragment.app.FragmentManager; 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;
import net.osmand.plus.measurementtool.command.ChangeRouteModeCommand.ChangeRouteType; import net.osmand.plus.measurementtool.command.ChangeRouteModeCommand.ChangeRouteType;
import net.osmand.plus.measurementtool.command.ClearPointsCommand; 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.MovePointCommand;
import net.osmand.plus.measurementtool.command.RemovePointCommand; import net.osmand.plus.measurementtool.command.RemovePointCommand;
import net.osmand.plus.measurementtool.command.ReorderPointCommand; import net.osmand.plus.measurementtool.command.ReorderPointCommand;
import net.osmand.plus.measurementtool.command.ReversePointsCommand; 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.routepreparationmenu.cards.BaseCard;
import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.settings.backend.OsmandSettings; 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.TopToolbarControllerType;
import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarView; import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarView;
import net.osmand.plus.widgets.MultiStateToggleButton; 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.OnRadioItemClickListener;
import net.osmand.plus.widgets.MultiStateToggleButton.RadioItem;
import net.osmand.router.RoutePlannerFrontEnd.GpxRouteApproximation; import net.osmand.router.RoutePlannerFrontEnd.GpxRouteApproximation;
import net.osmand.util.Algorithms; import net.osmand.util.Algorithms;
@ -230,7 +234,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
return null; return null;
} }
final MeasurementToolLayer measurementLayer = mapActivity.getMapLayers().getMeasurementToolLayer(); final MeasurementToolLayer measurementLayer = mapActivity.getMapLayers().getMeasurementToolLayer();
OsmandApplication app = mapActivity.getMyApplication(); final OsmandApplication app = mapActivity.getMyApplication();
editingCtx.setApplication(mapActivity.getMyApplication()); editingCtx.setApplication(mapActivity.getMyApplication());
editingCtx.setProgressListener(new SnapToRoadProgressListener() { editingCtx.setProgressListener(new SnapToRoadProgressListener() {
@ -368,9 +372,10 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
@Override @Override
public void onClick(View view) { public void onClick(View view) {
boolean trackSnappedToRoad = !editingCtx.isApproximationNeeded(); boolean trackSnappedToRoad = !editingCtx.isApproximationNeeded();
boolean addNewSegmentAllowed = editingCtx.isAddNewSegmentAllowed();
OptionsBottomSheetDialogFragment.showInstance(mapActivity.getSupportFragmentManager(), OptionsBottomSheetDialogFragment.showInstance(mapActivity.getSupportFragmentManager(),
MeasurementToolFragment.this, MeasurementToolFragment.this,
trackSnappedToRoad, trackSnappedToRoad, addNewSegmentAllowed,
editingCtx.getAppMode().getStringKey() editingCtx.getAppMode().getStringKey()
); );
} }
@ -432,7 +437,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
@Override @Override
public void onMeasure(float distance, float bearing) { public void onMeasure(float distance, float bearing) {
String distStr = OsmAndFormatter.getFormattedDistance(distance, mapActivity.getMyApplication()); 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)); distanceToCenterTv.setText(String.format("%1$s • %2$s", distStr, azimuthStr));
TextViewCompat.setAutoSizeTextTypeUniformWithConfiguration( TextViewCompat.setAutoSizeTextTypeUniformWithConfiguration(
distanceToCenterTv, 14, 18, 2, distanceToCenterTv, 14, 18, 2,
@ -496,7 +501,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
final GpxData gpxData = editingCtx.getGpxData(); 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.setBackgroundResource(nightMode ? R.drawable.btn_circle_night : R.drawable.btn_circle);
snapToRoadBtn.setOnClickListener(new OnClickListener() { snapToRoadBtn.setOnClickListener(new OnClickListener() {
@Override @Override
@ -505,6 +510,31 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
} }
}); });
snapToRoadBtn.setVisibility(View.VISIBLE); 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); initMeasurementMode(gpxData, savedInstanceState == null);
@ -829,6 +859,11 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
startSnapToRoad(true); startSnapToRoad(true);
} }
@Override
public void addNewSegmentOnClick() {
onSplitPointsAfter();
}
@Override @Override
public void directionsOnClick() { public void directionsOnClick() {
MapActivity mapActivity = getMapActivity(); MapActivity mapActivity = getMapActivity();
@ -1012,6 +1047,39 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
trimRoute(AFTER); 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) { private void trimRoute(ClearCommandMode before) {
MeasurementToolLayer measurementLayer = getMeasurementLayer(); MeasurementToolLayer measurementLayer = getMeasurementLayer();
editingCtx.getCommandManager().execute(new ClearPointsCommand(measurementLayer, before)); editingCtx.getCommandManager().execute(new ClearPointsCommand(measurementLayer, before));
@ -1251,17 +1319,24 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
final ApplicationMode appMode = editingCtx.getAppMode(); final ApplicationMode appMode = editingCtx.getAppMode();
if (mapActivity != null) { if (mapActivity != null) {
Drawable icon; 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 (isTrackReadyToCalculate()) {
if (appMode == MeasurementEditingContext.DEFAULT_APP_MODE) { if (appMode == MeasurementEditingContext.DEFAULT_APP_MODE) {
icon = getActiveIcon(R.drawable.ic_action_split_interval); icon = getActiveIcon(R.drawable.ic_action_split_interval);
snapToRoadBtn.setVisibility(View.VISIBLE);
profileWithConfig.setVisibility(View.GONE);
} else { } else {
icon = getIcon(appMode.getIconRes(), appMode.getIconColorInfo().getColor(nightMode)); icon = getIcon(appMode.getIconRes(), appMode.getIconColorInfo().getColor(nightMode));
snapToRoadBtn.setVisibility(View.GONE);
profileWithConfig.setVisibility(View.VISIBLE);
} }
} else { } else {
icon = getContentIcon(R.drawable.ic_action_help); icon = getContentIcon(R.drawable.ic_action_help);
} }
ImageButton snapToRoadBtn = (ImageButton) mapActivity.findViewById(R.id.snap_to_road_image_button);
snapToRoadBtn.setImageDrawable(icon); snapToRoadBtn.setImageDrawable(icon);
configBtn.setImageDrawable(icon);
mapActivity.refreshMap(); mapActivity.refreshMap();
} }
} }
@ -1274,6 +1349,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
MapActivity mapActivity = getMapActivity(); MapActivity mapActivity = getMapActivity();
if (mapActivity != null) { if (mapActivity != null) {
mapActivity.findViewById(R.id.snap_to_road_image_button).setVisibility(View.GONE); mapActivity.findViewById(R.id.snap_to_road_image_button).setVisibility(View.GONE);
mapActivity.findViewById(R.id.profile_with_config_btn).setVisibility(View.GONE);
} }
} }

View file

@ -328,7 +328,7 @@ public class MeasurementToolLayer extends OsmandMapLayer implements ContextMenuL
hasPointsBefore = true; hasPointsBefore = true;
WptPt pt = segment.points.get(segment.points.size() - 1); WptPt pt = segment.points.get(segment.points.size() - 1);
hasGapBefore = pt.isGap(); hasGapBefore = pt.isGap();
if (!pt.isGap() || !editingCtx.isInAddPointBeforeMode()) { if (!pt.isGap() || (editingCtx.isInAddPointMode() && !editingCtx.isInAddPointBeforeMode())) {
float locX = tb.getPixXFromLatLon(pt.lat, pt.lon); float locX = tb.getPixXFromLatLon(pt.lat, pt.lon);
float locY = tb.getPixYFromLatLon(pt.lat, pt.lon); float locY = tb.getPixYFromLatLon(pt.lat, pt.lon);
tx.add(locX); tx.add(locX);
@ -345,7 +345,7 @@ public class MeasurementToolLayer extends OsmandMapLayer implements ContextMenuL
tx.add((float) tb.getCenterPixelX()); tx.add((float) tb.getCenterPixelX());
ty.add((float) tb.getCenterPixelY()); ty.add((float) tb.getCenterPixelY());
} }
if (!hasGapBefore || editingCtx.isInAddPointBeforeMode()) { if (!hasGapBefore || (editingCtx.isInAddPointMode() && editingCtx.isInAddPointBeforeMode())) {
WptPt pt = segment.points.get(0); WptPt pt = segment.points.get(0);
float locX = tb.getPixXFromLatLon(pt.lat, pt.lon); float locX = tb.getPixXFromLatLon(pt.lat, pt.lon);
float locY = tb.getPixYFromLatLon(pt.lat, pt.lon); float locY = tb.getPixYFromLatLon(pt.lat, pt.lon);

View file

@ -15,6 +15,7 @@ import net.osmand.PlatformUtil;
import net.osmand.plus.R; import net.osmand.plus.R;
import net.osmand.plus.base.MenuBottomSheetDialogFragment; import net.osmand.plus.base.MenuBottomSheetDialogFragment;
import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem; 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.BottomSheetItemWithDescriptionDifHeight;
import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem; import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem; 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 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 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; private ApplicationMode routeAppMode;
@ -36,8 +38,10 @@ public class OptionsBottomSheetDialogFragment extends MenuBottomSheetDialogFragm
public void createMenuItems(Bundle savedInstanceState) { public void createMenuItems(Bundle savedInstanceState) {
Bundle args = getArguments(); Bundle args = getArguments();
boolean trackSnappedToRoad = false; boolean trackSnappedToRoad = false;
boolean addNewSegmentAllowed = false;
if (args != null) { if (args != null) {
trackSnappedToRoad = args.getBoolean(TRACK_SNAPPED_TO_ROAD_KEY); 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); routeAppMode = ApplicationMode.valueOfStringKey(args.getString(SNAP_TO_ROAD_APP_MODE_KEY), null);
} }
@ -78,6 +82,25 @@ public class OptionsBottomSheetDialogFragment extends MenuBottomSheetDialogFragm
items.add(snapToRoadItem); 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())); items.add(new OptionsDividerItem(getContext()));
BaseBottomSheetItem saveAsNewSegmentItem = new SimpleBottomSheetItem.Builder() BaseBottomSheetItem saveAsNewSegmentItem = new SimpleBottomSheetItem.Builder()
@ -200,12 +223,13 @@ public class OptionsBottomSheetDialogFragment extends MenuBottomSheetDialogFragm
} }
public static void showInstance(@NonNull FragmentManager fm, Fragment targetFragment, public static void showInstance(@NonNull FragmentManager fm, Fragment targetFragment,
boolean trackSnappedToRoad, String routeAppModeStringKey) { boolean trackSnappedToRoad, boolean addNewSegmentAllowed, String routeAppModeStringKey) {
try { try {
if (!fm.isStateSaved()) { if (!fm.isStateSaved()) {
OptionsBottomSheetDialogFragment fragment = new OptionsBottomSheetDialogFragment(); OptionsBottomSheetDialogFragment fragment = new OptionsBottomSheetDialogFragment();
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putBoolean(TRACK_SNAPPED_TO_ROAD_KEY, trackSnappedToRoad); 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); args.putString(SNAP_TO_ROAD_APP_MODE_KEY, routeAppModeStringKey);
fragment.setArguments(args); fragment.setArguments(args);
fragment.setTargetFragment(targetFragment,0); fragment.setTargetFragment(targetFragment,0);
@ -225,6 +249,8 @@ public class OptionsBottomSheetDialogFragment extends MenuBottomSheetDialogFragm
void snapToRoadOnCLick(); void snapToRoadOnCLick();
void addNewSegmentOnClick();
void saveChangesOnClick(); void saveChangesOnClick();
void saveAsNewTrackOnClick(); void saveAsNewTrackOnClick();

View file

@ -2,7 +2,6 @@ package net.osmand.plus.measurementtool;
import android.app.Activity; import android.app.Activity;
import android.content.Intent; import android.content.Intent;
import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.view.View; import android.view.View;
import android.widget.TextView; import android.widget.TextView;
@ -11,7 +10,6 @@ import androidx.annotation.NonNull;
import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import net.osmand.AndroidUtils;
import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R; import net.osmand.plus.R;
import net.osmand.plus.UiUtilities; 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.BottomSheetItemButton;
import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem; import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.DividerItem; import net.osmand.plus.base.bottomsheetmenu.simpleitems.DividerItem;
import net.osmand.plus.helpers.GpxUiHelper;
import net.osmand.util.Algorithms; import net.osmand.util.Algorithms;
import java.io.File; import java.io.File;
@ -80,13 +79,10 @@ public class SavedTrackBottomSheetDialogFragment extends MenuBottomSheetDialogFr
@Override @Override
protected void onThirdBottomButtonClick() { protected void onThirdBottomButtonClick() {
final Intent sendIntent = new Intent(); FragmentActivity activity = getActivity();
sendIntent.setAction(Intent.ACTION_SEND); if (activity != null) {
final Uri fileUri = AndroidUtils.getUriForFile(getMyApplication(), new File(fileName)); GpxUiHelper.shareGpx(activity, new File(fileName));
sendIntent.putExtra(Intent.EXTRA_STREAM, fileUri); }
sendIntent.setType("application/gpx+xml");
sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(sendIntent);
dismiss(); dismiss();
} }

View file

@ -9,6 +9,7 @@ import android.widget.TextView;
import androidx.annotation.StringRes; import androidx.annotation.StringRes;
import androidx.appcompat.view.ContextThemeWrapper; import androidx.appcompat.view.ContextThemeWrapper;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
@ -20,7 +21,7 @@ import net.osmand.OsmAndCollator;
import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R; import net.osmand.plus.R;
import net.osmand.plus.UiUtilities; 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.base.bottomsheetmenu.BaseBottomSheetItem;
import net.osmand.plus.helpers.GpxTrackAdapter; import net.osmand.plus.helpers.GpxTrackAdapter;
import net.osmand.plus.helpers.GpxTrackAdapter.OnItemClickListener; import net.osmand.plus.helpers.GpxTrackAdapter.OnItemClickListener;
@ -38,11 +39,11 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; 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.plus.helpers.GpxUiHelper.getSortedGPXFilesInfo;
import static net.osmand.util.Algorithms.collectDirs; import static net.osmand.util.Algorithms.collectDirs;
public class SelectFileBottomSheet extends BottomSheetBehaviourDialogFragment { public class SelectFileBottomSheet extends MenuBottomSheetDialogFragment {
private List<File> folders; private List<File> folders;
private HorizontalSelectionAdapter folderAdapter; private HorizontalSelectionAdapter folderAdapter;
@ -301,8 +302,27 @@ public class SelectFileBottomSheet extends BottomSheetBehaviourDialogFragment {
} }
@Override @Override
protected int getPeekHeight() { protected boolean useScrollableItemsContainer() {
return AndroidUtils.dpToPx(getContext(), BOTTOM_SHEET_HEIGHT_DP); 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) { public static void showInstance(FragmentManager fragmentManager, SelectFileListener listener, Mode mode) {

View file

@ -133,7 +133,7 @@ public class SelectedPointBottomSheetDialogFragment extends MenuBottomSheetDialo
dismiss(); dismiss();
} }
}) })
.setDisabled(editingCtx.isFirstPointSelected()) .setDisabled(editingCtx.isFirstPointSelected(false))
.create(); .create();
items.add(trimRouteBefore); items.add(trimRouteBefore);
@ -152,10 +152,93 @@ public class SelectedPointBottomSheetDialogFragment extends MenuBottomSheetDialo
dismiss(); dismiss();
} }
}) })
.setDisabled(editingCtx.isLastPointSelected()) .setDisabled(editingCtx.isLastPointSelected(false))
.create(); .create();
items.add(trimRouteAfter); 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())); items.add(new OptionsDividerItem(getContext()));
BaseBottomSheetItem changeRouteTypeBefore = new BottomSheetItemWithDescription.Builder() BaseBottomSheetItem changeRouteTypeBefore = new BottomSheetItemWithDescription.Builder()
@ -172,7 +255,7 @@ public class SelectedPointBottomSheetDialogFragment extends MenuBottomSheetDialo
dismiss(); dismiss();
} }
}) })
.setDisabled(editingCtx.isFirstPointSelected() || editingCtx.isSelectionNeedApproximation()) .setDisabled(editingCtx.isFirstPointSelected(false) || editingCtx.isApproximationNeeded())
.create(); .create();
items.add(changeRouteTypeBefore); items.add(changeRouteTypeBefore);
@ -190,7 +273,7 @@ public class SelectedPointBottomSheetDialogFragment extends MenuBottomSheetDialo
dismiss(); dismiss();
} }
}) })
.setDisabled(editingCtx.isLastPointSelected() || editingCtx.isSelectionNeedApproximation()) .setDisabled(editingCtx.isLastPointSelected(false) || editingCtx.isApproximationNeeded())
.create(); .create();
items.add(changeRouteTypeAfter); items.add(changeRouteTypeAfter);
@ -352,6 +435,12 @@ public class SelectedPointBottomSheetDialogFragment extends MenuBottomSheetDialo
void onTrimRouteAfter(); void onTrimRouteAfter();
void onSplitPointsAfter();
void onSplitPointsBefore();
void onJoinPoints();
void onChangeRouteTypeBefore(); void onChangeRouteTypeBefore();
void onChangeRouteTypeAfter(); void onChangeRouteTypeAfter();

View file

@ -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<WptPt> points;
private Map<Pair<WptPt, WptPt>, 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<WptPt> 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;
}
}

View file

@ -41,6 +41,8 @@ public abstract class MeasurementModeCommand implements Command {
SNAP_TO_ROAD, SNAP_TO_ROAD,
CHANGE_ROUTE_MODE, CHANGE_ROUTE_MODE,
APPROXIMATE_POINTS, APPROXIMATE_POINTS,
REVERSE_POINTS REVERSE_POINTS,
SPLIT_POINTS,
JOIN_POINTS
} }
} }

View file

@ -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<WptPt> points;
private Map<Pair<WptPt, WptPt>, 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<WptPt> 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;
}
}

View file

@ -61,11 +61,14 @@ public class CustomGraphAdapter extends BaseGraphAdapter<HorizontalBarChart, Bar
public void onValueSelected(Entry e, Highlight h) { public void onValueSelected(Entry e, Highlight h) {
if (getStatistics() == null) return; if (getStatistics() == null) return;
List<RouteStatisticsHelper.RouteSegmentAttribute> elems = getStatistics().elements; List<RouteSegmentAttribute> elems = getStatistics().elements;
int i = h.getStackIndex(); int i = h.getStackIndex();
if (i >= 0 && elems.size() > i) { if (i >= 0 && elems.size() > i) {
selectedPropertyName = elems.get(i).getPropertyName(); selectedPropertyName = elems.get(i).getPropertyName();
updateLegend(); 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<HorizontalBarChart, Bar
} }
private void attachLegend() { private void attachLegend() {
if (getSegmentsList() == null) return; List<RouteSegmentAttribute> attributes = getSegmentsList();
if (attributes == null) return;
switch (legendViewType) { switch (legendViewType) {
case ONE_ELEMENT: case ONE_ELEMENT:
for (RouteSegmentAttribute segment : getSegmentsList()) { for (RouteSegmentAttribute attribute : attributes) {
if (segment.getPropertyName().equals(selectedPropertyName)) { if (attribute.getPropertyName().equals(selectedPropertyName)) {
attachLegend(Collections.singletonList(segment), null); attachLegend(Collections.singletonList(attribute), null);
break; break;
} }
} }
break; break;
case ALL_AS_LIST: case ALL_AS_LIST:
attachLegend(getSegmentsList(), selectedPropertyName); attachLegend(attributes, selectedPropertyName);
break; break;
} }
} }
@ -137,7 +141,7 @@ public class CustomGraphAdapter extends BaseGraphAdapter<HorizontalBarChart, Bar
String propertyNameToFullSpan) { String propertyNameToFullSpan) {
OsmandApplication app = getMyApplication(); OsmandApplication app = getMyApplication();
LayoutInflater inflater = LayoutInflater.from(app); LayoutInflater inflater = LayoutInflater.from(app);
for (RouteStatisticsHelper.RouteSegmentAttribute segment : list) { for (RouteSegmentAttribute segment : list) {
View view = inflater.inflate(R.layout.route_details_legend, legendContainer, false); View view = inflater.inflate(R.layout.route_details_legend, legendContainer, false);
int segmentColor = segment.getColor(); int segmentColor = segment.getColor();
Drawable circle = app.getUIUtilities().getPaintedIcon(R.drawable.ic_action_circle, segmentColor); Drawable circle = app.getUIUtilities().getPaintedIcon(R.drawable.ic_action_circle, segmentColor);

View file

@ -105,11 +105,11 @@ public class GraphAdapterHelper {
@NonNull final TrackDetailsMenu detailsMenu) { @NonNull final TrackDetailsMenu detailsMenu) {
final RefreshMapCallback refreshMapCallback = new RefreshMapCallback() { final RefreshMapCallback refreshMapCallback = new RefreshMapCallback() {
@Override @Override
public void refreshMap(boolean forceFit) { public void refreshMap(boolean fitTrackOnMap, boolean forceFit) {
LineChart chart = graphAdapter.getChart(); LineChart chart = graphAdapter.getChart();
OsmandApplication app = mapActivity.getMyApplication(); OsmandApplication app = mapActivity.getMyApplication();
if (!app.getRoutingHelper().isFollowingMode()) { if (!app.getRoutingHelper().isFollowingMode()) {
detailsMenu.refreshChart(chart, forceFit); detailsMenu.refreshChart(chart, fitTrackOnMap, forceFit);
mapActivity.refreshMap(); mapActivity.refreshMap();
} }
} }
@ -120,7 +120,7 @@ public class GraphAdapterHelper {
@Override @Override
public void onValueSelected(Entry e, Highlight h) { public void onValueSelected(Entry e, Highlight h) {
refreshMapCallback.refreshMap(false); refreshMapCallback.refreshMap(true, false);
} }
@Override @Override
@ -141,7 +141,7 @@ public class GraphAdapterHelper {
lastPerformedGesture == ChartTouchListener.ChartGesture.PINCH_ZOOM || lastPerformedGesture == ChartTouchListener.ChartGesture.PINCH_ZOOM ||
lastPerformedGesture == ChartTouchListener.ChartGesture.DOUBLE_TAP || lastPerformedGesture == ChartTouchListener.ChartGesture.DOUBLE_TAP ||
lastPerformedGesture == ChartTouchListener.ChartGesture.ROTATE) { lastPerformedGesture == ChartTouchListener.ChartGesture.ROTATE) {
refreshMapCallback.refreshMap(true); refreshMapCallback.refreshMap(true, true);
} }
} }
}); });
@ -150,6 +150,6 @@ public class GraphAdapterHelper {
} }
public interface RefreshMapCallback { public interface RefreshMapCallback {
void refreshMap(boolean forceFit); void refreshMap(boolean fitTrackOnMap, boolean forceFit);
} }
} }

View file

@ -461,7 +461,7 @@ public class OsmandMonitoringPlugin extends OsmandPlugin {
if (activityRef != null && !Algorithms.isEmpty(result.getFilenames())) { if (activityRef != null && !Algorithms.isEmpty(result.getFilenames())) {
final Activity a = activityRef.get(); final Activity a = activityRef.get();
if (a instanceof FragmentActivity && !a.isFinishing()) { if (a instanceof FragmentActivity && !a.isFinishing()) {
OnSaveCurrentTrackFragment.showInstance(((FragmentActivity) a).getSupportFragmentManager(), result.getFilenames()); SaveGPXBottomSheetFragment.showInstance(((FragmentActivity) a).getSupportFragmentManager(), result.getFilenames());
} }
} }

View file

@ -6,18 +6,13 @@ import android.os.Bundle;
import android.text.Editable; import android.text.Editable;
import android.text.TextWatcher; import android.text.TextWatcher;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo; import android.view.inputmethod.EditorInfo;
import android.widget.CompoundButton; import android.widget.CompoundButton;
import android.widget.EditText; import android.widget.EditText;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.SwitchCompat; import androidx.appcompat.widget.SwitchCompat;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentActivity;
@ -25,17 +20,15 @@ import androidx.fragment.app.FragmentManager;
import net.osmand.FileUtils; import net.osmand.FileUtils;
import net.osmand.GPXUtilities; import net.osmand.GPXUtilities;
import net.osmand.GPXUtilities.WptPt;
import net.osmand.IndexConstants; import net.osmand.IndexConstants;
import net.osmand.PlatformUtil; import net.osmand.PlatformUtil;
import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R; import net.osmand.plus.R;
import net.osmand.plus.UiUtilities; import net.osmand.plus.UiUtilities;
import net.osmand.plus.UiUtilities.DialogButtonType;
import net.osmand.plus.activities.MapActivity; import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.base.BottomSheetDialogFragment; import net.osmand.plus.base.MenuBottomSheetDialogFragment;
import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem;
import net.osmand.plus.myplaces.AvailableGPXFragment; import net.osmand.plus.myplaces.AvailableGPXFragment;
import net.osmand.plus.myplaces.AvailableGPXFragment.GpxInfo;
import net.osmand.plus.views.OsmandMapTileView; import net.osmand.plus.views.OsmandMapTileView;
import net.osmand.plus.widgets.OsmandTextFieldBoxes; import net.osmand.plus.widgets.OsmandTextFieldBoxes;
import net.osmand.util.Algorithms; import net.osmand.util.Algorithms;
@ -48,11 +41,10 @@ import java.util.List;
import static net.osmand.FileUtils.ILLEGAL_FILE_NAME_CHARACTERS; import static net.osmand.FileUtils.ILLEGAL_FILE_NAME_CHARACTERS;
public class OnSaveCurrentTrackFragment extends BottomSheetDialogFragment { public class SaveGPXBottomSheetFragment extends MenuBottomSheetDialogFragment {
public static final String TAG = "SaveGPXBottomSheetFragment";
public static final String TAG = "OnSaveCurrentTrackBottomSheetFragment";
public static final String SAVED_TRACKS_KEY = "saved_track_filename"; public static final String SAVED_TRACKS_KEY = "saved_track_filename";
private static final Log LOG = PlatformUtil.getLog(OnSaveCurrentTrackFragment.class); private static final Log LOG = PlatformUtil.getLog(SaveGPXBottomSheetFragment.class);
private boolean openTrack = false; private boolean openTrack = false;
private File file; private File file;
@ -60,9 +52,8 @@ public class OnSaveCurrentTrackFragment extends BottomSheetDialogFragment {
private String savedGpxName = ""; private String savedGpxName = "";
private String newGpxName = ""; private String newGpxName = "";
@Nullable
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { public void createMenuItems(Bundle savedInstanceState) {
final OsmandApplication app = requiredMyApplication(); final OsmandApplication app = requiredMyApplication();
Bundle args = getArguments(); Bundle args = getArguments();
if (args != null && args.containsKey(SAVED_TRACKS_KEY)) { if (args != null && args.containsKey(SAVED_TRACKS_KEY)) {
@ -81,7 +72,7 @@ public class OnSaveCurrentTrackFragment extends BottomSheetDialogFragment {
file = new File(app.getAppCustomization().getTracksDir(), savedGpxName + IndexConstants.GPX_FILE_EXT); file = new File(app.getAppCustomization().getTracksDir(), savedGpxName + IndexConstants.GPX_FILE_EXT);
final boolean nightMode = app.getDaynightHelper().isNightModeForMapControls(); final boolean nightMode = app.getDaynightHelper().isNightModeForMapControls();
final int textPrimaryColor = nightMode ? R.color.text_color_primary_dark : R.color.text_color_primary_light; final int textPrimaryColor = nightMode ? R.color.text_color_primary_dark : R.color.text_color_primary_light;
View mainView = UiUtilities.getInflater(ctx, nightMode).inflate(R.layout.fragment_on_save_current_track, container); View mainView = UiUtilities.getInflater(ctx, nightMode).inflate(R.layout.save_gpx_fragment, null);
OsmandTextFieldBoxes textBox = (OsmandTextFieldBoxes) mainView.findViewById(R.id.name_text_box); OsmandTextFieldBoxes textBox = (OsmandTextFieldBoxes) mainView.findViewById(R.id.name_text_box);
if (nightMode) { if (nightMode) {
@ -131,25 +122,11 @@ public class OnSaveCurrentTrackFragment extends BottomSheetDialogFragment {
app.getSettings().SHOW_SAVED_TRACK_REMEMBER.set(isChecked); app.getSettings().SHOW_SAVED_TRACK_REMEMBER.set(isChecked);
} }
}); });
View openTrackBtn = mainView.findViewById(R.id.open_track_button);
UiUtilities.setupDialogButton(nightMode, openTrackBtn, DialogButtonType.SECONDARY, R.string.shared_string_open_track);
final View showOnMapBtn = mainView.findViewById(R.id.close_button);
UiUtilities.setupDialogButton(nightMode, showOnMapBtn, DialogButtonType.SECONDARY, R.string.shared_string_close);
openTrackBtn.setOnClickListener(new OnClickListener() { SimpleBottomSheetItem titleItem = (SimpleBottomSheetItem) new SimpleBottomSheetItem.Builder()
@Override .setCustomView(mainView)
public void onClick(View v) { .create();
doRename(true); items.add(titleItem);
}
});
showOnMapBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
doRename(false);
}
});
return mainView;
} }
private void doRename(boolean openTrack) { private void doRename(boolean openTrack) {
@ -160,6 +137,26 @@ public class OnSaveCurrentTrackFragment extends BottomSheetDialogFragment {
} }
} }
@Override
protected UiUtilities.DialogButtonType getRightBottomButtonType() {
return UiUtilities.DialogButtonType.SECONDARY;
}
@Override
protected int getRightBottomButtonTextId() {
return R.string.shared_string_open_track;
}
@Override
protected void onRightBottomButtonClick() {
doRename(true);
}
@Override
protected void onDismissButtonClickAction() {
doRename(false);
}
@Override @Override
public void onDismiss(DialogInterface dialog) { public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog); super.onDismiss(dialog);
@ -199,10 +196,10 @@ public class OnSaveCurrentTrackFragment extends BottomSheetDialogFragment {
} }
OsmandApplication app = (OsmandApplication) activity.getApplication(); OsmandApplication app = (OsmandApplication) activity.getApplication();
GpxInfo gpxInfo = new GpxInfo(); AvailableGPXFragment.GpxInfo gpxInfo = new AvailableGPXFragment.GpxInfo();
gpxInfo.setGpx(GPXUtilities.loadGPXFile(f)); gpxInfo.setGpx(GPXUtilities.loadGPXFile(f));
if (gpxInfo.gpx != null) { if (gpxInfo.gpx != null) {
WptPt loc = gpxInfo.gpx.findPointToShow(); GPXUtilities.WptPt loc = gpxInfo.gpx.findPointToShow();
if (loc != null) { if (loc != null) {
app.getSelectedGpxHelper().setGpxFileToDisplay(gpxInfo.gpx); app.getSelectedGpxHelper().setGpxFileToDisplay(gpxInfo.gpx);
if (activity instanceof MapActivity) { if (activity instanceof MapActivity) {
@ -223,7 +220,7 @@ public class OnSaveCurrentTrackFragment extends BottomSheetDialogFragment {
if (fragmentManager.isStateSaved()) { if (fragmentManager.isStateSaved()) {
return; return;
} }
OnSaveCurrentTrackFragment f = new OnSaveCurrentTrackFragment(); SaveGPXBottomSheetFragment f = new SaveGPXBottomSheetFragment();
Bundle b = new Bundle(); Bundle b = new Bundle();
b.putStringArrayList(SAVED_TRACKS_KEY, new ArrayList<>(filenames)); b.putStringArrayList(SAVED_TRACKS_KEY, new ArrayList<>(filenames));
f.setArguments(b); f.setArguments(b);
@ -234,3 +231,4 @@ public class OnSaveCurrentTrackFragment extends BottomSheetDialogFragment {
} }
} }
} }

View file

@ -4,7 +4,6 @@ import android.app.Activity;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.net.Uri;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; 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.GpxDisplayGroup;
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem; import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItemType; 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.OsmandApplication;
import net.osmand.plus.R; import net.osmand.plus.R;
import net.osmand.plus.UiUtilities; 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.activities.TrackActivity;
import net.osmand.plus.base.OsmandExpandableListFragment; import net.osmand.plus.base.OsmandExpandableListFragment;
import net.osmand.plus.base.PointImageDrawable; import net.osmand.plus.base.PointImageDrawable;
import net.osmand.plus.helpers.GpxUiHelper;
import net.osmand.plus.mapmarkers.CoordinateInputDialogFragment; 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.myplaces.TrackBitmapDrawer.TrackBitmapDrawerListener;
import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.track.SaveGpxAsyncTask.SaveGpxListener; import net.osmand.plus.track.SaveGpxAsyncTask.SaveGpxListener;
@ -303,7 +303,8 @@ public class TrackPointFragment extends OsmandExpandableListFragment implements
private void shareItems() { private void shareItems() {
final GPXFile gpxFile = getGpx(); final GPXFile gpxFile = getGpx();
if (gpxFile != null && getTrackActivity() != null) { FragmentActivity activity = getActivity();
if (gpxFile != null && activity != null) {
if (Algorithms.isEmpty(gpxFile.path)) { if (Algorithms.isEmpty(gpxFile.path)) {
SaveGpxListener saveGpxListener = new SaveGpxListener() { SaveGpxListener saveGpxListener = new SaveGpxListener() {
@Override @Override
@ -315,26 +316,20 @@ public class TrackPointFragment extends OsmandExpandableListFragment implements
public void gpxSavingFinished(Exception errorMessage) { public void gpxSavingFinished(Exception errorMessage) {
if (isResumed()) { if (isResumed()) {
hideProgressBar(); 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); new SaveCurrentTrackTask(app, gpxFile, saveGpxListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} else { } 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() { private void openCoordinatesInput() {
FragmentManager fm = getFragmentManager(); FragmentManager fm = getFragmentManager();
if (fm != null) { if (fm != null) {
@ -412,7 +407,7 @@ public class TrackPointFragment extends OsmandExpandableListFragment implements
final MapMarkersHelper markersHelper = app.getMapMarkersHelper(); final MapMarkersHelper markersHelper = app.getMapMarkersHelper();
final boolean synced = markersHelper.getMarkersGroup(getGpx()) != null; final boolean synced = markersHelper.getMarkersGroup(getGpx()) != null;
createMenuItem(menu, SELECT_MAP_MARKERS_ID, synced ? R.string.remove_from_map_markers 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, 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); createMenuItem(menu, DELETE_ID, R.string.shared_string_delete, R.drawable.ic_action_delete_dark, MenuItem.SHOW_AS_ACTION_NEVER);

View file

@ -3,11 +3,9 @@ package net.osmand.plus.myplaces;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Matrix; import android.graphics.Matrix;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.util.SparseArray; import android.util.SparseArray;
@ -28,6 +26,7 @@ import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.SwitchCompat; import androidx.appcompat.widget.SwitchCompat;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.fragment.app.FragmentActivity;
import androidx.viewpager.widget.PagerAdapter; import androidx.viewpager.widget.PagerAdapter;
import com.github.mikephil.charting.charts.LineChart; 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.base.OsmAndListFragment;
import net.osmand.plus.helpers.AndroidUiHelper; import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.helpers.GpxUiHelper; 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.GPXDataSetAxisType;
import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetType; 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.helpers.GpxUiHelper.OrderedLineDataSet;
import net.osmand.plus.myplaces.TrackBitmapDrawer.TrackBitmapDrawerListener; import net.osmand.plus.myplaces.TrackBitmapDrawer.TrackBitmapDrawerListener;
import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.settings.backend.OsmandSettings;
@ -163,12 +162,11 @@ public class TrackSegmentFragment extends OsmAndListFragment implements TrackBit
.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { .setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override @Override
public boolean onMenuItemClick(MenuItem item) { public boolean onMenuItemClick(MenuItem item) {
final Uri fileUri = AndroidUtils.getUriForFile(getMyApplication(), new File(getGpx().path)); GPXFile gpx = getGpx();
final Intent sendIntent = new Intent(Intent.ACTION_SEND); FragmentActivity activity = getActivity();
sendIntent.putExtra(Intent.EXTRA_STREAM, fileUri); if (activity != null && gpx != null) {
sendIntent.setType("application/gpx+xml"); GpxUiHelper.shareGpx(activity, new File(gpx.path));
sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); }
startActivity(sendIntent);
return true; return true;
} }
}); });
@ -1209,7 +1207,7 @@ public class TrackSegmentFragment extends OsmAndListFragment implements TrackBit
} }
private void saveGpx(final SelectedGpxFile selectedGpxFile, GPXFile gpxFile) { private void saveGpx(final SelectedGpxFile selectedGpxFile, GPXFile gpxFile) {
new SaveGpxAsyncTask(gpxFile, new SaveGpxListener() { new SaveGpxAsyncTask(new File(gpxFile.path), gpxFile, new SaveGpxListener() {
@Override @Override
public void gpxSavingStarted() { public void gpxSavingStarted() {
TrackActivity activity = getTrackActivity(); TrackActivity activity = getTrackActivity();

View file

@ -417,8 +417,9 @@ public class OpenstreetmapRemoteUtil implements OpenstreetmapUtil {
} }
} }
} }
} else if (MapUtils.getDistance(n.getLatLon(), entity.getLatLon()) < 10) { } else if (MapUtils.getDistance(n.getLatLon(), entity.getLatLon()) < 10 ||
// avoid shifting due to round error 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.setLatitude(entity.getLatitude());
n.setLongitude(entity.getLongitude()); n.setLongitude(entity.getLongitude());
} }

View file

@ -56,6 +56,7 @@ public class BugBottomSheetDialog extends MenuBottomSheetDialogFragment {
View osmNoteView = View.inflate(UiUtilities.getThemedContext(app, nightMode), View osmNoteView = View.inflate(UiUtilities.getThemedContext(app, nightMode),
R.layout.open_osm_note_text, null); R.layout.open_osm_note_text, null);
osmNoteView.getViewTreeObserver().addOnGlobalLayoutListener(getShadowLayoutListener());
TextInputLayout textBox = osmNoteView.findViewById(R.id.name_text_box); TextInputLayout textBox = osmNoteView.findViewById(R.id.name_text_box);
textBox.setHint(AndroidUtils.addColon(app, R.string.osn_bug_name)); textBox.setHint(AndroidUtils.addColon(app, R.string.osn_bug_name));
ColorStateList colorStateList = ColorStateList.valueOf(ContextCompat 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, public static void showInstance(@NonNull FragmentManager fm, OsmBugsUtil osmBugsUtil, OsmBugsUtil local,
String text, int titleTextId, int posButtonTextId, final OsmPoint.Action action, String text, int titleTextId, int posButtonTextId, final OsmPoint.Action action,
final OsmBugsLayer.OpenStreetNote bug, final OsmNotesPoint point, final OsmBugsLayer.OpenStreetNote bug, final OsmNotesPoint point,
HandleOsmNoteAsyncTask.HandleBugListener handleBugListener) { HandleOsmNoteAsyncTask.HandleBugListener handleBugListener) {
try { try {
if (!fm.isStateSaved()) { if (!fm.isStateSaved()) {
BugBottomSheetDialog fragment = new BugBottomSheetDialog(); BugBottomSheetDialog fragment = new BugBottomSheetDialog();

View file

@ -1,14 +1,11 @@
package net.osmand.plus.osmedit.dialogs; package net.osmand.plus.osmedit.dialogs;
import android.graphics.Rect;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.text.Editable; import android.text.Editable;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
@ -54,10 +51,6 @@ public class SendGpxBottomSheetFragment extends MenuBottomSheetDialogFragment {
private TextInputEditText tagsField; private TextInputEditText tagsField;
private TextInputEditText messageField; private TextInputEditText messageField;
private int contentHeightPrevious = 0;
private int buttonsHeight;
private int shadowHeight;
private ScrollView scrollView;
public void setGpxInfos(GpxInfo[] gpxInfos) { public void setGpxInfos(GpxInfo[] gpxInfos) {
this.gpxInfos = gpxInfos; this.gpxInfos = gpxInfos;
@ -69,13 +62,13 @@ public class SendGpxBottomSheetFragment extends MenuBottomSheetDialogFragment {
OsmandSettings settings = app.getSettings(); OsmandSettings settings = app.getSettings();
LayoutInflater themedInflater = UiUtilities.getInflater(app, nightMode); LayoutInflater themedInflater = UiUtilities.getInflater(app, nightMode);
View sendOsmPoiView = themedInflater.inflate(R.layout.send_gpx_fragment, null); View sendGpxView = themedInflater.inflate(R.layout.send_gpx_fragment, null);
sendOsmPoiView.getViewTreeObserver().addOnGlobalLayoutListener(getOnGlobalLayoutListener()); sendGpxView.getViewTreeObserver().addOnGlobalLayoutListener(getShadowLayoutListener());
tagsField = sendOsmPoiView.findViewById(R.id.tags_field); tagsField = sendGpxView.findViewById(R.id.tags_field);
messageField = sendOsmPoiView.findViewById(R.id.message_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())) { if (!Algorithms.isEmpty(settings.USER_DISPLAY_NAME.get())) {
accountName.setText(settings.USER_DISPLAY_NAME.get()); accountName.setText(settings.USER_DISPLAY_NAME.get());
} else { } else {
@ -86,8 +79,8 @@ public class SendGpxBottomSheetFragment extends MenuBottomSheetDialogFragment {
messageField.setText(Algorithms.getFileNameWithoutExtension(fileName)); messageField.setText(Algorithms.getFileNameWithoutExtension(fileName));
messageField.setSelection(messageField.getText().length()); messageField.setSelection(messageField.getText().length());
final TextView visibilityName = sendOsmPoiView.findViewById(R.id.visibility_name); final TextView visibilityName = sendGpxView.findViewById(R.id.visibility_name);
final TextView visibilityDescription = sendOsmPoiView.findViewById(R.id.visibility_description); final TextView visibilityDescription = sendGpxView.findViewById(R.id.visibility_description);
visibilityName.setText(selectedUploadVisibility.getTitleId()); visibilityName.setText(selectedUploadVisibility.getTitleId());
visibilityDescription.setText(selectedUploadVisibility.getDescriptionId()); visibilityDescription.setText(selectedUploadVisibility.getDescriptionId());
@ -110,7 +103,7 @@ public class SendGpxBottomSheetFragment extends MenuBottomSheetDialogFragment {
horizontalSelectionAdapter.notifyDataSetChanged(); horizontalSelectionAdapter.notifyDataSetChanged();
} }
}); });
LinearLayout account = sendOsmPoiView.findViewById(R.id.account_container); LinearLayout account = sendGpxView.findViewById(R.id.account_container);
account.setOnClickListener(new View.OnClickListener() { account.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
@ -121,39 +114,17 @@ public class SendGpxBottomSheetFragment extends MenuBottomSheetDialogFragment {
dismiss(); dismiss();
} }
}); });
RecyclerView iconCategoriesRecyclerView = sendOsmPoiView.findViewById(R.id.description_view); RecyclerView iconCategoriesRecyclerView = sendGpxView.findViewById(R.id.description_view);
iconCategoriesRecyclerView.setAdapter(horizontalSelectionAdapter); iconCategoriesRecyclerView.setAdapter(horizontalSelectionAdapter);
iconCategoriesRecyclerView.setLayoutManager(new LinearLayoutManager(app, RecyclerView.HORIZONTAL, false)); iconCategoriesRecyclerView.setLayoutManager(new LinearLayoutManager(app, RecyclerView.HORIZONTAL, false));
horizontalSelectionAdapter.notifyDataSetChanged(); horizontalSelectionAdapter.notifyDataSetChanged();
SimpleBottomSheetItem titleItem = (SimpleBottomSheetItem) new SimpleBottomSheetItem.Builder() SimpleBottomSheetItem titleItem = (SimpleBottomSheetItem) new SimpleBottomSheetItem.Builder()
.setCustomView(sendOsmPoiView) .setCustomView(sendGpxView)
.create(); .create();
items.add(titleItem); 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) { protected static void showOpenStreetMapScreen(@NonNull FragmentActivity activity) {
if (activity instanceof MapActivity) { if (activity instanceof MapActivity) {
BaseSettingsFragment.showInstance(activity, OPEN_STREET_MAP_EDITING); BaseSettingsFragment.showInstance(activity, OPEN_STREET_MAP_EDITING);

View file

@ -77,6 +77,7 @@ public class SendOsmNoteBottomSheetFragment extends MenuBottomSheetDialogFragmen
final View sendOsmNoteView = View.inflate(new ContextThemeWrapper(getContext(), themeRes), final View sendOsmNoteView = View.inflate(new ContextThemeWrapper(getContext(), themeRes),
R.layout.send_osm_note_fragment, null); R.layout.send_osm_note_fragment, null);
sendOsmNoteView.getViewTreeObserver().addOnGlobalLayoutListener(getShadowLayoutListener());
noteText = sendOsmNoteView.findViewById(R.id.note_text); noteText = sendOsmNoteView.findViewById(R.id.note_text);
noteText.setText(((OsmNotesPoint) poi[0]).getText()); noteText.setText(((OsmNotesPoint) poi[0]).getText());

View file

@ -37,221 +37,222 @@ import static net.osmand.plus.osmedit.dialogs.SendGpxBottomSheetFragment.showOpe
public class SendPoiBottomSheetFragment extends MenuBottomSheetDialogFragment { public class SendPoiBottomSheetFragment extends MenuBottomSheetDialogFragment {
public static final String TAG = SendPoiBottomSheetFragment.class.getSimpleName(); public static final String TAG = SendPoiBottomSheetFragment.class.getSimpleName();
private static final Log LOG = PlatformUtil.getLog(SendPoiBottomSheetFragment.class); private static final Log LOG = PlatformUtil.getLog(SendPoiBottomSheetFragment.class);
public static final String OPENSTREETMAP_POINT = "openstreetmap_point"; public static final String OPENSTREETMAP_POINT = "openstreetmap_point";
private OsmPoint[] poi; private OsmPoint[] poi;
private SwitchCompat closeChangeSet; private SwitchCompat closeChangeSet;
private EditText messageEditText; private EditText messageEditText;
private boolean isLoginOAuth(OsmandSettings settings) { private boolean isLoginOAuth(OsmandSettings settings) {
return !Algorithms.isEmpty(settings.USER_DISPLAY_NAME.get()); return !Algorithms.isEmpty(settings.USER_DISPLAY_NAME.get());
} }
@Override @Override
public void createMenuItems(Bundle savedInstanceState) { public void createMenuItems(Bundle savedInstanceState) {
OsmandApplication app = getMyApplication(); OsmandApplication app = getMyApplication();
if (app == null) { if (app == null) {
return; return;
} }
poi = (OsmPoint[]) getArguments().getSerializable(OPENSTREETMAP_POINT); poi = (OsmPoint[]) getArguments().getSerializable(OPENSTREETMAP_POINT);
final boolean isNightMode = app.getDaynightHelper().isNightModeForMapControls(); final boolean isNightMode = app.getDaynightHelper().isNightModeForMapControls();
final View sendOsmPoiView = View.inflate(new ContextThemeWrapper(getContext(), themeRes), final View sendOsmPoiView = View.inflate(new ContextThemeWrapper(getContext(), themeRes),
R.layout.send_poi_fragment, null); R.layout.send_poi_fragment, null);
closeChangeSet = sendOsmPoiView.findViewById(R.id.close_change_set_checkbox); sendOsmPoiView.getViewTreeObserver().addOnGlobalLayoutListener(getShadowLayoutListener());
messageEditText = sendOsmPoiView.findViewById(R.id.message_field); closeChangeSet = sendOsmPoiView.findViewById(R.id.close_change_set_checkbox);
String defaultChangeSet = createDefaultChangeSet(app); messageEditText = sendOsmPoiView.findViewById(R.id.message_field);
messageEditText.setText(defaultChangeSet); String defaultChangeSet = createDefaultChangeSet(app);
messageEditText.setSelection(messageEditText.getText().length()); messageEditText.setText(defaultChangeSet);
final TextView accountName = sendOsmPoiView.findViewById(R.id.user_name); messageEditText.setSelection(messageEditText.getText().length());
OsmandSettings settings = app.getSettings(); final TextView accountName = sendOsmPoiView.findViewById(R.id.user_name);
String userNameOAuth = settings.USER_DISPLAY_NAME.get(); OsmandSettings settings = app.getSettings();
String userNameOpenID = settings.USER_NAME.get(); String userNameOAuth = settings.USER_DISPLAY_NAME.get();
String userName = isLoginOAuth(settings) ? userNameOAuth : userNameOpenID; String userNameOpenID = settings.USER_NAME.get();
accountName.setText(userName); String userName = isLoginOAuth(settings) ? userNameOAuth : userNameOpenID;
closeChangeSet.setBackgroundResource(isNightMode ? R.drawable.layout_bg_dark : R.drawable.layout_bg); accountName.setText(userName);
final int paddingSmall = app.getResources().getDimensionPixelSize(R.dimen.content_padding_small); closeChangeSet.setBackgroundResource(isNightMode ? R.drawable.layout_bg_dark : R.drawable.layout_bg);
closeChangeSet.setPadding(paddingSmall, 0, paddingSmall, 0); final int paddingSmall = app.getResources().getDimensionPixelSize(R.dimen.content_padding_small);
closeChangeSet.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { closeChangeSet.setPadding(paddingSmall, 0, paddingSmall, 0);
@Override closeChangeSet.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { @Override
if (isNightMode) { public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
closeChangeSet.setBackgroundResource( if (isNightMode) {
isChecked ? R.drawable.layout_bg_dark_solid : R.drawable.layout_bg_dark); closeChangeSet.setBackgroundResource(
} else { isChecked ? R.drawable.layout_bg_dark_solid : R.drawable.layout_bg_dark);
closeChangeSet.setBackgroundResource( } else {
isChecked ? R.drawable.layout_bg_solid : R.drawable.layout_bg); closeChangeSet.setBackgroundResource(
} isChecked ? R.drawable.layout_bg_solid : R.drawable.layout_bg);
closeChangeSet.setPadding(paddingSmall, 0, paddingSmall, 0); }
} closeChangeSet.setPadding(paddingSmall, 0, paddingSmall, 0);
}); }
LinearLayout account = sendOsmPoiView.findViewById(R.id.account_container); });
account.setOnClickListener(new View.OnClickListener() { LinearLayout account = sendOsmPoiView.findViewById(R.id.account_container);
@Override account.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) { @Override
FragmentActivity activity = getActivity(); public void onClick(View v) {
if (activity != null) { FragmentActivity activity = getActivity();
showOpenStreetMapScreen(activity); if (activity != null) {
} showOpenStreetMapScreen(activity);
dismiss(); }
} dismiss();
}); }
final SimpleBottomSheetItem titleItem = (SimpleBottomSheetItem) new SimpleBottomSheetItem.Builder() });
.setCustomView(sendOsmPoiView) final SimpleBottomSheetItem titleItem = (SimpleBottomSheetItem) new SimpleBottomSheetItem.Builder()
.create(); .setCustomView(sendOsmPoiView)
items.add(titleItem); .create();
} items.add(titleItem);
}
public static void showInstance(@NonNull FragmentManager fm, @NonNull OsmPoint[] points) { public static void showInstance(@NonNull FragmentManager fm, @NonNull OsmPoint[] points) {
try { try {
if (!fm.isStateSaved()) { if (!fm.isStateSaved()) {
SendPoiBottomSheetFragment fragment = new SendPoiBottomSheetFragment(); SendPoiBottomSheetFragment fragment = new SendPoiBottomSheetFragment();
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putSerializable(OPENSTREETMAP_POINT, points); bundle.putSerializable(OPENSTREETMAP_POINT, points);
fragment.setArguments(bundle); fragment.setArguments(bundle);
fragment.show(fm, TAG); fragment.show(fm, TAG);
} }
} catch (RuntimeException e) { } catch (RuntimeException e) {
LOG.error("showInstance", e); LOG.error("showInstance", e);
} }
} }
@Override @Override
protected UiUtilities.DialogButtonType getRightBottomButtonType() { protected UiUtilities.DialogButtonType getRightBottomButtonType() {
return (UiUtilities.DialogButtonType.PRIMARY); return (UiUtilities.DialogButtonType.PRIMARY);
} }
@Override @Override
protected void onRightBottomButtonClick() { protected void onRightBottomButtonClick() {
ProgressDialogPoiUploader progressDialogPoiUploader = null; ProgressDialogPoiUploader progressDialogPoiUploader = null;
Activity activity = getActivity(); Activity activity = getActivity();
if (activity instanceof MapActivity) { if (activity instanceof MapActivity) {
progressDialogPoiUploader = new SimpleProgressDialogPoiUploader((MapActivity) activity); progressDialogPoiUploader = new SimpleProgressDialogPoiUploader((MapActivity) activity);
} else if (getParentFragment() instanceof ProgressDialogPoiUploader) { } else if (getParentFragment() instanceof ProgressDialogPoiUploader) {
progressDialogPoiUploader = (ProgressDialogPoiUploader) getParentFragment(); progressDialogPoiUploader = (ProgressDialogPoiUploader) getParentFragment();
} }
if (progressDialogPoiUploader != null) { if (progressDialogPoiUploader != null) {
String comment = messageEditText.getText().toString(); String comment = messageEditText.getText().toString();
if (comment.length() > 0) { if (comment.length() > 0) {
for (OsmPoint osmPoint : poi) { for (OsmPoint osmPoint : poi) {
if (osmPoint.getGroup() == OsmPoint.Group.POI) { if (osmPoint.getGroup() == OsmPoint.Group.POI) {
((OpenstreetmapPoint) osmPoint).setComment(comment); ((OpenstreetmapPoint) osmPoint).setComment(comment);
break; break;
} }
} }
} }
progressDialogPoiUploader.showProgressDialog(poi, closeChangeSet.isChecked(), false); progressDialogPoiUploader.showProgressDialog(poi, closeChangeSet.isChecked(), false);
} }
dismiss(); dismiss();
} }
@Override @Override
protected int getRightBottomButtonTextId() { protected int getRightBottomButtonTextId() {
return R.string.shared_string_upload; return R.string.shared_string_upload;
} }
private String createDefaultChangeSet(OsmandApplication app) { private String createDefaultChangeSet(OsmandApplication app) {
Map<String, PoiType> allTranslatedSubTypes = app.getPoiTypes().getAllTranslatedNames(true); Map<String, PoiType> allTranslatedSubTypes = app.getPoiTypes().getAllTranslatedNames(true);
if (allTranslatedSubTypes == null) { if (allTranslatedSubTypes == null) {
return ""; return "";
} }
Map<String, Integer> addGroup = new HashMap<>(); Map<String, Integer> addGroup = new HashMap<>();
Map<String, Integer> editGroup = new HashMap<>(); Map<String, Integer> editGroup = new HashMap<>();
Map<String, Integer> deleteGroup = new HashMap<>(); Map<String, Integer> deleteGroup = new HashMap<>();
Map<String, Integer> reopenGroup = new HashMap<>(); Map<String, Integer> reopenGroup = new HashMap<>();
String comment = ""; String comment = "";
for (OsmPoint p : poi) { for (OsmPoint p : poi) {
if (p.getGroup() == OsmPoint.Group.POI) { if (p.getGroup() == OsmPoint.Group.POI) {
OsmPoint.Action action = p.getAction(); OsmPoint.Action action = p.getAction();
String type = ((OpenstreetmapPoint) p).getEntity().getTag(Entity.POI_TYPE_TAG); String type = ((OpenstreetmapPoint) p).getEntity().getTag(Entity.POI_TYPE_TAG);
if (type == null) { if (type == null) {
continue; continue;
} }
PoiType localizedPoiType = allTranslatedSubTypes.get(type.toLowerCase().trim()); PoiType localizedPoiType = allTranslatedSubTypes.get(type.toLowerCase().trim());
if (localizedPoiType != null) { if (localizedPoiType != null) {
type = Algorithms.capitalizeFirstLetter(localizedPoiType.getKeyName().replace('_', ' ')); type = Algorithms.capitalizeFirstLetter(localizedPoiType.getKeyName().replace('_', ' '));
} }
if (action == OsmPoint.Action.CREATE) { if (action == OsmPoint.Action.CREATE) {
if (!addGroup.containsKey(type)) { if (!addGroup.containsKey(type)) {
addGroup.put(type, 1); addGroup.put(type, 1);
} else { } else {
addGroup.put(type, addGroup.get(type) + 1); addGroup.put(type, addGroup.get(type) + 1);
} }
} else if (action == OsmPoint.Action.MODIFY) { } else if (action == OsmPoint.Action.MODIFY) {
if (!editGroup.containsKey(type)) { if (!editGroup.containsKey(type)) {
editGroup.put(type, 1); editGroup.put(type, 1);
} else { } else {
editGroup.put(type, editGroup.get(type) + 1); editGroup.put(type, editGroup.get(type) + 1);
} }
} else if (action == OsmPoint.Action.DELETE) { } else if (action == OsmPoint.Action.DELETE) {
if (!deleteGroup.containsKey(type)) { if (!deleteGroup.containsKey(type)) {
deleteGroup.put(type, 1); deleteGroup.put(type, 1);
} else { } else {
deleteGroup.put(type, deleteGroup.get(type) + 1); deleteGroup.put(type, deleteGroup.get(type) + 1);
} }
} else if (action == OsmPoint.Action.REOPEN) { } else if (action == OsmPoint.Action.REOPEN) {
if (!reopenGroup.containsKey(type)) { if (!reopenGroup.containsKey(type)) {
reopenGroup.put(type, 1); reopenGroup.put(type, 1);
} else { } else {
reopenGroup.put(type, reopenGroup.get(type) + 1); reopenGroup.put(type, reopenGroup.get(type) + 1);
} }
} }
} }
} }
int modifiedItemsOutOfLimit = 0; int modifiedItemsOutOfLimit = 0;
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
String action; String action;
Map<String, Integer> group; Map<String, Integer> group;
switch (i) { switch (i) {
case 0: case 0:
action = getString(R.string.default_changeset_add); action = getString(R.string.default_changeset_add);
group = addGroup; group = addGroup;
break; break;
case 1: case 1:
action = getString(R.string.default_changeset_edit); action = getString(R.string.default_changeset_edit);
group = editGroup; group = editGroup;
break; break;
case 2: case 2:
action = getString(R.string.default_changeset_delete); action = getString(R.string.default_changeset_delete);
group = deleteGroup; group = deleteGroup;
break; break;
case 3: case 3:
action = getString(R.string.default_changeset_reopen); action = getString(R.string.default_changeset_reopen);
group = reopenGroup; group = reopenGroup;
break; break;
default: default:
action = ""; action = "";
group = new HashMap<>(); group = new HashMap<>();
} }
if (!group.isEmpty()) { if (!group.isEmpty()) {
int pos = 0; int pos = 0;
for (Map.Entry<String, Integer> entry : group.entrySet()) { for (Map.Entry<String, Integer> entry : group.entrySet()) {
String type = entry.getKey(); String type = entry.getKey();
int quantity = entry.getValue(); int quantity = entry.getValue();
if (comment.length() > 200) { if (comment.length() > 200) {
modifiedItemsOutOfLimit += quantity; modifiedItemsOutOfLimit += quantity;
} else { } else {
if (pos == 0) { if (pos == 0) {
comment = comment.concat(comment.length() == 0 ? "" : "; ").concat(action).concat(" ") comment = comment.concat(comment.length() == 0 ? "" : "; ").concat(action).concat(" ")
.concat(quantity == 1 ? "" : quantity + " ").concat(type); .concat(quantity == 1 ? "" : quantity + " ").concat(type);
} else { } else {
comment = comment.concat(", ").concat(quantity == 1 ? "" : quantity + " ").concat(type); comment = comment.concat(", ").concat(quantity == 1 ? "" : quantity + " ").concat(type);
} }
} }
pos++; pos++;
} }
} }
} }
if (modifiedItemsOutOfLimit != 0) { if (modifiedItemsOutOfLimit != 0) {
comment = comment.concat("; ").concat(modifiedItemsOutOfLimit + " ") comment = comment.concat("; ").concat(modifiedItemsOutOfLimit + " ")
.concat(getString(R.string.items_modified)).concat("."); .concat(getString(R.string.items_modified)).concat(".");
} else if (!comment.isEmpty()) { } else if (!comment.isEmpty()) {
comment = comment.concat("."); comment = comment.concat(".");
} }
return comment; return comment;
} }
} }

View file

@ -369,7 +369,7 @@ public class RouteDetailsFragment extends ContextMenuFragment
super.calculateLayout(view, initLayout); super.calculateLayout(view, initLayout);
if (!initLayout && getCurrentMenuState() != MenuState.FULL_SCREEN) { if (!initLayout && getCurrentMenuState() != MenuState.FULL_SCREEN) {
if (refreshMapCallback != null) { if (refreshMapCallback != null) {
refreshMapCallback.refreshMap(false); refreshMapCallback.refreshMap(false, false);
} }
} }
} }

View file

@ -1,6 +1,7 @@
package net.osmand.plus.routepreparationmenu; package net.osmand.plus.routepreparationmenu;
import android.app.Activity; import android.app.Activity;
import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Build; import android.os.Build;
@ -12,11 +13,15 @@ import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.ColorRes; import androidx.annotation.ColorRes;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.SwitchCompat;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import net.osmand.AndroidUtils; import net.osmand.AndroidUtils;
import net.osmand.GPXUtilities.GPXFile; import net.osmand.GPXUtilities.GPXFile;
import net.osmand.PlatformUtil;
import net.osmand.StateChangedListener; import net.osmand.StateChangedListener;
import net.osmand.plus.OsmAndLocationSimulation; import net.osmand.plus.OsmAndLocationSimulation;
import net.osmand.plus.OsmandApplication; 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.SimpleBottomSheetItem;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.DividerStartItem; import net.osmand.plus.base.bottomsheetmenu.simpleitems.DividerStartItem;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem; 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.AvoidPTTypesRoutingParameter;
import net.osmand.plus.routepreparationmenu.RoutingOptionsHelper.AvoidRoadsRoutingParameter; import net.osmand.plus.routepreparationmenu.RoutingOptionsHelper.AvoidRoadsRoutingParameter;
import net.osmand.plus.routepreparationmenu.RoutingOptionsHelper.DividerItem; 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.router.GeneralRouter.RoutingParameter;
import net.osmand.util.Algorithms; import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log;
import java.io.File; import java.io.File;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map; 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.routepreparationmenu.RoutingOptionsHelper.DRIVING_STYLE;
import static net.osmand.plus.settings.fragments.RouteParametersFragment.RELIEF_SMOOTHNESS_FACTOR; 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; import static net.osmand.router.GeneralRouter.USE_HEIGHT_OBSTACLES;
public class RouteOptionsBottomSheet extends MenuBottomSheetDialogFragment { 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 OsmandApplication app;
private OsmandSettings settings; private OsmandSettings settings;
@ -79,16 +95,28 @@ public class RouteOptionsBottomSheet extends MenuBottomSheetDialogFragment {
private CommonPreference<Boolean> useHeightPref; private CommonPreference<Boolean> useHeightPref;
private StateChangedListener<Boolean> voiceMuteChangeListener; private StateChangedListener<Boolean> voiceMuteChangeListener;
private StateChangedListener<Boolean> useHeightChangeListener; private StateChangedListener<Boolean> useHeightChangeListener;
private boolean planRouteMode;
private List<RoutingParameter> reliefParameters = new ArrayList<>();
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(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(); app = requiredMyApplication();
settings = app.getSettings(); settings = app.getSettings();
routingHelper = app.getRoutingHelper(); routingHelper = app.getRoutingHelper();
routingOptionsHelper = app.getRoutingOptionsHelper(); routingOptionsHelper = app.getRoutingOptionsHelper();
mapActivity = getMapActivity(); mapActivity = getMapActivity();
applicationMode = routingHelper.getAppMode(); if (applicationMode == null) {
applicationMode = routingHelper.getAppMode();
}
selectedModeColorId = applicationMode.getIconColorInfo().getColor(nightMode); selectedModeColorId = applicationMode.getIconColorInfo().getColor(nightMode);
voiceMuteChangeListener = new StateChangedListener<Boolean>() { voiceMuteChangeListener = new StateChangedListener<Boolean>() {
@Override @Override
@ -103,6 +131,7 @@ public class RouteOptionsBottomSheet extends MenuBottomSheetDialogFragment {
} }
}; };
useHeightPref = settings.getCustomRoutingBooleanProperty(USE_HEIGHT_OBSTACLES, false); useHeightPref = settings.getCustomRoutingBooleanProperty(USE_HEIGHT_OBSTACLES, false);
reliefParameters = getReliefParameters();
} }
@Override @Override
@ -115,21 +144,29 @@ public class RouteOptionsBottomSheet extends MenuBottomSheetDialogFragment {
if (optionsItem instanceof DividerItem) { if (optionsItem instanceof DividerItem) {
items.add(new DividerStartItem(app)); items.add(new DividerStartItem(app));
} else if (optionsItem instanceof MuteSoundRoutingParameter) { } else if (optionsItem instanceof MuteSoundRoutingParameter) {
items.add(createMuteSoundItem(optionsItem)); if (!planRouteMode) {
items.add(createMuteSoundItem(optionsItem));
}
} else if (optionsItem instanceof ShowAlongTheRouteItem) { } else if (optionsItem instanceof ShowAlongTheRouteItem) {
items.add(createShowAlongTheRouteItem(optionsItem)); items.add(createShowAlongTheRouteItem(optionsItem));
} else if (optionsItem instanceof RouteSimulationItem) { } else if (optionsItem instanceof RouteSimulationItem) {
items.add(createRouteSimulationItem(optionsItem)); if (!planRouteMode) {
items.add(createRouteSimulationItem(optionsItem));
}
} else if (optionsItem instanceof AvoidPTTypesRoutingParameter) { } else if (optionsItem instanceof AvoidPTTypesRoutingParameter) {
items.add(createAvoidPTTypesItem(optionsItem)); items.add(createAvoidPTTypesItem(optionsItem));
} else if (optionsItem instanceof AvoidRoadsRoutingParameter) { } else if (optionsItem instanceof AvoidRoadsRoutingParameter) {
items.add(createAvoidRoadsItem(optionsItem)); items.add(createAvoidRoadsItem(optionsItem));
} else if (optionsItem instanceof GpxLocalRoutingParameter) { } else if (optionsItem instanceof GpxLocalRoutingParameter) {
items.add(createGpxRoutingItem(optionsItem)); if (!planRouteMode) {
items.add(createGpxRoutingItem(optionsItem));
}
} else if (optionsItem instanceof TimeConditionalRoutingItem) { } else if (optionsItem instanceof TimeConditionalRoutingItem) {
items.add(createTimeConditionalRoutingItem(optionsItem)); items.add(createTimeConditionalRoutingItem(optionsItem));
} else if (optionsItem instanceof OtherSettingsRoutingParameter) { } else if (optionsItem instanceof OtherSettingsRoutingParameter) {
items.add(createOtherSettingsRoutingItem(optionsItem)); items.add(createOtherSettingsRoutingItem(optionsItem));
} else if (USE_HEIGHT_OBSTACLES.equals(optionsItem.getKey()) && hasReliefParameters()) {
items.add(inflateElevationParameter(optionsItem));
} else { } else {
inflateRoutingParameter(optionsItem); inflateRoutingParameter(optionsItem);
} }
@ -256,6 +293,62 @@ public class RouteOptionsBottomSheet extends MenuBottomSheetDialogFragment {
.create(); .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) { private BaseBottomSheetItem createTimeConditionalRoutingItem(final LocalRoutingParameter optionsItem) {
final BottomSheetItemWithCompoundButton[] timeConditionalRoutingItem = new BottomSheetItemWithCompoundButton[1]; final BottomSheetItemWithCompoundButton[] timeConditionalRoutingItem = new BottomSheetItemWithCompoundButton[1];
timeConditionalRoutingItem[0] = (BottomSheetItemWithCompoundButton) new BottomSheetItemWithCompoundButton.Builder() timeConditionalRoutingItem[0] = (BottomSheetItemWithCompoundButton) new BottomSheetItemWithCompoundButton.Builder()
@ -415,8 +508,10 @@ public class RouteOptionsBottomSheet extends MenuBottomSheetDialogFragment {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
dismiss(); dismiss();
Bundle args = new Bundle();
args.putBoolean(PLANE_ROUTE, planRouteMode);
BaseSettingsFragment.showInstance(mapActivity, BaseSettingsFragment.SettingsScreenType.NAVIGATION, BaseSettingsFragment.showInstance(mapActivity, BaseSettingsFragment.SettingsScreenType.NAVIGATION,
mapActivity.getRoutingHelper().getAppMode()); applicationMode, args);
} }
}) })
.create(); .create();
@ -468,14 +563,7 @@ public class RouteOptionsBottomSheet extends MenuBottomSheetDialogFragment {
builder.setOnClickListener(new View.OnClickListener() { builder.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
if (USE_HEIGHT_OBSTACLES.equals(parameter.getKey()) && hasReliefParameters()) { applyParameter(item[0], parameter);
FragmentManager fm = getFragmentManager();
if (fm != null) {
ElevationDateBottomSheet.showInstance(fm, applicationMode, RouteOptionsBottomSheet.this, false);
}
} else {
applyParameter(item[0], parameter);
}
} }
}); });
} }
@ -488,14 +576,19 @@ public class RouteOptionsBottomSheet extends MenuBottomSheetDialogFragment {
} }
private boolean hasReliefParameters() { private boolean hasReliefParameters() {
return !Algorithms.isEmpty(reliefParameters);
}
private List<RoutingParameter> getReliefParameters() {
List<RoutingParameter> reliefFactorParameters = new ArrayList<>();
Map<String, RoutingParameter> parameters = app.getRouter(applicationMode).getParameters(); Map<String, RoutingParameter> parameters = app.getRouter(applicationMode).getParameters();
for (Map.Entry<String, RoutingParameter> e : parameters.entrySet()) { for (Map.Entry<String, RoutingParameter> entry : parameters.entrySet()) {
RoutingParameter routingParameter = e.getValue(); RoutingParameter routingParameter = entry.getValue();
if (RELIEF_SMOOTHNESS_FACTOR.equals(routingParameter.getGroup())) { if (RELIEF_SMOOTHNESS_FACTOR.equals(routingParameter.getGroup())) {
return true; reliefFactorParameters.add(routingParameter);
} }
} }
return false; return reliefFactorParameters;
} }
private void applyParameter(BottomSheetItemWithCompoundButton bottomSheetItem, LocalRoutingParameter parameter) { private void applyParameter(BottomSheetItemWithCompoundButton bottomSheetItem, LocalRoutingParameter parameter) {
@ -515,6 +608,23 @@ public class RouteOptionsBottomSheet extends MenuBottomSheetDialogFragment {
if (mapActivity != null) { if (mapActivity != null) {
mapActivity.getMapRouteInfoMenu().updateMenu(); 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<LocalRoutingParameter> getRoutingParameters(ApplicationMode applicationMode) { private List<LocalRoutingParameter> getRoutingParameters(ApplicationMode applicationMode) {
@ -549,8 +659,21 @@ public class RouteOptionsBottomSheet extends MenuBottomSheetDialogFragment {
} }
public static void showInstance(FragmentManager fragmentManager) { public static void showInstance(FragmentManager fragmentManager) {
RouteOptionsBottomSheet f = new RouteOptionsBottomSheet(); showInstance(fragmentManager, null);
f.show(fragmentManager, RouteOptionsBottomSheet.TAG); }
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() { public void updateParameters() {

View file

@ -129,6 +129,7 @@ public class FileSettingsItem extends StreamSettingsItem {
} }
protected File file; protected File file;
protected File savedFile;
private final File appPath; private final File appPath;
protected FileSubtype subtype; protected FileSubtype subtype;
private long size; private long size;
@ -280,18 +281,18 @@ public class FileSettingsItem extends StreamSettingsItem {
@Override @Override
public void readFromStream(@NonNull InputStream inputStream, String entryName) throws IOException, IllegalArgumentException { public void readFromStream(@NonNull InputStream inputStream, String entryName) throws IOException, IllegalArgumentException {
OutputStream output; OutputStream output;
File dest = FileSettingsItem.this.getFile(); savedFile = FileSettingsItem.this.getFile();
if (dest.isDirectory()) { if (savedFile.isDirectory()) {
dest = new File(dest, entryName.substring(fileName.length())); savedFile = new File(savedFile, entryName.substring(fileName.length()));
} }
if (dest.exists() && !shouldReplace) { if (savedFile.exists() && !shouldReplace) {
dest = renameFile(dest); savedFile = renameFile(savedFile);
} }
if (dest.getParentFile() != null && !dest.getParentFile().exists()) { if (savedFile.getParentFile() != null && !savedFile.getParentFile().exists()) {
//noinspection ResultOfMethodCallIgnored //noinspection ResultOfMethodCallIgnored
dest.getParentFile().mkdirs(); savedFile.getParentFile().mkdirs();
} }
output = new FileOutputStream(dest); output = new FileOutputStream(savedFile);
byte[] buffer = new byte[SettingsHelper.BUFFER]; byte[] buffer = new byte[SettingsHelper.BUFFER];
int count; int count;
try { try {
@ -303,7 +304,7 @@ public class FileSettingsItem extends StreamSettingsItem {
Algorithms.closeStream(output); Algorithms.closeStream(output);
} }
if (lastModified != -1) { if (lastModified != -1) {
dest.setLastModified(lastModified); savedFile.setLastModified(lastModified);
} }
} }
}; };

View file

@ -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);
}
}
}

View file

@ -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);
}
}
}

View file

@ -99,6 +99,7 @@ public class PluginSettingsItem extends SettingsItem {
@Override @Override
void writeToJson(@NonNull JSONObject json) throws JSONException { void writeToJson(@NonNull JSONObject json) throws JSONException {
super.writeToJson(json); super.writeToJson(json);
json.put("version", plugin.getVersion());
plugin.writeAdditionalDataToJson(json); plugin.writeAdditionalDataToJson(json);
} }

View file

@ -176,7 +176,7 @@ public class ProfileSettingsItem extends OsmandSettingsItem {
ApplicationMode.changeProfileAvailability(appMode, true, app); ApplicationMode.changeProfileAvailability(appMode, true, app);
} }
public void applyAdditionalPrefs() { public void applyAdditionalParams() {
if (additionalPrefsJson != null) { if (additionalPrefsJson != null) {
updatePluginResPrefs(); updatePluginResPrefs();

View file

@ -95,6 +95,7 @@ public class SettingsHelper {
public static final String SETTINGS_TYPE_LIST_KEY = "settings_type_list_key"; public static final String SETTINGS_TYPE_LIST_KEY = "settings_type_list_key";
public static final String REPLACE_KEY = "replace"; 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_LATEST_CHANGES_KEY = "settings_latest_changes";
public static final String SETTINGS_VERSION_KEY = "settings_version"; 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); exportSettings(fileDir, fileName, listener, new ArrayList<>(Arrays.asList(items)), exportItemsFiles);
} }
public List<SettingsItem> getFilteredSettingsItems(List<ExportSettingsType> settingsTypes, boolean globalExport) { public List<SettingsItem> getFilteredSettingsItems(List<ExportSettingsType> settingsTypes, boolean addProfiles, boolean export) {
Map<ExportSettingsType, List<?>> typesMap = new HashMap<>(); Map<ExportSettingsType, List<?>> typesMap = new HashMap<>();
typesMap.putAll(getSettingsItems(globalExport)); typesMap.putAll(getSettingsItems(addProfiles));
typesMap.putAll(getMyPlacesItems()); typesMap.putAll(getMyPlacesItems());
typesMap.putAll(getResourcesItems()); typesMap.putAll(getResourcesItems());
return getFilteredSettingsItems(typesMap, settingsTypes); return getFilteredSettingsItems(typesMap, settingsTypes, export);
} }
public List<SettingsItem> getFilteredSettingsItems(Map<ExportSettingsType, List<?>> allSettingsMap, public List<SettingsItem> getFilteredSettingsItems(Map<ExportSettingsType, List<?>> allSettingsMap,
List<ExportSettingsType> settingsTypes) { List<ExportSettingsType> settingsTypes, boolean export) {
List<SettingsItem> settingsItems = new ArrayList<>(); List<SettingsItem> settingsItems = new ArrayList<>();
for (ExportSettingsType settingsType : settingsTypes) { for (ExportSettingsType settingsType : settingsTypes) {
List<?> settingsDataObjects = allSettingsMap.get(settingsType); List<?> settingsDataObjects = allSettingsMap.get(settingsType);
if (settingsDataObjects != null) { if (settingsDataObjects != null) {
settingsItems.addAll(prepareSettingsItems(new ArrayList<>(settingsDataObjects))); settingsItems.addAll(prepareSettingsItems(settingsDataObjects, export));
} }
} }
return settingsItems; return settingsItems;
} }
public Map<ExportSettingsCategory, SettingsCategoryItems> getSettingsByCategory(boolean globalExport) { public Map<ExportSettingsCategory, SettingsCategoryItems> getSettingsByCategory(boolean addProfiles) {
Map<ExportSettingsCategory, SettingsCategoryItems> dataList = new LinkedHashMap<>(); Map<ExportSettingsCategory, SettingsCategoryItems> dataList = new LinkedHashMap<>();
Map<ExportSettingsType, List<?>> settingsItems = getSettingsItems(globalExport); Map<ExportSettingsType, List<?>> settingsItems = getSettingsItems(addProfiles);
Map<ExportSettingsType, List<?>> myPlacesItems = getMyPlacesItems(); Map<ExportSettingsType, List<?>> myPlacesItems = getMyPlacesItems();
Map<ExportSettingsType, List<?>> resourcesItems = getResourcesItems(); Map<ExportSettingsType, List<?>> resourcesItems = getResourcesItems();
@ -513,10 +514,10 @@ public class SettingsHelper {
return dataList; return dataList;
} }
private Map<ExportSettingsType, List<?>> getSettingsItems(boolean globalExport) { private Map<ExportSettingsType, List<?>> getSettingsItems(boolean addProfiles) {
Map<ExportSettingsType, List<?>> settingsItems = new LinkedHashMap<>(); Map<ExportSettingsType, List<?>> settingsItems = new LinkedHashMap<>();
if (globalExport) { if (addProfiles) {
List<ApplicationModeBean> appModeBeans = new ArrayList<>(); List<ApplicationModeBean> appModeBeans = new ArrayList<>();
for (ApplicationMode mode : ApplicationMode.allPossibleValues()) { for (ApplicationMode mode : ApplicationMode.allPossibleValues()) {
appModeBeans.add(mode.toModeBean()); appModeBeans.add(mode.toModeBean());
@ -687,7 +688,7 @@ public class SettingsHelper {
return files; return files;
} }
public List<SettingsItem> prepareSettingsItems(List<? super Object> data) { public List<SettingsItem> prepareSettingsItems(List<?> data, boolean export) {
List<SettingsItem> settingsItems = new ArrayList<>(); List<SettingsItem> settingsItems = new ArrayList<>();
List<QuickAction> quickActions = new ArrayList<>(); List<QuickAction> quickActions = new ArrayList<>();
List<PoiUIFilter> poiUIFilters = new ArrayList<>(); List<PoiUIFilter> poiUIFilters = new ArrayList<>();
@ -710,7 +711,12 @@ public class SettingsHelper {
tileSourceTemplates.add((ITileSource) object); tileSourceTemplates.add((ITileSource) object);
} else if (object instanceof File) { } else if (object instanceof File) {
try { 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) { } catch (IllegalArgumentException e) {
LOG.warn("Trying to export unsuported file type", e); LOG.warn("Trying to export unsuported file type", e);
} }
@ -749,7 +755,14 @@ public class SettingsHelper {
} }
if (!appModeBeans.isEmpty()) { if (!appModeBeans.isEmpty()) {
for (ApplicationModeBean modeBean : appModeBeans) { 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()) { if (!osmNotesPointList.isEmpty()) {
@ -924,6 +937,9 @@ public class SettingsHelper {
SearchHistorySettingsItem searchHistorySettingsItem = (SearchHistorySettingsItem) item; SearchHistorySettingsItem searchHistorySettingsItem = (SearchHistorySettingsItem) item;
historyEntries.addAll(searchHistorySettingsItem.getItems()); historyEntries.addAll(searchHistorySettingsItem.getItems());
break; break;
case GPX:
tracksFilesList.add((GpxSettingsItem) item);
break;
default: default:
break; break;
} }

View file

@ -128,6 +128,7 @@ class SettingsImporter {
if (reader != null) { if (reader != null) {
reader.readFromStream(ois, fileName); reader.readFromStream(ois, fileName);
} }
item.applyAdditionalParams();
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
item.warnings.add(app.getString(R.string.settings_item_read_error, item.getName())); item.warnings.add(app.getString(R.string.settings_item_read_error, item.getName()));
SettingsHelper.LOG.error("Error reading item data: " + item.getName(), e); SettingsHelper.LOG.error("Error reading item data: " + item.getName(), e);

View file

@ -123,6 +123,10 @@ public abstract class SettingsItem {
// non implemented // non implemented
} }
public void applyAdditionalParams() {
// non implemented
}
void readFromJson(@NonNull JSONObject json) throws JSONException { void readFromJson(@NonNull JSONObject json) throws JSONException {
pluginId = json.has("pluginId") ? json.getString("pluginId") : null; pluginId = json.has("pluginId") ? json.getString("pluginId") : null;
if (json.has("name")) { if (json.has("name")) {

View file

@ -7,6 +7,7 @@ public enum SettingsItemType {
DATA, DATA,
FILE, FILE,
RESOURCES, RESOURCES,
GPX,
QUICK_ACTIONS, QUICK_ACTIONS,
POI_UI_FILTERS, POI_UI_FILTERS,
MAP_SOURCES, MAP_SOURCES,

View file

@ -143,6 +143,9 @@ class SettingsItemsFactory {
case SEARCH_HISTORY: case SEARCH_HISTORY:
item = new SearchHistorySettingsItem(app, json); item = new SearchHistorySettingsItem(app, json);
break; break;
case GPX:
item = new GpxSettingsItem(app, json);
break;
} }
return item; return item;
} }

View file

@ -119,7 +119,7 @@ public class BooleanPreferenceBottomSheet extends BasePreferenceBottomSheet {
@Override @Override
protected int getDismissButtonTextId() { 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) { protected static View getCustomButtonView(OsmandApplication app, ApplicationMode mode, boolean checked, boolean nightMode) {

View file

@ -2,6 +2,7 @@ package net.osmand.plus.settings.bottomsheets;
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.view.View; import android.view.View;
import android.widget.TextView; 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.DividerSpaceItem;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.LongDescriptionItem; import net.osmand.plus.base.bottomsheetmenu.simpleitems.LongDescriptionItem;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem; 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.ApplicationMode;
import net.osmand.plus.settings.backend.CommonPreference; import net.osmand.plus.settings.backend.CommonPreference;
import net.osmand.plus.settings.fragments.ApplyQueryType; 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 @Override
public void createMenuItems(Bundle savedInstanceState) { public void createMenuItems(Bundle savedInstanceState) {
Context themedCtx = UiUtilities.getThemedContext(requireContext(), nightMode); Context themedCtx = UiUtilities.getThemedContext(requireContext(), nightMode);
on = getString(R.string.shared_string_enable); on = getString(R.string.shared_string_enabled);
off = getString(R.string.shared_string_disable); off = getString(R.string.shared_string_disabled);
appModeColor = appMode.getIconColorInfo().getColor(nightMode); appModeColor = appMode.getIconColorInfo().getColor(nightMode);
activeColor = AndroidUtils.resolveAttribute(themedCtx, R.attr.active_color_basic); activeColor = AndroidUtils.resolveAttribute(themedCtx, R.attr.active_color_basic);
disabledColor = AndroidUtils.resolveAttribute(themedCtx, android.R.attr.textColorSecondary); disabledColor = AndroidUtils.resolveAttribute(themedCtx, android.R.attr.textColorSecondary);
@ -171,7 +178,20 @@ public class ElevationDateBottomSheet extends MenuBottomSheetDialogFragment {
RoutingParameter parameter = parameters.get(selectedEntryIndex); RoutingParameter parameter = parameters.get(selectedEntryIndex);
updateSelectedParameters(app, appMode, parameters, parameter.getId()); 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(); updateReliefButtons();
app.runInUIThread(new Runnable() {
@Override
public void run() {
dismiss();
}
}, 500);
} }
}).create(); }).create();
items.add(preferenceItem[0]); items.add(preferenceItem[0]);

View file

@ -6,10 +6,10 @@ import android.os.Bundle;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ScrollView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.content.res.AppCompatResources;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
@ -44,6 +44,7 @@ public class OsmLoginDataBottomSheet extends BasePreferenceBottomSheet {
LayoutInflater themedInflater = UiUtilities.getInflater(requireContext(), nightMode); LayoutInflater themedInflater = UiUtilities.getInflater(requireContext(), nightMode);
View view = themedInflater.inflate(R.layout.osm_login_data, null); View view = themedInflater.inflate(R.layout.osm_login_data, null);
view.getViewTreeObserver().addOnGlobalLayoutListener(getShadowLayoutListener());
userNameEditText = view.findViewById(R.id.name_edit_text); userNameEditText = view.findViewById(R.id.name_edit_text);
passwordEditText = view.findViewById(R.id.password_edit_text); passwordEditText = view.findViewById(R.id.password_edit_text);
@ -73,6 +74,7 @@ public class OsmLoginDataBottomSheet extends BasePreferenceBottomSheet {
items.add(titleItem); items.add(titleItem);
} }
@Override @Override
public void onSaveInstanceState(@NonNull Bundle outState) { public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState); super.onSaveInstanceState(outState);
@ -107,7 +109,7 @@ public class OsmLoginDataBottomSheet extends BasePreferenceBottomSheet {
} }
public static boolean showInstance(@NonNull FragmentManager fragmentManager, String key, Fragment target, public static boolean showInstance(@NonNull FragmentManager fragmentManager, String key, Fragment target,
boolean usedOnMap, @Nullable ApplicationMode appMode) { boolean usedOnMap, @Nullable ApplicationMode appMode) {
try { try {
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putString(PREFERENCE_ID, key); args.putString(PREFERENCE_ID, key);

View file

@ -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;
import net.osmand.plus.settings.backend.backup.FileSettingsItem.FileSubtype; import net.osmand.plus.settings.backend.backup.FileSettingsItem.FileSubtype;
import net.osmand.plus.settings.backend.backup.GlobalSettingsItem; 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.plus.settings.fragments.ExportSettingsAdapter.OnItemSelectedListener;
import net.osmand.util.Algorithms; import net.osmand.util.Algorithms;
import net.osmand.view.ThreeStateCheckbox; import net.osmand.view.ThreeStateCheckbox;
@ -313,11 +315,13 @@ public class ExportItemsBottomSheet extends MenuBottomSheetDialogFragment {
builder.setTitle(tileSource.getName()); builder.setTitle(tileSource.getName());
builder.setIcon(uiUtilities.getIcon(R.drawable.ic_map, activeColorRes)); builder.setIcon(uiUtilities.getIcon(R.drawable.ic_map, activeColorRes));
} else if (object instanceof File) { } else if (object instanceof File) {
File file = (File) object; setupBottomSheetItemForFile(builder, (File) object);
setupBottomSheetItemForFile(builder, file, file.lastModified(), file.length()); } else if (object instanceof GpxSettingsItem) {
GpxSettingsItem item = (GpxSettingsItem) object;
setupBottomSheetItemForGpx(builder, item.getFile(), item.getAppearanceInfo());
} else if (object instanceof FileSettingsItem) { } else if (object instanceof FileSettingsItem) {
FileSettingsItem item = (FileSettingsItem) object; FileSettingsItem item = (FileSettingsItem) object;
setupBottomSheetItemForFile(builder, item.getFile(), item.getLastModified(), item.getSize()); setupBottomSheetItemForFile(builder, item.getFile());
} else if (object instanceof AvoidRoadInfo) { } else if (object instanceof AvoidRoadInfo) {
AvoidRoadInfo avoidRoadInfo = (AvoidRoadInfo) object; AvoidRoadInfo avoidRoadInfo = (AvoidRoadInfo) object;
builder.setTitle(avoidRoadInfo.name); 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()); FileSubtype fileSubtype = FileSubtype.getSubtypeByPath(app, file.getPath());
builder.setTitle(file.getName()); builder.setTitle(file.getName());
if (file.getAbsolutePath().contains(IndexConstants.RENDERERS_DIR)) { 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)) { } else if (file.getAbsolutePath().contains(IndexConstants.ROUTING_PROFILES_DIR)) {
builder.setIcon(uiUtilities.getIcon(R.drawable.ic_action_route_distance, activeColorRes)); builder.setIcon(uiUtilities.getIcon(R.drawable.ic_action_route_distance, activeColorRes));
} else if (file.getAbsolutePath().contains(IndexConstants.GPX_INDEX_DIR)) { } else if (file.getAbsolutePath().contains(IndexConstants.GPX_INDEX_DIR)) {
builder.setTitle(GpxUiHelper.getGpxTitle(file.getName())); setupBottomSheetItemForGpx(builder, file, null);
builder.setTag(file);
builder.setDescription(getTrackDescr(file, lastModified, size));
builder.setIcon(uiUtilities.getIcon(R.drawable.ic_action_route_distance, activeColorRes));
} else if (file.getAbsolutePath().contains(IndexConstants.AV_INDEX_DIR)) { } else if (file.getAbsolutePath().contains(IndexConstants.AV_INDEX_DIR)) {
int iconId = AudioVideoNotesPlugin.getIconIdForRecordingFile(file); int iconId = AudioVideoNotesPlugin.getIconIdForRecordingFile(file);
if (iconId == -1) { if (iconId == -1) {
iconId = R.drawable.ic_action_photo_dark; iconId = R.drawable.ic_action_photo_dark;
} }
builder.setIcon(uiUtilities.getIcon(iconId, activeColorRes)); builder.setIcon(uiUtilities.getIcon(iconId, activeColorRes));
builder.setDescription(AndroidUtils.formatSize(app, size)); builder.setDescription(AndroidUtils.formatSize(app, file.length()));
} else if (fileSubtype.isMap() } else if (fileSubtype.isMap()
|| fileSubtype == FileSettingsItem.FileSubtype.TTS_VOICE || fileSubtype == FileSettingsItem.FileSubtype.TTS_VOICE
|| fileSubtype == FileSettingsItem.FileSubtype.VOICE) { || fileSubtype == FileSettingsItem.FileSubtype.VOICE) {
@ -388,7 +389,7 @@ public class ExportItemsBottomSheet extends MenuBottomSheetDialogFragment {
if (fileSubtype.isMap()) { if (fileSubtype.isMap()) {
String mapDescription = getMapDescription(file); String mapDescription = getMapDescription(file);
String formattedSize = AndroidUtils.formatSize(app, size); String formattedSize = AndroidUtils.formatSize(app, file.length());
if (mapDescription != null) { if (mapDescription != null) {
builder.setDescription(getString(R.string.ltr_or_rtl_combine_via_bold_point, mapDescription, formattedSize)); builder.setDescription(getString(R.string.ltr_or_rtl_combine_via_bold_point, mapDescription, formattedSize));
} else { } 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() { private final GpxDataItemCallback gpxDataItemCallback = new GpxDataItemCallback() {
@Override @Override
public boolean isCancelled() { public boolean isCancelled() {
@ -407,15 +414,18 @@ public class ExportItemsBottomSheet extends MenuBottomSheetDialogFragment {
@Override @Override
public void onGpxDataItemReady(GpxDataItem item) { public void onGpxDataItemReady(GpxDataItem item) {
for (BaseBottomSheetItem bottomSheetItem : items) { for (BaseBottomSheetItem bottomSheetItem : items) {
if (Algorithms.objectEquals(item.getFile(), bottomSheetItem.getTag())) { Object tag = bottomSheetItem.getTag();
((BottomSheetItemWithDescription) bottomSheetItem).setDescription(getTrackDescrForDataItem(item)); if (tag instanceof FileSettingsItem) {
break; 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 = ""; String folder = "";
File parent = file.getParentFile(); File parent = file.getParentFile();
if (parent != null) { if (parent != null) {
@ -426,6 +436,11 @@ public class ExportItemsBottomSheet extends MenuBottomSheetDialogFragment {
if (dataItem != null) { if (dataItem != null) {
return getTrackDescrForDataItem(dataItem); 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 { } else {
String date = OsmAndFormatter.getFormattedDate(app, lastModified); String date = OsmAndFormatter.getFormattedDate(app, lastModified);
String formattedSize = AndroidUtils.formatSize(app, size); String formattedSize = AndroidUtils.formatSize(app, size);

View file

@ -24,14 +24,18 @@ import net.osmand.IndexConstants;
import net.osmand.PlatformUtil; import net.osmand.PlatformUtil;
import net.osmand.plus.R; import net.osmand.plus.R;
import net.osmand.plus.settings.backend.ApplicationMode; 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.FileSettingsItem;
import net.osmand.plus.settings.backend.backup.SettingsHelper.SettingsExportListener; import net.osmand.plus.settings.backend.backup.SettingsHelper.SettingsExportListener;
import net.osmand.plus.settings.backend.backup.SettingsItem; import net.osmand.plus.settings.backend.backup.SettingsItem;
import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import java.io.File; import java.io.File;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
@ -73,7 +77,10 @@ public class ExportSettingsFragment extends BaseSettingsListFragment {
progressValue = savedInstanceState.getInt(PROGRESS_VALUE_KEY); progressValue = savedInstanceState.getInt(PROGRESS_VALUE_KEY);
} }
exportMode = true; exportMode = true;
dataList = app.getSettingsHelper().getSettingsByCategory(globalExport); dataList = app.getSettingsHelper().getSettingsByCategory(true);
if (!globalExport && savedInstanceState == null) {
updateSelectedProfile();
}
} }
@Nullable @Nullable
@ -122,6 +129,20 @@ public class ExportSettingsFragment extends BaseSettingsListFragment {
} }
} }
private void updateSelectedProfile() {
List<Object> profileItems = getItemsForType(ExportSettingsType.PROFILE);
if (!Algorithms.isEmpty(profileItems)) {
for (Object item : profileItems) {
if (item instanceof ApplicationModeBean && appMode.getStringKey().equals(((ApplicationModeBean) item).stringKey)) {
List<Object> selectedProfiles = new ArrayList<>();
selectedProfiles.add(item);
selectedItemsMap.put(ExportSettingsType.PROFILE, selectedProfiles);
break;
}
}
}
}
private void prepareFile() { private void prepareFile() {
if (app != null) { if (app != null) {
exportingStarted = true; exportingStarted = true;
@ -129,7 +150,7 @@ public class ExportSettingsFragment extends BaseSettingsListFragment {
showExportProgressDialog(); showExportProgressDialog();
File tempDir = FileUtils.getTempDir(app); File tempDir = FileUtils.getTempDir(app);
String fileName = getFileName(); String fileName = getFileName();
List<SettingsItem> items = app.getSettingsHelper().prepareSettingsItems(adapter.getData()); List<SettingsItem> items = app.getSettingsHelper().prepareSettingsItems(adapter.getData(), true);
progress.setMax(getMaxProgress(items)); progress.setMax(getMaxProgress(items));
app.getSettingsHelper().exportSettings(tempDir, fileName, getSettingsExportListener(), items, true); app.getSettingsHelper().exportSettings(tempDir, fileName, getSettingsExportListener(), items, true);
} }

View file

@ -18,6 +18,7 @@ import androidx.fragment.app.FragmentManager;
import com.google.android.material.appbar.CollapsingToolbarLayout; import com.google.android.material.appbar.CollapsingToolbarLayout;
import net.osmand.IndexConstants;
import net.osmand.PlatformUtil; import net.osmand.PlatformUtil;
import net.osmand.map.ITileSource; import net.osmand.map.ITileSource;
import net.osmand.map.TileSourceManager.TileSourceTemplate; 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.FavoritesSettingsItem;
import net.osmand.plus.settings.backend.backup.FileSettingsItem; import net.osmand.plus.settings.backend.backup.FileSettingsItem;
import net.osmand.plus.settings.backend.backup.GlobalSettingsItem; 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.HistoryMarkersSettingsItem;
import net.osmand.plus.settings.backend.backup.MapSourcesSettingsItem; import net.osmand.plus.settings.backend.backup.MapSourcesSettingsItem;
import net.osmand.plus.settings.backend.backup.MarkersSettingsItem; 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) { } else if (object instanceof TileSourceTemplate || object instanceof SQLiteTileSource) {
tileSourceTemplates.add((ITileSource) object); tileSourceTemplates.add((ITileSource) object);
} else if (object instanceof File) { } 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) { } else if (object instanceof FileSettingsItem) {
settingsItems.add((FileSettingsItem) object); settingsItems.add((FileSettingsItem) object);
} else if (object instanceof AvoidRoadInfo) { } else if (object instanceof AvoidRoadInfo) {

View file

@ -3,9 +3,11 @@ package net.osmand.plus.settings.fragments;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Bundle; import android.os.Bundle;
import androidx.activity.OnBackPressedCallback;
import androidx.preference.Preference; import androidx.preference.Preference;
import androidx.preference.SwitchPreferenceCompat; import androidx.preference.SwitchPreferenceCompat;
import net.osmand.plus.routepreparationmenu.RouteOptionsBottomSheet;
import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin; 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.PROFILE_KEY_ARG;
import static net.osmand.plus.profiles.SelectProfileBottomSheetDialogFragment.SELECTED_KEY; import static net.osmand.plus.profiles.SelectProfileBottomSheetDialogFragment.SELECTED_KEY;
import static net.osmand.plus.profiles.SelectProfileBottomSheetDialogFragment.TYPE_NAV_PROFILE; import static net.osmand.plus.profiles.SelectProfileBottomSheetDialogFragment.TYPE_NAV_PROFILE;
import static net.osmand.plus.routepreparationmenu.RouteOptionsBottomSheet.PLANE_ROUTE;
public class NavigationFragment extends BaseSettingsFragment { public class NavigationFragment extends BaseSettingsFragment {
@ -48,6 +51,16 @@ public class NavigationFragment extends BaseSettingsFragment {
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
routingProfileDataObjects = getRoutingProfiles(app); 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 @Override

View file

@ -285,12 +285,12 @@ public class RouteParametersFragment extends BaseSettingsFragment implements OnP
if (p.getType() == RoutingParameterType.BOOLEAN) { if (p.getType() == RoutingParameterType.BOOLEAN) {
OsmandPreference pref = settings.getCustomRoutingBooleanProperty(p.getId(), p.getDefaultBoolean()); 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.setDescription(description);
switchPreferenceEx.setIcon(getRoutingPrefIcon(p.getId())); switchPreferenceEx.setIcon(getRoutingPrefIcon(p.getId()));
switchPreferenceEx.setSummaryOn(R.string.shared_string_on);
switchPreferenceEx.setSummaryOff(R.string.shared_string_off);
screen.addPreference(switchPreferenceEx); screen.addPreference(switchPreferenceEx);
setupOtherBooleanParameterSummary(am, p, switchPreferenceEx);
} else { } else {
Object[] vls = p.getPossibleValues(); Object[] vls = p.getPossibleValues();
String[] svlss = new String[vls.length]; String[] svlss = new String[vls.length];
@ -340,6 +340,22 @@ public class RouteParametersFragment extends BaseSettingsFragment implements OnP
setupFastRecalculationPref(); 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) { private void addDivider(PreferenceScreen screen) {
Preference divider = new Preference(requireContext()); Preference divider = new Preference(requireContext());
divider.setLayoutResource(R.layout.simple_divider_item); divider.setLayoutResource(R.layout.simple_divider_item);
@ -403,7 +419,7 @@ public class RouteParametersFragment extends BaseSettingsFragment implements OnP
return; return;
} }
final OsmandApplication app = (OsmandApplication) activity.getApplication(); 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); boolean nightMode = !app.getSettings().isLightContentForMode(mode);
Context themedContext = UiUtilities.getThemedContext(activity, nightMode); Context themedContext = UiUtilities.getThemedContext(activity, nightMode);
AlertDialog.Builder builder = new AlertDialog.Builder(themedContext); AlertDialog.Builder builder = new AlertDialog.Builder(themedContext);

View file

@ -3,6 +3,7 @@ package net.osmand.plus.track;
import android.content.Context; import android.content.Context;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes; import androidx.annotation.StringRes;
import net.osmand.plus.R; import net.osmand.plus.R;
@ -36,21 +37,23 @@ public enum GpxSplitType {
return ctx.getString(resId); return ctx.getString(resId);
} }
public static GpxSplitType getSplitTypeByName(@NonNull String name) { @NonNull
public static GpxSplitType getSplitTypeByName(@Nullable String name) {
for (GpxSplitType splitType : GpxSplitType.values()) { for (GpxSplitType splitType : GpxSplitType.values()) {
if (splitType.name().equalsIgnoreCase(name)) { if (splitType.name().equalsIgnoreCase(name)) {
return splitType; return splitType;
} }
} }
return null; return NO_SPLIT;
} }
@NonNull
public static GpxSplitType getSplitTypeByTypeId(int typeId) { public static GpxSplitType getSplitTypeByTypeId(int typeId) {
for (GpxSplitType splitType : GpxSplitType.values()) { for (GpxSplitType splitType : GpxSplitType.values()) {
if (splitType.getType() == typeId) { if (splitType.getType() == typeId) {
return splitType; return splitType;
} }
} }
return null; return NO_SPLIT;
} }
} }

View file

@ -12,12 +12,14 @@ import java.io.File;
public class SaveGpxAsyncTask extends AsyncTask<Void, Void, Exception> { public class SaveGpxAsyncTask extends AsyncTask<Void, Void, Exception> {
private final File file;
private final GPXFile gpx; private final GPXFile gpx;
private final SaveGpxListener saveGpxListener; private final SaveGpxListener saveGpxListener;
public SaveGpxAsyncTask(@NonNull GPXFile gpx, public SaveGpxAsyncTask(@NonNull File file, @NonNull GPXFile gpx,
@Nullable SaveGpxListener saveGpxListener) { @Nullable SaveGpxListener saveGpxListener) {
this.gpx = gpx; this.gpx = gpx;
this.file = file;
this.saveGpxListener = saveGpxListener; this.saveGpxListener = saveGpxListener;
} }
@ -30,7 +32,7 @@ public class SaveGpxAsyncTask extends AsyncTask<Void, Void, Exception> {
@Override @Override
protected Exception doInBackground(Void... params) { protected Exception doInBackground(Void... params) {
return GPXUtilities.writeGpxFile(new File(gpx.path), gpx); return GPXUtilities.writeGpxFile(file, gpx);
} }
@Override @Override

View file

@ -28,6 +28,7 @@ import net.osmand.PlatformUtil;
import net.osmand.data.QuadRect; import net.osmand.data.QuadRect;
import net.osmand.data.RotatedTileBox; import net.osmand.data.RotatedTileBox;
import net.osmand.plus.GPXDatabase.GpxDataItem; import net.osmand.plus.GPXDatabase.GpxDataItem;
import net.osmand.plus.GpxDbHelper;
import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup; import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup;
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItemType; import net.osmand.plus.GpxSelectionHelper.GpxDisplayItemType;
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile; 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 static final String SHOW_START_FINISH_ICONS_INITIAL_VALUE_KEY = "showStartFinishIconsInitialValueKey";
private OsmandApplication app; private OsmandApplication app;
private GpxDbHelper gpxDbHelper;
@Nullable @Nullable
private GpxDataItem gpxDataItem; private GpxDataItem gpxDataItem;
@ -128,6 +130,7 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
app = requireMyApplication(); app = requireMyApplication();
gpxDbHelper = app.getGpxDbHelper();
Bundle arguments = getArguments(); Bundle arguments = getArguments();
if (savedInstanceState != null) { if (savedInstanceState != null) {
@ -138,7 +141,7 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement
selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(trackDrawInfo.getFilePath()); selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(trackDrawInfo.getFilePath());
} }
if (!selectedGpxFile.isShowCurrentTrack()) { 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, showStartFinishIconsInitialValue = savedInstanceState.getBoolean(SHOW_START_FINISH_ICONS_INITIAL_VALUE_KEY,
app.getSettings().SHOW_START_FINISH_ICONS.get()); 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()); trackDrawInfo.setShowStartFinish(app.getSettings().CURRENT_TRACK_SHOW_START_FINISH.get());
selectedGpxFile = app.getSavingTrackHelper().getCurrentTrack(); selectedGpxFile = app.getSavingTrackHelper().getCurrentTrack();
} else { } else {
gpxDataItem = app.getGpxDbHelper().getItem(new File(gpxFilePath)); gpxDataItem = gpxDbHelper.getItem(new File(gpxFilePath));
trackDrawInfo = new TrackDrawInfo(app, gpxDataItem, false); trackDrawInfo = new TrackDrawInfo(app, gpxDataItem, false);
selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(gpxFilePath); selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(gpxFilePath);
} }
@ -527,10 +530,10 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement
} }
private void saveCustomColorsToTracks(int prevColor, int newColor) { private void saveCustomColorsToTracks(int prevColor, int newColor) {
List<GpxDataItem> gpxDataItems = app.getGpxDbHelper().getItems(); List<GpxDataItem> gpxDataItems = gpxDbHelper.getItems();
for (GpxDataItem dataItem : gpxDataItems) { for (GpxDataItem dataItem : gpxDataItems) {
if (prevColor == dataItem.getColor()) { if (prevColor == dataItem.getColor()) {
app.getGpxDbHelper().updateColor(dataItem, newColor); gpxDbHelper.updateColor(dataItem, newColor);
} }
} }
List<SelectedGpxFile> files = app.getSelectedGpxHelper().getSelectedGPXFiles(); List<SelectedGpxFile> files = app.getSelectedGpxHelper().getSelectedGPXFiles();
@ -554,36 +557,19 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement
private void saveTrackInfo() { private void saveTrackInfo() {
GPXFile gpxFile = selectedGpxFile.getGpxFile(); 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) { if (gpxFile.showCurrentTrack) {
app.getSettings().CURRENT_TRACK_COLOR.set(trackDrawInfo.getColor()); app.getSettings().CURRENT_TRACK_COLOR.set(trackDrawInfo.getColor());
app.getSettings().CURRENT_TRACK_WIDTH.set(trackDrawInfo.getWidth()); app.getSettings().CURRENT_TRACK_WIDTH.set(trackDrawInfo.getWidth());
app.getSettings().CURRENT_TRACK_SHOW_ARROWS.set(trackDrawInfo.isShowArrows()); app.getSettings().CURRENT_TRACK_SHOW_ARROWS.set(trackDrawInfo.isShowArrows());
app.getSettings().CURRENT_TRACK_SHOW_START_FINISH.set(trackDrawInfo.isShowStartFinish()); app.getSettings().CURRENT_TRACK_SHOW_START_FINISH.set(trackDrawInfo.isShowStartFinish());
} else { } else if (gpxDataItem != null) {
if (gpxDataItem != null) { GpxSplitType splitType = GpxSplitType.getSplitTypeByTypeId(trackDrawInfo.getSplitType());
gpxDataItem = new GpxDataItem(new File(gpxFile.path), gpxFile); gpxDbHelper.updateColor(gpxDataItem, trackDrawInfo.getColor());
app.getGpxDbHelper().add(gpxDataItem); gpxDbHelper.updateWidth(gpxDataItem, trackDrawInfo.getWidth());
} gpxDbHelper.updateShowArrows(gpxDataItem, trackDrawInfo.isShowArrows());
app.getSelectedGpxHelper().updateSelectedGpxFile(selectedGpxFile); // gpxDbHelper.updateShowStartFinish(gpxDataItem, trackDrawInfo.isShowStartFinish());
saveGpx(gpxFile); 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(); double distanceSplit = gpxDataItem.getSplitInterval();
GpxSplitType splitType = GpxSplitType.getSplitTypeByTypeId(gpxDataItem.getSplitType()); GpxSplitType splitType = GpxSplitType.getSplitTypeByTypeId(gpxDataItem.getSplitType());
if (splitType == null) {
splitType = GpxSplitType.NO_SPLIT;
}
applySplit(splitType, timeSplit, distanceSplit); applySplit(splitType, timeSplit, distanceSplit);
} }
} }
@ -633,10 +616,6 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement
timeSplit, distanceSplit).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 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() { private void setupCards() {
MapActivity mapActivity = getMapActivity(); MapActivity mapActivity = getMapActivity();
if (mapActivity != null) { if (mapActivity != null) {

View file

@ -33,6 +33,8 @@ import net.osmand.data.PointDescription;
import net.osmand.data.QuadRect; import net.osmand.data.QuadRect;
import net.osmand.data.QuadTree; import net.osmand.data.QuadTree;
import net.osmand.data.RotatedTileBox; 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;
import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup; import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup;
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem; import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
@ -69,6 +71,7 @@ import net.osmand.util.MapUtils;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
@ -106,8 +109,10 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
private TrackDrawInfo trackDrawInfo; private TrackDrawInfo trackDrawInfo;
private TrackChartPoints trackChartPoints; private TrackChartPoints trackChartPoints;
private GpxSelectionHelper selectedGpxHelper; private GpxDbHelper gpxDbHelper;
private MapMarkersHelper mapMarkersHelper; private MapMarkersHelper mapMarkersHelper;
private GpxSelectionHelper selectedGpxHelper;
private List<WptPt> cache = new ArrayList<>(); private List<WptPt> cache = new ArrayList<>();
private Map<WptPt, SelectedGpxFile> pointFileMap = new HashMap<>(); private Map<WptPt, SelectedGpxFile> pointFileMap = new HashMap<>();
private MapTextLayer textLayer; private MapTextLayer textLayer;
@ -144,6 +149,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
@Override @Override
public void initLayer(OsmandMapTileView view) { public void initLayer(OsmandMapTileView view) {
this.view = view; this.view = view;
gpxDbHelper = view.getApplication().getGpxDbHelper();
selectedGpxHelper = view.getApplication().getSelectedGpxHelper(); selectedGpxHelper = view.getApplication().getSelectedGpxHelper();
mapMarkersHelper = view.getApplication().getMapMarkersHelper(); mapMarkersHelper = view.getApplication().getMapMarkersHelper();
osmandRenderer = view.getApplication().getResourceManager().getRenderer().getRenderer(); 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()); RenderingContext rc = new OsmandRenderer.RenderingContext(view.getContext());
rc.setDensityValue((float) tileBox.getMapDensity()); rc.setDensityValue((float) tileBox.getMapDensity());
cachedColor = req.getIntPropertyValue(rrs.PROPS.R_COLOR); cachedColor = req.getIntPropertyValue(rrs.PROPS.R_COLOR);
defaultTrackWidth = rc.getComplexValue(req, req.ALL.R_STROKE_WIDTH);
osmandRenderer.updatePaint(req, paint, 0, false, rc); osmandRenderer.updatePaint(req, paint, 0, false, rc);
if (req.isSpecified(rrs.PROPS.R_SHADOW_RADIUS)) { 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()); boolean showArrows = isShowArrowsForTrack(selectedGpxFile.getGpxFile());
if (showArrows) { if (showArrows) {
QuadRect correctedQuadRect = getCorrectedQuadRect(tileBox.getLatLonBounds()); QuadRect correctedQuadRect = getCorrectedQuadRect(tileBox.getLatLonBounds());
String width = getTrackWidthName(selectedGpxFile.getGpxFile(), ""); String width = getTrackWidthName(selectedGpxFile.getGpxFile(), defaultTrackWidthPref.get());
float trackWidth = getTrackWidth(width, defaultTrackWidth); float trackWidth = getTrackWidth(width, defaultTrackWidth);
int trackColor = getTrackColor(selectedGpxFile.getGpxFile(), cachedColor); int trackColor = getTrackColor(selectedGpxFile.getGpxFile(), cachedColor);
int arrowColor = UiUtilities.getContrastColor(view.getApplication(), trackColor, false); int arrowColor = UiUtilities.getContrastColor(view.getApplication(), trackColor, false);
@ -637,7 +644,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
List<SelectedGpxFile> selectedGPXFiles, DrawSettings settings) { List<SelectedGpxFile> selectedGPXFiles, DrawSettings settings) {
SelectedGpxFile currentTrack = null; SelectedGpxFile currentTrack = null;
for (SelectedGpxFile selectedGpxFile : selectedGPXFiles) { for (SelectedGpxFile selectedGpxFile : selectedGPXFiles) {
String width = getTrackWidthName(selectedGpxFile.getGpxFile(), ""); String width = getTrackWidthName(selectedGpxFile.getGpxFile(), defaultTrackWidthPref.get());
if (!cachedTrackWidth.containsKey(width)) { if (!cachedTrackWidth.containsKey(width)) {
cachedTrackWidth.put(width, null); cachedTrackWidth.put(width, null);
} }
@ -656,7 +663,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
RotatedTileBox tileBox, DrawSettings settings) { RotatedTileBox tileBox, DrawSettings settings) {
List<TrkSegment> segments = selectedGpxFile.getPointsToDisplay(); List<TrkSegment> segments = selectedGpxFile.getPointsToDisplay();
for (TrkSegment ts : segments) { for (TrkSegment ts : segments) {
String width = getTrackWidthName(selectedGpxFile.getGpxFile(), ""); String width = getTrackWidthName(selectedGpxFile.getGpxFile(), defaultTrackWidthPref.get());
int color = getTrackColor(selectedGpxFile.getGpxFile(), ts.getColor(cachedColor)); int color = getTrackColor(selectedGpxFile.getGpxFile(), ts.getColor(cachedColor));
if (ts.renderer == null && !ts.points.isEmpty()) { if (ts.renderer == null && !ts.points.isEmpty()) {
Renderable.RenderableSegment renderer; Renderable.RenderableSegment renderer;
@ -681,25 +688,31 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
} }
private int getTrackColor(GPXFile gpxFile, int defaultColor) { private int getTrackColor(GPXFile gpxFile, int defaultColor) {
int color; int color = 0;
if (hasTrackDrawInfoForTrack(gpxFile)) { if (hasTrackDrawInfoForTrack(gpxFile)) {
color = trackDrawInfo.getColor(); color = trackDrawInfo.getColor();
} else if (gpxFile.showCurrentTrack) { } else if (gpxFile.showCurrentTrack) {
color = currentTrackColorPref.get(); color = currentTrackColorPref.get();
} else { } else {
color = gpxFile.getColor(defaultColor); GpxDataItem dataItem = gpxDbHelper.getItem(new File(gpxFile.path));
if (dataItem != null) {
color = dataItem.getColor();
}
} }
return color != 0 ? color : defaultColor; return color != 0 ? color : defaultColor;
} }
private String getTrackWidthName(GPXFile gpxFile, String defaultWidth) { private String getTrackWidthName(GPXFile gpxFile, String defaultWidth) {
String width; String width = null;
if (hasTrackDrawInfoForTrack(gpxFile)) { if (hasTrackDrawInfoForTrack(gpxFile)) {
width = trackDrawInfo.getWidth(); width = trackDrawInfo.getWidth();
} else if (gpxFile.showCurrentTrack) { } else if (gpxFile.showCurrentTrack) {
width = currentTrackWidthPref.get(); width = currentTrackWidthPref.get();
} else { } else {
width = gpxFile.getWidth(defaultWidth); GpxDataItem dataItem = gpxDbHelper.getItem(new File(gpxFile.path));
if (dataItem != null) {
width = dataItem.getWidth();
}
} }
return width != null ? width : defaultWidth; return width != null ? width : defaultWidth;
} }
@ -710,7 +723,11 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
} else if (gpxFile.showCurrentTrack) { } else if (gpxFile.showCurrentTrack) {
return currentTrackShowArrowsPref.get(); return currentTrackShowArrowsPref.get();
} else { } 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); callback.onApplyMovedObject(true, objectInMotion);
} }
} else { } else {
new SaveGpxAsyncTask(gpxFile, new SaveGpxAsyncTask.SaveGpxListener() { new SaveGpxAsyncTask(new File(gpxFile.path), gpxFile, new SaveGpxAsyncTask.SaveGpxListener() {
@Override @Override
public void gpxSavingStarted() { public void gpxSavingStarted() {