Merge pull request #9469 from osmandapp/track_appearance

Track appearance
This commit is contained in:
max-klaus 2020-07-21 13:55:24 +03:00 committed by GitHub
commit 620433fe85
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
73 changed files with 3114 additions and 581 deletions

View file

@ -1536,52 +1536,42 @@ public class GPXUtilities {
return new QuadRect(left, top, right, bottom);
}
public int getGradientScaleColor(GradientScaleType gradientScaleType, int defColor) {
public int getGradientScaleColor(String gradientScaleType, int defColor) {
String clrValue = null;
if (extensions != null) {
clrValue = extensions.get(gradientScaleType.getTypeName());
clrValue = extensions.get(gradientScaleType);
}
return parseColor(clrValue, defColor);
}
public void setGradientScaleColor(GradientScaleType gradientScaleType, int gradientScaleColor) {
getExtensionsToWrite().put(gradientScaleType.getTypeName(), Algorithms.colorToString(gradientScaleColor));
public void setGradientScaleColor(String gradientScaleType, int gradientScaleColor) {
getExtensionsToWrite().put(gradientScaleType, Algorithms.colorToString(gradientScaleColor));
}
public GradientScaleType getGradientScaleType() {
public String getGradientScaleType() {
if (extensions != null) {
String gradientScaleTypeName = extensions.get("gradient_scale_type");
if (!Algorithms.isEmpty(gradientScaleTypeName)) {
try {
return GradientScaleType.valueOf(gradientScaleTypeName);
} catch (IllegalArgumentException e) {
log.error("Error reading gradientScaleType", e);
}
}
return extensions.get("gradient_scale_type");
}
return null;
}
public void setGradientScaleType(GradientScaleType gradientScaleType) {
getExtensionsToWrite().put("gradient_scale_type", gradientScaleType.name());
public void setGradientScaleType(String gradientScaleType) {
getExtensionsToWrite().put("gradient_scale_type", gradientScaleType);
}
public GpxSplitType getSplitType() {
public void removeGradientScaleType() {
getExtensionsToWrite().remove("gradient_scale_type");
}
public String getSplitType() {
if (extensions != null) {
String gradientScaleTypeName = extensions.get("split_type");
if (!Algorithms.isEmpty(gradientScaleTypeName)) {
try {
return GpxSplitType.valueOf(gradientScaleTypeName);
} catch (IllegalArgumentException e) {
log.error("Error reading GpxSplitType", e);
}
}
return extensions.get("split_type");
}
return null;
}
public void setSplitType(GpxSplitType gpxSplitType) {
getExtensionsToWrite().put("split_type", gpxSplitType.name());
public void setSplitType(String gpxSplitType) {
getExtensionsToWrite().put("split_type", gpxSplitType);
}
public double getSplitInterval() {
@ -1636,38 +1626,6 @@ public class GPXUtilities {
public void setShowStartFinish(boolean showStartFinish) {
getExtensionsToWrite().put("show_start_finish", String.valueOf(showStartFinish));
}
public enum GradientScaleType {
SPEED("gradient_speed_color"),
ALTITUDE("gradient_altitude_color"),
SLOPE("gradient_slope_color");
private String typeName;
GradientScaleType(String typeName) {
this.typeName = typeName;
}
public String getTypeName() {
return typeName;
}
}
public enum GpxSplitType {
NO_SPLIT(-1),
DISTANCE(1),
TIME(2);
private int type;
GpxSplitType(int type) {
this.type = type;
}
public int getType() {
return type;
}
}
}
public static String asString(GPXFile file) {

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="rectangle"
xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/icon_color_secondary_dark" />
<corners android:radius="30dp" />
</shape>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="rectangle"
xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/icon_color_secondary_light" />
<corners android:radius="30dp" />
</shape>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/radio_button_selected_center" android:state_checked="true" />
<item android:drawable="@drawable/radio_button_regular_center" />
</selector>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/radio_button_selected_center_dark" android:state_checked="true" />
<item android:drawable="@drawable/radio_button_regular_center_dark" />
</selector>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/radio_button_selected_center_light" android:state_checked="true" />
<item android:drawable="@drawable/radio_button_regular_center_light" />
</selector>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/radio_button_selected_left" android:state_checked="true" />
<item android:drawable="@drawable/radio_button_regular_left" />
</selector>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/radio_button_selected_left_dark" android:state_checked="true" />
<item android:drawable="@drawable/radio_button_regular_left_dark" />
</selector>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/radio_button_selected_left_light" android:state_checked="true" />
<item android:drawable="@drawable/radio_button_regular_left_light" />
</selector>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<stroke
android:width="1dp"
android:color="@color/stroked_buttons_and_links_outline_light" />
</shape>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<stroke
android:width="1dp"
android:color="@color/stroked_buttons_and_links_outline_dark" />
</shape>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<stroke
android:width="1dp"
android:color="@color/stroked_buttons_and_links_outline_light" />
</shape>

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:bottomLeftRadius="4dp"
android:topLeftRadius="4dp" />
<stroke
android:width="1dp"
android:color="@color/stroked_buttons_and_links_outline_light" />
</shape>

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:bottomLeftRadius="4dp"
android:topLeftRadius="4dp" />
<stroke
android:width="1dp"
android:color="@color/stroked_buttons_and_links_outline_dark" />
</shape>

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:bottomLeftRadius="4dp"
android:topLeftRadius="4dp" />
<stroke
android:width="1dp"
android:color="@color/stroked_buttons_and_links_outline_light" />
</shape>

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:bottomRightRadius="4dp"
android:topRightRadius="4dp" />
<stroke
android:width="1dp"
android:color="@color/stroked_buttons_and_links_outline_light" />
</shape>

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:bottomRightRadius="4dp"
android:topRightRadius="4dp" />
<stroke
android:width="1dp"
android:color="@color/stroked_buttons_and_links_outline_dark" />
</shape>

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:bottomRightRadius="4dp"
android:topRightRadius="4dp" />
<stroke
android:width="1dp"
android:color="@color/stroked_buttons_and_links_outline_light" />
</shape>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/radio_button_selected_right" android:state_checked="true" />
<item android:drawable="@drawable/radio_button_regular_right" />
</selector>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/radio_button_selected_right_dark" android:state_checked="true" />
<item android:drawable="@drawable/radio_button_regular_right_dark" />
</selector>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/radio_button_selected_right_light" android:state_checked="true" />
<item android:drawable="@drawable/radio_button_regular_right_light" />
</selector>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#1A237BFF" />
<stroke
android:width="1dp"
android:color="#80237BFF" />
</shape>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/switch_button_active_dark" />
<stroke
android:width="1dp"
android:color="@color/switch_button_active_stroke_dark" />
</shape>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/switch_button_active_light" />
<stroke
android:width="1dp"
android:color="@color/switch_button_active_stroke_light" />
</shape>

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:bottomLeftRadius="4dp"
android:topLeftRadius="4dp" />
<solid android:color="#1A237BFF" />
<stroke
android:width="1dp"
android:color="#80237BFF" />
</shape>

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:bottomLeftRadius="4dp"
android:topLeftRadius="4dp" />
<solid android:color="@color/switch_button_active_dark" />
<stroke
android:width="1dp"
android:color="@color/switch_button_active_stroke_dark" />
</shape>

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:bottomLeftRadius="4dp"
android:topLeftRadius="4dp" />
<solid android:color="@color/switch_button_active_light" />
<stroke
android:width="1dp"
android:color="@color/switch_button_active_stroke_light" />
</shape>

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:bottomRightRadius="4dp"
android:topRightRadius="4dp" />
<solid android:color="#1A237BFF" />
<stroke
android:width="1dp"
android:color="#80237BFF" />
</shape>

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:bottomRightRadius="4dp"
android:topRightRadius="4dp" />
<solid android:color="@color/switch_button_active_dark" />
<stroke
android:width="1dp"
android:color="@color/switch_button_active_stroke_dark" />
</shape>

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:bottomRightRadius="4dp"
android:topRightRadius="4dp" />
<solid android:color="@color/switch_button_active_light" />
<stroke
android:width="1dp"
android:color="@color/switch_button_active_stroke_light" />
</shape>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/active_color_primary_light" android:state_checked="false" />
<item android:color="@color/text_color_primary_light" android:state_checked="true" />
</selector>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/active_color_primary_dark" android:state_checked="false" />
<item android:color="@color/text_color_primary_dark" android:state_checked="true" />
</selector>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/active_color_primary_light" android:state_checked="false" />
<item android:color="@color/text_color_primary_light" android:state_checked="true" />
</selector>

View file

@ -158,42 +158,38 @@
</LinearLayout>
<LinearLayout
android:id="@+id/color_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:minHeight="48dp"
android:paddingRight="@dimen/content_padding"
android:paddingTop="@dimen/content_padding_half"
android:paddingBottom="@dimen/content_padding_half"
android:background="?attr/selectableItemBackground"
android:orientation="horizontal"
android:gravity="center_vertical"
android:paddingEnd="@dimen/content_padding">
<TextView
android:id="@+id/colorText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="end"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size"
android:text="@string/shared_string_color"/>
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/colorImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="@dimen/content_padding"
osmand:srcCompat="@drawable/ic_action_circle"
android:paddingStart="@dimen/content_padding" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/appearance_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:gravity="center_vertical"
android:minHeight="48dp"
android:orientation="horizontal"
android:paddingLeft="@dimen/content_padding"
android:paddingTop="@dimen/content_padding_half"
android:paddingRight="@dimen/content_padding"
android:paddingBottom="@dimen/content_padding_half">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/shared_string_appearance"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/appearanceImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:tint="?attr/default_icon_color"
osmand:srcCompat="@drawable/ic_action_appearance" />
</LinearLayout>
</LinearLayout>
<LinearLayout

View file

@ -37,15 +37,17 @@
tools:text="255" />
</LinearLayout>
<TextView
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/groupName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="@dimen/content_padding_half"
android:paddingStart="@dimen/content_padding_half"
android:paddingRight="@dimen/content_padding_half"
android:paddingLeft="@dimen/content_padding_half"
android:paddingTop="@dimen/list_content_padding_large"
android:paddingEnd="@dimen/content_padding_half"
android:paddingTop="@dimen/list_content_padding_large"
android:paddingRight="@dimen/content_padding_half"
android:textColor="?attr/active_color_basic"
app:typeface="@string/font_roboto_medium"
tools:text="@string/favorite" />
</FrameLayout>

View file

@ -0,0 +1,115 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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="match_parent"
android:background="@color/color_transparent">
<net.osmand.plus.mapcontextmenu.InterceptorLinearLayout
android:id="@+id/main_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/context_menu_top_shadow" />
<LinearLayout
android:id="@+id/route_menu_top_shadow_all"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/card_and_list_background_basic"
android:minHeight="@dimen/bottom_sheet_title_height"
android:orientation="vertical"
android:paddingLeft="@dimen/content_padding"
android:paddingRight="@dimen/content_padding">
<View
android:layout_width="@dimen/content_padding"
android:layout_height="2dp"
android:layout_gravity="center"
android:layout_marginTop="@dimen/context_menu_padding_margin_tiny"
android:layout_marginBottom="@dimen/list_item_button_padding"
android:background="?attr/bg_dash_line" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/no_search_results_description"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:gravity="center_vertical"
android:letterSpacing="@dimen/text_button_letter_spacing"
android:text="@string/shared_string_appearance"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size"
osmand:typeface="@string/font_roboto_medium" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/appearance_icon"
android:layout_width="@dimen/standard_icon_size"
android:layout_height="@dimen/standard_icon_size"
android:layout_gravity="center_vertical"
osmand:srcCompat="@drawable/ic_action_gpx_width_bold"
tools:tint="@color/description_font_and_bottom_sheet_icons" />
</LinearLayout>
</LinearLayout>
<FrameLayout
android:id="@+id/bottom_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:foreground="@drawable/bg_contextmenu_shadow"
android:foregroundGravity="top|fill_horizontal">
<net.osmand.plus.LockableScrollView
android:id="@+id/route_menu_bottom_scroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/route_info_bg">
<LinearLayout
android:id="@+id/route_menu_cards_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/route_info_bg"
android:orientation="vertical"
android:paddingBottom="@dimen/dialog_button_ex_height">
</LinearLayout>
</net.osmand.plus.LockableScrollView>
</FrameLayout>
</net.osmand.plus.mapcontextmenu.InterceptorLinearLayout>
<LinearLayout
android:id="@+id/control_buttons"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/buttons_shadow"
android:layout_width="match_parent"
android:layout_height="10dp"
android:layout_gravity="bottom"
android:background="@drawable/bg_contextmenu_shadow_top_light" />
<include
layout="@layout/bottom_buttons"
android:layout_width="match_parent"
android:layout_height="@dimen/dialog_button_ex_height"
android:layout_gravity="bottom" />
</LinearLayout>
</FrameLayout>

View file

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<View
android:id="@+id/top_divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?attr/divider_color_basic"
android:focusable="false" />
<include
android:id="@+id/header_view"
layout="@layout/bottom_sheet_item_with_right_descr" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingTop="@dimen/context_menu_padding_margin_tiny"
android:paddingBottom="@dimen/content_padding">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:orientation="horizontal"
android:paddingStart="@dimen/content_padding_half"
android:paddingLeft="@dimen/content_padding_half"
android:paddingEnd="@dimen/content_padding"
android:paddingRight="@dimen/content_padding"
tools:itemCount="3"
tools:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/point_editor_group_select_item"
tools:orientation="horizontal" />
</LinearLayout>
<net.osmand.plus.widgets.FlowLayout
android:id="@+id/select_color"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/content_padding_small"
android:layout_marginLeft="@dimen/content_padding_small"
android:layout_marginTop="@dimen/context_menu_padding_margin_tiny"
android:layout_marginBottom="@dimen/content_padding_half" />
</LinearLayout>

View file

@ -0,0 +1,152 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RadioGroup
android:id="@+id/split_type"
android:layout_width="match_parent"
android:layout_height="@dimen/dialog_button_height"
android:layout_marginStart="@dimen/content_padding"
android:layout_marginTop="@dimen/text_margin_small"
android:layout_marginEnd="@dimen/content_padding"
android:layout_marginBottom="@dimen/content_padding_small"
android:background="?attr/btn_bg_border_inactive"
android:baselineAligned="false"
android:orientation="horizontal">
<RadioButton
android:id="@+id/no_split"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="?attr/btn_radio_button_left"
android:button="@android:color/transparent"
android:checked="true"
android:foreground="?attr/selectableItemBackground"
android:gravity="center"
android:text="@string/shared_string_none"
android:textColor="@drawable/radio_flat_text_selector_light" />
<RadioButton
android:id="@+id/time_split"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="?attr/btn_radio_button_center"
android:button="@android:color/transparent"
android:foreground="?attr/selectableItemBackground"
android:gravity="center"
android:text="@string/shared_string_time"
android:textColor="@drawable/radio_flat_text_selector_light" />
<RadioButton
android:id="@+id/distance_split"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="?attr/btn_radio_button_right"
android:button="@android:color/transparent"
android:foreground="?attr/selectableItemBackground"
android:gravity="center"
android:text="@string/distance"
android:textColor="@drawable/radio_flat_text_selector_light"
android:textSize="@dimen/default_desc_text_size" />
</RadioGroup>
<LinearLayout
android:id="@+id/slider_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingStart="@dimen/content_padding"
android:paddingTop="@dimen/content_padding"
android:paddingEnd="@dimen/content_padding">
<net.osmand.plus.widgets.TextViewEx
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="start"
android:lineSpacingExtra="@dimen/line_spacing_extra_description"
android:text="@string/gpx_split_interval"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/split_value_tv"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="end"
android:lineSpacingExtra="@dimen/line_spacing_extra_description"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size"
tools:text="@string/shared_string_max" />
</LinearLayout>
<com.google.android.material.slider.Slider
android:id="@+id/split_slider"
style="@style/Widget.Styled.Slider"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
android:stepSize="1" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingStart="@dimen/content_padding"
android:paddingEnd="@dimen/content_padding">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/split_value_min"
android:layout_width="@dimen/standard_icon_size"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="start"
android:lineSpacingExtra="@dimen/line_spacing_extra_description"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_list_text_size"
tools:text="3" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/split_value_max"
android:layout_width="@dimen/standard_icon_size"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="end"
android:lineSpacingExtra="@dimen/line_spacing_extra_description"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_list_text_size"
tools:text="19" />
</LinearLayout>
</LinearLayout>
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/split_interval_none_descr"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/content_padding"
android:layout_marginEnd="@dimen/content_padding"
android:layout_marginBottom="@dimen/content_padding"
android:lineSpacingExtra="@dimen/line_spacing_extra_description"
android:text="@string/gpx_split_interval_none_descr"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_desc_text_size" />
</LinearLayout>

View file

@ -0,0 +1,119 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<View
android:id="@+id/top_divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?attr/divider_color_basic"
android:focusable="false" />
<include
android:id="@+id/header_view"
layout="@layout/bottom_sheet_item_with_right_descr" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingTop="@dimen/context_menu_padding_margin_tiny"
android:paddingBottom="@dimen/content_padding">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:orientation="horizontal"
android:paddingStart="@dimen/content_padding_half"
android:paddingLeft="@dimen/content_padding_half"
android:paddingEnd="@dimen/content_padding"
android:paddingRight="@dimen/content_padding"
tools:itemCount="3"
tools:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/point_editor_group_select_item"
tools:orientation="horizontal" />
</LinearLayout>
<LinearLayout
android:id="@+id/slider_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingStart="@dimen/content_padding"
android:paddingTop="@dimen/content_padding"
android:paddingEnd="@dimen/content_padding">
<net.osmand.plus.widgets.TextViewEx
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="start"
android:lineSpacingExtra="@dimen/line_spacing_extra_description"
android:text="@string/shared_string_custom"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/width_value_tv"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="end"
android:lineSpacingExtra="@dimen/line_spacing_extra_description"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingStart="@dimen/content_padding"
android:paddingEnd="@dimen/content_padding">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/width_value_min"
android:layout_width="@dimen/standard_icon_size"
android:layout_height="wrap_content"
android:gravity="start"
android:lineSpacingExtra="@dimen/line_spacing_extra_description"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_list_text_size" />
<com.google.android.material.slider.Slider
android:id="@+id/width_slider"
style="@style/Widget.Styled.Slider"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
android:layout_weight="1"
android:stepSize="1" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/width_value_max"
android:layout_width="@dimen/standard_icon_size"
android:layout_height="wrap_content"
android:gravity="end"
android:lineSpacingExtra="@dimen/line_spacing_extra_description"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_list_text_size" />
</LinearLayout>
</LinearLayout>
</LinearLayout>

View file

@ -3823,4 +3823,6 @@
<string name="set_working_days_to_continue">Необходимо указать рабочие дни для продолжения</string>
<string name="route_between_points">Маршрут между пунктами</string>
<string name="plan_a_route">План маршрута</string>
<string name="gpx_split_interval_none_descr">Выберите нужный вариант разбиения: по времени или по расстоянию.</string>
<string name="gpx_split_interval_descr">Выберите интервал с которым будут отображаться метки с расстоянием или временем на треке.</string>
</resources>

View file

@ -133,6 +133,10 @@
<attr name="profile_save_btn" format="reference"/>
<attr name="profile_cancel_btn" format="reference"/>
<attr name="btn_bg_border_inactive" format="reference"/>
<attr name="btn_radio_button_left" format="reference"/>
<attr name="btn_radio_button_right" format="reference"/>
<attr name="btn_radio_button_center" format="reference"/>
<attr name="bg_dash_line" format="reference"/>
</declare-styleable>
<declare-styleable name="PagerSlidingTabStrip">

View file

@ -471,7 +471,8 @@
<color name="switch_button_active_light">#1A237BFF</color>
<color name="switch_button_active_dark">#1AD28521</color>
<color name="switch_button_active_stroke">#80237BFF</color>
<color name="switch_button_active_stroke_light">#80237BFF</color>
<color name="switch_button_active_stroke_dark">#80D28521</color>
<color name="empty_hint_bg">#80000000</color>
<color name="input_layout_bg_color">#4DCCCCCC</color>

View file

@ -96,7 +96,8 @@
<dimen name="gpx_small_icon_margin">3dp</dimen>
<dimen name="gpx_small_text_margin">14dp</dimen>
<dimen name="gpx_text_top_margin">6dp</dimen>
<dimen name="gpx_group_button_height">60dp</dimen>
<dimen name="gpx_group_button_width">96dp</dimen>
<dimen name="dashboard_parking_left_margin">16dp</dimen>
<dimen name="dashboard_parking_icon_size">48dp</dimen>

View file

@ -11,6 +11,13 @@
Thx - Hardy
-->
<string name="track_coloring_solid">Solid</string>
<string name="gpx_direction_arrows">Direction arrows</string>
<string name="shared_string_custom">Custom</string>
<string name="gpx_split_interval_none_descr">Select the desired splitting option: by time or by distance.</string>
<string name="gpx_split_interval_descr">Select the interval at which marks with distance or time on the track will be displayed.</string>
<string name="select_track_width">Select width</string>
<string name="track_show_start_finish_icons">Show start finish icons</string>
<string name="add_to_a_track">Add to a Track</string>
<string name="plan_a_route">Plan a route</string>
<string name="route_between_points">Route between points</string>

View file

@ -296,6 +296,10 @@
<item name="actionBarSize">@dimen/action_bar_height</item>
<item name="android:toolbarStyle">@style/ToolbarStyle</item>
<item name="toolbarStyle">@style/ToolbarStyle</item>
<item name="bg_dash_line">@drawable/bg_dash_line_light</item>
<item name="btn_radio_button_left">@drawable/radio_button_left_light</item>
<item name="btn_radio_button_right">@drawable/radio_button_right_light</item>
<item name="btn_radio_button_center">@drawable/radio_button_center_light</item>
</style>
<style name="ToolbarStyle" parent="@style/Widget.AppCompat.Toolbar">
@ -576,6 +580,10 @@
<item name="actionBarSize">@dimen/action_bar_height</item>
<item name="android:toolbarStyle">@style/ToolbarStyle</item>
<item name="toolbarStyle">@style/ToolbarStyle</item>
<item name="bg_dash_line">@drawable/bg_dash_line_dark</item>
<item name="btn_radio_button_left">@drawable/radio_button_left_dark</item>
<item name="btn_radio_button_right">@drawable/radio_button_right_dark</item>
<item name="btn_radio_button_center">@drawable/radio_button_center_dark</item>
</style>
<style name="FreeVersionBanner" parent="OsmandDarkTheme">

View file

@ -4,11 +4,12 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.GPXUtilities.GPXFile.GradientScaleType;
import net.osmand.GPXUtilities.GPXTrackAnalysis;
import net.osmand.IndexConstants;
import net.osmand.plus.api.SQLiteAPI.SQLiteConnection;
import net.osmand.plus.api.SQLiteAPI.SQLiteCursor;
import net.osmand.plus.track.GpxSplitType;
import net.osmand.plus.track.GradientScaleType;
import net.osmand.util.Algorithms;
import java.io.File;
@ -201,17 +202,27 @@ public class GPXDatabase {
public GpxDataItem(File file, @NonNull GPXFile gpxFile) {
this.file = file;
readGpxParams(gpxFile);
}
private void readGpxParams(GPXFile gpxFile) {
color = gpxFile.getColor(0);
width = gpxFile.getWidth(null);
showArrows = gpxFile.isShowArrows();
showStartFinish = gpxFile.isShowStartFinish();
gradientScaleType = gpxFile.getGradientScaleType();
gradientSpeedColor = gpxFile.getGradientScaleColor(GradientScaleType.SPEED, 0);
gradientSlopeColor = gpxFile.getGradientScaleColor(GradientScaleType.SLOPE, 0);
gradientAltitudeColor = gpxFile.getGradientScaleColor(GradientScaleType.ALTITUDE, 0);
if (gpxFile.getSplitType() != null && gpxFile.getSplitInterval() != 0) {
splitType = gpxFile.getSplitType().getType();
splitInterval = gpxFile.getSplitInterval();
gradientSpeedColor = gpxFile.getGradientScaleColor(GradientScaleType.SPEED.getColorTypeName(), 0);
gradientSlopeColor = gpxFile.getGradientScaleColor(GradientScaleType.SLOPE.getColorTypeName(), 0);
gradientAltitudeColor = gpxFile.getGradientScaleColor(GradientScaleType.ALTITUDE.getColorTypeName(), 0);
if (!Algorithms.isEmpty(gpxFile.getSplitType()) && gpxFile.getSplitInterval() > 0) {
GpxSplitType gpxSplitType = GpxSplitType.getSplitTypeByName(gpxFile.getSplitType());
if (gpxSplitType != null) {
splitType = gpxSplitType.getType();
splitInterval = gpxFile.getSplitInterval();
}
}
if (!Algorithms.isEmpty(gpxFile.getGradientScaleType())) {
gradientScaleType = GradientScaleType.getGradientTypeByName(gpxFile.getGradientScaleType());
}
}
@ -521,7 +532,7 @@ public class GPXDatabase {
return false;
}
public boolean updateGradientScaleType(@NonNull GpxDataItem item, GradientScaleType gradientScaleType) {
public boolean updateGradientScaleType(@NonNull GpxDataItem item, @Nullable GradientScaleType gradientScaleType) {
SQLiteConnection db = openConnection(false);
if (db != null) {
try {
@ -529,7 +540,7 @@ public class GPXDatabase {
String fileDir = getFileDir(item.file);
db.execSQL("UPDATE " + GPX_TABLE_NAME + " SET " + GPX_COL_GRADIENT_SCALE_TYPE + " = ? " +
" WHERE " + GPX_COL_NAME + " = ? AND " + GPX_COL_DIR + " = ?",
new Object[] {(gradientScaleType == null ? "" : gradientScaleType.name()), fileName, fileDir});
new Object[] {(gradientScaleType == null ? "" : gradientScaleType.getTypeName()), fileName, fileDir});
item.gradientScaleType = gradientScaleType;
} finally {
db.close();
@ -705,7 +716,7 @@ public class GPXDatabase {
} else {
color = Algorithms.colorToString(item.color);
}
String gradientScaleType = item.gradientScaleType != null ? item.gradientScaleType.name() : null;
String gradientScaleType = item.gradientScaleType != null ? item.gradientScaleType.getTypeName() : null;
if (a != null) {
db.execSQL(
"INSERT INTO " + GPX_TABLE_NAME + " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",

View file

@ -8,11 +8,11 @@ import androidx.annotation.Nullable;
import net.osmand.GPXUtilities;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.GPXUtilities.GPXFile.GpxSplitType;
import net.osmand.GPXUtilities.GPXFile.GradientScaleType;
import net.osmand.plus.track.GpxSplitType;
import net.osmand.GPXUtilities.GPXTrackAnalysis;
import net.osmand.plus.GPXDatabase.GpxDataItem;
import net.osmand.plus.api.SQLiteAPI.SQLiteConnection;
import net.osmand.plus.track.GradientScaleType;
import java.io.File;
import java.util.List;

View file

@ -11,8 +11,6 @@ import androidx.core.content.ContextCompat;
import net.osmand.GPXUtilities;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.GPXUtilities.GPXFile.GpxSplitType;
import net.osmand.GPXUtilities.GPXFile.GradientScaleType;
import net.osmand.GPXUtilities.GPXTrackAnalysis;
import net.osmand.GPXUtilities.Route;
import net.osmand.GPXUtilities.Track;
@ -29,6 +27,8 @@ import net.osmand.plus.helpers.GpxUiHelper;
import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetAxisType;
import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetType;
import net.osmand.plus.settings.backend.OsmandSettings.MetricsConstants;
import net.osmand.plus.track.GpxSplitType;
import net.osmand.plus.track.GradientScaleType;
import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log;
@ -173,19 +173,21 @@ public class GpxSelectionHelper {
if (selectedGpxFile != null && selectedGpxFile.getGpxFile() != null) {
GPXFile gpxFile = selectedGpxFile.getGpxFile();
List<GpxDisplayGroup> groups = app.getSelectedGpxHelper().collectDisplayGroups(gpxFile);
if (dataItem.getSplitType() == GpxSplitType.NO_SPLIT.getType()) {
for (GpxDisplayGroup model : groups) {
model.noSplit(app);
}
selectedGpxFile.setDisplayGroups(groups, app);
} else if (dataItem.getSplitType() == GpxSplitType.DISTANCE.getType()) {
for (GpxDisplayGroup model : groups) {
model.splitByDistance(app, dataItem.getSplitInterval(), dataItem.isJoinSegments());
}
selectedGpxFile.setDisplayGroups(groups, app);
} else if (dataItem.getSplitType() == GpxSplitType.TIME.getType()) {
for (GpxDisplayGroup model : groups) {
model.splitByTime(app, (int) dataItem.getSplitInterval(), dataItem.isJoinSegments());
GpxSplitType splitType = GpxSplitType.getSplitTypeByTypeId(dataItem.getSplitType());
if (splitType != null) {
if (splitType == GpxSplitType.NO_SPLIT) {
for (GpxDisplayGroup model : groups) {
model.noSplit(app);
}
} else if (splitType == GpxSplitType.DISTANCE) {
for (GpxDisplayGroup model : groups) {
model.splitByDistance(app, dataItem.getSplitInterval(), dataItem.isJoinSegments());
}
} else if (splitType == GpxSplitType.TIME) {
for (GpxDisplayGroup model : groups) {
model.splitByTime(app, (int) dataItem.getSplitInterval(), dataItem.isJoinSegments());
}
}
selectedGpxFile.setDisplayGroups(groups, app);
}
@ -522,24 +524,19 @@ public class GpxSelectionHelper {
gpx.setColor(clr);
}
for (GradientScaleType scaleType : GradientScaleType.values()) {
if (obj.has(scaleType.getTypeName())) {
int clr = Algorithms.parseColor(obj.getString(scaleType.getTypeName()));
gpx.setGradientScaleColor(scaleType, clr);
if (obj.has(scaleType.getColorTypeName())) {
int clr = Algorithms.parseColor(obj.getString(scaleType.getColorTypeName()));
gpx.setGradientScaleColor(scaleType.getColorTypeName(), clr);
}
}
if (obj.has(SHOW_ARROWS)) {
boolean showArrows = obj.optBoolean(SHOW_ARROWS, false);
gpx.setShowArrows(showArrows);
gpx.setShowArrows(obj.optBoolean(SHOW_ARROWS, false));
}
if (obj.has(GRADIENT_SCALE_TYPE)) {
String gradientScaleTypeName = obj.optString(GRADIENT_SCALE_TYPE);
if (!Algorithms.isEmpty(gradientScaleTypeName)) {
gpx.setGradientScaleType(GradientScaleType.valueOf(gradientScaleTypeName));
}
gpx.setGradientScaleType(obj.optString(GRADIENT_SCALE_TYPE));
}
if (obj.has(SHOW_START_FINISH)) {
boolean showStartFinish = obj.optBoolean(SHOW_START_FINISH, false);
gpx.setShowStartFinish(showStartFinish);
gpx.setShowStartFinish(obj.optBoolean(SHOW_START_FINISH, false));
}
if (obj.has(WIDTH)) {
gpx.setWidth(obj.getString(WIDTH));
@ -592,9 +589,9 @@ public class GpxSelectionHelper {
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, 0);
int gradientScaleColor = s.gpxFile.getGradientScaleColor(scaleType.getColorTypeName(), 0);
if (gradientScaleColor != 0) {
obj.put(scaleType.getTypeName(), Algorithms.colorToString(gradientScaleColor));
obj.put(scaleType.getColorTypeName(), Algorithms.colorToString(gradientScaleColor));
}
}
}
@ -650,16 +647,16 @@ public class GpxSelectionHelper {
gpx.setColor(dataItem.getColor());
}
if (dataItem.getGradientSpeedColor() != 0) {
gpx.setGradientScaleColor(GradientScaleType.SPEED, dataItem.getGradientSpeedColor());
gpx.setGradientScaleColor(GradientScaleType.SPEED.getColorTypeName(), dataItem.getGradientSpeedColor());
}
if (dataItem.getGradientAltitudeColor() != 0) {
gpx.setGradientScaleColor(GradientScaleType.ALTITUDE, dataItem.getGradientAltitudeColor());
gpx.setGradientScaleColor(GradientScaleType.ALTITUDE.getColorTypeName(), dataItem.getGradientAltitudeColor());
}
if (dataItem.getGradientSlopeColor() != 0) {
gpx.setGradientScaleColor(GradientScaleType.SLOPE, dataItem.getGradientSlopeColor());
gpx.setGradientScaleColor(GradientScaleType.SLOPE.getColorTypeName(), dataItem.getGradientSlopeColor());
}
if (dataItem.getGradientScaleType() != null) {
gpx.setGradientScaleType(dataItem.getGradientScaleType());
gpx.setGradientScaleType(dataItem.getGradientScaleType().getTypeName());
}
if (dataItem.getWidth() != null) {
gpx.setWidth(dataItem.getWidth());

View file

@ -45,6 +45,7 @@ import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceFragmentCompat.OnPreferenceStartFragmentCallback;
import net.osmand.AndroidUtils;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.Location;
import net.osmand.PlatformUtil;
import net.osmand.SecondSplashScreenFragment;
@ -79,6 +80,7 @@ import net.osmand.plus.TargetPointsHelper.TargetPoint;
import net.osmand.plus.Version;
import net.osmand.plus.activities.search.SearchActivity;
import net.osmand.plus.base.BaseOsmAndFragment;
import net.osmand.plus.base.ContextMenuFragment;
import net.osmand.plus.base.FailSafeFuntions;
import net.osmand.plus.base.MapViewTrackingUtilities;
import net.osmand.plus.chooseplan.OsmLiveCancelledDialog;
@ -105,6 +107,7 @@ import net.osmand.plus.helpers.ScrollHelper;
import net.osmand.plus.helpers.ScrollHelper.OnScrollEventListener;
import net.osmand.plus.mapcontextmenu.AdditionalActionsBottomSheetDialogFragment;
import net.osmand.plus.mapcontextmenu.MapContextMenu;
import net.osmand.plus.mapcontextmenu.MenuController;
import net.osmand.plus.mapcontextmenu.MenuController.MenuState;
import net.osmand.plus.mapcontextmenu.builders.cards.dialogs.ContextMenuCardDialogFragment;
import net.osmand.plus.mapcontextmenu.editors.FavoritePointEditor;
@ -141,6 +144,7 @@ import net.osmand.plus.settings.fragments.DataStorageFragment;
import net.osmand.plus.settings.fragments.ImportCompleteFragment;
import net.osmand.plus.settings.fragments.ImportSettingsFragment;
import net.osmand.plus.settings.fragments.ProfileAppearanceFragment;
import net.osmand.plus.track.TrackAppearanceFragment;
import net.osmand.plus.views.AddGpxPointBottomSheetHelper.NewGpxPoint;
import net.osmand.plus.views.AnimateDraggingMapThread;
import net.osmand.plus.views.MapControlsLayer;
@ -171,6 +175,7 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import static net.osmand.aidlapi.OsmAndCustomizationConstants.DRAWER_SETTINGS_ID;
import static net.osmand.plus.track.TrackDrawInfo.TRACK_FILE_PATH;
public class MapActivity extends OsmandActionBarActivity implements DownloadEvents,
OnRequestPermissionsResultCallback, IRouteInformationListener, AMapPointUpdateListener,
@ -705,6 +710,14 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven
return;
}
TrackAppearanceFragment trackAppearanceFragment = getTrackAppearanceFragment();
if (trackAppearanceFragment != null) {
trackAppearanceFragment.dismissImmediate();
if (prevActivityIntent == null) {
return;
}
}
if (mapContextMenu.isVisible() && mapContextMenu.isClosable()) {
if (mapContextMenu.getCurrentMenuState() != MenuState.HEADER_ONLY && !isLandscapeLayout()) {
mapContextMenu.openMenuHeaderOnly();
@ -1230,6 +1243,14 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven
mapContextMenu.showMinimized(latLonToShow, mapLabelToShow, toShow);
mapRouteInfoMenu.updateMenu();
MapRouteInfoMenu.showLocationOnMap(this, latLonToShow.getLatitude(), latLonToShow.getLongitude());
} else if (toShow instanceof GPXFile) {
Bundle args = new Bundle();
args.putString(TRACK_FILE_PATH, ((GPXFile) toShow).path);
args.putInt(ContextMenuFragment.MENU_STATE_KEY, MenuController.MenuState.HALF_SCREEN);
TrackAppearanceFragment fragment = new TrackAppearanceFragment();
fragment.setArguments(args);
TrackAppearanceFragment.showInstance(this, fragment);
} else if (toShow instanceof QuadRect) {
QuadRect qr = (QuadRect) toShow;
mapView.fitRectToMap(qr.left, qr.right, qr.top, qr.bottom, (int) qr.width(), (int) qr.height(), 0);
@ -2257,6 +2278,10 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven
return getFragment(ConfigureMenuItemsFragment.TAG);
}
public TrackAppearanceFragment getTrackAppearanceFragment(){
return getFragment(TrackAppearanceFragment.TAG);
}
public PointEditorFragmentNew getPointEditorFragmentNew() {
PointEditorFragmentNew pointEditorFragmentNew;
pointEditorFragmentNew = getFragment(FavoritePointEditor.TAG);

View file

@ -148,6 +148,10 @@ public abstract class ContextMenuFragment extends BaseOsmAndFragment {
return getLandscapeWidth() - getResources().getDimensionPixelSize(R.dimen.dashboard_land_shadow_width);
}
public float getMiddleStateKoef() {
return MIDDLE_STATE_KOEF;
}
public abstract int getToolbarHeight();
public boolean isSingleFragment() {
@ -605,7 +609,7 @@ public abstract class ContextMenuFragment extends BaseOsmAndFragment {
}
private int getMinHalfY(MapActivity mapActivity) {
return viewHeight - (int) Math.min(viewHeight * MIDDLE_STATE_KOEF,
return viewHeight - (int) Math.min(viewHeight * getMiddleStateKoef(),
MIDDLE_STATE_MIN_HEIGHT_DP * mapActivity.getMapView().getDensity() );
}

View file

@ -18,10 +18,14 @@ import net.osmand.render.RenderingRuleProperty;
import net.osmand.render.RenderingRulesStorage;
import net.osmand.util.Algorithms;
import java.util.ArrayList;
import java.util.List;
public class GpxAppearanceAdapter extends ArrayAdapter<GpxAppearanceAdapter.AppearanceListItem> {
public static final String TRACK_WIDTH_BOLD = "bold";
public static final String TRACK_WIDTH_MEDIUM = "medium";
private OsmandApplication app;
private GpxAppearanceAdapterType adapterType;
private int currentColor;
@ -61,14 +65,7 @@ public class GpxAppearanceAdapter extends ArrayAdapter<GpxAppearanceAdapter.Appe
TextView textView = (TextView) v.findViewById(R.id.text1);
textView.setText(item.localizedValue);
if (ConfigureMapMenu.CURRENT_TRACK_WIDTH_ATTR.equals(item.attrName)) {
int iconId;
if ("bold".equals(item.value)) {
iconId = R.drawable.ic_action_gpx_width_bold;
} else if ("medium".equals(item.value)) {
iconId = R.drawable.ic_action_gpx_width_medium;
} else {
iconId = R.drawable.ic_action_gpx_width_thin;
}
int iconId = getWidthIconId(item.value);
textView.setCompoundDrawablesWithIntrinsicBounds(null, null,
app.getUIUtilities().getPaintedIcon(iconId, currentColor), null);
} else {
@ -87,7 +84,22 @@ public class GpxAppearanceAdapter extends ArrayAdapter<GpxAppearanceAdapter.Appe
return v;
}
public void init() {
public static int getWidthIconId(String widthAttr) {
if (TRACK_WIDTH_BOLD.equals(widthAttr)) {
return R.drawable.ic_action_gpx_width_bold;
} else if (TRACK_WIDTH_MEDIUM.equals(widthAttr)) {
return R.drawable.ic_action_gpx_width_medium;
} else {
return R.drawable.ic_action_gpx_width_thin;
}
}
private void init() {
addAll(getAppearanceItems(app, adapterType));
}
public static List<AppearanceListItem> getAppearanceItems(OsmandApplication app, GpxAppearanceAdapterType adapterType) {
List<AppearanceListItem> items = new ArrayList<>();
RenderingRuleProperty trackWidthProp = null;
RenderingRuleProperty trackColorProp = null;
RenderingRulesStorage renderer = app.getRendererRegistry().getCurrentSelectedRenderer();
@ -102,30 +114,31 @@ public class GpxAppearanceAdapter extends ArrayAdapter<GpxAppearanceAdapter.Appe
if (trackWidthProp != null) {
AppearanceListItem item = new AppearanceListItem(ConfigureMapMenu.CURRENT_TRACK_WIDTH_ATTR, "",
SettingsActivity.getStringPropertyValue(getContext(), trackWidthProp.getDefaultValueDescription()));
add(item);
SettingsActivity.getStringPropertyValue(app, trackWidthProp.getDefaultValueDescription()));
items.add(item);
for (int j = 0; j < trackWidthProp.getPossibleValues().length; j++) {
item = new AppearanceListItem(ConfigureMapMenu.CURRENT_TRACK_WIDTH_ATTR,
trackWidthProp.getPossibleValues()[j],
SettingsActivity.getStringPropertyValue(getContext(), trackWidthProp.getPossibleValues()[j]));
add(item);
SettingsActivity.getStringPropertyValue(app, trackWidthProp.getPossibleValues()[j]));
items.add(item);
}
item.setLastItem(true);
}
if (trackColorProp != null) {
AppearanceListItem item = new AppearanceListItem(ConfigureMapMenu.CURRENT_TRACK_COLOR_ATTR, "",
SettingsActivity.getStringPropertyValue(getContext(), trackColorProp.getDefaultValueDescription()),
SettingsActivity.getStringPropertyValue(app, trackColorProp.getDefaultValueDescription()),
parseTrackColor(renderer, ""));
add(item);
items.add(item);
for (int j = 0; j < trackColorProp.getPossibleValues().length; j++) {
item = new AppearanceListItem(ConfigureMapMenu.CURRENT_TRACK_COLOR_ATTR,
trackColorProp.getPossibleValues()[j],
SettingsActivity.getStringPropertyValue(getContext(), trackColorProp.getPossibleValues()[j]),
SettingsActivity.getStringPropertyValue(app, trackColorProp.getPossibleValues()[j]),
parseTrackColor(renderer, trackColorProp.getPossibleValues()[j]));
add(item);
items.add(item);
}
item.setLastItem(true);
}
return items;
}
public static int parseTrackColor(RenderingRulesStorage renderer, String colorName) {
@ -195,6 +208,10 @@ public class GpxAppearanceAdapter extends ArrayAdapter<GpxAppearanceAdapter.Appe
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getLocalizedValue() {
return localizedValue;
}

View file

@ -12,7 +12,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;
import net.osmand.GPXUtilities;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.GPXUtilities.WptPt;
import net.osmand.data.LatLon;
@ -27,9 +26,10 @@ import net.osmand.plus.activities.SavingTrackHelper;
import net.osmand.plus.base.PointImageDrawable;
import net.osmand.plus.mapcontextmenu.MapContextMenu;
import net.osmand.plus.mapcontextmenu.editors.WptPtEditor.OnDismissListener;
import net.osmand.plus.track.SaveGpxAsyncTask;
import net.osmand.plus.track.SaveGpxAsyncTask.SaveGpxListener;
import net.osmand.util.Algorithms;
import java.io.File;
import java.util.Map;
public class WptPtEditorFragment extends PointEditorFragment {
@ -251,7 +251,7 @@ public class WptPtEditorFragment extends PointEditorFragment {
}
} else {
addWpt(gpx, description, name, category, color);
new SaveGpxAsyncTask(getMyApplication(), gpx, editor.isGpxSelected()).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
saveGpx(getMyApplication(), gpx, editor.isGpxSelected());
}
syncGpx(gpx);
}
@ -284,7 +284,7 @@ public class WptPtEditorFragment extends PointEditorFragment {
} else {
gpx.updateWptPt(wpt, wpt.getLatitude(), wpt.getLongitude(),
System.currentTimeMillis(), description, name, category, color);
new SaveGpxAsyncTask(getMyApplication(), gpx, editor.isGpxSelected()).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
saveGpx(getMyApplication(), gpx, editor.isGpxSelected());
}
syncGpx(gpx);
}
@ -309,7 +309,7 @@ public class WptPtEditorFragment extends PointEditorFragment {
savingTrackHelper.deletePointData(wpt);
} else {
gpx.deleteWptPt(wpt);
new SaveGpxAsyncTask(getMyApplication(), gpx, editor.isGpxSelected()).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
saveGpx(getMyApplication(), gpx, editor.isGpxSelected());
}
syncGpx(gpx);
}
@ -378,28 +378,19 @@ public class WptPtEditorFragment extends PointEditorFragment {
return color == 0 ? defaultColor : color;
}
private static class SaveGpxAsyncTask extends AsyncTask<Void, Void, Void> {
private final OsmandApplication app;
private final GPXFile gpx;
private final boolean gpxSelected;
private void saveGpx(final OsmandApplication app, final GPXFile gpxFile, final boolean gpxSelected) {
new SaveGpxAsyncTask(gpxFile, new SaveGpxListener() {
@Override
public void gpxSavingStarted() {
SaveGpxAsyncTask(OsmandApplication app, GPXFile gpx, boolean gpxSelected) {
this.app = app;
this.gpx = gpx;
this.gpxSelected = gpxSelected;
}
@Override
protected Void doInBackground(Void... params) {
GPXUtilities.writeGpxFile(new File(gpx.path), gpx);
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
if (!gpxSelected) {
app.getSelectedGpxHelper().setGpxFileToDisplay(gpx);
}
}
@Override
public void gpxSavingFinished(Exception errorMessage) {
if (errorMessage == null && !gpxSelected) {
app.getSelectedGpxHelper().setGpxFileToDisplay(gpxFile);
}
}
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
}

View file

@ -14,7 +14,6 @@ import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.FragmentActivity;
import net.osmand.GPXUtilities;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.GPXUtilities.WptPt;
import net.osmand.data.FavouritePoint.BackgroundType;
@ -31,9 +30,10 @@ import net.osmand.plus.activities.SavingTrackHelper;
import net.osmand.plus.base.PointImageDrawable;
import net.osmand.plus.mapcontextmenu.MapContextMenu;
import net.osmand.plus.mapcontextmenu.editors.WptPtEditor.OnDismissListener;
import net.osmand.plus.track.SaveGpxAsyncTask;
import net.osmand.plus.track.SaveGpxAsyncTask.SaveGpxListener;
import net.osmand.util.Algorithms;
import java.io.File;
import java.util.List;
import java.util.Map;
import java.util.Set;
@ -269,7 +269,7 @@ public class WptPtEditorFragmentNew extends PointEditorFragmentNew {
}
} else {
addWpt(gpx, description, name, category, color, iconName, backgroundTypeName);
new SaveGpxAsyncTask(getMyApplication(), gpx, editor.isGpxSelected()).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
saveGpx(getMyApplication(), gpx, editor.isGpxSelected());
}
syncGpx(gpx);
}
@ -303,7 +303,7 @@ public class WptPtEditorFragmentNew extends PointEditorFragmentNew {
} else {
gpx.updateWptPt(wpt, wpt.getLatitude(), wpt.getLongitude(),
System.currentTimeMillis(), description, name, category, color, iconName, backgroundTypeName);
new SaveGpxAsyncTask(getMyApplication(), gpx, editor.isGpxSelected()).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
saveGpx(getMyApplication(), gpx, editor.isGpxSelected());
}
syncGpx(gpx);
}
@ -332,7 +332,7 @@ public class WptPtEditorFragmentNew extends PointEditorFragmentNew {
savingTrackHelper.deletePointData(wpt);
} else {
gpx.deleteWptPt(wpt);
new SaveGpxAsyncTask(getMyApplication(), gpx, editor.isGpxSelected()).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
saveGpx(getMyApplication(), gpx, editor.isGpxSelected());
}
syncGpx(gpx);
}
@ -478,28 +478,19 @@ public class WptPtEditorFragmentNew extends PointEditorFragmentNew {
return 0;
}
private static class SaveGpxAsyncTask extends AsyncTask<Void, Void, Void> {
private final OsmandApplication app;
private final GPXFile gpx;
private final boolean gpxSelected;
private void saveGpx(final OsmandApplication app, final GPXFile gpxFile, final boolean gpxSelected) {
new SaveGpxAsyncTask(gpxFile, new SaveGpxListener() {
@Override
public void gpxSavingStarted() {
SaveGpxAsyncTask(OsmandApplication app, GPXFile gpx, boolean gpxSelected) {
this.app = app;
this.gpx = gpx;
this.gpxSelected = gpxSelected;
}
@Override
protected Void doInBackground(Void... params) {
GPXUtilities.writeGpxFile(new File(gpx.path), gpx);
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
if (!gpxSelected) {
app.getSelectedGpxHelper().setGpxFileToDisplay(gpx);
}
}
@Override
public void gpxSavingFinished(Exception errorMessage) {
if (errorMessage == null && !gpxSelected) {
app.getSelectedGpxHelper().setGpxFileToDisplay(gpxFile);
}
}
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
}

View file

@ -0,0 +1,49 @@
package net.osmand.plus.myplaces;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.TextView;
import androidx.annotation.NonNull;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.routepreparationmenu.cards.BaseCard;
import net.osmand.plus.track.TrackDrawInfo;
public class DirectionArrowsCard extends BaseCard {
private TrackDrawInfo trackDrawInfo;
public DirectionArrowsCard(@NonNull MapActivity mapActivity, @NonNull TrackDrawInfo trackDrawInfo) {
super(mapActivity);
this.trackDrawInfo = trackDrawInfo;
}
@Override
public int getCardLayoutId() {
return R.layout.bottom_sheet_item_with_switch;
}
@Override
protected void updateContent() {
AndroidUiHelper.updateVisibility(view.findViewById(R.id.icon), false);
TextView titleView = view.findViewById(R.id.title);
titleView.setText(R.string.gpx_direction_arrows);
final CompoundButton compoundButton = view.findViewById(R.id.compound_button);
compoundButton.setChecked(trackDrawInfo.isShowArrows());
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
boolean checked = !compoundButton.isChecked();
compoundButton.setChecked(checked);
trackDrawInfo.setShowArrows(checked);
mapActivity.refreshMap();
}
});
}
}

View file

@ -0,0 +1,49 @@
package net.osmand.plus.myplaces;
import android.os.AsyncTask;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import net.osmand.GPXUtilities;
import net.osmand.GPXUtilities.GPXFile;
import java.io.File;
public class SaveGpxAsyncTask extends AsyncTask<Void, Void, Exception> {
private final GPXFile gpx;
private final SaveGpxListener saveGpxListener;
public SaveGpxAsyncTask(@NonNull GPXFile gpx,
@Nullable SaveGpxListener saveGpxListener) {
this.gpx = gpx;
this.saveGpxListener = saveGpxListener;
}
@Override
protected void onPreExecute() {
if (saveGpxListener != null) {
saveGpxListener.gpxSavingStarted();
}
}
@Override
protected Exception doInBackground(Void... params) {
return GPXUtilities.writeGpxFile(new File(gpx.path), gpx);
}
@Override
protected void onPostExecute(Exception errorMessage) {
if (saveGpxListener != null) {
saveGpxListener.gpxSavingFinished(errorMessage);
}
}
public interface SaveGpxListener {
void gpxSavingStarted();
void gpxSavingFinished(Exception errorMessage);
}
}

View file

@ -0,0 +1,76 @@
package net.osmand.plus.myplaces;
import android.os.AsyncTask;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import net.osmand.plus.GpxSelectionHelper;
import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.track.GpxSplitType;
import java.util.List;
public class SplitTrackAsyncTask extends AsyncTask<Void, Void, Void> {
private OsmandApplication app;
private GpxSplitType gpxSplitType;
private List<GpxDisplayGroup> groups;
private SplitTrackListener splitTrackListener;
private boolean joinSegments;
private int timeSplitInterval;
private double distanceSplitInterval;
public SplitTrackAsyncTask(@NonNull OsmandApplication app,
@NonNull GpxSplitType gpxSplitType,
@NonNull List<GpxDisplayGroup> groups,
@Nullable SplitTrackListener splitTrackListener,
boolean joinSegments,
int timeSplitInterval,
double distanceSplitInterval) {
this.app = app;
this.groups = groups;
this.gpxSplitType = gpxSplitType;
this.splitTrackListener = splitTrackListener;
this.joinSegments = joinSegments;
this.timeSplitInterval = timeSplitInterval;
this.distanceSplitInterval = distanceSplitInterval;
}
@Override
protected void onPreExecute() {
if (splitTrackListener != null) {
splitTrackListener.trackSplittingStarted();
}
}
@Override
protected Void doInBackground(Void... params) {
for (GpxSelectionHelper.GpxDisplayGroup model : groups) {
if (gpxSplitType == GpxSplitType.NO_SPLIT) {
model.noSplit(app);
} else if (gpxSplitType == GpxSplitType.DISTANCE && distanceSplitInterval > 0) {
model.splitByDistance(app, distanceSplitInterval, joinSegments);
} else if (gpxSplitType == GpxSplitType.TIME && timeSplitInterval > 0) {
model.splitByTime(app, timeSplitInterval, joinSegments);
}
}
return null;
}
@Override
protected void onPostExecute(Void result) {
if (splitTrackListener != null) {
splitTrackListener.trackSplittingFinished();
}
}
public interface SplitTrackListener {
void trackSplittingStarted();
void trackSplittingFinished();
}
}

View file

@ -39,10 +39,8 @@ import com.squareup.picasso.RequestCreator;
import net.osmand.AndroidUtils;
import net.osmand.GPXUtilities;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.GPXUtilities.GPXFile.GpxSplitType;
import net.osmand.GPXUtilities.WptPt;
import net.osmand.PicassoUtils;
import net.osmand.data.LatLon;
import net.osmand.data.PointDescription;
import net.osmand.data.QuadRect;
import net.osmand.plus.GPXDatabase.GpxDataItem;
@ -55,30 +53,24 @@ import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.activities.TrackActivity;
import net.osmand.plus.dialogs.GpxAppearanceAdapter;
import net.osmand.plus.dialogs.GpxAppearanceAdapter.AppearanceListItem;
import net.osmand.plus.dialogs.GpxAppearanceAdapter.GpxAppearanceAdapterType;
import net.osmand.plus.measurementtool.NewGpxData;
import net.osmand.plus.track.SplitTrackAsyncTask;
import net.osmand.plus.track.SplitTrackAsyncTask.SplitTrackListener;
import net.osmand.plus.myplaces.TrackBitmapDrawer.TrackBitmapDrawerListener;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.settings.backend.OsmandSettings.CommonPreference;
import net.osmand.plus.track.GpxSplitType;
import net.osmand.plus.widgets.tools.CropCircleTransformation;
import net.osmand.plus.wikipedia.WikiArticleHelper;
import net.osmand.plus.wikivoyage.WikivoyageUtils;
import net.osmand.plus.wikivoyage.article.WikivoyageArticleDialogFragment;
import net.osmand.plus.wikivoyage.data.TravelArticle;
import net.osmand.render.RenderingRulesStorage;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import gnu.trove.list.array.TIntArrayList;
import static net.osmand.plus.dialogs.ConfigureMapMenu.CURRENT_TRACK_COLOR_ATTR;
import static net.osmand.plus.dialogs.ConfigureMapMenu.CURRENT_TRACK_WIDTH_ATTR;
public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
private OsmandApplication app;
@ -269,46 +261,13 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
TrackActivity activity = getTrackActivity();
GpxDataItem gpxDataItem = getGpxDataItem();
GPXFile gpx = getGpx();
WptPt pointToShow = gpx != null ? gpx.findPointToShow() : null;
if (activity != null && pointToShow != null) {
boolean gpxFileSelected = isGpxFileSelected(gpx);
if (!gpxFileSelected) {
Intent intent = activity.getIntent();
if (intent != null) {
intent.putExtra(TrackActivity.SHOW_TEMPORARILY, true);
}
}
setTrackVisibilityOnMap(true);
LatLon location = new LatLon(pointToShow.getLatitude(),
pointToShow.getLongitude());
final OsmandSettings settings = app.getSettings();
String trackName;
if (gpx.showCurrentTrack) {
trackName = app.getString(R.string.shared_string_currently_recording_track);
} else if (gpxDataItem != null) {
trackName = gpxDataItem.getFile().getName();
} else {
trackName = gpx.path;
}
settings.setMapLocationToShow(location.getLatitude(), location.getLongitude(),
settings.getLastKnownMapZoom(),
new PointDescription(PointDescription.POINT_TYPE_WPT, trackName),
false,
getRect()
);
MapActivity.launchMapActivityMoveToTop(activity);
}
showTemporaryObjectOnMap(getRect());
}
});
final View splitColorView = headerView.findViewById(R.id.split_color_view);
final View appearanceView = headerView.findViewById(R.id.appearance_view);
final View divider = headerView.findViewById(R.id.divider);
final View splitIntervalView = headerView.findViewById(R.id.split_interval_view);
final View colorView = headerView.findViewById(R.id.color_view);
vis = (SwitchCompat) headerView.findViewById(R.id.showOnMapToggle);
final View bottomDivider = headerView.findViewById(R.id.bottom_divider);
GPXFile gpxFile = getGpx();
@ -340,7 +299,6 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
setTrackVisibilityOnMap(vis.isChecked());
if (!showMapOnly) {
updateSplitIntervalView(splitIntervalView);
updateColorView(colorView);
}
TrackActivity trackActivity = getTrackActivity();
if (trackActivity != null) {
@ -353,42 +311,12 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
if (showMapOnly) {
splitIntervalView.setVisibility(View.GONE);
splitColorView.setVisibility(View.GONE);
appearanceView.setVisibility(View.GONE);
divider.setVisibility(View.GONE);
bottomDivider.setVisibility(View.VISIBLE);
} else {
bottomDivider.setVisibility(View.GONE);
updateColorView(colorView);
colorView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
TrackActivity activity = getTrackActivity();
final GPXFile gpxFile = getGpx();
if (activity != null && gpxFile != null) {
final GpxAppearanceAdapter appearanceAdapter = new GpxAppearanceAdapter(activity,
gpxFile.getColor(0), GpxAppearanceAdapterType.TRACK_WIDTH_COLOR);
OnItemClickListener itemClickListener = new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
AppearanceListItem item = appearanceAdapter.getItem(position);
if (item != null) {
if (CURRENT_TRACK_COLOR_ATTR.equals(item.getAttrName())) {
setGpxColor(item, gpxFile);
} else if (CURRENT_TRACK_WIDTH_ATTR.equals(item.getAttrName())) {
setGpxWidth(item, gpxFile);
}
}
colorListPopupWindow.dismiss();
updateColorView(colorView);
}
};
colorListPopupWindow = createPopupWindow(activity, splitIntervalView, appearanceAdapter, itemClickListener);
colorListPopupWindow.show();
}
}
});
if (hasPath) {
if (!gpxFile.showCurrentTrack && listItemsCount > 0) {
prepareSplitIntervalAdapterData();
@ -419,48 +347,55 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
} else {
splitIntervalView.setVisibility(View.GONE);
}
appearanceView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showTemporaryObjectOnMap(getGpx());
}
});
appearanceView.setVisibility(View.VISIBLE);
splitColorView.setVisibility(View.VISIBLE);
divider.setVisibility(View.VISIBLE);
} else {
appearanceView.setVisibility(View.GONE);
splitColorView.setVisibility(View.GONE);
divider.setVisibility(View.GONE);
}
}
}
private void setGpxColor(AppearanceListItem item, GPXFile gpxFile) {
int color = item.getColor();
if (vis.isChecked()) {
SelectedGpxFile sf = app.getSelectedGpxHelper().selectGpxFile(gpxFile, vis.isChecked(), false);
if (color != 0 && sf.getModifiableGpxFile() != null) {
sf.getModifiableGpxFile().setColor(color);
if (getGpxDataItem() != null) {
app.getGpxDbHelper().updateColor(getGpxDataItem(), color);
private void showTemporaryObjectOnMap(Object toShow){
TrackActivity activity = getTrackActivity();
GpxDataItem gpxDataItem = getGpxDataItem();
GPXFile gpx = getGpx();
WptPt pointToShow = gpx != null ? gpx.findPointToShow() : null;
if (activity != null && pointToShow != null) {
boolean gpxFileSelected = isGpxFileSelected(gpx);
if (!gpxFileSelected) {
Intent intent = activity.getIntent();
if (intent != null) {
intent.putExtra(TrackActivity.SHOW_TEMPORARILY, true);
}
}
} else if (getGpxDataItem() != null) {
app.getGpxDbHelper().updateColor(getGpxDataItem(), color);
}
if (gpxFile.showCurrentTrack) {
app.getSettings().CURRENT_TRACK_COLOR.set(color);
}
refreshTrackBitmap();
}
setTrackVisibilityOnMap(true);
private void setGpxWidth(AppearanceListItem item, GPXFile gpxFile) {
String width = item.getValue();
if (vis.isChecked()) {
SelectedGpxFile sf = app.getSelectedGpxHelper().selectGpxFile(gpxFile, vis.isChecked(), false);
if (width != null && sf.getModifiableGpxFile() != null) {
sf.getModifiableGpxFile().setWidth(width);
if (getGpxDataItem() != null) {
app.getGpxDbHelper().updateWidth(getGpxDataItem(), width);
}
final OsmandSettings settings = app.getSettings();
String trackName;
if (gpx.showCurrentTrack) {
trackName = app.getString(R.string.shared_string_currently_recording_track);
} else if (gpxDataItem != null) {
trackName = gpxDataItem.getFile().getName();
} else {
trackName = gpx.path;
}
} else if (getGpxDataItem() != null) {
app.getGpxDbHelper().updateWidth(getGpxDataItem(), width);
settings.setMapLocationToShow(pointToShow.getLatitude(), pointToShow.getLongitude(),
settings.getLastKnownMapZoom(),
new PointDescription(PointDescription.POINT_TYPE_WPT, trackName),
false,
toShow
);
MapActivity.launchMapActivityMoveToTop(activity);
}
refreshTrackBitmap();
}
private ListPopupWindow createPopupWindow(Activity activity, View anchorView, ListAdapter adapter, OnItemClickListener itemClickListener) {
@ -773,33 +708,6 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
return Math.max(position, 0);
}
private void updateColorView(View colorView) {
final ImageView colorImageView = (ImageView) colorView.findViewById(R.id.colorImage);
int color = getGpxDataItem() != null ? getGpxDataItem().getColor() : 0;
GPXFile gpxFile = getGpx();
if (color == 0 && gpxFile != null) {
if (gpxFile.showCurrentTrack) {
color = app.getSettings().CURRENT_TRACK_COLOR.get();
} else {
color = gpxFile.getColor(0);
}
}
if (color == 0) {
RenderingRulesStorage renderer = app.getRendererRegistry().getCurrentSelectedRenderer();
CommonPreference<String> prefColor = app.getSettings().getCustomRenderProperty(CURRENT_TRACK_COLOR_ATTR);
color = GpxAppearanceAdapter.parseTrackColor(renderer, prefColor.get());
}
if (color == 0) {
colorImageView.setImageDrawable(app.getUIUtilities().getThemedIcon(R.drawable.ic_action_circle));
} else {
colorImageView.setImageDrawable(app.getUIUtilities().getPaintedIcon(R.drawable.ic_action_circle, color));
}
TrackBitmapDrawer trackDrawer = getTrackBitmapDrawer();
if (trackDrawer != null) {
trackDrawer.setTrackColor(color);
}
}
public List<GpxSelectionHelper.GpxDisplayItem> flatten(List<GpxDisplayGroup> groups) {
ArrayList<GpxSelectionHelper.GpxDisplayItem> list = new ArrayList<>();
for (GpxDisplayGroup g : groups) {
@ -841,14 +749,57 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
addOptionSplit(3600, false, groups);
}
private void updateSplit(@NonNull List<GpxDisplayGroup> groups, @Nullable SelectedGpxFile sf) {
private void updateSplit(@NonNull List<GpxDisplayGroup> groups, @Nullable final SelectedGpxFile selectedGpx) {
GPXFile gpxFile = getGpx();
TrackActivity activity = getTrackActivity();
if (activity != null) {
new SplitTrackAsyncTask(activity, this, sf, groups)
.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null);
GpxSplitType gpxSplitType = getGpxSplitType();
if (activity != null && gpxSplitType != null && gpxFile != null) {
int timeSplit = 0;
double distanceSplit = 0;
if (!gpxFile.showCurrentTrack) {
timeSplit = this.timeSplit.get(selectedSplitInterval);
distanceSplit = this.distanceSplit.get(selectedSplitInterval);
}
SplitTrackListener splitTrackListener = new SplitTrackListener() {
@Override
public void trackSplittingStarted() {
TrackActivity activity = getTrackActivity();
if (activity != null) {
activity.setSupportProgressBarIndeterminateVisibility(true);
}
}
@Override
public void trackSplittingFinished() {
TrackActivity activity = getTrackActivity();
if (activity != null) {
if (AndroidUtils.isActivityNotDestroyed(activity)) {
activity.setSupportProgressBarIndeterminateVisibility(false);
}
if (selectedGpx != null) {
List<GpxDisplayGroup> groups = getDisplayGroups();
selectedGpx.setDisplayGroups(groups, app);
}
}
}
};
new SplitTrackAsyncTask(app, gpxSplitType, groups, splitTrackListener, activity.isJoinSegments(),
timeSplit, distanceSplit).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
}
private GpxSplitType getGpxSplitType() {
if (selectedSplitInterval == 0) {
return GpxSplitType.NO_SPLIT;
} else if (distanceSplit.get(selectedSplitInterval) > 0) {
return GpxSplitType.DISTANCE;
} else if (timeSplit.get(selectedSplitInterval) > 0) {
return GpxSplitType.TIME;
}
return null;
}
private void addOptionSplit(int value, boolean distance, @NonNull List<GpxDisplayGroup> model) {
if (model.size() > 0) {
if (distance) {
@ -1008,75 +959,4 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
public void drawTrackBitmap(Bitmap bitmap) {
imageView.setImageDrawable(new BitmapDrawable(app.getResources(), bitmap));
}
private static class SplitTrackAsyncTask extends AsyncTask<Void, Void, Void> {
private final SelectedGpxFile selectedGpx;
private OsmandApplication app;
private final WeakReference<TrackActivity> activityRef;
private final WeakReference<TrackActivityFragmentAdapter> fragmentAdapterRef;
private final List<GpxDisplayGroup> groups;
private List<Double> distanceSplit;
private TIntArrayList timeSplit;
private int selectedSplitInterval;
private boolean joinSegments;
SplitTrackAsyncTask(@NonNull TrackActivity activity,
@NonNull TrackActivityFragmentAdapter fragmentAdapter,
@Nullable SelectedGpxFile selectedGpx,
@NonNull List<GpxDisplayGroup> groups) {
activityRef = new WeakReference<>(activity);
fragmentAdapterRef = new WeakReference<>(fragmentAdapter);
app = activity.getMyApplication();
this.selectedGpx = selectedGpx;
this.groups = groups;
selectedSplitInterval = fragmentAdapter.selectedSplitInterval;
distanceSplit = fragmentAdapter.distanceSplit;
timeSplit = fragmentAdapter.timeSplit;
joinSegments = activity.isJoinSegments();
}
@Override
protected void onPreExecute() {
TrackActivity activity = activityRef.get();
if (activity != null) {
activity.setSupportProgressBarIndeterminateVisibility(true);
}
}
@Override
protected void onPostExecute(Void result) {
TrackActivity activity = activityRef.get();
TrackActivityFragmentAdapter fragment = fragmentAdapterRef.get();
if (activity != null && fragment != null) {
if (!activity.isFinishing()) {
activity.setSupportProgressBarIndeterminateVisibility(false);
}
if (selectedGpx != null) {
List<GpxDisplayGroup> groups = fragment.getDisplayGroups();
selectedGpx.setDisplayGroups(groups, app);
}
/*
if (fragment.isVisible()) {
fragment.updateContent();
}
*/
}
}
@Override
protected Void doInBackground(Void... params) {
for (GpxDisplayGroup model : groups) {
if (selectedSplitInterval == 0) {
model.noSplit(app);
} else if (distanceSplit.get(selectedSplitInterval) > 0) {
model.splitByDistance(app, distanceSplit.get(selectedSplitInterval), joinSegments);
} else if (timeSplit.get(selectedSplitInterval) > 0) {
model.splitByTime(app, timeSplit.get(selectedSplitInterval), joinSegments);
}
}
return null;
}
}
}

View file

@ -68,6 +68,8 @@ import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetAxisType;
import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetType;
import net.osmand.plus.helpers.GpxUiHelper.OrderedLineDataSet;
import net.osmand.plus.measurementtool.NewGpxData;
import net.osmand.plus.track.SaveGpxAsyncTask;
import net.osmand.plus.track.SaveGpxAsyncTask.SaveGpxListener;
import net.osmand.plus.myplaces.TrackBitmapDrawer.TrackBitmapDrawerListener;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.views.controls.PagerSlidingTabStrip;
@ -79,7 +81,6 @@ import net.osmand.util.Algorithms;
import net.osmand.util.MapUtils;
import java.io.File;
import java.lang.ref.WeakReference;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
@ -788,10 +789,7 @@ public class TrackSegmentFragment extends OsmAndListFragment implements TrackBit
public boolean onMenuItemClick(MenuItem item) {
int i = item.getItemId();
if (i == R.id.action_edit) {
TrkSegment segment = getTrkSegment();
if (segment != null && fragmentAdapter != null) {
fragmentAdapter.addNewGpxData(NewGpxData.ActionType.EDIT_SEGMENT, segment);
}
editSegment();
return true;
} else if (i == R.id.action_delete) {
TrackActivity activity = getTrackActivity();
@ -801,16 +799,7 @@ public class TrackSegmentFragment extends OsmAndListFragment implements TrackBit
builder.setPositiveButton(R.string.shared_string_yes, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
TrackActivity trackActivity = getTrackActivity();
if (trackActivity != null && deleteSegment()) {
GPXFile gpx = getGpx();
if (gpx != null && fragmentAdapter != null) {
boolean showOnMap = fragmentAdapter.isShowOnMap();
SelectedGpxFile sf = app.getSelectedGpxHelper().selectGpxFile(gpx, showOnMap, false);
new SaveGpxAsyncTask(trackActivity, TrackSegmentFragment.this, gpx, showOnMap ? sf : null)
.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
}
deleteAndSaveSegment();
}
});
builder.setNegativeButton(R.string.shared_string_cancel, null);
@ -914,22 +903,10 @@ public class TrackSegmentFragment extends OsmAndListFragment implements TrackBit
public boolean onMenuItemClick(MenuItem item) {
int i = item.getItemId();
if (i == R.id.action_edit) {
TrkSegment segment = getTrkSegment();
if (segment != null && fragmentAdapter != null) {
fragmentAdapter.addNewGpxData(NewGpxData.ActionType.EDIT_SEGMENT, segment);
}
editSegment();
return true;
} else if (i == R.id.action_delete) {
TrackActivity trackActivity = getTrackActivity();
if (trackActivity != null && deleteSegment()) {
GPXFile gpx = getGpx();
if (gpx != null && fragmentAdapter != null) {
boolean showOnMap = fragmentAdapter.isShowOnMap();
SelectedGpxFile sf = app.getSelectedGpxHelper().selectGpxFile(gpx, showOnMap, false);
new SaveGpxAsyncTask(trackActivity, TrackSegmentFragment.this, gpx, showOnMap ? sf : null)
.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
}
deleteAndSaveSegment();
return true;
}
return false;
@ -1023,22 +1000,10 @@ public class TrackSegmentFragment extends OsmAndListFragment implements TrackBit
public boolean onMenuItemClick(MenuItem item) {
int i = item.getItemId();
if (i == R.id.action_edit) {
TrkSegment segment = getTrkSegment();
if (segment != null && fragmentAdapter != null) {
fragmentAdapter.addNewGpxData(NewGpxData.ActionType.EDIT_SEGMENT, segment);
}
editSegment();
return true;
} else if (i == R.id.action_delete) {
TrackActivity trackActivity = getTrackActivity();
if (trackActivity != null && deleteSegment()) {
GPXFile gpx = getGpx();
if (gpx != null && fragmentAdapter != null) {
boolean showOnMap = fragmentAdapter.isShowOnMap();
SelectedGpxFile sf = app.getSelectedGpxHelper().selectGpxFile(gpx, showOnMap, false);
new SaveGpxAsyncTask(trackActivity, TrackSegmentFragment.this, gpx, showOnMap ? sf : null)
.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
}
deleteAndSaveSegment();
return true;
}
return false;
@ -1060,6 +1025,25 @@ public class TrackSegmentFragment extends OsmAndListFragment implements TrackBit
return view;
}
private void editSegment() {
TrkSegment segment = getTrkSegment();
if (segment != null && fragmentAdapter != null) {
fragmentAdapter.addNewGpxData(NewGpxData.ActionType.EDIT_SEGMENT, segment);
}
}
private void deleteAndSaveSegment() {
TrackActivity trackActivity = getTrackActivity();
if (trackActivity != null && deleteSegment()) {
GPXFile gpx = getGpx();
if (gpx != null && fragmentAdapter != null) {
boolean showOnMap = fragmentAdapter.isShowOnMap();
SelectedGpxFile selectedGpxFile = app.getSelectedGpxHelper().selectGpxFile(gpx, showOnMap, false);
saveGpx(showOnMap ? selectedGpxFile : null, gpx);
}
}
}
private boolean deleteSegment() {
TrkSegment segment = getTrkSegment();
if (segment != null) {
@ -1269,55 +1253,33 @@ public class TrackSegmentFragment extends OsmAndListFragment implements TrackBit
}
}
private static class SaveGpxAsyncTask extends AsyncTask<Void, Void, Void> {
private final GPXFile gpx;
private final SelectedGpxFile selectedGpx;
private OsmandApplication app;
private final WeakReference<TrackActivity> activityRef;
private final WeakReference<TrackSegmentFragment> fragmentRef;
SaveGpxAsyncTask(@NonNull TrackActivity activity,
@NonNull TrackSegmentFragment fragment,
@NonNull GPXFile gpx,
@Nullable SelectedGpxFile selectedGpx) {
this.gpx = gpx;
activityRef = new WeakReference<>(activity);
fragmentRef = new WeakReference<>(fragment);
app = activity.getMyApplication();
this.selectedGpx = selectedGpx;
}
@Override
protected void onPreExecute() {
TrackActivity activity = activityRef.get();
if (activity != null) {
activity.setSupportProgressBarIndeterminateVisibility(true);
private void saveGpx(final SelectedGpxFile selectedGpxFile, GPXFile gpxFile) {
new SaveGpxAsyncTask(gpxFile, new SaveGpxListener() {
@Override
public void gpxSavingStarted() {
TrackActivity activity = getTrackActivity();
if (activity != null && AndroidUtils.isActivityNotDestroyed(activity)) {
activity.setSupportProgressBarIndeterminateVisibility(true);
}
}
}
@Override
protected Void doInBackground(Void... params) {
GPXUtilities.writeGpxFile(new File(gpx.path), gpx);
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
TrackActivity activity = activityRef.get();
TrackSegmentFragment fragment = fragmentRef.get();
if (activity != null && fragment != null) {
if (selectedGpx != null) {
List<GpxDisplayGroup> groups = fragment.getDisplayGroups();
if (groups != null) {
selectedGpx.setDisplayGroups(groups, app);
selectedGpx.processPoints(app);
@Override
public void gpxSavingFinished(Exception errorMessage) {
TrackActivity activity = getTrackActivity();
if (activity != null) {
if (selectedGpxFile != null) {
List<GpxDisplayGroup> groups = getDisplayGroups();
if (groups != null) {
selectedGpxFile.setDisplayGroups(groups, app);
selectedGpxFile.processPoints(app);
}
}
updateContent();
if (AndroidUtils.isActivityNotDestroyed(activity)) {
activity.setSupportProgressBarIndeterminateVisibility(false);
}
}
fragment.updateContent();
if (!activity.isFinishing()) {
activity.setSupportProgressBarIndeterminateVisibility(false);
}
}
}
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
}

View file

@ -0,0 +1,48 @@
package net.osmand.plus.track;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.TextView;
import androidx.annotation.NonNull;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.routepreparationmenu.cards.BaseCard;
public class DirectionArrowsCard extends BaseCard {
private TrackDrawInfo trackDrawInfo;
public DirectionArrowsCard(@NonNull MapActivity mapActivity, @NonNull TrackDrawInfo trackDrawInfo) {
super(mapActivity);
this.trackDrawInfo = trackDrawInfo;
}
@Override
public int getCardLayoutId() {
return R.layout.bottom_sheet_item_with_switch;
}
@Override
protected void updateContent() {
AndroidUiHelper.updateVisibility(view.findViewById(R.id.icon), false);
TextView titleView = view.findViewById(R.id.title);
titleView.setText(R.string.gpx_direction_arrows);
final CompoundButton compoundButton = view.findViewById(R.id.compound_button);
compoundButton.setChecked(trackDrawInfo.isShowArrows());
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
boolean checked = !compoundButton.isChecked();
compoundButton.setChecked(checked);
trackDrawInfo.setShowArrows(checked);
mapActivity.refreshMap();
}
});
}
}

View file

@ -0,0 +1,56 @@
package net.osmand.plus.track;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import net.osmand.plus.R;
public enum GpxSplitType {
NO_SPLIT("no_split", -1, R.string.shared_string_none),
DISTANCE("distance", 1, R.string.distance),
TIME("time", 2, R.string.shared_string_time);
private String typeName;
private int type;
@StringRes
private int resId;
GpxSplitType(@NonNull String typeName, int type, @StringRes int resId) {
this.typeName = typeName;
this.type = type;
this.resId = resId;
}
public int getType() {
return type;
}
public String getTypeName() {
return typeName;
}
public String getHumanString(@NonNull Context ctx) {
return ctx.getString(resId);
}
public static GpxSplitType getSplitTypeByName(@NonNull String name) {
for (GpxSplitType splitType : GpxSplitType.values()) {
if (splitType.name().equalsIgnoreCase(name)) {
return splitType;
}
}
return null;
}
public static GpxSplitType getSplitTypeByTypeId(int typeId) {
for (GpxSplitType splitType : GpxSplitType.values()) {
if (splitType.getType() == typeId) {
return splitType;
}
}
return null;
}
}

View file

@ -0,0 +1,55 @@
package net.osmand.plus.track;
import android.content.Context;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import net.osmand.plus.R;
public enum GradientScaleType {
SPEED("speed", "gradient_speed_color", R.string.map_widget_speed, R.drawable.ic_action_speed),
ALTITUDE("altitude", "gradient_altitude_color", R.string.altitude, R.drawable.ic_action_altitude_average),
SLOPE("slope", "gradient_slope_color", R.string.shared_string_slope, R.drawable.ic_action_altitude_ascent);
private String typeName;
private String colorTypeName;
@StringRes
private int resId;
@DrawableRes
private int iconId;
GradientScaleType(@NonNull String typeName, @NonNull String colorTypeName, @StringRes int resId, @DrawableRes int iconId) {
this.typeName = typeName;
this.colorTypeName = colorTypeName;
this.resId = resId;
this.iconId = iconId;
}
public String getTypeName() {
return typeName;
}
public String getColorTypeName() {
return colorTypeName;
}
public int getIconId() {
return iconId;
}
public String getHumanString(@NonNull Context ctx) {
return ctx.getString(resId);
}
public static GradientScaleType getGradientTypeByName(@NonNull String name) {
for (GradientScaleType scaleType : GradientScaleType.values()) {
if (scaleType.name().equalsIgnoreCase(name)) {
return scaleType;
}
}
return null;
}
}

View file

@ -0,0 +1,49 @@
package net.osmand.plus.track;
import android.os.AsyncTask;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import net.osmand.GPXUtilities;
import net.osmand.GPXUtilities.GPXFile;
import java.io.File;
public class SaveGpxAsyncTask extends AsyncTask<Void, Void, Exception> {
private final GPXFile gpx;
private final SaveGpxListener saveGpxListener;
public SaveGpxAsyncTask(@NonNull GPXFile gpx,
@Nullable SaveGpxListener saveGpxListener) {
this.gpx = gpx;
this.saveGpxListener = saveGpxListener;
}
@Override
protected void onPreExecute() {
if (saveGpxListener != null) {
saveGpxListener.gpxSavingStarted();
}
}
@Override
protected Exception doInBackground(Void... params) {
return GPXUtilities.writeGpxFile(new File(gpx.path), gpx);
}
@Override
protected void onPostExecute(Exception errorMessage) {
if (saveGpxListener != null) {
saveGpxListener.gpxSavingFinished(errorMessage);
}
}
public interface SaveGpxListener {
void gpxSavingStarted();
void gpxSavingFinished(Exception errorMessage);
}
}

View file

@ -0,0 +1,364 @@
package net.osmand.plus.track;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.RadioGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import com.google.android.material.slider.Slider;
import net.osmand.PlatformUtil;
import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup;
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItemType;
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
import net.osmand.plus.OsmAndFormatter;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.base.MenuBottomSheetDialogFragment;
import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.LongDescriptionItem;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.track.SplitTrackAsyncTask.SplitTrackListener;
import org.apache.commons.logging.Log;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import static net.osmand.plus.track.TrackDrawInfo.TRACK_FILE_PATH;
public class SplitIntervalBottomSheet extends MenuBottomSheetDialogFragment {
public static final String TAG = SplitIntervalBottomSheet.class.getSimpleName();
private static final Log log = PlatformUtil.getLog(SplitIntervalBottomSheet.class);
public static final String SELECTED_TRACK_SPLIT_TYPE = "selected_track_split_type";
public static final String SELECTED_TIME_SPLIT_INTERVAL = "selected_time_split_interval";
public static final String SELECTED_DISTANCE_SPLIT_INTERVAL = "selected_distance_split_interval";
private OsmandApplication app;
private SelectedGpxFile selectedGpxFile;
private TrackDrawInfo trackDrawInfo;
private Map<String, Integer> timeSplitOptions = new LinkedHashMap<>();
private Map<String, Double> distanceSplitOptions = new LinkedHashMap<>();
private int selectedTimeSplitInterval;
private int selectedDistanceSplitInterval;
private GpxSplitType selectedSplitType = GpxSplitType.NO_SPLIT;
private Slider slider;
private View sliderContainer;
private TextView splitValueMin;
private TextView splitValueMax;
private TextView selectedSplitValue;
private TextView splitIntervalNoneDescr;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
app = requiredMyApplication();
Fragment target = getTargetFragment();
if (target instanceof TrackAppearanceFragment) {
trackDrawInfo = ((TrackAppearanceFragment) target).getTrackDrawInfo();
}
Bundle arguments = getArguments();
if (savedInstanceState != null) {
String gpxFilePath = savedInstanceState.getString(TRACK_FILE_PATH);
selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(gpxFilePath);
prepareSplitIntervalOptions();
selectedTimeSplitInterval = savedInstanceState.getInt(SELECTED_TIME_SPLIT_INTERVAL);
selectedDistanceSplitInterval = savedInstanceState.getInt(SELECTED_DISTANCE_SPLIT_INTERVAL);
selectedSplitType = GpxSplitType.valueOf(savedInstanceState.getString(SELECTED_TRACK_SPLIT_TYPE));
} else if (arguments != null) {
String gpxFilePath = arguments.getString(TRACK_FILE_PATH);
selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(gpxFilePath);
prepareSplitIntervalOptions();
updateSelectedSplitParams();
}
}
@Override
public void createMenuItems(Bundle savedInstanceState) {
items.add(new TitleItem(getString(R.string.gpx_split_interval)));
items.add(new LongDescriptionItem(getString(R.string.gpx_split_interval_descr)));
LayoutInflater themedInflater = UiUtilities.getInflater(requireContext(), nightMode);
View view = themedInflater.inflate(R.layout.track_split_interval, null);
sliderContainer = view.findViewById(R.id.slider_container);
slider = sliderContainer.findViewById(R.id.split_slider);
splitValueMin = view.findViewById(R.id.split_value_min);
splitValueMax = view.findViewById(R.id.split_value_max);
selectedSplitValue = view.findViewById(R.id.split_value_tv);
splitIntervalNoneDescr = view.findViewById(R.id.split_interval_none_descr);
UiUtilities.setupSlider(slider, nightMode, null);
RadioGroup splitTypeGroup = view.findViewById(R.id.split_type);
if (selectedSplitType == GpxSplitType.NO_SPLIT) {
splitTypeGroup.check(R.id.no_split);
} else if (selectedSplitType == GpxSplitType.TIME) {
splitTypeGroup.check(R.id.time_split);
} else if (selectedSplitType == GpxSplitType.DISTANCE) {
splitTypeGroup.check(R.id.distance_split);
}
splitTypeGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
if (checkedId == R.id.no_split) {
selectedSplitType = GpxSplitType.NO_SPLIT;
} else if (checkedId == R.id.time_split) {
selectedSplitType = GpxSplitType.TIME;
} else if (checkedId == R.id.distance_split) {
selectedSplitType = GpxSplitType.DISTANCE;
}
updateSlider();
}
});
SimpleBottomSheetItem titleItem = (SimpleBottomSheetItem) new SimpleBottomSheetItem.Builder()
.setCustomView(view)
.create();
items.add(titleItem);
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(SELECTED_TIME_SPLIT_INTERVAL, selectedTimeSplitInterval);
outState.putInt(SELECTED_DISTANCE_SPLIT_INTERVAL, selectedDistanceSplitInterval);
outState.putString(SELECTED_TRACK_SPLIT_TYPE, selectedSplitType.name());
outState.putString(TRACK_FILE_PATH, selectedGpxFile.getGpxFile().path);
}
private void updateSelectedSplitParams() {
if (trackDrawInfo != null) {
if (trackDrawInfo.getSplitType() == GpxSplitType.DISTANCE.getType()) {
selectedSplitType = GpxSplitType.DISTANCE;
List<Double> splitOptions = new ArrayList<>(distanceSplitOptions.values());
int index = splitOptions.indexOf(trackDrawInfo.getSplitInterval());
selectedDistanceSplitInterval = Math.max(index, 0);
} else if (trackDrawInfo.getSplitType() == GpxSplitType.TIME.getType()) {
selectedSplitType = GpxSplitType.TIME;
List<Integer> splitOptions = new ArrayList<>(timeSplitOptions.values());
int index = splitOptions.indexOf((int) trackDrawInfo.getSplitInterval());
selectedTimeSplitInterval = Math.max(index, 0);
}
}
}
private void prepareSplitIntervalOptions() {
List<GpxDisplayGroup> groups = getDisplayGroups();
addDistanceOptionSplit(30, groups); // 50 feet, 20 yards, 20 m
addDistanceOptionSplit(60, groups); // 100 feet, 50 yards, 50 m
addDistanceOptionSplit(150, groups); // 200 feet, 100 yards, 100 m
addDistanceOptionSplit(300, groups); // 500 feet, 200 yards, 200 m
addDistanceOptionSplit(600, groups); // 1000 feet, 500 yards, 500 m
addDistanceOptionSplit(1500, groups); // 2000 feet, 1000 yards, 1 km
addDistanceOptionSplit(3000, groups); // 1 mi, 2 km
addDistanceOptionSplit(6000, groups); // 2 mi, 5 km
addDistanceOptionSplit(15000, groups); // 5 mi, 10 km
addTimeOptionSplit(15, groups);
addTimeOptionSplit(30, groups);
addTimeOptionSplit(60, groups);
addTimeOptionSplit(120, groups);
addTimeOptionSplit(150, groups);
addTimeOptionSplit(300, groups);
addTimeOptionSplit(600, groups);
addTimeOptionSplit(900, groups);
addTimeOptionSplit(1800, groups);
addTimeOptionSplit(3600, groups);
}
private void addDistanceOptionSplit(int value, @NonNull List<GpxDisplayGroup> displayGroups) {
if (displayGroups.size() > 0) {
double dvalue = OsmAndFormatter.calculateRoundedDist(value, app);
String formattedDist = OsmAndFormatter.getFormattedDistance((float) dvalue, app);
distanceSplitOptions.put(formattedDist, dvalue);
if (Math.abs(displayGroups.get(0).getSplitDistance() - dvalue) < 1) {
selectedDistanceSplitInterval = distanceSplitOptions.size() - 1;
}
}
}
private void addTimeOptionSplit(int value, @NonNull List<GpxDisplayGroup> model) {
if (model.size() > 0) {
String time;
if (value < 60) {
time = value + " " + getString(R.string.int_seconds);
} else if (value % 60 == 0) {
time = (value / 60) + " " + getString(R.string.int_min);
} else {
time = (value / 60f) + " " + getString(R.string.int_min);
}
timeSplitOptions.put(time, value);
if (model.get(0).getSplitTime() == value) {
selectedTimeSplitInterval = timeSplitOptions.size() - 1;
}
}
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
updateSlider();
}
private void updateSlider() {
if (selectedSplitType != GpxSplitType.NO_SPLIT) {
slider.clearOnChangeListeners();
if (selectedSplitType == GpxSplitType.TIME) {
updateSliderTimeInterval();
} else {
updateSliderDistanceInterval();
}
AndroidUiHelper.updateVisibility(sliderContainer, true);
AndroidUiHelper.updateVisibility(splitIntervalNoneDescr, false);
} else {
AndroidUiHelper.updateVisibility(sliderContainer, false);
AndroidUiHelper.updateVisibility(splitIntervalNoneDescr, true);
}
setupHeightAndBackground(getView());
}
private void updateSliderTimeInterval() {
final List<String> splitOptions = new ArrayList<>(timeSplitOptions.keySet());
updateSliderMinMaxValues(splitOptions);
slider.setValue(selectedTimeSplitInterval);
slider.addOnChangeListener(new Slider.OnChangeListener() {
@Override
public void onValueChange(@NonNull Slider slider, float value, boolean fromUser) {
if (fromUser) {
selectedTimeSplitInterval = (int) value;
selectedSplitValue.setText(splitOptions.get(selectedTimeSplitInterval));
}
}
});
selectedSplitValue.setText(splitOptions.get(selectedTimeSplitInterval));
}
private void updateSliderDistanceInterval() {
final List<String> splitOptions = new ArrayList<>(distanceSplitOptions.keySet());
updateSliderMinMaxValues(splitOptions);
slider.setValue(selectedDistanceSplitInterval);
slider.addOnChangeListener(new Slider.OnChangeListener() {
@Override
public void onValueChange(@NonNull Slider slider, float value, boolean fromUser) {
if (fromUser) {
selectedDistanceSplitInterval = (int) value;
selectedSplitValue.setText(splitOptions.get(selectedDistanceSplitInterval));
}
}
});
selectedSplitValue.setText(splitOptions.get(selectedDistanceSplitInterval));
}
private void updateSliderMinMaxValues(List<String> splitOptions) {
int valueFrom = 0;
int valueTo = splitOptions.size() - 1;
slider.setValueTo(valueTo);
slider.setValueFrom(valueFrom);
splitValueMin.setText(splitOptions.get(valueFrom));
splitValueMax.setText(splitOptions.get(valueTo));
}
@Override
protected int getRightBottomButtonTextId() {
return R.string.shared_string_apply;
}
@Override
protected void onRightBottomButtonClick() {
updateSplit();
applySelectedSplit();
dismiss();
}
private void updateSplit() {
double splitInterval = 0;
if (selectedSplitType == GpxSplitType.NO_SPLIT) {
splitInterval = 0;
} else if (selectedSplitType == GpxSplitType.DISTANCE) {
splitInterval = new ArrayList<>(distanceSplitOptions.values()).get(selectedDistanceSplitInterval);
} else if (selectedSplitType == GpxSplitType.TIME) {
splitInterval = new ArrayList<>(timeSplitOptions.values()).get(selectedTimeSplitInterval);
}
trackDrawInfo.setSplitType(selectedSplitType.getType());
trackDrawInfo.setSplitInterval(splitInterval);
}
private void applySelectedSplit() {
int timeSplit = new ArrayList<>(timeSplitOptions.values()).get(selectedTimeSplitInterval);
double distanceSplit = new ArrayList<>(distanceSplitOptions.values()).get(selectedDistanceSplitInterval);
SplitTrackListener splitTrackListener = new SplitTrackListener() {
@Override
public void trackSplittingStarted() {
}
@Override
public void trackSplittingFinished() {
if (selectedGpxFile != null) {
List<GpxDisplayGroup> groups = getDisplayGroups();
selectedGpxFile.setDisplayGroups(groups, app);
}
}
};
List<GpxDisplayGroup> groups = getDisplayGroups();
new SplitTrackAsyncTask(app, selectedSplitType, groups, splitTrackListener, trackDrawInfo.isJoinSegments(),
timeSplit, distanceSplit).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
@NonNull
public List<GpxDisplayGroup> getDisplayGroups() {
List<GpxDisplayGroup> groups = new ArrayList<>();
Fragment target = getTargetFragment();
if (target instanceof TrackAppearanceFragment) {
List<GpxDisplayGroup> result = ((TrackAppearanceFragment) target).getGpxDisplayGroups();
for (GpxDisplayGroup group : result) {
if (GpxDisplayItemType.TRACK_SEGMENT == group.getType()) {
groups.add(group);
}
}
}
return groups;
}
public static void showInstance(@NonNull FragmentManager fragmentManager, TrackDrawInfo trackDrawInfo, Fragment target) {
try {
if (fragmentManager.findFragmentByTag(SplitIntervalBottomSheet.TAG) == null) {
Bundle args = new Bundle();
args.putString(TRACK_FILE_PATH, trackDrawInfo.getFilePath());
SplitIntervalBottomSheet splitIntervalBottomSheet = new SplitIntervalBottomSheet();
splitIntervalBottomSheet.setArguments(args);
splitIntervalBottomSheet.setTargetFragment(target, 0);
splitIntervalBottomSheet.show(fragmentManager, SplitIntervalBottomSheet.TAG);
}
} catch (RuntimeException e) {
log.error("showInstance", e);
}
}
}

View file

@ -0,0 +1,41 @@
package net.osmand.plus.track;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.NonNull;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.routepreparationmenu.cards.BaseCard;
public class SplitIntervalCard extends BaseCard {
public SplitIntervalCard(@NonNull MapActivity mapActivity) {
super(mapActivity);
}
@Override
public int getCardLayoutId() {
return R.layout.bottom_sheet_item_with_right_descr;
}
@Override
protected void updateContent() {
AndroidUiHelper.updateVisibility(view.findViewById(R.id.icon), false);
TextView titleView = view.findViewById(R.id.title);
titleView.setText(R.string.gpx_split_interval);
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
CardListener listener = getListener();
if (listener != null) {
listener.onCardPressed(SplitIntervalCard.this);
}
}
});
}
}

View file

@ -0,0 +1,75 @@
package net.osmand.plus.track;
import android.os.AsyncTask;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import net.osmand.plus.GpxSelectionHelper;
import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup;
import net.osmand.plus.OsmandApplication;
import java.util.List;
public class SplitTrackAsyncTask extends AsyncTask<Void, Void, Void> {
private OsmandApplication app;
private GpxSplitType gpxSplitType;
private List<GpxDisplayGroup> groups;
private SplitTrackListener splitTrackListener;
private boolean joinSegments;
private int timeSplitInterval;
private double distanceSplitInterval;
public SplitTrackAsyncTask(@NonNull OsmandApplication app,
@NonNull GpxSplitType gpxSplitType,
@NonNull List<GpxDisplayGroup> groups,
@Nullable SplitTrackListener splitTrackListener,
boolean joinSegments,
int timeSplitInterval,
double distanceSplitInterval) {
this.app = app;
this.groups = groups;
this.gpxSplitType = gpxSplitType;
this.splitTrackListener = splitTrackListener;
this.joinSegments = joinSegments;
this.timeSplitInterval = timeSplitInterval;
this.distanceSplitInterval = distanceSplitInterval;
}
@Override
protected void onPreExecute() {
if (splitTrackListener != null) {
splitTrackListener.trackSplittingStarted();
}
}
@Override
protected Void doInBackground(Void... params) {
for (GpxSelectionHelper.GpxDisplayGroup model : groups) {
if (gpxSplitType == GpxSplitType.NO_SPLIT) {
model.noSplit(app);
} else if (gpxSplitType == GpxSplitType.DISTANCE && distanceSplitInterval > 0) {
model.splitByDistance(app, distanceSplitInterval, joinSegments);
} else if (gpxSplitType == GpxSplitType.TIME && timeSplitInterval > 0) {
model.splitByTime(app, timeSplitInterval, joinSegments);
}
}
return null;
}
@Override
protected void onPostExecute(Void result) {
if (splitTrackListener != null) {
splitTrackListener.trackSplittingFinished();
}
}
public interface SplitTrackListener {
void trackSplittingStarted();
void trackSplittingFinished();
}
}

View file

@ -0,0 +1,436 @@
package net.osmand.plus.track;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import androidx.annotation.NonNull;
import androidx.fragment.app.FragmentManager;
import net.osmand.AndroidUtils;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.PlatformUtil;
import net.osmand.plus.GPXDatabase.GpxDataItem;
import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup;
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.UiUtilities.DialogButtonType;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.base.ContextMenuFragment;
import net.osmand.plus.dialogs.GpxAppearanceAdapter;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.routepreparationmenu.cards.BaseCard;
import net.osmand.plus.routepreparationmenu.cards.BaseCard.CardListener;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.render.RenderingRulesStorage;
import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import static net.osmand.plus.dialogs.ConfigureMapMenu.CURRENT_TRACK_COLOR_ATTR;
import static net.osmand.plus.track.TrackDrawInfo.TRACK_FILE_PATH;
public class TrackAppearanceFragment extends ContextMenuFragment implements CardListener {
public static final String TAG = TrackAppearanceFragment.class.getName();
private static final Log log = PlatformUtil.getLog(TrackAppearanceFragment.class);
private OsmandApplication app;
private GpxDataItem gpxDataItem;
private TrackDrawInfo trackDrawInfo;
private SelectedGpxFile selectedGpxFile;
private List<GpxDisplayGroup> displayGroups;
private ImageView appearanceIcon;
private int menuTitleHeight;
private long modifiedTime = -1;
private TrackWidthCard trackWidthCard;
@Override
public int getMainLayoutId() {
return R.layout.track_appearance;
}
@Override
public int getHeaderViewHeight() {
return menuTitleHeight;
}
@Override
public boolean isHeaderViewDetached() {
return false;
}
@Override
public int getToolbarHeight() {
return 0;
}
public float getMiddleStateKoef() {
return 0.5f;
}
public TrackDrawInfo getTrackDrawInfo() {
return trackDrawInfo;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
app = requireMyApplication();
Bundle arguments = getArguments();
if (savedInstanceState != null) {
trackDrawInfo = new TrackDrawInfo();
trackDrawInfo.readBundle(savedInstanceState);
gpxDataItem = app.getGpxDbHelper().getItem(new File(trackDrawInfo.getFilePath()));
selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(trackDrawInfo.getFilePath());
} else if (arguments != null) {
String gpxFilePath = arguments.getString(TRACK_FILE_PATH);
selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(gpxFilePath);
File file = new File(selectedGpxFile.getGpxFile().path);
gpxDataItem = app.getGpxDbHelper().getItem(file);
trackDrawInfo = new TrackDrawInfo(gpxDataItem);
updateTrackColor();
}
}
private void updateTrackColor() {
int color = gpxDataItem != null ? gpxDataItem.getColor() : 0;
GPXFile gpxFile = selectedGpxFile.getGpxFile();
if (color == 0 && gpxFile != null) {
if (gpxFile.showCurrentTrack) {
color = app.getSettings().CURRENT_TRACK_COLOR.get();
} else {
color = gpxFile.getColor(0);
}
}
if (color == 0) {
RenderingRulesStorage renderer = app.getRendererRegistry().getCurrentSelectedRenderer();
OsmandSettings.CommonPreference<String> prefColor = app.getSettings().getCustomRenderProperty(CURRENT_TRACK_COLOR_ATTR);
color = GpxAppearanceAdapter.parseTrackColor(renderer, prefColor.get());
}
trackDrawInfo.setColor(color);
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = super.onCreateView(inflater, container, savedInstanceState);
if (view != null) {
appearanceIcon = view.findViewById(R.id.appearance_icon);
if (isPortrait()) {
updateCardsLayout();
}
updateCards();
updateButtons(view);
updateAppearanceIcon();
if (!isPortrait()) {
int widthNoShadow = getLandscapeNoShadowWidth();
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(widthNoShadow, ViewGroup.LayoutParams.WRAP_CONTENT);
params.gravity = Gravity.BOTTOM | Gravity.START;
view.findViewById(R.id.control_buttons).setLayoutParams(params);
}
runLayoutListener();
}
return view;
}
@Override
protected void calculateLayout(View view, boolean initLayout) {
menuTitleHeight = view.findViewById(R.id.route_menu_top_shadow_all).getHeight()
+ view.findViewById(R.id.control_buttons).getHeight()
- view.findViewById(R.id.buttons_shadow).getHeight();
super.calculateLayout(view, initLayout);
}
@Override
protected void setViewY(int y, boolean animated, boolean adjustMapPos) {
super.setViewY(y, animated, adjustMapPos);
updateStatusBarColor();
}
@Override
protected void updateMainViewLayout(int posY) {
super.updateMainViewLayout(posY);
updateStatusBarColor();
}
@Override
public void onResume() {
super.onResume();
MapActivity mapActivity = getMapActivity();
if (mapActivity != null) {
mapActivity.getMapLayers().getGpxLayer().setTrackDrawInfo(trackDrawInfo);
}
}
@Override
public void onPause() {
super.onPause();
MapActivity mapActivity = getMapActivity();
if (mapActivity != null) {
mapActivity.getMapLayers().getGpxLayer().setTrackDrawInfo(null);
}
}
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
trackDrawInfo.saveToBundle(outState);
}
@Override
public int getStatusBarColorId() {
View view = getView();
if (view != null) {
boolean nightMode = isNightMode();
if (getViewY() <= getFullScreenTopPosY() || !isPortrait()) {
if (Build.VERSION.SDK_INT >= 23 && !nightMode) {
view.setSystemUiVisibility(view.getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
}
return nightMode ? R.color.divider_color_dark : R.color.divider_color_light;
} else {
if (Build.VERSION.SDK_INT >= 23 && !nightMode) {
view.setSystemUiVisibility(view.getSystemUiVisibility() & ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
}
}
}
return -1;
}
private void updateStatusBarColor() {
MapActivity mapActivity = getMapActivity();
if (mapActivity != null) {
mapActivity.updateStatusBarColor();
}
}
@Override
public void onCardLayoutNeeded(@NonNull BaseCard card) {
}
@Override
public void onCardPressed(@NonNull BaseCard card) {
MapActivity mapActivity = getMapActivity();
if (mapActivity != null) {
if (card instanceof SplitIntervalCard) {
SplitIntervalBottomSheet.showInstance(mapActivity.getSupportFragmentManager(), trackDrawInfo, this);
} else if (card instanceof TrackColoringCard) {
updateAppearanceIcon();
if (trackWidthCard != null) {
trackWidthCard.updateItems();
}
}
}
}
@Override
public void onCardButtonPressed(@NonNull BaseCard card, int buttonIndex) {
}
private void updateAppearanceIcon() {
Drawable icon = getPaintedContentIcon(R.drawable.ic_action_gpx_width_bold, trackDrawInfo.getColor());
appearanceIcon.setImageDrawable(icon);
}
private void updateCardsLayout() {
View mainView = getMainView();
if (mainView != null) {
LinearLayout cardsContainer = getCardsContainer();
View topShadow = getTopShadow();
FrameLayout bottomContainer = getBottomContainer();
if (getCurrentMenuState() == MenuState.HEADER_ONLY) {
topShadow.setVisibility(View.INVISIBLE);
bottomContainer.setBackgroundDrawable(null);
AndroidUtils.setBackground(mainView.getContext(), cardsContainer, isNightMode(), R.drawable.travel_card_bg_light, R.drawable.travel_card_bg_dark);
} else {
topShadow.setVisibility(View.VISIBLE);
AndroidUtils.setBackground(mainView.getContext(), bottomContainer, isNightMode(), R.color.card_and_list_background_light, R.color.card_and_list_background_dark);
AndroidUtils.setBackground(mainView.getContext(), cardsContainer, isNightMode(), R.color.card_and_list_background_light, R.color.card_and_list_background_dark);
}
}
}
private void updateButtons(View view) {
View buttonsContainer = view.findViewById(R.id.buttons_container);
buttonsContainer.setBackgroundColor(AndroidUtils.getColorFromAttr(view.getContext(), R.attr.route_info_bg));
View saveButton = view.findViewById(R.id.right_bottom_button);
saveButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
saveTrackInfo();
dismiss();
}
});
View cancelButton = view.findViewById(R.id.dismiss_button);
cancelButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
discardChanges();
dismiss();
}
});
UiUtilities.setupDialogButton(isNightMode(), cancelButton, DialogButtonType.SECONDARY, R.string.shared_string_cancel);
UiUtilities.setupDialogButton(isNightMode(), saveButton, DialogButtonType.PRIMARY, R.string.shared_string_apply);
AndroidUiHelper.updateVisibility(saveButton, true);
AndroidUiHelper.updateVisibility(view.findViewById(R.id.buttons_divider), true);
}
private void saveTrackInfo() {
GPXFile gpxFile = selectedGpxFile.getGpxFile();
gpxFile.setWidth(trackDrawInfo.getWidth());
if (trackDrawInfo.getGradientScaleType() != null) {
gpxFile.setGradientScaleType(trackDrawInfo.getGradientScaleType().name());
} else {
gpxFile.removeGradientScaleType();
}
gpxFile.setColor(trackDrawInfo.getColor());
GpxSplitType splitType = GpxSplitType.getSplitTypeByTypeId(trackDrawInfo.getSplitType());
if (splitType != null) {
gpxFile.setSplitType(splitType.getTypeName());
}
gpxFile.setSplitInterval(trackDrawInfo.getSplitInterval());
gpxFile.setShowArrows(trackDrawInfo.isShowArrows());
gpxFile.setShowStartFinish(trackDrawInfo.isShowStartFinish());
app.getSelectedGpxHelper().updateSelectedGpxFile(selectedGpxFile);
gpxDataItem = new GpxDataItem(new File(gpxFile.path), gpxFile);
app.getGpxDbHelper().add(gpxDataItem);
saveGpx(gpxFile);
}
private void discardChanges() {
if (gpxDataItem.getSplitType() != trackDrawInfo.getSplitType() || gpxDataItem.getSplitInterval() != trackDrawInfo.getSplitInterval()) {
int timeSplit = (int) gpxDataItem.getSplitInterval();
double distanceSplit = gpxDataItem.getSplitInterval();
GpxSplitType splitType = GpxSplitType.getSplitTypeByTypeId(gpxDataItem.getSplitType());
if (splitType == null) {
splitType = GpxSplitType.NO_SPLIT;
}
SplitTrackAsyncTask.SplitTrackListener splitTrackListener = new SplitTrackAsyncTask.SplitTrackListener() {
@Override
public void trackSplittingStarted() {
}
@Override
public void trackSplittingFinished() {
if (selectedGpxFile != null) {
List<GpxDisplayGroup> groups = getGpxDisplayGroups();
selectedGpxFile.setDisplayGroups(groups, app);
}
}
};
List<GpxDisplayGroup> groups = getGpxDisplayGroups();
new SplitTrackAsyncTask(app, splitType, groups, splitTrackListener, trackDrawInfo.isJoinSegments(),
timeSplit, distanceSplit).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
}
private void saveGpx(final GPXFile gpxFile) {
new SaveGpxAsyncTask(gpxFile, new SaveGpxAsyncTask.SaveGpxListener() {
@Override
public void gpxSavingStarted() {
}
@Override
public void gpxSavingFinished(Exception errorMessage) {
if (errorMessage == null) {
app.showShortToastMessage(R.string.shared_string_track_is_saved, Algorithms.getFileWithoutDirs(gpxFile.path));
}
}
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
private void updateCards() {
MapActivity mapActivity = getMapActivity();
if (mapActivity != null) {
ViewGroup cardsContainer = getCardsContainer();
cardsContainer.removeAllViews();
SplitIntervalCard splitIntervalCard = new SplitIntervalCard(mapActivity);
splitIntervalCard.setListener(this);
cardsContainer.addView(splitIntervalCard.build(mapActivity));
DirectionArrowsCard directionArrowsCard = new DirectionArrowsCard(mapActivity, trackDrawInfo);
cardsContainer.addView(directionArrowsCard.build(mapActivity));
TrackColoringCard trackColoringCard = new TrackColoringCard(mapActivity, trackDrawInfo);
trackColoringCard.setListener(this);
cardsContainer.addView(trackColoringCard.build(mapActivity));
trackWidthCard = new TrackWidthCard(mapActivity, trackDrawInfo);
cardsContainer.addView(trackWidthCard.build(mapActivity));
}
}
public List<GpxDisplayGroup> getGpxDisplayGroups() {
GPXFile gpxFile = selectedGpxFile.getGpxFile();
if (gpxFile == null) {
return new ArrayList<>();
}
if (gpxFile.modifiedTime != modifiedTime) {
modifiedTime = gpxFile.modifiedTime;
displayGroups = app.getSelectedGpxHelper().collectDisplayGroups(gpxFile);
if (selectedGpxFile.getDisplayGroups(app) != null) {
displayGroups = selectedGpxFile.getDisplayGroups(app);
}
}
return displayGroups;
}
public void dismissImmediate() {
MapActivity mapActivity = getMapActivity();
if (mapActivity != null) {
try {
mapActivity.getSupportFragmentManager().popBackStackImmediate(TAG, FragmentManager.POP_BACK_STACK_INCLUSIVE);
} catch (Exception e) {
log.error(e);
}
}
}
public static boolean showInstance(@NonNull MapActivity mapActivity, TrackAppearanceFragment fragment) {
try {
mapActivity.getSupportFragmentManager()
.beginTransaction()
.replace(R.id.fragmentContainer, fragment, fragment.getFragmentTag())
.addToBackStack(fragment.getFragmentTag())
.commitAllowingStateLoss();
return true;
} catch (RuntimeException e) {
return false;
}
}
}

View file

@ -0,0 +1,23 @@
package net.osmand.plus.track;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import net.osmand.plus.R;
public class TrackAppearanceViewHolder extends RecyclerView.ViewHolder {
final TextView title;
final ImageView icon;
final ImageView button;
TrackAppearanceViewHolder(View itemView) {
super(itemView);
title = itemView.findViewById(R.id.groupName);
icon = itemView.findViewById(R.id.groupIcon);
button = itemView.findViewById(R.id.outlineRect);
}
}

View file

@ -0,0 +1,284 @@
package net.osmand.plus.track;
import android.graphics.drawable.GradientDrawable;
import android.os.Build;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.ColorInt;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.appcompat.content.res.AppCompatResources;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import net.osmand.AndroidUtils;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.dialogs.GpxAppearanceAdapter.AppearanceListItem;
import net.osmand.plus.dialogs.GpxAppearanceAdapter.GpxAppearanceAdapterType;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.routepreparationmenu.cards.BaseCard;
import net.osmand.plus.widgets.FlowLayout;
import java.util.ArrayList;
import java.util.List;
import static net.osmand.plus.dialogs.GpxAppearanceAdapter.getAppearanceItems;
public class TrackColoringCard extends BaseCard {
private final static String SOLID_COLOR = "solid_color";
private TrackDrawInfo trackDrawInfo;
private TrackColoringAdapter coloringAdapter;
private TrackAppearanceItem selectedAppearanceItem;
private List<TrackAppearanceItem> appearanceItems;
public TrackColoringCard(MapActivity mapActivity, TrackDrawInfo trackDrawInfo) {
super(mapActivity);
this.trackDrawInfo = trackDrawInfo;
appearanceItems = getGradientAppearanceItems();
}
@Override
public int getCardLayoutId() {
return R.layout.track_coloring_card;
}
@Override
protected void updateContent() {
updateHeader();
createColorSelector();
updateColorSelector();
coloringAdapter = new TrackColoringAdapter(appearanceItems);
RecyclerView groupRecyclerView = view.findViewById(R.id.recycler_view);
groupRecyclerView.setAdapter(coloringAdapter);
groupRecyclerView.setLayoutManager(new LinearLayoutManager(app, RecyclerView.HORIZONTAL, false));
AndroidUiHelper.updateVisibility(view.findViewById(R.id.top_divider), isShowDivider());
}
private List<TrackAppearanceItem> getGradientAppearanceItems() {
List<TrackAppearanceItem> items = new ArrayList<>();
items.add(new TrackAppearanceItem(SOLID_COLOR, app.getString(R.string.track_coloring_solid), R.drawable.ic_action_circle));
// for (GradientScaleType scaleType : GradientScaleType.values()) {
// items.add(new TrackAppearanceItem(scaleType.getTypeName(), scaleType.getHumanString(app), scaleType.getIconId()));
// }
return items;
}
private void createColorSelector() {
FlowLayout selectColor = view.findViewById(R.id.select_color);
List<Integer> colors = new ArrayList<>();
for (AppearanceListItem appearanceListItem : getAppearanceItems(app, GpxAppearanceAdapterType.TRACK_COLOR)) {
if (!colors.contains(appearanceListItem.getColor())) {
colors.add(appearanceListItem.getColor());
}
}
for (int color : colors) {
selectColor.addView(createColorItemView(color, selectColor), new FlowLayout.LayoutParams(0, 0));
}
updateColorSelector(trackDrawInfo.getColor(), selectColor);
}
private View createColorItemView(@ColorInt final int color, final FlowLayout rootView) {
FrameLayout colorItemView = (FrameLayout) UiUtilities.getInflater(rootView.getContext(), nightMode)
.inflate(R.layout.point_editor_button, rootView, false);
ImageView outline = colorItemView.findViewById(R.id.outline);
outline.setImageDrawable(
UiUtilities.tintDrawable(AppCompatResources.getDrawable(app, R.drawable.bg_point_circle_contour),
ContextCompat.getColor(app,
nightMode ? R.color.stroked_buttons_and_links_outline_dark
: R.color.stroked_buttons_and_links_outline_light)));
ImageView backgroundCircle = colorItemView.findViewById(R.id.background);
backgroundCircle.setImageDrawable(UiUtilities.tintDrawable(AppCompatResources.getDrawable(app, R.drawable.bg_point_circle), color));
backgroundCircle.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
updateColorSelector(color, rootView);
coloringAdapter.notifyDataSetChanged();
trackDrawInfo.setColor(color);
CardListener listener = getListener();
if (listener != null) {
listener.onCardPressed(TrackColoringCard.this);
}
}
});
colorItemView.setTag(color);
return colorItemView;
}
private void updateColorSelector(int color, View rootView) {
View oldColor = rootView.findViewWithTag(trackDrawInfo.getColor());
if (oldColor != null) {
oldColor.findViewById(R.id.outline).setVisibility(View.INVISIBLE);
ImageView icon = oldColor.findViewById(R.id.icon);
icon.setImageDrawable(UiUtilities.tintDrawable(icon.getDrawable(), R.color.icon_color_default_light));
}
View newColor = rootView.findViewWithTag(color);
if (newColor != null) {
newColor.findViewById(R.id.outline).setVisibility(View.VISIBLE);
}
mapActivity.refreshMap();
}
private TrackAppearanceItem getSelectedAppearanceItem() {
if (selectedAppearanceItem == null) {
GradientScaleType scaleType = trackDrawInfo.getGradientScaleType();
for (TrackAppearanceItem item : appearanceItems) {
if (scaleType == null && item.getAttrName().equals(SOLID_COLOR)
|| scaleType != null && scaleType.getTypeName().equals(item.getAttrName())) {
selectedAppearanceItem = item;
break;
}
}
}
return selectedAppearanceItem;
}
private void updateHeader() {
AndroidUiHelper.updateVisibility(view.findViewById(R.id.icon), false);
TextView titleView = view.findViewById(R.id.title);
titleView.setText(R.string.select_color);
TextView descriptionView = view.findViewById(R.id.description);
descriptionView.setText(getSelectedAppearanceItem().getLocalizedValue());
}
private void updateColorSelector() {
boolean visible = getSelectedAppearanceItem().getAttrName().equals(SOLID_COLOR);
AndroidUiHelper.updateVisibility(view.findViewById(R.id.select_color), visible);
}
public void setGradientScaleType(TrackAppearanceItem item) {
if (item.getAttrName().equals(SOLID_COLOR)) {
trackDrawInfo.setGradientScaleType(null);
} else {
trackDrawInfo.setGradientScaleType(GradientScaleType.valueOf(item.getAttrName()));
}
mapActivity.refreshMap();
updateHeader();
updateColorSelector();
}
private class TrackColoringAdapter extends RecyclerView.Adapter<TrackAppearanceViewHolder> {
private List<TrackAppearanceItem> items;
private TrackColoringAdapter(List<TrackAppearanceItem> items) {
this.items = items;
}
@NonNull
@Override
public TrackAppearanceViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater themedInflater = UiUtilities.getInflater(parent.getContext(), nightMode);
View view = themedInflater.inflate(R.layout.point_editor_group_select_item, parent, false);
view.getLayoutParams().width = app.getResources().getDimensionPixelSize(R.dimen.gpx_group_button_width);
view.getLayoutParams().height = app.getResources().getDimensionPixelSize(R.dimen.gpx_group_button_height);
TrackAppearanceViewHolder holder = new TrackAppearanceViewHolder(view);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
AndroidUtils.setBackground(app, holder.button, nightMode, R.drawable.ripple_solid_light_6dp,
R.drawable.ripple_solid_dark_6dp);
}
return holder;
}
@Override
public void onBindViewHolder(@NonNull final TrackAppearanceViewHolder holder, int position) {
TrackAppearanceItem item = items.get(position);
holder.title.setText(item.getLocalizedValue());
updateButtonBg(holder, item);
int colorId;
if (item.getAttrName().equals(SOLID_COLOR)) {
colorId = trackDrawInfo.getColor();
} else if (item.getAttrName().equals(getSelectedAppearanceItem().getAttrName())) {
colorId = ContextCompat.getColor(app, nightMode ? R.color.icon_color_active_dark : R.color.icon_color_active_light);
} else {
colorId = AndroidUtils.getColorFromAttr(holder.itemView.getContext(), R.attr.default_icon_color);
}
holder.icon.setImageDrawable(app.getUIUtilities().getPaintedIcon(item.getIconId(), colorId));
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int prevSelectedPosition = getItemPosition(getSelectedAppearanceItem());
selectedAppearanceItem = items.get(holder.getAdapterPosition());
notifyItemChanged(holder.getAdapterPosition());
notifyItemChanged(prevSelectedPosition);
setGradientScaleType(selectedAppearanceItem);
}
});
}
private void updateButtonBg(TrackAppearanceViewHolder holder, TrackAppearanceItem item) {
GradientDrawable rectContourDrawable = (GradientDrawable) AppCompatResources.getDrawable(app, R.drawable.bg_select_group_button_outline);
if (rectContourDrawable != null) {
if (getSelectedAppearanceItem() != null && getSelectedAppearanceItem().equals(item)) {
int strokeColor = ContextCompat.getColor(app, nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light);
rectContourDrawable.setStroke(AndroidUtils.dpToPx(app, 2), strokeColor);
} else {
int strokeColor = ContextCompat.getColor(app, nightMode ? R.color.stroked_buttons_and_links_outline_dark
: R.color.stroked_buttons_and_links_outline_light);
rectContourDrawable.setStroke(AndroidUtils.dpToPx(app, 1), strokeColor);
}
holder.button.setImageDrawable(rectContourDrawable);
}
}
@Override
public int getItemCount() {
return items.size();
}
int getItemPosition(TrackAppearanceItem name) {
return items.indexOf(name);
}
}
public static class TrackAppearanceItem {
private String attrName;
private String localizedValue;
@DrawableRes
private int iconId;
public TrackAppearanceItem(String attrName, String localizedValue, int iconId) {
this.attrName = attrName;
this.localizedValue = localizedValue;
this.iconId = iconId;
}
public String getAttrName() {
return attrName;
}
public String getLocalizedValue() {
return localizedValue;
}
public int getIconId() {
return iconId;
}
}
}

View file

@ -0,0 +1,134 @@
package net.osmand.plus.track;
import android.os.Bundle;
import androidx.annotation.NonNull;
import net.osmand.plus.GPXDatabase.GpxDataItem;
import net.osmand.util.Algorithms;
public class TrackDrawInfo {
public static final String TRACK_FILE_PATH = "track_file_path";
private static final String TRACK_WIDTH = "track_width";
private static final String TRACK_GRADIENT_SCALE_TYPE = "track_gradient_scale_type";
private static final String TRACK_COLOR = "track_color";
private static final String TRACK_SPLIT_TYPE = "track_split_type";
private static final String TRACK_SPLIT_INTERVAL = "track_split_interval";
private static final String TRACK_JOIN_SEGMENTS = "track_join_segments";
private static final String TRACK_SHOW_ARROWS = "track_show_arrows";
private static final String TRACK_SHOW_START_FINISH = "track_show_start_finish";
private String filePath;
private String width;
private GradientScaleType gradientScaleType;
private int color;
private int splitType;
private double splitInterval;
private boolean joinSegments;
private boolean showArrows;
private boolean showStartFinish;
public TrackDrawInfo() {
}
public TrackDrawInfo(GpxDataItem gpxDataItem) {
filePath = gpxDataItem.getFile().getPath();
width = gpxDataItem.getWidth();
gradientScaleType = gpxDataItem.getGradientScaleType();
color = gpxDataItem.getColor();
splitType = gpxDataItem.getSplitType();
splitInterval = gpxDataItem.getSplitInterval();
joinSegments = gpxDataItem.isJoinSegments();
showArrows = gpxDataItem.isShowArrows();
showStartFinish = gpxDataItem.isShowStartFinish();
}
public String getFilePath() {
return filePath;
}
public String getWidth() {
return width;
}
public void setWidth(String width) {
this.width = width;
}
public GradientScaleType getGradientScaleType() {
return gradientScaleType;
}
public void setGradientScaleType(GradientScaleType gradientScaleType) {
this.gradientScaleType = gradientScaleType;
}
public int getColor() {
return color;
}
public void setColor(int color) {
this.color = color;
}
public int getSplitType() {
return splitType;
}
public void setSplitType(int splitType) {
this.splitType = splitType;
}
public double getSplitInterval() {
return splitInterval;
}
public void setSplitInterval(double splitInterval) {
this.splitInterval = splitInterval;
}
public boolean isJoinSegments() {
return joinSegments;
}
public boolean isShowArrows() {
return showArrows;
}
public void setShowArrows(boolean showArrows) {
this.showArrows = showArrows;
}
public boolean isShowStartFinish() {
return showStartFinish;
}
protected void readBundle(@NonNull Bundle bundle) {
filePath = bundle.getString(TRACK_FILE_PATH);
width = bundle.getString(TRACK_WIDTH);
String gradientScaleTypeName = bundle.getString(TRACK_GRADIENT_SCALE_TYPE);
if (!Algorithms.isEmpty(gradientScaleTypeName)) {
gradientScaleType = GradientScaleType.valueOf(gradientScaleTypeName);
}
color = bundle.getInt(TRACK_COLOR);
splitType = bundle.getInt(TRACK_SPLIT_TYPE);
splitInterval = bundle.getDouble(TRACK_SPLIT_INTERVAL);
joinSegments = bundle.getBoolean(TRACK_JOIN_SEGMENTS);
showArrows = bundle.getBoolean(TRACK_SHOW_ARROWS);
showStartFinish = bundle.getBoolean(TRACK_SHOW_START_FINISH);
}
protected void saveToBundle(@NonNull Bundle bundle) {
bundle.putString(TRACK_FILE_PATH, filePath);
bundle.putString(TRACK_WIDTH, width);
bundle.putString(TRACK_GRADIENT_SCALE_TYPE, gradientScaleType != null ? gradientScaleType.getTypeName() : "");
bundle.putInt(TRACK_COLOR, color);
bundle.putInt(TRACK_SPLIT_TYPE, splitType);
bundle.putDouble(TRACK_SPLIT_INTERVAL, splitInterval);
bundle.putBoolean(TRACK_JOIN_SEGMENTS, joinSegments);
bundle.putBoolean(TRACK_SHOW_ARROWS, showArrows);
bundle.putBoolean(TRACK_SHOW_START_FINISH, showStartFinish);
}
}

View file

@ -0,0 +1,239 @@
package net.osmand.plus.track;
import android.graphics.drawable.GradientDrawable;
import android.os.Build;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.content.res.AppCompatResources;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.slider.Slider;
import net.osmand.AndroidUtils;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.dialogs.GpxAppearanceAdapter;
import net.osmand.plus.dialogs.GpxAppearanceAdapter.AppearanceListItem;
import net.osmand.plus.dialogs.GpxAppearanceAdapter.GpxAppearanceAdapterType;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.routepreparationmenu.cards.BaseCard;
import net.osmand.util.Algorithms;
import java.util.List;
public class TrackWidthCard extends BaseCard {
private final static String CUSTOM_WIDTH = "custom_width";
private final static int CUSTOM_WIDTH_MIN = 1;
private final static int CUSTOM_WIDTH_MAX = 24;
private TrackDrawInfo trackDrawInfo;
private AppearanceListItem selectedItem;
private List<AppearanceListItem> appearanceItems;
private GpxWidthAdapter widthAdapter;
public TrackWidthCard(MapActivity mapActivity, TrackDrawInfo trackDrawInfo) {
super(mapActivity);
this.trackDrawInfo = trackDrawInfo;
appearanceItems = getWidthAppearanceItems();
}
@Override
public int getCardLayoutId() {
return R.layout.track_width_card;
}
@Override
protected void updateContent() {
updateHeader();
updateCustomWidthSlider();
widthAdapter = new GpxWidthAdapter(appearanceItems);
RecyclerView groupRecyclerView = view.findViewById(R.id.recycler_view);
groupRecyclerView.setAdapter(widthAdapter);
groupRecyclerView.setLayoutManager(new LinearLayoutManager(app, RecyclerView.HORIZONTAL, false));
AndroidUiHelper.updateVisibility(view.findViewById(R.id.top_divider), isShowDivider());
}
public void updateItems() {
if (widthAdapter != null) {
widthAdapter.notifyDataSetChanged();
}
}
private AppearanceListItem getSelectedItem() {
if (selectedItem == null) {
String selectedWidth = trackDrawInfo.getWidth();
for (AppearanceListItem item : appearanceItems) {
if (Algorithms.objectEquals(item.getValue(), selectedWidth)
|| Algorithms.isEmpty(selectedWidth) && Algorithms.isEmpty(item.getValue())
|| Algorithms.isInt(selectedWidth) && CUSTOM_WIDTH.equals(item.getAttrName())) {
selectedItem = item;
break;
}
}
}
return selectedItem;
}
private List<AppearanceListItem> getWidthAppearanceItems() {
List<AppearanceListItem> items = GpxAppearanceAdapter.getAppearanceItems(app, GpxAppearanceAdapterType.TRACK_WIDTH);
String selectedWidth = trackDrawInfo.getWidth();
String customWidth = !Algorithms.isEmpty(selectedWidth) && Algorithms.isInt(selectedWidth) ? selectedWidth : String.valueOf(CUSTOM_WIDTH_MIN);
items.add(new AppearanceListItem(CUSTOM_WIDTH, customWidth, app.getString(R.string.shared_string_custom)));
return items;
}
private void updateHeader() {
AndroidUiHelper.updateVisibility(view.findViewById(R.id.icon), false);
TextView titleView = view.findViewById(R.id.title);
titleView.setText(R.string.select_track_width);
TextView descriptionView = view.findViewById(R.id.description);
descriptionView.setText(getSelectedItem().getLocalizedValue());
}
private void updateCustomWidthSlider() {
if (CUSTOM_WIDTH.equals(getSelectedItem().getAttrName())) {
Slider widthSlider = view.findViewById(R.id.width_slider);
widthSlider.setValueTo(CUSTOM_WIDTH_MAX);
widthSlider.setValueFrom(CUSTOM_WIDTH_MIN);
((TextView) view.findViewById(R.id.width_value_min)).setText(String.valueOf(CUSTOM_WIDTH_MIN));
((TextView) view.findViewById(R.id.width_value_max)).setText(String.valueOf(CUSTOM_WIDTH_MAX));
String width = getSelectedItem().getValue();
if (!Algorithms.isEmpty(width) && Algorithms.isInt(width)) {
try {
widthSlider.setValue(Integer.parseInt(width));
} catch (NumberFormatException e) {
widthSlider.setValue(1);
}
} else {
widthSlider.setValue(1);
}
final TextView selectedCustomWidth = view.findViewById(R.id.width_value_tv);
widthSlider.addOnChangeListener(new Slider.OnChangeListener() {
@Override
public void onValueChange(@NonNull Slider slider, float value, boolean fromUser) {
if (fromUser) {
String valueStr = String.valueOf((int) value);
selectedCustomWidth.setText(valueStr);
getSelectedItem().setValue(valueStr);
setGpxWidth(valueStr);
}
}
});
UiUtilities.setupSlider(widthSlider, nightMode, null);
AndroidUiHelper.updateVisibility(view.findViewById(R.id.slider_container), true);
} else {
AndroidUiHelper.updateVisibility(view.findViewById(R.id.slider_container), false);
}
}
private void setGpxWidth(String width) {
trackDrawInfo.setWidth(width);
mapActivity.refreshMap();
}
private class GpxWidthAdapter extends RecyclerView.Adapter<TrackAppearanceViewHolder> {
private List<AppearanceListItem> items;
private GpxWidthAdapter(List<AppearanceListItem> items) {
this.items = items;
}
@NonNull
@Override
public TrackAppearanceViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater themedInflater = UiUtilities.getInflater(parent.getContext(), nightMode);
View view = themedInflater.inflate(R.layout.point_editor_group_select_item, parent, false);
view.getLayoutParams().width = app.getResources().getDimensionPixelSize(R.dimen.gpx_group_button_width);
view.getLayoutParams().height = app.getResources().getDimensionPixelSize(R.dimen.gpx_group_button_height);
TrackAppearanceViewHolder holder = new TrackAppearanceViewHolder(view);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
AndroidUtils.setBackground(app, holder.button, nightMode, R.drawable.ripple_solid_light_6dp,
R.drawable.ripple_solid_dark_6dp);
}
return holder;
}
@Override
public void onBindViewHolder(@NonNull final TrackAppearanceViewHolder holder, int position) {
AppearanceListItem item = items.get(position);
holder.title.setText(item.getLocalizedValue());
updateButtonBg(holder, item);
updateWidthIcon(holder, item);
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int prevSelectedPosition = getItemPosition(getSelectedItem());
selectedItem = items.get(holder.getAdapterPosition());
notifyItemChanged(holder.getAdapterPosition());
notifyItemChanged(prevSelectedPosition);
setGpxWidth(selectedItem.getValue());
updateHeader();
updateCustomWidthSlider();
}
});
}
private void updateWidthIcon(TrackAppearanceViewHolder holder, AppearanceListItem item) {
int color = trackDrawInfo.getColor();
int iconId;
if (CUSTOM_WIDTH.equals(item.getAttrName())) {
iconId = R.drawable.ic_action_settings;
color = AndroidUtils.getColorFromAttr(holder.itemView.getContext(), R.attr.active_color_basic);
} else {
iconId = GpxAppearanceAdapter.getWidthIconId(item.getValue());
}
holder.icon.setImageDrawable(app.getUIUtilities().getPaintedIcon(iconId, color));
}
private void updateButtonBg(TrackAppearanceViewHolder holder, AppearanceListItem item) {
GradientDrawable rectContourDrawable = (GradientDrawable) AppCompatResources.getDrawable(app, R.drawable.bg_select_group_button_outline);
if (rectContourDrawable != null) {
if (getSelectedItem() != null && getSelectedItem().equals(item)) {
int strokeColor = ContextCompat.getColor(app, nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light);
rectContourDrawable.setStroke(AndroidUtils.dpToPx(app, 2), strokeColor);
} else {
int strokeColor = ContextCompat.getColor(app, nightMode ? R.color.stroked_buttons_and_links_outline_dark
: R.color.stroked_buttons_and_links_outline_light);
rectContourDrawable.setStroke(AndroidUtils.dpToPx(app, 1), strokeColor);
}
holder.button.setImageDrawable(rectContourDrawable);
}
}
@Override
public int getItemCount() {
return items.size();
}
int getItemPosition(AppearanceListItem name) {
return items.indexOf(name);
}
}
}

View file

@ -48,9 +48,11 @@ import net.osmand.plus.UiUtilities;
import net.osmand.plus.base.PointImageDrawable;
import net.osmand.plus.mapcontextmenu.controllers.SelectedGpxMenuController.SelectedGpxPoint;
import net.osmand.plus.mapcontextmenu.other.TrackChartPoints;
import net.osmand.plus.track.SaveGpxAsyncTask;
import net.osmand.plus.render.OsmandRenderer;
import net.osmand.plus.render.OsmandRenderer.RenderingContext;
import net.osmand.plus.settings.backend.OsmandSettings.CommonPreference;
import net.osmand.plus.track.TrackDrawInfo;
import net.osmand.plus.views.ContextMenuLayer.IContextMenuProvider;
import net.osmand.plus.views.ContextMenuLayer.IMoveObjectProvider;
import net.osmand.plus.views.MapTextLayer.MapTextProvider;
@ -62,7 +64,6 @@ import net.osmand.util.MapUtils;
import org.apache.commons.logging.Log;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@ -94,6 +95,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
private Drawable startPointIcon;
private Drawable finishPointIcon;
private LayerDrawable selectedPoint;
private TrackDrawInfo trackDrawInfo;
private TrackChartPoints trackChartPoints;
private GpxSelectionHelper selectedGpxHelper;
@ -141,6 +143,14 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
this.trackChartPoints = trackChartPoints;
}
public boolean isInTrackAppearanceMode() {
return trackDrawInfo != null;
}
public void setTrackDrawInfo(TrackDrawInfo trackDrawInfo) {
this.trackDrawInfo = trackDrawInfo;
}
private void initUI() {
paint = new Paint();
paint.setStyle(Style.STROKE);
@ -224,10 +234,9 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
if (textLayer != null && isTextVisible()) {
textLayer.putData(this, cache);
}
}
private int updatePaints(int color, String width, boolean routePoints, boolean currentTrack, DrawSettings drawSettings, RotatedTileBox tileBox) {
private void updatePaints(int color, String width, boolean routePoints, boolean currentTrack, DrawSettings drawSettings, RotatedTileBox tileBox) {
RenderingRulesStorage rrs = view.getApplication().getRendererRegistry().getCurrentSelectedRenderer();
boolean nightMode = drawSettings != null && drawSettings.isNightMode();
int hash = calculateHash(rrs, cachedTrackWidth, routePoints, nightMode, tileBox.getMapDensity(), tileBox.getZoom(),
@ -291,7 +300,6 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
if (strikeWidth != null) {
paint.setStrokeWidth(strikeWidth);
}
return cachedColor;
}
private void acquireTrackWidth(String widthKey, RenderingRulesStorage rrs, RenderingRuleSearchRequest req, RenderingContext rc) {
@ -324,8 +332,9 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
DrawSettings settings) {
if (tileBox.getZoom() >= START_ZOOM) {
// request to load
OsmandApplication app = view.getApplication();
for (SelectedGpxFile g : selectedGPXFiles) {
List<GpxDisplayGroup> groups = g.getDisplayGroups(view.getApplication());
List<GpxDisplayGroup> groups = g.getDisplayGroups(app);
if (groups != null && !groups.isEmpty()) {
int color = g.getGpxFile().getColor(0);
if (color == 0) {
@ -338,8 +347,9 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
paintInnerRect.setColor(color);
paintInnerRect.setAlpha(179);
paintTextIcon.setColor(txtlabelColor(color));
paintOuterRect.setColor(txtlabelColor(color));
int contrastColor = UiUtilities.getContrastColor(app, color, false);
paintTextIcon.setColor(contrastColor);
paintOuterRect.setColor(contrastColor);
List<GpxDisplayItem> items = groups.get(0).getModifiableList();
@ -349,14 +359,6 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
}
}
private int txtlabelColor(int color) {
//Hardy, 2020-03-16: Contrast logic for text labels on tracks
if (((int) Color.red(color) * .299 + Color.green(color) * .587 + Color.blue(color) * .114) > 149) {
return Color.BLACK;
}
return Color.WHITE;
}
private void drawSplitItems(Canvas canvas, RotatedTileBox tileBox, List<GpxDisplayItem> items, DrawSettings settings) {
final QuadRect latLonBounds = tileBox.getLatLonBounds();
int r = (int) (12 * tileBox.getDensity());
@ -406,12 +408,18 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
if (!tileBox.isZoomAnimated()) {
for (SelectedGpxFile selectedGpxFile : selectedGPXFiles) {
boolean showArrows = selectedGpxFile.getGpxFile().isShowArrows();
if (hasTrackDrawInfoForSelectedGpx(selectedGpxFile)) {
showArrows = trackDrawInfo.isShowArrows();
}
if (showArrows) {
QuadRect correctedQuadRect = getCorrectedQuadRect(tileBox.getLatLonBounds());
int color = selectedGpxFile.getGpxFile().getColor(cachedColor);
if (selectedGpxFile.isShowCurrentTrack()) {
color = currentTrackColor;
}
if (hasTrackDrawInfoForSelectedGpx(selectedGpxFile)) {
color = trackDrawInfo.getColor();
}
int contrastColor = UiUtilities.getContrastColor(view.getApplication(), color, false);
GeometryWayStyle arrowsWayStyle = new GeometryArrowsWayStyle(wayContext, contrastColor);
for (TrkSegment segment : selectedGpxFile.getPointsToDisplay()) {
@ -526,20 +534,30 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
private void drawSelectedFilesStartEndPoints(Canvas canvas, RotatedTileBox tileBox, List<SelectedGpxFile> selectedGPXFiles) {
if (tileBox.getZoom() >= START_ZOOM) {
for (SelectedGpxFile selectedGpxFile : selectedGPXFiles) {
if (selectedGpxFile.getGpxFile().isShowStartFinish()) {
boolean showStartFinish = selectedGpxFile.getGpxFile().isShowStartFinish();
if (hasTrackDrawInfoForSelectedGpx(selectedGpxFile)) {
showStartFinish = trackDrawInfo.isShowStartFinish();
}
if (showStartFinish) {
List<TrkSegment> segments = selectedGpxFile.getPointsToDisplay();
TrkSegment endSegment = segments.get(segments.size() - 1);
for (TrkSegment segment : segments) {
if (segment.points.size() >= 2) {
WptPt start = segment.points.get(0);
WptPt end = segment.points.get(segment.points.size() - 1);
WptPt start = segments.get(0).points.get(0);
WptPt end = endSegment.points.get(endSegment.points.size() - 1);
drawPoint(canvas, tileBox, start, startPointIcon);
drawPoint(canvas, tileBox, end, finishPointIcon);
drawPoint(canvas, tileBox, start, startPointIcon);
drawPoint(canvas, tileBox, end, finishPointIcon);
}
}
}
}
}
}
private boolean hasTrackDrawInfoForSelectedGpx(SelectedGpxFile selectedGpxFile) {
return trackDrawInfo != null && trackDrawInfo.getFilePath().equals(selectedGpxFile.getGpxFile().path);
}
private void drawPoint(Canvas canvas, RotatedTileBox tileBox, WptPt wptPt, Drawable icon) {
int pointX = (int) tileBox.getPixXFromLatLon(wptPt.lat, wptPt.lon);
int pointY = (int) tileBox.getPixYFromLatLon(wptPt.lat, wptPt.lon);
@ -703,6 +721,9 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
List<SelectedGpxFile> selectedGPXFiles, DrawSettings settings) {
for (SelectedGpxFile selectedGpxFile : selectedGPXFiles) {
String width = selectedGpxFile.getGpxFile().getWidth(currentTrackWidthPref.get());
if (hasTrackDrawInfoForSelectedGpx(selectedGpxFile)) {
width = trackDrawInfo.getWidth();
}
if (!cachedTrackWidth.containsKey(width)) {
cachedTrackWidth.put(width, null);
}
@ -732,6 +753,10 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
if (color == 0) {
color = ts.getColor(cachedColor);
}
if (hasTrackDrawInfoForSelectedGpx(selectedGpxFile)) {
color = trackDrawInfo.getColor();
width = trackDrawInfo.getWidth();
}
if (ts.renderer == null && !ts.points.isEmpty()) {
if (currentTrack) {
ts.renderer = new Renderable.CurrentTrack(ts.points);
@ -1010,10 +1035,9 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
@Override
public void applyNewObjectPosition(@NonNull Object o,
@NonNull LatLon position,
@Nullable ContextMenuLayer.ApplyMovedObjectCallback callback) {
@Nullable final ContextMenuLayer.ApplyMovedObjectCallback callback) {
if (o instanceof WptPt) {
WptPt objectInMotion = (WptPt) o;
final WptPt objectInMotion = (WptPt) o;
SelectedGpxFile selectedGpxFile = pointFileMap.get(objectInMotion);
if (selectedGpxFile != null) {
GPXFile gpxFile = selectedGpxFile.getGpxFile();
@ -1027,7 +1051,20 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
callback.onApplyMovedObject(true, objectInMotion);
}
} else {
new SaveGpxFileAsyncTask(view.getApplication(), callback, objectInMotion).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, gpxFile);
new SaveGpxAsyncTask(gpxFile, new SaveGpxAsyncTask.SaveGpxListener() {
@Override
public void gpxSavingStarted() {
}
@Override
public void gpxSavingFinished(Exception errorMessage) {
if (callback != null) {
callback.onApplyMovedObject(errorMessage == null, objectInMotion);
}
}
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
}
} else if (callback != null) {
@ -1041,33 +1078,4 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
mapMarkersHelper.runSynchronization(group);
}
}
static class SaveGpxFileAsyncTask extends AsyncTask<GPXFile, Void, Exception> {
private final OsmandApplication app;
@Nullable
private final ContextMenuLayer.ApplyMovedObjectCallback callback;
@Nullable
private final WptPt point;
SaveGpxFileAsyncTask(OsmandApplication app,
@Nullable ContextMenuLayer.ApplyMovedObjectCallback callback,
@Nullable WptPt point) {
this.app = app;
this.callback = callback;
this.point = point;
}
@Override
protected Exception doInBackground(GPXFile... params) {
GPXFile gpxFile = params[0];
return GPXUtilities.writeGpxFile(new File(gpxFile.path), gpxFile);
}
@Override
protected void onPostExecute(Exception errorMessage) {
if (callback != null) {
callback.onApplyMovedObject(errorMessage == null, point);
}
}
}
}

View file

@ -37,15 +37,10 @@ import net.osmand.core.android.MapRendererContext;
import net.osmand.data.LatLon;
import net.osmand.data.PointDescription;
import net.osmand.data.RotatedTileBox;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.settings.backend.OsmAndAppCustomization;
import net.osmand.plus.OsmAndLocationProvider;
import net.osmand.plus.OsmAndLocationSimulation;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.settings.backend.OsmandSettings.CommonPreference;
import net.osmand.plus.settings.backend.OsmandSettings.LayerTransparencySeekbarMode;
import net.osmand.plus.R;
import net.osmand.plus.TargetPointsHelper;
import net.osmand.plus.TargetPointsHelper.TargetPoint;
@ -63,6 +58,11 @@ import net.osmand.plus.routepreparationmenu.MapRouteInfoMenu.PointType;
import net.osmand.plus.routing.RoutingHelper;
import net.osmand.plus.routing.TransportRoutingHelper;
import net.osmand.plus.search.QuickSearchDialogFragment.QuickSearchType;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.settings.backend.OsmAndAppCustomization;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.settings.backend.OsmandSettings.CommonPreference;
import net.osmand.plus.settings.backend.OsmandSettings.LayerTransparencySeekbarMode;
import net.osmand.plus.views.corenative.NativeCoreContext;
import java.util.ArrayList;
@ -791,7 +791,9 @@ public class MapControlsLayer extends OsmandMapLayer {
boolean routeDialogOpened = mapRouteInfoMenu.isVisible() || (showRouteCalculationControls && mapRouteInfoMenu.needShowMenu());
updateMyLocation(rh, routeDialogOpened || contextMenuOpened);
boolean showButtons = (showRouteCalculationControls || !routeFollowingMode)
&& !isInMovingMarkerMode() && !isInGpxDetailsMode() && !isInMeasurementToolMode() && !isInPlanRouteMode() && !contextMenuOpened && !isInChoosingRoutesMode() && !isInWaypointsChoosingMode();
&& !isInMovingMarkerMode() && !isInGpxDetailsMode() && !isInMeasurementToolMode()
&& !isInPlanRouteMode() && !contextMenuOpened && !isInChoosingRoutesMode()
&& !isInWaypointsChoosingMode() && !isInTrackAppearanceMode();
//routePlanningBtn.setIconResId(routeFollowingMode ? R.drawable.ic_action_info_dark : R.drawable.ic_action_gdirections_dark);
int routePlanningBtnImage = mapRouteInfoMenu.getRoutePlanningBtnImage();
if (routePlanningBtnImage != 0) {
@ -811,10 +813,10 @@ public class MapControlsLayer extends OsmandMapLayer {
menuControl.updateVisibility(showButtons);
mapZoomIn.updateVisibility(!routeDialogOpened && !contextMenuOpened && (!isInChoosingRoutesMode() || !isInWaypointsChoosingMode() || !portrait));
mapZoomOut.updateVisibility(!routeDialogOpened && !contextMenuOpened && (!isInChoosingRoutesMode() || !isInWaypointsChoosingMode() || !portrait));
mapZoomIn.updateVisibility(!routeDialogOpened && !contextMenuOpened && !isInTrackAppearanceMode() && (!isInChoosingRoutesMode() || !isInWaypointsChoosingMode() || !portrait));
mapZoomOut.updateVisibility(!routeDialogOpened && !contextMenuOpened && !isInTrackAppearanceMode() && (!isInChoosingRoutesMode() || !isInWaypointsChoosingMode() || !portrait));
boolean forceHideCompass = routeDialogOpened || trackDialogOpened
|| isInMeasurementToolMode() || isInPlanRouteMode() || contextMenuOpened || isInChoosingRoutesMode() || isInWaypointsChoosingMode();
|| isInMeasurementToolMode() || isInPlanRouteMode() || contextMenuOpened || isInChoosingRoutesMode() || isInTrackAppearanceMode() || isInWaypointsChoosingMode();
compassHud.forceHideCompass = forceHideCompass;
compassHud.updateVisibility(!forceHideCompass && shouldShowCompass());
@ -824,9 +826,9 @@ public class MapControlsLayer extends OsmandMapLayer {
layersHud.update(app, isNight);
}
layersHud.updateVisibility(!routeDialogOpened && !trackDialogOpened && !isInMeasurementToolMode() && !isInPlanRouteMode()
&& !contextMenuOpened && !isInChoosingRoutesMode() && !isInWaypointsChoosingMode());
&& !contextMenuOpened && !isInChoosingRoutesMode() && !isInTrackAppearanceMode() && !isInWaypointsChoosingMode());
quickSearchHud.updateVisibility(!routeDialogOpened && !trackDialogOpened && !isInMeasurementToolMode() && !isInPlanRouteMode()
&& !contextMenuOpened && !isInChoosingRoutesMode() && !isInWaypointsChoosingMode());
&& !contextMenuOpened && !isInChoosingRoutesMode() && !isInTrackAppearanceMode() && !isInWaypointsChoosingMode());
if (mapView.isZooming()) {
lastZoom = System.currentTimeMillis();
@ -904,7 +906,8 @@ public class MapControlsLayer extends OsmandMapLayer {
backToLocationControl.iv.setContentDescription(mapActivity.getString(R.string.map_widget_back_to_loc));
}
boolean visible = !(tracked && rh.isFollowingMode());
backToLocationControl.updateVisibility(visible && !dialogOpened && !isInPlanRouteMode() && (!isInChoosingRoutesMode() || !isInWaypointsChoosingMode() || !portrait));
backToLocationControl.updateVisibility(visible && !dialogOpened && !isInPlanRouteMode()
&& !isInTrackAppearanceMode() && (!isInChoosingRoutesMode() || !isInWaypointsChoosingMode() || !portrait));
if (app.accessibilityEnabled()) {
backToLocationControl.iv.setClickable(enabled && visible);
}
@ -1212,6 +1215,10 @@ public class MapControlsLayer extends OsmandMapLayer {
return mapActivity.getMapLayers().getMapMarkersLayer().isInPlanRouteMode();
}
private boolean isInTrackAppearanceMode() {
return mapActivity.getMapLayers().getGpxLayer().isInTrackAppearanceMode();
}
private boolean isInChoosingRoutesMode() {
return MapRouteInfoMenu.chooseRoutesVisible;
}

View file

@ -57,6 +57,7 @@ public class MapQuickActionLayer extends OsmandMapLayer implements QuickActionRe
private final ContextMenuLayer contextMenuLayer;
private final MeasurementToolLayer measurementToolLayer;
private final MapMarkersLayer mapMarkersLayer;
private final GPXLayer gpxLayer;
private ImageView contextMarker;
private final MapActivity mapActivity;
private final OsmandApplication app;
@ -84,9 +85,9 @@ public class MapQuickActionLayer extends OsmandMapLayer implements QuickActionRe
quickActionRegistry = app.getQuickActionRegistry();
measurementToolLayer = mapActivity.getMapLayers().getMeasurementToolLayer();
mapMarkersLayer = mapActivity.getMapLayers().getMapMarkersLayer();
gpxLayer = mapActivity.getMapLayers().getGpxLayer();
}
@Override
public void initLayer(OsmandMapTileView view) {
this.view = view;
@ -410,6 +411,7 @@ public class MapQuickActionLayer extends OsmandMapLayer implements QuickActionRe
contextMenuLayer.isInGpxDetailsMode() ||
measurementToolLayer.isInMeasurementMode() ||
mapMarkersLayer.isInPlanRouteMode() ||
gpxLayer.isInTrackAppearanceMode() ||
mapRouteInfoMenu.isVisible() ||
MapRouteInfoMenu.chooseRoutesVisible ||
MapRouteInfoMenu.waypointsVisible ||