Merge branch 'sasha_pasha_branch' of ssh://github.com/osmandapp/Osmand into sasha_pasha_branch

This commit is contained in:
PavelRatushnyi 2017-08-10 00:57:44 +03:00
commit 226162a76f
40 changed files with 2138 additions and 350 deletions

View file

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:osmand="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@android:id/empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<ImageView
android:layout_marginTop="@dimen/my_places_empty_state_image_margin_top"
android:layout_marginBottom="@dimen/my_places_empty_state_image_margin_bottom"
android:adjustViewBounds="true"
android:layout_marginLeft="@dimen/my_places_empty_state_image_margin_left"
android:layout_marginStart="@dimen/my_places_empty_state_image_margin_left"
android:id="@+id/empty_state_image_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
tools:src="@drawable/ic_empty_state_favorites_night_result"/>
<LinearLayout
android:clipToPadding="false"
android:paddingLeft="@dimen/my_places_empty_state_text_button_padding_left"
android:paddingStart="@dimen/my_places_empty_state_text_button_padding_left"
android:paddingRight="@dimen/my_places_empty_state_text_button_padding_right"
android:paddingEnd="@dimen/my_places_empty_state_text_button_padding_right"
android:paddingTop="@dimen/my_places_empty_state_text_button_padding_top"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical">
<net.osmand.plus.widgets.TextViewEx
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/my_places_empty_state_text_interval"
android:background="@null"
android:text="@string/empty_state_favourites"
android:textColor="?android:attr/textColorPrimary"
android:textSize="@dimen/my_places_empty_state_text_size"
osmand:typeface="@string/font_roboto_medium"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@null"
android:text="@string/empty_state_favourites_desc"
android:textColor="?android:attr/textColorSecondary"
android:textSize="@dimen/my_places_empty_state_text_desc_size"/>
<Button
android:id="@+id/import_button"
style="@style/DialogActionButton"
android:layout_marginTop="@dimen/my_places_empty_state_button_margin_top"
android:text="@string/shared_string_import"/>
</LinearLayout>
</LinearLayout>

View file

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:osmand="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@android:id/empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<ImageView
android:layout_marginTop="@dimen/my_places_empty_state_image_margin_top"
android:layout_marginBottom="@dimen/my_places_empty_state_image_margin_bottom"
android:adjustViewBounds="true"
android:layout_marginLeft="@dimen/my_places_empty_state_image_margin_left"
android:layout_marginStart="@dimen/my_places_empty_state_image_margin_left"
android:id="@+id/empty_state_image_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
tools:src="@drawable/ic_empty_state_trip_night_result"/>
<LinearLayout
android:clipToPadding="false"
android:paddingLeft="@dimen/my_places_empty_state_text_button_padding_left"
android:paddingStart="@dimen/my_places_empty_state_text_button_padding_left"
android:paddingRight="@dimen/my_places_empty_state_text_button_padding_right"
android:paddingEnd="@dimen/my_places_empty_state_text_button_padding_right"
android:paddingTop="@dimen/my_places_empty_state_text_button_padding_top"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical">
<net.osmand.plus.widgets.TextViewEx
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/my_places_empty_state_text_interval"
android:background="@null"
android:text="@string/empty_state_my_tracks"
android:textColor="?android:attr/textColorPrimary"
android:textSize="@dimen/my_places_empty_state_text_size"
osmand:typeface="@string/font_roboto_medium"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@null"
android:text="@string/empty_state_my_tracks_desc"
android:textColor="?android:attr/textColorSecondary"
android:textSize="@dimen/my_places_empty_state_text_desc_size"/>
<Button
android:id="@+id/import_button"
style="@style/DialogActionButton"
android:layout_marginTop="@dimen/my_places_empty_state_button_margin_top"
android:text="@string/shared_string_import"/>
</LinearLayout>
</LinearLayout>

View file

@ -1,8 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/ctx_menu_info_view_bg"
android:orientation="vertical">
<ExpandableListView
android:id="@android:id/list"
@ -17,4 +18,6 @@
android:drawSelectorOnTop="false"
android:groupIndicator="@android:color/transparent"/>
<include layout="@layout/empty_state_my_tracks"/>
</LinearLayout>

View file

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:osmand="http://schemas.android.com/apk/res-auto"
android:id="@android:id/empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical">
<ImageView
android:id="@+id/empty_state_image_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/my_places_empty_state_image_margin_bottom"
android:layout_marginTop="@dimen/my_places_empty_state_image_margin_top"
tools:src="@drawable/ic_empty_state_favorites_night_result"/>
<net.osmand.plus.widgets.TextViewEx
osmand:typeface="@string/font_roboto_medium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/my_places_empty_state_text_interval"
android:background="@null"
android:text="@string/empty_state_favourites"
android:textColor="?android:attr/textColorPrimary"
android:textSize="@dimen/my_places_empty_state_text_size"/>
<TextView
android:gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@null"
android:layout_marginLeft="@dimen/my_places_empty_state_text_desc_margin"
android:layout_marginRight="@dimen/my_places_empty_state_text_desc_margin"
android:text="@string/empty_state_favourites_desc"
android:textColor="?android:attr/textColorSecondary"
android:textSize="@dimen/my_places_empty_state_text_desc_size"/>
<Button
android:id="@+id/import_button"
style="@style/DialogActionButton"
android:layout_marginTop="@dimen/my_places_empty_state_button_margin_top"
android:text="@string/shared_string_import"/>
</LinearLayout>

View file

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:osmand="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@android:id/empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical">
<ImageView
android:id="@+id/empty_state_image_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/my_places_empty_state_image_margin_bottom"
android:layout_marginTop="@dimen/my_places_empty_state_image_margin_top"
tools:src="@drawable/ic_empty_state_trip_night_result"/>
<net.osmand.plus.widgets.TextViewEx
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/my_places_empty_state_text_interval"
android:background="@null"
android:text="@string/empty_state_my_tracks"
android:textColor="?android:attr/textColorPrimary"
android:textSize="@dimen/my_places_empty_state_text_size"
osmand:typeface="@string/font_roboto_medium"/>
<TextView
android:gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@null"
android:layout_marginLeft="@dimen/my_places_empty_state_text_desc_margin"
android:layout_marginRight="@dimen/my_places_empty_state_text_desc_margin"
android:text="@string/empty_state_my_tracks_desc"
android:textColor="?android:attr/textColorSecondary"
android:textSize="@dimen/my_places_empty_state_text_desc_size"/>
<Button
android:id="@+id/import_button"
style="@style/DialogActionButton"
android:layout_marginTop="@dimen/my_places_empty_state_button_margin_top"
android:text="@string/shared_string_import"/>
</LinearLayout>

View file

@ -1,9 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/MainLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
android:id="@+id/MainLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="?attr/ctx_menu_info_view_bg">
<ExpandableListView
android:id="@android:id/list"
@ -16,6 +17,8 @@
android:divider="@null"
android:dividerHeight="0dp"
android:drawSelectorOnTop="false"
android:groupIndicator="@android:color/transparent" />
android:groupIndicator="@android:color/transparent"/>
<include layout="@layout/empty_state_favourites"/>
</LinearLayout>

View file

@ -4,6 +4,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:osmand="http://schemas.android.com/apk/res-auto"
android:background="@color/color_transparent"
android:clickable="true">
@ -17,8 +18,10 @@
android:orientation="vertical">
<RelativeLayout
android:id="@+id/up_down_row"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:paddingBottom="12dp"
android:paddingTop="12dp">
@ -36,16 +39,31 @@
android:background="@null"
tools:src="@drawable/ic_action_ruler"/>
<ImageButton
<ImageView
android:id="@+id/move_point_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:layout_marginEnd="16dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginStart="16dp"
android:background="@null"
tools:src="@drawable/ic_action_measure_point"
android:visibility="gone"/>
<ImageView
android:id="@+id/up_down_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginEnd="16dp"
android:layout_marginStart="16dp"
android:background="@null"
android:paddingEnd="16dp"
android:paddingStart="16dp"
tools:src="@drawable/ic_action_arrow_down"/>
<TextView
@ -74,6 +92,21 @@
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_list_text_size"
tools:text="points: 3"/>
<TextView
android:id="@+id/move_point_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginEnd="4dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="4dp"
android:layout_marginStart="8dp"
android:layout_toEndOf="@id/move_point_icon"
android:layout_toRightOf="@id/move_point_icon"
android:textAppearance="@style/TextAppearance.ListItemTitle"
android:text="@string/move_point"
android:visibility="gone"/>
</RelativeLayout>
<View
@ -81,31 +114,32 @@
android:layout_height="1dp"
android:background="?attr/dashboard_divider"/>
<LinearLayout
<FrameLayout
android:id="@+id/points_list_container"
android:layout_width="match_parent"
android:layout_height="220dp"
android:background="@color/ctx_menu_info_view_bg_dark"
android:orientation="vertical"
android:visibility="gone">
<android.support.v7.widget.RecyclerView
android:id="@+id/measure_points_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<include layout="@layout/card_bottom_divider"/>
<android.support.v7.widget.RecyclerView
android:id="@+id/points_recycler_view"
android:layout_width="match_parent"
android:layout_height="215dp"/>
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="5dp"
android:layout_gravity="bottom"
android:alpha="0.5"
android:scaleType="fitXY"
android:src="@drawable/bg_shadow_onmap"/>
</LinearLayout>
</FrameLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="52dp">
<ImageButton
android:id="@+id/undo_point_button"
@ -114,9 +148,13 @@
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:background="@null"
android:paddingEnd="16dp"
android:background="?attr/selectableItemBackground"
android:paddingBottom="14dp"
android:paddingEnd="12dp"
android:paddingLeft="16dp"
android:paddingRight="12dp"
android:paddingStart="16dp"
android:paddingTop="14dp"
tools:src="@drawable/ic_action_undo_dark"/>
<ImageButton
@ -126,9 +164,13 @@
android:layout_centerVertical="true"
android:layout_toEndOf="@id/undo_point_button"
android:layout_toRightOf="@id/undo_point_button"
android:background="@null"
android:paddingEnd="8dp"
android:paddingStart="8dp"
android:background="?attr/selectableItemBackground"
android:paddingBottom="14dp"
android:paddingEnd="16dp"
android:paddingLeft="12dp"
android:paddingRight="16dp"
android:paddingStart="12dp"
android:paddingTop="14dp"
tools:src="@drawable/ic_action_redo_dark"/>
<Button
@ -149,6 +191,41 @@
android:paddingRight="8dp"
android:text="@string/shared_string_add"
android:textColor="@color/color_white"/>
<Button
android:id="@+id/apply_point_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="8dp"
android:background="@drawable/btn_round_blue"
android:minHeight="36dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:text="@string/shared_string_apply"
android:textColor="@color/color_white"
android:visibility="gone"/>
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/cancel_button"
android:gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="?attr/selectableItemBackground"
android:paddingEnd="12dp"
android:paddingLeft="16dp"
android:paddingRight="12dp"
android:paddingStart="16dp"
android:text="@string/shared_string_cancel"
android:textColor="?attr/color_dialog_buttons"
osmand:textAllCapsCompat="true"
osmand:typeface="@string/font_roboto_medium"
android:visibility="gone"/>
</RelativeLayout>
</LinearLayout>

View file

@ -0,0 +1,91 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="48dp"
android:descendantFocusability="blocksDescendants">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/selectableItemBackground">
<android.support.v7.widget.AppCompatImageView
android:id="@+id/measure_point_reorder_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:paddingBottom="12dp"
android:paddingEnd="16dp"
android:paddingStart="16dp"
android:paddingTop="12dp"
android:tint="?attr/secondary_icon_color"
tools:src="@drawable/ic_action_reorder"/>
<android.support.v7.widget.AppCompatImageView
android:id="@+id/measure_point_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:layout_toEndOf="@id/measure_point_reorder_icon"
android:layout_toRightOf="@id/measure_point_reorder_icon"
tools:src="@drawable/ic_action_measure_point"/>
<ImageButton
android:id="@+id/measure_point_remove_image_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:background="?attr/selectableItemBackground"
android:focusableInTouchMode="true"
android:paddingBottom="12dp"
android:paddingEnd="16dp"
android:paddingStart="16dp"
android:paddingTop="12dp"
tools:src="@drawable/ic_action_remove_dark"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toEndOf="@+id/measure_point_icon"
android:layout_toLeftOf="@id/measure_point_remove_image_button"
android:layout_toRightOf="@+id/measure_point_icon"
android:layout_toStartOf="@id/measure_point_remove_image_button"
android:orientation="vertical">
<android.support.v7.widget.AppCompatTextView
android:id="@+id/measure_point_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_desc_text_size"
tools:text="@string/plugin_distance_point"/>
<android.support.v7.widget.AppCompatTextView
android:id="@+id/measure_point_descr"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_sub_text_size"
tools:text="@string/shared_string_control_start"/>
</LinearLayout>
<View
android:id="@+id/points_divider"
android:layout_width="wrap_content"
android:layout_height="1dp"
android:layout_alignParentBottom="true"
android:layout_toEndOf="@+id/measure_point_reorder_icon"
android:layout_toRightOf="@+id/measure_point_reorder_icon"
android:background="?attr/dashboard_divider"/>
</RelativeLayout>
</FrameLayout>

View file

@ -5,8 +5,7 @@
xmlns:osmand="http://schemas.android.com/apk/res-auto"
android:id="@+id/MainLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
android:layout_height="match_parent">
<ExpandableListView
android:id="@android:id/list"
@ -110,4 +109,44 @@
</FrameLayout>
<android.support.design.widget.FloatingActionButton
android:id="@+id/line_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/route_fab"
android:layout_alignParentRight="true"
android:layout_marginBottom="16dp"
android:layout_marginRight="24dp"
android:contentDescription="@string/quick_action_new_action"
android:src="@drawable/ic_action_polygom_dark"
android:visibility="gone"
app:backgroundTint="@color/dashboard_blue"
app:fabSize="mini"
tools:visibility="visible"/>
<FrameLayout
android:id="@+id/line_text_layout"
android:layout_toLeftOf="@id/line_fab"
android:layout_toStartOf="@id/line_fab"
android:layout_above="@id/route_fab"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_marginBottom="16dp"
android:layout_marginRight="16dp"
android:layout_marginEnd="16dp"
android:visibility="gone"
tools:visibility="visible">
<net.osmand.plus.widgets.TextViewEx
android:textColor="?android:attr/textColorPrimary"
osmand:typeface="@string/font_roboto_medium"
android:layout_gravity="center_vertical"
android:id="@+id/line_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:text="@string/add_line"/>
</FrameLayout>
</RelativeLayout>

View file

@ -0,0 +1,147 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:osmand="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical">
<ListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="0dp"
android:layout_marginRight="0dp"
android:layout_marginTop="0dp"/>
<android.support.design.widget.FloatingActionButton
android:id="@+id/menu_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_margin="16dp"
android:contentDescription="@string/quick_action_new_action"
android:src="@drawable/ic_action_plus"
app:backgroundTint="@color/dashboard_blue"
app:fabSize="normal"/>
<android.support.design.widget.FloatingActionButton
android:id="@+id/waypoint_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/menu_fab"
android:layout_alignParentRight="true"
android:layout_marginRight="24dp"
android:contentDescription="@string/quick_action_new_action"
android:src="@drawable/ic_action_marker_dark"
android:visibility="gone"
app:backgroundTint="@color/dashboard_blue"
app:fabSize="mini"
tools:visibility="visible"/>
<FrameLayout
android:id="@+id/waypoint_text_layout"
android:layout_toLeftOf="@id/waypoint_fab"
android:layout_toStartOf="@id/waypoint_fab"
android:layout_above="@id/menu_fab"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_marginRight="16dp"
android:layout_marginEnd="16dp"
android:visibility="gone"
tools:visibility="visible">
<net.osmand.plus.widgets.TextViewEx
android:textColor="?android:attr/textColorPrimary"
osmand:typeface="@string/font_roboto_medium"
android:layout_gravity="center_vertical"
android:id="@+id/waypoint_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:text="@string/add_waypoint"/>
</FrameLayout>
<android.support.design.widget.FloatingActionButton
android:id="@+id/route_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/waypoint_fab"
android:layout_alignParentRight="true"
android:layout_marginBottom="16dp"
android:layout_marginRight="24dp"
android:contentDescription="@string/quick_action_new_action"
android:src="@drawable/ic_action_markers_dark"
android:visibility="gone"
app:backgroundTint="@color/dashboard_blue"
app:fabSize="mini"
tools:visibility="visible"/>
<FrameLayout
android:id="@+id/route_text_layout"
android:layout_toLeftOf="@id/route_fab"
android:layout_toStartOf="@id/route_fab"
android:layout_above="@id/waypoint_fab"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_marginBottom="16dp"
android:layout_marginRight="16dp"
android:layout_marginEnd="16dp"
android:visibility="gone"
tools:visibility="visible">
<net.osmand.plus.widgets.TextViewEx
android:textColor="?android:attr/textColorPrimary"
osmand:typeface="@string/font_roboto_medium"
android:layout_gravity="center_vertical"
android:id="@+id/route_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:text="@string/add_route_point"/>
</FrameLayout>
<android.support.design.widget.FloatingActionButton
android:id="@+id/line_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/route_fab"
android:layout_alignParentRight="true"
android:layout_marginBottom="16dp"
android:layout_marginRight="24dp"
android:contentDescription="@string/quick_action_new_action"
android:src="@drawable/ic_action_polygom_dark"
android:visibility="gone"
app:backgroundTint="@color/dashboard_blue"
app:fabSize="mini"
tools:visibility="visible"/>
<FrameLayout
android:id="@+id/line_text_layout"
android:layout_toLeftOf="@id/line_fab"
android:layout_toStartOf="@id/line_fab"
android:layout_above="@id/route_fab"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_marginBottom="16dp"
android:layout_marginRight="16dp"
android:layout_marginEnd="16dp"
android:visibility="gone"
tools:visibility="visible">
<net.osmand.plus.widgets.TextViewEx
android:textColor="?android:attr/textColorPrimary"
osmand:typeface="@string/font_roboto_medium"
android:layout_gravity="center_vertical"
android:id="@+id/line_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:text="@string/add_line"/>
</FrameLayout>
</RelativeLayout>

View file

@ -1,5 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:visible="false"
android:id="@+id/action_save_as_new_segment"
android:icon="@drawable/ic_action_polygom_dark"
android:title="@string/save_as_new_segment"/>
<item
android:id="@+id/action_save_as_gpx"
android:icon="@drawable/ic_action_polygom_dark"

View file

@ -4,4 +4,7 @@
<dimen name="splash_screen_logo_top">24dp</dimen>
<dimen name="splash_screen_text_bottom">48dp</dimen>
<dimen name="my_places_empty_state_image_margin_top">39dp</dimen>
<dimen name="my_places_empty_state_image_margin_bottom">39dp</dimen>
</resources>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="my_places_empty_state_image_margin_top">59dp</dimen>
<dimen name="my_places_empty_state_image_margin_bottom">59dp</dimen>
</resources>

View file

@ -78,5 +78,17 @@
<dimen name="default_split_segments_overview">15sp</dimen>
<dimen name="default_split_segments_data">15sp</dimen>
<dimen name="default_split_segments_sub">12sp</dimen>
<dimen name="my_places_empty_state_image_margin_top">63dp</dimen>
<dimen name="my_places_empty_state_image_margin_bottom">45dp</dimen>
<dimen name="my_places_empty_state_text_interval">12dp</dimen>
<dimen name="my_places_empty_state_button_margin_top">30dp</dimen>
<dimen name="my_places_empty_state_text_size">20sp</dimen>
<dimen name="my_places_empty_state_text_desc_size">18sp</dimen>
<dimen name="my_places_empty_state_text_desc_margin">68dp</dimen>
<dimen name="my_places_empty_state_image_margin_left">138dp</dimen>
<dimen name="my_places_empty_state_text_button_padding_left">72dp</dimen>
<dimen name="my_places_empty_state_text_button_padding_right">90dp</dimen>
<dimen name="my_places_empty_state_text_button_padding_top">96dp</dimen>
</resources>

View file

@ -143,4 +143,16 @@
<dimen name="splash_screen_logo_top">150dp</dimen>
<dimen name="splash_screen_text_bottom">128dp</dimen>
<dimen name="my_places_empty_state_image_margin_top">42dp</dimen>
<dimen name="my_places_empty_state_image_margin_bottom">30dp</dimen>
<dimen name="my_places_empty_state_text_interval">8dp</dimen>
<dimen name="my_places_empty_state_button_margin_top">20dp</dimen>
<dimen name="my_places_empty_state_text_size">18sp</dimen>
<dimen name="my_places_empty_state_text_desc_size">16sp</dimen>
<dimen name="my_places_empty_state_text_desc_margin">45dp</dimen>
<dimen name="my_places_empty_state_image_margin_left">92dp</dimen>
<dimen name="my_places_empty_state_text_button_padding_left">48dp</dimen>
<dimen name="my_places_empty_state_text_button_padding_right">60dp</dimen>
<dimen name="my_places_empty_state_text_button_padding_top">64dp</dimen>
</resources>

View file

@ -790,7 +790,7 @@
<string name="shared_string_clear">Clear</string>
<string name="shared_string_clear_all">Clear all</string>
<string name="shared_string_save">Save</string>
<string name="shared_string_save_as_gpx">Save as GPX track</string>
<string name="shared_string_save_as_gpx">Save as Track</string>
<string name="shared_string_rename">Rename</string>
<string name="shared_string_delete">Delete</string>
<string name="shared_string_delete_all">Delete all</string>
@ -2665,8 +2665,17 @@
<string name="retry">Retry</string>
<string name="add_route_point">Add Route Point</string>
<string name="add_waypoint">Add Waypoint</string>
<string name="add_line">Add Line</string>
<string name="save_gpx_waypoint">Save GPX Waypoint</string>
<string name="save_route_point">Save Route Point</string>
<string name="waypoint_one">Waypoint 1</string>
<string name="route_point_one">Route Point 1</string>
<string name="empty_state_my_tracks">Add and Record Tracks</string>
<string name="empty_state_my_tracks_desc">Record or import tracks to view</string>
<string name="empty_state_favourites">Add Favorites</string>
<string name="empty_state_favourites_desc">Add favorites on map or import them from filesystem</string>
<string name="import_track">Import track</string>
<string name="import_track_desc">File %1$s does not contain waypoints, import it as a track?</string>
<string name="save_as_new_segment">Save as new segment</string>
<string name="move_point">Move Point</string>
</resources>

View file

@ -880,7 +880,7 @@ public class GPXUtilities {
if (routes.size() == 0) {
routes.add(new Route());
}
Route currentRoute = routes.get(routes.size() -1);
Route currentRoute = routes.get(routes.size() - 1);
currentRoute.points.add(pt);
modifiedTime = System.currentTimeMillis();
@ -888,6 +888,26 @@ public class GPXUtilities {
return pt;
}
public void addTrkSegment(List<WptPt> points) {
Track generalTrack = getGeneralTrack();
if (generalTrack != null) {
tracks.remove(generalTrack);
this.generalTrack = null;
this.generalSegment = null;
}
TrkSegment segment = new TrkSegment();
segment.points.addAll(points);
if (tracks.size() == 0) {
tracks.add(new Track());
}
Track lastTrack = tracks.get(tracks.size() - 1);
lastTrack.segments.add(segment);
modifiedTime = System.currentTimeMillis();
}
public void updateWptPt(WptPt pt, double lat, double lon, long time, String description, String name, String category, int color) {
int index = points.indexOf(pt);

View file

@ -1244,7 +1244,8 @@ public class OsmandSettings {
// this value string is synchronized with settings_pref.xml preference name
public static final int CENTER_CONSTANT = 0;
public static final int BOTTOM_CONSTANT = 1;
public static final int MIDDLE_CONSTANT = 2;
public static final int MIDDLE_BOTTOM_CONSTANT = 2;
public static final int MIDDLE_TOP_CONSTANT = 3;
public final CommonPreference<Boolean> CENTER_POSITION_ON_MAP = new BooleanPreference("center_position_on_map", false).makeProfile();
// this value string is synchronized with settings_pref.xml preference name

View file

@ -21,6 +21,7 @@ import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ExpandableListView;
import android.widget.Filter;
@ -71,11 +72,13 @@ public class FavoritesTreeFragment extends OsmandExpandableListFragment {
public static final int SHARE_ID = 4;
public static final int SELECT_MAP_MARKERS_ID = 5;
public static final int SELECT_MAP_MARKERS_ACTION_MODE_ID = 6;
public static final int IMPORT_FAVOURITES_ID = 7;
public static final String GROUP_EXPANDED_POSTFIX = "_group_expanded";
private FavouritesAdapter favouritesAdapter = new FavouritesAdapter();
private FavouritesDbHelper helper;
private OsmandApplication app;
private boolean selectionMode = false;
private Set<FavouritePoint> favoritesSelected = new LinkedHashSet<>();
private Set<FavoriteGroup> groupsToDelete = new LinkedHashSet<>();
@ -88,6 +91,7 @@ public class FavoritesTreeFragment extends OsmandExpandableListFragment {
@Override
public void onAttach(Context context) {
super.onAttach(context);
this.app = (OsmandApplication) getActivity().getApplication();
helper = getMyApplication().getFavorites();
favouritesAdapter.synchronizeGroups();
@ -156,6 +160,17 @@ public class FavoritesTreeFragment extends OsmandExpandableListFragment {
footerView = inflater.inflate(R.layout.list_shadow_footer, null, false);
listView.addFooterView(footerView);
}
View emptyView = view.findViewById(android.R.id.empty);
ImageView emptyImageView = (ImageView) emptyView.findViewById(R.id.empty_state_image_view);
emptyImageView.setImageResource(app.getSettings().isLightContent() ? R.drawable.ic_empty_state_favorites_day_result : R.drawable.ic_empty_state_favorites_night_result);
Button importButton = (Button) emptyView.findViewById(R.id.import_button);
importButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
importFavourites();
}
});
listView.setEmptyView(emptyView);
listView.setAdapter(favouritesAdapter);
setListView(listView);
setHasOptionsMenu(true);
@ -237,6 +252,9 @@ public class FavoritesTreeFragment extends OsmandExpandableListFragment {
} else if (item.getItemId() == DELETE_ACTION_ID) {
deleteFavoritesAction();
return true;
} else if (item.getItemId() == IMPORT_FAVOURITES_ID) {
importFavourites();
return true;
} else {
return super.onOptionsItemSelected(item);
}
@ -268,6 +286,8 @@ public class FavoritesTreeFragment extends OsmandExpandableListFragment {
if (!MenuItemCompat.isActionViewExpanded(mi)) {
createMenuItem(menu, IMPORT_FAVOURITES_ID, R.string.shared_string_add_to_favorites, R.drawable.ic_action_plus,
R.drawable.ic_action_plus, MenuItemCompat.SHOW_AS_ACTION_ALWAYS);
createMenuItem(menu, SHARE_ID, R.string.shared_string_share, R.drawable.ic_action_gshare_dark,
R.drawable.ic_action_gshare_dark, MenuItemCompat.SHOW_AS_ACTION_ALWAYS);
if (getSettings().USE_MAP_MARKERS.get()) {
@ -467,6 +487,10 @@ public class FavoritesTreeFragment extends OsmandExpandableListFragment {
}
}
private void importFavourites() {
((FavoritesActivity) getActivity()).importFavourites();
}
public void shareFavorites(final FavoriteGroup group) {
final AsyncTask<Void, Void, Void> exportTask = new AsyncTask<Void, Void, Void>() {

View file

@ -70,6 +70,7 @@ import net.osmand.plus.TargetPointsHelper;
import net.osmand.plus.TargetPointsHelper.TargetPoint;
import net.osmand.plus.Version;
import net.osmand.plus.activities.search.SearchActivity;
import net.osmand.plus.activities.TrackActivity.NewGpxLine;
import net.osmand.plus.base.FailSafeFuntions;
import net.osmand.plus.base.MapViewTrackingUtilities;
import net.osmand.plus.dashboard.DashboardOnMap;
@ -501,7 +502,7 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven
}
}
if (getMeasurementToolFragment() != null) {
getMeasurementToolFragment().showQuitDialog();
getMeasurementToolFragment().showQuitDialog(true);
return;
}
if (mapContextMenu.isVisible() && mapContextMenu.isClosable()) {
@ -929,6 +930,11 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven
} else if (toShow instanceof NewGpxPoint) {
NewGpxPoint newGpxPoint = (NewGpxPoint) toShow;
getMapLayers().getContextMenuLayer().enterAddGpxPointMode(newGpxPoint);
} else if (toShow instanceof NewGpxLine) {
NewGpxLine newGpxLine = (NewGpxLine) toShow;
QuadRect qr = newGpxLine.getRect();
mapView.fitRectToMap(qr.left, qr.right, qr.top, qr.bottom, (int) qr.width(), (int) qr.height(), 0);
openAddingNewGpxLine(newGpxLine);
} else {
mapContextMenu.show(latLonToShow, mapLabelToShow, toShow);
}
@ -942,6 +948,16 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven
}
}
private void openAddingNewGpxLine(NewGpxLine newGpxLine) {
MeasurementToolFragment fragment = new MeasurementToolFragment();
fragment.setNewGpxLine(newGpxLine);
getSupportFragmentManager()
.beginTransaction()
.add(R.id.bottomFragmentContainer, fragment, MeasurementToolFragment.TAG)
.addToBackStack(MeasurementToolFragment.TAG)
.commitAllowingStateLoss();
}
public OsmandApplication getMyApplication() {
return ((OsmandApplication) getApplication());
}

View file

@ -13,19 +13,25 @@ import android.view.MenuItem;
import android.view.View;
import net.osmand.AndroidUtils;
import net.osmand.data.LatLon;
import net.osmand.data.PointDescription;
import net.osmand.data.QuadRect;
import net.osmand.plus.GPXDatabase.GpxDataItem;
import net.osmand.plus.GPXUtilities;
import net.osmand.plus.GPXUtilities.GPXFile;
import net.osmand.plus.GPXUtilities.WptPt;
import net.osmand.plus.GpxSelectionHelper;
import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup;
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
import net.osmand.plus.OsmAndAppCustomization;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandSettings;
import net.osmand.plus.R;
import net.osmand.plus.myplaces.FavoritesActivity;
import net.osmand.plus.myplaces.SplitSegmentFragment;
import net.osmand.plus.myplaces.TrackPointFragment;
import net.osmand.plus.myplaces.TrackSegmentFragment;
import net.osmand.plus.views.AddGpxPointBottomSheetHelper;
import net.osmand.plus.views.controls.PagerSlidingTabStrip;
import java.io.File;
@ -39,6 +45,7 @@ public class TrackActivity extends TabActivity {
public static final String OPEN_POINTS_TAB = "OPEN_POINTS_TAB";
public static final String CURRENT_RECORDING = "CURRENT_RECORDING";
protected List<WeakReference<Fragment>> fragList = new ArrayList<>();
private OsmandApplication app;
protected PagerSlidingTabStrip slidingTabLayout;
private File file = null;
private GPXFile gpxFile;
@ -56,7 +63,8 @@ public class TrackActivity extends TabActivity {
@Override
public void onCreate(Bundle icicle) {
((OsmandApplication) getApplication()).applyTheme(this);
this.app = getMyApplication();
app.applyTheme(this);
super.onCreate(icicle);
Intent intent = getIntent();
if (intent == null || (!intent.hasExtra(TRACK_FILE_NAME) &&
@ -83,6 +91,97 @@ public class TrackActivity extends TabActivity {
setContentView(R.layout.tab_content);
}
public void addPoint(PointDescription pointDescription) {
Intent currentIntent = getIntent();
if (currentIntent != null) {
currentIntent.putExtra(TrackActivity.OPEN_POINTS_TAB, true);
}
final OsmandSettings settings = app.getSettings();
GPXFile gpx = getGpx();
LatLon location = settings.getLastKnownMapLocation();
if (gpx != null && location != null) {
settings.setMapLocationToShow(location.getLatitude(), location.getLongitude(),
settings.getLastKnownMapZoom(),
pointDescription,
false,
new AddGpxPointBottomSheetHelper.NewGpxPoint(gpx, pointDescription));
MapActivity.launchMapActivityMoveToTop(this);
}
}
public void addLine() {
GPXFile gpxFile = getGpx();
QuadRect rect = getRect();
NewGpxLine newGpxLine = new NewGpxLine(gpxFile, rect);
WptPt pointToShow = gpxFile != null ? gpxFile.findPointToShow() : null;
if (pointToShow != null) {
LatLon location = new LatLon(pointToShow.getLatitude(), pointToShow.getLongitude());
final OsmandSettings settings = app.getSettings();
settings.setMapLocationToShow(location.getLatitude(), location.getLongitude(),
settings.getLastKnownMapZoom(),
new PointDescription(PointDescription.POINT_TYPE_WPT, getString(R.string.add_line)),
false,
newGpxLine
);
MapActivity.launchMapActivityMoveToTop(this);
}
}
public QuadRect getRect() {
double left = 0, right = 0;
double top = 0, bottom = 0;
if (getGpx() != null) {
for (GPXUtilities.Track track : getGpx().tracks) {
for (GPXUtilities.TrkSegment segment : track.segments) {
for (WptPt p : segment.points) {
if (left == 0 && right == 0) {
left = p.getLongitude();
right = p.getLongitude();
top = p.getLatitude();
bottom = p.getLatitude();
} else {
left = Math.min(left, p.getLongitude());
right = Math.max(right, p.getLongitude());
top = Math.max(top, p.getLatitude());
bottom = Math.min(bottom, p.getLatitude());
}
}
}
}
for (WptPt p : getGpx().points) {
if (left == 0 && right == 0) {
left = p.getLongitude();
right = p.getLongitude();
top = p.getLatitude();
bottom = p.getLatitude();
} else {
left = Math.min(left, p.getLongitude());
right = Math.max(right, p.getLongitude());
top = Math.max(top, p.getLatitude());
bottom = Math.min(bottom, p.getLatitude());
}
}
for (GPXUtilities.Route route : getGpx().routes) {
for (WptPt p : route.points) {
if (left == 0 && right == 0) {
left = p.getLongitude();
right = p.getLongitude();
top = p.getLatitude();
bottom = p.getLatitude();
} else {
left = Math.min(left, p.getLongitude());
right = Math.max(right, p.getLongitude());
top = Math.max(top, p.getLatitude());
bottom = Math.min(bottom, p.getLatitude());
}
}
}
}
return new QuadRect(left, top, right, bottom);
}
protected void setGpxDataItem(GpxDataItem gpxDataItem) {
this.gpxDataItem = gpxDataItem;
}
@ -304,4 +403,22 @@ public class TrackActivity extends TabActivity {
public GpxDataItem getGpxDataItem() {
return gpxDataItem;
}
public static class NewGpxLine {
private GPXFile gpxFile;
private QuadRect rect;
public NewGpxLine(GPXFile gpxFile, QuadRect rect) {
this.gpxFile = gpxFile;
this.rect = rect;
}
public GPXFile getGpxFile() {
return gpxFile;
}
public QuadRect getRect() {
return rect;
}
}
}

View file

@ -21,6 +21,7 @@ import net.osmand.plus.GPXUtilities.GPXFile;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.myplaces.FavoritesActivity;
import net.osmand.plus.views.OsmandMapTileView;
import java.io.ByteArrayInputStream;
@ -88,6 +89,21 @@ public class GpxImportHelper {
return false;
}
public void handleFavouritesImport(Uri uri) {
String scheme = uri.getScheme();
boolean isFileIntent = "file".equals(scheme);
boolean isContentIntent = "content".equals(scheme);
boolean isOsmandSubdir = isSubDirectory(app.getAppPath(IndexConstants.GPX_INDEX_DIR), new File(uri.getPath()));
final boolean saveFile = !isFileIntent || !isOsmandSubdir;
String fileName = "";
if (isFileIntent) {
fileName = new File(uri.getPath()).getName();
} else if (isContentIntent) {
fileName = getNameFromContentUri(uri);
}
handleFavouritesImport(uri, fileName, saveFile, false, true);
}
public void handleFileImport(final Uri intentUri, final String fileName, final boolean useImportDir) {
final boolean isFileIntent = "file".equals(intentUri.getScheme());
final boolean isOsmandSubdir = isSubDirectory(app.getAppPath(IndexConstants.GPX_INDEX_DIR), new File(intentUri.getPath()));
@ -99,7 +115,7 @@ public class GpxImportHelper {
} else if (fileName != null && fileName.endsWith(KMZ_SUFFIX)) {
handleKmzImport(intentUri, fileName, saveFile, useImportDir);
} else {
handleFavouritesImport(intentUri, fileName, saveFile, useImportDir);
handleFavouritesImport(intentUri, fileName, saveFile, useImportDir, false);
}
}
@ -155,12 +171,12 @@ public class GpxImportHelper {
@Override
protected void onPostExecute(GPXFile result) {
progress.dismiss();
handleResult(result, fileName, save, useImportDir);
handleResult(result, fileName, save, useImportDir, false);
}
}.execute();
}
private void handleFavouritesImport(final Uri gpxFile, final String fileName, final boolean save, final boolean useImportDir) {
private void handleFavouritesImport(final Uri gpxFile, final String fileName, final boolean save, final boolean useImportDir, final boolean forceImportFavourites) {
new AsyncTask<Void, Void, GPXFile>() {
ProgressDialog progress = null;
@ -193,12 +209,12 @@ public class GpxImportHelper {
@Override
protected void onPostExecute(final GPXFile result) {
progress.dismiss();
importFavourites(result, fileName, save, useImportDir);
importFavourites(result, fileName, save, useImportDir, forceImportFavourites);
}
}.execute();
}
private void importFavoritesImpl(final GPXFile gpxFile) {
private void importFavoritesImpl(final GPXFile gpxFile, final String fileName, final boolean forceImportFavourites) {
new AsyncTask<Void, Void, GPXFile>() {
ProgressDialog progress = null;
@ -209,7 +225,7 @@ public class GpxImportHelper {
@Override
protected GPXFile doInBackground(Void... nothing) {
final List<FavouritePoint> favourites = asFavourites(gpxFile.points);
final List<FavouritePoint> favourites = asFavourites(gpxFile.points, fileName, forceImportFavourites);
final FavouritesDbHelper favoritesHelper = app.getFavorites();
for (final FavouritePoint favourite : favourites) {
favoritesHelper.deleteFavourite(favourite, false);
@ -225,6 +241,8 @@ public class GpxImportHelper {
progress.dismiss();
Toast.makeText(activity, R.string.fav_imported_sucessfully, Toast.LENGTH_LONG).show();
final Intent newIntent = new Intent(activity, app.getAppCustomization().getFavoritesActivity());
newIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
newIntent.putExtra(FavoritesActivity.OPEN_FAVOURITES_TAB, true);
activity.startActivity(newIntent);
}
}.execute();
@ -277,7 +295,7 @@ public class GpxImportHelper {
@Override
protected void onPostExecute(GPXFile result) {
progress.dismiss();
handleResult(result, name, save, useImportDir);
handleResult(result, name, save, useImportDir, false);
}
}.execute();
@ -322,13 +340,13 @@ public class GpxImportHelper {
@Override
protected void onPostExecute(GPXFile result) {
progress.dismiss();
handleResult(result, name, save, useImportDir);
handleResult(result, name, save, useImportDir, false);
}
}.execute();
}
private void handleResult(final GPXFile result, final String name, final boolean save,
final boolean useImportDir) {
final boolean useImportDir, boolean forceImportFavourites) {
if (result != null) {
if (result.warning != null) {
Toast.makeText(activity, result.warning, Toast.LENGTH_LONG).show();
@ -372,6 +390,12 @@ public class GpxImportHelper {
})
.show();
}
if (forceImportFavourites) {
final Intent newIntent = new Intent(activity, app.getAppCustomization().getFavoritesActivity());
newIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
newIntent.putExtra(FavoritesActivity.OPEN_MY_PLACES_TAB, true);
activity.startActivity(newIntent);
}
}
private String saveImport(final GPXFile gpxFile, final String fileName, final boolean useImportDir) {
@ -467,38 +491,76 @@ public class GpxImportHelper {
}
private void importFavourites(final GPXFile gpxFile, final String fileName, final boolean save,
final boolean useImportDir) {
final boolean useImportDir, final boolean forceImportFavourites) {
if (gpxFile == null || gpxFile.points == null || gpxFile.points.size() == 0) {
handleResult(gpxFile, fileName, save, useImportDir);
return;
}
final DialogInterface.OnClickListener importFavouritesListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
importFavoritesImpl(gpxFile);
break;
case DialogInterface.BUTTON_NEGATIVE:
handleResult(gpxFile, fileName, save, useImportDir);
break;
}
}
};
if (forceImportFavourites) {
final DialogInterface.OnClickListener importAsTrackListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
handleResult(gpxFile, fileName, save, useImportDir, true);
break;
case DialogInterface.BUTTON_NEGATIVE:
dialog.dismiss();
break;
}
}
};
new AlertDialog.Builder(activity)
.setTitle(R.string.shared_string_import2osmand)
.setMessage(R.string.import_file_favourites)
.setPositiveButton(R.string.shared_string_import, importFavouritesListener)
.setNegativeButton(R.string.shared_string_save, importFavouritesListener)
.show();
new AlertDialog.Builder(activity)
.setTitle(R.string.import_track)
.setMessage(activity.getString(R.string.import_track_desc, fileName))
.setPositiveButton(R.string.shared_string_import, importAsTrackListener)
.setNegativeButton(R.string.shared_string_cancel, importAsTrackListener)
.show();
return;
} else {
handleResult(gpxFile, fileName, save, useImportDir, false);
return;
}
}
if (forceImportFavourites) {
importFavoritesImpl(gpxFile, fileName, true);
} else {
final DialogInterface.OnClickListener importFavouritesListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
importFavoritesImpl(gpxFile, fileName, false);
break;
case DialogInterface.BUTTON_NEGATIVE:
handleResult(gpxFile, fileName, save, useImportDir, false);
break;
}
}
};
new AlertDialog.Builder(activity)
.setTitle(R.string.shared_string_import2osmand)
.setMessage(R.string.import_file_favourites)
.setPositiveButton(R.string.shared_string_import, importFavouritesListener)
.setNegativeButton(R.string.shared_string_save, importFavouritesListener)
.show();
}
}
private List<FavouritePoint> asFavourites(final List<GPXUtilities.WptPt> wptPts) {
private List<FavouritePoint> asFavourites(final List<GPXUtilities.WptPt> wptPts, String fileName, boolean forceImportFavourites) {
final List<FavouritePoint> favourites = new ArrayList<>();
for (GPXUtilities.WptPt p : wptPts) {
if (p.name != null) {
final String fpCat = (p.category != null) ? p.category : "";
final String fpCat;
if (p.category == null) {
if (forceImportFavourites) {
fpCat = fileName;
} else {
fpCat = "";
}
} else {
fpCat = p.category;
}
final FavouritePoint fp = new FavouritePoint(p.lat, p.lon, p.name, fpCat);
if (p.desc != null) {
fp.setDescription(p.desc);

View file

@ -3,7 +3,6 @@ package net.osmand.plus.mapcontextmenu.builders.cards.dialogs;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import net.osmand.plus.OsmandSettings;
@ -12,8 +11,6 @@ import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.mapillary.MapillaryImageDialog;
import net.osmand.plus.views.OsmandMapTileView;
import java.util.List;
public abstract class ContextMenuCardDialog {
private MapActivity mapActivity;
@ -109,9 +106,9 @@ public abstract class ContextMenuCardDialog {
private void shiftMapPosition() {
OsmandMapTileView mapView = mapActivity.getMapView();
if (AndroidUiHelper.isOrientationPortrait(mapActivity)) {
if (mapView.getMapPosition() != OsmandSettings.MIDDLE_CONSTANT) {
if (mapView.getMapPosition() != OsmandSettings.MIDDLE_BOTTOM_CONSTANT) {
prevMapPosition = mapView.getMapPosition();
mapView.setMapPosition(OsmandSettings.MIDDLE_CONSTANT);
mapView.setMapPosition(OsmandSettings.MIDDLE_BOTTOM_CONSTANT);
}
} else {
mapView.setMapPositionX(1);

View file

@ -2,6 +2,7 @@ package net.osmand.plus.measurementtool;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
@ -10,7 +11,10 @@ import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.SwitchCompat;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.ContextThemeWrapper;
@ -19,6 +23,7 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
@ -30,35 +35,65 @@ import net.osmand.IndexConstants;
import net.osmand.plus.GPXUtilities;
import net.osmand.plus.GPXUtilities.Route;
import net.osmand.plus.GPXUtilities.WptPt;
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
import net.osmand.plus.IconsCache;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.activities.TrackActivity;
import net.osmand.plus.activities.TrackActivity.NewGpxLine;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.measurementtool.adapter.MeasurementToolAdapter;
import net.osmand.plus.measurementtool.adapter.MeasurementToolItemTouchHelperCallback;
import net.osmand.plus.measurementtool.command.AddPointCommand;
import net.osmand.plus.measurementtool.command.ClearPointsCommand;
import net.osmand.plus.measurementtool.command.CommandManager;
import net.osmand.plus.measurementtool.command.MovePointCommand;
import net.osmand.plus.measurementtool.command.RemovePointCommand;
import net.osmand.plus.measurementtool.command.ReorderPointCommand;
import net.osmand.plus.views.OsmandMapTileView;
import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory;
import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarController;
import net.osmand.plus.widgets.IconPopupMenu;
import net.osmand.plus.widgets.TextViewEx;
import java.io.File;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import static net.osmand.plus.GPXUtilities.GPXFile;
import static net.osmand.plus.OsmandSettings.MIDDLE_TOP_CONSTANT;
import static net.osmand.plus.helpers.GpxImportHelper.GPX_SUFFIX;
public class MeasurementToolFragment extends Fragment {
public static final String TAG = "MeasurementToolFragment";
private final CommandManager commandManager = new CommandManager();
private MeasurementToolBarController toolBarController;
private MeasurementToolAdapter adapter;
private TextView distanceTv;
private TextView pointsTv;
private String pointsSt;
private Drawable upIcon;
private Drawable downIcon;
private View pointsListContainer;
private ImageView upDownBtn;
private ImageView undoBtn;
private ImageView redoBtn;
private boolean wasCollapseButtonVisible;
private boolean pointsDetailsOpened;
private boolean pointsListOpened;
private boolean saved;
private int previousMapPosition;
private NewGpxLine newGpxLine;
public void setNewGpxLine(NewGpxLine newGpxLine) {
this.newGpxLine = newGpxLine;
}
@Nullable
@Override
@ -71,6 +106,8 @@ public class MeasurementToolFragment extends Fragment {
final int backgroundColor = ContextCompat.getColor(getActivity(),
nightMode ? R.color.ctx_menu_info_view_bg_dark : R.color.ctx_menu_info_view_bg_light);
boolean portrait = AndroidUiHelper.isOrientationPortrait(mapActivity);
upIcon = iconsCache.getThemedIcon(R.drawable.ic_action_arrow_up);
downIcon = iconsCache.getThemedIcon(R.drawable.ic_action_arrow_down);
pointsSt = getString(R.string.points).toLowerCase();
@ -78,7 +115,8 @@ public class MeasurementToolFragment extends Fragment {
final View mainView = view.findViewById(R.id.main_view);
AndroidUtils.setBackground(mapActivity, mainView, nightMode, R.drawable.bg_bottom_menu_light, R.drawable.bg_bottom_menu_dark);
view.findViewById(R.id.points_list_container).setBackgroundColor(backgroundColor);
pointsListContainer = view.findViewById(R.id.points_list_container);
pointsListContainer.setBackgroundColor(backgroundColor);
distanceTv = (TextView) mainView.findViewById(R.id.measurement_distance_text_view);
pointsTv = (TextView) mainView.findViewById(R.id.measurement_points_text_view);
@ -86,31 +124,56 @@ public class MeasurementToolFragment extends Fragment {
((ImageView) mainView.findViewById(R.id.ruler_icon))
.setImageDrawable(iconsCache.getIcon(R.drawable.ic_action_ruler, R.color.color_myloc_distance));
final ImageButton upDownBtn = ((ImageButton) mainView.findViewById(R.id.up_down_button));
((ImageView) mainView.findViewById(R.id.move_point_icon))
.setImageDrawable(iconsCache.getIcon(R.drawable.ic_action_measure_point, R.color.color_myloc_distance));
upDownBtn = (ImageView) mainView.findViewById(R.id.up_down_button);
upDownBtn.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_arrow_up));
upDownBtn.setOnClickListener(new View.OnClickListener() {
((TextViewEx) mainView.findViewById(R.id.cancel_button)).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (!pointsDetailsOpened) {
upBtnOnClick(mainView, iconsCache.getThemedIcon(R.drawable.ic_action_arrow_down));
cancelMovePointMode();
}
});
mainView.findViewById(R.id.up_down_row).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (!pointsListOpened && measurementLayer.getPointsCount() > 0 && !measurementLayer.isInMovePointMode()) {
showPointsList();
} else {
downBtnOnClick(mainView, iconsCache.getThemedIcon(R.drawable.ic_action_arrow_up));
hidePointsList();
}
}
});
final ImageButton undoBtn = ((ImageButton) mainView.findViewById(R.id.undo_point_button));
final ImageButton redoBtn = ((ImageButton) mainView.findViewById(R.id.redo_point_button));
((Button) mainView.findViewById(R.id.apply_point_button))
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
applyMovePointMode();
}
});
undoBtn = ((ImageButton) mainView.findViewById(R.id.undo_point_button));
redoBtn = ((ImageButton) mainView.findViewById(R.id.redo_point_button));
undoBtn.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_undo_dark));
undoBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (measurementLayer.undoPointOnClick()) {
commandManager.undo();
if (commandManager.canUndo()) {
enable(undoBtn);
} else {
disable(undoBtn);
}
hidePointsListIfNoPoints();
if (measurementLayer.getPointsCount() > 0) {
enable(upDownBtn);
}
adapter.notifyDataSetChanged();
enable(redoBtn);
updateText();
}
@ -120,23 +183,44 @@ public class MeasurementToolFragment extends Fragment {
redoBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (measurementLayer.redoPointOnClick()) {
commandManager.redo();
if (commandManager.canRedo()) {
enable(redoBtn);
} else {
disable(redoBtn);
}
hidePointsListIfNoPoints();
if (measurementLayer.getPointsCount() > 0) {
enable(upDownBtn);
}
adapter.notifyDataSetChanged();
enable(undoBtn);
updateText();
}
});
mainView.findViewById(R.id.add_point_button).setOnClickListener(new View.OnClickListener() {
((Button) mainView.findViewById(R.id.add_point_button))
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
addPoint();
}
});
measurementLayer.setOnSingleTapListener(new MeasurementToolLayer.OnSingleTapListener() {
@Override
public void onClick(View view) {
measurementLayer.addPointOnClick();
enable(undoBtn, upDownBtn);
disable(redoBtn);
updateText();
public void onSingleTap() {
addPoint();
}
});
measurementLayer.setOnEnterMovePointModeListener(new MeasurementToolLayer.OnEnterMovePointModeListener() {
@Override
public void onEnterMovePointMode() {
if (pointsListOpened) {
hidePointsList();
}
enterMovePointMode();
}
});
@ -150,7 +234,7 @@ public class MeasurementToolFragment extends Fragment {
toolBarController.setOnBackButtonClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showQuitDialog();
showQuitDialog(false);
}
});
toolBarController.setOnCloseButtonClickListener(new View.OnClickListener() {
@ -160,12 +244,26 @@ public class MeasurementToolFragment extends Fragment {
popup.getMenuInflater().inflate(R.menu.measurement_tool_menu, popup.getMenu());
final Menu menu = popup.getMenu();
IconsCache ic = mapActivity.getMyApplication().getIconsCache();
menu.findItem(R.id.action_save_as_gpx).setIcon(ic.getThemedIcon(R.drawable.ic_action_polygom_dark));
MenuItem saveAsNewSegmentMenuItem = menu.findItem(R.id.action_save_as_new_segment);
MenuItem saveAsGpxTrack = menu.findItem(R.id.action_save_as_gpx);
saveAsNewSegmentMenuItem.setIcon(ic.getThemedIcon(R.drawable.ic_action_polygom_dark));
saveAsGpxTrack.setIcon(ic.getThemedIcon(R.drawable.ic_action_polygom_dark));
if (newGpxLine != null) {
saveAsNewSegmentMenuItem.setVisible(true);
saveAsGpxTrack.setVisible(false);
}
menu.findItem(R.id.action_clear_all).setIcon(ic.getThemedIcon(R.drawable.ic_action_reset_to_default_dark));
popup.setOnMenuItemClickListener(new IconPopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem menuItem) {
switch (menuItem.getItemId()) {
case R.id.action_save_as_new_segment:
if (measurementLayer.getPointsCount() > 0) {
saveAsNewSegment(mapActivity);
} else {
Toast.makeText(mapActivity, getString(R.string.none_point_error), Toast.LENGTH_SHORT).show();
}
return true;
case R.id.action_save_as_gpx:
if (measurementLayer.getPointsCount() > 0) {
saveAsGpxOnClick(mapActivity);
@ -174,9 +272,13 @@ public class MeasurementToolFragment extends Fragment {
}
return true;
case R.id.action_clear_all:
measurementLayer.clearPoints();
disable(undoBtn, redoBtn, upDownBtn);
commandManager.execute(new ClearPointsCommand(measurementLayer));
if (pointsListOpened) {
hidePointsList();
}
disable(redoBtn, upDownBtn);
updateText();
saved = false;
return true;
}
return false;
@ -188,19 +290,171 @@ public class MeasurementToolFragment extends Fragment {
mapActivity.showTopToolbar(toolBarController);
}
adapter = new MeasurementToolAdapter(getMapActivity(), measurementLayer.getMeasurementPoints());
final RecyclerView rv = mainView.findViewById(R.id.measure_points_recycler_view);
final ItemTouchHelper touchHelper = new ItemTouchHelper(new MeasurementToolItemTouchHelperCallback(adapter));
touchHelper.attachToRecyclerView(rv);
adapter.setAdapterListener(new MeasurementToolAdapter.MeasurementAdapterListener() {
private int fromPosition;
private int toPosition;
@Override
public void onRemoveClick(int position) {
commandManager.execute(new RemovePointCommand(measurementLayer, position));
adapter.notifyDataSetChanged();
disable(redoBtn);
updateText();
saved = false;
hidePointsListIfNoPoints();
}
@Override
public void onItemClick(View view) {
int pos = rv.indexOfChild(view);
measurementLayer.moveMapToPoint(pos);
}
@Override
public void onDragStarted(RecyclerView.ViewHolder holder) {
fromPosition = holder.getAdapterPosition();
touchHelper.startDrag(holder);
}
@Override
public void onDragEnded(RecyclerView.ViewHolder holder) {
toPosition = holder.getAdapterPosition();
if (toPosition != fromPosition) {
commandManager.execute(new ReorderPointCommand(measurementLayer, fromPosition, toPosition));
adapter.notifyDataSetChanged();
disable(redoBtn);
mapActivity.refreshMap();
saved = false;
}
}
});
rv.setLayoutManager(new LinearLayoutManager(getContext()));
rv.setAdapter(adapter);
return view;
}
private void upBtnOnClick(View view, Drawable icon) {
pointsDetailsOpened = true;
view.findViewById(R.id.points_list_container).setVisibility(View.VISIBLE);
((ImageButton) view.findViewById(R.id.up_down_button)).setImageDrawable(icon);
private void cancelMovePointMode() {
exitMovePointMode();
MeasurementToolLayer measurementToolLayer = getMeasurementLayer();
if (measurementToolLayer != null) {
measurementToolLayer.exitMovePointMode();
}
}
private void downBtnOnClick(View view, Drawable icon) {
pointsDetailsOpened = false;
view.findViewById(R.id.points_list_container).setVisibility(View.GONE);
((ImageButton) view.findViewById(R.id.up_down_button)).setImageDrawable(icon);
private void applyMovePointMode() {
exitMovePointMode();
MeasurementToolLayer measurementLayer = getMeasurementLayer();
if (measurementLayer != null) {
WptPt newPoint = measurementLayer.getMovedPointToApply();
WptPt oldPoint = measurementLayer.getPreviouslyMovedPoint();
int position = measurementLayer.getMovePointPosition();
commandManager.execute(new MovePointCommand(measurementLayer, oldPoint, newPoint, position));
enable(undoBtn, upDownBtn);
disable(redoBtn);
updateText();
adapter.notifyDataSetChanged();
saved = false;
measurementLayer.exitMovePointMode();
measurementLayer.refreshMap();
}
}
private void enterMovePointMode() {
mark(View.GONE,
R.id.ruler_icon,
R.id.measurement_distance_text_view,
R.id.measurement_points_text_view,
R.id.up_down_button,
R.id.undo_point_button,
R.id.redo_point_button,
R.id.add_point_button);
mark(View.VISIBLE,
R.id.move_point_icon,
R.id.move_point_text,
R.id.cancel_button,
R.id.apply_point_button);
}
private void exitMovePointMode() {
mark(View.GONE,
R.id.move_point_icon,
R.id.move_point_text,
R.id.cancel_button,
R.id.apply_point_button);
mark(View.VISIBLE,
R.id.ruler_icon,
R.id.measurement_distance_text_view,
R.id.measurement_points_text_view,
R.id.up_down_button,
R.id.undo_point_button,
R.id.redo_point_button,
R.id.add_point_button);
}
private void hidePointsListIfNoPoints() {
MeasurementToolLayer measurementLayer = getMeasurementLayer();
if (measurementLayer != null) {
if (measurementLayer.getPointsCount() < 1) {
disable(upDownBtn);
if (pointsListOpened) {
hidePointsList();
}
}
}
}
private void addPoint() {
MeasurementToolLayer measurementLayer = getMeasurementLayer();
if (measurementLayer != null) {
commandManager.execute(new AddPointCommand(measurementLayer));
enable(undoBtn, upDownBtn);
disable(redoBtn);
updateText();
adapter.notifyDataSetChanged();
saved = false;
}
}
private void showPointsList() {
pointsListOpened = true;
pointsListContainer.setVisibility(View.VISIBLE);
upDownBtn.setImageDrawable(downIcon);
MapActivity mapActivity = getMapActivity();
if (mapActivity != null) {
OsmandMapTileView tileView = mapActivity.getMapView();
previousMapPosition = tileView.getMapPosition();
tileView.setMapPosition(MIDDLE_TOP_CONSTANT);
mapActivity.refreshMap();
}
}
private void hidePointsList() {
pointsListOpened = false;
pointsListContainer.setVisibility(View.GONE);
upDownBtn.setImageDrawable(upIcon);
setPreviousMapPosition();
}
private void setPreviousMapPosition() {
MapActivity mapActivity = getMapActivity();
if (mapActivity != null) {
mapActivity.getMapView().setMapPosition(previousMapPosition);
mapActivity.refreshMap();
}
}
private void saveAsNewSegment(MapActivity mapActivity) {
GPXFile gpx = newGpxLine.getGpxFile();
SelectedGpxFile selectedGpxFile = mapActivity.getMyApplication().getSelectedGpxHelper().getSelectedFileByPath(gpx.path);
boolean showOnMap = selectedGpxFile != null;
saveGpx(null, null, showOnMap);
}
private void saveAsGpxOnClick(MapActivity mapActivity) {
@ -287,25 +541,40 @@ public class MeasurementToolFragment extends Fragment {
@Override
protected String doInBackground(Void... voids) {
toSave = new File(dir, fileName);
GPXFile gpx = new GPXFile();
MeasurementToolLayer measurementLayer = getMeasurementLayer();
if (measurementLayer != null) {
LinkedList<WptPt> points = measurementLayer.getMeasurementPoints();
if (points.size() == 1) {
gpx.points.add(points.getFirst());
} else if (points.size() > 1) {
Route rt = new Route();
gpx.routes.add(rt);
rt.points.addAll(points);
GPXFile gpx;
if (newGpxLine != null) {
gpx = newGpxLine.getGpxFile();
toSave = new File(gpx.path);
if (measurementLayer != null) {
List<WptPt> points = measurementLayer.getMeasurementPoints();
gpx.addTrkSegment(points);
}
} else {
gpx = new GPXFile();
toSave = new File(dir, fileName);
if (measurementLayer != null) {
LinkedList<WptPt> points = measurementLayer.getMeasurementPoints();
if (points.size() == 1) {
gpx.points.add(points.getFirst());
} else if (points.size() > 1) {
Route rt = new Route();
gpx.routes.add(rt);
rt.points.addAll(points);
}
}
}
MapActivity activity = getMapActivity();
if (activity != null) {
String res = GPXUtilities.writeGpxFile(toSave, gpx, activity.getMyApplication());
gpx.path = toSave.getAbsolutePath();
if (newGpxLine == null) {
gpx.path = toSave.getAbsolutePath();
}
if (showOnMap) {
activity.getMyApplication().getSelectedGpxHelper().selectGpxFile(gpx, true, false);
SelectedGpxFile sf = activity.getMyApplication().getSelectedGpxHelper().selectGpxFile(gpx, true, false);
if (newGpxLine != null && sf != null) {
sf.processPoints();
}
}
return res;
}
@ -320,6 +589,7 @@ public class MeasurementToolFragment extends Fragment {
Toast.makeText(activity,
MessageFormat.format(getString(R.string.gpx_saved_sucessfully), toSave.getAbsolutePath()),
Toast.LENGTH_LONG).show();
saved = true;
} else {
Toast.makeText(activity, warning, Toast.LENGTH_LONG).show();
}
@ -336,6 +606,14 @@ public class MeasurementToolFragment extends Fragment {
public void onDestroyView() {
super.onDestroyView();
exitMeasurementMode();
adapter.setAdapterListener(null);
if (pointsListOpened) {
setPreviousMapPosition();
}
MeasurementToolLayer layer = getMeasurementLayer();
if (layer != null) {
layer.setOnSingleTapListener(null);
}
}
private MapActivity getMapActivity() {
@ -430,11 +708,15 @@ public class MeasurementToolFragment extends Fragment {
}
}
public void showQuitDialog() {
public void showQuitDialog(boolean hidePointsListFirst) {
final MapActivity mapActivity = getMapActivity();
MeasurementToolLayer measurementLayer = getMeasurementLayer();
if (mapActivity != null && measurementLayer != null) {
if (measurementLayer.getPointsCount() < 1) {
if (pointsListOpened && hidePointsListFirst) {
hidePointsList();
return;
}
if (measurementLayer.getPointsCount() < 1 || saved) {
dismiss(mapActivity);
return;
}
@ -454,6 +736,13 @@ public class MeasurementToolFragment extends Fragment {
private void dismiss(MapActivity mapActivity) {
try {
if (newGpxLine != null) {
GPXFile gpx = newGpxLine.getGpxFile();
Intent newIntent = new Intent(mapActivity, mapActivity.getMyApplication().getAppCustomization().getTrackActivity());
newIntent.putExtra(TrackActivity.TRACK_FILE_NAME, gpx.path);
newIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(newIntent);
}
mapActivity.getSupportFragmentManager().popBackStackImmediate(TAG, FragmentManager.POP_BACK_STACK_INCLUSIVE);
} catch (Exception e) {
// ignore

View file

@ -6,6 +6,7 @@ import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import android.util.Log;
import net.osmand.data.LatLon;
import net.osmand.data.PointDescription;
@ -28,18 +29,23 @@ public class MeasurementToolLayer extends OsmandMapLayer implements ContextMenuL
private OsmandMapTileView view;
private boolean inMeasurementMode;
private LinkedList<WptPt> measurementPoints = new LinkedList<>();
private LinkedList<WptPt> cacheMeasurementPoints = new LinkedList<>();
private boolean inMovePointMode;
private final LinkedList<WptPt> measurementPoints = new LinkedList<>();
private Bitmap centerIconDay;
private Bitmap centerIconNight;
private Bitmap pointIcon;
private Bitmap movePointIcon;
private Paint bitmapPaint;
private RenderingLineAttributes lineAttrs = new RenderingLineAttributes("rulerLine");
private Path path = new Path();
private final RenderingLineAttributes lineAttrs = new RenderingLineAttributes("measureDistanceLine");
private final Path path = new Path();
private int marginX;
private int marginY;
private TIntArrayList tx = new TIntArrayList();
private TIntArrayList ty = new TIntArrayList();
private final TIntArrayList tx = new TIntArrayList();
private final TIntArrayList ty = new TIntArrayList();
private OnSingleTapListener singleTapListener;
private OnEnterMovePointModeListener enterMovePointModeListener;
private int movePointPos;
private WptPt previouslyMovedPoint;
@Override
public void initLayer(OsmandMapTileView view) {
@ -48,6 +54,7 @@ public class MeasurementToolLayer extends OsmandMapLayer implements ContextMenuL
centerIconDay = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_ruler_center_day);
centerIconNight = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_ruler_center_night);
pointIcon = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_pedestrian_location);
movePointIcon = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_mapillary_location);
bitmapPaint = new Paint();
bitmapPaint.setAntiAlias(true);
@ -58,15 +65,35 @@ public class MeasurementToolLayer extends OsmandMapLayer implements ContextMenuL
marginX = pointIcon.getWidth() / 2;
}
void setOnSingleTapListener(OnSingleTapListener listener) {
this.singleTapListener = listener;
}
void setOnEnterMovePointModeListener(OnEnterMovePointModeListener listener) {
this.enterMovePointModeListener = listener;
}
WptPt getPreviouslyMovedPoint() {
return previouslyMovedPoint;
}
int getMovePointPosition() {
return movePointPos;
}
public boolean isInMeasurementMode() {
return inMeasurementMode;
}
public boolean isInMovePointMode() {
return inMovePointMode;
}
void setInMeasurementMode(boolean inMeasurementMode) {
this.inMeasurementMode = inMeasurementMode;
}
int getPointsCount() {
public int getPointsCount() {
return measurementPoints.size();
}
@ -85,17 +112,63 @@ public class MeasurementToolLayer extends OsmandMapLayer implements ContextMenuL
return OsmAndFormatter.getFormattedDistance(dist, view.getApplication());
}
void clearPoints() {
public void clearPoints() {
measurementPoints.clear();
cacheMeasurementPoints.clear();
view.refreshMap();
}
@Override
public boolean onSingleTap(PointF point, RotatedTileBox tileBox) {
if (inMeasurementMode && singleTapListener != null) {
singleTapListener.onSingleTap();
}
return false;
}
@Override
public boolean onLongPressEvent(PointF point, RotatedTileBox tileBox) {
if (inMovePointMode || measurementPoints.size() == 0) {
return false;
}
double pressedPointLat = tileBox.getLatFromPixel(point.x, point.y);
double pressedPointLon = tileBox.getLonFromPixel(point.x, point.y);
getPointToMove(pressedPointLat, pressedPointLon);
if (movePointPos != -1) {
enterMovingPointMode();
if (inMeasurementMode && inMovePointMode && enterMovePointModeListener != null) {
enterMovePointModeListener.onEnterMovePointMode();
}
}
return false;
}
private void enterMovingPointMode() {
inMovePointMode = true;
moveMapToPoint(movePointPos);
}
private void getPointToMove(double lat, double lon) {
double lowestDistance = Double.MAX_VALUE;
for (int i = 0; i < measurementPoints.size(); i++) {
WptPt pt = measurementPoints.get(i);
double latDiff = pt.getLatitude() - lat;
double lonDiff = pt.getLongitude() - lon;
double distToPoint = Math.sqrt(Math.pow(latDiff, 2) + Math.pow(lonDiff, 2));
if (distToPoint < lowestDistance) {
lowestDistance = distToPoint;
previouslyMovedPoint = new WptPt(pt);
movePointPos = i;
}
}
}
@Override
public void onDraw(Canvas canvas, RotatedTileBox tb, DrawSettings settings) {
if (inMeasurementMode) {
lineAttrs.updatePaints(view, settings, tb);
drawCenterIcon(canvas, tb, tb.getCenterPixelPoint(), settings.isNightMode());
if (!inMovePointMode) {
drawCenterIcon(canvas, tb, tb.getCenterPixelPoint(), settings.isNightMode());
}
if (measurementPoints.size() > 0) {
path.reset();
@ -103,8 +176,15 @@ public class MeasurementToolLayer extends OsmandMapLayer implements ContextMenuL
ty.reset();
for (int i = 0; i < measurementPoints.size(); i++) {
WptPt pt = measurementPoints.get(i);
int locX = tb.getPixXFromLonNoRot(pt.lon);
int locY = tb.getPixYFromLatNoRot(pt.lat);
int locX;
int locY;
if (inMovePointMode && movePointPos == i) {
locX = tb.getCenterPixelX();
locY = tb.getCenterPixelY();
} else {
locX = tb.getPixXFromLonNoRot(pt.lon);
locY = tb.getPixYFromLatNoRot(pt.lat);
}
if (i == 0) {
path.moveTo(locX, locY);
} else {
@ -113,22 +193,37 @@ public class MeasurementToolLayer extends OsmandMapLayer implements ContextMenuL
tx.add(locX);
ty.add(locY);
}
path.lineTo(tb.getCenterPixelX(), tb.getCenterPixelY());
tx.add(tb.getCenterPixelX());
ty.add(tb.getCenterPixelY());
if (!inMovePointMode) {
path.lineTo(tb.getCenterPixelX(), tb.getCenterPixelY());
tx.add(tb.getCenterPixelX());
ty.add(tb.getCenterPixelY());
}
calculatePath(tb, tx, ty, path);
canvas.drawPath(path, lineAttrs.paint);
for (WptPt pt : measurementPoints) {
if (tb.containsLatLon(pt.lat, pt.lon)) {
int locX = tb.getPixXFromLonNoRot(pt.lon);
int locY = tb.getPixYFromLatNoRot(pt.lat);
canvas.drawBitmap(pointIcon, locX - marginX, locY - marginY, bitmapPaint);
for (int i = 0; i < measurementPoints.size(); i++) {
WptPt pt = measurementPoints.get(i);
if (inMovePointMode && i == movePointPos) {
int locX = tb.getCenterPixelX();
int locY = tb.getCenterPixelY();
canvas.drawBitmap(movePointIcon, locX - marginX, locY - marginY, bitmapPaint);
} else {
if (tb.containsLatLon(pt.lat, pt.lon)) {
int locX = tb.getPixXFromLonNoRot(pt.lon);
int locY = tb.getPixYFromLatNoRot(pt.lat);
canvas.drawBitmap(pointIcon, locX - marginX, locY - marginY, bitmapPaint);
}
}
}
}
}
}
void exitMovePointMode() {
inMovePointMode = false;
movePointPos = -1;
previouslyMovedPoint = null;
}
private void drawCenterIcon(Canvas canvas, RotatedTileBox tb, QuadPoint center, boolean nightMode) {
canvas.rotate(-tb.getRotate(), center.x, center.y);
if (nightMode) {
@ -141,7 +236,12 @@ public class MeasurementToolLayer extends OsmandMapLayer implements ContextMenuL
canvas.rotate(tb.getRotate(), center.x, center.y);
}
void addPointOnClick() {
public void addPoint(int position, WptPt point) {
measurementPoints.add(position, point);
view.refreshMap();
}
public WptPt addPoint(int position) {
RotatedTileBox tb = view.getCurrentRotatedTileBox();
LatLon l = tb.getLatLonFromPixel(tb.getCenterPixelX(), tb.getCenterPixelY());
WptPt pt = new WptPt();
@ -149,29 +249,47 @@ public class MeasurementToolLayer extends OsmandMapLayer implements ContextMenuL
pt.lon = l.getLongitude();
if (measurementPoints.size() > 0) {
if (!measurementPoints.get(measurementPoints.size() - 1).equals(pt)) {
measurementPoints.add(pt);
measurementPoints.add(position, pt);
view.refreshMap();
return pt;
}
} else {
measurementPoints.add(pt);
measurementPoints.add(position, pt);
view.refreshMap();
return pt;
}
cacheMeasurementPoints = new LinkedList<>(measurementPoints);
view.refreshMap();
return null;
}
boolean undoPointOnClick() {
measurementPoints.remove(measurementPoints.size() - 1);
WptPt getMovedPointToApply() {
RotatedTileBox tb = view.getCurrentRotatedTileBox();
LatLon latLon = tb.getCenterLatLon();
WptPt pt = measurementPoints.get(movePointPos);
pt.lat = latLon.getLatitude();
pt.lon = latLon.getLongitude();
return pt;
}
public WptPt removePoint(int position) {
WptPt res = measurementPoints.remove(position);
view.refreshMap();
return res;
}
public void moveMapToPoint(int pos) {
if (measurementPoints.size() > 0) {
WptPt pt = measurementPoints.get(measurementPoints.size() - 1);
if (pos >= measurementPoints.size()) {
pos = measurementPoints.size() - 1;
} else if (pos < 0) {
pos = 0;
}
WptPt pt = measurementPoints.get(pos);
view.getAnimatedDraggingThread().startMoving(pt.getLatitude(), pt.getLongitude(), view.getZoom(), true);
}
return measurementPoints.size() > 0;
}
boolean redoPointOnClick() {
WptPt pt = cacheMeasurementPoints.get(measurementPoints.size());
measurementPoints.add(pt);
view.getAnimatedDraggingThread().startMoving(pt.getLatitude(), pt.getLongitude(), view.getZoom(), true);
return cacheMeasurementPoints.size() > measurementPoints.size();
public void refreshMap() {
view.refreshMap();
}
@Override
@ -213,4 +331,12 @@ public class MeasurementToolLayer extends OsmandMapLayer implements ContextMenuL
public boolean isObjectClickable(Object o) {
return !isInMeasurementMode();
}
interface OnSingleTapListener {
void onSingleTap();
}
interface OnEnterMovePointModeListener {
void onEnterMovePointMode();
}
}

View file

@ -0,0 +1,138 @@
package net.osmand.plus.measurementtool.adapter;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.MotionEventCompat;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import net.osmand.plus.GPXUtilities.WptPt;
import net.osmand.plus.IconsCache;
import net.osmand.plus.OsmAndFormatter;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.util.MapUtils;
import java.util.Collections;
import java.util.List;
public class MeasurementToolAdapter extends RecyclerView.Adapter<MeasurementToolAdapter.MeasureToolItemVH>
implements MeasurementToolItemTouchHelperCallback.ItemTouchHelperAdapter {
private final MapActivity mapActivity;
private final List<WptPt> points;
private MeasurementAdapterListener listener;
public MeasurementToolAdapter(MapActivity mapActivity, List<WptPt> points) {
this.mapActivity = mapActivity;
this.points = points;
}
public void setAdapterListener(MeasurementAdapterListener listener) {
this.listener = listener;
}
@Override
public MeasureToolItemVH onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.measure_points_list_item, viewGroup, false);
final boolean nightMode = mapActivity.getMyApplication().getDaynightHelper().isNightModeForMapControls();
if (!nightMode) {
view.findViewById(R.id.points_divider).setBackgroundResource(R.drawable.divider);
}
final int backgroundColor = ContextCompat.getColor(mapActivity,
nightMode ? R.color.ctx_menu_info_view_bg_dark : R.color.ctx_menu_info_view_bg_light);
view.setBackgroundColor(backgroundColor);
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
listener.onItemClick(view);
}
});
return new MeasureToolItemVH(view);
}
@Override
public void onBindViewHolder(final MeasureToolItemVH holder, int pos) {
IconsCache iconsCache = mapActivity.getMyApplication().getIconsCache();
holder.iconReorder.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_reorder));
holder.iconReorder.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent event) {
if (MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_DOWN) {
listener.onDragStarted(holder);
}
return false;
}
});
holder.icon.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_measure_point));
holder.title.setText(mapActivity.getString(R.string.plugin_distance_point) + " - " + (pos + 1));
if (pos < 1) {
holder.descr.setText(mapActivity.getString(R.string.shared_string_control_start));
} else {
float dist = 0;
for (int i = 1; i <= pos; i++) {
dist += MapUtils.getDistance(points.get(i - 1).lat, points.get(i - 1).lon,
points.get(i).lat, points.get(i).lon);
}
holder.descr.setText(OsmAndFormatter.getFormattedDistance(dist, mapActivity.getMyApplication()));
}
holder.deleteBtn.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_remove_dark));
holder.deleteBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
listener.onRemoveClick(holder.getAdapterPosition());
}
});
}
@Override
public int getItemCount() {
return points.size();
}
@Override
public boolean onItemMove(int from, int to) {
Collections.swap(points, from, to);
notifyItemMoved(from, to);
return true;
}
@Override
public void onItemDismiss(RecyclerView.ViewHolder holder) {
listener.onDragEnded(holder);
}
static class MeasureToolItemVH extends RecyclerView.ViewHolder {
final ImageView iconReorder;
final ImageView icon;
final TextView title;
final TextView descr;
final ImageButton deleteBtn;
MeasureToolItemVH(View view) {
super(view);
iconReorder = (ImageView) view.findViewById(R.id.measure_point_reorder_icon);
icon = (ImageView) view.findViewById(R.id.measure_point_icon);
title = (TextView) view.findViewById(R.id.measure_point_title);
descr = (TextView) view.findViewById(R.id.measure_point_descr);
deleteBtn = (ImageButton) view.findViewById(R.id.measure_point_remove_image_button);
}
}
public interface MeasurementAdapterListener {
void onRemoveClick(int position);
void onItemClick(View view);
void onDragStarted(RecyclerView.ViewHolder holder);
void onDragEnded(RecyclerView.ViewHolder holder);
}
}

View file

@ -0,0 +1,53 @@
package net.osmand.plus.measurementtool.adapter;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
public class MeasurementToolItemTouchHelperCallback extends ItemTouchHelper.Callback {
private final ItemTouchHelperAdapter adapter;
public MeasurementToolItemTouchHelperCallback(ItemTouchHelperAdapter adapter) {
this.adapter = adapter;
}
@Override
public boolean isLongPressDragEnabled() {
return false;
}
@Override
public boolean isItemViewSwipeEnabled() {
return false;
}
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
return makeMovementFlags(dragFlags, 0);
}
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder source, RecyclerView.ViewHolder target) {
return adapter.onItemMove(source.getAdapterPosition(), target.getAdapterPosition());
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int i) {
}
@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);
adapter.onItemDismiss(viewHolder);
}
interface ItemTouchHelperAdapter {
boolean onItemMove(int from, int to);
void onItemDismiss(RecyclerView.ViewHolder holder);
}
}

View file

@ -0,0 +1,37 @@
package net.osmand.plus.measurementtool.command;
import net.osmand.plus.GPXUtilities.WptPt;
import net.osmand.plus.measurementtool.MeasurementToolLayer;
public class AddPointCommand implements Command {
private final MeasurementToolLayer measurementLayer;
private final int position;
private WptPt point;
public AddPointCommand(MeasurementToolLayer measurementLayer, int position) {
this.measurementLayer = measurementLayer;
this.position = position;
}
public AddPointCommand(MeasurementToolLayer measurementLayer) {
this.measurementLayer = measurementLayer;
position = measurementLayer.getPointsCount();
}
@Override
public boolean execute() {
return (point = measurementLayer.addPoint(position)) != null;
}
@Override
public void undo() {
measurementLayer.removePoint(position);
}
@Override
public void redo() {
measurementLayer.addPoint(position, point);
measurementLayer.moveMapToPoint(position);
}
}

View file

@ -0,0 +1,36 @@
package net.osmand.plus.measurementtool.command;
import net.osmand.plus.GPXUtilities;
import net.osmand.plus.measurementtool.MeasurementToolLayer;
import java.util.LinkedList;
import java.util.List;
public class ClearPointsCommand implements Command {
private final MeasurementToolLayer measurementLayer;
private List<GPXUtilities.WptPt> points;
public ClearPointsCommand(MeasurementToolLayer measurementLayer) {
this.measurementLayer = measurementLayer;
}
@Override
public boolean execute() {
points = new LinkedList<>(measurementLayer.getMeasurementPoints());
measurementLayer.clearPoints();
return true;
}
@Override
public void undo() {
measurementLayer.getMeasurementPoints().addAll(points);
measurementLayer.refreshMap();
}
@Override
public void redo() {
measurementLayer.clearPoints();
measurementLayer.refreshMap();
}
}

View file

@ -0,0 +1,10 @@
package net.osmand.plus.measurementtool.command;
public interface Command {
boolean execute();
void undo();
void redo();
}

View file

@ -0,0 +1,41 @@
package net.osmand.plus.measurementtool.command;
import java.util.Deque;
import java.util.LinkedList;
public class CommandManager {
private final Deque<Command> undoCommands = new LinkedList<>();
private final Deque<Command> redoCommands = new LinkedList<>();
public boolean canUndo() {
return undoCommands.size() > 0;
}
public boolean canRedo() {
return redoCommands.size() > 0;
}
public void execute(Command command) {
if (command.execute()) {
undoCommands.push(command);
redoCommands.clear();
}
}
public void undo() {
if (canUndo()) {
Command command = undoCommands.pop();
redoCommands.push(command);
command.undo();
}
}
public void redo() {
if (canRedo()) {
Command command = redoCommands.pop();
undoCommands.push(command);
command.redo();
}
}
}

View file

@ -0,0 +1,44 @@
package net.osmand.plus.measurementtool.command;
import net.osmand.plus.GPXUtilities.WptPt;
import net.osmand.plus.measurementtool.MeasurementToolLayer;
public class MovePointCommand implements Command {
private final MeasurementToolLayer measurementLayer;
private final WptPt oldPoint;
private final WptPt newPoint;
private final int position;
public MovePointCommand (MeasurementToolLayer measurementLayer, WptPt oldPoint, WptPt newPoint, int position) {
this.measurementLayer = measurementLayer;
this.oldPoint = oldPoint;
this.newPoint = newPoint;
this.position = position;
}
@Override
public boolean execute() {
return true;
}
@Override
public void undo() {
replacePointWithOldOne();
}
@Override
public void redo() {
replacePointWithNewOne();
}
private void replacePointWithOldOne() {
measurementLayer.getMeasurementPoints().remove(position);
measurementLayer.getMeasurementPoints().add(position, oldPoint);
}
private void replacePointWithNewOne() {
measurementLayer.getMeasurementPoints().remove(position);
measurementLayer.getMeasurementPoints().add(position, newPoint);
}
}

View file

@ -0,0 +1,33 @@
package net.osmand.plus.measurementtool.command;
import net.osmand.plus.GPXUtilities.WptPt;
import net.osmand.plus.measurementtool.MeasurementToolLayer;
public class RemovePointCommand implements Command {
private final MeasurementToolLayer measurementLayer;
private final int position;
private WptPt point;
public RemovePointCommand(MeasurementToolLayer measurementLayer, int position) {
this.measurementLayer = measurementLayer;
this.position = position;
}
@Override
public boolean execute() {
point = measurementLayer.removePoint(position);
return true;
}
@Override
public void undo() {
measurementLayer.addPoint(position, point);
measurementLayer.moveMapToPoint(position);
}
@Override
public void redo() {
measurementLayer.removePoint(position);
}
}

View file

@ -0,0 +1,38 @@
package net.osmand.plus.measurementtool.command;
import net.osmand.plus.measurementtool.MeasurementToolLayer;
import java.util.Collections;
public class ReorderPointCommand implements Command {
private final MeasurementToolLayer measurementLayer;
private final int from;
private final int to;
public ReorderPointCommand(MeasurementToolLayer measurementLayer, int from, int to) {
this.measurementLayer = measurementLayer;
this.from = from;
this.to = to;
}
@Override
public boolean execute() {
return true;
}
@Override
public void undo() {
swap();
}
@Override
public void redo() {
swap();
}
private void swap() {
Collections.swap(measurementLayer.getMeasurementPoints(), from, to);
measurementLayer.refreshMap();
}
}

View file

@ -327,6 +327,17 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment {
}
footerView = inflater.inflate(R.layout.list_shadow_footer, null, false);
listView.addFooterView(footerView);
View emptyView = v.findViewById(android.R.id.empty);
ImageView emptyImageView = (ImageView) emptyView.findViewById(R.id.empty_state_image_view);
emptyImageView.setImageResource(app.getSettings().isLightContent() ? R.drawable.ic_empty_state_trip_day_result : R.drawable.ic_empty_state_trip_night_result);
Button importButton = (Button) emptyView.findViewById(R.id.import_button);
importButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
addTrack();
}
});
listView.setEmptyView(emptyView);
if (this.adapter != null) {
listView.setAdapter(this.adapter);
}

View file

@ -41,6 +41,10 @@ import java.util.List;
public class FavoritesActivity extends TabActivity {
private static final int OPEN_GPX_DOCUMENT_REQUEST = 1006;
private static final int IMPORT_FAVOURITES_REQUEST = 1007;
public static final String OPEN_FAVOURITES_TAB = "open_favourites_tab";
public static final String OPEN_MY_PLACES_TAB = "open_my_places_tab";
public static final int GPX_TAB = R.string.shared_string_my_tracks;
public static final int FAV_TAB = R.string.shared_string_my_favorites;
@ -67,6 +71,16 @@ public class FavoritesActivity extends TabActivity {
List<TabItem> mTabs = getTabItems();
setTabs(mTabs);
// setupHomeButton();
ViewPager mViewPager = (ViewPager) findViewById(R.id.pager);
Intent intent = getIntent();
if (intent != null) {
if (intent.hasExtra(OPEN_FAVOURITES_TAB) && intent.getBooleanExtra(OPEN_FAVOURITES_TAB, false)) {
mViewPager.setCurrentItem(0, false);
} else if (intent.hasExtra(OPEN_MY_PLACES_TAB) && intent.getBooleanExtra(OPEN_MY_PLACES_TAB, false)) {
mViewPager.setCurrentItem(1, false);
}
}
}
@TargetApi(Build.VERSION_CODES.KITKAT)
@ -76,6 +90,13 @@ public class FavoritesActivity extends TabActivity {
startActivityForResult(intent, OPEN_GPX_DOCUMENT_REQUEST);
}
@TargetApi(Build.VERSION_CODES.KITKAT)
public void importFavourites() {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.setType("*/*");
startActivityForResult(intent, IMPORT_FAVOURITES_REQUEST);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == OPEN_GPX_DOCUMENT_REQUEST && resultCode == Activity.RESULT_OK) {
@ -101,6 +122,11 @@ public class FavoritesActivity extends TabActivity {
}
}
}
} else if (requestCode == IMPORT_FAVOURITES_REQUEST && resultCode == Activity.RESULT_OK) {
if (data != null) {
Uri uri = data.getData();
gpxImportHelper.handleFavouritesImport(uri);
}
} else {
super.onActivityResult(requestCode, resultCode, data);
}
@ -135,22 +161,9 @@ public class FavoritesActivity extends TabActivity {
}
private List<TabItem> getTabItems() {
File[] lf = ((OsmandApplication) getApplication()).getAppPath(IndexConstants.GPX_INDEX_DIR).listFiles();
boolean hasGpx = false;
if (lf != null) {
for (File t : lf) {
if (t.isDirectory() || (t.getName().toLowerCase().endsWith(".gpx"))) {
hasGpx = true;
break;
}
}
}
List<TabItem> mTabs = new ArrayList<>();
mTabs.add(getTabIndicator(FAV_TAB, FavoritesTreeFragment.class));
if (hasGpx) {
mTabs.add(getTabIndicator(GPX_TAB, AvailableGPXFragment.class));
}
mTabs.add(getTabIndicator(GPX_TAB, AvailableGPXFragment.class));
OsmandPlugin.addMyPlacesTabPlugins(this, mTabs, getIntent());
return mTabs;
}

View file

@ -99,6 +99,8 @@ public class TrackPointFragment extends OsmandExpandableListFragment {
private View waypointTextLayout;
private FloatingActionButton routePointFab;
private View routePointTextLayout;
private FloatingActionButton lineFab;
private View lineTextLayout;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
@ -128,6 +130,32 @@ public class TrackPointFragment extends OsmandExpandableListFragment {
: R.color.ctx_menu_info_view_bg_dark));
}
private View.OnClickListener onFabClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.menu_fab:
if (menuOpened) {
closeMenu();
} else {
openMenu();
}
break;
case R.id.waypoint_fab:
PointDescription pointWptDescription = new PointDescription(PointDescription.POINT_TYPE_WPT, getString(R.string.add_waypoint));
addPoint(pointWptDescription);
break;
case R.id.route_fab:
PointDescription pointRteDescription = new PointDescription(PointDescription.POINT_TYPE_RTE, getString(R.string.add_route_point));
addPoint(pointRteDescription);
break;
case R.id.line_fab:
addLine();
break;
}
}
};
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.points_tree, container, false);
@ -135,37 +163,20 @@ public class TrackPointFragment extends OsmandExpandableListFragment {
setHasOptionsMenu(true);
menuFab = (FloatingActionButton) view.findViewById(R.id.menu_fab);
menuFab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (menuOpened) {
closeMenu();
} else {
openMenu();
}
}
});
menuFab.setOnClickListener(onFabClickListener);
waypointFab = (FloatingActionButton) view.findViewById(R.id.waypoint_fab);
waypointFab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
PointDescription pointDescription = new PointDescription(PointDescription.POINT_TYPE_WPT, getString(R.string.add_waypoint));
addPoint(pointDescription);
}
});
waypointFab.setOnClickListener(onFabClickListener);
waypointTextLayout = view.findViewById(R.id.waypoint_text_layout);
routePointFab = (FloatingActionButton) view.findViewById(R.id.route_fab);
routePointFab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
PointDescription pointDescription = new PointDescription(PointDescription.POINT_TYPE_RTE, getString(R.string.add_route_point));
addPoint(pointDescription);
}
});
routePointFab.setOnClickListener(onFabClickListener);
routePointTextLayout = view.findViewById(R.id.route_text_layout);
lineFab = (FloatingActionButton) view.findViewById(R.id.line_fab);
lineFab.setOnClickListener(onFabClickListener);
lineTextLayout = view.findViewById(R.id.line_text_layout);
TextView tv = new TextView(getActivity());
tv.setText(R.string.none_selected_gpx);
tv.setTextSize(24);
@ -178,22 +189,11 @@ public class TrackPointFragment extends OsmandExpandableListFragment {
}
private void addPoint(PointDescription pointDescription) {
Intent currentIntent = getTrackActivity().getIntent();
if (currentIntent != null) {
currentIntent.putExtra(TrackActivity.OPEN_POINTS_TAB, true);
}
final OsmandSettings settings = app.getSettings();
GPXFile gpx = getGpx();
LatLon location = settings.getLastKnownMapLocation();
if (gpx != null && location != null) {
settings.setMapLocationToShow(location.getLatitude(), location.getLongitude(),
settings.getLastKnownMapZoom(),
pointDescription,
false,
new NewGpxPoint(gpx, pointDescription));
getTrackActivity().addPoint(pointDescription);
}
MapActivity.launchMapActivityMoveToTop(getActivity());
}
private void addLine() {
getTrackActivity().addLine();
}
private void openMenu() {
@ -202,6 +202,8 @@ public class TrackPointFragment extends OsmandExpandableListFragment {
waypointTextLayout.setVisibility(View.VISIBLE);
routePointFab.setVisibility(View.VISIBLE);
routePointTextLayout.setVisibility(View.VISIBLE);
lineFab.setVisibility(View.VISIBLE);
lineTextLayout.setVisibility(View.VISIBLE);
menuOpened = true;
}
@ -211,6 +213,8 @@ public class TrackPointFragment extends OsmandExpandableListFragment {
waypointTextLayout.setVisibility(View.GONE);
routePointFab.setVisibility(View.GONE);
routePointTextLayout.setVisibility(View.GONE);
lineFab.setVisibility(View.GONE);
lineTextLayout.setVisibility(View.GONE);
menuOpened = false;
}

View file

@ -17,6 +17,7 @@ import android.os.Handler;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.MenuItemCompat;
import android.support.v4.view.PagerAdapter;
@ -34,6 +35,7 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.CompoundButton;
@ -139,6 +141,15 @@ public class TrackSegmentFragment extends OsmAndListFragment {
private RotatedTileBox rotatedTileBox;
private Bitmap mapBitmap;
private Bitmap mapTrackBitmap;
private boolean chartClicked;
private boolean menuOpened = false;
private FloatingActionButton menuFab;
private FloatingActionButton waypointFab;
private View waypointTextLayout;
private FloatingActionButton routePointFab;
private View routePointTextLayout;
private FloatingActionButton lineFab;
private View lineTextLayout;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
@ -149,16 +160,55 @@ public class TrackSegmentFragment extends OsmAndListFragment {
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
getListView().setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView absListView, int i) {
if (i == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
if (menuOpened) {
closeMenu();
}
}
}
@Override
public void onScroll(AbsListView absListView, int i, int i1, int i2) {
}
});
getListView().setBackgroundColor(getResources().getColor(
getMyApplication().getSettings().isLightContent() ? R.color.ctx_menu_info_view_bg_light
: R.color.ctx_menu_info_view_bg_dark));
}
private View.OnClickListener onFabClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.menu_fab:
if (menuOpened) {
closeMenu();
} else {
openMenu();
}
break;
case R.id.waypoint_fab:
PointDescription pointWptDescription = new PointDescription(PointDescription.POINT_TYPE_WPT, getString(R.string.add_waypoint));
addPoint(pointWptDescription);
break;
case R.id.route_fab:
PointDescription pointRteDescription = new PointDescription(PointDescription.POINT_TYPE_RTE, getString(R.string.add_route_point));
addPoint(pointRteDescription);
break;
case R.id.line_fab:
addLine();
break;
}
}
};
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
setHasOptionsMenu(true);
View view = getActivity().getLayoutInflater().inflate(R.layout.update_index, container, false);
view.findViewById(R.id.header_layout).setVisibility(View.GONE);
View view = getActivity().getLayoutInflater().inflate(R.layout.track_segments_tree, container, false);
ListView listView = (ListView) view.findViewById(android.R.id.list);
listView.setDivider(null);
@ -169,6 +219,21 @@ public class TrackSegmentFragment extends OsmAndListFragment {
tv.setTextSize(24);
listView.setEmptyView(tv);
menuFab = (FloatingActionButton) view.findViewById(R.id.menu_fab);
menuFab.setOnClickListener(onFabClickListener);
waypointFab = (FloatingActionButton) view.findViewById(R.id.waypoint_fab);
waypointFab.setOnClickListener(onFabClickListener);
waypointTextLayout = view.findViewById(R.id.waypoint_text_layout);
routePointFab = (FloatingActionButton) view.findViewById(R.id.route_fab);
routePointFab.setOnClickListener(onFabClickListener);
routePointTextLayout = view.findViewById(R.id.route_text_layout);
lineFab = (FloatingActionButton) view.findViewById(R.id.line_fab);
lineFab.setOnClickListener(onFabClickListener);
lineTextLayout = view.findViewById(R.id.line_text_layout);
paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setAntiAlias(true);
@ -182,11 +247,46 @@ public class TrackSegmentFragment extends OsmAndListFragment {
headerView = getActivity().getLayoutInflater().inflate(R.layout.gpx_item_list_header, null, false);
listView.addHeaderView(headerView);
listView.addFooterView(getActivity().getLayoutInflater().inflate(R.layout.list_shadow_footer, null, false));
View emptyView = new View(getActivity());
emptyView.setLayoutParams(new AbsListView.LayoutParams(
AbsListView.LayoutParams.MATCH_PARENT,
AndroidUtils.dpToPx(getActivity(), 72)));
listView.addFooterView(emptyView);
updateHeader();
setListAdapter(adapter);
return view;
}
private void addPoint(PointDescription pointDescription) {
getTrackActivity().addPoint(pointDescription);
}
private void addLine() {
getTrackActivity().addLine();
}
private void openMenu() {
menuFab.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.ic_action_remove_dark));
waypointFab.setVisibility(View.VISIBLE);
waypointTextLayout.setVisibility(View.VISIBLE);
routePointFab.setVisibility(View.VISIBLE);
routePointTextLayout.setVisibility(View.VISIBLE);
lineFab.setVisibility(View.VISIBLE);
lineTextLayout.setVisibility(View.VISIBLE);
menuOpened = true;
}
private void closeMenu() {
menuFab.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.ic_action_plus));
waypointFab.setVisibility(View.GONE);
waypointTextLayout.setVisibility(View.GONE);
routePointFab.setVisibility(View.GONE);
routePointTextLayout.setVisibility(View.GONE);
lineFab.setVisibility(View.GONE);
lineTextLayout.setVisibility(View.GONE);
menuOpened = false;
}
public TrackActivity getTrackActivity() {
return (TrackActivity) getActivity();
}
@ -598,56 +698,7 @@ public class TrackSegmentFragment extends OsmAndListFragment {
}
private QuadRect getRect() {
double left = 0, right = 0;
double top = 0, bottom = 0;
if (getGpx() != null) {
for (Track track : getGpx().tracks) {
for (TrkSegment segment : track.segments) {
for (WptPt p : segment.points) {
if (left == 0 && right == 0) {
left = p.getLongitude();
right = p.getLongitude();
top = p.getLatitude();
bottom = p.getLatitude();
} else {
left = Math.min(left, p.getLongitude());
right = Math.max(right, p.getLongitude());
top = Math.max(top, p.getLatitude());
bottom = Math.min(bottom, p.getLatitude());
}
}
}
}
for (WptPt p : getGpx().points) {
if (left == 0 && right == 0) {
left = p.getLongitude();
right = p.getLongitude();
top = p.getLatitude();
bottom = p.getLatitude();
} else {
left = Math.min(left, p.getLongitude());
right = Math.max(right, p.getLongitude());
top = Math.max(top, p.getLatitude());
bottom = Math.min(bottom, p.getLatitude());
}
}
for (Route route : getGpx().routes) {
for (WptPt p : route.points) {
if (left == 0 && right == 0) {
left = p.getLongitude();
right = p.getLongitude();
top = p.getLatitude();
bottom = p.getLatitude();
} else {
left = Math.min(left, p.getLongitude());
right = Math.max(right, p.getLongitude());
top = Math.max(top, p.getLatitude());
bottom = Math.min(bottom, p.getLatitude());
}
}
}
}
return new QuadRect(left, top, right, bottom);
return getTrackActivity().getRect();
}
private List<GpxDisplayGroup> getOriginalGroups() {
@ -1073,6 +1124,7 @@ public class TrackSegmentFragment extends OsmAndListFragment {
@Override
public Object instantiateItem(ViewGroup container, int position) {
chartClicked = false;
GPXTabItemType tabType = tabTypes[position];
View view = null;
switch (tabType) {
@ -1091,102 +1143,112 @@ public class TrackSegmentFragment extends OsmAndListFragment {
if (gpxItem != null) {
GPXTrackAnalysis analysis = gpxItem.analysis;
final LineChart chart = (LineChart) view.findViewById(R.id.chart);
chart.setOnTouchListener(new View.OnTouchListener() {
chart.setHighlightPerDragEnabled(false);
chart.setOnClickListener(new View.OnClickListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
getListView().requestDisallowInterceptTouchEvent(true);
switch (event.getAction()) {
case android.view.MotionEvent.ACTION_DOWN:
listViewYPos = event.getRawY();
break;
case android.view.MotionEvent.ACTION_MOVE:
scrollBy(Math.round(listViewYPos - event.getRawY()));
listViewYPos = event.getRawY();
break;
}
return false;
}
});
chart.setOnChartValueSelectedListener(new OnChartValueSelectedListener() {
@Override
public void onValueSelected(Entry e, Highlight h) {
WptPt wpt = getPoint(chart, h.getX());
if (wpt != null) {
selectedPointLatLon = new LatLon(wpt.lat, wpt.lon);
Bitmap bmp = drawSelectedPoint();
imageView.setImageDrawable(new BitmapDrawable(app.getResources(), bmp));
}
}
@Override
public void onNothingSelected() {
}
});
final View finalView = view;
chart.setOnChartGestureListener(new OnChartGestureListener() {
float highlightDrawX = -1;
@Override
public void onChartGestureStart(MotionEvent me, ChartGesture lastPerformedGesture) {
if (chart.getHighlighted() != null && chart.getHighlighted().length > 0) {
highlightDrawX = chart.getHighlighted()[0].getDrawX();
} else {
highlightDrawX = -1;
}
}
@Override
public void onChartGestureEnd(MotionEvent me, ChartGesture lastPerformedGesture) {
gpxItem.chartMatrix = new Matrix(chart.getViewPortHandler().getMatrixTouch());
Highlight[] highlights = chart.getHighlighted();
if (highlights != null && highlights.length > 0) {
gpxItem.chartHighlightPos = highlights[0].getX();
} else {
gpxItem.chartHighlightPos = -1;
}
for (int i = 0; i < getCount(); i++) {
View v = getViewAtPosition(i);
if (v != finalView) {
updateChart(i);
}
}
}
@Override
public void onChartLongPressed(MotionEvent me) {
}
@Override
public void onChartDoubleTapped(MotionEvent me) {
}
@Override
public void onChartSingleTapped(MotionEvent me) {
}
@Override
public void onChartFling(MotionEvent me1, MotionEvent me2, float velocityX, float velocityY) {
}
@Override
public void onChartScale(MotionEvent me, float scaleX, float scaleY) {
}
@Override
public void onChartTranslate(MotionEvent me, float dX, float dY) {
if (highlightDrawX != -1) {
Highlight h = chart.getHighlightByTouchPoint(highlightDrawX, 0f);
if (h != null) {
chart.highlightValue(h);
WptPt wpt = getPoint(chart, h.getX());
if (wpt != null) {
selectedPointLatLon = new LatLon(wpt.lat, wpt.lon);
Bitmap bmp = drawSelectedPoint();
imageView.setImageDrawable(new BitmapDrawable(app.getResources(), bmp));
public void onClick(View view) {
if (!chartClicked) {
chartClicked = true;
chart.setHighlightPerDragEnabled(true);
chart.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
getListView().requestDisallowInterceptTouchEvent(true);
switch (event.getAction()) {
case android.view.MotionEvent.ACTION_DOWN:
listViewYPos = event.getRawY();
break;
case android.view.MotionEvent.ACTION_MOVE:
scrollBy(Math.round(listViewYPos - event.getRawY()));
listViewYPos = event.getRawY();
break;
}
return false;
}
}
});
chart.setOnChartValueSelectedListener(new OnChartValueSelectedListener() {
@Override
public void onValueSelected(Entry e, Highlight h) {
WptPt wpt = getPoint(chart, h.getX());
if (wpt != null) {
selectedPointLatLon = new LatLon(wpt.lat, wpt.lon);
Bitmap bmp = drawSelectedPoint();
imageView.setImageDrawable(new BitmapDrawable(app.getResources(), bmp));
}
}
@Override
public void onNothingSelected() {
}
});
final View finalView = view;
chart.setOnChartGestureListener(new OnChartGestureListener() {
float highlightDrawX = -1;
@Override
public void onChartGestureStart(MotionEvent me, ChartGesture lastPerformedGesture) {
if (chart.getHighlighted() != null && chart.getHighlighted().length > 0) {
highlightDrawX = chart.getHighlighted()[0].getDrawX();
} else {
highlightDrawX = -1;
}
}
@Override
public void onChartGestureEnd(MotionEvent me, ChartGesture lastPerformedGesture) {
gpxItem.chartMatrix = new Matrix(chart.getViewPortHandler().getMatrixTouch());
Highlight[] highlights = chart.getHighlighted();
if (highlights != null && highlights.length > 0) {
gpxItem.chartHighlightPos = highlights[0].getX();
} else {
gpxItem.chartHighlightPos = -1;
}
for (int i = 0; i < getCount(); i++) {
View v = getViewAtPosition(i);
if (v != finalView) {
updateChart(i);
}
}
}
@Override
public void onChartLongPressed(MotionEvent me) {
}
@Override
public void onChartDoubleTapped(MotionEvent me) {
}
@Override
public void onChartSingleTapped(MotionEvent me) {
}
@Override
public void onChartFling(MotionEvent me1, MotionEvent me2, float velocityX, float velocityY) {
}
@Override
public void onChartScale(MotionEvent me, float scaleX, float scaleY) {
}
@Override
public void onChartTranslate(MotionEvent me, float dX, float dY) {
if (highlightDrawX != -1) {
Highlight h = chart.getHighlightByTouchPoint(highlightDrawX, 0f);
if (h != null) {
chart.highlightValue(h);
WptPt wpt = getPoint(chart, h.getX());
if (wpt != null) {
selectedPointLatLon = new LatLon(wpt.lat, wpt.lon);
Bitmap bmp = drawSelectedPoint();
imageView.setImageDrawable(new BitmapDrawable(app.getResources(), bmp));
}
}
}
}
});
}
}
});

View file

@ -218,7 +218,7 @@ public class MapQuickActionLayer extends OsmandMapLayer implements QuickActionRe
private void enterMovingMode(RotatedTileBox tileBox) {
previousMapPosition = view.getMapPosition();
view.setMapPosition(OsmandSettings.MIDDLE_CONSTANT);
view.setMapPosition(OsmandSettings.MIDDLE_BOTTOM_CONSTANT);
MapContextMenu menu = mapActivity.getContextMenu();
LatLon ll = menu.isActive() && tileBox.containsLatLon(menu.getLatLon()) ? menu.getLatLon() : tileBox.getCenterLatLon();

View file

@ -578,8 +578,10 @@ public class OsmandMapTileView implements IMapDownloaderCallback {
final float ratioy;
if (mapPosition == OsmandSettings.BOTTOM_CONSTANT) {
ratioy = 0.85f;
} else if (mapPosition == OsmandSettings.MIDDLE_CONSTANT) {
} else if (mapPosition == OsmandSettings.MIDDLE_BOTTOM_CONSTANT) {
ratioy = 0.70f;
} else if (mapPosition == OsmandSettings.MIDDLE_TOP_CONSTANT) {
ratioy = 0.25f;
} else {
ratioy = 0.5f;
}